void Render(double time) { const Vec3f light_position(16.0, 10.0, 9.0); const Vec3f torus_center(0.0, 1.5, 0.0); const Mat4f torus_matrix = ModelMatrixf::Translation(torus_center) * ModelMatrixf::RotationA( Vec3f(1, 2, 1), FullCircles(time / 17.0) ); const Mat4f light_proj_matrix = CamMatrixf::PerspectiveX(Degrees(10), 1.0, 1, 100) * CamMatrixf::LookingAt(light_position, torus_center); transf_prog.light_position.Set(light_position); RenderShadowMap( light_position, torus_matrix, light_proj_matrix ); RenderImage( time, torus_matrix, light_proj_matrix ); }
LightRayExample(void) : gl() , mesh_loader( mesh_input.stream, shapes::ObjMesh::LoadingOptions(false).Normals() ), meshes(List("Position")("Normal").Get(), mesh_loader) , fan_index(mesh_loader.GetMeshIndex("Fan")) , light_position(0.0, 0.0, -100.0) , vert_shader() , mask_prog(vert_shader) , mask_vao(meshes.VAOForProgram(mask_prog)) , draw_prog(vert_shader) , draw_vao(meshes.VAOForProgram(draw_prog)) , shadow_tex_unit(0) , light_tex_unit(1) { mesh_input.stream.close(); gl.ClearDepth(1.0f); gl.Enable(Capability::DepthTest); RenderShadowMap(512); SetupLightMask(); mask_prog.Use(); mask_prog.light_position.Set(light_position); draw_prog.Use(); draw_prog.light_position.Set(light_position); gl.ClearColor(1.0f, 1.0f, 1.0f, 0.0f); }
// Our Win32 main int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprev, PSTR cmdline, int ishow) { HWND hwnd = NULL; // Handle to our window MSG msg = {0}; WNDCLASSEX wndclassex = {0}; // Init fields we care about wndclassex.cbSize = sizeof(WNDCLASSEX); // Always set to size of WNDCLASSEX wndclassex.style = CS_HREDRAW | CS_VREDRAW; wndclassex.lpfnWndProc = WinProc; wndclassex.hInstance = hinstance; wndclassex.lpszClassName = kClassName; wndclassex.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_SHARED); RegisterClassEx(&wndclassex); // Register the WNDCLASSEX RECT rect = { 0, 0, kWinWid, kWinHgt }; // Desired window client rect DWORD winStyleEx = WS_EX_CLIENTEDGE; DWORD winStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME; // Adjust window rect so it gives us our desired client rect when we // create the window AdjustWindowRectEx(&rect, winStyle, false, winStyleEx); // Create the window hwnd = CreateWindowEx(winStyleEx, kClassName, "www.GameTutorials.com -- Shadow Mapping (HLSL)", winStyle, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hinstance, NULL); // Get the client rect and make sure our client is the size we want GetClientRect(hwnd, &rect); assert(rect.right == kWinWid && rect.bottom == kWinHgt); // Init our global 3D object if(g3D->init(hwnd) == false) return EXIT_FAILURE; // There's been an error, lets get out of this joint if(!CreateSphere(0.05f, D3DCOLOR_XRGB(255,255,0), &gLight)) return false; // Couldn't create the sphere... Something very bad happened... if(!CreateSphere(0.75f, D3DCOLOR_XRGB(0,128,64), &gSphere)) return false; // Couldn't create the sphere... Something very bad happened... if(!CreateBox(1.0f, 2.0f, 1.0f, D3DCOLOR_XRGB(0, 128, 64), &gBox)) return false; // Couldn't create the box... This isn't good! if(!CreateBox(16.0f, 0.05f, 16.0f, D3DCOLOR_XRGB(225, 225, 255), &gGround)) return false; // Couldn't create the ground... Time to bail if(!gShadowMap.createRenderTexture(512, 512, D3DFMT_R32F)) return false; // Couldn't create a shadow map texture. Your video card // probably doesn't support the D3DFMT_R32F format. You will need a beefier card to // run this tutorial if(!gRenderTarget.init(512, 512, D3DFMT_R32F, D3DFMT_D24S8)) return false; // Couldn't create a shadow map texture. Your video card doesn't support render // targets or it probably doesn't support the D3DFMT_R32F format. You will need // a beefier card to run this tutorial // Set up our projection matrix once because it will not change g3D->setProjMatrix(DEG2RAD(60), 1.0f, 2048.0f); // We set up our view matrix once because it will never change g3D->setViewMatrix(kEyePos, CPos(0.0f, 0.0f, 0.0f)); D3DXMATRIXA16 projMat; // Create texture projection matrix D3DXMatrixPerspectiveFovLH(&projMat, DEG2RAD(60), 1.0f, 0.1f, 100.0f); // Set data in our shader that will never change g3D->mShader->SetFloatArray("gLightProjMat", &projMat._11, 16); g3D->mShader->SetFloatArray("gEyePos", &kEyePos.x, 3); // Set the camera's eye position g3D->mShader->SetFloatArray("gDiffuse", &kDiffuse.r, 3); // Lights diffuse color g3D->mShader->SetFloatArray("gSpecular", &kSpecular.r, 3); // Lights specular color g3D->mShader->SetFloatArray("gAmbient", &kAmbient.r, 3); // Lights ambient color // Show and update the window ShowWindow(hwnd, ishow); UpdateWindow(hwnd); while(1) // While the app is alive { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // If the OS has a message for us { if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else if(LockFrameRate()) // Else, if it's time to draw { static int angle = 0; // Stores the amount rotated in degrees D3DXMATRIX tMat, rMat; // This will hold translation and rotation matrices D3DXMATRIX wMat; // This will hold the world matrix of objects we want rendered D3DXMATRIX shadowMat; // The matrix for projecting the shadow to a plane // The light is going to potentially move, so we need to // set it's position every frame g3D->mShader->SetFloatArray("gLightPos", &gLightPos.x, 3); // Render the shadow map RenderShadowMap(); // Render the ground, box and sphere with shadows RenderScene(); } else Sleep(1); // Otherwise, give the OS some time to process other programs } // end of while(1) gLight->Release(); // Free up the light gSphere->Release(); // Free up the sphere gBox->Release(); // Free up the box gGround->Release(); // Free up the ground g3D->deinit(); // Free up the D3D object UnregisterClass(kClassName,hinstance); // Free up WNDCLASSEX return EXIT_SUCCESS; // Application was a success }
// Render a frame void AtmosphereSample::Render() { float4x4 mViewProj = m_mCameraView * m_mCameraProj; LightAttribs LightAttrs; LightAttrs.f4DirOnLight = -m_f3LightDir; LightAttrs.f4DirOnLight.w = 0; float4 f4ExtraterrestrialSunColor = float4(10,10,10,10); LightAttrs.f4ExtraterrestrialSunColor = f4ExtraterrestrialSunColor;// *m_fScatteringScale; LightAttrs.f4AmbientLight = float4( 0, 0, 0, 0 ); // m_iFirstCascade must be initialized before calling RenderShadowMap()! m_PPAttribs.m_iFirstCascade = std::min(m_PPAttribs.m_iFirstCascade, m_TerrainRenderParams.m_iNumShadowCascades - 1); m_PPAttribs.m_fFirstCascade = (float)m_PPAttribs.m_iFirstCascade; RenderShadowMap(m_pImmediateContext, LightAttrs, m_mCameraView, m_mCameraProj); LightAttrs.ShadowAttribs.bVisualizeCascades = m_bVisualizeCascades ? TRUE : FALSE; // Calculate location of the sun on the screen float4 &f4LightPosPS = LightAttrs.f4LightScreenPos; f4LightPosPS = LightAttrs.f4DirOnLight * mViewProj; f4LightPosPS.x /= f4LightPosPS.w; f4LightPosPS.y /= f4LightPosPS.w; f4LightPosPS.z /= f4LightPosPS.w; float fDistToLightOnScreen = length( (float2&)f4LightPosPS ); float fMaxDist = 100; if( fDistToLightOnScreen > fMaxDist ) (float2&)f4LightPosPS *= fMaxDist/fDistToLightOnScreen; const auto& SCDesc = m_pSwapChain->GetDesc(); // Note that in fact the outermost visible screen pixels do not lie exactly on the boundary (+1 or -1), but are biased by // 0.5 screen pixel size inwards. Using these adjusted boundaries improves precision and results in // smaller number of pixels which require inscattering correction LightAttrs.bIsLightOnScreen = fabs(f4LightPosPS.x) <= 1.f - 1.f/(float)SCDesc.Width && fabs(f4LightPosPS.y) <= 1.f - 1.f/(float)SCDesc.Height; { MapHelper<LightAttribs> pLightAttribs( m_pImmediateContext, m_pcbLightAttribs, MAP_WRITE, MAP_FLAG_DISCARD ); *pLightAttribs = LightAttrs; } // The first time GetAmbientSkyLightSRV() is called, the ambient sky light texture // is computed and render target is set. So we need to query the texture before setting // render targets auto *pAmbientSkyLightSRV = m_pLightSctrPP->GetAmbientSkyLightSRV(m_pDevice, m_pImmediateContext); m_pImmediateContext->SetRenderTargets( 0, nullptr, nullptr ); const float ClearColor[] = { 0.350f, 0.350f, 0.350f, 1.0f }; const float Zero[] = { 0.f, 0.f, 0.f, 0.f }; m_pImmediateContext->ClearRenderTarget(nullptr, m_bEnableLightScattering ? Zero : ClearColor); ITextureView *pRTV = nullptr, *pDSV = nullptr; if( m_bEnableLightScattering ) { pRTV = m_pOffscreenColorBuffer->GetDefaultView( TEXTURE_VIEW_RENDER_TARGET ); pDSV = m_pOffscreenDepthBuffer->GetDefaultView( TEXTURE_VIEW_DEPTH_STENCIL ); m_pImmediateContext->SetRenderTargets( 1, &pRTV, pDSV ); m_pImmediateContext->ClearRenderTarget(pRTV, Zero); } else { pRTV = nullptr; pDSV = nullptr; m_pImmediateContext->SetRenderTargets( 0, nullptr, nullptr ); } m_pImmediateContext->ClearDepthStencil(pDSV, CLEAR_DEPTH_FLAG, 1.f); { MapHelper<CameraAttribs> CamAttribs( m_pImmediateContext, m_pcbCameraAttribs, MAP_WRITE, MAP_FLAG_DISCARD ); CamAttribs->mViewProjT = transposeMatrix( mViewProj ); CamAttribs->mProjT = transposeMatrix( m_mCameraProj ); CamAttribs->mViewProjInvT = transposeMatrix( inverseMatrix(mViewProj) ); float fNearPlane = 0.f, fFarPlane = 0.f; GetNearFarPlaneFromProjMatrix( m_mCameraProj, fNearPlane, fFarPlane, m_bIsDXDevice); CamAttribs->fNearPlaneZ = fNearPlane; CamAttribs->fFarPlaneZ = fFarPlane * 0.999999f; CamAttribs->f4CameraPos = m_f3CameraPos; } // Render terrain auto *pPrecomputedNetDensitySRV = m_pLightSctrPP->GetPrecomputedNetDensitySRV(); m_TerrainRenderParams.DstRTVFormat = m_bEnableLightScattering ? m_pOffscreenColorBuffer->GetDesc().Format : m_pSwapChain->GetDesc().ColorBufferFormat; m_EarthHemisphere.Render( m_pImmediateContext, m_TerrainRenderParams, m_f3CameraPos, mViewProj, m_pShadowMapSRV, pPrecomputedNetDensitySRV, pAmbientSkyLightSRV, false); if( m_bEnableLightScattering ) { FrameAttribs FrameAttribs; FrameAttribs.pDevice = m_pDevice; FrameAttribs.pDeviceContext = m_pImmediateContext; FrameAttribs.dElapsedTime = m_fElapsedTime; FrameAttribs.pLightAttribs = &LightAttrs; m_PPAttribs.m_iNumCascades = m_TerrainRenderParams.m_iNumShadowCascades; m_PPAttribs.m_fNumCascades = (float)m_TerrainRenderParams.m_iNumShadowCascades; FrameAttribs.pcbLightAttribs = m_pcbLightAttribs; FrameAttribs.pcbCameraAttribs = m_pcbCameraAttribs; m_PPAttribs.m_fMaxShadowMapStep = static_cast<float>(m_uiShadowMapResolution / 4); m_PPAttribs.m_f2ShadowMapTexelSize = float2( 1.f / static_cast<float>(m_uiShadowMapResolution), 1.f / static_cast<float>(m_uiShadowMapResolution) ); m_PPAttribs.m_uiShadowMapResolution = m_uiShadowMapResolution; // During the ray marching, on each step we move by the texel size in either horz // or vert direction. So resolution of min/max mipmap should be the same as the // resolution of the original shadow map m_PPAttribs.m_uiMinMaxShadowMapResolution = m_uiShadowMapResolution; m_PPAttribs.m_uiInitialSampleStepInSlice = std::min( m_PPAttribs.m_uiInitialSampleStepInSlice, m_PPAttribs.m_uiMaxSamplesInSlice ); m_PPAttribs.m_uiEpipoleSamplingDensityFactor = std::min( m_PPAttribs.m_uiEpipoleSamplingDensityFactor, m_PPAttribs.m_uiInitialSampleStepInSlice ); FrameAttribs.ptex2DSrcColorBufferSRV = m_pOffscreenColorBuffer->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); FrameAttribs.ptex2DSrcColorBufferRTV = m_pOffscreenColorBuffer->GetDefaultView(TEXTURE_VIEW_RENDER_TARGET); FrameAttribs.ptex2DSrcDepthBufferSRV = m_pOffscreenDepthBuffer->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); FrameAttribs.ptex2DSrcDepthBufferDSV = m_pOffscreenDepthBuffer->GetDefaultView(TEXTURE_VIEW_DEPTH_STENCIL); FrameAttribs.ptex2DShadowMapSRV = m_pShadowMapSRV; FrameAttribs.pDstRTV = 0;// mpBackBufferRTV; // Then perform the post processing, swapping the inverseworld view projection matrix axes. m_pLightSctrPP->PerformPostProcessing(FrameAttribs, m_PPAttribs); } }
void DemoApp::DrawScene() { assert(md3dImmediateContext); assert(mSwapChain); //Render shadow map m_pShadowMap->BindShadowMapDSV(md3dImmediateContext); RenderShadowMap(); m_pDepthSRV = m_pShadowMap->DepthShaderResourceView(); //Restore render targets md3dImmediateContext->RSSetState(0); ID3D11RenderTargetView* renderTargets[1] = { mRenderTargetView }; md3dImmediateContext->OMSetRenderTargets(1, renderTargets, mDepthStencilView); md3dImmediateContext->RSSetViewports(1, &mScreenViewport); //Clear Render Targets float clearColor[4] = { 199.0f / 255.0f, 197.0f / 255.0f, 206.0f / 255.0f, 1.0f }; md3dImmediateContext->ClearRenderTargetView(mRenderTargetView, clearColor); md3dImmediateContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); //Set Render State md3dImmediateContext->RSSetState(RenderStates::CullClockwiseRS); //Set Vertex and Index Buffers UINT strides[2] = { sizeof(Vertex::VertexPNT), sizeof(Vertex::VertexIns_Mat) }; UINT offsets[2] = { 0, 0 }; ID3D11Buffer * buffers[2] = { m_pVertexBuffer, m_pInstancedBuffer }; md3dImmediateContext->IASetVertexBuffers(0, 2, buffers, strides, offsets); md3dImmediateContext->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0); //Update Per Object Constant Buffer CBPerObject cbPerObj; cbPerObj.matWorld = XMMatrixTranspose(mWorld); cbPerObj.matWorldInvTranspose = XMMatrixTranspose(MathHelper::InverseTranspose(mWorld)); cbPerObj.matWVP = XMMatrixTranspose(mWorld * m_pCamera->GetViewProjMatrix()); cbPerObj.matLightWVPT = XMMatrixTranspose(mWorld * mLightVPT); cbPerObj.isInstancing = 1; cbPerObj.material.Ambient = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f); cbPerObj.material.Diffuse = XMFLOAT4(0.8f, 0.8f, 0.8f, 1.0f); cbPerObj.material.Specular = XMFLOAT4(0.1f, 0.1f, 0.1f, 1.0f); cbPerObj.material.Reflect = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f); md3dImmediateContext->UpdateSubresource(m_pCBPerObject, 0, NULL, &cbPerObj, 0, 0); //Set Shaders and Resources md3dImmediateContext->VSSetShader(m_pVertexShader, NULL, 0); md3dImmediateContext->VSSetConstantBuffers(3, 1, &m_pCBPerObject); md3dImmediateContext->PSSetShader(m_pPixelShader, NULL, 0); md3dImmediateContext->PSSetConstantBuffers(3, 1, &m_pCBPerObject); md3dImmediateContext->PSSetShaderResources(0, 1, &m_pPillarSRV); md3dImmediateContext->PSSetShaderResources(2, 1, &m_pDepthSRV); md3dImmediateContext->PSSetSamplers(0, 1, &m_pSampleLinear); md3dImmediateContext->PSSetSamplers(1, 1, &m_pSampleShadowMap); //Draw Pillars md3dImmediateContext->DrawIndexedInstanced(36, instanceCnt, 0, 0, 0); UINT stride = sizeof(Vertex::VertexPNT); UINT offset = 0; md3dImmediateContext->IASetVertexBuffers(0, 1, &m_pGroundVertexBuffer, &stride, &offset); md3dImmediateContext->IASetIndexBuffer(m_pGroundIndexBuffer, DXGI_FORMAT_R32_UINT, 0); cbPerObj.isInstancing = 0; md3dImmediateContext->UpdateSubresource(m_pCBPerObject, 0, NULL, &cbPerObj, 0, 0); md3dImmediateContext->PSSetShaderResources(0, 1, &m_pGroundSRV); //Draw Ground md3dImmediateContext->DrawIndexed(36, 0, 0); //Draw Skybox m_pSkybox->Draw(md3dImmediateContext, m_pCamera); md3dImmediateContext->RSSetState(0); md3dImmediateContext->OMSetDepthStencilState(0, 0); //Render mini window displaying shadow map RenderMiniWindow(); HR(mSwapChain->Present(0, 0)); }
//-------------------------------------------------------------------------------------- // render callback //-------------------------------------------------------------------------------------- void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, float fElapsedTime, void* pUserContext ) { static int s_iCounter = 0; // If the settings dialog is being shown, then render it instead of rendering the app's scene if( g_D3DSettingsDlg.IsActive() ) { g_D3DSettingsDlg.OnRender( fElapsedTime ); return; } if( g_pScenePS == NULL && s_iCounter == 0 ) { s_iCounter = 4; } if( s_iCounter > 0 ) s_iCounter --; if( s_iCounter == 1 && g_pScenePS == NULL ) { HRESULT hr = S_OK; // Create the shaders ID3DBlob* pBlob = NULL; // VS hr = CompileShaderFromFile( L"ContactHardeningShadows11.hlsl", "VS_RenderScene", "vs_5_0", &pBlob ); hr = pd3dDevice->CreateVertexShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &g_pSceneVS ); DXUT_SetDebugName( g_pSceneVS, "VS_RenderScene" ); // Define our scene vertex data layout const D3D11_INPUT_ELEMENT_DESC SceneLayout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXTURE", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; hr = pd3dDevice->CreateInputLayout( SceneLayout, ARRAYSIZE( SceneLayout ), pBlob->GetBufferPointer(), pBlob->GetBufferSize(), &g_pSceneVertexLayout ); SAFE_RELEASE( pBlob ); DXUT_SetDebugName( g_pSceneVertexLayout, "SceneLayout" ); hr = CompileShaderFromFile( L"ContactHardeningShadows11.hlsl", "VS_RenderSceneSM", "vs_5_0", &pBlob ); hr = pd3dDevice->CreateVertexShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &g_pSM_VS ); SAFE_RELEASE( pBlob ); DXUT_SetDebugName( g_pSM_VS, "VS_RenderSceneSM" ); // PS hr = CompileShaderFromFile( L"ContactHardeningShadows11.hlsl", "PS_RenderScene", "ps_5_0", &pBlob ); hr = pd3dDevice->CreatePixelShader( pBlob->GetBufferPointer(), pBlob->GetBufferSize(), NULL, &g_pScenePS ); SAFE_RELEASE( pBlob ); DXUT_SetDebugName( g_pScenePS, "PS_RenderScene" ); s_iCounter = 0; } else if( g_pScenePS != NULL ) { ID3D11RenderTargetView* pRTV[2] = { NULL,NULL }; ID3D11ShaderResourceView* pSRV[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; // Array of our samplers ID3D11SamplerState* ppSamplerStates[3] = { g_pSamplePoint, g_pSampleLinear, g_pSamplePointCmp }; pd3dImmediateContext->PSSetSamplers( 0, 3, ppSamplerStates ); // Store off original render target, this is the back buffer of the swap chain ID3D11RenderTargetView* pOrigRTV = DXUTGetD3D11RenderTargetView(); ID3D11DepthStencilView* pOrigDSV = DXUTGetD3D11DepthStencilView(); // Clear the render target float ClearColor[4] = { 0.0f, 0.25f, 0.25f, 0.55f }; pd3dImmediateContext->ClearRenderTargetView( DXUTGetD3D11RenderTargetView(), ClearColor ); pd3dImmediateContext->ClearDepthStencilView( DXUTGetD3D11DepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0, 0 ); // Get the projection & view matrix from the camera class D3DXMATRIXA16 mWorld; D3DXMATRIXA16 mView; D3DXMATRIXA16 mProj; D3DXMATRIXA16 mViewProjLight; D3DXMATRIXA16 mWorldViewProjection; D3DXVECTOR3 vLightDir; // disable color writes pd3dImmediateContext->OMSetBlendState(g_pBlendStateColorWritesOff, 0, 0xffffffff); RenderShadowMap( pd3dDevice, pd3dImmediateContext, mViewProjLight, vLightDir ); // enable color writes pd3dImmediateContext->OMSetBlendState(g_pBlendStateNoBlend, 0, 0xffffffff); mView = *g_Camera.GetViewMatrix(); mProj = *g_Camera.GetProjMatrix(); mWorldViewProjection = mView * mProj; // Setup the constant buffer for the scene vertex shader D3D11_MAPPED_SUBRESOURCE MappedResource; pd3dImmediateContext->Map( g_pcbConstants, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ); CB_CONSTANTS* pConstants = ( CB_CONSTANTS* )MappedResource.pData; D3DXMatrixTranspose( &pConstants->f4x4WorldViewProjection, &mWorldViewProjection ); D3DXMatrixTranspose( &pConstants->f4x4WorldViewProjLight, &mViewProjLight ); pConstants->vShadowMapDimensions = D3DXVECTOR4(g_fShadowMapWidth, g_fShadowMapHeight, 1.0f/g_fShadowMapWidth, 1.0f/g_fShadowMapHeight); pConstants->vLightDir = D3DXVECTOR4( vLightDir.x, vLightDir.y, vLightDir.z, 0.0f ); pConstants->fSunWidth = g_fSunWidth; pd3dImmediateContext->Unmap( g_pcbConstants, 0 ); pd3dImmediateContext->VSSetConstantBuffers( g_iCONSTANTSCBBind, 1, &g_pcbConstants ); pd3dImmediateContext->PSSetConstantBuffers( g_iCONSTANTSCBBind, 1, &g_pcbConstants ); // Set the shaders pd3dImmediateContext->VSSetShader( g_pSceneVS, NULL, 0 ); pd3dImmediateContext->PSSetShader( g_pScenePS, NULL, 0 ); // Set the vertex buffer format pd3dImmediateContext->IASetInputLayout( g_pSceneVertexLayout ); // Rebind to original back buffer and depth buffer pRTV[0] = pOrigRTV; pd3dImmediateContext->OMSetRenderTargets(1, pRTV, pOrigDSV ); // set the shadow map pd3dImmediateContext->PSSetShaderResources( 1, 1, &g_pDepthTextureSRV ); // Render the scene g_SceneMesh.Render( pd3dImmediateContext, 0 ); g_Poles.Render( pd3dImmediateContext, 0 ); // restore resources pd3dImmediateContext->PSSetShaderResources( 0, 8, pSRV ); } // Render GUI DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"HUD / Stats" ); if( g_bGuiVisible ) { g_HUD.OnRender( fElapsedTime ); g_SampleUI.OnRender( fElapsedTime ); } RenderText(); DXUT_EndPerfEvent(); }
/** **************************************************************************************************** @brief Render scene - camera, lights and objects(run through object list and call render function for every object) @param delete_buffer should we delete color and depth buffer? ***************************************************************************************************/ void TScene::Redraw(bool delete_buffer) { GLenum mrt[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; ///draw all lights unsigned i; for(i=0, m_il = m_lights.begin(); m_il != m_lights.end(), i<m_lights.size(); ++m_il, i++) { ///if light has a shadow, render scene from light view to texture (TScene::RenderShadowMap()) if((*m_il)->IsCastingShadow()) { //render shadow map if((*m_il)->GetType() == OMNI) { RenderShadowMapOmni(*m_il); } else RenderShadowMap(*m_il); } } //HDR/SSAO renderer - render to texture if(m_useHDR || m_useSSAO) { //render target viewport size glViewport(0,0,m_RT_resX,m_RT_resY); //attach framebuffer to render to glBindFramebuffer(GL_FRAMEBUFFER, m_f_buffer); //attach render texture glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex_cache["render_texture"], 0); ///use multisampled FBO if required if(m_msamples > 1) glBindFramebuffer(GL_FRAMEBUFFER, m_f_bufferMSAA); //multiple render targets - only when using SSAO and/or normal buffer if(m_useNormalBuffer) glDrawBuffers(2, mrt); //clear screen (if desired) if(delete_buffer) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } else //else render to default framebuffer, clear it(if desired) { if(delete_buffer) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } if(m_wireframe) glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glViewport(0,0,m_RT_resX,m_RT_resY); //render all opaque objects DrawScene(DRAW_OPAQUE); //then transparent objects glBlendFunc(GL_SRC_ALPHA, GL_ONE); glEnable(GL_BLEND); DrawScene(DRAW_TRANSPARENT); glDisable(GL_BLEND); if(m_wireframe) glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); //HDR/SSAO renderer if(m_useHDR || m_useSSAO) { //if MSAA enabled, copy from multisampled FBO to normal FBO if(m_msamples > 1) { //blit colors glReadBuffer(GL_COLOR_ATTACHMENT0); glDrawBuffer(GL_COLOR_ATTACHMENT0); glBindFramebuffer(GL_READ_FRAMEBUFFER, m_f_bufferMSAA); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_f_buffer); glBlitFramebuffer(0, 0, m_resx, m_resy, 0, 0, m_resx, m_resy, GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, GL_NEAREST); //blit normals if(m_useNormalBuffer) { glReadBuffer(GL_COLOR_ATTACHMENT1); glDrawBuffer(GL_COLOR_ATTACHMENT1); glBlitFramebuffer(0, 0, m_resx, m_resy, 0, 0, m_resx, m_resy, GL_COLOR_BUFFER_BIT, GL_NEAREST); } } if(m_useNormalBuffer) glDrawBuffer(GL_COLOR_ATTACHMENT0); //attach bloom texture glBindFramebuffer(GL_FRAMEBUFFER, m_f_buffer); glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex_cache["bloom_texture"], 0); //downsample bloom texture by setting new viewport glViewport(0,0,m_RT_resX/2,m_RT_resY/2); //Bloom/SSAO pass RenderPass("mat_bloom_hdr_ssao"); //horizontal blur pass RenderPass("mat_blur_horiz"); //vertical blur pass glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex_cache["blur_texture"], 0); RenderPass("mat_blur_vert"); //go back to regular framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //final draw with bloom and tone mapping glViewport(0,0,m_resx,m_resy); //restore original scene viewport RenderPass("mat_tonemap"); } //show shadow maps if(m_draw_shadow_map) { for(int i=0; i<2; i++) { const float q_size = 0.5f; if(m_lights[0]->GetType() == OMNI) { SetUniform("show_depth_omni", "far_plane", SHADOW_FAR); SetUniform("show_depth_omni", "index", float(i)); RenderSmallQuad("show_depth_omni", 0.0f, i*q_size, q_size); } else { SetUniform("show_depth", "far_plane", SHADOW_FAR); RenderSmallQuad("show_depth", 0.0f, 0.0f, q_size); break; } } } //finish drawing, restore buffers glBindVertexArray(0); }