Răsfoiți Sursa

Add support for rendering particles to the glow buffer

LukasPJ 10 ani în urmă
părinte
comite
30a8401d14

+ 8 - 0
Engine/source/T3D/fx/particleEmitter.cpp

@@ -145,6 +145,7 @@ ParticleEmitterData::ParticleEmitterData()
    blendStyle = ParticleRenderInst::BlendUndefined;
    sortParticles = false;
    renderReflection = true;
+   glow = false;
    reverseOrder = false;
    textureName = 0;
    textureHandle = 0;
@@ -289,6 +290,9 @@ void ParticleEmitterData::initPersistFields()
       addField( "renderReflection", TYPEID< bool >(), Offset(renderReflection, ParticleEmitterData),
          "Controls whether particles are rendered onto reflective surfaces like water." );
 
+      addField("glow", TYPEID< bool >(), Offset(glow, ParticleEmitterData),
+         "If true, the particles are rendered to the glow buffer as well.");
+
       //@}
 
    endGroup( "ParticleEmitterData" );
@@ -356,6 +360,7 @@ void ParticleEmitterData::packData(BitStream* stream)
    }
    stream->writeFlag(highResOnly);
    stream->writeFlag(renderReflection);
+   stream->writeFlag(glow);
    stream->writeInt( blendStyle, 4 );
 }
 
@@ -418,6 +423,7 @@ void ParticleEmitterData::unpackData(BitStream* stream)
    }
    highResOnly = stream->readFlag();
    renderReflection = stream->readFlag();
+   glow = stream->readFlag();
    blendStyle = stream->readInt( 4 );
 }
 
@@ -909,6 +915,8 @@ void ParticleEmitter::prepRenderImage(SceneRenderState* state)
 
    ri->blendStyle = mDataBlock->blendStyle;
 
+   ri->glow = mDataBlock->glow;
+
    // use first particle's texture unless there is an emitter texture to override it
    if (mDataBlock->textureHandle)
      ri->diffuseTex = &*(mDataBlock->textureHandle);

+ 1 - 0
Engine/source/T3D/fx/particleEmitter.h

@@ -114,6 +114,7 @@ class ParticleEmitterData : public GameBaseData
    GFXTexHandle          textureHandle;      ///< Emitter texture handle from txrName
    bool                  highResOnly;        ///< This particle system should not use the mixed-resolution particle rendering
    bool                  renderReflection;   ///< Enables this emitter to render into reflection passes.
+   bool glow;                                ///< Renders this emitter into the glow buffer.
 
    bool reload();
 };

+ 40 - 1
Engine/source/renderInstance/renderGlowMgr.cpp

@@ -22,6 +22,7 @@
 
 #include "platform/platform.h"
 #include "renderInstance/renderGlowMgr.h"
+#include "renderInstance/renderParticleMgr.h"
 
 #include "scene/sceneManager.h"
 #include "scene/sceneRenderState.h"
@@ -89,6 +90,9 @@ RenderGlowMgr::RenderGlowMgr()
 {
    notifyType( RenderPassManager::RIT_Decal );
    notifyType( RenderPassManager::RIT_Translucent );
+   notifyType( RenderPassManager::RIT_Particle );
+
+   mParticleRenderMgr = NULL;
 
    mNamedTarget.registerWithName( "glowbuffer" );
    mTargetSizeType = WindowSize;
@@ -122,6 +126,14 @@ void RenderGlowMgr::addElement( RenderInst *inst )
    // manner so we can skip glow in a non-diffuse render pass.
    //if ( !mParentManager->getSceneManager()->getSceneState()->isDiffusePass() )
       //return RenderBinManager::arSkipped;
+   ParticleRenderInst *particleInst = NULL;
+   if(inst->type == RenderPassManager::RIT_Particle)
+      particleInst = static_cast<ParticleRenderInst*>(inst);
+   if(particleInst && particleInst->glow)
+   {
+      internalAddElement(inst);
+      return;
+   }
 
    // Skip it if we don't have a glowing material.
    BaseMatInstance *matInst = getMaterial( inst );
@@ -171,7 +183,31 @@ void RenderGlowMgr::render( SceneRenderState *state )
 
    for( U32 j=0; j<binSize; )
    {
-      MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[j].inst);
+      RenderInst *_ri = mElementList[j].inst;
+      if(_ri->type == RenderPassManager::RIT_Particle)
+      {
+         // Find the particle render manager (if we don't have it)
+         if(mParticleRenderMgr == NULL)
+         {
+            RenderPassManager *rpm = state->getRenderPass();
+            for( U32 i = 0; i < rpm->getManagerCount(); i++ )
+            {
+               RenderBinManager *bin = rpm->getManager(i);
+               if( bin->getRenderInstType() == RenderParticleMgr::RIT_Particles )
+               {
+                  mParticleRenderMgr = reinterpret_cast<RenderParticleMgr *>(bin);
+                  break;
+               }
+            }
+         }
+
+         ParticleRenderInst *ri = static_cast<ParticleRenderInst*>(_ri);
+         mParticleRenderMgr->renderParticle(ri, state);
+         j++;
+         continue;
+      }
+
+      MeshRenderInst *ri = static_cast<MeshRenderInst*>(_ri);
 
       setupSGData( ri, sgData );
 
@@ -191,6 +227,9 @@ void RenderGlowMgr::render( SceneRenderState *state )
          U32 a;
          for( a=j; a<binSize; a++ )
          {
+            if (mElementList[a].inst->type == RenderPassManager::RIT_Particle)
+               break;
+
             MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst);
 
             if ( newPassNeeded( ri, passRI ) )

+ 2 - 1
Engine/source/renderInstance/renderGlowMgr.h

@@ -26,6 +26,7 @@
 #ifndef _TEXTARGETBIN_MGR_H_
 #include "renderInstance/renderTexTargetBinManager.h"
 #endif
+#include <renderInstance/renderParticleMgr.h>
 
 
 class PostEffect;
@@ -82,7 +83,7 @@ protected:
    };
 
    SimObjectPtr<PostEffect> mGlowEffect;
