Cubemap Depth Sample

Started by
15 comments, last by widmowyfox 8 years, 3 months ago

That was helpful, as i understand I can simply set render target to 0: ID3D11RenderTargetView* renderTargets[1]={0};
Now my depth cube texture is 100% correct, but I still dont know how to sample it in shader:


float4 PS(VertexOut pin, uniform int index) : SV_Target
{
float4 c = gTexture.Sample(samLinear, pin.Tex).r;

return float4(c.rrr, 1);
}

In cubetexture i cant use 2d coord system :/

Please, please, can someone explain me cube texture sampling methods step by step?

Advertisement

You need to use the (Light - Position) 3d vector to sample the cubemap..

This is for OpenGL, but pretty much the same in HLSL:

http://www.sunandblackcat.com/tipFullView.php?l=eng&topicid=36


  vec3 fromLightToFragment = u_lightPos - o_worldPosition.xyz;
   // normalized distance to the point light source
   float distanceToLight = length(fromLightToFragment);
   float currentDistanceToLight = (distanceToLight - u_nearFarPlane.x) /
            (u_nearFarPlane.y - u_nearFarPlane.x);
   currentDistanceToLight = clamp(currentDistanceToLight, 0, 1);
   // normalized direction from light source for sampling
   fromLightToFragment = normalize(fromLightToFragment);

   // sample shadow cube map
   float referenceDistanceToLight = texture(u_shadowCubeMap, -fromLightToFragment).r;
   // compare distances to determine whether the fragment is in shadow
   float shadowFactor = float(referenceDistanceToLight > currentDistanceToLight);

As you can see, he calculates a 3d vector and uses it to sample the cubemap.

.:vinterberg:.

I calculate shadow factor according to the instructions:


float CalcShadowFactor(SamplerComparisonState samShadow, 
                       TextureCube shadowMap, 
					   float3 shadowPosH)
{
float3 l=float3(4.0f,2.0f,8.0f);
float3 d=l-shadowPosH;
float dis=length(d);
d=normalize(d);

	float percentLit = 0.0f;


	[unroll]
	
		percentLit += shadowMap.SampleCmpLevelZero(samShadow, 
			d,dis).r;
	
	return percentLit;
}

It simply dont work, it projects shadows to wrong places, Am I doing something wrong?

l-light world position

shadowPosH-world position calculated by mul(float4(vin.PosL, 1.0f), gWorld).xyz

If all shader code is necessery:


#include "LightHelper.fx"
 
cbuffer cbPerFrame
{
	PointLight gDirLights;
	float3 gEyePosW;

	float  gFogStart;
	float  gFogRange;
	float4 gFogColor; 
};

cbuffer cbPerObject
{
	float4x4 gWorld;
	float4x4 gWorldInvTranspose;
	float4x4 gWorldViewProj;
	float4x4 gTexTransform;
	float4x4 gShadowTransform; 
	Material gMaterial;
}; 


Texture2D gDiffuseMap;
TextureCube gShadowMap;

TextureCube gCubeMap;

SamplerState samLinear
{
	Filter = MIN_MAG_MIP_LINEAR;
	AddressU = WRAP;
	AddressV = WRAP;
};

SamplerComparisonState samShadow
{
	Filter   = COMPARISON_MIN_MAG_MIP_LINEAR;
	AddressU = BORDER;
	AddressV = BORDER;
	AddressW = BORDER;
	BorderColor = float4(0.0f, 0.0f, 0.0f, 0.0f);

    ComparisonFunc = LESS_EQUAL;
};
 
struct VertexIn
{
	float3 PosL    : POSITION;
	float3 NormalL : NORMAL;
	float2 Tex     : TEXCOORD;
};

struct VertexOut
{
	float4 PosH       : SV_POSITION;
	float3 PosL: POSITION0;
    float3 PosW       : POSITION1;
    float3 NormalW    : NORMAL;
	float2 Tex        : TEXCOORD0;
	float3 ShadowPosH : TEXCOORD1;
};

VertexOut VS(VertexIn vin)
{
	VertexOut vout;
	
	
	vout.PosW    = mul(float4(vin.PosL, 1.0f), gWorld).xyz;
	vout.NormalW = mul(vin.NormalL, (float3x3)gWorldInvTranspose);
		
	
	vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
	
	
	vout.Tex = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy;

	
	vout.ShadowPosH = vout.PosW;
	vout.PosL=vin.PosL;
	return vout;
}
 
float4 PS(VertexOut pin, 
          uniform int gLightCount, 
		  uniform bool gUseTexure, 
		  uniform bool gAlphaClip, 
		  uniform bool gFogEnabled, 
		  uniform bool gReflectionEnabled) : SV_Target
{
	
    pin.NormalW = normalize(pin.NormalW);

	
	float3 toEye = gEyePosW - pin.PosW;
float3 toEyeW = normalize(gEyePosW - pin.PosW);
	
	float distToEye = length(toEye);

	
	toEye /= distToEye;
	
    
    float4 texColor = float4(1, 1, 1, 1);
    if(gUseTexure)
	{
		// Próbkuj tekstur?.
		texColor = gDiffuseMap.Sample( samLinear, pin.Tex );

		if(gAlphaClip)
		{
		
			clip(texColor.a - 0.1f);
		}
	}
	 
	
	float4 litColor = texColor;
	if( gLightCount > 0  )
	{  
		
		float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
		float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
		float4 spec    = float4(0.0f, 0.0f, 0.0f, 0.0f);

		
		float3 shadow = float3(1.0f, 1.0f, 1.0f);
	shadow[0] = CalcShadowFactor(samShadow, gShadowMap, pin.ShadowPosH);

		// Sumuj udzia? ?wiat?a z ka?dego ?ród?a.  
		[unroll]
	
			float4 A, D, S;
			ComputePointLight(gMaterial, gDirLights, pin.PosW, pin.NormalW, toEyeW, A, D, S);

			ambient += A;    
			diffuse += shadow[0]*D;
			spec    += shadow[0]*S;
		

		litColor = texColor*(ambient + diffuse) + spec;

		if( gReflectionEnabled )
		{
			float3 incident = -toEye;
			float3 reflectionVector = reflect(incident, pin.NormalW);
			float4 reflectionColor  = gCubeMap.Sample(samLinear, reflectionVector);

			litColor += gMaterial.Reflect*reflectionColor;
		}
	}
 
	

	if( gFogEnabled )
	{
		float fogLerp = saturate( (distToEye - gFogStart) / gFogRange ); 

		
		litColor = lerp(litColor, gFogColor, fogLerp);
	}

	
	litColor.a = gMaterial.Diffuse.a * texColor.a;

    return litColor;
}
//techniques bla bla bla

Have you checked that your six sides of your cubemap produces the correct shadows for their respective directions? Maybe you've gotten the axis signs wrong, so -X produces the shadowmap for +X and so on..?

Edit: Have you tried sampling with -d?


percentLit += shadowMap.SampleCmpLevelZero(samShadow, 
-d,dis).r;

.:vinterberg:.

Hmmm, shadows are on totally wrong positions, not only on incorrect sides, I check depth map and its looks 100% fine, i tried with -d, the result of this was the disappearance of light. Any sugestions? Maybe upload visual project here for tests?

the result of this was the disappearance of light
the result of this was the disappearance of light
the result of this was the disappearance of light
the result of this was the disappearance of light
the result of this was the disappearance of light
the result of this was the disappearance of light
the result of this was the disappearance of light
It looks like the direction that you use to sample the cubemap is backwards. You want to do "shadowPosH - l", assuming that "l" is the world space position of your point light. The code that vinterberg posted is actually incorrect in the same way: it uses the variable name "fromLightToFragment", but it's actually computing a vector from the fragment to the light (this is why it uses "-fromLightToFragment" when sampling the cube map).

Also...if you're going to use SampleCmp to sample a depth buffer, then you can't use the distance from your point light to the surface as the comparison value. Your depth buffer will contain [0, 1] values that correspond to z/w after applying your projection matrix, not the absolute world space distance from the light to the surface. This means you need to project your light->surface vector onto the axis that corresponds to the cubemap face you'll be sampling from:


float3 shadowPos = surfacePos - lightPos;
float3 shadowDistance = length(shadowPos);
float3 shadowDir = normalize(shadowPos);

// Doing the max of the components tells us 2 things: which cubemap face we're going to use,
// and also what the projected distance is onto the major axis for that face.
float projectedDistance = max(max(abs(shadowPos.x), abs(shadowPos.y)), abs(shadowPos.z));

// Compute the project depth value that matches what would be stored in the depth buffer
// for the current cube map face. "ShadowProjection" is the projection matrix used when
// rendering to the shadow map.
float a = ShadowProjection._33;
float b = ShadowProjection._43;
float z = projectedDistance * a + b;
float dbDistance = z / projectedDistance;

return ShadowMap.SampleCmpLevelZero(PCFSampler, shadowDir, dbDistance - Bias);

Thank you MJP that was very helpful, i tested it and yours solution work in 100%.

This topic is closed to new replies.

Advertisement