GLSL shaders for CElementGen

This commit is contained in:
Jack Andersen 2016-02-14 18:00:26 -10:00
parent ae900345fe
commit 160940abde
11 changed files with 1121 additions and 153 deletions

View File

@ -144,60 +144,70 @@ Zeus::CVector2i CGraphics::ProjectPoint(const Zeus::CVector3f& point)
int(projPt.y * g_ViewportResolutionHalf.y) + g_ViewportResolutionHalf.y};
}
SClipScreenRect CGraphics::ClipScreenRectFromMS(const Zeus::CVector3f& pos,
const Zeus::CVector3f& extent,
ETexelFormat fmt)
SClipScreenRect CGraphics::ClipScreenRectFromMS(const Zeus::CVector3f& p1,
const Zeus::CVector3f& p2)
{
Zeus::CVector3f xfExt = (g_GXModelMatrix * extent) - g_ViewMatrix.m_origin;
Zeus::CVector3f xfExt = (g_GXModelMatrix * p2) - g_ViewMatrix.m_origin;
xfExt = g_ViewMatrix.transposeRotate(xfExt);
Zeus::CVector3f xfPos = (g_GXModelMatrix * pos) - g_ViewMatrix.m_origin;
Zeus::CVector3f xfPos = (g_GXModelMatrix * p1) - g_ViewMatrix.m_origin;
xfPos = g_ViewMatrix.transposeRotate(xfPos);
return ClipScreenRectFromVS(xfPos, xfExt, fmt);
return ClipScreenRectFromVS(xfPos, xfExt);
}
SClipScreenRect CGraphics::ClipScreenRectFromVS(const Zeus::CVector3f& pos,
const Zeus::CVector3f& extent,
ETexelFormat fmt)
SClipScreenRect CGraphics::ClipScreenRectFromVS(const Zeus::CVector3f& p1,
const Zeus::CVector3f& p2)
{
if (pos.x == 0.f && pos.y == 0.f && pos.z == 0.f)
if (p1.x == 0.f && p1.y == 0.f && p1.z == 0.f)
return {};
if (extent.x == 0.f && extent.y == 0.f && extent.z == 0.f)
if (p2.x == 0.f && p2.y == 0.f && p2.z == 0.f)
return {};
if (pos.y < GetProjectionState().x14_near || extent.y < GetProjectionState().x14_near)
if (p1.y < GetProjectionState().x14_near || p2.y < GetProjectionState().x14_near)
return {};
if (pos.y > GetProjectionState().x18_far || extent.y > GetProjectionState().x18_far)
if (p1.y > GetProjectionState().x18_far || p2.y > GetProjectionState().x18_far)
return {};
Zeus::CVector2i pt1 = ProjectPoint(pos);
Zeus::CVector2i pt2 = ProjectPoint(extent);
int minX = std::min(pt2.x, pt1.x);
Zeus::CVector2i sp1 = ProjectPoint(p1);
Zeus::CVector2i sp2 = ProjectPoint(p2);
int minX = std::min(sp2.x, sp1.x);
int minX2 = minX & 0xfffffffe;
int minY = std::min(pt2.y, pt1.y);
int minY = std::min(sp2.y, sp1.y);
int minY2 = minY & 0xfffffffe;
if (minX2 >= g_ViewportResolution.x)
return {};
int minX3 = (abs(pt1.x - pt2.x) + 2 + minX) & 0xfffffffe;
if (minX3 <= 0 /* ViewportX origin */)
int maxX = abs(sp1.x - sp2.x) + minX;
int maxX2 = (maxX + 2) & 0xfffffffe;
if (maxX2 <= 0 /* ViewportX origin */)
return {};
int outX = std::max(minX2, 0 /* ViewportX origin */);
int finalMinX = std::max(minX, 0 /* ViewportX origin */);
int finalMaxX = std::min(maxX, g_ViewportResolution.x);
if (minY2 >= g_ViewportResolution.y)
return {};
int minY3 = (abs(pt1.y - pt2.y) + 2 + minY) & 0xfffffffe;
if (minY3 <= 0 /* ViewportY origin */)
int maxY = abs(sp1.y - sp2.y) + minY;
int maxY2 = (maxY + 2) & 0xfffffffe;
if (maxY2 <= 0 /* ViewportY origin */)
return {};
int outY = std::max(minY2, 0 /* ViewportY origin */);
int finalMinY = std::max(minY, 0 /* ViewportY origin */);
int finalMaxY = std::min(maxY, g_ViewportResolution.y);
int width = maxX2 - minX2;
int height = maxY2 - minY2;
return {true, minX2, minY2, width, height, width,
(finalMinX - minX2) / float(width), (finalMaxX - minX2) / float(width),
(finalMinY - minY2) / float(height), (finalMaxY - minY2) / float(height)};
}
boo::IGraphicsDataFactory* CGraphics::g_BooFactory = nullptr;
boo::IGraphicsCommandQueue* CGraphics::g_BooMainCommandQueue = nullptr;
boo::ITextureR* CGraphics::g_SpareTexture = nullptr;
}

View File

@ -5,6 +5,9 @@
#include "CTransform.hpp"
#include "CVector2i.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include "boo/graphicsdev/IGraphicsCommandQueue.hpp"
namespace pshag
{
@ -105,11 +108,11 @@ enum class ERglAlphaOp
struct SClipScreenRect
{
bool x0_valid;
u32 x4_left;
u32 x8_top;
u32 xc_width;
u32 x10_height;
u32 x14_dstWidth;
int x4_left;
int x8_top;
int xc_width;
int x10_height;
int x14_dstWidth;
float x18_uvXMin;
float x1c_uvXMax;
float x20_uvYMin;
@ -146,6 +149,7 @@ public:
static Zeus::CVector2i g_ViewportResolution;
static Zeus::CVector2i g_ViewportResolutionHalf;
static bool g_IsGXModelMatrixIdentity;
static void DisableAllLights();
static void EnableLight(ERglLight light);
static void SetLightState(ERglLight lightState);
@ -162,8 +166,29 @@ public:
static void SetPerspective(float, float, float, float);
static void FlushProjection();
static Zeus::CVector2i ProjectPoint(const Zeus::CVector3f& point);
static SClipScreenRect ClipScreenRectFromMS(const Zeus::CVector3f& pos, const Zeus::CVector3f& extent, ETexelFormat);
static SClipScreenRect ClipScreenRectFromVS(const Zeus::CVector3f& pos, const Zeus::CVector3f& extent, ETexelFormat);
static SClipScreenRect ClipScreenRectFromMS(const Zeus::CVector3f& p1, const Zeus::CVector3f& p2);
static SClipScreenRect ClipScreenRectFromVS(const Zeus::CVector3f& p1, const Zeus::CVector3f& p2);
static boo::IGraphicsDataFactory* g_BooFactory;
static boo::IGraphicsCommandQueue* g_BooMainCommandQueue;
static boo::ITextureR* g_SpareTexture;
static boo::IGraphicsBufferD* NewDynamicGPUBuffer(boo::BufferUse use, size_t stride, size_t count)
{
return g_BooFactory->newDynamicBuffer(use, stride, count);
}
static boo::GraphicsDataToken CommitResources()
{
return g_BooFactory->commit();
}
static void SetShaderDataBinding(boo::IShaderDataBinding* binding)
{
g_BooMainCommandQueue->setShaderDataBinding(binding);
}
static void DrawInstances(size_t start, size_t count, size_t instCount)
{
g_BooMainCommandQueue->drawInstances(start, count, instCount);
}
};
}