-
+   RenderParticleMgr *mParticleRenderMgr;
 };
 
 

+ 63 - 58
Engine/source/renderInstance/renderParticleMgr.cpp

@@ -399,64 +399,7 @@ void RenderParticleMgr::renderInstance(ParticleRenderInst *ri, SceneRenderState
          mParticleShaderConsts.mShaderConsts->setSafe( mParticleShaderConsts.mModelViewProjSC, *ri->modelViewProj );
       }
 
-      // We want to turn everything into variation on a pre-multiplied alpha blend
-      F32 alphaFactor = 0.0f, alphaScale = 1.0f;
-      switch(ri->blendStyle)
-      {
-         // SrcAlpha, InvSrcAlpha
-      case ParticleRenderInst::BlendNormal:
-         alphaFactor = 1.0f;
-         break;
-
-         // SrcAlpha, One
-      case ParticleRenderInst::BlendAdditive:
-         alphaFactor = 1.0f;
-         alphaScale = 0.0f;
-         break;
-
-         // SrcColor, One
-      case ParticleRenderInst::BlendGreyscale:
-         alphaFactor = -1.0f;
-         alphaScale = 0.0f;
-         break;
-      }
-
-      mParticleShaderConsts.mShaderConsts->setSafe( mParticleShaderConsts.mAlphaFactorSC, alphaFactor );
-      mParticleShaderConsts.mShaderConsts->setSafe( mParticleShaderConsts.mAlphaScaleSC, alphaScale );
-
-      mParticleShaderConsts.mShaderConsts->setSafe( mParticleShaderConsts.mFSModelViewProjSC, *ri->modelViewProj  );
-      mParticleShaderConsts.mShaderConsts->setSafe( mParticleShaderConsts.mOneOverFarSC, 1.0f / state->getFarPlane() );     
-
-      if ( mParticleShaderConsts.mOneOverSoftnessSC->isValid() )
-      {
-         F32 oneOverSoftness = 1.0f;
-         if ( ri->softnessDistance > 0.0f )
-            oneOverSoftness = 1.0f / ( ri->softnessDistance / state->getFarPlane() );
-         mParticleShaderConsts.mShaderConsts->set( mParticleShaderConsts.mOneOverSoftnessSC, oneOverSoftness );
-      }
-
-      GFX->setShader( mParticleShader );
-      GFX->setShaderConstBuffer( mParticleShaderConsts.mShaderConsts );
-
-      GFX->setTexture( 0, ri->diffuseTex );
-
-      // Set up the prepass texture.
-      if ( mParticleShaderConsts.mPrePassTargetParamsSC->isValid() )
-      {
-         GFXTextureObject *texObject = mPrepassTarget ? mPrepassTarget->getTexture(0) : NULL;
-         GFX->setTexture( 1, texObject );
-
-         Point4F rtParams( 0.0f, 0.0f, 1.0f, 1.0f );
-         if ( texObject )
-            ScreenSpace::RenderTargetParameters(texObject->getSize(), mPrepassTarget->getViewport(), rtParams);
-
-         mParticleShaderConsts.mShaderConsts->set( mParticleShaderConsts.mPrePassTargetParamsSC, rtParams );
-      }
-
-      GFX->setPrimitiveBuffer( *ri->primBuff );
-      GFX->setVertexBuffer( *ri->vertBuff );
-
-      GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, ri->count * 4, 0, ri->count * 2 );
+      renderParticle(ri, state);
    }
    else if(ri->systemState == PSS_AwaitingCompositeDraw)
    {
@@ -530,6 +473,68 @@ void RenderParticleMgr::renderInstance(ParticleRenderInst *ri, SceneRenderState
    }
 }
 
