Shadow Mapping Issues

Started by
1 comment, last by markypooch 10 years ago

Hello all,

I've run into some problems implementing Shadow Mapping.

I am able to Create a seperate render target, depthBuffer, shaderResourceView

I then render all the depth on a first pass from the objects (from the perspective of the one light source) and put it into a texture.

I then use THAT texture as input into the next shader. My problem? No Shadows are appearing on the screen :(

Ill post the code pertaining to the shadow Mapping below and maybe you guys can see something I can't. (I am following the Rastertek tutorials)

 
//Create Shadow Map Texture
    ///////////////////////////////////////////////////
    D3D11_TEXTURE2D_DESC textureDesc;
    HRESULT result;
    D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
    D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
    D3D11_TEXTURE2D_DESC depthBufferDesc;
    D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;


    // Initialize the render target texture description.
    ZeroMemory(&textureDesc, sizeof(textureDesc));

    // Setup the render target texture description.
    textureDesc.Width =  1024;
    textureDesc.Height = 1024;
    textureDesc.MipLevels = 1;
    textureDesc.ArraySize = 1;
    textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
    textureDesc.SampleDesc.Count = 1;
    textureDesc.Usage = D3D11_USAGE_DEFAULT;
    textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
    textureDesc.CPUAccessFlags = 0;
    textureDesc.MiscFlags = 0;

    // Create the render target texture.
    bro->dev->CreateTexture2D(&textureDesc, NULL, &renderTargetTexture);

    // Setup the description of the render target view.
    renderTargetViewDesc.Format = textureDesc.Format;
    renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
    renderTargetViewDesc.Texture2D.MipSlice = 0;

    // Create the render target view.
    bro->dev->CreateRenderTargetView(renderTargetTexture, &renderTargetViewDesc, &renderTargetView);
    
    // Setup the description of the shader resource view.
    shaderResourceViewDesc.Format = textureDesc.Format;
    shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
    shaderResourceViewDesc.Texture2D.MipLevels = 1;

    // Create the shader resource view.
    bro->dev->CreateShaderResourceView(renderTargetTexture, &shaderResourceViewDesc, &shaderResourceView);
    
    // Initialize the description of the depth buffer.
    ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));

    // Set up the description of the depth buffer.
    depthBufferDesc.Width = 1024;
    depthBufferDesc.Height = 1024;
    depthBufferDesc.MipLevels = 1;
    depthBufferDesc.ArraySize = 1;
    depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthBufferDesc.SampleDesc.Count = 1;
    depthBufferDesc.SampleDesc.Quality = 0;
    depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    depthBufferDesc.CPUAccessFlags = 0;
    depthBufferDesc.MiscFlags = 0;

    // Create the texture for the depth buffer using the filled out description.
    bro->dev->CreateTexture2D(&depthBufferDesc, NULL, &depthStencilBuffer);

    // Initailze the depth stencil view description.
    ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));

    // Set up the depth stencil view description.
    depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    depthStencilViewDesc.Texture2D.MipSlice = 0;

    // Create the depth stencil view.
    bro->dev->CreateDepthStencilView(depthStencilBuffer, &depthStencilViewDesc, &depthStencilView);

    // Setup the viewport for rendering.
    viewPort.Width = (float)1024;
    viewPort.Height = (float)1024;
    viewPort.MinDepth = 0.0f;
    viewPort.MaxDepth = 1.0f;
    viewPort.TopLeftX = 0.0f;
    viewPort.TopLeftY = 0.0f;

    // Setup the projection matrix. //lProj == lightProjection
    lProj.lightProj = XMMatrixPerspectiveFovLH(((float)3.12f / 2.0f), 1.0f, 0.1f, 600.0f);

    // Create an orthographic projection matrix for 2D rendering.
    //lProj.lightProj = XMMatrixOrthographicLH((float)1024, (float)1024, 0.1f, 600.0f);
    /////////////////////////////////////////////
    //
 

Thats the code to create the textures for the shadow map and the additonal renderTarget, DepthBuffer, and viewport

 
//RenderToTexture
            /////////////////////////////////////////////////////////
            /////////////////////////////////////////////////////////
            bro->devcon->OMSetRenderTargets(1, &renderTargetView, depthStencilView);
    
            // Set the viewport.
            float clearColor2[] = {0.0f, 0.0f, 0.0f, 0.0f};

            bro->devcon->RSSetViewports(1, &viewPort);
    

            XMFLOAT3 position;
            position.x = lightCB.light[5].pos.x;
            position.y = lightCB.light[5].pos.y;
            position.z = lightCB.light[5].pos.z;

            XMFLOAT3 lookat;
            lookat.x            = 0.0f;
            lookat.y            = 0.0f;
            lookat.z            = 0.0f;

            XMFLOAT3 up;
            up.x         = 0.0f;
            up.y         = -1.0f;
            up.z         = 0.0f;

            lView.lightView = XMMatrixLookAtLH(XMLoadFloat3(&position), XMLoadFloat3(&lookat), XMLoadFloat3(&up));  

            float fieldOfView, screenAspect;

            // Setup field of view and screen aspect for a square light source.
            fieldOfView = (float)3.12 / 2.0f;
            screenAspect = 1.0f;

            // Create the projection matrix for the light.
            lProj.lightProj = XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, 0.1f, 600.0f);

            depthSh.RenderToTexture(bro, 6, &worldMat, &lView.lightView, &lProj.lightProj, vertexBuffer, indexBuffer,
                                   worldCB, lightViewCB, lightProjCB, x, y, 0.0f, 1.57f, 0.0f, 0.0f);

            bro->devcon->OMSetRenderTargets(1, &bro->backBuffer, bro->depthBuffer);
            bro->devcon->RSSetViewports(1, &bro->view);
            //////////////////////////////////////////////////////////////////////
            //////////////////////////////////////////////////////////////////////



            bro->devcon->UpdateSubresource(lightC, 0, 0, lightCB.light, 0, 0);

            unsigned int stride = 0;

            stride = sizeof(Verts);
            unsigned int offset = 0;

            bro->devcon->IASetInputLayout(bro->shadowL);
            bro->devcon->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R16_UINT, offset);
            bro->devcon->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
            bro->devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

            bro->devcon->VSSetShader(bro->shadowVS, 0, 0);
            bro->devcon->PSSetShader(bro->shadowPS, 0, 0);

            bro->devcon->PSSetShaderResources(0, 3, bro->colorMap);
            bro->devcon->PSSetShaderResources(1, 1, &shaderResourceView);
            bro->devcon->PSSetSamplers(0, 1, &bro->colorSampler);
            bro->devcon->PSSetSamplers(1, 1, &clamp);

            bro->rotMat   = XMMatrixRotationRollPitchYaw(1.57f, 0.0f, 0.0f);
            bro->transMat = XMMatrixTranslation(x * xOffset - 0.0f, 0.0f, y * yOffset - 0.0f);

            worldMat = bro->rotMat * bro->transMat;
            worldMat = XMMatrixTranspose(worldMat);

            bro->devcon->UpdateSubresource(worldCB, 0, 0, &worldMat, 0, 0);
            bro->devcon->UpdateSubresource(bro->viewCB, 0, 0, &bro->viewMat, 0, 0);
            bro->devcon->UpdateSubresource(bro->projCB, 0, 0, &bro->projMat, 0, 0);
            bro->devcon->UpdateSubresource(lightViewCB,   0, 0, &lView.lightView, 0, 0);        
            bro->devcon->UpdateSubresource(lightProjCB,  0,  0, &lProj.lightProj, 0, 0);
            bro->devcon->UpdateSubresource(lightC, 0, 0, lightCB.light, 0, 0);

            bro->devcon->VSSetConstantBuffers(0, 1, &worldCB);
            bro->devcon->VSSetConstantBuffers(1, 1, &bro->viewCB);
            bro->devcon->VSSetConstantBuffers(2, 1, &bro->projCB);
            bro->devcon->VSSetConstantBuffers(3, 1, &lightViewCB);
            bro->devcon->VSSetConstantBuffers(4, 1, &lightProjCB);
            bro->devcon->PSSetConstantBuffers(0, 1, &lightC);

            bro->devcon->DrawIndexed(6, 0, 0);

Above is the code to switch the render target view, viewport and to render to the shader resource view through the depthShader Class

