Hi all,
I've managed to implement a skybox shader in my d3d engine, which functionally is 'OK'.
Never the less there are a few things I can't figure out yet.
Rendering order;
- I know render the skybox first thing each frame, with zbuffer and zwrite disabled, enabled after draw skybox
- after this I render the scene/ meshes
Clipping;
- when objects reach the far clipping plane, they are clipped inside the skybox.
This sounds logically but doesn't look ok. Here are 2 screenshots:
My questions;
1. would there be an advantage in rendering the skybox after the meshes/ last thing per frame?
I tried it out with zbuffer true and zwrite false. When scaling my skybox x15 (or so) this functionally works, but I don't see the advantage. Enlarging the skybox rather doesn't feel good.
2. what could I with the ugly clipping? I could change the far plane so objects or completely culled or not, instead of 'clipped'. Are make the far plane even farther so you won't notice that much (performance impact?).
Or maybe you have other ideas on this.
Here's the code of my draw skybox function and pseudo code of my renderframe function;
bool CD3dskybox::Render(D3DXVECTOR3 pPlayerPosition, CD3dcam *pCam, LPDIRECT3DDEVICE9 pD3ddev)
{
mSkyBoxMesh.mWorldPos = mPlayerPosition;
mSkyBoxMesh.UpdateWorldMatrix();
D3DXVECTOR3ToFloat3(pPlayerPosition, mPlayerPosition);
if(D3DERR_INVALIDCALL == mSkyBoxEffect->SetTechnique("SkyBoxShader")) return false;
if(D3DERR_INVALIDCALL == mSkyBoxEffect->SetMatrix("ViewProj", &pCam->mMatViewProjection)) return false;
if(D3DERR_INVALIDCALL == mSkyBoxEffect->SetFloatArray("CameraPosition", mPlayerPosition, 3)) return false;
if(D3DERR_INVALIDCALL == mSkyBoxEffect->SetTexture("SkyBoxTexture", mSkyBoxTexture)) return false;
if(D3DERR_INVALIDCALL == mSkyBoxEffect->SetMatrix("World", &mSkyBoxMesh.mMatWorld)) return false;
if(D3D_OK != pD3ddev->SetStreamSource(0, mSkyBoxMesh.mVtxBuffer, 0, mSkyBoxMesh.mVtxSize)) return false;
if(D3D_OK != pD3ddev->SetIndices(mSkyBoxMesh.mFaceBuffer)) return false;
if(D3D_OK != pD3ddev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE)) return false;
if(D3D_OK != pD3ddev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE)) return false;
if(D3D_OK != pD3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW)) return false;
mSkyBoxEffect->Begin(&mNumPasses, 0); // D3DXFX_DONOTSAVESTATE);
for(unsigned int i=0;i<1;++i)
{
mSkyBoxEffect->BeginPass(i);
mSkyBoxMesh.RenderAll(pD3ddev, LIST);
mSkyBoxEffect->EndPass();
}
mSkyBoxEffect->End();
if(D3D_OK != pD3ddev->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE)) return false;
if(D3D_OK != pD3ddev->SetRenderState(D3DRS_ZWRITEENABLE, TRUE)) return false;
if(D3D_OK != pD3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW)) return false;
return true;
}
bool CD3d::RenderFrameV2(CD3dscene *pD3dscene, CD3dcam *pCam)
{
if(!CheckDevice()) { mDeviceLost = true; return true; }
mObjRendered = 0; mAttrRendered = 0;
pCam->Update();
mD3ddev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
mD3ddev->BeginScene();
// SKY BOX; SHADER RENDERING
if(pD3dscene->mSkyBoxInScene)
if(!pD3dscene->mSkyBox.Render(pCam->mPosition, pCam, mD3ddev)) return false;
// WORLD MESHES; SHADER RENDERING
for(ec=0;ec<pD3dscene->mNrEffects;++ec)
{
if(!SetVertexShader(pD3dscene, ec, "BasicShader", pCam)) return false;
pD3dscene->mEffect[ec]->Begin(&pD3dscene->mEffectNumPasses[ec], 0); //D3DXFX_DONOTSAVESTATE);
// loop through all materials, meshes and subobjects, drawprimitives etc.
pD3dscene->mEffect[ec]->End();
}
// FFP rendering
PrintSceneInfo(pCam, mObjRendered, mAttrRendered);
mD3ddev->EndScene();
HRESULT hr = mD3ddev->Present(NULL, NULL, NULL, NULL);
return true;
}