#include "RenderQueue.h" #include "SceneEntity.h" #include "Geometry.h" #include "Texture.h" #include "Material.h" #include "Camera.h" #include "Shape.h" #include "RenderState.h" #include "Transform3.h" using namespace std; namespace CHCDemoEngine { RenderQueue::RenderQueue(): mState(NULL), mNumEntries(0) { } RenderQueue::RenderQueue(RenderState *state): mState(state), mNumEntries(0) { } RenderQueue::~RenderQueue() { for (size_t i = 0; i < mBuckets.size(); ++ i) { DEL_PTR(mBuckets[i]); } } bool RenderQueue::FitsInBucket(Shape *shape, size_t idx) const { Technique *tech = shape->GetMaterial()->GetTechnique(mState->GetRenderTechnique()); // test if entity belongs to this bucket if (tech->IsAlphaTestEnabled() != mBuckets[idx]->mAlphaTestEnabled) { return false; } if (tech->IsCullFaceEnabled() != mBuckets[idx]->mCullFaceEnabled) { return false; } if (tech->IsColorWriteEnabled() != mBuckets[idx]->mColorWriteEnabled) { return false; } if (tech->IsLightingEnabled() != mBuckets[idx]->mLightingEnabled) { return false; } if (tech->IsDepthWriteEnabled() != mBuckets[idx]->mDepthWriteEnabled) { return false; } const bool hasTexture = (tech->GetTexture() != NULL); if (hasTexture != mBuckets[idx]->mHasTexture) { return false; } if (hasTexture) { if (tech->GetTexture()->GetWidth() != mBuckets[idx]->mTexWidth) { return false; } if (tech->GetTexture()->GetHeight() != mBuckets[idx]->mTexHeight) {return false; } if (tech->GetTexture()->GetFormat() != mBuckets[idx]->mTexFormat) { return false; } } //if (!tech->GetFragmentProgram() && mBuckets[idx]->mHasFragmentProgram) { return false; } //if (!tech->GetVertexProgram() && mBuckets[idx]->mHasVertexProgram) { return false; } if (tech->GetFragmentProgram() != mBuckets[idx]->mFragmentProgram) { return false; } if (tech->GetVertexProgram() != mBuckets[idx]->mVertexProgram) { return false; } return true; } void RenderQueue::Enqueue(SceneEntity *entity) { ShapeContainer::iterator sit, sit_end; entity->GetCurrentLODLevel(sit, sit_end); for (; sit != sit_end; ++ sit) { Enqueue(*sit, entity); } } void RenderQueue::Enqueue(Shape *shape, SceneEntity *containingEnt) { Technique *tech = shape->GetMaterial()->GetTechnique(mState->GetRenderTechnique()); RenderQueueBucket *bucket = tech->mRenderQueueBucket; ++ mNumEntries; if (!bucket) { bool bucketFound = false; size_t i = 0; for (; i < mBuckets.size(); ++ i) { if (bucketFound = FitsInBucket(shape, i)) break; } // create new bucket if (!bucketFound) { RenderQueueBucket *bucket = new RenderQueueBucket(); //bucket->mMinDistance = -1; bucket->mAlphaTestEnabled = tech->IsAlphaTestEnabled(); bucket->mCullFaceEnabled = tech->IsCullFaceEnabled(); bucket->mColorWriteEnabled = tech->IsColorWriteEnabled(); bucket->mLightingEnabled = tech->IsLightingEnabled(); bucket->mDepthWriteEnabled = tech->IsDepthWriteEnabled(); Texture *tex = tech->GetTexture(); if (tex != NULL) { bucket->mHasTexture = true; bucket->mTexWidth = tex->GetWidth(); bucket->mTexHeight = tex->GetHeight(); bucket->mTexFormat = tex->GetFormat(); } else { bucket->mHasTexture = false; bucket->mTexWidth = 0; bucket->mTexHeight = 0; bucket->mTexFormat = 0; } // bucket->mHasVertexProgram = (tech->GetVertexProgram() != NULL); // bucket->mHasFragmentProgram = (tech->GetFragmentProgram() != NULL); bucket->mVertexProgram = tech->GetVertexProgram(); bucket->mFragmentProgram = tech->GetFragmentProgram(); mBuckets.push_back(bucket); //cout << "increased #buckets to " << (int)mBuckets.size() << endl; } bucket = mBuckets[i]; tech->mRenderQueueBucket = bucket; } if (bucket->IsEmpty()) { // add bucket to the list of currently active buckets that will be rendered // assume that the incoming nodes are ordered by distance // => active buckets are sorted by distance mActiveBuckets.push_back(bucket); } bucket->mShapes.push_back(ShapePair(shape, containingEnt)); } void RenderQueue::Clear() { for (size_t i = 0; i < mActiveBuckets.size(); ++ i) { mActiveBuckets[i]->mShapes.clear(); } mNumEntries = 0; mActiveBuckets.clear(); } void RenderQueue::SetRenderState(RenderState *state) { mState = state; } void RenderQueue::Render() { // render all buckets for (size_t i = 0; i < mActiveBuckets.size(); ++ i) { ShapePairArray::const_iterator sit, sit_end = mActiveBuckets[i]->mShapes.end(); for (sit = mActiveBuckets[i]->mShapes.begin(); sit != sit_end; ++ sit) { ShapePair s = *sit; Shape *shape = s.first; SceneEntity *ent = s.second; if (ent) ent->Prepare(mState); shape->Render(mState, ent); if (ent) ent->GetTransform()->Unload(mState); } } //cout << "active: " << (int)mActiveBuckets.size() << endl; } void RenderQueue::Apply() { Render(); Clear(); } }