After I render the texture through the depthShader Class (whose code Ill post below). I use the texture created as input into the next shader

 
unsigned int stride = sizeof(Verts);
    unsigned int offset = 0;

    bro->devcon->IASetInputLayout(bro->depthL);
    bro->devcon->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R16_UINT, offset);
    bro->devcon->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
    bro->devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    bro->devcon->VSSetShader(bro->depthVS, 0, 0);
    bro->devcon->PSSetShader(bro->depthPS, 0, 0);
    
    bro->transMat = XMMatrixTranslation((x * 2.0f) + xOffset, offsetY, y * -2.0f);
    bro->rotMat   = XMMatrixRotationRollPitchYaw(rotationX, rotationY, rotationZ);

    *worldMat = bro->transMat * bro->rotMat;
    *worldMat = XMMatrixTranspose(*worldMat);

    *lightView = XMMatrixTranspose(*lightView);
    *lightProj = XMMatrixTranspose(*lightProj);

    bro->devcon->UpdateSubresource(worldCB, 0, 0, &worldMat, 0, 0);
    bro->devcon->UpdateSubresource(viewCB, 0, 0, &lightView, 0, 0);
    bro->devcon->UpdateSubresource(projCB, 0, 0, &lightProj, 0, 0);

    bro->devcon->VSSetConstantBuffers(0, 1, &worldCB);
    bro->devcon->VSSetConstantBuffers(1, 1, &viewCB);
    bro->devcon->VSSetConstantBuffers(2, 1, &projCB);

    bro->devcon->DrawIndexed(drawC, 0, 0);

And the corresponding depth shader that I use to render to texture

 
cbuffer world : register(b0)
{
    matrix worldMat;
};

cbuffer view  : register(b1)
{
    matrix viewMat;
};

cbuffer proj  : register(b2)
{
    matrix projMat;
};

struct VS_Input
{
    float4 position : POSITION;
};

struct PS_Input
{
    float4 position      : SV_POSITION;
    float4 depthPosition : TEXTURE0;
};


////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
PS_Input VS(VS_Input input)
{
    PS_Input output = (PS_Input)0;
    
    
    // Change the position vector to be 4 units for proper matrix calculations.
   // input.position.w = 1.0f;

    // Calculate the position of the vertex against the world, view, and projection matrices.
    output.position = mul(input.position, worldMat);
    output.position = mul(output.position, viewMat);
    output.position = mul(output.position, projMat);

    // Store the position value in a second input value for depth value calculations.
    output.depthPosition = output.position;
    
    return output;
}

float4 PS(PS_Input input) : SV_TARGET
{
    float depthValue;
    float4 color;
    
    
    // Get the depth value of the pixel by dividing the Z pixel depth by the homogeneous W coordinate.
    depthValue = input.depthPosition.z / input.depthPosition.w;

    color = float4(depthValue, depthValue, depthValue, 1.0f);

    return color;
}
 

And below is the final shader that takes the rendered to texture image as input and performs the calculations and projective texturing

 
//Load three textures into GPU Register(t0) for one pixel
//////////////////////////////////////////////////////////////////
Texture2D                colorMap[3]            : register(t0);
Texture2D               depthMTexture       : register(t1);

//Load Unused Sampler into GPU Register(s0)
//////////////////////////////////////////////////////////////////
SamplerState            colorSampler        : register(s0);
SamplerState            sampleTypeClamp        : register(s1);

//CONSTANT BUFFERS=========================
//CB's for Matrices, allows C++ Code to send constants
//to the shader and bind them into Registers (b0, b1, b2 respectively)
//===========================================================
cbuffer world : register(b0)
{
    matrix worldMat;
}

cbuffer view  : register(b1)
{
    matrix viewMat;
}

cbuffer proj  : register(b2)
{
    matrix projMat;
}

cbuffer lView : register(b3)
{
    matrix lightViewMat;
}

cbuffer lProj : register(b4)
{
    matrix lightProjMat;
}
//==================================================

//Structure for Light
struct Light
{
    float3 dir;
    float3 att;
    float  range;
    float4 diffuse;
    float4 ambient;
    float  specularPower;
    float4 specularColor;
    float4 isLight;
};

struct Shadow
{
    float4 ambient;
    float4 diffuse;
    float4 specular;
};

//Load the main light into the shader and bind it to register b0
cbuffer LightCB  : register(b0)
{
    Light light[6];
}


//Structures for Vertex and Pixel
/////////////////////////////////////////
struct VS_Input
{
    float4 pos       : POSITION;
    float2 tex       : TEXCOORD;
    float3 norm      : NORMAL;
    float3 binorm    : BINORMAL;
    float3 tang         : TANGENT;
};

struct PS_Input
{
    float4 pos            : SV_POSITION;
    float4 wPos            : POSITION;
    float2 tex            : TEXCOORD;
    float3 norm            : NORMAL;
    float3 binorm        : BINORMAL;
    float3 tang            : TANGENT;

    float4 lightViewP    : TEXCOORD1;
    float3 lightPos     : TEXCOORD2;
};
///////////////////////////////////////////