View File

@ -2,6 +2,7 @@
#define __PSHAG_CTEXTURE_HPP__
#include "GCNTypes.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
namespace pshag
{
@ -10,6 +11,7 @@ class CTexture
{
u16 x4_w;
u16 x6_h;
boo::ITexture* m_booTex;
public:
enum class EClampMode
{
@ -19,6 +21,7 @@ public:
u16 GetWidth() const {return x4_w;}
u16 GetHeight() const {return x6_h;}
void Load(int slot, EClampMode clamp);
boo::ITexture* GetBooTexture() {return m_booTex;}
};
}

View File

@ -5,6 +5,8 @@
#include "CParticleElectric.hpp"
#include "CModel.hpp"
#include "CElementGenShaders.hpp"
#define MAX_GLOBAL_PARTICLES 2560
namespace pshag
@ -20,6 +22,208 @@ bool CElementGen::g_StaticListInitialized = false;
bool CElementGen::g_MoveRedToAlphaBuffer = false;
static rstl::reserved_vector<CElementGen::CParticle, MAX_GLOBAL_PARTICLES> g_StaticParticleList;
static rstl::reserved_vector<u16, MAX_GLOBAL_PARTICLES> g_StaticFreeList;
boo::IShaderPipeline* CElementGenShaders::m_texZTestZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_texNoZTestZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_texZTestNoZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_texNoZTestNoZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_texAdditiveZTest = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_texAdditiveNoZTest = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_texRedToAlphaZTest = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_texRedToAlphaNoZTest = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_indTexZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_indTexNoZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_indTexAdditive = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_cindTexZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_cindTexNoZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_cindTexAdditive = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_noTexZTestZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_noTexNoZTestZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_noTexZTestNoZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_noTexNoZTestNoZWrite = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_noTexAdditiveZTest = nullptr;
boo::IShaderPipeline* CElementGenShaders::m_noTexAdditiveNoZTest = nullptr;
boo::IVertexFormat* CElementGenShaders::m_vtxFormatTex = nullptr;
boo::IVertexFormat* CElementGenShaders::m_vtxFormatIndTex = nullptr;
boo::IVertexFormat* CElementGenShaders::m_vtxFormatNoTex = nullptr;
std::unique_ptr<CElementGenShaders::IDataBindingFactory> CElementGenShaders::m_bindFactory;
boo::GraphicsDataToken CElementGenShaders::m_gfxToken;
CElementGenShaders::EShaderClass CElementGenShaders::GetShaderClass(CElementGen& gen)
{
CGenDescription* desc = gen.x1c_genDesc.GetObj();
if (desc->x54_TEXR)
{
if (desc->x58_TIND)
return EShaderClass::IndTex;
else
return EShaderClass::Tex;
}
else
return EShaderClass::NoTex;
}
void CElementGenShaders::BuildShaderDataBinding(CElementGen& gen)
{
CGenDescription* desc = gen.x1c_genDesc.GetObj();
boo::IShaderPipeline* regPipeline = nullptr;
boo::IShaderPipeline* redToAlphaPipeline = nullptr;
if (desc->x54_TEXR)
{
if (desc->x58_TIND)
{
if (desc->x45_30_CIND)
{
if (gen.x224_26_AAPH)
regPipeline = m_cindTexAdditive;
else
{
if (gen.x224_27_ZBUF)
regPipeline = m_cindTexZWrite;
else
regPipeline = m_cindTexNoZWrite;
}
}
else
{
if (gen.x224_26_AAPH)
regPipeline = m_indTexAdditive;
else
{
if (gen.x224_27_ZBUF)
regPipeline = m_indTexZWrite;
else
regPipeline = m_indTexNoZWrite;
}
}
}
else
{
if (gen.x224_28_zTest)
redToAlphaPipeline = m_texRedToAlphaZTest;
else
redToAlphaPipeline = m_texRedToAlphaNoZTest;
if (gen.x224_26_AAPH)
{
if (gen.x224_28_zTest)
regPipeline = m_texAdditiveZTest;
else
regPipeline = m_texAdditiveNoZTest;
}
else
{
if (gen.x224_28_zTest)
{
if (gen.x224_27_ZBUF)
regPipeline = m_texZTestZWrite;
else
regPipeline = m_texZTestNoZWrite;
}
else
{
if (gen.x224_27_ZBUF)
regPipeline = m_texNoZTestZWrite;
else
regPipeline = m_texNoZTestNoZWrite;
}
}
}
}
else
{
if (gen.x224_26_AAPH)
{
if (gen.x224_28_zTest)
regPipeline = m_noTexAdditiveZTest;
else
regPipeline = m_noTexAdditiveNoZTest;
}
else
{
if (gen.x224_28_zTest)
{
if (gen.x224_27_ZBUF)
regPipeline = m_noTexZTestZWrite;
else
regPipeline = m_noTexZTestNoZWrite;
}
else
{
if (gen.x224_27_ZBUF)
regPipeline = m_noTexNoZTestZWrite;
else
regPipeline = m_noTexNoZTestNoZWrite;
}
}
}
m_bindFactory->BuildShaderDataBinding(gen, regPipeline, redToAlphaPipeline);
}
void CElementGenShaders::Initialize()
{
if (!CGraphics::g_BooFactory)
return;
switch (CGraphics::g_BooFactory->platform())
{
case boo::IGraphicsDataFactory::Platform::OGL:
m_bindFactory.reset(Initialize(*static_cast<boo::GLDataFactory*>(CGraphics::g_BooFactory)));
break;
#if _WIN32
case boo::IGraphicsDataFactory::Platform::D3D11:
case boo::IGraphicsDataFactory::Platform::D3D12:
m_bindFactory.reset(Initialize(*static_cast<boo::ID3DDataFactory*>(CGraphics::g_BooFactory)));
break;
#elif __APPLE__
case boo::IGraphicsDataFactory::Platform::Metal:
m_bindFactory.reset(Initialize(*static_cast<boo::MetalDataFactory*>(CGraphics::g_BooFactory)));
break;
#endif
default: break;
}
m_gfxToken = CGraphics::CommitResources();
}
struct SParticleInstanceTex
{
Zeus::CVector4f pos[4];
Zeus::CColor color;
Zeus::CVector2f uvs[4];
};
static std::vector<SParticleInstanceTex> g_instTexData;
struct SParticleInstanceIndTex
{
Zeus::CVector4f pos[4];
Zeus::CColor color;
Zeus::CVector4f texrTindUVs[4];
Zeus::CVector2f sceneUVs[4];
};
static std::vector<SParticleInstanceIndTex> g_instIndTexData;
struct SParticleInstanceNoTex
{
Zeus::CVector4f pos[4];
Zeus::CColor color;
};
static std::vector<SParticleInstanceNoTex> g_instNoTexData;
struct SParticleUniforms
{
Zeus::CMatrix4f mvp;
Zeus::CColor moduColor;
};
void CElementGen::Initialize()
{
if (g_StaticListInitialized)
@ -38,11 +242,12 @@ void CElementGen::Initialize()
g_FreeIndex = MAX_GLOBAL_PARTICLES - 1;
Log.report(LogVisor::Info, "size %d (%d each part).",
(sizeof(CParticle) + sizeof(u16)) * MAX_GLOBAL_PARTICLES, 56);
(sizeof(CParticle) + sizeof(u16)) * MAX_GLOBAL_PARTICLES, sizeof(CParticle));
g_StaticListInitialized = true;
}
CElementGen::CElementGen(const TToken<CGenDescription>& gen) : x1c_genDesc(gen), x230_randState(x74_randomSeed) {}
/* Compile shaders */
CElementGenShaders::Initialize();
}
CElementGen::CElementGen(const TToken<CGenDescription>& gen,
EModelOrientationType orientType,
@ -69,6 +274,7 @@ CElementGen::CElementGen(const TToken<CGenDescription>& gen,
CIntElement* mbspElem = desc->x48_MBSP.get();
if (mbspElem)
mbspElem->GetValue(x50_curFrame, x228_MBSP);
m_maxMBSP = x228_MBSP;
x224_30_VMD1 = desc->x45_26_VMD1;
x224_31_VMD2 = desc->x45_27_VMD2;
@ -138,7 +344,7 @@ CElementGen::CElementGen(const TToken<CGenDescription>& gen,
if (maxpElem)
maxpElem->GetValue(x50_curFrame, x70_MAXP);
x2c_particleLists.reserve(std::min(256, x70_MAXP));
x2c_particleLists.reserve(x70_MAXP);
if (x28_orientType == EModelOrientationType::One)
{
x3c_parentMatrices.insert(x3c_parentMatrices.end(), x70_MAXP,
@ -194,6 +400,19 @@ CElementGen::CElementGen(const TToken<CGenDescription>& gen,
break;
}
}
m_shaderClass = CElementGenShaders::GetShaderClass(*this);
static const size_t ShadClsSizes[] =
{
sizeof(SParticleInstanceTex),
sizeof(SParticleInstanceIndTex),
sizeof(SParticleInstanceNoTex)
};
size_t maxInsts = x224_29_MBLR ? (m_maxMBSP * x70_MAXP) : x70_MAXP;
m_instBuf = CGraphics::NewDynamicGPUBuffer(boo::BufferUse::Vertex, ShadClsSizes[int(m_shaderClass)], maxInsts);
m_uniformBuf = CGraphics::NewDynamicGPUBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1);
CElementGenShaders::BuildShaderDataBinding(*this);
m_gfxToken = CGraphics::CommitResources();
}
CElementGen::~CElementGen()
@ -248,6 +467,7 @@ bool CElementGen::InternalUpdate(double dt)
CIntElement* mbspElem = desc->x48_MBSP.get();
if (mbspElem)
mbspElem->GetValue(x50_curFrame, x228_MBSP);
x228_MBSP = std::min(x228_MBSP, m_maxMBSP);
}
int frameUpdateCount = 0;
@ -1145,6 +1365,128 @@ void CElementGen::RenderModels()
void CElementGen::RenderLines()
{
CGenDescription* desc = x1c_genDesc.GetObj();
CGlobalRandom gr(x230_randState);
Zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix);
systemViewPointMatrix.m_origin.zeroOut();
Zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x1d8_globalOrientation;
systemViewPointMatrix = ((Zeus::CTransform::Translate(x88_globalTranslation) * xac_globalScaleTransform) * systemViewPointMatrix) * x118_localScaleTransform;
CGraphics::SetModelMatrix(systemViewPointMatrix);
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
if (x224_26_AAPH)
{
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false);
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear);
}
else
{
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true);
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear);
}
CRealElement* widt = desc->x24_WIDT.get();
bool widtConst = false;
if (widt)
widtConst = widt->IsConstant();
CUVElement* texr = desc->x54_TEXR.get();
SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f};
bool constTexr = true;
bool constUVs = true;
CTexture* cachedTex = nullptr;
if (texr)
{
CParticle& target = g_StaticParticleList[x2c_particleLists[0].x0_partIdx];
int partFrame = x50_curFrame - target.x28_startFrame;
cachedTex = texr->GetValueTexture(partFrame).GetObj();
cachedTex->Load(0, CTexture::EClampMode::One);
/* Set TEXC * RASC */
if (x30c_moduColor != Zeus::CColor::skBlack)
{
/* Add RASC * PREVC pass for MODU color loaded into channel mat-color */
}
else
{
/* Pass-thru */
}
constTexr = texr->HasConstantTexture();
texr->GetValueUV(partFrame, uvs);
constUVs = texr->HasConstantUV();
}
else
{
/* Pass-thru */
}
if (widtConst)
{
float width = 1.f;
widt->GetValue(0, width);
width = std::max(0.f, std::min(width, 42.5f));
/* Set line width */
/* Start line draw of x2c_particleLists.size() * 2 */
}
for (CParticleListItem& item : x2c_particleLists)
{
CParticle& particle = g_StaticParticleList[item.x0_partIdx];
int partFrame = x50_curFrame - particle.x28_startFrame;
if (!constTexr)
{
CTexture* tex = texr->GetValueTexture(partFrame).GetObj();
if (tex != cachedTex)
{
tex->Load(0, CTexture::EClampMode::One);
cachedTex = tex;
}
}
if (!constUVs)
texr->GetValueUV(partFrame, uvs);
Zeus::CVector3f dVec = particle.x4_pos - particle.x10_prevPos;
if (x225_27_FXLL)
if (dVec.magSquared() >= 0.f)
dVec.normalize();
Zeus::CVector3f p1 = systemCameraMatrix * particle.x4_pos;
Zeus::CVector3f p2 = systemCameraMatrix * (particle.x2c_lineLengthOrSize * dVec + particle.x4_pos);
if (widtConst)
{
/* Draw: */
/* Pos: p1 Color: particle.color UV0: {uv[0], uv[1]} */
/* Pos: p2 Color: particle.color UV0: {uv[2], uv[3]} */
}
else
{
float width = 1.f;
widt->GetValue(0, width);
width = std::max(0.f, std::min(width, 42.5f));
/* Set line width */
/* Start line draw of 2 */
/* Draw: */
/* Pos: p1 Color: particle.color UV0: {uv[0], uv[1]} */
/* Pos: p2 Color: particle.color UV0: {uv[2], uv[3]} */
/* EndDraw */
}
}
if (widtConst)
{
/* EndDraw */
}
/* Restore line-width to 1.0 */
}
void CElementGen::RenderParticles()
@ -1186,6 +1528,12 @@ void CElementGen::RenderParticles()
bool constUVs = true;
CTexture* cachedTex = nullptr;
SParticleUniforms uniformData =
{
CGraphics::GetPerspectiveProjectionMatrix() * CGraphics::g_GXModelView.toMatrix4f(),
{1.f, 1.f, 1.f, 1.f}
};
if (texr)
{
CParticle& target = g_StaticParticleList[x2c_particleLists[0].x0_partIdx];
@ -1196,20 +1544,15 @@ void CElementGen::RenderParticles()
if (x30c_moduColor != Zeus::CColor::skBlack)
{
/* Add RASC * PREVC pass for MODU color loaded into channel mat-color */
}
else
{
/* Pass-thru */
uniformData.moduColor = x30c_moduColor;
}
constTexr = texr->HasConstantTexture();
texr->GetValueUV(partFrame, uvs);
constUVs = texr->HasConstantUV();
}
else
{
/* Pass-thru */
}
m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms));
if (desc->x44_28_SORT)
{
@ -1222,35 +1565,6 @@ void CElementGen::RenderParticles()
std::sort(x2c_particleLists.begin(), x2c_particleLists.end(),
[](const CParticleListItem& a, const CParticleListItem& b) -> bool
{return a.x4_viewPoint[1] >= b.x4_viewPoint[1];});
#if 0
bool done = false;
while (!done)
{
done = true;
for (int i=0 ; i<x2c_particleLists.size()-1 ; ++i)
{
CParticleListItem& p1 = x2c_particleLists[i];
CParticleListItem& p2 = x2c_particleLists[i+1];
if (p1.x4_viewPoint[1] < p2.x4_viewPoint[1])
{
CParticleListItem tmp = p2;
p2 = p1;
p1 = tmp;
done = false;
}
}
}
#endif
}
if (x30c_moduColor != Zeus::CColor::skBlack)
{
/* Load mat-color here */
}
else
{
/* Pass-thru */
}
bool moveRedToAlphaBuffer = false;
@ -1258,39 +1572,29 @@ void CElementGen::RenderParticles()
moveRedToAlphaBuffer = true;
if (moveRedToAlphaBuffer)
{
CGraphics::SetDepthWriteMode(x224_28_zTest, ERglEnum::LEqual, false);
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
/* Color = Prev.rgb * Prev.a */
/* Alpha = Tex.r * Prev.a */
}
CGraphics::SetShaderDataBinding(m_redToAlphaDataBind);
else
{
if (x224_26_AAPH)
{
CGraphics::SetDepthWriteMode(x224_28_zTest, ERglEnum::LEqual, false);
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear);
}
else
{
CGraphics::SetDepthWriteMode(x224_28_zTest, ERglEnum::LEqual, x224_27_ZBUF);
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear);
}
}
CGraphics::SetShaderDataBinding(m_normalDataBind);
int mbspVal = std::max(1, x228_MBSP);
if (!x224_29_MBLR)
{
/* Begin quad draw of x2c_particleLists.size() * 4 verts */
}
else
{
/* Begin quad draw of x2c_particleLists.size() * 4 * mbspVal verts */
}
CParticleGlobals::SetEmitterTime(x50_curFrame);
if (!x224_29_MBLR)
{
switch (m_shaderClass)
{
case CElementGenShaders::EShaderClass::Tex:
g_instTexData.clear();
g_instTexData.reserve(x2c_particleLists.size());
break;
case CElementGenShaders::EShaderClass::NoTex:
g_instNoTexData.clear();
g_instNoTexData.reserve(x2c_particleLists.size());
break;
default:
Log.report(LogVisor::FatalError, "unexpected particle shader class");
break;
}
for (CParticleListItem& item : x2c_particleLists)
{
CParticle& particle = g_StaticParticleList[item.x0_partIdx];
@ -1321,11 +1625,36 @@ void CElementGen::RenderParticles()
float size = 0.5f * particle.x2c_lineLengthOrSize;
if (0.f == particle.x30_lineWidthOrRota)
{
/* Draw: */
/* Pos: {viewPoint.x + size, 0.0, viewPoint.z + size} Color: particle.color UV0: {uv[2], uv[3]} */
/* Pos: {viewPoint.x - size, 0.0, viewPoint.z + size} Color: particle.color UV0: {uv[0], uv[3]} */
/* Pos: {viewPoint.x - size, 0.0, viewPoint.z - size} Color: particle.color UV0: {uv[0], uv[1]} */
/* Pos: {viewPoint.x + size, 0.0, viewPoint.z - size} Color: particle.color UV0: {uv[2], uv[1]} */
switch (m_shaderClass)
{
case CElementGenShaders::EShaderClass::Tex:
{
g_instTexData.emplace_back();
SParticleInstanceTex& inst = g_instTexData.back();
inst.pos[0] = Zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z + size, 1.f};
inst.pos[1] = Zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z + size, 1.f};
inst.pos[2] = Zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z - size, 1.f};
inst.pos[3] = Zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z - size, 1.f};
inst.color = particle.x34_color;
inst.uvs[0] = {uvs.xMax, uvs.yMax};
inst.uvs[1] = {uvs.xMin, uvs.yMax};
inst.uvs[2] = {uvs.xMax, uvs.yMin};
inst.uvs[3] = {uvs.xMin, uvs.yMin};
break;
}
case CElementGenShaders::EShaderClass::NoTex:
{
g_instNoTexData.emplace_back();
SParticleInstanceNoTex& inst = g_instNoTexData.back();
inst.pos[0] = Zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z + size, 1.f};
inst.pos[1] = Zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z + size, 1.f};
inst.pos[2] = Zeus::CVector4f{viewPoint.x + size, 0.f, viewPoint.z - size, 1.f};
inst.pos[3] = Zeus::CVector4f{viewPoint.x - size, 0.f, viewPoint.z - size, 1.f};
inst.color = particle.x34_color;
break;
}
default: break;
}
}
else
{
@ -1333,28 +1662,67 @@ void CElementGen::RenderParticles()
float sinT = sinf(theta) * size;
float cosT = sinf(theta) * size;
/* Draw:
viewPoint.x + sinT + cosT;
0.f;
viewPoint.z + cosT - sinT;
viewPoint.x + sinT - cosT;
0.f;
viewPoint.z + sinT + cosT;
viewPoint.x - (sinT + cosT);
0.f;
viewPoint.z - (cosT - sinT);
viewPoint.x + (cosT - sinT);
0.f;
viewPoint.z + (-cosT - sinT);
*/
switch (m_shaderClass)
{
case CElementGenShaders::EShaderClass::Tex:
{
g_instTexData.emplace_back();
SParticleInstanceTex& inst = g_instTexData.back();
inst.pos[0] = Zeus::CVector4f{viewPoint.x + sinT + cosT, 0.f, viewPoint.z + cosT - sinT, 1.f};
inst.pos[1] = Zeus::CVector4f{viewPoint.x + sinT - cosT, 0.f, viewPoint.z + sinT + cosT, 1.f};
inst.pos[2] = Zeus::CVector4f{viewPoint.x + (cosT - sinT), 0.f, viewPoint.z + (-cosT - sinT), 1.f};
inst.pos[3] = Zeus::CVector4f{viewPoint.x - (sinT + cosT), 0.f, viewPoint.z - (cosT - sinT), 1.f};
inst.color = particle.x34_color;
inst.uvs[0] = {uvs.xMax, uvs.yMax};
inst.uvs[1] = {uvs.xMin, uvs.yMax};
inst.uvs[2] = {uvs.xMax, uvs.yMin};
inst.uvs[3] = {uvs.xMin, uvs.yMin};
break;
}
case CElementGenShaders::EShaderClass::NoTex:
{
g_instNoTexData.emplace_back();
SParticleInstanceNoTex& inst = g_instNoTexData.back();
inst.pos[0] = Zeus::CVector4f{viewPoint.x + sinT + cosT, 0.f, viewPoint.z + cosT - sinT, 1.f};
inst.pos[1] = Zeus::CVector4f{viewPoint.x + sinT - cosT, 0.f, viewPoint.z + sinT + cosT, 1.f};
inst.pos[2] = Zeus::CVector4f{viewPoint.x + (cosT - sinT), 0.f, viewPoint.z + (-cosT - sinT), 1.f};
inst.pos[3] = Zeus::CVector4f{viewPoint.x - (sinT + cosT), 0.f, viewPoint.z - (cosT - sinT), 1.f};
inst.color = particle.x34_color;
break;
}
default: break;
}
}
}
switch (m_shaderClass)
{
case CElementGenShaders::EShaderClass::Tex:
m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
CGraphics::DrawInstances(0, 4, g_instTexData.size());
break;
case CElementGenShaders::EShaderClass::NoTex:
m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
break;
default: break;
}
}
else
{
switch (m_shaderClass)
{
case CElementGenShaders::EShaderClass::Tex:
g_instTexData.clear();
g_instTexData.reserve(x2c_particleLists.size() * mbspVal);
break;
case CElementGenShaders::EShaderClass::NoTex:
g_instNoTexData.clear();
g_instNoTexData.reserve(x2c_particleLists.size() * mbspVal);
break;
default:
Log.report(LogVisor::FatalError, "unexpected particle shader class");
break;
}
float mbspFac = 1.f / float(mbspVal);
for (CParticleListItem& item : x2c_particleLists)
{
@ -1388,11 +1756,37 @@ void CElementGen::RenderParticles()
{
vec += mbspVec;
Zeus::CVector3f vec2 = systemCameraMatrix * vec;
/* Draw: */
/* Pos: {vec2.x + size, vec2.y, vec2.z + size} Color: particle.color UV0: {uv[2], uv[3]} */
/* Pos: {vec2.x - size, vec2.y, vec2.z + size} Color: particle.color UV0: {uv[0], uv[3]} */
/* Pos: {vec2.x - size, vec2.y, vec2.z - size} Color: particle.color UV0: {uv[0], uv[1]} */
/* Pos: {vec2.x + size, vec2.y, vec2.z - size} Color: particle.color UV0: {uv[2], uv[1]} */
switch (m_shaderClass)
{
case CElementGenShaders::EShaderClass::Tex:
{
g_instTexData.emplace_back();
SParticleInstanceTex& inst = g_instTexData.back();
inst.pos[0] = Zeus::CVector4f{vec2.x + size, vec2.y, vec2.z + size, 1.f};
inst.pos[1] = Zeus::CVector4f{vec2.x - size, vec2.y, vec2.z + size, 1.f};
inst.pos[2] = Zeus::CVector4f{vec2.x + size, vec2.y, vec2.z - size, 1.f};
inst.pos[3] = Zeus::CVector4f{vec2.x - size, vec2.y, vec2.z - size, 1.f};
inst.color = particle.x34_color;
inst.uvs[0] = {uvs.xMax, uvs.yMax};
inst.uvs[1] = {uvs.xMin, uvs.yMax};
inst.uvs[2] = {uvs.xMax, uvs.yMin};
inst.uvs[3] = {uvs.xMin, uvs.yMin};
break;
}
case CElementGenShaders::EShaderClass::NoTex:
{
g_instNoTexData.emplace_back();
SParticleInstanceNoTex& inst = g_instNoTexData.back();
inst.pos[0] = Zeus::CVector4f{vec2.x + size, vec2.y, vec2.z + size, 1.f};
inst.pos[1] = Zeus::CVector4f{vec2.x - size, vec2.y, vec2.z + size, 1.f};
inst.pos[2] = Zeus::CVector4f{vec2.x + size, vec2.y, vec2.z - size, 1.f};
inst.pos[3] = Zeus::CVector4f{vec2.x - size, vec2.y, vec2.z - size, 1.f};
inst.color = particle.x34_color;
break;
}
default: break;
}
}
}
else
@ -1405,31 +1799,52 @@ void CElementGen::RenderParticles()
{
vec += mbspVec;
Zeus::CVector3f vec2 = systemCameraMatrix * vec;
/* Draw:
vec2.x + sinT + cosT;
vec2.y;
vec2.z + cosT - sinT;
vec2.x + sinT - cosT;
vec2.y;
vec2.z + sinT + cosT;
vec2.x - (sinT + cosT);
vec2.y;
vec2.z - (cosT - sinT);
vec2.x + (cosT - sinT);
vec2.y;
vec2.z + (-cosT - sinT);
*/
}
}
}
}
if (moveRedToAlphaBuffer)
switch (m_shaderClass)
{
/* Restore */
case CElementGenShaders::EShaderClass::Tex:
{
g_instTexData.emplace_back();
SParticleInstanceTex& inst = g_instTexData.back();
inst.pos[0] = Zeus::CVector4f{vec2.x + sinT + cosT, vec2.y, vec2.z + cosT - sinT, 1.f};
inst.pos[1] = Zeus::CVector4f{vec2.x + sinT - cosT, vec2.y, vec2.z + sinT + cosT, 1.f};
inst.pos[2] = Zeus::CVector4f{vec2.x + (cosT - sinT), vec2.y, vec2.z + (-cosT - sinT), 1.f};
inst.pos[3] = Zeus::CVector4f{vec2.x - (sinT + cosT), vec2.y, vec2.z - (cosT - sinT), 1.f};
inst.color = particle.x34_color;
inst.uvs[0] = {uvs.xMax, uvs.yMax};
inst.uvs[1] = {uvs.xMin, uvs.yMax};
inst.uvs[2] = {uvs.xMax, uvs.yMin};
inst.uvs[3] = {uvs.xMin, uvs.yMin};
break;
}
case CElementGenShaders::EShaderClass::NoTex:
{
g_instNoTexData.emplace_back();
SParticleInstanceNoTex& inst = g_instNoTexData.back();
inst.pos[0] = Zeus::CVector4f{vec2.x + sinT + cosT, vec2.y, vec2.z + cosT - sinT, 1.f};
inst.pos[1] = Zeus::CVector4f{vec2.x + sinT - cosT, vec2.y, vec2.z + sinT + cosT, 1.f};
inst.pos[2] = Zeus::CVector4f{vec2.x + (cosT - sinT), vec2.y, vec2.z + (-cosT - sinT), 1.f};
inst.pos[3] = Zeus::CVector4f{vec2.x - (sinT + cosT), vec2.y, vec2.z - (cosT - sinT), 1.f};
inst.color = particle.x34_color;
break;
}
default: break;
}
}
}
}
switch (m_shaderClass)
{
case CElementGenShaders::EShaderClass::Tex:
m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
CGraphics::DrawInstances(0, 4, g_instTexData.size());
break;
case CElementGenShaders::EShaderClass::NoTex:
m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
break;
default: break;
}
}
}
@ -1476,6 +1891,89 @@ void CElementGen::RenderParticlesIndirectTexture()
bool constIndUVs = tind->HasConstantUV();
tind->GetValueUV(partFrame, uvsInd);
if (!desc->x45_30_CIND)
{
/* 1. TEXC
* 2. Indirect TEXC * RASC + PREVC
*/
}
else
{
/* 1. TEXC * RASC
* 2. Indirect TEXC * PREVC
*/
}
/* 1. TEXA
* 2. RASA * PREVA
*/
if (desc->x44_28_SORT)
{
for (CParticleListItem& item : x2c_particleLists)
{
CParticle& particle = g_StaticParticleList[item.x0_partIdx];
item.x4_viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos);
}
std::sort(x2c_particleLists.begin(), x2c_particleLists.end(),
[](const CParticleListItem& a, const CParticleListItem& b) -> bool
{return a.x4_viewPoint[1] >= b.x4_viewPoint[1];});
}
for (CParticleListItem& item : x2c_particleLists)
{
CParticle& particle = g_StaticParticleList[item.x0_partIdx];
int partFrame = x50_curFrame - particle.x28_startFrame;
Zeus::CVector3f viewPoint;
if (desc->x44_28_SORT)
viewPoint = item.x4_viewPoint;
else
viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos);
if (!constTexr)
{
CTexture* tex = texr->GetValueTexture(partFrame).GetObj();
if (tex != cachedTex)
{
tex->Load(0, CTexture::EClampMode::One);
cachedTex = tex;
}
}
if (!constIndTexr)
{
CTexture* tex = tind->GetValueTexture(partFrame).GetObj();
if (tex != cachedIndTex)
{
tex->Load(2, CTexture::EClampMode::One);
cachedIndTex = tex;
}
}
if (!constUVs)
texr->GetValueUV(partFrame, uvs);
if (!constIndUVs)
tind->GetValueUV(partFrame, uvsInd);
float size = 0.5f * particle.x2c_lineLengthOrSize;
Zeus::CVector3f p1 = {viewPoint.x - size, viewPoint.y, viewPoint.z - size};
Zeus::CVector3f p2 = {viewPoint.x + size, viewPoint.y, viewPoint.z + size};
SClipScreenRect clipRect = CGraphics::ClipScreenRectFromMS(p1, p2);
if (!clipRect.x0_valid)
continue;
/* Perform render-to-texture */
/* Draw: */
/* Pos: {viewPoint.x + size, viewPoint.y, viewPoint.z + size} Color: particle.color UV0: {uva[2], uva[3]} UV1: {clip.xmax, clip.ymax} UV2: {uvb[2], uvb[3]} */
/* Pos: {viewPoint.x - size, viewPoint.y, viewPoint.z + size} Color: particle.color UV0: {uva[0], uva[3]} UV1: {clip.xmin, clip.ymax} UV2: {uvb[0], uvb[3]} */
/* Pos: {viewPoint.x - size, viewPoint.y, viewPoint.z - size} Color: particle.color UV0: {uva[0], uva[1]} UV1: {clip.xmin, clip.ymin} UV2: {uvb[0], uvb[1]} */
/* Pos: {viewPoint.x + size, viewPoint.y, viewPoint.z - size} Color: particle.color UV0: {uva[2], uva[1]} UV1: {clip.xmax, clip.ymin} UV2: {uvb[2], uvb[1]} */
}
}
void CElementGen::SetOrientation(const Zeus::CTransform& orientation)

