📄 rendercontext.cpp
字号:
// --------------------------------------------------------------------------
// Dingus project - a collection of subsystems for game/graphics applications
// --------------------------------------------------------------------------
#include "stdafx.h"
#include "RenderContext.h"
#include "Renderable.h"
#include "../kernel/D3DDevice.h"
using namespace dingus;
CRenderContext::CRenderContext( CD3DXEffect& globalFx )
: mGlobalEffect( &globalFx ),
mInsideDirect( false ),
mDirectCurrFX( NULL )
{
assert( mGlobalEffect );
mGlobalParams.setEffect( *mGlobalEffect );
// reserve some space in renderables
mRenderables.reserve( 256 );
// add-by-ref view & projection matrices to the global params
mGlobalParams.addMatrix4x4Ref( "mView", mRenderCamera.getViewMatrix() );
mGlobalParams.addMatrix4x4Ref( "mProjection", mRenderCamera.getProjectionMatrix() );
mGlobalParams.addMatrix4x4Ref( "mViewProj", mRenderCamera.getViewProjMatrix() );
mGlobalParams.addVector3Ref( "vEye", mRenderCamera.getCameraMatrix().getOrigin() );
}
// --------------------------------------------------------------------------
void CRenderContext::beforeRendering()
{
TListenerVector::iterator it, itEnd = getListeners().end();
for( it = getListeners().begin(); it != getListeners().end(); ++it ) {
assert( *it );
(*it)->beforeRendering( *this );
}
}
void CRenderContext::afterRendering()
{
TListenerVector::iterator it, itEnd = getListeners().end();
for( it = getListeners().begin(); it != getListeners().end(); ++it ) {
assert( *it );
(*it)->afterRendering( *this );
}
}
// --------------------------------------------------------------------------
//
// Sorter for renderables. Takes care of sort-from-back, inter-effects sort, etc.
struct SRenderableSorter {
const CRenderContext* ctx;
bool operator()( const CRenderable* ra, const CRenderable* rb ) {
assert( ra && rb );
// Just shortcut
if( ra == rb )
return false;
// priority
int apri = ra->getPriority();
int bpri = rb->getPriority();
if( apri != bpri )
return apri < bpri;
const CD3DXEffect* ea = ra->getParams().getEffect();
const CD3DXEffect* eb = rb->getParams().getEffect();
// if effects inter-sort order
// this puts sorted effects last, and orders effects by required
// vertex shader version
if( ea->getSortValue() != eb->getSortValue() ) {
return ea->getSortValue() < eb->getSortValue();
}
// if back-to-front: by distance to camera
bool aback = ea->isBackToFrontSorted();
bool bback = eb->isBackToFrontSorted();
if( aback && bback ) {
const SVector3* aor = ra->getOrigin();
const SVector3* bor = rb->getOrigin();
if( aor && bor ) {
const SVector3& eye = ctx->getCamera().getEye3();
float adist = SVector3(*aor-eye).lengthSq();
float bdist = SVector3(*bor-eye).lengthSq();
// NOTE
// Should be this, but VC seems to generate somewhat buggy
// code - sometimes returns true even if equal. This doesn't
// happen in Debug build... Spent 3 days on this! :(
//return adist > bdist;
return adist - bdist > 0.00001f;
}
// Strange case - should be sorted, but one/both don't supply
// origins. So just order them arbitrarily (by pointers).
return ra < rb;
}
// These cases should be caught in effect's "sort value"
assert( !aback && !bback );
// by effect - just compare pointers :)
if( ea != eb )
return ea < eb;
// by used IB
const CD3DIndexBuffer* iba = ra->getUsedIB();
const CD3DIndexBuffer* ibb = rb->getUsedIB();
if( iba != ibb )
return iba < ibb;
// by used VB
const CD3DVertexBuffer* vba = ra->getUsedVB();
const CD3DVertexBuffer* vbb = rb->getUsedVB();
if( vba != vbb )
return vba < vbb;
// just by pointers...
return ra < rb;
};
};
// --------------------------------------------------------------------------
void CRenderContext::sortRenderables()
{
SRenderableSorter sorter;
sorter.ctx = this;
std::sort( mRenderables.begin(), mRenderables.end(), sorter );
}
void CRenderContext::renderRenderables()
{
CD3DDevice& device = CD3DDevice::getInstance();
//
// turn SWVP off (just in case)
if( device.getVertexProcessing() == CD3DDevice::VP_MIXED )
device.getDevice().SetSoftwareVertexProcessing( false );
// here we have our renderables attached and sorted by (with the exception
// of back-to-front):
// 1. priority,
// 2. need to sort back-to-front (unsorted, then sorted)
// 3. vertex shader req. (in ascending order - none, 1.1, 2.0 etc.)
// 4. effect (in no particular order)
int sz = mRenderables.size();
CD3DXEffect* currFX = NULL;
bool currSWVP = false;
//
// go thru all renderables
TRenderableVector::iterator itR = mRenderables.begin();
TRenderableVector::iterator itEnd = mRenderables.end();
TRenderableVector::iterator itFxStart = itR;
for( ; itR != itEnd; ++itR ) {
CRenderable* rend = *itR;
assert( rend );
CEffectParams& params = rend->getParams();
CD3DXEffect* newFX = params.getEffect();
assert( newFX );
//
// check effect change. if changed, render all renderables of the old effect
if( newFX != currFX ) {
// render all renderables with old fx
if( currFX ) {
assert( currFX );
// begin
int passes = currFX->beginFx();
// all passes
for( int p = 0; p < passes; ++p ) {
currFX->beginPass( p );
// all objects
TRenderableVector::iterator it;
for( it = itFxStart; it != itR; ++it ) {
CRenderable* r = *it;
assert( r );
r->beforeRender( *this );
r->getParams().applyToEffect();
currFX->commitParams();
r->render( *this );
r->afterRender( *this );
}
currFX->endPass();
}
// end old fx
currFX->endFx();
// stats
device.getStats().incEffectChanges();
}
// set new fx
currFX = newFX;
itFxStart = itR;
// check SWVP change
bool newSWVP = newFX->isSoftwareVertexProcessed();
if( newSWVP != currSWVP && device.getVertexProcessing() == CD3DDevice::VP_MIXED ) {
currSWVP = newSWVP;
device.getDevice().SetSoftwareVertexProcessing( newSWVP );
}
}
}
//
// here we have to render all renderables of the last fx
if( currFX ) {
assert( currFX );
// begin
int passes = currFX->beginFx();
// all passes
for( int p = 0; p < passes; ++p ) {
currFX->beginPass( p );
// all objects
TRenderableVector::iterator it;
for( it = itFxStart; it != itEnd; ++it ) {
CRenderable* r = *it;
assert( r );
r->beforeRender( *this );
r->getParams().applyToEffect();
currFX->commitParams();
r->render( *this );
r->afterRender( *this );
}
currFX->endPass();
}
// end old fx
currFX->endFx();
// stats
device.getStats().incEffectChanges();
}
//
// and turn SWVP off
if( device.getVertexProcessing() == CD3DDevice::VP_MIXED )
device.getDevice().SetSoftwareVertexProcessing( false );
}
void CRenderContext::perform()
{
beforeRendering();
CD3DDevice& device = CD3DDevice::getInstance();
IDirect3DDevice9* dx = &device.getDevice();
assert( dx );
// global params and effect
mGlobalParams.applyToEffect();
int passes = mGlobalEffect->beginFx();
mGlobalEffect->beginPass( 0 );
// sort
sortRenderables();
// renderRenderables
renderRenderables();
mGlobalEffect->endPass();
mGlobalEffect->endFx();
afterRendering();
clear();
}
// --------------------------------------------------------------------------
void CRenderContext::directBegin()
{
// turn SWVP off (just in case)
CD3DDevice& device = CD3DDevice::getInstance();
if( device.getVertexProcessing() == CD3DDevice::VP_MIXED )
device.getDevice().SetSoftwareVertexProcessing( false );
assert( !mInsideDirect );
assert( !mDirectCurrFX );
mInsideDirect = true;
mDirectCurrFX = NULL;
mDirectCurrPasses = 0;
// global params and effect
mGlobalParams.applyToEffect();
int passes = mGlobalEffect->beginFx();
mGlobalEffect->beginPass( 0 );
mGlobalEffect->endPass();
}
void CRenderContext::directEnd()
{
assert( mInsideDirect );
if( mDirectCurrFX ) {
// end
mDirectCurrFX->endFx();
}
mInsideDirect = false;
mDirectCurrFX = NULL;
mDirectCurrPasses = 0;
mGlobalEffect->endFx();
// turn SWVP off (just in case)
CD3DDevice& device = CD3DDevice::getInstance();
if( device.getVertexProcessing() == CD3DDevice::VP_MIXED )
device.getDevice().SetSoftwareVertexProcessing( false );
}
void CRenderContext::directRender( CRenderable& r )
{
CD3DXEffect* fx = r.getParams().getEffect();
assert( fx );
// effect changed?
directSetFX( *fx );
// apply renderable params to fx
assert( mDirectCurrFX );
assert( mDirectCurrFX == fx );
r.getParams().applyToEffect();
// renderRenderables all passes
assert( mDirectCurrPasses > 0 );
r.beforeRender( *this );
for( int p = 0; p < mDirectCurrPasses; ++p ) {
mDirectCurrFX->beginPass( p );
r.render( *this );
mDirectCurrFX->endPass();
}
r.afterRender( *this );
}
int CRenderContext::directSetFX( CD3DXEffect& fx )
{
// effect changed?
if( &fx != mDirectCurrFX ) {
CD3DDevice& device = CD3DDevice::getInstance();
// if old was - end it
if( mDirectCurrFX ) {
mDirectCurrFX->endFx();
device.getStats().incEffectChanges();
}
// see HW/SW VP
if( device.getVertexProcessing() == CD3DDevice::VP_MIXED )
device.getDevice().SetSoftwareVertexProcessing( fx.isSoftwareVertexProcessed() );
// begin new one
mDirectCurrFX = &fx;
mDirectCurrPasses = fx.beginFx();
}
return mDirectCurrPasses;
}
void CRenderContext::directFXPassBegin( int pass )
{
mDirectCurrFX->beginPass( pass );
}
void CRenderContext::directFXPassEnd()
{
mDirectCurrFX->endPass();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -