Shadowmap transparency for multiple objects

Started by
13 comments, last by ankhd 10 years, 2 months ago

Hi,

I have Shadowmaps working based off of several tutorials around the internet, and have been able to get transparency working by discarding pixels in a texture that have an alpha value. But this only seems to work on only a single texture sampler which I pass to the shadowmap pixel shader.

I'm now trying to work out how I would get my shadows working irrespective of how many textures/models I have in a scene. I can't quite get my head around how I can do this. How have others managed to do this?

Cheers

6

Advertisement

Hi,

Can I bump this question please.

Thanks

6

Hmm, no anwser after 300+ views. I'm sure it's not that complicated so let me re-word the issue I have.

The depthmap texture, ( from the lights point-of-view), is created when my pixel shader receives the depth value of a fragment from a vertex shader. This is all very simple and creates a nice depthmap of my geometry.

Next, to create the shadowmap I have a pixelshader which compares the Projected depthMap with the depth from my current Viewposition and accordingly set the pixel as in light or in shadow.

The problem is, at some point, ( either at the creation of the depthMap or shadowMap), I would like to check if the texture fragment has an alpha channel value. I have been able to do this when I explicitly pass in a texture sampler to the pixel shader, but I don't know how to check for alpha values when there is an unknown number of textures to test.

So how do others do this? I'm just looking for a general direction to go in, not for specific code. Just out of interest, is it best to perform the alpha test when creating the depthMap or at the shadowMap stage.

Thanks

6

Next, to create the shadowmap

You already created the shadow map. The light’s depth map is the shadow map. Now you need to find pixels in a shadow or not in a shadow. This is not “creating the shadow map,” it’s applying the shadow map you just created.

but I don't know how to check for alpha values when there is an unknown number of textures to test.

This is why no one has replied. I didn’t have a clue how to even ask for clarification on what this even meant. At least this time it might be a bit clearer as to where you are going wrong since you think making a depth map and making a shadow map are different processes.

Step #1: Create the shadow map (write depth values to a depth/float texture). If the alpha value of the object you are rendering at this time is below a certain threshold, discard it.

Step #2: Apply shadow map using your existing comparison process to determine in or out of shadow.

That is all there is.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Ok, perhaps I have my terminology wrong. So it sounds like what you're saying is that the depth texture which tells me how far the lighting is reaching, is actually called the shadowMap. In other words the shadowMap actually stores light depth information. Kinda makes sense.

Now, where you say "If the alpha value of the object you are rendering at this time is below a certain threshold, discard it.". Yep, I understand that's what I need to do, but the shader is a post process shader so how to I access the texture/sampler belonging to that object? Do I need to declare the sampler at the beginning of the shader file? If so then what if I have 50 textures with alpha information?

Thanks

6

Yep, I understand that's what I need to do, but the shader is a post process shader so how to I access the texture/sampler belonging to that object? Do I need to declare the sampler at the beginning of the shader file?

It doesn’t matter if you are using a deferred renderer or what. At the point in time when you create the shadow map, you are rendering object-by-object one at a time.
At that time you have access to alpha values. If not, you need to modify your shaders so that you do.

Shaders used to generate a shadow map are typically custom and are forward-renderred. Opaque objects are drawn first, all with the same shader which simply outputs depth as the color, in a way similar to vec4(depth, 0.0, 0.0, 1.0) (in advanced techniques you will later use vec(depth, ddXderiv, ddYderiv, 1.0) etc., but you can climb that hill once you get there).

When you render translucent objects you need to at least read the alpha from the texture or material (or both) and decide to discard or not.


You make the decision to discard on an object-by-object basis during the creation of the shadow map, so there is no situation in which you have to figure out which sampler to use or X number of textures to potentially sample, etc., unless that single object actually takes 50 textures to render (which simply never is the case). Creating shadow maps is forward-rendering with simplified shaders.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Sorry, I'm still confused. I've various different things, but nothing seems to be working.

At the point where I'm creating the ShadowMap ( aka depthmap) the vertex shader is passing all the vertex data including the depth information to the pixel shader. At the moment the pixel shader just stores the depth in a 'r32f' texture. Is it at this point I clip() any alpha values?

If so, I'm still not clear how I access the alpha value. I presume the Vertex Shader can't provide this info because it just processes vertices. Is there some semantic, ( like COLOR0) I need to use when I'm in the Pixel shader? I just can't find anything online about how to do this part :(

Here is a snippet of my code which shows a shadowMap texture being created, then it is used in ScreenShadOUT_PS as part of the camparison process


///////////////////////////////////////////////////////////
///////////////////////////// Connector Data Struct ///////
///////////////////////////////////////////////////////////

struct OneTexelVertex
 {
    float4 Position	: POSITION;
    float4 color	: COLOR0;
    float2 UV		: TEXCOORD0;
    float4 depth	: TEXCOORD1;
    float4 ViewPosition : TEXCOORD2;
    float4 normal   : NORMAL;	
};


///////////////////////////////////////////////////////////
////////////////////Pass = DepthMap ///////////////////////
///////////////////////////////////////////////////////////
// RTT available in this pass = ScnMap
OneTexelVertex ScreenIN_VS(OneTexelVertex IN) 
{
    OneTexelVertex OUT = (OneTexelVertex)0;
	OUT.Position = mul(IN.Position, gWorld);
	OUT.Position = mul(OUT.Position, gLightView);
	OUT.Position = mul(OUT.Position, gLightOrtho);
	
    OUT.UV = float2(IN.UV.xy + ViewportOffset);
	OUT.depth.x = OUT.Position.z/OUT.Position.w;
	OUT.normal = IN.normal;
    return OUT;
}
float4 ScreenOUT_PS(OneTexelVertex IN) : COLOR
{   
	float depthValue =  IN.depth.x;
	return float4(depthValue,depthValue,depthValue,1.0f);
} 

// RTT Output = ShadowMap
///////////////////////////////////////////////////////////
/////////////// Pass = Shadow /////////////////////////////
///////////////////////////////////////////////////////////
OneTexelVertex ScreenShadIN_VS(OneTexelVertex IN) 
{
    OneTexelVertex OUT = (OneTexelVertex)0;
    OUT.Position = mul(IN.Position, gWorldViewProjection);
	OUT.ViewPosition = mul(IN.Position, gWorld);
	OUT.ViewPosition = mul(OUT.ViewPosition, gLightView);
	OUT.ViewPosition = mul(OUT.ViewPosition, gLightOrtho);
	
    OUT.UV = float2(IN.UV.xy + ViewportOffset);
	OUT.normal = mul(IN.normal, gWorld);
	OUT.normal = normalize(OUT.normal);
    return OUT;
	
}

float4 ScreenShadOUT_PS(OneTexelVertex IN) : COLOR
{
	float depthValue;
	float4 color;
	float3 lightDir;
	float lightIntensity;
	float4 textureColor;
	float2 projectTexCoord;
	float4 projectionColor;	
	color = float4(0.5,0.5,0.5,1);
	lightDir = -gLightDirection;
	lightIntensity = saturate(dot(IN.normal, lightDir));	
	projectTexCoord.x = (IN.ViewPosition.x / IN.ViewPosition.w) /2.0f + 0.5f; 
	projectTexCoord.y = (-IN.ViewPosition.y / IN.ViewPosition.w) /2.0f + 0.5f; 	
	if((saturate(projectTexCoord.x)==projectTexCoord.x)&&(saturate(projectTexCoord.y)==projectTexCoord.y))
	{
		depthValue = tex2D(ShadowMap, projectTexCoord).r;		
		lightDepthValue = IN.ViewPosition.z / IN.ViewPosition.w;		
		lightDepthValue = lightDepthValue - bias;		
		if(lightDepthValue < depthValue)
		{
			if(lightIntensity > 0.0f)
			{
				color = (float4(1, 1, 1,1));// * lightIntensity);
				color = saturate(color);
			}
		}
	}	
	return color;
} 

// RTT Output = ShadowOverlay

I don't even know where to begin....


If so, I'm still not clear how I access the alpha value.

I'm assuming you are drawing objects that have textures with transparent parts. And in that case, you want to make sure light "shines through" those parts, right?

So, when rendering the object to your shadow map, you do your texture sample (exactly like you do when drawing the object during the lighting pass) and discard the pixel at that point based on the alpha value of your object's texture.


At the moment the pixel shader just stores the depth in a 'r32f' texture. Is it at this point I clip() any alpha values?

Yes. And if you clip, then the pixel shader won't write the depth to the shadow map. Which is exactly what you want to happen.

Hi Phil,

When I apply a shader to an object I know exactly which textures are to be used and only the vertices's for that object are acted on. But during a post process shader, every object vertex in the scene is processed. I don't have to include every texture sampler for those objects do i?

So lets say I have a simple scene with 4 trees and each tree uses a different RGBA texture. How do I access each of those textures during the shadowmap creation step? Thats all I'm looking to get answered really.

Cheers

6

Edit. Ok, after a bit more reading it sounds like I can access the texture through something like this:

sampler2D input : register(s0);


But during a post process shader, every object vertex in the scene is processed.

A post-process shader generally acts on the entire screen, which is just a bunch of pixels. The only vertices it acts on are the 4 vertices used to draw the full screen quad. The vertices used to draw the original objects aren't relevant anymore. None of this matters though, because:


I don't have to include every texture sampler for those objects do i?

Shadow map creation is not a post process shader, so that question doesn't make sense.


So lets say I have a simple scene with 4 trees and each tree uses a different RGBA texture. How do I access each of those textures during the shadowmap creation step? Thats all I'm looking to get answered really.

How would you draw though 4 trees normally? 4 separate draw calls, each with a different texture bound. You do the exact same thing when creating the shadow map, except you use a pixel shader that outputs a depth value instead of a color value.

This topic is closed to new replies.

Advertisement