View File

@ -11,6 +11,7 @@
#include "CGraphics.hpp"
#include "CRandom16.hpp"
#include "CParticleGen.hpp"
#include "CElementGenShaders.hpp"
namespace pshag
{
@ -70,9 +71,8 @@ public:
float x30_lineWidthOrRota = 0.f;
Zeus::CColor x34_color = {0.f, 0.f, 0.f, 1.f};
};
protected:
CElementGen(const TToken<CGenDescription>& gen);
private:
friend class CElementGenShaders;
TLockedToken<CGenDescription> x1c_genDesc;
EModelOrientationType x28_orientType;
std::vector<CParticleListItem> x2c_particleLists;
@ -119,7 +119,7 @@ protected:
bool x225_28_warmedUp = false;
bool x225_29_modelsUseLights = false;
bool x226_enableOPTS;
int x228_MBSP;
int x228_MBSP = 0; int m_maxMBSP = 0;
ERglLight x22c_backupLightActive = ERglLight::None;
CRandom16 x230_randState;
std::vector<std::unique_ptr<CElementGen>> x234_activePartChildren;
@ -149,12 +149,22 @@ protected:
float x308_LSLA = 45.f;
Zeus::CColor x30c_moduColor = {1.f, 1.f, 1.f, 1.f};
CElementGenShaders::EShaderClass m_shaderClass;
void AccumulateBounds(Zeus::CVector3f& pos, float size);
public:
CElementGen(const TToken<CGenDescription>& gen, EModelOrientationType orientType, EOptionalSystemFlags flags);
~CElementGen();
boo::GraphicsDataToken m_gfxToken;
boo::IShaderDataBinding* m_normalDataBind = nullptr;
boo::IShaderDataBinding* m_redToAlphaDataBind = nullptr;
boo::IGraphicsBufferD* m_instBuf = nullptr;
boo::IGraphicsBufferD* m_uniformBuf = nullptr;
CGenDescription* GetDesc() {return x1c_genDesc.GetObj();}
static s32 g_FreeIndex;
static bool g_StaticListInitialized;
static int g_ParticleAliveCount;

