Let's fix Shadows.

Let's fix Shadows.

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Let's fix Shadows.

Post by Argh »

Well, since this seems to be something that won't get fixed until I get digging into it, I've taken a look at why Unit / Feature shadows remain broken.

References:

http://github.com/spring/spring/blob/7c ... Drawer.cpp

http://github.com/spring/spring/blob/7c ... andler.cpp

http://github.com/spring/spring/blob/7c ... Drawer.cpp

http://github.com/spring/spring/blob/7c ... andler.cpp

Also see treeShadow.vp vs. unit_genshadow.vp, in the shaders directory.




I started with what I know: tree shadows still work. Nothing else does. I've been staring at the sourcecode and the shaders, and I'm rather puzzled by several things:

1. The Unit code reinitializes ARB values 16,17 and 18, which ShadowHandler says aren't supposed to be touched by anything else.

2. The difference between the TreeShadow.vp and UnitGenShadow.vp is that there is a difference between the use of ARB values 11 and 12.

The Unit code refers to it thus:

Code: Select all

glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,11, unitSunColor.x,unitSunColor.y,unitSunColor.z,0);
Whereas the tree code refers to it thus:

Code: Select all

glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,11, mapInfo->light.groundSunColor.x,mapInfo->light.groundSunColor.y,mapInfo->light.groundSunColor.z,0.85f);
This appears to be trivial- it's just using groundSunColor instead of unitSunColor. But it should be the same- Trees are Features, and therefore should use the same rules, in terms of rendering.

As for 12... I think that's where the issue is. Here's the tree code:

Code: Select all

glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,12, 0,0,0,0.20f*(1.0f/MAX_TREE_HEIGHT));	//w=alpha/height modifier
This is clearly referring to the tree textures, which are getting stretched according to the height of the tree.

Whereas 12 gets used for something Entirely Else in UnitDrawer.cpp:

Code: Select all

glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,12, unitAmbientColor.x,unitAmbientColor.y,unitAmbientColor.z,1);
It appears to me that nowhere in UnitDrawer.cpp does it ever get the value of w for the extraColor texture, which is why it's not handling this correctly.

Then there's this mystery:

Code: Select all

 // When rendering shadows, we just want to take extraColor.alpha (tex2) into account,
// so textures with masked texels create correct shadows.
if (shadowHandler->inShadowPass)
{
// Instead of enabling GL_TEXTURE1_ARB i have modified CTextureHandler.SetS3oTexture()
// to set texture 0 if shadowHandler->inShadowPass is true.
glEnable(GL_TEXTURE_2D);
glAlphaFunc(GL_GREATER, 0.5f);
glEnable(GL_ALPHA_TEST);
return;
}
Well, that certainly sounds like somebody wanted this to work. However, it doesn't, which makes me wonder if that's where it's borked.

And this, in the texture handler, a somewhat-anomalous thing:

Code: Select all

 //if(unitDrawer->advShading)
{
CBitmap bm;
// No error checking here... other code relies on an empty texture
// being generated if it couldn't be loaded.
// Also many map features specify a tex2 but don't ship it with the map,
// so throwing here would cause maps to break.
if(!bm.Load(string("unittextures/"+tex2))) {
bm.Alloc(1,1);
bm.mem[3] = 255;//file not found, set alpha to white so unit is visible
}
tex.tex2 = bm.CreateTexture(true);
tex.tex2SizeX = bm.xsize;
tex.tex2SizeY = bm.ysize;
}
This looks like it could possibly be a major problem, if it's being applied incorrectly, but again, if that wasn't working right, texture2 would be borked everywhere. I don't think that's it, but it was a weird thing to see. I thought that if tex2 wasn't specified, then the values were just (0,0,0,1.0) for every texture coordinate- creating a fake texture of the same size as tex1 seems rather wasteful.

So... we know that tex2 is getting loaded, otherwise the existing fragment programs wouldn't work. Using the value of the tex2.w at a given position is trivial, so surely that's not what's wrong. Or at least, all that's wrong- I see no sign that tex2 is being used during the shadowmapping step on Units.

I am fairly certain that the step referring to ARB value 12 is key here. The vertex program for Units just refers back to the texture coordinate value, but doesn't use that value to alter the final result, like the tree version does.

Then we have this major difference:

Tree:

