Tutorial 42: Soft Shadows - RasterTek

文章推薦指數: 80 %
投票人數:10人

To create soft shadows we first need to modify the shadow shader. Instead of using the shader to render the shadowed scene with lighting as it previously did it ... Tutorial42:SoftShadows ThistutorialwillcoverhowtoimplementsoftshadowsinDirectX11usingHLSLandC++. Thecodeinthistutorialisbasedontheshadowmappingtutorial. Oneoftheissueswithshadowmapsisthelackofprecisioninthetextureusedfortheshadowmap. Evenhighresolutiontexturessuchas1024x1024(aswasusedintheshadowmappingtutorial)stillcreateshadowswithjaggededges. Forexamplelookingattheedgeoftheshadowforthespherewegetthefollowingvisualartifact: Withthatsaidoneofthemainadvantagesofusingshadowmapsisthatwecaneasilyproducesoftshadowstofixthejaggedshadowedges. Tocreatesoftshadowswefirstneedtomodifytheshadowshader. Insteadofusingtheshadertorendertheshadowedscenewithlightingasitpreviouslydiditwillnowinsteadjustrender shadowareasaspureblackandtheilluminatedareasaspurewhite. Sorenderingourscenewillnowproduceablackandwhiteimageasfollows: Alsowerendertheblackandwhitescenetoarendertotextureinsteadoftothebackbuffer. Thereasonwerendertoatextureissothatwecanperformthenextstepwhichistoblurtheblackandwhiteimage. Forthistutorialwewillperformaregularblurlikewedidintheblurtutorial(Tutorial36). Withtheblackandwhitetextureblurredwenowhavethefollowingtextureresult: Asyoucanseetheshadowedgesarenowblurredcreatingthesoftshadows. Toapplythesoftshadowstothefinalsceneweusejustaregularlightingshaderexceptthatittakesasinputtheblurredimage andattheendofthepixelshaderwemultiplethecolorresultbytheprojectedblurimagetogetsoftshadows. Weprojecttheblurredimagefromthecamera'sviewpoint. Doingsogivesusthefollowingsoftshadowscene: Wewillstartthecodesectionofthetutorialbylookingatthemodifiedshadowshader. Shadow.vs Thevertexshadercanremainthesame. //////////////////////////////////////////////////////////////////////////////// //Filename:shadow.vs //////////////////////////////////////////////////////////////////////////////// ///////////// //GLOBALS// ///////////// cbufferMatrixBuffer { matrixworldMatrix; matrixviewMatrix; matrixprojectionMatrix; matrixlightViewMatrix; matrixlightProjectionMatrix; }; ////////////////////// //CONSTANTBUFFERS// ////////////////////// cbufferLightBuffer2 { float3lightPosition; floatpadding; }; ////////////// //TYPEDEFS// ////////////// structVertexInputType { float4position:POSITION; float2tex:TEXCOORD0; float3normal:NORMAL; }; structPixelInputType { float4position:SV_POSITION; float2tex:TEXCOORD0; float3normal:NORMAL; float4lightViewPosition:TEXCOORD1; float3lightPos:TEXCOORD2; }; //////////////////////////////////////////////////////////////////////////////// //VertexShader //////////////////////////////////////////////////////////////////////////////// PixelInputTypeShadowVertexShader(VertexInputTypeinput) { PixelInputTypeoutput; float4worldPosition; //Changethepositionvectortobe4unitsforpropermatrixcalculations. input.position.w=1.0f; //Calculatethepositionofthevertexagainsttheworld,view,andprojectionmatrices. output.position=mul(input.position,worldMatrix); output.position=mul(output.position,viewMatrix); output.position=mul(output.position,projectionMatrix); //Calculatethepositionoftheverticeasviewedbythelightsource. output.lightViewPosition=mul(input.position,worldMatrix); output.lightViewPosition=mul(output.lightViewPosition,lightViewMatrix); output.lightViewPosition=mul(output.lightViewPosition,lightProjectionMatrix); //Storethetexturecoordinatesforthepixelshader. output.tex=input.tex; //Calculatethenormalvectoragainsttheworldmatrixonly. output.normal=mul(input.normal,(float3x3)worldMatrix); //Normalizethenormalvector. output.normal=normalize(output.normal); //Calculatethepositionofthevertexintheworld. worldPosition=mul(input.position,worldMatrix); //Determinethelightpositionbasedonthepositionofthelightandthepositionofthevertexintheworld. output.lightPos=lightPosition.xyz-worldPosition.xyz; //Normalizethelightpositionvector. output.lightPos=normalize(output.lightPos); returnoutput; } Shadow.ps Inthepixelshaderwehaveremovedanumberoftheinputsaslightingandtexturingarenolongerneededtoproducetheblackandwhiteshadowimage. //////////////////////////////////////////////////////////////////////////////// //Filename:shadow.ps //////////////////////////////////////////////////////////////////////////////// ////////////// //TEXTURES// ////////////// Texture2DdepthMapTexture:register(t0); /////////////////// //SAMPLESTATES// /////////////////// SamplerStateSampleTypeClamp:register(s0); ////////////// //TYPEDEFS// ////////////// structPixelInputType { float4position:SV_POSITION; float2tex:TEXCOORD0; float3normal:NORMAL; float4lightViewPosition:TEXCOORD1; float3lightPos:TEXCOORD2; }; //////////////////////////////////////////////////////////////////////////////// //PixelShader //////////////////////////////////////////////////////////////////////////////// float4ShadowPixelShader(PixelInputTypeinput):SV_TARGET { floatbias; float4color; float2projectTexCoord; floatdepthValue; floatlightDepthValue; floatlightIntensity; //Setthebiasvalueforfixingthefloatingpointprecisionissues. bias=0.001f; Nowinthepixelshaderwesetthedefaultcolortobeblack(shadowed). //Setthedefaultoutputcolortobeblack(shadow). color=float4(0.0f,0.0f,0.0f,1.0f); //Calculatetheprojectedtexturecoordinates. projectTexCoord.x=input.lightViewPosition.x/input.lightViewPosition.w/2.0f+0.5f; projectTexCoord.y=-input.lightViewPosition.y/input.lightViewPosition.w/2.0f+0.5f; //Determineiftheprojectedcoordinatesareinthe0to1range.Ifsothenthispixelisintheviewofthelight. if((saturate(projectTexCoord.x)==projectTexCoord.x)&&(saturate(projectTexCoord.y)==projectTexCoord.y)) { //Sampletheshadowmapdepthvaluefromthedepthtextureusingthesamplerattheprojectedtexturecoordinatelocation. depthValue=depthMapTexture.Sample(SampleTypeClamp,projectTexCoord).r; //Calculatethedepthofthelight. lightDepthValue=input.lightViewPosition.z/input.lightViewPosition.w; //SubtractthebiasfromthelightDepthValue. lightDepthValue=lightDepthValue-bias; //Comparethedepthoftheshadowmapvalueandthedepthofthelighttodeterminewhethertoshadowortolightthispixel. //Ifthelightisinfrontoftheobjectthenlightthepixel,ifnotthenshadowthispixelsinceanobject(occluder)iscastingashadowonit. if(lightDepthValue0.0f) { Andifwedetermineapixelisilluminatedthenitiscoloredpurewhite. color=float4(1.0f,1.0f,1.0f,1.0f); } } } Thiswillreturnablackandwhiteimageoftheshadowedscenesowecanuseitasinputtotheblurringshader. returncolor; } Shadowshaderclass.h TheShadowShaderClasshashadjustthetexturingandlightingcolorelementsremovedfromitsinceitonlyneedstoproduceanun-texturedblackandwhiteimage. Otherwiseitremainsthesame. //////////////////////////////////////////////////////////////////////////////// //Filename:shadowshaderclass.h //////////////////////////////////////////////////////////////////////////////// #ifndef_SHADOWSHADERCLASS_H_ #define_SHADOWSHADERCLASS_H_ ////////////// //INCLUDES// ////////////// #include #include #include #include usingnamespacestd; //////////////////////////////////////////////////////////////////////////////// //Classname:ShadowShaderClass //////////////////////////////////////////////////////////////////////////////// classShadowShaderClass { private: structMatrixBufferType { D3DXMATRIXworld; D3DXMATRIXview; D3DXMATRIXprojection; D3DXMATRIXlightView; D3DXMATRIXlightProjection; }; structLightBufferType2 { D3DXVECTOR3lightPosition; floatpadding; }; public: ShadowShaderClass(); ShadowShaderClass(constShadowShaderClass&); ~ShadowShaderClass(); boolInitialize(ID3D11Device*,HWND); voidShutdown(); boolRender(ID3D11DeviceContext*,int,D3DXMATRIX,D3DXMATRIX,D3DXMATRIX,D3DXMATRIX,D3DXMATRIX,ID3D11ShaderResourceView*,D3DXVECTOR3); private: boolInitializeShader(ID3D11Device*,HWND,WCHAR*,WCHAR*); voidShutdownShader(); voidOutputShaderErrorMessage(ID3D10Blob*,HWND,WCHAR*); boolSetShaderParameters(ID3D11DeviceContext*,D3DXMATRIX,D3DXMATRIX,D3DXMATRIX,D3DXMATRIX,D3DXMATRIX,ID3D11ShaderResourceView*,D3DXVECTOR3); voidRenderShader(ID3D11DeviceContext*,int); private: ID3D11VertexShader*m_vertexShader; ID3D11PixelShader*m_pixelShader; ID3D11InputLayout*m_layout; ID3D11SamplerState*m_sampleStateClamp; ID3D11Buffer*m_matrixBuffer; ID3D11Buffer*m_lightBuffer2; }; #endif Shadowshaderclass.cpp //////////////////////////////////////////////////////////////////////////////// //Filename:shadowshaderclass.cpp //////////////////////////////////////////////////////////////////////////////// #include"shadowshaderclass.h" ShadowShaderClass::ShadowShaderClass() { m_vertexShader=0; m_pixelShader=0; m_layout=0; m_sampleStateClamp=0; m_matrixBuffer=0; m_lightBuffer2=0; } ShadowShaderClass::ShadowShaderClass(constShadowShaderClass&other) { } ShadowShaderClass::~ShadowShaderClass() { } boolShadowShaderClass::Initialize(ID3D11Device*device,HWNDhwnd) { boolresult; //Initializethevertexandpixelshaders. result=InitializeShader(device,hwnd,L"../Engine/shadow.vs",L"../Engine/shadow.ps"); if(!result) { returnfalse; } returntrue; } voidShadowShaderClass::Shutdown() { //Shutdownthevertexandpixelshadersaswellastherelatedobjects. ShutdownShader(); return; } boolShadowShaderClass::Render(ID3D11DeviceContext*deviceContext,intindexCount,D3DXMATRIXworldMatrix,D3DXMATRIXviewMatrix, D3DXMATRIXprojectionMatrix,D3DXMATRIXlightViewMatrix,D3DXMATRIXlightProjectionMatrix, ID3D11ShaderResourceView*depthMapTexture,D3DXVECTOR3lightPosition) { boolresult; //Settheshaderparametersthatitwilluseforrendering. result=SetShaderParameters(deviceContext,worldMatrix,viewMatrix,projectionMatrix,lightViewMatrix,lightProjectionMatrix,depthMapTexture, lightPosition); if(!result) { returnfalse; } //Nowrenderthepreparedbufferswiththeshader. RenderShader(deviceContext,indexCount); returntrue; } boolShadowShaderClass::InitializeShader(ID3D11Device*device,HWNDhwnd,WCHAR*vsFilename,WCHAR*psFilename) { HRESULTresult; ID3D10Blob*errorMessage; ID3D10Blob*vertexShaderBuffer; ID3D10Blob*pixelShaderBuffer; D3D11_INPUT_ELEMENT_DESCpolygonLayout[3]; unsignedintnumElements; D3D11_SAMPLER_DESCsamplerDesc; D3D11_BUFFER_DESCmatrixBufferDesc; D3D11_BUFFER_DESClightBufferDesc2; //Initializethepointersthisfunctionwillusetonull. errorMessage=0; vertexShaderBuffer=0; pixelShaderBuffer=0; //Compilethevertexshadercode. result=D3DX11CompileFromFile(vsFilename,NULL,NULL,"ShadowVertexShader","vs_5_0",D3D10_SHADER_ENABLE_STRICTNESS,0,NULL, &vertexShaderBuffer,&errorMessage,NULL); if(FAILED(result)) { //Iftheshaderfailedtocompileitshouldhavewritensomethingtotheerrormessage. if(errorMessage) { OutputShaderErrorMessage(errorMessage,hwnd,vsFilename); } //Iftherewasnothingintheerrormessagethenitsimplycouldnotfindtheshaderfileitself. else { MessageBox(hwnd,vsFilename,L"MissingShaderFile",MB_OK); } returnfalse; } //Compilethepixelshadercode. result=D3DX11CompileFromFile(psFilename,NULL,NULL,"ShadowPixelShader","ps_5_0",D3D10_SHADER_ENABLE_STRICTNESS,0,NULL, &pixelShaderBuffer,&errorMessage,NULL); if(FAILED(result)) { //Iftheshaderfailedtocompileitshouldhavewritensomethingtotheerrormessage. if(errorMessage) { OutputShaderErrorMessage(errorMessage,hwnd,psFilename); } //Iftherewasnothingintheerrormessagethenitsimplycouldnotfindthefileitself. else { MessageBox(hwnd,psFilename,L"MissingShaderFile",MB_OK); } returnfalse; } //Createthevertexshaderfromthebuffer. result=device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(),vertexShaderBuffer->GetBufferSize(),NULL,&m_vertexShader); if(FAILED(result)) { returnfalse; } //Createthepixelshaderfromthebuffer. result=device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(),pixelShaderBuffer->GetBufferSize(),NULL,&m_pixelShader); if(FAILED(result)) { returnfalse; } //Createthevertexinputlayoutdescription. polygonLayout[0].SemanticName="POSITION"; polygonLayout[0].SemanticIndex=0; polygonLayout[0].Format=DXGI_FORMAT_R32G32B32_FLOAT; polygonLayout[0].InputSlot=0; polygonLayout[0].AlignedByteOffset=0; polygonLayout[0].InputSlotClass=D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[0].InstanceDataStepRate=0; polygonLayout[1].SemanticName="TEXCOORD"; polygonLayout[1].SemanticIndex=0; polygonLayout[1].Format=DXGI_FORMAT_R32G32_FLOAT; polygonLayout[1].InputSlot=0; polygonLayout[1].AlignedByteOffset=D3D11_APPEND_ALIGNED_ELEMENT; polygonLayout[1].InputSlotClass=D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[1].InstanceDataStepRate=0; polygonLayout[2].SemanticName="NORMAL"; polygonLayout[2].SemanticIndex=0; polygonLayout[2].Format=DXGI_FORMAT_R32G32B32_FLOAT; polygonLayout[2].InputSlot=0; polygonLayout[2].AlignedByteOffset=D3D11_APPEND_ALIGNED_ELEMENT; polygonLayout[2].InputSlotClass=D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[2].InstanceDataStepRate=0; //Getacountoftheelementsinthelayout. numElements=sizeof(polygonLayout)/sizeof(polygonLayout[0]); //Createthevertexinputlayout. result=device->CreateInputLayout(polygonLayout,numElements,vertexShaderBuffer->GetBufferPointer(),vertexShaderBuffer->GetBufferSize(), &m_layout); if(FAILED(result)) { returnfalse; } //Releasethevertexshaderbufferandpixelshaderbuffersincetheyarenolongerneeded. vertexShaderBuffer->Release(); vertexShaderBuffer=0; pixelShaderBuffer->Release(); pixelShaderBuffer=0; //Createaclamptexturesamplerstatedescription. samplerDesc.Filter=D3D11_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.AddressU=D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressV=D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressW=D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.MipLODBias=0.0f; samplerDesc.MaxAnisotropy=1; samplerDesc.ComparisonFunc=D3D11_COMPARISON_ALWAYS; samplerDesc.BorderColor[0]=0; samplerDesc.BorderColor[1]=0; samplerDesc.BorderColor[2]=0; samplerDesc.BorderColor[3]=0; samplerDesc.MinLOD=0; samplerDesc.MaxLOD=D3D11_FLOAT32_MAX; //Createthetexturesamplerstate. result=device->CreateSamplerState(&samplerDesc,&m_sampleStateClamp); if(FAILED(result)) { returnfalse; } //Setupthedescriptionofthedynamicmatrixconstantbufferthatisinthevertexshader. matrixBufferDesc.Usage=D3D11_USAGE_DYNAMIC; matrixBufferDesc.ByteWidth=sizeof(MatrixBufferType); matrixBufferDesc.BindFlags=D3D11_BIND_CONSTANT_BUFFER; matrixBufferDesc.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE; matrixBufferDesc.MiscFlags=0; matrixBufferDesc.StructureByteStride=0; //Createtheconstantbufferpointersowecanaccessthevertexshaderconstantbufferfromwithinthisclass. result=device->CreateBuffer(&matrixBufferDesc,NULL,&m_matrixBuffer); if(FAILED(result)) { returnfalse; } //Setupthedescriptionofthelightdynamicconstantbufferthatisinthevertexshader. lightBufferDesc2.Usage=D3D11_USAGE_DYNAMIC; lightBufferDesc2.ByteWidth=sizeof(LightBufferType2); lightBufferDesc2.BindFlags=D3D11_BIND_CONSTANT_BUFFER; lightBufferDesc2.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE; lightBufferDesc2.MiscFlags=0; lightBufferDesc2.StructureByteStride=0; //Createtheconstantbufferpointersowecanaccessthevertexshaderconstantbufferfromwithinthisclass. result=device->CreateBuffer(&lightBufferDesc2,NULL,&m_lightBuffer2); if(FAILED(result)) { returnfalse; } returntrue; } voidShadowShaderClass::ShutdownShader() { //Releasethelightconstantbuffer. if(m_lightBuffer2) { m_lightBuffer2->Release(); m_lightBuffer2=0; } //Releasethematrixconstantbuffer. if(m_matrixBuffer) { m_matrixBuffer->Release(); m_matrixBuffer=0; } //Releasethesamplerstate. if(m_sampleStateClamp) { m_sampleStateClamp->Release(); m_sampleStateClamp=0; } //Releasethelayout. if(m_layout) { m_layout->Release(); m_layout=0; } //Releasethepixelshader. if(m_pixelShader) { m_pixelShader->Release(); m_pixelShader=0; } //Releasethevertexshader. if(m_vertexShader) { m_vertexShader->Release(); m_vertexShader=0; } return; } voidShadowShaderClass::OutputShaderErrorMessage(ID3D10Blob*errorMessage,HWNDhwnd,WCHAR*shaderFilename) { char*compileErrors; unsignedlongbufferSize,i; ofstreamfout; //Getapointertotheerrormessagetextbuffer. compileErrors=(char*)(errorMessage->GetBufferPointer()); //Getthelengthofthemessage. bufferSize=errorMessage->GetBufferSize(); //Openafiletowritetheerrormessageto. fout.open("shader-error.txt"); //Writeouttheerrormessage. for(i=0;iRelease(); errorMessage=0; //Popamessageuponthescreentonotifytheusertocheckthetextfileforcompileerrors. MessageBox(hwnd,L"Errorcompilingshader.Checkshader-error.txtformessage.",shaderFilename,MB_OK); return; } boolShadowShaderClass::SetShaderParameters(ID3D11DeviceContext*deviceContext,D3DXMATRIXworldMatrix,D3DXMATRIXviewMatrix, D3DXMATRIXprojectionMatrix,D3DXMATRIXlightViewMatrix,D3DXMATRIXlightProjectionMatrix, ID3D11ShaderResourceView*depthMapTexture,D3DXVECTOR3lightPosition) { HRESULTresult; D3D11_MAPPED_SUBRESOURCEmappedResource; unsignedintbufferNumber; MatrixBufferType*dataPtr; LightBufferType2*dataPtr3; //Transposethematricestopreparethemfortheshader. D3DXMatrixTranspose(&worldMatrix,&worldMatrix); D3DXMatrixTranspose(&viewMatrix,&viewMatrix); D3DXMatrixTranspose(&projectionMatrix,&projectionMatrix); D3DXMatrixTranspose(&lightViewMatrix,&lightViewMatrix); D3DXMatrixTranspose(&lightProjectionMatrix,&lightProjectionMatrix); //Locktheconstantbuffersoitcanbewrittento. result=deviceContext->Map(m_matrixBuffer,0,D3D11_MAP_WRITE_DISCARD,0,&mappedResource); if(FAILED(result)) { returnfalse; } //Getapointertothedataintheconstantbuffer. dataPtr=(MatrixBufferType*)mappedResource.pData; //Copythematricesintotheconstantbuffer. dataPtr->world=worldMatrix; dataPtr->view=viewMatrix; dataPtr->projection=projectionMatrix; dataPtr->lightView=lightViewMatrix; dataPtr->lightProjection=lightProjectionMatrix; //Unlocktheconstantbuffer. deviceContext->Unmap(m_matrixBuffer,0); //Setthepositionoftheconstantbufferinthevertexshader. bufferNumber=0; //Nowsettheconstantbufferinthevertexshaderwiththeupdatedvalues. deviceContext->VSSetConstantBuffers(bufferNumber,1,&m_matrixBuffer); //Setshadertextureresourceinthepixelshader. deviceContext->PSSetShaderResources(0,1,&depthMapTexture); //Lockthesecondlightconstantbuffersoitcanbewrittento. result=deviceContext->Map(m_lightBuffer2,0,D3D11_MAP_WRITE_DISCARD,0,&mappedResource); if(FAILED(result)) { returnfalse; } //Getapointertothedataintheconstantbuffer. dataPtr3=(LightBufferType2*)mappedResource.pData; //Copythelightingvariablesintotheconstantbuffer. dataPtr3->lightPosition=lightPosition; dataPtr3->padding=0.0f; //Unlocktheconstantbuffer. deviceContext->Unmap(m_lightBuffer2,0); //Setthepositionofthelightconstantbufferinthevertexshader. bufferNumber=1; //Finallysetthelightconstantbufferinthepixelshaderwiththeupdatedvalues. deviceContext->VSSetConstantBuffers(bufferNumber,1,&m_lightBuffer2); returntrue; } voidShadowShaderClass::RenderShader(ID3D11DeviceContext*deviceContext,intindexCount) { //Setthevertexinputlayout. deviceContext->IASetInputLayout(m_layout); //Setthevertexandpixelshadersthatwillbeusedtorenderthistriangle. deviceContext->VSSetShader(m_vertexShader,NULL,0); deviceContext->PSSetShader(m_pixelShader,NULL,0); //Setthesamplerstatesinthepixelshader. deviceContext->PSSetSamplers(0,1,&m_sampleStateClamp); //Renderthetriangle. deviceContext->DrawIndexed(indexCount,0,0); return; } Softshadow.vs Thesoftshadowshadersarewherewelightthesceneasnormalbutthenprojecttheblurredblackandwhiteshadow textureontothescenetocompletethesoftshadoweffect. //////////////////////////////////////////////////////////////////////////////// //Filename:softshadow.vs //////////////////////////////////////////////////////////////////////////////// ///////////// //GLOBALS// ///////////// cbufferMatrixBuffer { matrixworldMatrix; matrixviewMatrix; matrixprojectionMatrix; }; ////////////////////// //CONSTANTBUFFERS// ////////////////////// cbufferLightBuffer2 { float3lightPosition; floatpadding; }; ////////////// //TYPEDEFS// ////////////// structVertexInputType { float4position:POSITION; float2tex:TEXCOORD0; float3normal:NORMAL; }; structPixelInputType { float4position:SV_POSITION; float2tex:TEXCOORD0; float3normal:NORMAL; float4viewPosition:TEXCOORD1; float3lightPos:TEXCOORD2; }; //////////////////////////////////////////////////////////////////////////////// //VertexShader //////////////////////////////////////////////////////////////////////////////// PixelInputTypeSoftShadowVertexShader(VertexInputTypeinput) { PixelInputTypeoutput; float4worldPosition; //Changethepositionvectortobe4unitsforpropermatrixcalculations. input.position.w=1.0f; //Calculatethepositionofthevertexagainsttheworld,view,andprojectionmatrices. output.position=mul(input.position,worldMatrix); output.position=mul(output.position,viewMatrix); output.position=mul(output.position,projectionMatrix); TheviewPositionwillbeusedtocalculatetheprojectioncoordinatestoprojectthesoftshadowsontothescene. //Storethepositionoftheverticeasviewedbythecamerainaseparatevariable. output.viewPosition=output.position; //Storethetexturecoordinatesforthepixelshader. output.tex=input.tex; //Calculatethenormalvectoragainsttheworldmatrixonly. output.normal=mul(input.normal,(float3x3)worldMatrix); //Normalizethenormalvector. output.normal=normalize(output.normal); //Calculatethepositionofthevertexintheworld. worldPosition=mul(input.position,worldMatrix); //Determinethelightpositionbasedonthepositionofthelightandthepositionofthevertexintheworld. output.lightPos=lightPosition.xyz-worldPosition.xyz; //Normalizethelightpositionvector. output.lightPos=normalize(output.lightPos); returnoutput; } Softshadow.ps //////////////////////////////////////////////////////////////////////////////// //Filename:softshadow.ps //////////////////////////////////////////////////////////////////////////////// ////////////// //TEXTURES// ////////////// Texture2DshaderTexture:register(t0); TheshadowTextureistheblackandwhiteblurredimagethatcontainsthesoftshadows.Wewillprojectthistextureontothescene. Texture2DshadowTexture:register(t1); /////////////////// //SAMPLESTATES// /////////////////// SamplerStateSampleTypeClamp:register(s0); SamplerStateSampleTypeWrap:register(s1); ////////////////////// //CONSTANTBUFFERS// ////////////////////// cbufferLightBuffer { float4ambientColor; float4diffuseColor; }; ////////////// //TYPEDEFS// ////////////// structPixelInputType { float4position:SV_POSITION; float2tex:TEXCOORD0; float3normal:NORMAL; float4viewPosition:TEXCOORD1; float3lightPos:TEXCOORD2; }; //////////////////////////////////////////////////////////////////////////////// //PixelShader //////////////////////////////////////////////////////////////////////////////// float4SoftShadowPixelShader(PixelInputTypeinput):SV_TARGET { float4color; floatlightIntensity; float4textureColor; float2projectTexCoord; floatshadowValue; Calculatethelightingandtexturingasnormal. //Setthedefaultoutputcolortotheambientlightvalueforallpixels. color=ambientColor; //Calculatetheamountoflightonthispixel. lightIntensity=saturate(dot(input.normal,input.lightPos)); if(lightIntensity>0.0f) { //Determinethelightcolorbasedonthediffusecolorandtheamountoflightintensity. color+=(diffuseColor*lightIntensity); //Saturatethelightcolor. color=saturate(color); } //Samplethepixelcolorfromthetextureusingthesampleratthistexturecoordinatelocation. textureColor=shaderTexture.Sample(SampleTypeWrap,input.tex); //Combinethelightandtexturecolor. color=color*textureColor; Nowcalculatetheprojectedcoordinatestosampletheblurredblackandwhiteimagefrombasedonthecamera'sviewpoint. //Calculatetheprojectedtexturecoordinatestobeusedwiththeshadowtexture. projectTexCoord.x=input.viewPosition.x/input.viewPosition.w/2.0f+0.5f; projectTexCoord.y=-input.viewPosition.y/input.viewPosition.w/2.0f+0.5f; Samplethesoftshadowimageusingtheprojectedcoordinatesandthenmultipleitinthesamefashionasalightmaptothefinalcolortogetthesoftshadoweffect. //Sampletheshadowvaluefromtheshadowtextureusingthesamplerattheprojectedtexturecoordinatelocation. shadowValue=shadowTexture.Sample(SampleTypeClamp,projectTexCoord).r; //Combinetheshadowswiththefinalcolor. color=color*shadowValue; returncolor; } Softshadowshaderclass.h TheSoftShadowShaderClassisthesameastheLightShaderClassexceptthatwealsoprovideablurredblackand whitesoftshadowtextureasinputtotheRenderfunction. //////////////////////////////////////////////////////////////////////////////// //Filename:softshadowshaderclass.h //////////////////////////////////////////////////////////////////////////////// #ifndef_SOFTSHADOWSHADERCLASS_H_ #define_SOFTSHADOWSHADERCLASS_H_ ////////////// //INCLUDES// ////////////// #include #include #include #include usingnamespacestd; //////////////////////////////////////////////////////////////////////////////// //Classname:SoftShadowShaderClass //////////////////////////////////////////////////////////////////////////////// classSoftShadowShaderClass { private: structMatrixBufferType { D3DXMATRIXworld; D3DXMATRIXview; D3DXMATRIXprojection; }; structLightBufferType { D3DXVECTOR4ambientColor; D3DXVECTOR4diffuseColor; }; structLightBufferType2 { D3DXVECTOR3lightPosition; floatpadding; }; public: SoftShadowShaderClass(); SoftShadowShaderClass(constSoftShadowShaderClass&); ~SoftShadowShaderClass(); boolInitialize(ID3D11Device*,HWND); voidShutdown(); boolRender(ID3D11DeviceContext*,int,D3DXMATRIX,D3DXMATRIX,D3DXMATRIX,ID3D11ShaderResourceView*,ID3D11ShaderResourceView*,D3DXVECTOR3, D3DXVECTOR4,D3DXVECTOR4); private: boolInitializeShader(ID3D11Device*,HWND,WCHAR*,WCHAR*); voidShutdownShader(); voidOutputShaderErrorMessage(ID3D10Blob*,HWND,WCHAR*); boolSetShaderParameters(ID3D11DeviceContext*,D3DXMATRIX,D3DXMATRIX,D3DXMATRIX,ID3D11ShaderResourceView*,ID3D11ShaderResourceView*,D3DXVECTOR3, D3DXVECTOR4,D3DXVECTOR4); voidRenderShader(ID3D11DeviceContext*,int); private: ID3D11VertexShader*m_vertexShader; ID3D11PixelShader*m_pixelShader; ID3D11InputLayout*m_layout; ID3D11SamplerState*m_sampleStateWrap; ID3D11SamplerState*m_sampleStateClamp; ID3D11Buffer*m_matrixBuffer; ID3D11Buffer*m_lightBuffer; ID3D11Buffer*m_lightBuffer2; }; #endif Softshadowshaderclass.cpp //////////////////////////////////////////////////////////////////////////////// //Filename:softshadowshaderclass.cpp //////////////////////////////////////////////////////////////////////////////// #include"softshadowshaderclass.h" SoftShadowShaderClass::SoftShadowShaderClass() { m_vertexShader=0; m_pixelShader=0; m_layout=0; m_sampleStateWrap=0; m_sampleStateClamp=0; m_matrixBuffer=0; m_lightBuffer=0; m_lightBuffer2=0; } SoftShadowShaderClass::SoftShadowShaderClass(constSoftShadowShaderClass&other) { } SoftShadowShaderClass::~SoftShadowShaderClass() { } boolSoftShadowShaderClass::Initialize(ID3D11Device*device,HWNDhwnd) { boolresult; LoadthesoftshadowHLSLprograms. //Initializethevertexandpixelshaders. result=InitializeShader(device,hwnd,L"../Engine/softshadow.vs",L"../Engine/softshadow.ps"); if(!result) { returnfalse; } returntrue; } voidSoftShadowShaderClass::Shutdown() { //Shutdownthevertexandpixelshadersaswellastherelatedobjects. ShutdownShader(); return; } boolSoftShadowShaderClass::Render(ID3D11DeviceContext*deviceContext,intindexCount,D3DXMATRIXworldMatrix,D3DXMATRIXviewMatrix, D3DXMATRIXprojectionMatrix,ID3D11ShaderResourceView*texture,ID3D11ShaderResourceView*shadowTexture, D3DXVECTOR3lightPosition,D3DXVECTOR4ambientColor,D3DXVECTOR4diffuseColor) { boolresult; //Settheshaderparametersthatitwilluseforrendering. result=SetShaderParameters(deviceContext,worldMatrix,viewMatrix,projectionMatrix,texture,shadowTexture,lightPosition,ambientColor, diffuseColor); if(!result) { returnfalse; } //Nowrenderthepreparedbufferswiththeshader. RenderShader(deviceContext,indexCount); returntrue; } boolSoftShadowShaderClass::InitializeShader(ID3D11Device*device,HWNDhwnd,WCHAR*vsFilename,WCHAR*psFilename) { HRESULTresult; ID3D10Blob*errorMessage; ID3D10Blob*vertexShaderBuffer; ID3D10Blob*pixelShaderBuffer; D3D11_INPUT_ELEMENT_DESCpolygonLayout[3]; unsignedintnumElements; D3D11_SAMPLER_DESCsamplerDesc; D3D11_BUFFER_DESCmatrixBufferDesc; D3D11_BUFFER_DESClightBufferDesc; D3D11_BUFFER_DESClightBufferDesc2; //Initializethepointersthisfunctionwillusetonull. errorMessage=0; vertexShaderBuffer=0; pixelShaderBuffer=0; CompileandloadthesoftshadowHLSLprograms. //Compilethevertexshadercode. result=D3DX11CompileFromFile(vsFilename,NULL,NULL,"SoftShadowVertexShader","vs_5_0",D3D10_SHADER_ENABLE_STRICTNESS,0,NULL, &vertexShaderBuffer,&errorMessage,NULL); if(FAILED(result)) { //Iftheshaderfailedtocompileitshouldhavewritensomethingtotheerrormessage. if(errorMessage) { OutputShaderErrorMessage(errorMessage,hwnd,vsFilename); } //Iftherewasnothingintheerrormessagethenitsimplycouldnotfindtheshaderfileitself. else { MessageBox(hwnd,vsFilename,L"MissingShaderFile",MB_OK); } returnfalse; } //Compilethepixelshadercode. result=D3DX11CompileFromFile(psFilename,NULL,NULL,"SoftShadowPixelShader","ps_5_0",D3D10_SHADER_ENABLE_STRICTNESS,0,NULL, &pixelShaderBuffer,&errorMessage,NULL); if(FAILED(result)) { //Iftheshaderfailedtocompileitshouldhavewritensomethingtotheerrormessage. if(errorMessage) { OutputShaderErrorMessage(errorMessage,hwnd,psFilename); } //Iftherewasnothingintheerrormessagethenitsimplycouldnotfindthefileitself. else { MessageBox(hwnd,psFilename,L"MissingShaderFile",MB_OK); } returnfalse; } //Createthevertexshaderfromthebuffer. result=device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(),vertexShaderBuffer->GetBufferSize(),NULL,&m_vertexShader); if(FAILED(result)) { returnfalse; } //Createthepixelshaderfromthebuffer. result=device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(),pixelShaderBuffer->GetBufferSize(),NULL,&m_pixelShader); if(FAILED(result)) { returnfalse; } //Createthevertexinputlayoutdescription. polygonLayout[0].SemanticName="POSITION"; polygonLayout[0].SemanticIndex=0; polygonLayout[0].Format=DXGI_FORMAT_R32G32B32_FLOAT; polygonLayout[0].InputSlot=0; polygonLayout[0].AlignedByteOffset=0; polygonLayout[0].InputSlotClass=D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[0].InstanceDataStepRate=0; polygonLayout[1].SemanticName="TEXCOORD"; polygonLayout[1].SemanticIndex=0; polygonLayout[1].Format=DXGI_FORMAT_R32G32_FLOAT; polygonLayout[1].InputSlot=0; polygonLayout[1].AlignedByteOffset=D3D11_APPEND_ALIGNED_ELEMENT; polygonLayout[1].InputSlotClass=D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[1].InstanceDataStepRate=0; polygonLayout[2].SemanticName="NORMAL"; polygonLayout[2].SemanticIndex=0; polygonLayout[2].Format=DXGI_FORMAT_R32G32B32_FLOAT; polygonLayout[2].InputSlot=0; polygonLayout[2].AlignedByteOffset=D3D11_APPEND_ALIGNED_ELEMENT; polygonLayout[2].InputSlotClass=D3D11_INPUT_PER_VERTEX_DATA; polygonLayout[2].InstanceDataStepRate=0; //Getacountoftheelementsinthelayout. numElements=sizeof(polygonLayout)/sizeof(polygonLayout[0]); //Createthevertexinputlayout. result=device->CreateInputLayout(polygonLayout,numElements,vertexShaderBuffer->GetBufferPointer(),vertexShaderBuffer->GetBufferSize(), &m_layout); if(FAILED(result)) { returnfalse; } //Releasethevertexshaderbufferandpixelshaderbuffersincetheyarenolongerneeded. vertexShaderBuffer->Release(); vertexShaderBuffer=0; pixelShaderBuffer->Release(); pixelShaderBuffer=0; //Createawraptexturesamplerstatedescription. samplerDesc.Filter=D3D11_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.AddressU=D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.AddressV=D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.AddressW=D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.MipLODBias=0.0f; samplerDesc.MaxAnisotropy=1; samplerDesc.ComparisonFunc=D3D11_COMPARISON_ALWAYS; samplerDesc.BorderColor[0]=0; samplerDesc.BorderColor[1]=0; samplerDesc.BorderColor[2]=0; samplerDesc.BorderColor[3]=0; samplerDesc.MinLOD=0; samplerDesc.MaxLOD=D3D11_FLOAT32_MAX; //Createthetexturesamplerstate. result=device->CreateSamplerState(&samplerDesc,&m_sampleStateWrap); if(FAILED(result)) { returnfalse; } //Createaclamptexturesamplerstatedescription. samplerDesc.AddressU=D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressV=D3D11_TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressW=D3D11_TEXTURE_ADDRESS_CLAMP; //Createthetexturesamplerstate. result=device->CreateSamplerState(&samplerDesc,&m_sampleStateClamp); if(FAILED(result)) { returnfalse; } //Setupthedescriptionofthedynamicmatrixconstantbufferthatisinthevertexshader. matrixBufferDesc.Usage=D3D11_USAGE_DYNAMIC; matrixBufferDesc.ByteWidth=sizeof(MatrixBufferType); matrixBufferDesc.BindFlags=D3D11_BIND_CONSTANT_BUFFER; matrixBufferDesc.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE; matrixBufferDesc.MiscFlags=0; matrixBufferDesc.StructureByteStride=0; //Createtheconstantbufferpointersowecanaccessthevertexshaderconstantbufferfromwithinthisclass. result=device->CreateBuffer(&matrixBufferDesc,NULL,&m_matrixBuffer); if(FAILED(result)) { returnfalse; } //Setupthedescriptionofthelightdynamicconstantbufferthatisinthepixelshader. lightBufferDesc.Usage=D3D11_USAGE_DYNAMIC; lightBufferDesc.ByteWidth=sizeof(LightBufferType); lightBufferDesc.BindFlags=D3D11_BIND_CONSTANT_BUFFER; lightBufferDesc.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE; lightBufferDesc.MiscFlags=0; lightBufferDesc.StructureByteStride=0; //Createtheconstantbufferpointersowecanaccessthepixelshaderconstantbufferfromwithinthisclass. result=device->CreateBuffer(&lightBufferDesc,NULL,&m_lightBuffer); if(FAILED(result)) { returnfalse; } //Setupthedescriptionofthelightdynamicconstantbufferthatisinthevertexshader. lightBufferDesc2.Usage=D3D11_USAGE_DYNAMIC; lightBufferDesc2.ByteWidth=sizeof(LightBufferType2); lightBufferDesc2.BindFlags=D3D11_BIND_CONSTANT_BUFFER; lightBufferDesc2.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE; lightBufferDesc2.MiscFlags=0; lightBufferDesc2.StructureByteStride=0; //Createtheconstantbufferpointersowecanaccessthevertexshaderconstantbufferfromwithinthisclass. result=device->CreateBuffer(&lightBufferDesc2,NULL,&m_lightBuffer2); if(FAILED(result)) { returnfalse; } returntrue; } voidSoftShadowShaderClass::ShutdownShader() { //Releasethelightconstantbuffers. if(m_lightBuffer) { m_lightBuffer->Release(); m_lightBuffer=0; } if(m_lightBuffer2) { m_lightBuffer2->Release(); m_lightBuffer2=0; } //Releasethematrixconstantbuffer. if(m_matrixBuffer) { m_matrixBuffer->Release(); m_matrixBuffer=0; } //Releasethesamplerstates. if(m_sampleStateWrap) { m_sampleStateWrap->Release(); m_sampleStateWrap=0; } if(m_sampleStateClamp) { m_sampleStateClamp->Release(); m_sampleStateClamp=0; } //Releasethelayout. if(m_layout) { m_layout->Release(); m_layout=0; } //Releasethepixelshader. if(m_pixelShader) { m_pixelShader->Release(); m_pixelShader=0; } //Releasethevertexshader. if(m_vertexShader) { m_vertexShader->Release(); m_vertexShader=0; } return; } voidSoftShadowShaderClass::OutputShaderErrorMessage(ID3D10Blob*errorMessage,HWNDhwnd,WCHAR*shaderFilename) { char*compileErrors; unsignedlongbufferSize,i; ofstreamfout; //Getapointertotheerrormessagetextbuffer. compileErrors=(char*)(errorMessage->GetBufferPointer()); //Getthelengthofthemessage. bufferSize=errorMessage->GetBufferSize(); //Openafiletowritetheerrormessageto. fout.open("shader-error.txt"); //Writeouttheerrormessage. for(i=0;iRelease(); errorMessage=0; //Popamessageuponthescreentonotifytheusertocheckthetextfileforcompileerrors. MessageBox(hwnd,L"Errorcompilingshader.Checkshader-error.txtformessage.",shaderFilename,MB_OK); return; } boolSoftShadowShaderClass::SetShaderParameters(ID3D11DeviceContext*deviceContext,D3DXMATRIXworldMatrix,D3DXMATRIXviewMatrix, D3DXMATRIXprojectionMatrix,ID3D11ShaderResourceView*texture,ID3D11ShaderResourceView*shadowTexture, D3DXVECTOR3lightPosition,D3DXVECTOR4ambientColor,D3DXVECTOR4diffuseColor) { HRESULTresult; D3D11_MAPPED_SUBRESOURCEmappedResource; unsignedintbufferNumber; MatrixBufferType*dataPtr; LightBufferType*dataPtr2; LightBufferType2*dataPtr3; //Transposethematricestopreparethemfortheshader. D3DXMatrixTranspose(&worldMatrix,&worldMatrix); D3DXMatrixTranspose(&viewMatrix,&viewMatrix); D3DXMatrixTranspose(&projectionMatrix,&projectionMatrix); //Locktheconstantbuffersoitcanbewrittento. result=deviceContext->Map(m_matrixBuffer,0,D3D11_MAP_WRITE_DISCARD,0,&mappedResource); if(FAILED(result)) { returnfalse; } //Getapointertothedataintheconstantbuffer. dataPtr=(MatrixBufferType*)mappedResource.pData; //Copythematricesintotheconstantbuffer. dataPtr->world=worldMatrix; dataPtr->view=viewMatrix; dataPtr->projection=projectionMatrix; //Unlocktheconstantbuffer. deviceContext->Unmap(m_matrixBuffer,0); //Setthepositionoftheconstantbufferinthevertexshader. bufferNumber=0; //Nowsettheconstantbufferinthevertexshaderwiththeupdatedvalues. deviceContext->VSSetConstantBuffers(bufferNumber,1,&m_matrixBuffer); //Setshadertextureresourceinthepixelshader. deviceContext->PSSetShaderResources(0,1,&texture); Bindtheblurredblackandwhitesoftshadowtexturehere. deviceContext->PSSetShaderResources(1,1,&shadowTexture); //Lockthelightconstantbuffersoitcanbewrittento. result=deviceContext->Map(m_lightBuffer,0,D3D11_MAP_WRITE_DISCARD,0,&mappedResource); if(FAILED(result)) { returnfalse; } //Getapointertothedataintheconstantbuffer. dataPtr2=(LightBufferType*)mappedResource.pData; //Copythelightingvariablesintotheconstantbuffer. dataPtr2->ambientColor=ambientColor; dataPtr2->diffuseColor=diffuseColor; //Unlocktheconstantbuffer. deviceContext->Unmap(m_lightBuffer,0); //Setthepositionofthelightconstantbufferinthepixelshader. bufferNumber=0; //Finallysetthelightconstantbufferinthepixelshaderwiththeupdatedvalues. deviceContext->PSSetConstantBuffers(bufferNumber,1,&m_lightBuffer); //Lockthesecondlightconstantbuffersoitcanbewrittento. result=deviceContext->Map(m_lightBuffer2,0,D3D11_MAP_WRITE_DISCARD,0,&mappedResource); if(FAILED(result)) { returnfalse; } //Getapointertothedataintheconstantbuffer. dataPtr3=(LightBufferType2*)mappedResource.pData; //Copythelightingvariablesintotheconstantbuffer. dataPtr3->lightPosition=lightPosition; dataPtr3->padding=0.0f; //Unlocktheconstantbuffer. deviceContext->Unmap(m_lightBuffer2,0); //Setthepositionofthelightconstantbufferinthevertexshader. bufferNumber=1; //Finallysetthelightconstantbufferinthepixelshaderwiththeupdatedvalues. deviceContext->VSSetConstantBuffers(bufferNumber,1,&m_lightBuffer2); returntrue; } voidSoftShadowShaderClass::RenderShader(ID3D11DeviceContext*deviceContext,intindexCount) { //Setthevertexinputlayout. deviceContext->IASetInputLayout(m_layout); //Setthevertexandpixelshadersthatwillbeusedtorenderthistriangle. deviceContext->VSSetShader(m_vertexShader,NULL,0); deviceContext->PSSetShader(m_pixelShader,NULL,0); //Setthesamplerstatesinthepixelshader. deviceContext->PSSetSamplers(0,1,&m_sampleStateClamp); deviceContext->PSSetSamplers(1,1,&m_sampleStateWrap); //Renderthetriangle. deviceContext->DrawIndexed(indexCount,0,0); return; } Graphicsclass.h TheGraphicsClasswillrequireanumberofobjectssinceweareperformingablurandseparatingthealgorithmintoindividualstepsforclaritypurposes. Thisisnotthemostefficientwaytoperformsoftshadowingbutforthepurposesofthetutorialitmakesiteasiertodebugandlearnthedifferentstepsinvolved. Youcanalsorefertotutorial36asthisisprettymuchacopyofthattutorialwithshadowingadded. //////////////////////////////////////////////////////////////////////////////// //Filename:graphicsclass.h //////////////////////////////////////////////////////////////////////////////// #ifndef_GRAPHICSCLASS_H_ #define_GRAPHICSCLASS_H_ /////////////////////// //MYCLASSINCLUDES// /////////////////////// #include"d3dclass.h" #include"cameraclass.h" #include"modelclass.h" #include"lightclass.h" #include"rendertextureclass.h" #include"depthshaderclass.h" #include"shadowshaderclass.h" Addthenewheadersrequiredforblurringandsoftshadowing. #include"orthowindowclass.h" #include"textureshaderclass.h" #include"horizontalblurshaderclass.h" #include"verticalblurshaderclass.h" #include"softshadowshaderclass.h" ///////////// //GLOBALS// ///////////// constboolFULL_SCREEN=true; constboolVSYNC_ENABLED=true; constfloatSCREEN_DEPTH=100.0f; constfloatSCREEN_NEAR=1.0f; constintSHADOWMAP_WIDTH=1024; constintSHADOWMAP_HEIGHT=1024; //////////////////////////////////////////////////////////////////////////////// //Classname:GraphicsClass //////////////////////////////////////////////////////////////////////////////// classGraphicsClass { public: GraphicsClass(); GraphicsClass(constGraphicsClass&); ~GraphicsClass(); boolInitialize(int,int,HWND); voidShutdown(); boolFrame(float,float,float,float,float,float); private: boolRenderSceneToTexture(); boolRenderBlackAndWhiteShadows(); boolDownSampleTexture(); boolRenderHorizontalBlurToTexture(); boolRenderVerticalBlurToTexture(); boolUpSampleTexture(); boolRender(); private: D3DClass*m_D3D; CameraClass*m_Camera; ModelClass*m_CubeModel,*m_GroundModel,*m_SphereModel; LightClass*m_Light; RenderTextureClass*m_RenderTexture,*m_BlackWhiteRenderTexture,*m_DownSampleTexure; RenderTextureClass*m_HorizontalBlurTexture,*m_VerticalBlurTexture,*m_UpSampleTexure; DepthShaderClass*m_DepthShader; ShadowShaderClass*m_ShadowShader; OrthoWindowClass*m_SmallWindow,*m_FullScreenWindow; TextureShaderClass*m_TextureShader; HorizontalBlurShaderClass*m_HorizontalBlurShader; VerticalBlurShaderClass*m_VerticalBlurShader; SoftShadowShaderClass*m_SoftShadowShader; }; #endif Graphicsclass.cpp //////////////////////////////////////////////////////////////////////////////// //Filename:graphicsclass.cpp //////////////////////////////////////////////////////////////////////////////// #include"graphicsclass.h" GraphicsClass::GraphicsClass() { m_D3D=0; m_Camera=0; m_CubeModel=0; m_GroundModel=0; m_SphereModel=0; m_Light=0; m_RenderTexture=0; m_DepthShader=0; m_BlackWhiteRenderTexture=0; m_ShadowShader=0; m_DownSampleTexure=0; m_SmallWindow=0; m_TextureShader=0; m_HorizontalBlurTexture=0; m_HorizontalBlurShader=0; m_VerticalBlurTexture=0; m_VerticalBlurShader=0; m_UpSampleTexure=0; m_FullScreenWindow=0; m_SoftShadowShader=0; } GraphicsClass::GraphicsClass(constGraphicsClass&other) { } GraphicsClass::~GraphicsClass() { } boolGraphicsClass::Initialize(intscreenWidth,intscreenHeight,HWNDhwnd) { boolresult; intdownSampleWidth,downSampleHeight; //CreatetheDirect3Dobject. m_D3D=newD3DClass; if(!m_D3D) { returnfalse; } //InitializetheDirect3Dobject. result=m_D3D->Initialize(screenWidth,screenHeight,VSYNC_ENABLED,hwnd,FULL_SCREEN,SCREEN_DEPTH,SCREEN_NEAR); if(!result) { MessageBox(hwnd,L"CouldnotinitializeDirect3D.",L"Error",MB_OK); returnfalse; } //Createthecameraobject. m_Camera=newCameraClass; if(!m_Camera) { returnfalse; } //Settheinitialpositionofthecamera. m_Camera->SetPosition(0.0f,0.0f,-10.0f); m_Camera->RenderBaseViewMatrix(); //Createthecubemodelobject. m_CubeModel=newModelClass; if(!m_CubeModel) { returnfalse; } //Initializethecubemodelobject. result=m_CubeModel->Initialize(m_D3D->GetDevice(),"../Engine/data/cube.txt",L"../Engine/data/wall01.dds"); if(!result) { MessageBox(hwnd,L"Couldnotinitializethecubemodelobject.",L"Error",MB_OK); returnfalse; } //Setthepositionforthecubemodel. m_CubeModel->SetPosition(-2.0f,2.0f,0.0f); //Createthespheremodelobject. m_SphereModel=newModelClass; if(!m_SphereModel) { returnfalse; } //Initializethespheremodelobject. result=m_SphereModel->Initialize(m_D3D->GetDevice(),"../Engine/data/sphere.txt",L"../Engine/data/ice.dds"); if(!result) { MessageBox(hwnd,L"Couldnotinitializethespheremodelobject.",L"Error",MB_OK); returnfalse; } //Setthepositionforthespheremodel. m_SphereModel->SetPosition(2.0f,2.0f,0.0f); //Createthegroundmodelobject. m_GroundModel=newModelClass; if(!m_GroundModel) { returnfalse; } //Initializethegroundmodelobject. result=m_GroundModel->Initialize(m_D3D->GetDevice(),"../Engine/data/plane01.txt",L"../Engine/data/metal001.dds"); if(!result) { MessageBox(hwnd,L"Couldnotinitializethegroundmodelobject.",L"Error",MB_OK); returnfalse; } //Setthepositionforthegroundmodel. m_GroundModel->SetPosition(0.0f,1.0f,0.0f); //Createthelightobject. m_Light=newLightClass; if(!m_Light) { returnfalse; } //Initializethelightobject. m_Light->SetAmbientColor(0.15f,0.15f,0.15f,1.0f); m_Light->SetDiffuseColor(1.0f,1.0f,1.0f,1.0f); m_Light->SetLookAt(0.0f,0.0f,0.0f); m_Light->GenerateProjectionMatrix(SCREEN_DEPTH,SCREEN_NEAR); //Createtherendertotextureobject. m_RenderTexture=newRenderTextureClass; if(!m_RenderTexture) { returnfalse; } //Initializetherendertotextureobject. result=m_RenderTexture->Initialize(m_D3D->GetDevice(),SHADOWMAP_WIDTH,SHADOWMAP_HEIGHT,SCREEN_DEPTH,SCREEN_NEAR); if(!result) { MessageBox(hwnd,L"Couldnotinitializetherendertotextureobject.",L"Error",MB_OK); returnfalse; } //Createthedepthshaderobject. m_DepthShader=newDepthShaderClass; if(!m_DepthShader) { returnfalse; } //Initializethedepthshaderobject. result=m_DepthShader->Initialize(m_D3D->GetDevice(),hwnd); if(!result) { MessageBox(hwnd,L"Couldnotinitializethedepthshaderobject.",L"Error",MB_OK); returnfalse; } //Createtherendertotextureobject. m_BlackWhiteRenderTexture=newRenderTextureClass; if(!m_BlackWhiteRenderTexture) { returnfalse; } //Initializetheblackandwhiterendertotextureobject. result=m_BlackWhiteRenderTexture->Initialize(m_D3D->GetDevice(),SHADOWMAP_WIDTH,SHADOWMAP_HEIGHT,SCREEN_DEPTH,SCREEN_NEAR); if(!result) { MessageBox(hwnd,L"Couldnotinitializetheblackandwhiterendertotextureobject.",L"Error",MB_OK); returnfalse; } //Createtheshadowshaderobject. m_ShadowShader=newShadowShaderClass; if(!m_ShadowShader) { returnfalse; } //Initializetheshadowshaderobject. result=m_ShadowShader->Initialize(m_D3D->GetDevice(),hwnd); if(!result) { MessageBox(hwnd,L"Couldnotinitializetheshadowshaderobject.",L"Error",MB_OK); returnfalse; } //Setthesizetosampledownto. downSampleWidth=SHADOWMAP_WIDTH/2; downSampleHeight=SHADOWMAP_HEIGHT/2; //Createthedownsamplerendertotextureobject. m_DownSampleTexure=newRenderTextureClass; if(!m_DownSampleTexure) { returnfalse; } //Initializethedownsamplerendertotextureobject. result=m_DownSampleTexure->Initialize(m_D3D->GetDevice(),downSampleWidth,downSampleHeight,100.0f,1.0f); if(!result) { MessageBox(hwnd,L"Couldnotinitializethedownsamplerendertotextureobject.",L"Error",MB_OK); returnfalse; } //Createthesmallorthowindowobject. m_SmallWindow=newOrthoWindowClass; if(!m_SmallWindow) { returnfalse; } //Initializethesmallorthowindowobject. result=m_SmallWindow->Initialize(m_D3D->GetDevice(),downSampleWidth,downSampleHeight); if(!result) { MessageBox(hwnd,L"Couldnotinitializethesmallorthowindowobject.",L"Error",MB_OK); returnfalse; } //Createthetextureshaderobject. m_TextureShader=newTextureShaderClass; if(!m_TextureShader) { returnfalse; } //Initializethetextureshaderobject. result=m_TextureShader->Initialize(m_D3D->GetDevice(),hwnd); if(!result) { MessageBox(hwnd,L"Couldnotinitializethetextureshaderobject.",L"Error",MB_OK); returnfalse; } //Createthehorizontalblurrendertotextureobject. m_HorizontalBlurTexture=newRenderTextureClass; if(!m_HorizontalBlurTexture) { returnfalse; } //Initializethehorizontalblurrendertotextureobject. result=m_HorizontalBlurTexture->Initialize(m_D3D->GetDevice(),downSampleWidth,downSampleHeight,SCREEN_DEPTH,0.1f); if(!result) { MessageBox(hwnd,L"Couldnotinitializethehorizontalblurrendertotextureobject.",L"Error",MB_OK); returnfalse; } //Createthehorizontalblurshaderobject. m_HorizontalBlurShader=newHorizontalBlurShaderClass; if(!m_HorizontalBlurShader) { returnfalse; } //Initializethehorizontalblurshaderobject. result=m_HorizontalBlurShader->Initialize(m_D3D->GetDevice(),hwnd); if(!result) { MessageBox(hwnd,L"Couldnotinitializethehorizontalblurshaderobject.",L"Error",MB_OK); returnfalse; } //Createtheverticalblurrendertotextureobject. m_VerticalBlurTexture=newRenderTextureClass; if(!m_VerticalBlurTexture) { returnfalse; } //Initializetheverticalblurrendertotextureobject. result=m_VerticalBlurTexture->Initialize(m_D3D->GetDevice(),downSampleWidth,downSampleHeight,SCREEN_DEPTH,0.1f); if(!result) { MessageBox(hwnd,L"Couldnotinitializetheverticalblurrendertotextureobject.",L"Error",MB_OK); returnfalse; } //Createtheverticalblurshaderobject. m_VerticalBlurShader=newVerticalBlurShaderClass; if(!m_VerticalBlurShader) { returnfalse; } //Initializetheverticalblurshaderobject. result=m_VerticalBlurShader->Initialize(m_D3D->GetDevice(),hwnd); if(!result) { MessageBox(hwnd,L"Couldnotinitializetheverticalblurshaderobject.",L"Error",MB_OK); returnfalse; } //Createtheupsamplerendertotextureobject. m_UpSampleTexure=newRenderTextureClass; if(!m_UpSampleTexure) { returnfalse; } //Initializetheupsamplerendertotextureobject. result=m_UpSampleTexure->Initialize(m_D3D->GetDevice(),SHADOWMAP_WIDTH,SHADOWMAP_HEIGHT,SCREEN_DEPTH,0.1f); if(!result) { MessageBox(hwnd,L"Couldnotinitializetheupsamplerendertotextureobject.",L"Error",MB_OK); returnfalse; } //Createthefullscreenorthowindowobject. m_FullScreenWindow=newOrthoWindowClass; if(!m_FullScreenWindow) { returnfalse; } //Initializethefullscreenorthowindowobject. result=m_FullScreenWindow->Initialize(m_D3D->GetDevice(),SHADOWMAP_WIDTH,SHADOWMAP_HEIGHT); if(!result) { MessageBox(hwnd,L"Couldnotinitializethefullscreenorthowindowobject.",L"Error",MB_OK); returnfalse; } //Createthesoftshadowshaderobject. m_SoftShadowShader=newSoftShadowShaderClass; if(!m_SoftShadowShader) { returnfalse; } //Initializethesoftshadowshaderobject. result=m_SoftShadowShader->Initialize(m_D3D->GetDevice(),hwnd); if(!result) { MessageBox(hwnd,L"Couldnotinitializethesoftshadowshaderobject.",L"Error",MB_OK); returnfalse; } returntrue; } voidGraphicsClass::Shutdown() { //Releasethesoftshadowshaderobject. if(m_SoftShadowShader) { m_SoftShadowShader->Shutdown(); deletem_SoftShadowShader; m_SoftShadowShader=0; } //Releasethefullscreenorthowindowobject. if(m_FullScreenWindow) { m_FullScreenWindow->Shutdown(); deletem_FullScreenWindow; m_FullScreenWindow=0; } //Releasetheupsamplerendertotextureobject. if(m_UpSampleTexure) { m_UpSampleTexure->Shutdown(); deletem_UpSampleTexure; m_UpSampleTexure=0; } //Releasetheverticalblurshaderobject. if(m_VerticalBlurShader) { m_VerticalBlurShader->Shutdown(); deletem_VerticalBlurShader; m_VerticalBlurShader=0; } //Releasetheverticalblurrendertotextureobject. if(m_VerticalBlurTexture) { m_VerticalBlurTexture->Shutdown(); deletem_VerticalBlurTexture; m_VerticalBlurTexture=0; } //Releasethehorizontalblurshaderobject. if(m_HorizontalBlurShader) { m_HorizontalBlurShader->Shutdown(); deletem_HorizontalBlurShader; m_HorizontalBlurShader=0; } //Releasethehorizontalblurrendertotextureobject. if(m_HorizontalBlurTexture) { m_HorizontalBlurTexture->Shutdown(); deletem_HorizontalBlurTexture; m_HorizontalBlurTexture=0; } //Releasethetextureshaderobject. if(m_TextureShader) { m_TextureShader->Shutdown(); deletem_TextureShader; m_TextureShader=0; } //Releasethesmallorthowindowobject. if(m_SmallWindow) { m_SmallWindow->Shutdown(); deletem_SmallWindow; m_SmallWindow=0; } //Releasethedownsamplerendertotextureobject. if(m_DownSampleTexure) { m_DownSampleTexure->Shutdown(); deletem_DownSampleTexure; m_DownSampleTexure=0; } //Releasetheshadowshaderobject. if(m_ShadowShader) { m_ShadowShader->Shutdown(); deletem_ShadowShader; m_ShadowShader=0; } //Releasetheblackandwhiterendertotexture. if(m_BlackWhiteRenderTexture) { m_BlackWhiteRenderTexture->Shutdown(); deletem_BlackWhiteRenderTexture; m_BlackWhiteRenderTexture=0; } //Releasethedepthshaderobject. if(m_DepthShader) { m_DepthShader->Shutdown(); deletem_DepthShader; m_DepthShader=0; } //Releasetherendertotextureobject. if(m_RenderTexture) { m_RenderTexture->Shutdown(); deletem_RenderTexture; m_RenderTexture=0; } //Releasethelightobject. if(m_Light) { deletem_Light; m_Light=0; } //Releasethegroundmodelobject. if(m_GroundModel) { m_GroundModel->Shutdown(); deletem_GroundModel; m_GroundModel=0; } //Releasethespheremodelobject. if(m_SphereModel) { m_SphereModel->Shutdown(); deletem_SphereModel; m_SphereModel=0; } //Releasethecubemodelobject. if(m_CubeModel) { m_CubeModel->Shutdown(); deletem_CubeModel; m_CubeModel=0; } //Releasethecameraobject. if(m_Camera) { deletem_Camera; m_Camera=0; } //ReleasetheD3Dobject. if(m_D3D) { m_D3D->Shutdown(); deletem_D3D; m_D3D=0; } return; } boolGraphicsClass::Frame(floatposX,floatposY,floatposZ,floatrotX,floatrotY,floatrotZ) { boolresult; staticfloatlightPositionX=-5.0f; //Setthepositionofthecamera. m_Camera->SetPosition(posX,posY,posZ); m_Camera->SetRotation(rotX,rotY,rotZ); //Updatethepositionofthelighteachframe. lightPositionX+=0.05f; if(lightPositionX>5.0f) { lightPositionX=-5.0f; } //Updatethepositionofthelight. m_Light->SetPosition(lightPositionX,8.0f,-5.0f); //Renderthegraphicsscene. result=Render(); if(!result) { returnfalse; } returntrue; } Thisfunctioniswherewerenderthescenetotexturetoperformthebasicshadowing. boolGraphicsClass::RenderSceneToTexture() { D3DXMATRIXworldMatrix,lightViewMatrix,lightProjectionMatrix,translateMatrix; floatposX,posY,posZ; boolresult; //Settherendertargettobetherendertotexture. m_RenderTexture->SetRenderTarget(m_D3D->GetDeviceContext()); //Cleartherendertotexture. m_RenderTexture->ClearRenderTarget(m_D3D->GetDeviceContext(),0.0f,0.0f,0.0f,1.0f); //Generatethelightviewmatrixbasedonthelight'sposition. m_Light->GenerateViewMatrix(); //Gettheworldmatrixfromthed3dobject. m_D3D->GetWorldMatrix(worldMatrix); //Gettheviewandorthographicmatricesfromthelightobject. m_Light->GetViewMatrix(lightViewMatrix); m_Light->GetProjectionMatrix(lightProjectionMatrix); //Setupthetranslationmatrixforthecubemodel. m_CubeModel->GetPosition(posX,posY,posZ); D3DXMatrixTranslation(&worldMatrix,posX,posY,posZ); //Renderthecubemodelwiththedepthshader. m_CubeModel->Render(m_D3D->GetDeviceContext()); result=m_DepthShader->Render(m_D3D->GetDeviceContext(),m_CubeModel->GetIndexCount(),worldMatrix,lightViewMatrix,lightProjectionMatrix); if(!result) { returnfalse; } //Resettheworldmatrix. m_D3D->GetWorldMatrix(worldMatrix); //Setupthetranslationmatrixforthespheremodel. m_SphereModel->GetPosition(posX,posY,posZ); D3DXMatrixTranslation(&worldMatrix,posX,posY,posZ); //Renderthespheremodelwiththedepthshader. m_SphereModel->Render(m_D3D->GetDeviceContext()); result=m_DepthShader->Render(m_D3D->GetDeviceContext(),m_SphereModel->GetIndexCount(),worldMatrix,lightViewMatrix,lightProjectionMatrix); if(!result) { returnfalse; } //Resettheworldmatrix. m_D3D->GetWorldMatrix(worldMatrix); //Setupthetranslationmatrixforthegroundmodel. m_GroundModel->GetPosition(posX,posY,posZ); D3DXMatrixTranslation(&worldMatrix,posX,posY,posZ); //Renderthegroundmodelwiththedepthshader. m_GroundModel->Render(m_D3D->GetDeviceContext()); result=m_DepthShader->Render(m_D3D->GetDeviceContext(),m_GroundModel->GetIndexCount(),worldMatrix,lightViewMatrix,lightProjectionMatrix); if(!result) { returnfalse; } //Resettherendertargetbacktotheoriginalbackbufferandnottherendertotextureanymore. m_D3D->SetBackBufferRenderTarget(); //Resettheviewportbacktotheoriginal. m_D3D->ResetViewport(); returntrue; } Thisnextfunctioniswherewerendertheshadowsbutasablackandwhiteonlyimagetoanotherrendertotexture. boolGraphicsClass::RenderBlackAndWhiteShadows() { D3DXMATRIXworldMatrix,viewMatrix,projectionMatrix,translateMatrix; D3DXMATRIXlightViewMatrix,lightProjectionMatrix; floatposX,posY,posZ; boolresult; //Settherendertargettobetherendertotexture. m_BlackWhiteRenderTexture->SetRenderTarget(m_D3D->GetDeviceContext()); //Cleartherendertotexture. m_BlackWhiteRenderTexture->ClearRenderTarget(m_D3D->GetDeviceContext(),0.0f,0.0f,0.0f,1.0f); //Generatetheviewmatrixbasedonthecamera'sposition. m_Camera->Render(); //Generatethelightviewmatrixbasedonthelight'sposition. m_Light->GenerateViewMatrix(); //Gettheworld,view,andprojectionmatricesfromthecameraandd3dobjects. m_Camera->GetViewMatrix(viewMatrix); m_D3D->GetWorldMatrix(worldMatrix); m_D3D->GetProjectionMatrix(projectionMatrix); //Getthelight'sviewandprojectionmatricesfromthelightobject. m_Light->GetViewMatrix(lightViewMatrix); m_Light->GetProjectionMatrix(lightProjectionMatrix); //Setupthetranslationmatrixforthecubemodel. m_CubeModel->GetPosition(posX,posY,posZ); D3DXMatrixTranslation(&worldMatrix,posX,posY,posZ); //Renderthecubemodelusingtheshadowshader. m_CubeModel->Render(m_D3D->GetDeviceContext()); result=m_ShadowShader->Render(m_D3D->GetDeviceContext(),m_CubeModel->GetIndexCount(),worldMatrix,viewMatrix,projectionMatrix,lightViewMatrix, lightProjectionMatrix,m_RenderTexture->GetShaderResourceView(),m_Light->GetPosition()); if(!result) { returnfalse; } //Resettheworldmatrix. m_D3D->GetWorldMatrix(worldMatrix); //Setupthetranslationmatrixforthespheremodel. m_SphereModel->GetPosition(posX,posY,posZ); D3DXMatrixTranslation(&worldMatrix,posX,posY,posZ); //Renderthespheremodelusingtheshadowshader. m_SphereModel->Render(m_D3D->GetDeviceContext()); result=m_ShadowShader->Render(m_D3D->GetDeviceContext(),m_SphereModel->GetIndexCount(),worldMatrix,viewMatrix,projectionMatrix,lightViewMatrix, lightProjectionMatrix,m_RenderTexture->GetShaderResourceView(),m_Light->GetPosition()); if(!result) { returnfalse; } //Resettheworldmatrix. m_D3D->GetWorldMatrix(worldMatrix); //Setupthetranslationmatrixforthegroundmodel. m_GroundModel->GetPosition(posX,posY,posZ); D3DXMatrixTranslation(&worldMatrix,posX,posY,posZ); //Renderthegroundmodelusingtheshadowshader. m_GroundModel->Render(m_D3D->GetDeviceContext()); result=m_ShadowShader->Render(m_D3D->GetDeviceContext(),m_GroundModel->GetIndexCount(),worldMatrix,viewMatrix,projectionMatrix,lightViewMatrix, lightProjectionMatrix,m_RenderTexture->GetShaderResourceView(),m_Light->GetPosition()); if(!result) { returnfalse; } //Resettherendertargetbacktotheoriginalbackbufferandnottherendertotextureanymore. m_D3D->SetBackBufferRenderTarget(); //Resettheviewportbacktotheoriginal. m_D3D->ResetViewport(); returntrue; } Thisfunctioniswherewedownsampletheblackandwhiteshadowimagetobegintheblurprocess. boolGraphicsClass::DownSampleTexture() { D3DXMATRIXworldMatrix,baseViewMatrix,orthoMatrix; boolresult; //Settherendertargettobetherendertotexture. m_DownSampleTexure->SetRenderTarget(m_D3D->GetDeviceContext()); //Cleartherendertotexture. m_DownSampleTexure->ClearRenderTarget(m_D3D->GetDeviceContext(),0.0f,0.0f,0.0f,1.0f); //Generatetheviewmatrixbasedonthecamera'sposition. m_Camera->Render(); //Gettheworldandviewmatricesfromthecameraandd3dobjects. m_D3D->GetWorldMatrix(worldMatrix); m_Camera->GetBaseViewMatrix(baseViewMatrix); //Gettheorthomatrixfromtherendertotexturesincetexturehasdifferentdimensionsbeingthatitissmaller. m_DownSampleTexure->GetOrthoMatrix(orthoMatrix); //TurnofftheZbuffertobeginall2Drendering. m_D3D->TurnZBufferOff(); //Putthesmallorthowindowvertexandindexbuffersonthegraphicspipelinetopreparethemfordrawing. m_SmallWindow->Render(m_D3D->GetDeviceContext()); //Renderthesmallorthowindowusingthetextureshaderandtherendertotextureofthesceneasthetextureresource. result=m_TextureShader->Render(m_D3D->GetDeviceContext(),m_SmallWindow->GetIndexCount(),worldMatrix,baseViewMatrix,orthoMatrix, m_BlackWhiteRenderTexture->GetShaderResourceView()); if(!result) { returnfalse; } //TurntheZbufferbackonnowthatall2Drenderinghascompleted. m_D3D->TurnZBufferOn(); //Resettherendertargetbacktotheoriginalbackbufferandnottherendertotextureanymore. m_D3D->SetBackBufferRenderTarget(); //Resettheviewportbacktotheoriginal. m_D3D->ResetViewport(); returntrue; } Thisfunctioniswhereperformthehorizontalbluronthedownsampledblackandwhiteshadowimage. boolGraphicsClass::RenderHorizontalBlurToTexture() { D3DXMATRIXworldMatrix,baseViewMatrix,orthoMatrix; floatscreenSizeX; boolresult; //Storethescreenwidthinafloatthatwillbeusedinthehorizontalblurshader. screenSizeX=(float)(SHADOWMAP_WIDTH/2); //Settherendertargettobetherendertotexture. m_HorizontalBlurTexture->SetRenderTarget(m_D3D->GetDeviceContext()); //Cleartherendertotexture. m_HorizontalBlurTexture->ClearRenderTarget(m_D3D->GetDeviceContext(),0.0f,0.0f,0.0f,1.0f); //Generatetheviewmatrixbasedonthecamera'sposition. m_Camera->Render(); //Gettheworldandviewmatricesfromthecameraandd3dobjects. m_Camera->GetBaseViewMatrix(baseViewMatrix); m_D3D->GetWorldMatrix(worldMatrix); //Gettheorthomatrixfromtherendertotexturesincetexturehasdifferentdimensions. m_HorizontalBlurTexture->GetOrthoMatrix(orthoMatrix); //TurnofftheZbuffertobeginall2Drendering. m_D3D->TurnZBufferOff(); //Putthesmallorthowindowvertexandindexbuffersonthegraphicspipelinetopreparethemfordrawing. m_SmallWindow->Render(m_D3D->GetDeviceContext()); //Renderthesmallorthowindowusingthehorizontalblurshaderandthedownsampledrendertotextureresource. result=m_HorizontalBlurShader->Render(m_D3D->GetDeviceContext(),m_SmallWindow->GetIndexCount(),worldMatrix,baseViewMatrix,orthoMatrix, m_DownSampleTexure->GetShaderResourceView(),screenSizeX); if(!result) { returnfalse; } //TurntheZbufferbackonnowthatall2Drenderinghascompleted. m_D3D->TurnZBufferOn(); //Resettherendertargetbacktotheoriginalbackbufferandnottherendertotextureanymore. m_D3D->SetBackBufferRenderTarget(); //Resettheviewportbacktotheoriginal. m_D3D->ResetViewport(); returntrue; } Thisfunctioniswhereperformtheverticalbluronthehorizontallyblurredblackandwhiteshadowimage. boolGraphicsClass::RenderVerticalBlurToTexture() { D3DXMATRIXworldMatrix,baseViewMatrix,orthoMatrix; floatscreenSizeY; boolresult; //Storethescreenheightinafloatthatwillbeusedintheverticalblurshader. screenSizeY=(float)(SHADOWMAP_HEIGHT/2); //Settherendertargettobetherendertotexture. m_VerticalBlurTexture->SetRenderTarget(m_D3D->GetDeviceContext()); //Cleartherendertotexture. m_VerticalBlurTexture->ClearRenderTarget(m_D3D->GetDeviceContext(),0.0f,0.0f,0.0f,1.0f); //Generatetheviewmatrixbasedonthecamera'sposition. m_Camera->Render(); //Gettheworldandviewmatricesfromthecameraandd3dobjects. m_Camera->GetBaseViewMatrix(baseViewMatrix); m_D3D->GetWorldMatrix(worldMatrix); //Gettheorthomatrixfromtherendertotexturesincetexturehasdifferentdimensions. m_VerticalBlurTexture->GetOrthoMatrix(orthoMatrix); //TurnofftheZbuffertobeginall2Drendering. m_D3D->TurnZBufferOff(); //Putthesmallorthowindowvertexandindexbuffersonthegraphicspipelinetopreparethemfordrawing. m_SmallWindow->Render(m_D3D->GetDeviceContext()); //Renderthesmallorthowindowusingtheverticalblurshaderandthehorizontalblurredrendertotextureresource. result=m_VerticalBlurShader->Render(m_D3D->GetDeviceContext(),m_SmallWindow->GetIndexCount(),worldMatrix,baseViewMatrix,orthoMatrix, m_HorizontalBlurTexture->GetShaderResourceView(),screenSizeY); if(!result) { returnfalse; } //TurntheZbufferbackonnowthatall2Drenderinghascompleted. m_D3D->TurnZBufferOn(); //Resettherendertargetbacktotheoriginalbackbufferandnottherendertotextureanymore. m_D3D->SetBackBufferRenderTarget(); //Resettheviewportbacktotheoriginal. m_D3D->ResetViewport(); returntrue; } Andthisfunctioniswhereperformtheupsampleoftheblurredblackandwhiteshadowimage. boolGraphicsClass::UpSampleTexture() { D3DXMATRIXworldMatrix,baseViewMatrix,orthoMatrix; boolresult; //Settherendertargettobetherendertotexture. m_UpSampleTexure->SetRenderTarget(m_D3D->GetDeviceContext()); //Cleartherendertotexture. m_UpSampleTexure->ClearRenderTarget(m_D3D->GetDeviceContext(),0.0f,0.0f,0.0f,1.0f); //Generatetheviewmatrixbasedonthecamera'sposition. m_Camera->Render(); //Gettheworldandviewmatricesfromthecameraandd3dobjects. m_Camera->GetBaseViewMatrix(baseViewMatrix); m_D3D->GetWorldMatrix(worldMatrix); //Gettheorthomatrixfromtherendertotexturesincetexturehasdifferentdimensions. m_UpSampleTexure->GetOrthoMatrix(orthoMatrix); //TurnofftheZbuffertobeginall2Drendering. m_D3D->TurnZBufferOff(); //Putthefullscreenorthowindowvertexandindexbuffersonthegraphicspipelinetopreparethemfordrawing. m_FullScreenWindow->Render(m_D3D->GetDeviceContext()); //Renderthefullscreenorthowindowusingthetextureshaderandthesmallsizedfinalblurredrendertotextureresource. result=m_TextureShader->Render(m_D3D->GetDeviceContext(),m_FullScreenWindow->GetIndexCount(),worldMatrix,baseViewMatrix,orthoMatrix, m_VerticalBlurTexture->GetShaderResourceView()); if(!result) { returnfalse; } //TurntheZbufferbackonnowthatall2Drenderinghascompleted. m_D3D->TurnZBufferOn(); //Resettherendertargetbacktotheoriginalbackbufferandnottherendertotextureanymore. m_D3D->SetBackBufferRenderTarget(); //Resettheviewportbacktotheoriginal. m_D3D->ResetViewport(); returntrue; } TheRenderfunctioncallsalltheabovefunctionsinthecorrectorderandthenusestheupsampledblurredimagetoperformthesoftshadowrendering. boolGraphicsClass::Render() { boolresult; D3DXMATRIXworldMatrix,viewMatrix,projectionMatrix,translateMatrix; floatposX,posY,posZ; //Firstrenderthescenetoatexture. result=RenderSceneToTexture(); if(!result) { returnfalse; } //Nextrendertheshadowedsceneinblackandwhite. result=RenderBlackAndWhiteShadows(); if(!result) { returnfalse; } //Thendownsampletheblackandwhitescenetexture. result=DownSampleTexture(); if(!result) { returnfalse; } //Performahorizontalbluronthedownsampledtexture. result=RenderHorizontalBlurToTexture(); if(!result) { returnfalse; } //Nowperformaverticalbluronthetexture. result=RenderVerticalBlurToTexture(); if(!result) { returnfalse; } //Finallyupsamplethefinalblurredrendertotexturethatcannowbeusedinthesoftshadowshader. result=UpSampleTexture(); if(!result) { returnfalse; } //Clearthebufferstobeginthescene. m_D3D->BeginScene(0.0f,0.0f,0.0f,1.0f); //Generatetheviewmatrixbasedonthecamera'sposition. m_Camera->Render(); //Gettheworld,view,andprojectionmatricesfromthecameraandd3dobjects. m_Camera->GetViewMatrix(viewMatrix); m_D3D->GetWorldMatrix(worldMatrix); m_D3D->GetProjectionMatrix(projectionMatrix); //Setupthetranslationmatrixforthecubemodel. m_CubeModel->GetPosition(posX,posY,posZ); D3DXMatrixTranslation(&worldMatrix,posX,posY,posZ); //Renderthecubemodelusingthesoftshadowshader. m_CubeModel->Render(m_D3D->GetDeviceContext()); result=m_SoftShadowShader->Render(m_D3D->GetDeviceContext(),m_CubeModel->GetIndexCount(),worldMatrix,viewMatrix,projectionMatrix, m_CubeModel->GetTexture(),m_UpSampleTexure->GetShaderResourceView(),m_Light->GetPosition(), m_Light->GetAmbientColor(),m_Light->GetDiffuseColor()); if(!result) { returnfalse; } //Resettheworldmatrix. m_D3D->GetWorldMatrix(worldMatrix); //Setupthetranslationmatrixforthespheremodel. m_SphereModel->GetPosition(posX,posY,posZ); D3DXMatrixTranslation(&worldMatrix,posX,posY,posZ); //Renderthespheremodelusingthesoftshadowshader. m_SphereModel->Render(m_D3D->GetDeviceContext()); result=m_SoftShadowShader->Render(m_D3D->GetDeviceContext(),m_SphereModel->GetIndexCount(),worldMatrix,viewMatrix,projectionMatrix, m_SphereModel->GetTexture(),m_UpSampleTexure->GetShaderResourceView(),m_Light->GetPosition(), m_Light->GetAmbientColor(),m_Light->GetDiffuseColor()); if(!result) { returnfalse; } //Resettheworldmatrix. m_D3D->GetWorldMatrix(worldMatrix); //Setupthetranslationmatrixforthegroundmodel. m_GroundModel->GetPosition(posX,posY,posZ); D3DXMatrixTranslation(&worldMatrix,posX,posY,posZ); //Renderthegroundmodelusingthesoftshadowshader. m_GroundModel->Render(m_D3D->GetDeviceContext()); result=m_SoftShadowShader->Render(m_D3D->GetDeviceContext(),m_GroundModel->GetIndexCount(),worldMatrix,viewMatrix,projectionMatrix, m_GroundModel->GetTexture(),m_UpSampleTexure->GetShaderResourceView(),m_Light->GetPosition(), m_Light->GetAmbientColor(),m_Light->GetDiffuseColor()); if(!result) { returnfalse; } //Presenttherenderedscenetothescreen. m_D3D->EndScene(); returntrue; } Summary Theshadowsnowhavesoftedgescreatingamorerealisticshadowingeffect. ToDoExercises 1.Compileandruntheprogram.Usethearrowkeys,A,Z,PgUp,andPgDntonavigatethroughthescene. 2.Changetheblureffecttoafasterperformingblur.Therearequiteafewoptimizedtechniquesthatcanbefoundonthenet. SourceCode SourceCodeandDataFiles:dx11src42.zip Executable:dx11exe42.zip BacktoTutorialIndex



請為這篇文章評分?