Advertisement Jump to content
Sign in to follow this  
markypooch

Shadow Mapping Issues

This topic is 1757 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

 

 

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

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?

Edited by markypooch

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!