diff --git a/wowViewerLib/shaders/glsl/vulkan/m2ParticleShader.frag b/wowViewerLib/shaders/glsl/vulkan/m2ParticleShader.frag index 4dde9646d..b72a4df8e 100644 --- a/wowViewerLib/shaders/glsl/vulkan/m2ParticleShader.frag +++ b/wowViewerLib/shaders/glsl/vulkan/m2ParticleShader.frag @@ -10,6 +10,7 @@ layout(location = 1) in vec4 vColor; layout(location = 2) in vec2 vTexcoord0; layout(location = 3) in vec2 vTexcoord1; layout(location = 4) in vec2 vTexcoord2; +layout(location = 5) in float alphaCutoff; #include "../common/commonLightFunctions.glsl" #include "../common/commonFogFunctions.glsl" @@ -88,6 +89,9 @@ void main() { if(finalColor.a < uAlphaTest) discard; + if(finalColor.a < alphaCutoff) + discard; + // vec3 sunDir = // mix( // scene.uInteriorSunDir, diff --git a/wowViewerLib/shaders/glsl/vulkan/m2ParticleShader.vert b/wowViewerLib/shaders/glsl/vulkan/m2ParticleShader.vert index dc3f247aa..b4071ee4b 100644 --- a/wowViewerLib/shaders/glsl/vulkan/m2ParticleShader.vert +++ b/wowViewerLib/shaders/glsl/vulkan/m2ParticleShader.vert @@ -10,6 +10,7 @@ layout(location = 1) in vec4 aColor; layout(location = 2) in vec2 aTexcoord0; layout(location = 3) in vec2 aTexcoord1; layout(location = 4) in vec2 aTexcoord2; +layout(location = 5) in float aAlphaCutoff; layout(location = 0) out vec3 vPosition; @@ -17,6 +18,7 @@ layout(location = 1) out vec4 vColor; layout(location = 2) out vec2 vTexcoord0; layout(location = 3) out vec2 vTexcoord1; layout(location = 4) out vec2 vTexcoord2; +layout(location = 5) out float vAlphaCutoff; #include "../common/commonLightFunctions.glsl" #include "../common/commonFogFunctions.glsl" @@ -38,6 +40,7 @@ void main() { vec4 vertexViewSpace = (scene.uLookAtMat * aPositionVec4); vPosition = vertexViewSpace.xyz; + vAlphaCutoff = aAlphaCutoff; gl_Position = scene.uPMatrix * vertexViewSpace; } \ No newline at end of file diff --git a/wowViewerLib/src/engine/algorithms/grahamScan.cpp b/wowViewerLib/src/engine/algorithms/grahamScan.cpp index 9c97d3673..eb8dcbe5a 100644 --- a/wowViewerLib/src/engine/algorithms/grahamScan.cpp +++ b/wowViewerLib/src/engine/algorithms/grahamScan.cpp @@ -96,13 +96,13 @@ stack grahamScan(std::vector &points) { // has larger polar angle (in counterclockwise // direction) than p1 - std::sort(points.begin()+1, points.end(), [&p0](auto const &p1, auto const &p2) -> int { + std::sort(points.begin()+1, points.end(), [p0](auto const &p1, auto const &p2) -> bool { // Find orientation int o = orientation(p0, p1, p2); if (o == 0) return (distSq(p0, p2) >= distSq(p0, p1))? -1 : 1; - return (o == 2)? -1: 1; + return (o == 2); }); // If two or more points make same angle with p0, diff --git a/wowViewerLib/src/engine/algorithms/mathHelper.cpp b/wowViewerLib/src/engine/algorithms/mathHelper.cpp index 149abf7a4..9e3ecfd48 100644 --- a/wowViewerLib/src/engine/algorithms/mathHelper.cpp +++ b/wowViewerLib/src/engine/algorithms/mathHelper.cpp @@ -192,10 +192,10 @@ std::vector MathHelper::getHullPoints(std::vector &p } mathfu::vec2 centerPoint = mathfu::vec2(0,0); - for (int i = 0; i< hullPoints.size(); i++) { + for (int i = 0; i< hullPointsArr.size(); i++) { centerPoint += hullPointsArr[i].xy(); } - centerPoint = centerPoint * (1.0f / hullPoints.size()); + centerPoint = centerPoint * (1.0f / hullPointsArr.size()); std::sort(hullPointsArr.begin(), hullPointsArr.end(), diff --git a/wowViewerLib/src/engine/managers/particles/particleEmitter.cpp b/wowViewerLib/src/engine/managers/particles/particleEmitter.cpp index 529bfad8d..16f05b53f 100644 --- a/wowViewerLib/src/engine/managers/particles/particleEmitter.cpp +++ b/wowViewerLib/src/engine/managers/particles/particleEmitter.cpp @@ -20,14 +20,14 @@ HGIndexBuffer ParticleEmitter::m_indexVBO = nullptr; static const size_t MAX_PARTICLES_PER_EMITTER = 2000; -static GBufferBinding staticM2ParticleBindings[5] = { - {+m2ParticleShader::Attribute::aPosition, 3, GBindingType::GFLOAT, false, 13*4, 0 }, - {+m2ParticleShader::Attribute::aColor, 4, GBindingType::GFLOAT, false, 13*4, 12}, - {+m2ParticleShader::Attribute::aTexcoord0, 2, GBindingType::GFLOAT, false, 13*4, 28}, - {+m2ParticleShader::Attribute::aTexcoord1, 2, GBindingType::GFLOAT, false, 13*4, 36}, - {+m2ParticleShader::Attribute::aTexcoord2, 2, GBindingType::GFLOAT, false, 13*4, 44}, -}; - +static const std::vector staticM2ParticleBindings = {{ + {+m2ParticleShader::Attribute::aPosition, 3, GBindingType::GFLOAT, false, sizeof(ParticleBuffStruct), offsetof(ParticleBuffStruct, position) }, + {+m2ParticleShader::Attribute::aColor, 4, GBindingType::GFLOAT, false, sizeof(ParticleBuffStruct), offsetof(ParticleBuffStruct, color)}, + {+m2ParticleShader::Attribute::aTexcoord0, 2, GBindingType::GFLOAT, false, sizeof(ParticleBuffStruct), offsetof(ParticleBuffStruct, textCoord0)}, + {+m2ParticleShader::Attribute::aTexcoord1, 2, GBindingType::GFLOAT, false, sizeof(ParticleBuffStruct), offsetof(ParticleBuffStruct, textCoord1)}, + {+m2ParticleShader::Attribute::aTexcoord2, 2, GBindingType::GFLOAT, false, sizeof(ParticleBuffStruct), offsetof(ParticleBuffStruct, textCoord2)}, + {+m2ParticleShader::Attribute::aAlphaCutoff, 1, GBindingType::GFLOAT, false, sizeof(ParticleBuffStruct), offsetof(ParticleBuffStruct, alphaCutoff)}, + }}; enum class ParticleVertexShader : int { None = -1, @@ -89,7 +89,7 @@ static const struct { }; -ParticleEmitter::ParticleEmitter(HApiContainer api, M2Particle *particle, M2Object *m2Object, HM2Geom geom, int txac_val_raw) : m_seed(rand()), m_api(api), m2Object(m2Object) { +ParticleEmitter::ParticleEmitter(HApiContainer api, M2Particle *particle, Exp2Record *exp2, M2Object *m2Object, HM2Geom geom, int txac_val_raw) : m_seed(rand()), m_api(api), m2Object(m2Object) { if (!randTableInited) { for (int i = 0; i < 128; i++) { @@ -98,6 +98,7 @@ ParticleEmitter::ParticleEmitter(HApiContainer api, M2Particle *particle, M2Obje randTableInited = true; } + m_exp2Data = exp2; m_data = particle; txac_particles_value.value = txac_val_raw; @@ -857,6 +858,7 @@ int ParticleEmitter::buildVertex1(CParticle2 &p, ParticlePreRenderData &particle particlePreRenderData.m_particleCenter, particlePreRenderData.m_ageDependentValues.m_timedColor, particlePreRenderData.m_ageDependentValues.m_alpha, + particlePreRenderData.m_ageDependentValues.exp2_unk3, texScaleVec.x, texScaleVec.y, p.texPos); @@ -913,6 +915,7 @@ int ParticleEmitter::buildVertex2(CParticle2 &p, ParticlePreRenderData &particle particlePreRenderData.m_particleCenter, particlePreRenderData.m_ageDependentValues.m_timedColor, particlePreRenderData.m_ageDependentValues.m_alpha, + particlePreRenderData.m_ageDependentValues.exp2_unk3, texScaleVec.x, texScaleVec.y, p.texPos); @@ -1066,6 +1069,12 @@ void ParticleEmitter::fillTimedParticleData(CParticle2 &p, defaultCell = 0; ageDependentValues.timedTailCell = animatePartTrack(percentTime, &m_data->old.tailCellTrack, defaultCell); + ageDependentValues.exp2_unk3 = 0.0f; + if (m_exp2Data != nullptr) { + ageDependentValues.exp2_unk3 = animatePartTrack(percentTime, &m_exp2Data->unk3, ageDependentValues.exp2_unk3); + } + + ageDependentValues.timedTailCell = (ageDependentValues.timedTailCell + m_randomizedTextureIndexMask) & textureIndexMask; float scaleMultiplier = 1.0f; @@ -1090,6 +1099,7 @@ void ParticleEmitter::BuildQuadT3( mathfu::vec3 &m0, mathfu::vec3 &m1, mathfu::vec3 &viewPos, mathfu::vec3 &color, float alpha, + float alphaCutoff, float texStartX, float texStartY, mathfu::vec2 *texPos) { static const float vxs[4] = {-1, -1, 1, 1}; @@ -1125,6 +1135,7 @@ ParticleEmitter::BuildQuadT3( txs[i] * paramXTransform(this->m_data->old.multiTextureParamX[1]) + texPos[1].x, tys[i] * paramXTransform(this->m_data->old.multiTextureParamX[1]) + texPos[1].y); + record.particle[i].alphaCutoff = alphaCutoff; } } diff --git a/wowViewerLib/src/engine/managers/particles/particleEmitter.h b/wowViewerLib/src/engine/managers/particles/particleEmitter.h index e7dd12d88..d400a4572 100644 --- a/wowViewerLib/src/engine/managers/particles/particleEmitter.h +++ b/wowViewerLib/src/engine/managers/particles/particleEmitter.h @@ -32,6 +32,7 @@ struct ParticleBuffStruct { C2Vector textCoord0; //28 C2Vector textCoord1; //36 C2Vector textCoord2; //44 + float alphaCutoff; }; struct ParticleBuffStructQuad { @@ -56,7 +57,7 @@ struct CParticleMaterialFlags { class ParticleEmitter { public: - ParticleEmitter(HApiContainer api, M2Particle *particle, M2Object *m2Object, HM2Geom geom, int txac_val_raw); + ParticleEmitter(HApiContainer api, M2Particle *particle, Exp2Record *exp2, M2Object *m2Object, HM2Geom geom, int txac_val_raw); ~ParticleEmitter() { delete generator; } @@ -81,6 +82,7 @@ class ParticleEmitter { HApiContainer m_api; M2Particle *m_data; + Exp2Record *m_exp2Data = nullptr; M2Object *m2Object; CRndSeed m_seed; @@ -183,8 +185,10 @@ class ParticleEmitter { void BuildQuadT3( - mathfu::vec3 &m0, mathfu::vec3 &m1, mathfu::vec3 &viewPos, mathfu::vec3 &color, float alpha, float texStartX, - float texStartY, mathfu::vec2 *texPos); + mathfu::vec3 &m0, mathfu::vec3 &m1, mathfu::vec3 &viewPos, mathfu::vec3 &color, float alpha, + float alphaCutoff, + float texStartX, + float texStartY, mathfu::vec2 *texPos); struct particleFrame { HGVertexBufferDynamic m_bufferVBO = nullptr; diff --git a/wowViewerLib/src/engine/objects/m2/m2Object.cpp b/wowViewerLib/src/engine/objects/m2/m2Object.cpp index 3a2f17573..50360ee5c 100644 --- a/wowViewerLib/src/engine/objects/m2/m2Object.cpp +++ b/wowViewerLib/src/engine/objects/m2/m2Object.cpp @@ -1632,7 +1632,12 @@ void M2Object::initParticleEmitters() { txacVal = m_m2Geom->txacMParticle[i].value; } - ParticleEmitter *emitter = new ParticleEmitter(m_api, m_m2Geom->getM2Data()->particle_emitters.getElement(i), this, m_m2Geom, txacVal); + Exp2Record *exp2 = nullptr; + if (m_m2Geom->exp2 != nullptr) { + exp2 = m_m2Geom->exp2->content.getElement(i); + } + + ParticleEmitter *emitter = new ParticleEmitter(m_api, m_m2Geom->getM2Data()->particle_emitters.getElement(i), exp2, this, m_m2Geom, txacVal); particleEmitters.push_back(emitter); if (m_m2Geom->exp2 != nullptr && emitter->getGenerator() != nullptr) { emitter->getGenerator()->getAniProp()->zSource = m_m2Geom->exp2->content.getElement(i)->zSource; diff --git a/wowViewerLib/src/engine/shader/ShaderDefinitions.h b/wowViewerLib/src/engine/shader/ShaderDefinitions.h index 7add55634..bdaea4dc3 100644 --- a/wowViewerLib/src/engine/shader/ShaderDefinitions.h +++ b/wowViewerLib/src/engine/shader/ShaderDefinitions.h @@ -68,7 +68,7 @@ struct waterShader { struct m2ParticleShader { enum class Attribute { - aPosition = 0, aColor = 1, aTexcoord0 = 2, aTexcoord1 = 3, aTexcoord2 = 4, m2ParticleShaderAttributeEnd + aPosition = 0, aColor = 1, aTexcoord0 = 2, aTexcoord1 = 3, aTexcoord2 = 4, aAlphaCutoff = 5, m2ParticleShaderAttributeEnd }; }; @@ -168,6 +168,7 @@ const std::unordered_map> attributesPe {"aTexcoord0", 2}, {"aTexcoord1", 3}, {"aTexcoord2", 4}, +{"aAlphaCutoff", 5}, }},{"drawFrustumShader", { {"aPosition", 0}, }},{"drawPoints", { @@ -922,23 +923,23 @@ const std::unordered_map