Hello everybody,
I work on water reflection on my project. And I have some problems with HLSL code.
My water work with many primitives and work like a large plane with coordinates.
I cannot found the right way to make an mirror of the view and use it with my water rendering.
D3DXMATRIX matTextTransformWater // Represent the texture matrix of my water.
float m_fWaterTextCoordBase // Represent the size of the texture.
LPDIRECT3DTEXTURE9 water // Represent the texture of my water.
Part of Texture size calculation:
D3DXMatrixScaling(&matTexTransformWater, m_fWaterTexCoordBase, -m_fWaterTexCoordBase, 0.0f); D3DXMatrixMultiply(&matTexTransformWater, &m_matViewInverse, &matTexTransformWater);
Part of setting texture with matrix:
STATEMANAGER.SetTexture(0, water); STATEMANAGER.SaveTransform(D3DTS_TEXTURE0, &matTexTransformWater);
Part of get Reflection Texture map:
void CMapOutdoor::MapTextureReflection() { D3DXMATRIX oldView; // Ancienne vue. D3DXMATRIX oldWorld; // Ancien monde. D3DXMATRIX oldProj; // Ancienne projection. STATEMANAGER.GetTransform(D3DTS_VIEW, &oldView); // récupération de la vue. STATEMANAGER.GetTransform(D3DTS_WORLD, &oldWorld); // récupération du monde. STATEMANAGER.GetTransform(D3DTS_PROJECTION, &oldProj); // récupération de la projection. STATEMANAGER.SetTransform(D3DTS_VIEW, &ReflectionView()); LPDIRECT3DSURFACE9 pBackBuffer; if (SUCCEEDED(STATEMANAGER.m_lpD3DDev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer))) { D3DVIEWPORT9 viewPort; STATEMANAGER.m_lpD3DDev->GetViewport(&viewPort); D3DXCreateTexture(STATEMANAGER.m_lpD3DDev, viewPort.Width, viewPort.Height, D3DX_DEFAULT, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &TextureReflectionMap); LPDIRECT3DSURFACE9 pTexSurface; TextureReflectionMap->GetSurfaceLevel(0, &pTexSurface); STATEMANAGER.m_lpD3DDev->StretchRect(pBackBuffer, NULL, pTexSurface, NULL, D3DTEXF_NONE); pBackBuffer->Release(); pTexSurface->Release(); } STATEMANAGER.SetTransform(D3DTS_VIEW, &oldView); STATEMANAGER.SetTransform(D3DTS_WORLD, &oldWorld); STATEMANAGER.SetTransform(D3DTS_PROJECTION, &oldProj); } D3DXMATRIX CMapOutdoor::ReflectedCameraPositionMatrix() { D3DXMATRIX CameraReflected; D3DXMatrixTranslation(&CameraReflected, ReflectedCameraPositionVector3().x, ReflectedCameraPositionVector3().y, ReflectedCameraPositionVector3().z); return CameraReflected; } D3DXVECTOR3 CMapOutdoor::ReflectedCameraPositionVector3() { D3DXVECTOR3 CameraReflectedPosition; CCamera * pCurrentCamera = CCameraManager::Instance().GetCurrentCamera(); CameraReflectedPosition = pCurrentCamera->GetTarget(); CameraReflectedPosition.z = -CameraReflectedPosition.z; return CameraReflectedPosition; } D3DXMATRIX CMapOutdoor::ReflectionView() { CCamera * pCurrentCamera = CCameraManager::Instance().GetCurrentCamera(); D3DXVECTOR3 CameraReflectedPosition; D3DXMATRIX ReflectionMatrix; CameraReflectedPosition = ReflectedCameraPositionVector3(); D3DXVECTOR3 CameraLookTowards(pCurrentCamera->GetTarget().x, pCurrentCamera->GetTarget().y, pCurrentCamera->GetTarget().z); CameraLookTowards += CameraReflectedPosition; D3DXVECTOR3 vectorUP(0.0f, 0.0f, 1.0f); //D3DXMatrixAffineTransformation(&ReflectionMatrix, &CameraLookTowards, &CameraReflectedPosition, &vectorUP); D3DXMatrixLookAtLH(&ReflectionMatrix, &CameraLookTowards, &CameraReflectedPosition, &vectorUP); return ReflectionMatrix; }
Part of HLSL code:
float4x4 World; float4x4 View; float4x4 Projection; float3 CameraPosition; float4x4 ReflectionView; float ViewPortWidth; float ViewPortHeight; texture ReflectionMap; sampler2D ReflectionSampler = sampler_state { texture = <ReflectionMap>; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; AddressU = Clamp; AddressV = Clamp; }; // TODO: add effect parameters here. float2 postProjToScreen(float4 position) { float2 screenPos = position.xy / position.w; return 0.5f * (float2(screenPos.x, -screenPos.y) + 1); } float2 halfPixel() { return 0.5f / float2(ViewPortWidth, ViewPortHeight); } struct VertexShaderInput { float4 Position : POSITION0; }; struct VertexShaderOutput { float4 Position : POSITION0; float4 ReflectionPosition : TEXCOORD1; // TODO: add vertex shader outputs such as colors and texture // coordinates here. These values will automatically be interpolated // over the triangle, and provided as input to your pixel shader. }; VertexShaderOutput VertexShaderFunction(VertexShaderInput input) { VertexShaderOutput output; float4 worldPosition = mul(input.Position, World); float4 viewPosition = mul(worldPosition, View); output.Position = mul(viewPosition, Projection); // TODO: add your vertex shader code here. float4x4 Reflected = mul(World, mul(ReflectionView, Projection)); output.ReflectionPosition = mul(input.Position, Reflected); return output; } float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0 { // TODO: add your pixel shader code here. //float2 ReflectionUV = float2(input.ReflectionPosition.x/input.ReflectionPosition.w/2.0f + 0.5f, input.ReflectionPosition.y/input.ReflectionPosition.w/2.0f + 0.5f); float2 ReflectionUV = postProjToScreen(input.ReflectionPosition) + halfPixel(); float3 Reflection = tex2D(ReflectionSampler, ReflectionUV); return float4(Reflection, 1); } technique Technique1 { pass Pass1 { // TODO: set renderstates here. VertexShader = compile vs_2_0 VertexShaderFunction(); PixelShader = compile ps_2_0 PixelShaderFunction(); } }
Part of Rendering primitive with HLSL initialization:
if (EffetEau) // If water hlsl file is correctly readed. { // Variable D3DVIEWPORT9 viewport; D3DXMATRIX oldWorld; D3DXMATRIX oldView; D3DXMATRIX oldProj; STATEMANAGER.GetTransform(D3DTS_WORLD, &oldWorld); STATEMANAGER.GetTransform(D3DTS_VIEW, &oldView); STATEMANAGER.GetTransform(D3DTS_PROJECTION, &oldProj); D3DXMATRIX invertWorld; D3DXMATRIX transposeWorld; D3DXMatrixInverse(&invertWorld, 0, &oldWorld); D3DXMatrixTranspose(&transposeWorld, &invertWorld); STATEMANAGER.m_lpD3DDev->GetViewport(&viewport); // Handle de l'effet; D3DXHANDLE Technique = matEauEffet->GetTechniqueByName("Technique1"); D3DXHANDLE World = matEauEffet->GetParameterByName(0, "World"); D3DXHANDLE View = matEauEffet->GetParameterByName(0, "View"); D3DXHANDLE Proj = matEauEffet->GetParameterByName(0, "Projection"); D3DXHANDLE CameraPosition = matEauEffet->GetParameterByName(0, "CameraPosition"); D3DXHANDLE ReflectionView = matEauEffet->GetParameterByName(0, "ReflectionView"); D3DXHANDLE ViewPortWidth = matEauEffet->GetParameterByName(0, "ViewPortWidth"); D3DXHANDLE ViewPortHeight = matEauEffet->GetParameterByName(0, "ViewPortHeight"); D3DXHANDLE ReflectionMap = matEauEffet->GetParameterByName(0, "ReflectionMap"); HRESULT hr; hr = matEauEffet->SetMatrix(View, &oldView); if (FAILED(hr)) { TraceError("Erreur Effet View"); } hr = matEauEffet->SetMatrix(World, &oldWorld); if (FAILED(hr)) { TraceError("Erreur Effet World"); } hr = matEauEffet->SetMatrix(Proj, &oldProj); if (FAILED(hr)) { TraceError("Erreur Effet Proj"); } hr = matEauEffet->SetValue(CameraPosition, &CCameraManager::Instance().GetCurrentCamera()->GetView(), sizeof(D3DXVECTOR3)); if (FAILED(hr)) { TraceError("Erreur Effet CameraPosition"); } hr = matEauEffet->SetMatrix(ReflectionView, &invertWorld); if (FAILED(hr)) { TraceError("Erreur Effet ReflectionView"); } hr = matEauEffet->SetFloat(ViewPortWidth, viewport.Width); if (FAILED(hr)) { TraceError("Erreur Effet Viewport Height"); } hr = matEauEffet->SetFloat(ViewPortHeight, viewport.Height); if (FAILED(hr)) { TraceError("Erreur Effet Viewport Width"); } hr = matEauEffet->SetTexture(ReflectionMap, TextureReflectionMap); if (FAILED(hr)) { TraceError("Erreur Effet Reflection Texture"); } hr = matEauEffet->SetTechnique(Technique); if (FAILED(hr)) { TraceError("Erreur Effet Technique"); } UINT cPasses; matEauEffet->Begin(&cPasses, 0); for (int k = 0; k < cPasses; k++) { matEauEffet->BeginPass(k); matEauEffet->CommitChanges(); STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLELIST, 0, uPriCount); matEauEffet->EndPass(); } matEauEffet->End(); } else { STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLELIST, 0, uPriCount); }
The result: