void MirrorApp::DrawScene() { md3dImmediateContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::Black)); md3dImmediateContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0); md3dImmediateContext->IASetInputLayout(InputLayouts::Basic32); md3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); float blendFactor[] = {0.0f, 0.0f, 0.0f, 0.0f}; UINT stride = sizeof(Vertex::Basic32); UINT offset = 0; XMMATRIX view = XMLoadFloat4x4(&mView); XMMATRIX proj = XMLoadFloat4x4(&mProj); XMMATRIX viewProj = view*proj; // Set per frame constants. Effects::BasicFX->SetDirLights(mDirLights); Effects::BasicFX->SetEyePosW(mEyePosW); Effects::BasicFX->SetFogColor(Colors::Black); Effects::BasicFX->SetFogStart(2.0f); Effects::BasicFX->SetFogRange(40.0f); // Skull doesn't have texture coordinates, so we can't texture it. ID3DX11EffectTechnique* activeTech; ID3DX11EffectTechnique* activeSkullTech; switch(mRenderOptions) { case RenderOptions::Lighting: activeTech = Effects::BasicFX->Light3Tech; activeSkullTech = Effects::BasicFX->Light3Tech; break; case RenderOptions::Textures: activeTech = Effects::BasicFX->Light3TexTech; activeSkullTech = Effects::BasicFX->Light3Tech; break; case RenderOptions::TexturesAndFog: activeTech = Effects::BasicFX->Light3TexFogTech; activeSkullTech = Effects::BasicFX->Light3FogTech; break; } D3DX11_TECHNIQUE_DESC techDesc; // // Draw the floor and walls to the back buffer as normal. // activeTech->GetDesc( &techDesc ); for(UINT p = 0; p < techDesc.Passes; ++p) { ID3DX11EffectPass* pass = activeTech->GetPassByIndex( p ); md3dImmediateContext->IASetVertexBuffers(0, 1, &mRoomVB, &stride, &offset); // Set per object constants. XMMATRIX world = XMLoadFloat4x4(&mRoomWorld); XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(world); XMMATRIX worldViewProj = world*view*proj; Effects::BasicFX->SetWorld(world); Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose); Effects::BasicFX->SetWorldViewProj(worldViewProj); Effects::BasicFX->SetTexTransform(XMMatrixIdentity()); Effects::BasicFX->SetMaterial(mRoomMat); // Floor Effects::BasicFX->SetDiffuseMap(mFloorDiffuseMapSRV); pass->Apply(0, md3dImmediateContext); md3dImmediateContext->Draw(6, 0); // Wall Effects::BasicFX->SetDiffuseMap(mWallDiffuseMapSRV); pass->Apply(0, md3dImmediateContext); md3dImmediateContext->Draw(18, 6); } // // Draw the skull to the back buffer as normal. // activeSkullTech->GetDesc( &techDesc ); for(UINT p = 0; p < techDesc.Passes; ++p) { ID3DX11EffectPass* pass = activeSkullTech->GetPassByIndex( p ); md3dImmediateContext->IASetVertexBuffers(0, 1, &mSkullVB, &stride, &offset); md3dImmediateContext->IASetIndexBuffer(mSkullIB, DXGI_FORMAT_R32_UINT, 0); XMMATRIX world = XMLoadFloat4x4(&mSkullWorld); XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(world); XMMATRIX worldViewProj = world*view*proj; Effects::BasicFX->SetWorld(world); Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose); Effects::BasicFX->SetWorldViewProj(worldViewProj); Effects::BasicFX->SetMaterial(mSkullMat); pass->Apply(0, md3dImmediateContext); md3dImmediateContext->DrawIndexed(mSkullIndexCount, 0, 0); } // // Draw the mirror to stencil buffer only. // activeTech->GetDesc( &techDesc ); for(UINT p = 0; p < techDesc.Passes; ++p) { ID3DX11EffectPass* pass = activeTech->GetPassByIndex( p ); md3dImmediateContext->IASetVertexBuffers(0, 1, &mRoomVB, &stride, &offset); // Set per object constants. XMMATRIX world = XMLoadFloat4x4(&mRoomWorld); XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(world); XMMATRIX worldViewProj = world*view*proj; Effects::BasicFX->SetWorld(world); Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose); Effects::BasicFX->SetWorldViewProj(worldViewProj); Effects::BasicFX->SetTexTransform(XMMatrixIdentity()); // Do not write to render target. md3dImmediateContext->OMSetBlendState(RenderStates::NoRenderTargetWritesBS, blendFactor, 0xffffffff); // Render visible mirror pixels to stencil buffer. // Do not write mirror depth to depth buffer at this point, otherwise it will occlude the reflection. md3dImmediateContext->OMSetDepthStencilState(RenderStates::MarkMirrorDSS, 1); pass->Apply(0, md3dImmediateContext); md3dImmediateContext->Draw(6, 24); // Restore states. md3dImmediateContext->OMSetDepthStencilState(0, 0); md3dImmediateContext->OMSetBlendState(0, blendFactor, 0xffffffff); } // // Draw the skull reflection. // activeSkullTech->GetDesc( &techDesc ); for(UINT p = 0; p < techDesc.Passes; ++p) { ID3DX11EffectPass* pass = activeSkullTech->GetPassByIndex( p ); md3dImmediateContext->IASetVertexBuffers(0, 1, &mSkullVB, &stride, &offset); md3dImmediateContext->IASetIndexBuffer(mSkullIB, DXGI_FORMAT_R32_UINT, 0); XMVECTOR mirrorPlane = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); // xy plane XMMATRIX R = XMMatrixReflect(mirrorPlane); XMMATRIX world = XMLoadFloat4x4(&mSkullWorld) * R; XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(world); XMMATRIX worldViewProj = world*view*proj; Effects::BasicFX->SetWorld(world); Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose); Effects::BasicFX->SetWorldViewProj(worldViewProj); Effects::BasicFX->SetMaterial(mSkullMat); // Cache the old light directions, and reflect the light directions. XMFLOAT3 oldLightDirections[3]; for(int i = 0; i < 3; ++i) { oldLightDirections[i] = mDirLights[i].Direction; XMVECTOR lightDir = XMLoadFloat3(&mDirLights[i].Direction); XMVECTOR reflectedLightDir = XMVector3TransformNormal(lightDir, R); XMStoreFloat3(&mDirLights[i].Direction, reflectedLightDir); } Effects::BasicFX->SetDirLights(mDirLights); // Cull clockwise triangles for reflection. md3dImmediateContext->RSSetState(RenderStates::CullClockwiseRS); // Only draw reflection into visible mirror pixels as marked by the stencil buffer. md3dImmediateContext->OMSetDepthStencilState(RenderStates::DrawReflectionDSS, 1); pass->Apply(0, md3dImmediateContext); md3dImmediateContext->DrawIndexed(mSkullIndexCount, 0, 0); // Restore default states. md3dImmediateContext->RSSetState(0); md3dImmediateContext->OMSetDepthStencilState(0, 0); // Restore light directions. for(int i = 0; i < 3; ++i) { mDirLights[i].Direction = oldLightDirections[i]; } Effects::BasicFX->SetDirLights(mDirLights); } // // Draw the mirror to the back buffer as usual but with transparency // blending so the reflection shows through. // activeTech->GetDesc( &techDesc ); for(UINT p = 0; p < techDesc.Passes; ++p) { ID3DX11EffectPass* pass = activeTech->GetPassByIndex( p ); md3dImmediateContext->IASetVertexBuffers(0, 1, &mRoomVB, &stride, &offset); // Set per object constants. XMMATRIX world = XMLoadFloat4x4(&mRoomWorld); XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(world); XMMATRIX worldViewProj = world*view*proj; Effects::BasicFX->SetWorld(world); Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose); Effects::BasicFX->SetWorldViewProj(worldViewProj); Effects::BasicFX->SetTexTransform(XMMatrixIdentity()); Effects::BasicFX->SetMaterial(mMirrorMat); Effects::BasicFX->SetDiffuseMap(mMirrorDiffuseMapSRV); // Mirror md3dImmediateContext->OMSetBlendState(RenderStates::TransparentBS, blendFactor, 0xffffffff); pass->Apply(0, md3dImmediateContext); md3dImmediateContext->Draw(6, 24); } // // Draw the skull shadow. // activeSkullTech->GetDesc( &techDesc ); for(UINT p = 0; p < techDesc.Passes; ++p) { ID3DX11EffectPass* pass = activeSkullTech->GetPassByIndex( p ); md3dImmediateContext->IASetVertexBuffers(0, 1, &mSkullVB, &stride, &offset); md3dImmediateContext->IASetIndexBuffer(mSkullIB, DXGI_FORMAT_R32_UINT, 0); XMVECTOR shadowPlane = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); // xz plane XMVECTOR toMainLight = -XMLoadFloat3(&mDirLights[0].Direction); XMMATRIX S = XMMatrixShadow(shadowPlane, toMainLight); XMMATRIX shadowOffsetY = XMMatrixTranslation(0.0f, 0.001f, 0.0f); // Set per object constants. XMMATRIX world = XMLoadFloat4x4(&mSkullWorld)*S*shadowOffsetY; XMMATRIX worldInvTranspose = MathHelper::InverseTranspose(world); XMMATRIX worldViewProj = world*view*proj; Effects::BasicFX->SetWorld(world); Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose); Effects::BasicFX->SetWorldViewProj(worldViewProj); Effects::BasicFX->SetMaterial(mShadowMat); md3dImmediateContext->OMSetDepthStencilState(RenderStates::NoDoubleBlendDSS, 0); pass->Apply(0, md3dImmediateContext); md3dImmediateContext->DrawIndexed(mSkullIndexCount, 0, 0); // Restore default states. md3dImmediateContext->OMSetBlendState(0, blendFactor, 0xffffffff); md3dImmediateContext->OMSetDepthStencilState(0, 0); } HR(mSwapChain->Present(0, 0)); }
Float3 Float3::TransformDirection(const Float3&v, const Float4x4& m) { XMVECTOR vec = v.ToSIMD(); vec = XMVector3TransformNormal(vec, m.ToSIMD()); return Float3(vec); }
void ForwardRenderer::DrawScene() { DrawShadowMap(); RendererCore::Instance()->SetOriginalRenderTargetDepth(); float blendFactor[] = { 0.0f, 0.0f, 0.0f, 0.0f }; // Set constants XMMATRIX view = XMLoadFloat4x4( RendererCore::Instance()->GetView() ); XMMATRIX proj = XMLoadFloat4x4( RendererCore::Instance()->GetProj() ); XMMATRIX shadowTransform = XMLoadFloat4x4( &m_ShadowTransform ); int iCount = m_vDrawElements.size(); for ( int i = 0; i < iCount; ++i ) { DrawElement* pElem = m_vDrawElements[i]; if ( !pElem ) continue; UINT stride = pElem->stride; UINT offset = pElem->offset; GetD3D11DeviceImmContext()->IASetInputLayout( pElem->m_pInputLayout ); GetD3D11DeviceImmContext()->IASetPrimitiveTopology( pElem->ePrimitiveTopology ); pElem->m_spShader->SetDirLight( m_DirLights[0] ); pElem->m_spShader->SetDirLights( m_DirLights ); pElem->m_spShader->SetPointLight( m_PointLight ); pElem->m_spShader->SetSpotLight( m_SpotLight ); pElem->m_spShader->SetEyePosW( RendererCore::Instance()->GetEyePosW() ); pElem->m_spShader->SetFogStart( 15.0f ); pElem->m_spShader->SetFogRange( 300.0f ); pElem->m_spShader->SetFogColor( Colors::Silver ); for ( auto itor = pElem->m_vecSubElement.begin(); itor != pElem->m_vecSubElement.end() ; ++itor ) { ID3DX11EffectTechnique* pTech = pElem->m_spShader->GetTech( (*itor).m_iTechIndex ); if ( !pTech ) continue; ID3D11Buffer* pVB = pElem->m_spVB->GetVB(); GetD3D11DeviceImmContext()->IASetVertexBuffers( 0, 1, &pVB, &stride, &offset ); if ( pElem->m_spIB ) GetD3D11DeviceImmContext()->IASetIndexBuffer( pElem->m_spIB->GetIB(), DXGI_FORMAT_R32_UINT, 0 ); if ( pElem->m_pRasterS ) GetD3D11DeviceImmContext()->RSSetState( pElem->m_pRasterS ); if ( pElem->m_pBlendS ) GetD3D11DeviceImmContext()->OMSetBlendState( pElem->m_pBlendS, blendFactor, 0xffffffff ); if ( pElem->m_pDepthStencilS ) GetD3D11DeviceImmContext()->OMSetDepthStencilState( pElem->m_pDepthStencilS, pElem->m_uiStencilRef ); XMMATRIX world; XMFLOAT3 oldLightDirections; if ( pElem->m_bStencilReflect ) { XMVECTOR mirrorPlane = XMVectorSet( 0.0f, 0.0f, 1.0f, 0.0f ); // xy plane XMMATRIX R = XMMatrixReflect( mirrorPlane ); world = XMLoadFloat4x4( &pElem->m_vecSubElement[0].m_World ) * R; oldLightDirections = m_DirLights[0].Direction; XMVECTOR lightDir = XMLoadFloat3( &m_DirLights[0].Direction ); XMVECTOR reflectedLightDir = XMVector3TransformNormal( lightDir, R ); XMStoreFloat3( &m_DirLights[0].Direction, reflectedLightDir ); //ÀӽùæÆí pElem->m_spShader->SetDirLight( m_DirLights[0] ); } else if ( pElem->m_bShadowmap ) { XMVECTOR shadowPlane = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ); // xz plane XMVECTOR toMainLight = -XMLoadFloat3( &m_DirLights[0].Direction ); XMMATRIX S = XMMatrixShadow( shadowPlane, toMainLight ); XMMATRIX shadowOffsetY = XMMatrixTranslation( 0.0f, 0.001f, 0.0f ); world = XMLoadFloat4x4( &pElem->m_vecSubElement[0].m_World )*S*shadowOffsetY; } else { world = XMLoadFloat4x4( &pElem->m_vecSubElement[0].m_World ); } TexturePtr spDiffuseMap = (*itor).m_spDiffuseMap; TexturePtr spCubeMap = (*itor).m_spCubeMap; TexturePtr spNormalMap = (*itor).m_spNormalMap; TexturePtr spShadowMap = (*itor).m_spShadowMap; world = XMLoadFloat4x4( &(*itor).m_World ); XMMATRIX worldInvTranspose = MathHelper::InverseTranspose( world ); XMMATRIX viewProj = view*proj; XMMATRIX worldViewProj = world*view*proj; XMMATRIX texTransform = XMLoadFloat4x4( &(*itor).m_TexTransform ); D3DX11_TECHNIQUE_DESC techDesc; pTech->GetDesc( &techDesc ); for ( UINT p = 0; p < techDesc.Passes; ++p ) { pElem->m_spShader->SetWorld( world ); pElem->m_spShader->SetWorldViewProj( worldViewProj ); pElem->m_spShader->SetViewProj( viewProj ); pElem->m_spShader->SetWorldInvTranspose( worldInvTranspose ); pElem->m_spShader->SetTexTransform( texTransform ); pElem->m_spShader->SetShadowTransform( world*shadowTransform ); pElem->m_spShader->SetMaterial( (*itor).m_mat ); if ( spDiffuseMap ) { if ( !spDiffuseMap->IsArray() ) pElem->m_spShader->SetDiffuseMap( spDiffuseMap->GetSRV() ); else pElem->m_spShader->SetDiffuseMapArray( spDiffuseMap->GetSRV() ); } if ( spCubeMap ) { pElem->m_spShader->SetCubeMap( spCubeMap->GetSRV() ); } if ( spNormalMap ) { pElem->m_spShader->SetNormalMap( spNormalMap->GetSRV() ); } if ( spShadowMap ) { pElem->m_spShader->SetShadowMap( spShadowMap->GetSRV() ); } pTech->GetPassByIndex( p )->Apply( 0, GetD3D11DeviceImmContext() ); if ( pElem->m_bDrawIndex ) { GetD3D11DeviceImmContext()->DrawIndexed( (*itor).m_IndexCount, (*itor).m_StartIndexLocation, (*itor).m_BaseVertexLocation ); } else { GetD3D11DeviceImmContext()->Draw( (*itor).m_VertexCount, (*itor).m_StartVertexLocation ); } } if ( pElem->m_bStencilReflect ) { m_DirLights[0].Direction = oldLightDirections; } } } DrawScreenQuad(); }
void Game::CreateSphere(int latLines, int longLines) { NumSphereVertices = ((latLines - 2) * longLines) + 2; NumSphereFaces = ((latLines - 3)*(longLines)* 2) + (longLines * 2); float sphereYaw = 0.0f; float spherePitch = 0.0f; std::vector<Vertex> vertices(NumSphereVertices); XMVECTOR currVertPos = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); vertices[0].pos.x = 0.0f; vertices[0].pos.y = 0.0f; vertices[0].pos.z = 1.0f; for (DWORD i = 0; i < latLines - 2; ++i) { spherePitch = (i + 1) * (3.14 / (latLines - 1)); skyRotationX = XMMatrixRotationX(spherePitch); for (DWORD j = 0; j < longLines; ++j) { sphereYaw = j * (6.28 / (longLines)); skyRotationY = XMMatrixRotationZ(sphereYaw); currVertPos = XMVector3TransformNormal(XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f), (skyRotationX * skyRotationY)); currVertPos = XMVector3Normalize(currVertPos); vertices[i*longLines + j + 1].pos.x = XMVectorGetX(currVertPos); vertices[i*longLines + j + 1].pos.y = XMVectorGetY(currVertPos); vertices[i*longLines + j + 1].pos.z = XMVectorGetZ(currVertPos); } } vertices[NumSphereVertices - 1].pos.x = 0.0f; vertices[NumSphereVertices - 1].pos.y = 0.0f; vertices[NumSphereVertices - 1].pos.z = -1.0f; D3D11_BUFFER_DESC vertexBufferDesc; ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc)); vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT; vertexBufferDesc.ByteWidth = sizeof(Vertex)* NumSphereVertices; vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = 0; vertexBufferDesc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA vertexBufferData; ZeroMemory(&vertexBufferData, sizeof(vertexBufferData)); vertexBufferData.pSysMem = &vertices[0]; hr = device->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &sphereVertBuffer); std::vector<DWORD> indices(NumSphereFaces * 3); int k = 0; for (DWORD l = 0; l < longLines - 1; ++l) { indices[k] = 0; indices[k + 1] = l + 1; indices[k + 2] = l + 2; k += 3; } indices[k] = 0; indices[k + 1] = longLines; indices[k + 2] = 1; k += 3; for (DWORD i = 0; i < latLines - 3; ++i) { for (DWORD j = 0; j < longLines - 1; ++j) { indices[k] = i*longLines + j + 1; indices[k + 1] = i*longLines + j + 2; indices[k + 2] = (i + 1)*longLines + j + 1; indices[k + 3] = (i + 1)*longLines + j + 1; indices[k + 4] = i*longLines + j + 2; indices[k + 5] = (i + 1)*longLines + j + 2; k += 6; // next quad } indices[k] = (i*longLines) + longLines; indices[k + 1] = (i*longLines) + 1; indices[k + 2] = ((i + 1)*longLines) + longLines; indices[k + 3] = ((i + 1)*longLines) + longLines; indices[k + 4] = (i*longLines) + 1; indices[k + 5] = ((i + 1)*longLines) + 1; k += 6; } for (DWORD l = 0; l < longLines - 1; ++l) { indices[k] = NumSphereVertices - 1; indices[k + 1] = (NumSphereVertices - 1) - (l + 1); indices[k + 2] = (NumSphereVertices - 1) - (l + 2); k += 3; } indices[k] = NumSphereVertices - 1; indices[k + 1] = (NumSphereVertices - 1) - longLines; indices[k + 2] = NumSphereVertices - 2; D3D11_BUFFER_DESC indexBufferDesc; ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc)); indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; indexBufferDesc.ByteWidth = sizeof(DWORD)* NumSphereFaces * 3; indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; indexBufferDesc.CPUAccessFlags = 0; indexBufferDesc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA iinitData; iinitData.pSysMem = &indices[0]; device->CreateBuffer(&indexBufferDesc, &iinitData, &sphereIndexBuffer); }