mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-24 00:53:47 +00:00
Add all new AFX files
This commit is contained in:
parent
f2b86b7df3
commit
ace877b409
218 changed files with 54970 additions and 0 deletions
491
Engine/source/afx/util/afxParticlePool_T3D.cpp
Normal file
491
Engine/source/afx/util/afxParticlePool_T3D.cpp
Normal file
|
|
@ -0,0 +1,491 @@
|
|||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
|
||||
// Copyright (C) 2015 Faust Logic, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
#include "afx/arcaneFX.h"
|
||||
|
||||
#include "scene/sceneRenderState.h"
|
||||
#include "T3D/fx/particleEmitter.h"
|
||||
#include "renderInstance/renderPassManager.h"
|
||||
#include "lighting/lightinfo.h"
|
||||
#include "lighting/lightManager.h"
|
||||
|
||||
#include "afx/util/afxParticlePool.h"
|
||||
|
||||
void afxParticlePool::prepRenderImage(SceneRenderState* state)
|
||||
{
|
||||
const LightInfo *sunlight = LIGHTMGR->getSpecialLight( LightManager::slSunLightType );
|
||||
pool_prepBatchRender(state->getRenderPass(), state->getCameraPosition(), sunlight->getAmbient());
|
||||
};
|
||||
|
||||
void afxParticlePool::pool_prepBatchRender(RenderPassManager *renderManager, const Point3F &camPos, const LinearColorF &ambientColor)
|
||||
{
|
||||
if (emitters.empty())
|
||||
return;
|
||||
|
||||
switch (mDataBlock->pool_type)
|
||||
{
|
||||
case afxParticlePoolData::POOL_TWOPASS :
|
||||
pool_renderObject_TwoPass(renderManager, camPos, ambientColor);
|
||||
break;
|
||||
case afxParticlePoolData::POOL_NORMAL :
|
||||
default:
|
||||
pool_renderObject_Normal(renderManager, camPos, ambientColor);
|
||||
}
|
||||
}
|
||||
|
||||
void afxParticlePool::pool_renderObject_Normal(RenderPassManager *renderManager, const Point3F &camPos, const LinearColorF &ambientColor)
|
||||
{
|
||||
S32 n_parts = 0;
|
||||
for (S32 i = 0; i < emitters.size(); i++)
|
||||
n_parts += emitters[i]->n_parts;
|
||||
|
||||
if (n_parts == 0)
|
||||
return;
|
||||
|
||||
ParticleEmitterData* main_emitter_data = emitters[0]->mDataBlock;
|
||||
|
||||
main_emitter_data->allocPrimBuffer(n_parts);
|
||||
|
||||
orderedVector.clear();
|
||||
|
||||
MatrixF modelview = GFX->getWorldMatrix();
|
||||
Point3F viewvec; modelview.getRow(1, &viewvec);
|
||||
|
||||
for (U32 i=0; i < emitters.size(); i++)
|
||||
{
|
||||
// add each particle and a distance based sort key to orderedVector
|
||||
for (Particle* pp = emitters[i]->part_list_head.next; pp != NULL; pp = pp->next)
|
||||
{
|
||||
orderedVector.increment();
|
||||
orderedVector.last().p = pp;
|
||||
orderedVector.last().k = mDot(pp->pos, viewvec);
|
||||
orderedVector.last().emitter = emitters[i];
|
||||
}
|
||||
}
|
||||
|
||||
// qsort the list into far to near ordering
|
||||
dQsort(orderedVector.address(), orderedVector.size(), sizeof(SortParticlePool), cmpSortParticlePool);
|
||||
|
||||
static Vector<GFXVertexPCT> tempBuff(2048);
|
||||
tempBuff.reserve(n_parts*4 + 64); // make sure tempBuff is big enough
|
||||
GFXVertexPCT *buffPtr = tempBuff.address(); // use direct pointer (faster)
|
||||
|
||||
Point3F basePoints[4];
|
||||
basePoints[0] = Point3F(-1.0, 0.0, -1.0);
|
||||
basePoints[1] = Point3F( 1.0, 0.0, -1.0);
|
||||
basePoints[2] = Point3F( 1.0, 0.0, 1.0);
|
||||
basePoints[3] = Point3F(-1.0, 0.0, 1.0);
|
||||
|
||||
MatrixF camView = GFX->getWorldMatrix();
|
||||
camView.transpose(); // inverse - this gets the particles facing camera
|
||||
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
if (emitter->mDataBlock->orientParticles)
|
||||
emitter->setupOriented(particle, camPos, ambientColor, buffPtr);
|
||||
else
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
buffPtr+=4;
|
||||
}
|
||||
|
||||
// create new VB if emitter size grows
|
||||
if( !mVertBuff || n_parts > mCurBuffSize )
|
||||
{
|
||||
mCurBuffSize = n_parts;
|
||||
mVertBuff.set(GFX, n_parts*4, GFXBufferTypeDynamic);
|
||||
}
|
||||
// lock and copy tempBuff to video RAM
|
||||
GFXVertexPCT *verts = mVertBuff.lock();
|
||||
dMemcpy( verts, tempBuff.address(), n_parts * 4 * sizeof(GFXVertexPCT) );
|
||||
mVertBuff.unlock();
|
||||
|
||||
//MeshRenderInst *ri = gRenderInstManager->allocInst<MeshRenderInst>();
|
||||
ParticleRenderInst *ri = renderManager->allocInst<ParticleRenderInst>();
|
||||
ri->vertBuff = &mVertBuff;
|
||||
ri->primBuff = &main_emitter_data->primBuff;
|
||||
ri->translucentSort = true;
|
||||
ri->type = RenderPassManager::RIT_Particle;
|
||||
ri->sortDistSq = getWorldBox().getSqDistanceToPoint( camPos );
|
||||
|
||||
ri->defaultKey = (-sort_priority*100);
|
||||
|
||||
ri->modelViewProj = renderManager->allocUniqueXform( GFX->getProjectionMatrix() *
|
||||
GFX->getViewMatrix() *
|
||||
GFX->getWorldMatrix() );
|
||||
|
||||
ri->count = n_parts;
|
||||
|
||||
ri->blendStyle = main_emitter_data->blendStyle;
|
||||
|
||||
// use first particle's texture unless there is an emitter texture to override it
|
||||
if (main_emitter_data->textureHandle)
|
||||
ri->diffuseTex = &*(main_emitter_data->textureHandle);
|
||||
else
|
||||
ri->diffuseTex = &*(main_emitter_data->particleDataBlocks[0]->textureHandle);
|
||||
|
||||
ri->softnessDistance = main_emitter_data->softnessDistance;
|
||||
|
||||
// Sort by texture too.
|
||||
//ri->defaultKey = ri->diffuseTex ? (U32)ri->diffuseTex : (U32)ri->vertBuff;
|
||||
|
||||
renderManager->addInst( ri );
|
||||
}
|
||||
|
||||
void afxParticlePool::pool_renderObject_TwoPass(RenderPassManager *renderManager, const Point3F &camPos, const LinearColorF &ambientColor)
|
||||
{
|
||||
S32 n_parts = 0;
|
||||
for (S32 i = 0; i < emitters.size(); i++)
|
||||
n_parts += emitters[i]->n_parts;
|
||||
|
||||
if (n_parts == 0)
|
||||
return;
|
||||
|
||||
ParticleEmitterData* main_emitter_data = emitters[0]->mDataBlock;
|
||||
|
||||
main_emitter_data->allocPrimBuffer(n_parts);
|
||||
|
||||
orderedVector.clear();
|
||||
|
||||
F32 min_d=0.0f, max_d=0.0f;
|
||||
|
||||
for (U32 i=0; i < emitters.size(); i++)
|
||||
{
|
||||
if (!emitters[i]->mDataBlock->pool_depth_fade || !emitters[i]->mDataBlock->pool_radial_fade)
|
||||
continue;
|
||||
|
||||
// add particles to orderedVector and calc distance and min/max distance
|
||||
for (Particle* pp = emitters[i]->part_list_head.next; pp != NULL; pp = pp->next)
|
||||
{
|
||||
F32 dist = (pp->pos-camPos).len();
|
||||
if (dist > max_d)
|
||||
max_d = dist;
|
||||
else if (dist < min_d)
|
||||
min_d = dist;
|
||||
|
||||
orderedVector.increment();
|
||||
orderedVector.last().p = pp;
|
||||
orderedVector.last().k = dist;
|
||||
orderedVector.last().emitter = emitters[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Add remaining emitters particles to the orderedVector that do not participate in the
|
||||
// above depth computations:
|
||||
for (U32 i=0; i < emitters.size(); i++)
|
||||
{
|
||||
if (emitters[i]->mDataBlock->pool_depth_fade || emitters[i]->mDataBlock->pool_radial_fade)
|
||||
continue;
|
||||
|
||||
for (Particle* pp = emitters[i]->part_list_head.next; pp != NULL; pp = pp->next)
|
||||
{
|
||||
orderedVector.increment();
|
||||
orderedVector.last().p = pp;
|
||||
orderedVector.last().k = 0; // no need to compute depth here
|
||||
orderedVector.last().emitter = emitters[i];
|
||||
}
|
||||
}
|
||||
|
||||
static Vector<GFXVertexPCT> tempBuff(2048);
|
||||
tempBuff.reserve(n_parts*4 + 64); // make sure tempBuff is big enough
|
||||
GFXVertexPCT *buffPtr = tempBuff.address(); // use direct pointer (faster)
|
||||
|
||||
Point3F basePoints[4];
|
||||
basePoints[0] = Point3F(-1.0, 0.0, -1.0);
|
||||
basePoints[1] = Point3F( 1.0, 0.0, -1.0);
|
||||
basePoints[2] = Point3F( 1.0, 0.0, 1.0);
|
||||
basePoints[3] = Point3F(-1.0, 0.0, 1.0);
|
||||
|
||||
MatrixF camView = GFX->getWorldMatrix();
|
||||
camView.transpose(); // inverse - this gets the particles facing camera
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
Point3F bbox_center; mObjBox.getCenter(&bbox_center);
|
||||
F32 d_range = max_d - min_d;
|
||||
bool d_safe = (d_range>0.0001);
|
||||
F32 d_half = min_d + (d_range*0.5f);
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color.set(mDataBlock->base_color.red, mDataBlock->base_color.green, mDataBlock->base_color.blue, mDataBlock->base_color.alpha*particle->color.alpha);
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
|
||||
// create new VB if emitter size grows
|
||||
if( !mVertBuff || n_parts > mCurBuffSize )
|
||||
{
|
||||
mCurBuffSize = n_parts;
|
||||
mVertBuff.set(GFX, n_parts*4, GFXBufferTypeDynamic);
|
||||
}
|
||||
// lock and copy tempBuff to video RAM
|
||||
GFXVertexPCT *verts = mVertBuff.lock();
|
||||
dMemcpy( verts, tempBuff.address(), n_parts * 4 * sizeof(GFXVertexPCT) );
|
||||
mVertBuff.unlock();
|
||||
|
||||
ParticleRenderInst *ri = renderManager->allocInst<ParticleRenderInst>();
|
||||
ri->vertBuff = &mVertBuff;
|
||||
ri->primBuff = &main_emitter_data->primBuff;
|
||||
ri->translucentSort = true;
|
||||
ri->type = RenderPassManager::RIT_Particle;
|
||||
ri->sortDistSq = getWorldBox().getSqDistanceToPoint( camPos );
|
||||
|
||||
ri->defaultKey = (-sort_priority*100);
|
||||
|
||||
ri->modelViewProj = renderManager->allocUniqueXform( GFX->getProjectionMatrix() *
|
||||
GFX->getViewMatrix() *
|
||||
GFX->getWorldMatrix() );
|
||||
|
||||
ri->count = n_parts;
|
||||
|
||||
ri->blendStyle = ParticleRenderInst::BlendNormal;
|
||||
|
||||
// use first particle's texture unless there is an emitter texture to override it
|
||||
//if (main_emitter_data->textureHandle)
|
||||
// ri->diffuseTex = &*(main_emitter_data->textureHandle);
|
||||
//else
|
||||
ri->diffuseTex = &*(main_emitter_data->particleDataBlocks[0]->textureExtHandle);
|
||||
|
||||
F32 save_sort_dist = ri->sortDistSq;
|
||||
|
||||
ri->softnessDistance = main_emitter_data->softnessDistance;
|
||||
|
||||
renderManager->addInst( ri );
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
|
||||
// 2nd-pass
|
||||
|
||||
buffPtr = tempBuff.address();
|
||||
|
||||
bbox_center.z = mObjBox.minExtents.z;
|
||||
F32 max_radius = (max_d-min_d)*0.5f;
|
||||
|
||||
// gather fade settings
|
||||
bool do_mixed_fades = false;
|
||||
bool do_radial_fades = (emitters[0]->mDataBlock->pool_radial_fade && (max_radius>0.0001f));
|
||||
bool do_depth_fades = (emitters[0]->mDataBlock->pool_depth_fade && d_safe);
|
||||
for (U32 i = 1; i < emitters.size(); i++)
|
||||
{
|
||||
if ( (do_radial_fades != (emitters[i]->mDataBlock->pool_radial_fade && (max_radius>0.0001f))) ||
|
||||
(do_depth_fades != (emitters[i]->mDataBlock->pool_depth_fade && d_safe)))
|
||||
{
|
||||
do_mixed_fades = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_mixed_fades)
|
||||
{
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
F32 bf = 1.0; // blend factor
|
||||
|
||||
// blend factor due to radius
|
||||
if (emitter->mDataBlock->pool_radial_fade && (max_radius>0.0001f))
|
||||
{
|
||||
F32 p_radius = (particle->pos-bbox_center).len();
|
||||
F32 bf_radius = p_radius/max_radius;
|
||||
if (bf_radius>1.0f) bf_radius = 1.0f;
|
||||
bf *= bf_radius*bf_radius; // quadratic for faster falloff
|
||||
}
|
||||
|
||||
// blend factor, depth based
|
||||
if (emitter->mDataBlock->pool_depth_fade && d_safe && (orderedVector[i].k > d_half))
|
||||
{
|
||||
F32 bf_depth = ((max_d-orderedVector[i].k) / (d_range*0.5f));
|
||||
bf *= bf_depth;
|
||||
}
|
||||
|
||||
// overall blend factor weight
|
||||
bf *= mDataBlock->blend_weight;
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color = particle->color*bf;
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
}
|
||||
else if (do_radial_fades && do_depth_fades)
|
||||
{
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
F32 bf = 1.0; // blend factor
|
||||
|
||||
// blend factor due to radius
|
||||
F32 p_radius = (particle->pos-bbox_center).len();
|
||||
F32 bf_radius = p_radius/max_radius;
|
||||
if (bf_radius>1.0f) bf_radius = 1.0f;
|
||||
bf *= bf_radius*bf_radius; // quadratic for faster falloff
|
||||
|
||||
// blend factor, depth based
|
||||
if (orderedVector[i].k > d_half)
|
||||
{
|
||||
F32 bf_depth = ((max_d-orderedVector[i].k) / (d_range*0.5f));
|
||||
bf *= bf_depth;
|
||||
}
|
||||
|
||||
// overall blend factor weight
|
||||
bf *= mDataBlock->blend_weight;
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color = particle->color*bf;
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
}
|
||||
else if (do_radial_fades) // && !do_depth_fades
|
||||
{
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
F32 bf = 1.0; // blend factor
|
||||
|
||||
// blend factor due to radius
|
||||
F32 p_radius = (particle->pos-bbox_center).len();
|
||||
F32 bf_radius = p_radius/max_radius;
|
||||
if (bf_radius>1.0f) bf_radius = 1.0f;
|
||||
bf *= bf_radius*bf_radius; // quadratic for faster falloff
|
||||
|
||||
// overall blend factor weight
|
||||
bf *= mDataBlock->blend_weight;
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color = particle->color*bf;
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
}
|
||||
else if (do_depth_fades) // && !do_radial_fades
|
||||
{
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
F32 bf = 1.0; // blend factor
|
||||
|
||||
// blend factor, depth based
|
||||
if (orderedVector[i].k > d_half)
|
||||
{
|
||||
F32 bf_depth = ((max_d-orderedVector[i].k) / (d_range*0.5f));
|
||||
bf *= bf_depth;
|
||||
}
|
||||
|
||||
// overall blend factor weight
|
||||
bf *= mDataBlock->blend_weight;
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color = particle->color*bf;
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
}
|
||||
else // (no fades)
|
||||
{
|
||||
for (U32 i = 0; i < orderedVector.size(); i++)
|
||||
{
|
||||
Particle* particle = orderedVector[i].p;
|
||||
ParticleEmitter* emitter = orderedVector[i].emitter;
|
||||
|
||||
F32 bf = mDataBlock->blend_weight; // blend factor
|
||||
|
||||
LinearColorF color_save = particle->color;
|
||||
particle->color = particle->color*bf;
|
||||
emitter->setupBillboard(particle, basePoints, camView, ambientColor, buffPtr);
|
||||
particle->color = color_save;
|
||||
|
||||
buffPtr+=4;
|
||||
}
|
||||
}
|
||||
|
||||
// create new VB if emitter size grows
|
||||
if( !mVertBuff2 || n_parts > mCurBuffSize2 )
|
||||
{
|
||||
mCurBuffSize2 = n_parts;
|
||||
mVertBuff2.set(GFX, n_parts*4, GFXBufferTypeDynamic);
|
||||
}
|
||||
|
||||
// lock and copy tempBuff to video RAM
|
||||
verts = mVertBuff2.lock();
|
||||
dMemcpy( verts, tempBuff.address(), n_parts * 4 * sizeof(GFXVertexPCT) );
|
||||
mVertBuff2.unlock();
|
||||
|
||||
ri = renderManager->allocInst<ParticleRenderInst>();
|
||||
ri->vertBuff = &mVertBuff2;
|
||||
ri->primBuff = &main_emitter_data->primBuff;
|
||||
ri->translucentSort = true;
|
||||
ri->type = RenderPassManager::RIT_Particle;
|
||||
ri->sortDistSq = save_sort_dist;
|
||||
|
||||
ri->defaultKey = (-sort_priority*100) + 1;
|
||||
|
||||
ri->modelViewProj = renderManager->allocUniqueXform( GFX->getProjectionMatrix() *
|
||||
GFX->getViewMatrix() *
|
||||
GFX->getWorldMatrix() );
|
||||
|
||||
ri->count = n_parts;
|
||||
|
||||
ri->blendStyle = ParticleRenderInst::BlendAdditive;
|
||||
|
||||
// use first particle's texture unless there is an emitter texture to override it
|
||||
if (main_emitter_data->textureHandle)
|
||||
ri->diffuseTex = &*(main_emitter_data->textureHandle);
|
||||
else
|
||||
ri->diffuseTex = &*(main_emitter_data->particleDataBlocks[0]->textureHandle);
|
||||
|
||||
ri->softnessDistance = main_emitter_data->softnessDistance;
|
||||
|
||||
renderManager->addInst( ri );
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|
||||
Loading…
Add table
Add a link
Reference in a new issue