+void RenderParticleMgr::renderParticle(ParticleRenderInst* ri, SceneRenderState* state)
+{
+   // We want to turn everything into variation on a pre-multiplied alpha blend
+   F32 alphaFactor = 0.0f, alphaScale = 1.0f;
+   switch(ri->blendStyle)
+   {
+      // SrcAlpha, InvSrcAlpha
+   case ParticleRenderInst::BlendNormal:
+      alphaFactor = 1.0f;
+      break;
+
+      // SrcAlpha, One
+   case ParticleRenderInst::BlendAdditive:
+      alphaFactor = 1.0f;
+      alphaScale = 0.0f;
+      break;
+
+      // SrcColor, One
+   case ParticleRenderInst::BlendGreyscale:
+      alphaFactor = -1.0f;
+      alphaScale = 0.0f;
+      break;
+   }
+
+   mParticleShaderConsts.mShaderConsts->setSafe( mParticleShaderConsts.mAlphaFactorSC, alphaFactor );
+   mParticleShaderConsts.mShaderConsts->setSafe( mParticleShaderConsts.mAlphaScaleSC, alphaScale );
+
+   mParticleShaderConsts.mShaderConsts->setSafe( mParticleShaderConsts.mFSModelViewProjSC, *ri->modelViewProj  );
+   mParticleShaderConsts.mShaderConsts->setSafe( mParticleShaderConsts.mOneOverFarSC, 1.0f / state->getFarPlane() );     
+
+   if ( mParticleShaderConsts.mOneOverSoftnessSC->isValid() )
+   {
+      F32 oneOverSoftness = 1.0f;
+      if ( ri->softnessDistance > 0.0f )
+         oneOverSoftness = 1.0f / ( ri->softnessDistance / state->getFarPlane() );
+      mParticleShaderConsts.mShaderConsts->set( mParticleShaderConsts.mOneOverSoftnessSC, oneOverSoftness );
+   }
+
+   GFX->setShader( mParticleShader );
+   GFX->setShaderConstBuffer( mParticleShaderConsts.mShaderConsts );
+
+   GFX->setTexture( 0, ri->diffuseTex );
+
+   // Set up the prepass texture.
+   if ( mParticleShaderConsts.mPrePassTargetParamsSC->isValid() )
+   {
+      GFXTextureObject *texObject = mPrepassTarget ? mPrepassTarget->getTexture(0) : NULL;
+      GFX->setTexture( 1, texObject );
+
+      Point4F rtParams( 0.0f, 0.0f, 1.0f, 1.0f );
+      if ( texObject )
+         ScreenSpace::RenderTargetParameters(texObject->getSize(), mPrepassTarget->getViewport(), rtParams);
+
+      mParticleShaderConsts.mShaderConsts->set( mParticleShaderConsts.mPrePassTargetParamsSC, rtParams );
+   }
+
+   GFX->setPrimitiveBuffer( *ri->primBuff );
+   GFX->setVertexBuffer( *ri->vertBuff );
+
+   GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, ri->count * 4, 0, ri->count * 2 );
+}
+
 bool RenderParticleMgr::_initShader()
 {
    ShaderData *shaderData = NULL;

+ 3 - 1
Engine/source/renderInstance/renderParticleMgr.h

@@ -77,7 +77,9 @@ protected:
    // Not only a helper method, but a method for the RenderTranslucentMgr to
    // request a particle system draw
    void renderInstance(ParticleRenderInst *ri, SceneRenderState *state);
-
+public:
+   void renderParticle(ParticleRenderInst *ri, SceneRenderState *state);
+protected:
    bool mOffscreenRenderEnabled;
 
    /// The prepass render target used for the

+ 2 - 0
Engine/source/renderInstance/renderPassManager.h

@@ -392,6 +392,8 @@ struct ParticleRenderInst : public RenderInst
    /// The total particle count to render.
    S32 count;
 
+   bool glow;
+
    /// The combined model, camera, and projection transform.
    const MatrixF *modelViewProj;       
         

+ 28 - 1
Templates/Empty/game/tools/particleEditor/ParticleEditor.ed.gui

@@ -442,7 +442,7 @@ $PE_guielement_ext_colorpicker = "18 18";
                            text = "";
                         };
                      };