PS_Input VS(VS_Input vertex)
{
    PS_Input vsOut     = (PS_Input)0;
    float4   cameraPos = 0.0f;

    vsOut.pos = mul(vertex.pos, worldMat);
    vsOut.pos = mul(vsOut.pos , viewMat);
    vsOut.pos = mul(vsOut.pos , projMat);

    vsOut.lightViewP = mul(vertex.pos, worldMat);
    vsOut.lightViewP = mul(vsOut.lightViewP, lightViewMat);
    vsOut.lightViewP = mul(vsOut.lightViewP, lightProjMat);

    vsOut.norm = mul(vertex.norm, worldMat);
    vsOut.norm = normalize(vsOut.norm);

    vsOut.binorm = mul(vertex.binorm, worldMat);
    vsOut.binorm = normalize(vsOut.binorm);

    vsOut.tang   = mul(vertex.tang, worldMat);
    vsOut.tang   = normalize(vsOut.tang);

    vsOut.wPos   = mul(vertex.pos, worldMat);

    cameraPos = mul(vsOut.pos, worldMat);
    cameraPos = mul(cameraPos, viewMat);

    vsOut.tex = vertex.tex;

    return vsOut;
}

float4 PS(PS_Input texel) : SV_TARGET
{
    float3 finalColor = float3(0.0f, 0.0f, 0.0f);
    float4 textureMap = colorMap[0].Sample(colorSampler, texel.tex);
    float4 bumpMap    = float4(0.0f, 0.0f, 0.0f, 0.0f);
    float3 lightToPixelVec[6];
    float  d[6];
    float3 finalAmbient = 0.0f;
    float4 color = 0.0f;
    float4 color2  = 0.0f;
    float4 color3 = 0.0f;
    bool   isCloseEnough = false;
    float  lightIntensity = 0.0f;
    float  lightIntensity2 = 0.0f;
    float  bumpNormal     = 0.0f;
    float  lightClose      = 0.0f;
    bool   bumpHit          = false;

    color = textureMap;

    //Shadow Map Variables
    ////////////////////////////////////
    float  bias                = 0.001f;
    float2 projTexCoord        = float2(0.0f, 0.0f);
    float  depthValue        = 0.0f;
    float  lightDepthValue  = 0.0f;
    ////////////////////////////////////

    bias = 0.001f;

    projTexCoord.x =   texel.lightViewP.x / texel.lightViewP.w / 2.0f + 0.5f;
    projTexCoord.y =  -texel.lightViewP.y / texel.lightViewP.w / 2.0f + 0.5f;


    if((saturate(projTexCoord.x) == projTexCoord.x) && (saturate(projTexCoord.y) == projTexCoord.y))
    {
        depthValue = depthMTexture.Sample(sampleTypeClamp, projTexCoord).r;
        lightDepthValue = texel.lightViewP.z / texel.lightViewP.w;
        lightDepthValue -= bias;

        if (lightDepthValue < depthValue)
        {
            lightIntensity = saturate(dot(texel.norm, texel.lightPos));

            if (lightIntensity > 0.0f)
            {
                bumpMap    = colorMap[1].Sample(colorSampler, texel.tex);
                bumpMap = (bumpMap * 2.0f) - 1.0f;
                bumpNormal = texel.norm + bumpMap.x * texel.tang + bumpMap.y * texel.binorm;

                lightIntensity  = saturate(dot(bumpNormal, -2.0f));
                lightIntensity2 = saturate(dot(texel.norm, -2.0f));

                color2 = lightIntensity *  light[5].diffuse; // light[0].diffuse
                color3 = lightIntensity2 * light[5].diffuse;

                color = saturate(color2);

                bumpHit = true;
                //return color;
            }
        }            
    }

    
    color = light[5].ambient;
    color *= textureMap;

    return color;
}
 

I know it's a lot of code. But if someone could just take a quick glance at my code and tell me what i am overlooking. Am I missing something from the tutorial?

Maybe my texture creation and the arguments I feed to it are off.

Any response is appreciated, I work a bunch so I may not be able to respond swiftly.

-Marcus

Advertisement

I guess one thing I can try in the mean time is check if the shadowMap was even created.

Just take my greyscale image created through renderToTexture and map it onto a quad and see if

its even working

-Marcus

Alright made some progress.

However another peculiar thing occured after the shadow map was created.

The shadow bands around the object. I tried adjusting the bias, however, it still wraps around the

object

Any Idea's of where I should be looking?

This topic is closed to new replies.

Advertisement