void DistantLand::renderReflectedStatics(const D3DXMATRIX *view, const D3DXMATRIX *proj) { // Select appropriate static clipping distance D3DXMATRIX ds_proj = *proj, ds_viewproj; float zn = 4.0f, zf = Configuration.DL.NearStaticEnd * kCellSize; // Don't draw beyond fully fogged distance; early out if frustum is empty zf = std::min(fogEnd, zf); if(zf <= zn) return; // Create a clipping frustum for visibility determination editProjectionZ(&ds_proj, zn, zf); ds_viewproj = (*view) * ds_proj; // Cull sort and draw VisibleSet visReflected; ViewFrustum range_frustum(&ds_viewproj); D3DXVECTOR4 viewsphere(eyePos.x, eyePos.y, eyePos.z, zf); currentWorldSpace->NearStatics->GetVisibleMeshes(range_frustum, viewsphere, visReflected); currentWorldSpace->FarStatics->GetVisibleMeshes(range_frustum, viewsphere, visReflected); currentWorldSpace->VeryFarStatics->GetVisibleMeshes(range_frustum, viewsphere, visReflected); visReflected.SortByState(); device->SetVertexDeclaration(StaticDecl); visReflected.Render(device, effect, effect, &ehTex0, 0, &ehWorld, SIZEOFSTATICVERT); }
void DistantLand::cullGrass(const D3DXMATRIX *view, const D3DXMATRIX *proj) { D3DXMATRIX ds_proj = *proj, ds_viewproj; float zn = 4.0f, zf = 7168.0f; // Don't draw beyond fully fogged distance; early out if frustum is empty if(~Configuration.MGEFlags & EXP_FOG) zf = min(fogEnd, zf); if(zf <= zn) return; // Create a clipping frustum for visibility determination editProjectionZ(&ds_proj, zn, zf); ds_viewproj = (*view) * ds_proj; // Cull and sort ViewFrustum range_frustum(&ds_viewproj); visGrass.RemoveAll(); currentWorldSpace->GrassStatics->GetVisibleMeshesCoarse(range_frustum, visGrass); visGrass.SortByState(); buildGrassInstanceVB(); }
void DistantLand::renderWaterReflection(const D3DXMATRIX *view, const D3DXMATRIX *proj) { DECLARE_MWBRIDGE // Switch to render target RenderTargetSwitcher rtsw(texReflection, surfReflectionZ); device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, horizonCol, 1.0, 0); // Calculate reflected view matrix, mirror plane at water mesh level D3DXMATRIX reflView; D3DXPLANE plane(0, 0, 1.0, -(mwBridge->WaterLevel() - 1.0)); D3DXMatrixReflect(&reflView, &plane); D3DXMatrixMultiply(&reflView, &reflView, view); effect->SetMatrix(ehView, &reflView); // Calculate new projection D3DXMATRIX reflProj = *proj; editProjectionZ(&reflProj, 4.0, Configuration.DL.DrawDist * kCellSize); effect->SetMatrix(ehProj, &reflProj); // Clipping setup D3DXMATRIX clipMat; // Clip geometry on opposite side of water plane plane *= mwBridge->IsUnderwater(eyePos.z) ? -1.0 : 1.0; // If using dynamic ripples, the water level can be lowered by up to 0.5 * waveheight // so move clip plane downwards at the cost of some reflection errors if(Configuration.MGEFlags & DYNAMIC_RIPPLES) plane.d += 0.5 * Configuration.DL.WaterWaveHeight; // Doing inverses separately is a lot more numerically stable D3DXMatrixInverse(&clipMat, 0, &reflView); D3DXMatrixTranspose(&clipMat, &clipMat); D3DXPlaneTransform(&plane, &plane, &clipMat); D3DXMatrixInverse(&clipMat, 0, &reflProj); D3DXMatrixTranspose(&clipMat, &clipMat); D3DXPlaneTransform(&plane, &plane, &clipMat); if(visDistant.size() == 0) { // Workaround for a Direct3D bug with clipping planes, where SetClipPlane // has no effect on the shader pipeline if the last rendered draw call was using // the fixed function pipeline. This is usually covered by distant statics, but // not in compact interiors where all distant statics may be culled. // Provoking a DrawPrimitive with shader here makes the following SetClipPlane work. effect->BeginPass(PASS_WORKAROUND); device->SetVertexDeclaration(WaterDecl); device->SetStreamSource(0, vbFullFrame, 0, 12); device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); effect->EndPass(); } device->SetClipPlane(0, plane); device->SetRenderState(D3DRS_CLIPPLANEENABLE, 1); // Rendering if(mwBridge->IsExterior() && (Configuration.MGEFlags & REFLECTIVE_WATER)) { // Draw land reflection, with opposite culling effect->BeginPass(PASS_RENDERLANDREFL); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); renderDistantLand(effect, &reflView, &reflProj); effect->EndPass(); } if(isDistantCell() && (Configuration.MGEFlags & REFLECT_NEAR)) { // Draw statics reflection, with opposite culling and no dissolve DWORD p = (mwBridge->CellHasWeather() && !mwBridge->IsUnderwater(eyePos.z)) ? PASS_RENDERSTATICSEXTERIOR : PASS_RENDERSTATICSINTERIOR; effect->SetFloat(ehNearViewRange, 0); effect->BeginPass(p); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); renderReflectedStatics(&reflView, &reflProj); effect->EndPass(); effect->SetFloat(ehNearViewRange, nearViewRange); } if((Configuration.MGEFlags & REFLECT_SKY) && !recordSky.empty() && !mwBridge->IsUnderwater(eyePos.z)) { // Draw sky reflection, with opposite culling effect->BeginPass(PASS_RENDERSKY); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); renderReflectedSky(); effect->EndPass(); } // Restore view state device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); effect->SetMatrix(ehView, view); effect->SetMatrix(ehProj, proj); }