📄 demo.cpp
字号:
processInput();
// animate
float camFov = D3DX_PI * 0.25f;
if( mBenchMode || mAnimate ) {
float sunTheta;
mCameraAnim->animate( relTime, camFov, sunTheta );
mSun.setParams( sunTheta, mSun.getPhi(), mSun.getIntensity() );
}
mSunColorDivBetaSum = mSun.getColorMulIntensity();
mSunColorDivBetaSum.x *= mAtmosphere.getMulInvBetaRayMieSum().x;
mSunColorDivBetaSum.y *= mAtmosphere.getMulInvBetaRayMieSum().y;
mSunColorDivBetaSum.z *= mAtmosphere.getMulInvBetaRayMieSum().z;
// quad offset
CD3DDevice& dx = CD3DDevice::getInstance();
float pixX = 1.0f / dx.getBackBufferWidth();
float pixY = 1.0f / dx.getBackBufferHeight();
mQuadOffset.set( pixX * 0.5f, -pixY * 0.5f, 0.0f, 0.0f );
dx.getDevice().SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
// light dir from sun
mLightDirNeg = mSun.getDirection();
// move clouds
/*
for( int c = 0; c < mCloudMeshes.size(); ++c ) {
SMatrix4x4& m = mCloudMeshes[c]->mMatrix;
SVector3& o = m.getOrigin();
SVector3 v;
v.x = -10.0f + (170 - o.y) * 0.20f;
v.y = 0.0f;
v.z = -2.0f + (170 - o.y) * 0.02f;
v *= mElapsedTime;
o += v;
if( o.x > 400 ) o.x = -400;
else if( o.x < -400 ) o.x = 400;
if( o.z > 400 ) o.z = -400;
else if( o.z < -400 ) o.z = 400;
}
*/
// shadow map
renderShadowMap();
// camera
CRenderCamera& camera = G_RENDERCTX->getCamera();
SMatrix4x4 proj;
float aspect = dx.getBackBufferAspect();
D3DXMatrixPerspectiveFovLH( &proj, camFov, aspect, 0.1f, 1200.0f );
camera.setCameraMatrix( mMatCamera );
camera.setProjectionMatrix( proj );
// lake reflection
renderLakeRefl();
// camera
camera.setCameraMatrix( mMatCamera );
CProjector::computeTextureProjection( mMatCamera, mMatTexProj );
SVector3 lookDir = camera.getCameraMatrix().getAxisZ();
lookDir.y = 0.0f;
lookDir.normalize();
float phi = atan2f( lookDir.z, lookDir.x );
mBleedOffsetX = -phi/(camFov*aspect);
const float bleedVDist = 50.0f;
SVector3 target = camera.getCameraMatrix().getOrigin() + camera.getCameraMatrix().getAxisZ() * bleedVDist;
mBleedOffsetY = -target.y / (bleedVDist * tanf(camFov));
// base
renderBase();
dx.setZStencil( NULL );
// build small RT
computeSmallRT();
//// RGB->HSV
//fullscreenPass( RID_QUANTIZED, *mQuadRGB2HSV );
// compute bleeds
fullscreenPass( RID_BLEEDACC, *mQuadBleed );
//// back to RGB
//fullscreenPass( RID_FIXEDRT512, *mQuadHSV2RGB );
// detect edges
fullscreenPass( RID_EDGES, *mQuadEdges );
// final composite
dx.sceneBegin();
dx.setDefaultRenderTarget();
G_RENDERCTX->directBegin();
G_RENDERCTX->directRender( *mQuadFinal );
G_RENDERCTX->directEnd();
// some text
dx.resetCachedState();
CD3DFont& font = getFont();
char buf[300];
if( mBenchMode ) {
D3DCOLOR textColor = 0xFFC00000;
sprintf( buf, "BENCHMARK MODE. %ix%i", mBackBuffer.Width, mBackBuffer.Height );
font.drawText( 5, 5+16*0, textColor, buf );
if( !skipElapsed ) {
font.drawText( 5, 5+16*1, textColor, "WARMING UP..." );
} else if( mBenchOver ) {
sprintf( buf, "BENCHMARK OVER. SCORE %i", mRenderedFrames );
font.drawText( 5, 5+16*1, textColor, buf );
} else {
sprintf( buf, "%i%% completed", (int)(relTime*100.0) );
font.drawText( 5, 5+16*1, textColor, buf );
}
} else {
const CRenderStats& stats = dx.getStats();
D3DCOLOR textColor = 0xA0101010;
font.drawText( 5, 5+16*0, textColor, mFrameStats );
font.drawText( 5, 5+16*1, textColor, mDeviceStats );
char buf[200];
sprintf( buf,
"%.1f Mprims/s; %i DI/DIPs; %i RTchanges; %.1f Kverts; %.1f Kprims",
(stats.getPrimsRendered() * mFPS) / 1000000.0f,
stats.getDrawCalls(),
stats.changes.renderTarget,
stats.getVerticesRendered() / 1000.0f,
stats.getPrimsRendered() / 1000.0f );
font.drawText( 5, 5+16*2, textColor, buf );
}
dx.sceneEnd();
if( !mBenchOver )
++mRenderedFrames;
}
void CDemo::justRenderBaseNoLakes( eRenderMode mode, int terrainLod )
{
CD3DDevice& dx = CD3DDevice::getInstance();
mTerrain->render( terrainLod, mode );
if( mode != NORMALZ )
mSky->render();
// clouds
assert( !mCloudMeshes.empty() );
for( int i = 0; i < mCloudMeshes.size(); ++i )
mCloudMeshes[i]->render( mode );
// static meshes
renderStaticMeshes( mode );
}
void CDemo::renderBase()
{
CD3DDevice& dx = CD3DDevice::getInstance();
bool haveMRT = (dx.getMRTCount() >= 2);
if( !mUseMRT )
haveMRT = false;
// clear color for normal/z to match negative light direction
D3DXCOLOR clearColor;
clearColor.r = (mLightDirNeg.x + 1.0f) * 0.5f;
clearColor.g = (mLightDirNeg.y + 1.0f) * 0.5f;
clearColor.b = (mLightDirNeg.z + 1.0f) * 0.5f;
clearColor.a = 1.0f;
dx.getDevice().SetRenderState( D3DRS_FILLMODE, mWireframe ? D3DFILL_WIREFRAME : D3DFILL_SOLID );
dx.setDefaultZStencil();
dx.setRenderTarget( RGET_S_SURF(RID_BASERT), 0 );
if( haveMRT ) {
// set normal/Z RT1
dx.setRenderTarget( RGET_S_SURF(RID_NORMALZ), 1 );
dx.clearTargets( true, true, false, clearColor, 1.0f, 0L );
dx.sceneBegin();
justRenderBaseNoLakes( BASE, 0 );
renderWater( BASE );
G_RENDERCTX->perform();
dx.setRenderTarget( NULL, 1 );
dx.sceneEnd();
} else {
// fallback to separate passes
// color pass
dx.clearTargets( false, true, false, clearColor, 1.0f, 0L );
dx.sceneBegin();
justRenderBaseNoLakes( COLOR, 0 );
renderWater( COLOR );
G_RENDERCTX->perform();
dx.sceneEnd();
// normal/Z pass
dx.setRenderTarget( RGET_S_SURF(RID_NORMALZ), 0 );
//dx.setRenderTarget( RGET_S_SURF(RID_BASERT), 0 );
dx.clearTargets( true, true, false, clearColor/*0xFF000000*/, 1.0f, 0L );
dx.sceneBegin();
justRenderBaseNoLakes( NORMALZ, 0 );
renderWater( NORMALZ );
G_RENDERCTX->perform();
dx.sceneEnd();
}
dx.getDevice().SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
}
void CDemo::renderWater( eRenderMode mode )
{
//CD3DDevice::getInstance().getDevice().SetFVF( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 );
assert( !mWaterMeshes.empty() );
int n = mWaterMeshes.size();
for( int i = 0; i < n; ++i )
mWaterMeshes[i]->render( mode );
}
void CDemo::renderStaticMeshes( eRenderMode mode )
{
//CD3DDevice::getInstance().getDevice().SetFVF( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 );
assert( !mSimpleMeshes.empty() );
for( int i = 0; i < mSimpleMeshes.size(); ++i )
mSimpleMeshes[i]->render( mode );
}
void CDemo::renderShadowMap()
{
CRenderCamera& camera = G_RENDERCTX->getCamera();
CD3DDevice& dx = CD3DDevice::getInstance();
//
// setup shadow map transform params
const float SHADOW_CENTER_FWD = 100.0f;
const float SHADOW_CENTER_Y = 40.0f;
const float SHADOW_EYE_DIST = 260.0f;
const float SHADOW_REGION = 300.0f;
SVector3 shadowCenter = mMatCamera.getOrigin() + mMatCamera.getAxisZ() * SHADOW_CENTER_FWD;
shadowCenter.y = SHADOW_CENTER_Y;
SVector3 shadowEye = shadowCenter + mLightDirNeg * SHADOW_EYE_DIST;
// camera matrix
SMatrix4x4 matCam;
matCam.identify();
matCam.getOrigin() = shadowEye;
matCam.getAxisZ() = -mLightDirNeg;
matCam.getAxisY().set(0,1,0);
matCam.getAxisX() = matCam.getAxisY().cross( matCam.getAxisZ() ).getNormalized();
matCam.getAxisY() = matCam.getAxisZ().cross( matCam.getAxisX() ).getNormalized();
// now, set camera origin into "quantized" grid on the camera plane, so as we move,
// the texels of the shadowmap don't fiddle
// project point (0,0,0) into camera space. we could do this with view matrix,
// but that would require inversion, and one more inversion later (when we'll adjust the
// camera matrix)
SVector3 line = -shadowEye;
float projX = matCam.getAxisX().dot( line );
float projY = matCam.getAxisY().dot( line );
float projZ = matCam.getAxisZ().dot( line );
const float TEXEL_QUANTIZE = SHADOW_REGION / (SHADOW_MAP_SIZE-2); // one pixel border
const float modX = fmodf( projX, TEXEL_QUANTIZE );
const float modY = fmodf( projY, TEXEL_QUANTIZE );
const float modZ = fmodf( projZ, TEXEL_QUANTIZE );
projX -= modX;
projY -= modY;
projZ -= modZ;
SVector3 adjOrigin = matCam.getOrigin();
adjOrigin += matCam.getAxisX() * projX;
adjOrigin += matCam.getAxisY() * projY;
adjOrigin += matCam.getAxisZ() * projZ;
matCam.getOrigin() -= adjOrigin;
camera.setCameraMatrix( matCam );
SMatrix4x4 matProj;
D3DXMatrixOrthoLH( &matProj, SHADOW_REGION, SHADOW_REGION, 0.1f, SHADOW_EYE_DIST*2.0f );
camera.setProjectionMatrix( matProj );
// texture adjustment matrix
// jitter 4 samples
float fC1 = -0.1f / SHADOW_MAP_SIZE;
float fC2 = 0.9f / SHADOW_MAP_SIZE;
SMatrix4x4 matTexAdj;
matTexAdj.identify();
matTexAdj._11 = 0.5f;
matTexAdj._22 = -0.5f;
matTexAdj._33 = 0.0f;
matTexAdj._43 = 1.0f;
matTexAdj._41 = 0.5f+fC1; matTexAdj._42 = 0.5f+fC1;
mMatProjShadow[0] = camera.getViewProjMatrix() * matTexAdj;
matTexAdj._41 = 0.5f+fC1; matTexAdj._42 = 0.5f+fC2;
mMatProjShadow[1] = camera.getViewProjMatrix() * matTexAdj;
matTexAdj._41 = 0.5f+fC2; matTexAdj._42 = 0.5f+fC1;
mMatProjShadow[2] = camera.getViewProjMatrix() * matTexAdj;
matTexAdj._41 = 0.5f+fC2; matTexAdj._42 = 0.5f+fC2;
mMatProjShadow[3] = camera.getViewProjMatrix() * matTexAdj;
//
// render into shadow RT
dx.setRenderTarget( RGET_S_SURF(RID_SHADOWMAP), 0 );
dx.setZStencil( NULL );
dx.clearTargets( true, false, false, 0xFFffffff, 1.0f, 0L );
dx.sceneBegin();
D3DVIEWPORT9 vp;
vp.X = vp.Y = 1;
vp.Height = vp.Width = SHADOW_MAP_SIZE-2;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
dx.getDevice().SetViewport( &vp );
renderStaticMeshes( SHADOW );
G_RENDERCTX->perform();
dx.sceneEnd();
}
void CDemo::renderLakeRefl()
{
CRenderCamera& camera = G_RENDERCTX->getCamera();
CD3DDevice& dx = CD3DDevice::getInstance();
//
// find nearest lake to the viewer
CWaterMesh* lake = 0;
float minDistSq = 1.0e10f;
int nlakes = mWaterMeshes.size();
for( int i = 0; i < nlakes; ++i ) {
CWaterMesh* l = mWaterMeshes[i];
if( l->mAABB.frustumCull( l->mMatrix, camera.getViewProjMatrix() ) )
continue;
SVector3 v = l->mMatrix.getOrigin() - camera.getCameraMatrix().getOrigin();
float distSq = v.lengthSq();
if( distSq < minDistSq ) {
minDistSq = distSq;
lake = l;
}
}
if( !lake )
return;
//
// find lake's XZ plane, reflect camera, clip plane etc.
const SMatrix4x4& lakeMat = lake->mMatrix;
SPlane lakePlane( lakeMat.getOrigin() + SVector3(0,0.5f,0), lakeMat.getAxisY() );
SMatrix4x4 reflectMat;
D3DXMatrixReflect( &reflectMat, &lakePlane );
SMatrix4x4 matCam;
matCam = camera.getCameraMatrix() * reflectMat;
camera.setCameraMatrix( matCam );
SMatrix4x4 matFoo = camera.getViewProjMatrix();
matFoo.invert();
matFoo.transpose();
SPlane clipPlane;
D3DXPlaneTransform( &clipPlane, &lakePlane, &matFoo );
dx.getDevice().SetClipPlane( 0, clipPlane );
//
// reverse culling, enable clip plane
dx.getDevice().SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
dx.getDevice().SetRenderState( D3DRS_CLIPPLANEENABLE, D3DCLIPPLANE0 );
//
// reflection RT
dx.setRenderTarget( RGET_S_SURF(RID_LAKEREFL), 0 );
dx.setZStencil( RGET_S_SURF(RID_LAKEREFLZ) );
dx.clearTargets( false, true, false, 0xFFffffff, 1.0f, 0L );
dx.sceneBegin();
justRenderBaseNoLakes( COLOR, 3 );
G_RENDERCTX->perform();
dx.sceneEnd();
//
// restore culling, disable clip planes
dx.getDevice().SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
dx.getDevice().SetRenderState( D3DRS_CLIPPLANEENABLE, 0 );
}
void CDemo::computeSmallRT()
{
CD3DDevice& dx = CD3DDevice::getInstance();
IDirect3DSurface9* rtBig = RGET_S_SURF(RID_BASERT)->getObject();
IDirect3DSurface9* rtSmall = RGET_S_SURF(RID_FIXEDRT512)->getObject();
HRESULT hr = dx.getDevice().StretchRect( rtBig, 0, rtSmall, 0, D3DTEXF_NONE );
}
void CDemo::fullscreenPass( const char* renderTarget, CQuadMesh& quad )
{
CD3DDevice& dx = CD3DDevice::getInstance();
dx.setRenderTarget( RGET_S_SURF(renderTarget), 0 );
dx.sceneBegin();
G_RENDERCTX->directBegin();
G_RENDERCTX->directRender( quad );
G_RENDERCTX->directEnd();
dx.sceneEnd();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -