#include "dxstdafx.h" #include ".\ParticleRenderer.h" #include "GameManager.h" #include "SharedResourceTexture.h" ParticleRenderer::ParticleRenderer(void) : Renderer() { this->setRenderPriority(50); this->rendererType |= Renderer::RENDERER_PARTICLE; this->singleParticle = false; } ParticleRenderer::~ParticleRenderer(void) { SAFE_RELEASE( depthTexture ); } void ParticleRenderer::init() { HRESULT hr; this->device = DXUTGetD3DDevice(); this->ParticleEffect = this->myScene->manager->getEffect(GameManager::EFFECT_DEPTHIMP); if(!this->ParticleEffect) { this->ParticleEffect = this->myScene->manager->loadEffect(GameManager::EFFECT_DEPTHIMP, L"shaders/depthImp.obj"); } //Create DepthTexture this->sr = (SharedResourceTexture*) this->myScene->getSharedResource(Scene::SR_TEXTURE_VIEWDEPTH); if(!this->sr) { this->sr = (SharedResourceTexture*) this->myScene->createSharedResource(Scene::SR_TEXTURE_VIEWDEPTH); } this->depthTexture = this->sr->getTexture(); V( this->ParticleEffect->SetTexture("g_txDepthBuffer", this->depthTexture) ); nearPlane = this->myScene->getActiveCamera()->getNearClipping(); farPlane = this->myScene->getActiveCamera()->getFarClipping(); V(this->ParticleEffect->SetFloat("NearPlaneDistance", nearPlane)); V(this->ParticleEffect->SetFloat("FarPlaneMinusNearPlane", farPlane - nearPlane)); V( this->ParticleEffect->CommitChanges() ); this->depthTexture->GetSurfaceLevel(0, &depthSurface); } void ParticleRenderer::render() { if(this->singleParticle) { this->renderSingleParticle(); return; } HRESULT hr; SPTR node = this->myNode.lock(); Node* particleGroup = node.get(); std::list >::iterator it; std::list >* childList; std::vector sortedList; childList = particleGroup->getChildren(); if(childList->size()!=0) { LPD3DXMESH quad = this->myScene->getQuadMesh(); V( this->ParticleEffect->SetMatrix("g_mView", &this->myScene->getViewMatrix()) ); switch(this->myScene->getActivePassId()) { case Scene::PASS_NORMAL: //Render Particles this->device->SetTransform(D3DTS_PROJECTION, &this->myScene->getProjectionMatrix()); UINT cPass; V( this->ParticleEffect->SetTechnique("DepthImposter") ); V( this->ParticleEffect->SetMatrix("g_mProj", &this->myScene->getProjectionMatrix()) ); V( this->ParticleEffect->SetBool("useDepthImposter", this->myScene->useDepthImposter) ); V( this->ParticleEffect->CommitChanges() ); //Sort Sprites by Depth for(it=childList->begin();it!=childList->end();it++) { sortedList.push_back((Sprite*) (*it).get()); } this->cameraPos = this->myScene->getActiveCamera()->getAbsolutePosition(); spriteSortFunction ssf(this->cameraPos); std::sort(sortedList.begin(), sortedList.end(), ssf); this->device->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW); this->device->SetRenderState( D3DRS_LIGHTING, FALSE ); this->device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); this->device->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE); this->device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); this->device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); this->device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); this->device->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); this->device->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); this->device->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); for(UINT i=0; ifirstRendering) { float d = obj->getMinDim(); V( this->ParticleEffect->SetFloat("ParticleSize", d/(farPlane-nearPlane)) ); V( this->ParticleEffect->SetFloat("ReciprocalParticleSize", 1/(d/(farPlane-nearPlane))) ); //World Matrix setzen D3DXMATRIX viewMat; D3DXMATRIX projMat; D3DXMATRIX viewProjMat; viewMat = this->myScene->getViewMatrix(); projMat = this->myScene->getProjectionMatrix(); D3DXMatrixMultiply(&viewProjMat, &viewMat, &projMat); V( this->ParticleEffect->SetMatrix("g_mViewProjection", &viewProjMat) ); V( this->ParticleEffect->SetMatrix("g_mView", &this->myScene->getViewMatrix()) ); float pPos[3]; Vector absPos = obj->getAbsolutePosition(); pPos[0] = absPos.x; pPos[1] = absPos.y; pPos[2] = absPos.z; V( this->ParticleEffect->SetTexture("g_txCurrentTexture", obj->texture) ); V( this->ParticleEffect->SetFloatArray("argb", obj->currentValues, 4) ); V( this->ParticleEffect->SetFloatArray("hWidthHeight", &obj->currentValues[Sprite::KF_HWIDTH], 2) ); V( this->ParticleEffect->SetFloatArray("ParticlePos", pPos, 3) ); //Animation stuff V( this->ParticleEffect->SetBool("animatedSprite", obj->animatedSprite) ); if(obj->animatedSprite) { V( this->ParticleEffect->SetFloat("invNbRows", obj->invRows) ); V( this->ParticleEffect->SetFloat("invNbColumns", obj->invColumns) ); V( this->ParticleEffect->SetInt("nbFrame", obj->activeFrame) ); V( this->ParticleEffect->SetInt("nbColumns", obj->nbColumns) ); V( this->ParticleEffect->SetInt("nbRows", obj->nbRows) ); } V( this->ParticleEffect->CommitChanges() ); // bilinear texture filtering: V( this->device->BeginScene() ); V( this->ParticleEffect->Begin( &cPass, 0 ) ); V( this->ParticleEffect->BeginPass( 0 ) ); quad->DrawSubset(0); V( this->ParticleEffect->EndPass() ); V( this->ParticleEffect->End() ); V( this->device->EndScene() ); } else if(obj->firstRendering) { obj->firstRendering = false; } } //deactivate textures this->device->SetTexture(0, 0); this->device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); this->device->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_TRUE); this->device->SetTransform(D3DTS_PROJECTION, &this->myScene->getIdentityMatrix()); break; } } } void ParticleRenderer::OnLostDevice( void* pUserContext ) { HRESULT hr; this->myScene->manager->printToConsole(" OnLostDevice ParticleRenderer"); SAFE_RELEASE( depthTexture ); V( this->ParticleEffect->OnLostDevice() ); } void ParticleRenderer::OnDestroyDevice( void* pUserContext ) { this->myScene->manager->printToConsole(" OnDestroyDevice ParticleRenderer"); this->myScene->manager->releaseEffect(this->ParticleEffect); this->ParticleEffect = NULL; this->sr = NULL; } HRESULT ParticleRenderer::OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { this->device = pd3dDevice; this->ParticleEffect = this->myScene->manager->getEffect(GameManager::EFFECT_DEPTHIMP); if(!this->ParticleEffect) { this->ParticleEffect = this->myScene->manager->loadEffect(GameManager::EFFECT_DEPTHIMP, L"shaders/depthImp.obj"); } //Create DepthTexture this->sr = (SharedResourceTexture*) this->myScene->getSharedResource(Scene::SR_TEXTURE_VIEWDEPTH); if(!this->sr) { this->sr = (SharedResourceTexture*) this->myScene->createSharedResource(Scene::SR_TEXTURE_VIEWDEPTH); } this->depthTexture = this->sr->getTexture(); return S_OK; } bool ParticleRenderer::isLowerThan(Renderer* renderer) { //Der ParticleRenderer sollte die Sprites intern richtig aufzeichnen return this->getRenderPriority()getRenderPriority(); } bool ParticleRenderer::needsExtraPass() { SPTR node = this->myNode.lock(); ParticleGroup* particleGroup = (ParticleGroup*) node.get(); if(particleGroup->getChildren()->size()!=0) { return true; } for(UINT i=0; iemitterList.size();i++) { if(particleGroup->emitterList.at(i)->isEmitting()) { return true; } } return false; } bool ParticleRenderer::needHeatHazePass() { SPTR node = this->myNode.lock(); ParticleGroup* particleGroup = (ParticleGroup*) node.get(); if(particleGroup->getUseHeatHaze()) { return this->needsExtraPass(); } return false; } void ParticleRenderer::renderHeatHaze() { SPTR node = this->myNode.lock(); Node* particleGroup = node.get(); std::list >::iterator it; std::list >* childList; std::vector sortedList; childList = particleGroup->getChildren(); if(childList->size()!=0) { HRESULT hr; LPD3DXMESH quad = this->myScene->getQuadMesh(); //Render Particles this->device->SetTransform(D3DTS_PROJECTION, &this->myScene->getProjectionMatrix()); UINT cPass; V( this->ParticleEffect->SetTechnique("HeatHaze") ); V( this->ParticleEffect->SetMatrix("g_mProj", &this->myScene->getProjectionMatrix()) ); V( this->ParticleEffect->SetBool("useDepthImposter", this->myScene->useDepthImposter) ); V( this->ParticleEffect->CommitChanges() ); //Sort Sprites by Depth for(it=childList->begin();it!=childList->end();it++) { sortedList.push_back((Sprite*) (*it).get()); } this->cameraPos = this->myScene->getActiveCamera()->getAbsolutePosition(); spriteSortFunction ssf(this->cameraPos); std::sort(sortedList.begin(), sortedList.end(), ssf); for(UINT i=0; igetMinDim(); V( this->ParticleEffect->SetFloat("ParticleSize", d/(farPlane-nearPlane)) ); V( this->ParticleEffect->SetFloat("ReciprocalParticleSize", 1/(d/(farPlane-nearPlane))) ); D3DXMATRIX viewMat; D3DXMATRIX projMat; D3DXMATRIX viewProjMat; viewMat = this->myScene->getViewMatrix(); projMat = this->myScene->getProjectionMatrix(); D3DXMatrixMultiply(&viewProjMat, &viewMat, &projMat); V( this->ParticleEffect->SetMatrix("g_mViewProjection", &viewProjMat) ); V( this->ParticleEffect->SetMatrix("g_mView", &this->myScene->getViewMatrix()) ); if(obj!=NULL) { // bilinear texture filtering: V( this->device->BeginScene() ); V( this->ParticleEffect->Begin( &cPass, 0 ) ); V( this->ParticleEffect->BeginPass( 0 ) ); float pPos[3]; Vector absPos = obj->getAbsolutePosition(); pPos[0] = absPos.x; pPos[1] = absPos.y; pPos[2] = absPos.z; V( this->ParticleEffect->SetTexture("g_txCurrentTexture", obj->texture) ); V( this->ParticleEffect->SetFloatArray("argb", obj->currentValues, 4) ); V( this->ParticleEffect->SetFloatArray("hWidthHeight", &obj->currentValues[Sprite::KF_HWIDTH], 2) ); V( this->ParticleEffect->SetFloatArray("ParticlePos", pPos, 3) ); V( this->ParticleEffect->CommitChanges() ); quad->DrawSubset(0); V( this->ParticleEffect->EndPass() ); V( this->ParticleEffect->End() ); V( this->device->EndScene() ); } } //deactivate textures this->device->SetTexture(0, 0); this->device->SetTransform(D3DTS_PROJECTION, &this->myScene->getIdentityMatrix()); } } void ParticleRenderer::setRenderSingleParticle(bool _singleParticle) { this->singleParticle = _singleParticle; } void ParticleRenderer::renderSingleParticle() { HRESULT hr; SPTR node = this->myNode.lock(); Sprite* obj = (Sprite*) node.get(); LPD3DXMESH quad = this->myScene->getQuadMesh(); V( this->ParticleEffect->SetMatrix("g_mView", &this->myScene->getViewMatrix()) ); switch(this->myScene->getActivePassId()) { case Scene::PASS_NORMAL: //Render Particles this->device->SetTransform(D3DTS_PROJECTION, &this->myScene->getProjectionMatrix()); UINT cPass; V( this->ParticleEffect->SetTechnique("DepthImposter") ); V( this->ParticleEffect->SetMatrix("g_mProj", &this->myScene->getProjectionMatrix()) ); V( this->ParticleEffect->SetBool("useDepthImposter", this->myScene->useDepthImposter) ); V( this->ParticleEffect->CommitChanges() ); this->device->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW); this->device->SetRenderState( D3DRS_LIGHTING, FALSE ); this->device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); this->device->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE); this->device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); this->device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); this->device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); this->device->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); this->device->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); this->device->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); //ReciprokeParticleSize setzen if(obj!=NULL && !obj->firstRendering) { float d = obj->getMinDim(); V( this->ParticleEffect->SetFloat("ParticleSize", d/(farPlane-nearPlane)) ); V( this->ParticleEffect->SetFloat("ReciprocalParticleSize", 1/(d/(farPlane-nearPlane))) ); //World Matrix setzen D3DXMATRIX viewMat; D3DXMATRIX projMat; D3DXMATRIX viewProjMat; viewMat = this->myScene->getViewMatrix(); projMat = this->myScene->getProjectionMatrix(); D3DXMatrixMultiply(&viewProjMat, &viewMat, &projMat); V( this->ParticleEffect->SetMatrix("g_mViewProjection", &viewProjMat) ); V( this->ParticleEffect->SetMatrix("g_mView", &this->myScene->getViewMatrix()) ); float pPos[3]; Vector absPos = obj->getAbsolutePosition(); pPos[0] = absPos.x; pPos[1] = absPos.y; pPos[2] = absPos.z; V( this->ParticleEffect->SetTexture("g_txCurrentTexture", obj->texture) ); V( this->ParticleEffect->SetFloatArray("argb", obj->currentValues, 4) ); V( this->ParticleEffect->SetFloatArray("hWidthHeight", &obj->currentValues[Sprite::KF_HWIDTH], 2) ); V( this->ParticleEffect->SetFloatArray("ParticlePos", pPos, 3) ); //Animation stuff V( this->ParticleEffect->SetBool("animatedSprite", obj->animatedSprite) ); if(obj->animatedSprite) { V( this->ParticleEffect->SetFloat("invNbRows", obj->invRows) ); V( this->ParticleEffect->SetFloat("invNbColumns", obj->invColumns) ); V( this->ParticleEffect->SetInt("nbFrame", obj->activeFrame) ); V( this->ParticleEffect->SetInt("nbColumns", obj->nbColumns) ); V( this->ParticleEffect->SetInt("nbRows", obj->nbRows) ); } V( this->ParticleEffect->CommitChanges() ); // bilinear texture filtering: V( this->device->BeginScene() ); V( this->ParticleEffect->Begin( &cPass, 0 ) ); V( this->ParticleEffect->BeginPass( 0 ) ); quad->DrawSubset(0); V( this->ParticleEffect->EndPass() ); V( this->ParticleEffect->End() ); V( this->device->EndScene() ); } else if(obj->firstRendering) { obj->firstRendering = false; } this->device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); this->device->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_TRUE); this->device->SetTransform(D3DTS_PROJECTION, &this->myScene->getIdentityMatrix()); break; } }