View File

@ -0,0 +1,77 @@
#ifndef __PSHAG_CELEMENTGENSHADERS_HPP__
#define __PSHAG_CELEMENTGENSHADERS_HPP__
#include "CGraphics.hpp"
#include "boo/graphicsdev/GL.hpp"
#include "boo/graphicsdev/D3D.hpp"
#include "boo/graphicsdev/Metal.hpp"
namespace pshag
{
class CElementGen;
class CElementGenShaders
{
public:
struct IDataBindingFactory
{
virtual void BuildShaderDataBinding(CElementGen& gen,
boo::IShaderPipeline* regPipeline,
boo::IShaderPipeline* redToAlphaPipeline)=0;
};
enum class EShaderClass
{
Tex,
IndTex,
NoTex
};
private:
static boo::IShaderPipeline* m_texZTestZWrite;
static boo::IShaderPipeline* m_texNoZTestZWrite;
static boo::IShaderPipeline* m_texZTestNoZWrite;
static boo::IShaderPipeline* m_texNoZTestNoZWrite;
static boo::IShaderPipeline* m_texAdditiveZTest;
static boo::IShaderPipeline* m_texAdditiveNoZTest;
static boo::IShaderPipeline* m_texRedToAlphaZTest;
static boo::IShaderPipeline* m_texRedToAlphaNoZTest;
static boo::IShaderPipeline* m_indTexZWrite;
static boo::IShaderPipeline* m_indTexNoZWrite;
static boo::IShaderPipeline* m_indTexAdditive;
static boo::IShaderPipeline* m_cindTexZWrite;
static boo::IShaderPipeline* m_cindTexNoZWrite;
static boo::IShaderPipeline* m_cindTexAdditive;
static boo::IShaderPipeline* m_noTexZTestZWrite;
static boo::IShaderPipeline* m_noTexNoZTestZWrite;
static boo::IShaderPipeline* m_noTexZTestNoZWrite;
static boo::IShaderPipeline* m_noTexNoZTestNoZWrite;
static boo::IShaderPipeline* m_noTexAdditiveZTest;
static boo::IShaderPipeline* m_noTexAdditiveNoZTest;
static boo::IVertexFormat* m_vtxFormatTex; /* No OpenGL */
static boo::IVertexFormat* m_vtxFormatIndTex; /* No OpenGL */
static boo::IVertexFormat* m_vtxFormatNoTex; /* No OpenGL */
static std::unique_ptr<IDataBindingFactory> m_bindFactory;
static boo::GraphicsDataToken m_gfxToken;
public:
static IDataBindingFactory* Initialize(boo::GLDataFactory& factory);
#if _WIN32
static IDataBindingFactory* Initialize(boo::ID3DDataFactory& factory);
#elif __APPLE__
static IDataBindingFactory* Initialize(boo::MetalDataFactory& factory);
#endif
static void Initialize();
static EShaderClass GetShaderClass(CElementGen& gen);
static void BuildShaderDataBinding(CElementGen& gen);
};
}
#endif // __PSHAG_CELEMENTGENSHADERS_HPP__