Code: Select all

 glBindTexture(GL_TEXTURE_2D,shadowHandler->shadowTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
Unit:

Code: Select all

 glBindTexture(GL_TEXTURE_2D,shadowHandler->shadowTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
GL_ALPHA vs. GL_LUMINANCE, in case it's not obvious. Seems strange, given that these are both from the shadow step. But I don't know whether that's wrong or not here- my guess is "yes", but since it's pretty obvious that we're not even plugging tex2.w into UnitDrawer's shadow section, that's probably the place to start.
oliveoil
Posts: 10
Joined: 02 Jun 2009, 13:25

Re: Let's fix Shadows.

Post by oliveoil »

Hi Argh,

How exactly are unit and feature shadows broken? Is there o mantis or, better yet, screenshots?

I'm seeing some terrain shadow oddities with SM3, but that's not what you are talking about, is it?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Let's fix Shadows.

Post by Argh »

1. Unit / Feature shadows are supposed to be using tex2 when passed on to the ARB shader, to determine which areas are supposed to be transparent. This isn't working at all at present, and it appears that this is because tex2 isn't even being assigned as a uniform before that shader runs.

I found this out when checking the ARB shaders, and have confirmed it by looking at the current engine code. The only shadowmap section of the engine code that can even use the equivalent of tex2 is the code for trees.

This makes the shadows of things that should have transparent parts- i.e., trees, plants, and mechanical objects using transparency to cheat on polycount- render the shadowmap as if they're solid, which looks terrible.

Adding the uniform and assigning the tex2 is trivial stuff. Fixing the ARB shader is also trivial, and I'll be happy to do that part, if somebody will just fix the assignment of a uniform on the engine side, it's really not a big deal to fix the shader.

2. The shadowmap projection is not POV-correct, and is causing several problems: self-shadowing, "floating", and occasional fragments that aren't connected to others. As my recent screenshots of what's happening with the ROAM algorithm in place clearly show, the projections are really badly borked. It's even more obvious with texturemaps being projected onto fragments, such as the "road" objects I use in World Builder, where if you use non-OTA POV, you will see bands of spots where self-shadowing is occurring.

I brought up some shadowmap code that somebody else wrote, as preparation for rendering it with GLSL, where these issues were discussed and fixes were shown... but nobody's taken it up yet.

3. Because of the problems in 2, and the fact that it's not really being clamped well to the bounds of the POV, and other issues, it's necessary to use extremely large shadowmap texture sizes to achieve a decent result, and if you switch from the OTA POV to others, the problems are obvious.

The results I saw in that article I brought up during earlier discussion of these issues indicated that it's probably not necessary to use a shadowmap larger than the screen resolution to achieve an accurate result, unless you need to clamp to power-of-two for compatibility's sake.
User avatar
troycheek
Posts: 80
Joined: 22 May 2009, 19:13

Re: Let's fix Shadows.

Post by troycheek »

oliveoil wrote:How exactly are unit and feature shadows broken?
Here are how mine are broken:
screen000.jpg
screen000.jpg (21.01 KiB) Viewed 2266 times
Features and terrain have shadows but units do not. I'm hoping this is related to what Argh is working on. In the mean time, I need to hack the blob shadow widget again...
imbaczek
Posts: 3629
Joined: 22 Aug 2006, 16:19

Re: Let's fix Shadows.

Post by imbaczek »

this is the advanced unit shading setting. enable it.
User avatar
troycheek
Posts: 80
Joined: 22 May 2009, 19:13

Re: Let's fix Shadows.

Post by troycheek »

So I was hallucinating if I seem to remember some previous version when shadows worked without having to enable the shiny? (Although one of Argh's other posts suddenly makes a bit more sense.)
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Let's fix Shadows.

Post by Argh »

So I was hallucinating if I seem to remember some previous version when shadows worked without having to enable the shiny?
IDK if the vertex shader for generating Unit shadows on the map (as opposed to self-shadowing) worked without Advanced Rendering previously or not. I haven't played the game without Advanced Rendering in ages, frankly.

But basically that post is about making the "Advanced Rendering" less of an all-or-nothing proposition and introducing some speedups in certain places.
User avatar
smoth
Posts: 22309
Joined: 13 Jan 2005, 00:46

Re: Let's fix Shadows.

Post by smoth »

Transparencies are broken, they also flicker on vertical surfaces.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Let's fix Shadows.

Post by Argh »

Here's one part solved. This section should be:

// When rendering shadows, we just want to take extraColor.alpha (tex2) into account,
// so textures with masked texels create correct shadows.
if (shadowHandler->inShadowPass)
{
// Instead of enabling GL_TEXTURE1_ARB i have modified CTextureHandler.SetS3oTexture()
// to set texture 0 if shadowHandler->inShadowPass is true.
glEnable(GL_TEXTURE_2D);
glAlphaFunc(GL_ALWAYS, 0.0f);
glEnable(GL_ALPHA_TEST);
return;
}

Alpha should not be clamped to 1.0/0.0, it should be allowed to remain an 8-bit value. The shadowmap is not a 1-bit texture, it's 8 bits. There's no cost savings clamping it.

I'll have to find out where the blend function is being called, too.
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Let's fix Shadows.

Post by jK »

Argh wrote:Alpha should not be clamped to 1.0/0.0, it should be allowed to remain an 8-bit value. The shadowmap is not a 1-bit texture, it's 8 bits. There's no cost savings clamping it.
Please stop repeating this wrong stuff over and over again...
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Let's fix Shadows.

Post by Argh »

Help me out here, then.

I know that the resulting texture2d is a bitmap. It's just black and white at present, and doesn't need to be. There are no cost savings with letting it be 1.0 - tex2 alpha, since it's treated as 8-bit on the shader level.

The alpha clamp isn't necessary, and is one of several reasons why this isn't working like it should be. That, and it's apparent that we need to have an additional ARB value passed to the S3O shadowmap vertex shader with tex2 attached. But if we sent it after clamping the alpha, that means that we can't have half-shadows for transparent things.

It uses a mat4 for projection, but that's irrelevant to what I'm saying. I'm simply saying that when we use the vertex shader to build the shadowmap's bitmap in the first place, we should take tex2's alpha into account. Then we have an 8-bit shadowmap, which we already have, but it's not locked to black and white. There's no difference between what I'm saying and the tree code, it just uses a different method to determine what the alpha level is, and again is clamped, but doesn't need to be.
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Let's fix Shadows.

Post by jK »

Argh wrote:Help me out here, then.

I know that the resulting texture2d is a bitmap. It's just black and white at present, and doesn't need to be. There are no cost savings with letting it be 1.0 - tex2 alpha, since it's treated as 8-bit on the shader level.

The alpha clamp isn't necessary, and is one of several reasons why this isn't working like it should be. That, and it's apparent that we need to have an additional ARB value passed to the S3O shadowmap vertex shader with tex2 attached. But if we sent it after clamping the alpha, that means that we can't have half-shadows for transparent things.

It uses a mat4 for projection, but that's irrelevant to what I'm saying. I'm simply saying that when we use the vertex shader to build the shadowmap's bitmap in the first place, we should take tex2's alpha into account. Then we have an 8-bit shadowmap, which we already have, but it's not locked to black and white. There's no difference between what I'm saying and the tree code, it just uses a different method to determine what the alpha level is, and again is clamped, but doesn't need to be.
o_O ?

The shadowmap is either a 16,24 or 32bit texture with just 1 channel. This channel represents the depth of a specific voxel in the light's eye view.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Let's fix Shadows.

Post by Argh »

Then what am I pulling up, when I grab $shadow? That texture? And what are the other channels used for?
Kloot
Spring Developer
Posts: 1867
Joined: 08 Oct 2006, 16:58

Re: Let's fix Shadows.

Post by Kloot »

As I PM'ed you once: shadowmaps store depth values. $shadow is a texture of depth values. The individual channels (bytes) are interpreted as depth value octets.
Last edited by Kloot on 09 Aug 2009, 01:41, edited 1 time in total.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Let's fix Shadows.

Post by Argh »

OK, but what are the other 3 channels used for, then?

OK, so they're all used, to give us the precision we need, then?

Hmmph. So, basically it can be on or off, but to make it truly 8-bit we'd need to generate a texture to modulate that outcome. That sounds expensive. Drat.

I guess it's back to why we aren't passing tex2 to the vertex shader, then.
zerver
Spring Developer
Posts: 1358
Joined: 16 Dec 2006, 20:59

Re: Let's fix Shadows.

Post by zerver »

The alpha texture (tex2) did not have any texture coordinates. Fixed now, but there is probably a shitload of shadow bugs left.
imbaczek
Posts: 3629
Joined: 22 Aug 2006, 16:19

Re: Let's fix Shadows.

Post by imbaczek »

as reported on mantis, now features don't have any shadows at all on ATI 4850, which is arguably an improvement ;p
zerver
Spring Developer
Posts: 1358
Joined: 16 Dec 2006, 20:59

Re: Let's fix Shadows.

Post by zerver »

ATI 4850 sucks :P
imbaczek
Posts: 3629
Joined: 22 Aug 2006, 16:19

Re: Let's fix Shadows.

Post by imbaczek »

no u ;p

i can help with debugging but have no idea what to look for. if you could write up what to pay attention to, i can try to mess around.
zerver
Spring Developer
Posts: 1358
Joined: 16 Dec 2006, 20:59

Re: Let's fix Shadows.

Post by zerver »

Actually it seems I do own one 4850 :mrgreen:, so I will test with it.

Image
Post Reply

Return to “Engine”