0
\$\begingroup\$

I am shadow mapping in Direct3D 9. I'm trying to avoid rendering depth to a 32-bit render target. So, I've created a depth/stencil texture( a texture w/usage Depth/Stencil ). When I render I do this:

//device
IDirect3DDevice9 *pd3dDevice = GetDevice();

// set an rt the same size as the depth/stencil texture(needs attention...this render target will not be rendered to)
pd3dDevice->SetRenderTarget(0, GetShadowMapRT());

// set the shadow map depth/stencil texture surface
pd3dDevice->SetDepthStencilSurface(GetShadowMapDSSurface());

pd3dDevice.SetStreamSource(0, GDEOctree.Geometry,
                Constants.OctreeVertexSize * GDEOctree.StaticGeometryVertexCount, 12);

// set vertex format
pd3dDevice.VertexFormat = SlimDX.Direct3D9.VertexFormat.Position;

// set indices
pd3dDevice.Indices = GDEOctree.ShadowCasterIndices;

// set render states
DeviceManager.SetRenderState(RenderState.ZEnable, 1);
DeviceManager.SetRenderState(RenderState.ZWriteEnable, 1);
DeviceManager.SetRenderState(RenderState.ZFunc, (int)Compare.LessEqual);
DeviceManager.SetRenderState(RenderState.CullMode, (int)Cull.Counterclockwise);
DeviceManager.SetRenderState(RenderState.StencilEnable, 0);
DeviceManager.SetRenderState(RenderState.AlphaBlendEnable, 0);
DeviceManager.SetRenderState(RenderState.ColorWriteEnable, 0);


// draw shadow casting geometry
...

// get the effect
ID3DXEffect *pFX = GetFX();

// set the shadow map depth/stencil texture
pFX->SetTexture(GetShadowMapDSTexture());

// in pixel shader sample shadow map...
?

The problem is that the depth/stencil texture is a D24SX format...How do I sample from a texture of this format?

My original attempt which of course will not work:

tex2D(g_SamplerShadowMap, vShadowMapUV);

I read a post here that says:

When reading from the texture, one extra component in texture coordinates will be the depth to compare with.

Or, how do I convert the color returned from the sampler code above to a single floating point value? The above code will return a 4-component vector but depth should be one value for comparison.

EDIT:

Below is the vertex shader for the shadow map pass...I do not compile a pixel shader for the shadow map pass because color is not written...only depth.

//--------------------------------------------------------------//
// ShadowMap Pass
//--------------------------------------------------------------//
void VS_ShadowMap( in float4 Position : POSITION0, 
                    out float4 oPos : POSITION0 )
{
    // position of geometry in the shadow emitting light's clip space
    oPos = mul(mul(Position, mW), g_mShadowViewProjection);
}

technique DeferredShading
{
    pass ShadowMap
    {
        VertexShader = compile vs_3_0 VS_ShadowMap();
        PixelShader = NULL;
    }   
}
\$\endgroup\$
2
\$\begingroup\$

There are two main ways to do this.

First way is to do exactly what you're trying to avoid doing, and use a render target. This is the way used by the Shadow Mapping sample for D3D9 in the old DirectX SDK, although it needn't be 32-bit (D3DFMT_R16F may well be sufficient). As a possible optimization you could use a NULL depth/stencil target, enable blending, and use either D3DBLENDOP_MIN or D3DBLENDOP_MAX (your mileage may vary).

The second way is to use a Depth Buffer as Texture GPU Hack although be aware that hardware support may be patchy depending on what degree of older hardware you want to support - INTZ looks to be the only format supported across all 3 vendors:

INTZ is for recent (DX10+) hardware. With recent drivers, all three major IHVs expose this. According to ATI, it also allows using stencil buffer while rendering. Also allows reading from depth texture while it’s still being used for depth testing (but not depth writing). Looks like this applies to NV & Intel parts as well.

\$\endgroup\$
  • \$\begingroup\$ thanks darth satan. your first suggestion is the only solution available to me...I'm developing for DX9 hardware...Can you elaborate a little more on the blending method? \$\endgroup\$ – P. Avery Nov 29 '14 at 1:03
  • \$\begingroup\$ also, my question concerns what code to use when sampling a depth/stencil texture of format D24X8. The tex2D() method in HLSL will return a 4 component vector. Will I need to convert the 4 components to a single float? \$\endgroup\$ – P. Avery Nov 29 '14 at 1:08
1
\$\begingroup\$

tex2D(g_SamplerShadowMap, vShadowMapUV).r should get you the depth value, in case your sampler, and texture are set up and bound correctly.

\$\endgroup\$
  • \$\begingroup\$ Color writes are disabled. The idea of this method of shadow mapping is to write depth to a depth/stencil texture with usage 'DepthStencil' and format 'D24X8', not an 'R32F' formatted render target...So, what I'm sampling from is a depth/stencil texture. Is the data written to the 'r' component of the depth/stencil texture? \$\endgroup\$ – P. Avery Oct 26 '14 at 17:17
  • \$\begingroup\$ I am using DX11, which might be different, but if I want to access a D24X8 depthstencil resource, then I do it via a R24X8 shader resource view. So the depth information is in the red channel. \$\endgroup\$ – János Turánszki Oct 27 '14 at 11:55
  • \$\begingroup\$ It is different for DX9... \$\endgroup\$ – P. Avery Oct 27 '14 at 18:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.