View File

@ -0,0 +1,336 @@
#include "CElementGenShaders.hpp"
#include "CElementGen.hpp"
#include "CGenDescription.hpp"
namespace pshag
{
static const char* VS_GLSL_TEX =
"#version 330\n"
"layout(location=0) in vec3 posIn[4];\n"
"layout(location=4) in vec4 colorIn;\n"
"layout(location=5) in vec2 uvsIn[4];\n"
"\n"
"uniform ParticleUniform\n"
"{\n"
" mat4 mvp;\n"
" vec4 moduColor;\n"
"};\n"
"\n"
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
" vec2 uv;\n"
"};\n"
"\n"
"out VertToFrag vtf;\n"
"void main()\n"
"{\n"
" vtf.color = colorIn * moduColor;\n"
" vtf.uv = uvsIn[gl_VertexID];\n"
" gl_Position = mvp * posIn[gl_VertexID];\n"
"}\n";
static const char* FS_GLSL_TEX =
"#version 330\n"
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
" vec2 uv;\n"
"};\n"
"\n"
"in VertToFrag vtf;\n"
"layout(location=0) out vec4 colorOut;\n"
"uniform sampler2D texs[1];\n"
"void main()\n"
"{\n"
" colorOut = vtf.color * texture(texs[0], vtf.uv);\n"
"}\n";
static const char* FS_GLSL_TEX_REDTOALPHA =
"#version 330\n"
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
" vec2 uv;\n"
"};\n"
"\n"
"in VertToFrag vtf;\n"
"layout(location=0) out vec4 colorOut;\n"
"uniform sampler2D texs[1];\n"
"void main()\n"
"{\n"
" colorOut = vtf.color * texture(texs[0], vtf.uv);\n"
" colorOut.a = colorOut.r;\n"
"}\n";
static const char* VS_GLSL_INDTEX =
"#version 330\n"
"layout(location=0) in vec3 posIn[4];\n"
"layout(location=4) in vec4 colorIn;\n"
"layout(location=5) in vec4 uvsInTexrTind[4];\n"
"layout(location=9) in vec2 uvsInScene[4];\n"
"\n"
"uniform ParticleUniform\n"
"{\n"
" mat4 mvp;\n"
" vec4 moduColor;\n"
"};\n"
"\n"
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
" vec2 uvTexr;\n"
" vec2 uvScene;\n"
" vec2 uvTind;\n"
"};\n"
"\n"
"out VertToFrag vtf;\n"
"void main()\n"
"{\n"
" vtf.color = colorIn * moduColor;\n"
" vtf.uvTexr = uvsInTexrTind[gl_VertexID].xy;\n"
" vtf.uvScene = uvsInScene[gl_VertexID];\n"
" vtf.uvTind = uvsInTexrTind[gl_VertexID].zw;\n"
" gl_Position = mvp * posIn[gl_VertexID];\n"
"}\n";
static const char* FS_GLSL_INDTEX =
"#version 330\n"
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
" vec2 uvTexr;\n"
" vec2 uvScene;\n"
" vec2 uvTind;\n"
"};\n"
"\n"
"in VertToFrag vtf;\n"
"layout(location=0) out vec4 colorOut;\n"
"uniform sampler2D texs[3];\n"
"void main()\n"
"{\n"
" vec2 tindTexel = texture(texs[2], vtf.uvTind);\n"
" vec4 sceneTexel = texture(texs[1], vtf.uvScene + tindTexel);\n"
" vec4 texrTexel = texture(texs[0], vtf.uvTexr);\n"
" colorOut = vtf.color * sceneTexel + texrTexel;\n"
" colorOut.a = vtf.color.a * texrTexel.a;"
"}\n";
static const char* FS_GLSL_CINDTEX =
"#version 330\n"
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
" vec2 uvTexr;\n"
" vec2 uvScene;\n"
" vec2 uvTind;\n"
"};\n"
"\n"
"in VertToFrag vtf;\n"
"layout(location=0) out vec4 colorOut;\n"
"uniform sampler2D texs[3];\n"
"void main()\n"
"{\n"
" vec2 tindTexel = texture(texs[2], vtf.uvTind);\n"
" vec4 sceneTexel = texture(texs[1], vtf.uvScene + tindTexel);\n"
" colorOut = vtf.color * sceneTexel * texture(texs[0], vtf.uvTexr);\n"
"}\n";
static const char* VS_GLSL_NOTEX =
"#version 330\n"
"layout(location=0) in vec3 posIn[4];\n"
"layout(location=4) in vec4 colorIn;\n"
"\n"
"uniform ParticleUniform\n"
"{\n"
" mat4 mvp;\n"
" vec4 moduColor;\n"
"};\n"
"\n"
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
"};\n"
"\n"
"out VertToFrag vtf;\n"
"void main()\n"
"{\n"
" vtf.color = colorIn * moduColor;\n"
" gl_Position = mvp * posIn[gl_VertexID];\n"
"}\n";
static const char* FS_GLSL_NOTEX =
"#version 330\n"
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
"};\n"
"\n"
"in VertToFrag vtf;\n"
"layout(location=0) out vec4 colorOut;\n"
"void main()\n"
"{\n"
" colorOut = vtf.color;\n"
"}\n";
struct DataBindingFactory : CElementGenShaders::IDataBindingFactory
{
void BuildShaderDataBinding(CElementGen& gen,
boo::IShaderPipeline* regPipeline,
boo::IShaderPipeline* redToAlphaPipeline)
{
CGenDescription* desc = gen.GetDesc();
boo::IVertexFormat* vtxFmt = nullptr;
CUVElement* texr = desc->x54_TEXR.get();
CUVElement* tind = desc->x58_TIND.get();
int texCount = 0;
boo::ITexture* textures[3];
if (texr)
{
textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture();
texCount = 1;
if (tind)
{
textures[1] = CGraphics::g_SpareTexture;
textures[2] = tind->GetValueTexture(0).GetObj()->GetBooTexture();
texCount = 3;
const boo::VertexElementDescriptor TexFmtIndTex[] =
{
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 4},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 5},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 6},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 7}
};
vtxFmt = CGraphics::g_BooFactory->newVertexFormat(13, TexFmtIndTex);
}
else
{
const boo::VertexElementDescriptor TexFmtTex[] =
{
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2},
{gen.m_instBuf, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3}
};
vtxFmt = CGraphics::g_BooFactory->newVertexFormat(9, TexFmtTex);
}
}
else
{
const boo::VertexElementDescriptor TexFmtNoTex[] =
{
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3},
{gen.m_instBuf, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}
};
vtxFmt = CGraphics::g_BooFactory->newVertexFormat(5, TexFmtNoTex);
}
boo::IGraphicsBuffer* uniforms[] = {gen.m_uniformBuf};
if (regPipeline)
gen.m_normalDataBind = CGraphics::g_BooFactory->newShaderDataBinding(regPipeline, vtxFmt, nullptr,
gen.m_instBuf, nullptr, 1, uniforms,
texCount, textures);
if (redToAlphaPipeline)
gen.m_redToAlphaDataBind = CGraphics::g_BooFactory->newShaderDataBinding(redToAlphaPipeline, vtxFmt, nullptr,
gen.m_instBuf, nullptr, 1, uniforms,
texCount, textures);
}
};
CElementGenShaders::IDataBindingFactory* CElementGenShaders::Initialize(boo::GLDataFactory& factory)
{
static const char* UniNames[] = {"ParticleUniform"};
m_texZTestZWrite = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
true, true, false);
m_texNoZTestZWrite = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
false, true, false);
m_texZTestNoZWrite = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
true, false, false);
m_texNoZTestNoZWrite = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
false, false, false);
m_texAdditiveZTest = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
true, false, false);
m_texAdditiveNoZTest = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, 1, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
false, false, false);
m_texRedToAlphaZTest = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, 1, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
true, false, false);
m_texRedToAlphaNoZTest = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, 1, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
false, false, false);
m_indTexZWrite = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_INDTEX, 3, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
true, true, false);
m_indTexNoZWrite = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_INDTEX, 3, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
true, false, false);
m_indTexAdditive = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_INDTEX, 3, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
true, true, false);
m_cindTexZWrite = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_CINDTEX, 3, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
true, true, false);
m_cindTexNoZWrite = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_CINDTEX, 3, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
true, false, false);
m_cindTexAdditive = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_CINDTEX, 3, "texs", 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
true, true, false);
m_noTexZTestZWrite = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, 0, nullptr, 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
true, true, false);
m_noTexNoZTestZWrite = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, 0, nullptr, 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
false, true, false);
m_noTexZTestNoZWrite = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, 0, nullptr, 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
true, false, false);
m_noTexNoZTestNoZWrite = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, 0, nullptr, 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
false, false, false);
m_noTexAdditiveZTest = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, 0, nullptr, 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
true, false, false);
m_noTexAdditiveNoZTest = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, 0, nullptr, 1, UniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
false, false, false);
return new struct DataBindingFactory;
}
}

View File

@ -1,3 +1,9 @@
if(WIN32)
set(PLAT_SRCS CElementGenShadersHLSL.cpp)
elseif(APPLE)
set(PLAT_SRCS CElementGenShadersMetal.cpp)
endif()
add_library(RuntimeCommonParticle
IElement.hpp
CGenDescription.hpp CGenDescription.cpp
@ -25,4 +31,7 @@ add_library(RuntimeCommonParticle
CDecalManager.hpp CDecalManager.cpp
CSpawnSystemKeyframeData.hpp CSpawnSystemKeyframeData.cpp
CWarp.hpp CWarp.cpp
CParticleGlobals.hpp CParticleGlobals.cpp)
CParticleGlobals.hpp CParticleGlobals.cpp
CElementGenShaders.hpp
CElementGenShadersGLSL.cpp
${PLAT_SRCS})

@ -1 +1 @@
Subproject commit 524f9e05c3937d68a9f8949ab1c0e84ac003499e
Subproject commit ca6d7ff93bb8cf951d47752c0892258330bf5caa