-                     
+                        
                      new GuiControl(){ // Spacer ----------------------------
                         isContainer = "1"; HorizSizing = "width"; Position = "0 0"; Extent = "194 8";
                         new GuiBitmapCtrl(){
@@ -543,6 +543,33 @@ $PE_guielement_ext_colorpicker = "18 18";
                            altCommand = "$ThisControl.getParent().updateFromChild($ThisControl); PE_EmitterEditor.updateAmountFields( true, $ThisControl.getValue() );";
                         };
                      };
+                     
+                     new GuiControl(){ // Particle glow
+                        isContainer = "1";
+                        HorizSizing = "width";
+                        VertSizing = "bottom";
+                        Position = $PE_guielement_pos_single_container ;
+                        Extent = $PE_guielement_ext_single_container ;
+                        
+                        new GuiTextCtrl() {
+                           Profile = "ToolsGuiTextProfile";
+                           HorizSizing = "width";
+                           VertSizing = "bottom";
+                           position = $PE_guielement_pos_name;
+                           Extent = $PE_guielement_ext_checkbox_name;
+                           text = "Glow";
+                        };
+                        new GuiCheckBoxCtrl() {
+                           internalName = "PEE_glow";
+                           Profile = "ToolsGuiCheckBoxProfile";
+                           HorizSizing = "left";
+                           VertSizing = "bottom";
+                           position = $PE_guielement_pos_checkbox;
+                           Extent = $PE_guielement_ext_checkbox;
+                           Command = "PE_EmitterEditor.updateEmitter( \"glow\", $ThisControl.getValue());";
+                           text = "";
+                        };
+                     };
                   };// end stack
                }; // end "basic" rollout
                new GuiRolloutCtrl() {

+ 2 - 0
Templates/Empty/game/tools/particleEditor/particleEmitterEditor.ed.cs

@@ -100,6 +100,8 @@ function PE_EmitterEditor::guiSync( %this )
    PE_EmitterEditor-->PEE_reverseOrder.setValue( %data.reverseOrder );
    PE_EmitterEditor-->PEE_useEmitterSizes.setValue( %data.useEmitterSizes );
    PE_EmitterEditor-->PEE_useEmitterColors.setValue( %data.useEmitterColors );
+   
+   PE_EmitterEditor-->PEE_glow.setValue( %data.glow );
 
    // Sync up particle selectors.
    

+ 28 - 1
Templates/Full/game/tools/particleEditor/ParticleEditor.ed.gui

@@ -442,7 +442,7 @@ $PE_guielement_ext_colorpicker = "18 18";
                            text = "";
                         };
                      };
-                     
+                        
                      new GuiControl(){ // Spacer ----------------------------
                         isContainer = "1"; HorizSizing = "width"; Position = "0 0"; Extent = "194 8";
                         new GuiBitmapCtrl(){
@@ -543,6 +543,33 @@ $PE_guielement_ext_colorpicker = "18 18";
                            altCommand = "$ThisControl.getParent().updateFromChild($ThisControl); PE_EmitterEditor.updateAmountFields( true, $ThisControl.getValue() );";
                         };
                      };
+                     
+                     new GuiControl(){ // Particle glow
+                        isContainer = "1";
+                        HorizSizing = "width";
+                        VertSizing = "bottom";
+                        Position = $PE_guielement_pos_single_container ;
+                        Extent = $PE_guielement_ext_single_container ;
+                        
+                        new GuiTextCtrl() {
+                           Profile = "ToolsGuiTextProfile";
+                           HorizSizing = "width";
+                           VertSizing = "bottom";
+                           position = $PE_guielement_pos_name;
+                           Extent = $PE_guielement_ext_checkbox_name;
+                           text = "Glow";
+                        };
+                        new GuiCheckBoxCtrl() {
+                           internalName = "PEE_glow";
+                           Profile = "ToolsGuiCheckBoxProfile";
+                           HorizSizing = "left";
+                           VertSizing = "bottom";
+                           position = $PE_guielement_pos_checkbox;
+                           Extent = $PE_guielement_ext_checkbox;
+                           Command = "PE_EmitterEditor.updateEmitter( \"glow\", $ThisControl.getValue());";
+                           text = "";
+                        };
+                     };
                   };// end stack
                }; // end "basic" rollout
                new GuiRolloutCtrl() {

+ 2 - 0
Templates/Full/game/tools/particleEditor/particleEmitterEditor.ed.cs

@@ -100,6 +100,8 @@ function PE_EmitterEditor::guiSync( %this )
    PE_EmitterEditor-->PEE_reverseOrder.setValue( %data.reverseOrder );
    PE_EmitterEditor-->PEE_useEmitterSizes.setValue( %data.useEmitterSizes );
    PE_EmitterEditor-->PEE_useEmitterColors.setValue( %data.useEmitterColors );
+   
+   PE_EmitterEditor-->PEE_glow.setValue( %data.glow );
 
    // Sync up particle selectors.