From bd7a4850f8048ea94134fddbcdec01e94d0a7238 Mon Sep 17 00:00:00 2001 From: Nikolay Borodin Date: Mon, 28 Oct 2024 00:18:27 +0200 Subject: [PATCH] Added awesome shield effect --- data/base/shaders/tcmask_instanced.frag | 22 +++++++++++++-- lib/ivis_opengl/gfx_api.h | 1 + lib/ivis_opengl/gfx_api_gl.cpp | 5 ++-- lib/ivis_opengl/piedraw.cpp | 24 ++++++++++------ lib/ivis_opengl/pietypes.h | 2 ++ src/component.cpp | 37 +++++++++++++++++++++++++ 6 files changed, 78 insertions(+), 13 deletions(-) diff --git a/data/base/shaders/tcmask_instanced.frag b/data/base/shaders/tcmask_instanced.frag index 873941f5d96..8202fd00ed7 100644 --- a/data/base/shaders/tcmask_instanced.frag +++ b/data/base/shaders/tcmask_instanced.frag @@ -26,6 +26,7 @@ uniform int tcmask; // whether a tcmask texture exists for the model uniform int normalmap; // whether a normal map exists for the model uniform int specularmap; // whether a specular map exists for the model uniform int hasTangents; // whether tangents were calculated for model +uniform int shieldEffect; uniform float graphicsCycle; // a periodically cycling value for special effects uniform vec4 sceneColor; //emissive light @@ -74,6 +75,10 @@ out vec4 FragColor; #include "pointlights.frag" #endif +float random(vec2 uv) { + return fract(sin(dot(uv.xy, vec2(12.9898, 78.233))) * 43758.5453123); +} + float getShadowMapDepthComp(vec2 base_uv, float u, float v, vec2 shadowMapSizeInv, int cascadeIndex, float z) { vec2 uv = base_uv + vec2(u, v) * shadowMapSizeInv; @@ -418,8 +423,21 @@ void main() } #ifdef NEWGL - FragColor = fragColour; + if (shieldEffect == 1) { + float cycle = 0.66 + 0.66 * graphicsCycle; + vec3 col = vec3(random(vec2(fragColour.x * cycle, fragColour.y * cycle))); + col.b *= 1.5; + FragColor = vec4(col, fragColour.a / 6.0); + } else { + FragColor = fragColour; + } #else - gl_FragColor = fragColour; + if (shieldEffect == 1) { + vec3 col = vec3(random(vec2(fragColour.x * cycle, fragColour.y * cycle))); + col.b *= 1.5; + gl_FragColor = vec4(col, fragColour.a / 6.0); + } else { + gl_FragColor = fragColour; + } #endif } diff --git a/lib/ivis_opengl/gfx_api.h b/lib/ivis_opengl/gfx_api.h index c22be0a6851..e403d97fd98 100644 --- a/lib/ivis_opengl/gfx_api.h +++ b/lib/ivis_opengl/gfx_api.h @@ -781,6 +781,7 @@ namespace gfx_api int normalMap; int specularMap; int hasTangents; + int shieldEffect; }; // interleaved vertex data diff --git a/lib/ivis_opengl/gfx_api_gl.cpp b/lib/ivis_opengl/gfx_api_gl.cpp index 4424808112a..4c98adf1c50 100644 --- a/lib/ivis_opengl/gfx_api_gl.cpp +++ b/lib/ivis_opengl/gfx_api_gl.cpp @@ -835,7 +835,7 @@ static const std::map shader_to_file_table = // per-frame global uniforms "ProjectionMatrix", "ViewMatrix", "ModelUVLightmapMatrix", "ShadowMapMVPMatrix", "lightPosition", "sceneColor", "ambient", "diffuse", "specular", "fogColor", "ShadowMapCascadeSplits", "ShadowMapSize", "fogEnd", "fogStart", "graphicsCycle", "fogEnabled", "PointLightsPosition", "PointLightsColorAndEnergy", "bucketOffsetAndSize", "PointLightsIndex", "bucketDimensionUsed", "viewportWidth", "viewportHeight", // per-mesh uniforms - "tcmask", "normalmap", "specularmap", "hasTangents" + "tcmask", "normalmap", "specularmap", "hasTangents", "shieldEffect", }, { {"shadowMap", 4}, @@ -860,7 +860,7 @@ static const std::map shader_to_file_table = // per-frame global uniforms "ProjectionMatrix", "ViewMatrix", "ModelUVLightmapMatrix", "ShadowMapMVPMatrix", "lightPosition", "sceneColor", "ambient", "diffuse", "specular", "fogColor", "ShadowMapCascadeSplits", "ShadowMapSize", "fogEnd", "fogStart", "graphicsCycle", "fogEnabled", "PointLightsPosition", "PointLightsColorAndEnergy", "bucketOffsetAndSize", "PointLightsIndex", "bucketDimensionUsed", "viewportWidth", "viewportHeight", // per-mesh uniforms - "tcmask", "normalmap", "specularmap", "hasTangents", + "tcmask", "normalmap", "specularmap", "hasTangents", "shieldEffect", }, { {"shadowMap", 4} @@ -2123,6 +2123,7 @@ void gl_pipeline_state_object::set_constants(const gfx_api::Draw3DShapeInstanced setUniforms(24, cbuf.normalMap); setUniforms(25, cbuf.specularMap); setUniforms(26, cbuf.hasTangents); + setUniforms(27, cbuf.shieldEffect); } void gl_pipeline_state_object::set_constants(const gfx_api::Draw3DShapeInstancedDepthOnlyGlobalUniforms& cbuf) diff --git a/lib/ivis_opengl/piedraw.cpp b/lib/ivis_opengl/piedraw.cpp index e99636e131a..661dcc46bc8 100644 --- a/lib/ivis_opengl/piedraw.cpp +++ b/lib/ivis_opengl/piedraw.cpp @@ -1115,6 +1115,10 @@ bool InstancedMeshRenderer::Draw3DShape(iIMDShape *shape, int frame, PIELIGHT te tshape.stretch = stretchDepth; tshape.modelMatrix = modelMatrix; + if (pieFlag & pie_SHIELD) { + tshape.modelMatrix = glm::scale(tshape.modelMatrix, glm::vec3(pie_SHIELD_FACTOR, pie_SHIELD_FACTOR, pie_SHIELD_FACTOR)); + } + if (pieFlag & pie_HEIGHT_SCALED) // construct { tshape.modelMatrix = glm::scale(tshape.modelMatrix, glm::vec3(1.0f, (float)pieFlagData / (float)pie_RAISE_SCALE, 1.0f)); @@ -1463,7 +1467,7 @@ bool InstancedMeshRenderer::DrawAll(uint64_t currentGameFrame, const glm::mat4& } template -static void drawInstanced3dShapeTemplated_Inner(ShaderOnce& globalsOnce, const gfx_api::Draw3DShapeInstancedGlobalUniforms& globalUniforms, const iIMDShape * shape, gfx_api::buffer* instanceDataBuffer, size_t instanceBufferOffset, size_t instance_count, gfx_api::texture* lightmapTexture) +static void drawInstanced3dShapeTemplated_Inner(ShaderOnce& globalsOnce, const gfx_api::Draw3DShapeInstancedGlobalUniforms& globalUniforms, const iIMDShape * shape, gfx_api::buffer* instanceDataBuffer, size_t instanceBufferOffset, size_t instance_count, gfx_api::texture* lightmapTexture, bool shieldEffect) { const auto& textures = shape->getTextures(); auto* tcmask = textures.tcmaskpage != iV_TEX_INVALID ? &pie_Texture(textures.tcmaskpage) : nullptr; @@ -1471,7 +1475,7 @@ static void drawInstanced3dShapeTemplated_Inner(ShaderOnce& globalsOnce, const g auto* specularmap = textures.specularpage != iV_TEX_INVALID ? &pie_Texture(textures.specularpage) : nullptr; gfx_api::Draw3DShapeInstancedPerMeshUniforms meshUniforms { - tcmask ? 1 : 0, normalmap != nullptr, specularmap != nullptr, shape->buffers[VBO_TANGENT] != nullptr + tcmask ? 1 : 0, normalmap != nullptr, specularmap != nullptr, shape->buffers[VBO_TANGENT] != nullptr, shieldEffect ? 1 : 0 }; gfx_api::buffer* pTangentBuffer = (shape->buffers[VBO_TANGENT] != nullptr) ? shape->buffers[VBO_TANGENT] : getZeroedVertexBuffer(shape->vertexCount * 4 * sizeof(gfx_api::gfxFloat)); @@ -1525,43 +1529,45 @@ static void drawInstanced3dShapeDepthOnly(ShaderOnce& globalsOnce, const gfx_api template static void drawInstanced3dShapeTemplated(ShaderOnce& globalsOnce, const gfx_api::Draw3DShapeInstancedGlobalUniforms& globalUniforms, const iIMDShape * shape, int pieFlag, gfx_api::buffer* instanceDataBuffer, size_t instanceBufferOffset, size_t instance_count, gfx_api::texture* lightmapTexture) { + bool shieldEffect = pieFlag & pie_SHIELD; + /* Set tranlucency */ if (pieFlag & pie_ADDITIVE) { if (!(pieFlag & pie_NODEPTHWRITE)) { - return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture); + return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture, shieldEffect); } else { - return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture); + return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture, shieldEffect); } } else if (pieFlag & pie_TRANSLUCENT) { if (!(pieFlag & pie_NODEPTHWRITE)) { - return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture); + return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture, shieldEffect); } else { - return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture); + return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture, shieldEffect); } } else if (pieFlag & pie_PREMULTIPLIED) { if (!(pieFlag & pie_NODEPTHWRITE)) { - return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture); + return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture, shieldEffect); } else { - return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture); + return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture, shieldEffect); } } else { - return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture); + return drawInstanced3dShapeTemplated_Inner(globalsOnce, globalUniforms, shape, instanceDataBuffer, instanceBufferOffset, instance_count, lightmapTexture, shieldEffect); } } diff --git a/lib/ivis_opengl/pietypes.h b/lib/ivis_opengl/pietypes.h index 84e7ffd69cf..124b954c5d6 100644 --- a/lib/ivis_opengl/pietypes.h +++ b/lib/ivis_opengl/pietypes.h @@ -60,8 +60,10 @@ using nonstd::nullopt; #define pie_PREMULTIPLIED 0x200 #define pie_NODEPTHWRITE 0x400 #define pie_FORCELIGHT 0x800 +#define pie_SHIELD 0x1000 #define pie_RAISE_SCALE 256 +#define pie_SHIELD_FACTOR 1.125f enum LIGHTING_TYPE { diff --git a/src/component.cpp b/src/component.cpp index 1cd1ae553d2..9d9bc053f31 100644 --- a/src/component.cpp +++ b/src/component.cpp @@ -427,11 +427,18 @@ static bool displayCompObj(DROID *psDroid, bool bButton, const glm::mat4& modelM SDWORD iConnector; PROPULSION_STATS *psPropStats; SDWORD pieFlag, iPieData; + SDWORD shieldPieFlag, iShieldPieData; PIELIGHT brightness; UDWORD colour; size_t i = 0; bool didDrawSomething = false; + if (!bButton && psDroid->shieldPoints > 0) { + double factor = static_cast(psDroid->shieldPoints) / droidGetMaxShieldPoints(psDroid); + iShieldPieData = std::round(255.0f * factor); + shieldPieFlag = pie_FORCELIGHT | pie_TRANSLUCENT | pie_SHIELD; + } + glm::mat4 modifiedModelMatrix = modelMatrix2; if (psDroid->timeLastHit - graphicsTime < ELEC_DAMAGE_DURATION && psDroid->lastHitWeapon == WSC_ELECTRONIC && !gamePaused()) @@ -492,6 +499,12 @@ static bool displayCompObj(DROID *psDroid, bool bButton, const glm::mat4& modelM { didDrawSomething = true; } + if (!bButton && psDroid->shieldPoints > 0) { + if (pie_Draw3DShape(psShapeProp->displayModel(), 0, colour, brightness, shieldPieFlag, iShieldPieData, modifiedModelMatrix, viewMatrix, -(psDroid->heightAboveMap))) + { + didDrawSomething = true; + } + } } /* set default components transparent */ @@ -526,6 +539,12 @@ static bool displayCompObj(DROID *psDroid, bool bButton, const glm::mat4& modelM { didDrawSomething = true; } + if (!bButton && psDroid->shieldPoints > 0) { + if (drawShape(strImd, psDroid->timeAnimationStarted, colour, brightness, shieldPieFlag, iShieldPieData, modifiedModelMatrix, viewMatrix, -(psDroid->heightAboveMap))) + { + didDrawSomething = true; + } + } strImd = strImd->next.get(); } } @@ -640,6 +659,12 @@ static bool displayCompObj(DROID *psDroid, bool bButton, const glm::mat4& modelM { didDrawSomething = true; } + if (!bButton && psDroid->shieldPoints > 0) { + if (pie_Draw3DShape(psShape, 0, colour, brightness, shieldPieFlag, iShieldPieData, localModelMatrix, viewMatrix, -localHeightAboveTerrain)) + { + didDrawSomething = true; + } + } } localModelMatrix *= glm::translate(glm::vec3(0, 0, recoilValue)); @@ -673,6 +698,12 @@ static bool displayCompObj(DROID *psDroid, bool bButton, const glm::mat4& modelM { didDrawSomething = true; } + if (!bButton && psDroid->shieldPoints > 0) { + if (pie_Draw3DShape(psShape, 0, colour, brightness, shieldPieFlag, iShieldPieData, localModelMatrix, viewMatrix, -localHeightAboveTerrain)) + { + didDrawSomething = true; + } + } auto flashBaseModel = MUZZLE_FLASH_PIE(psDroid, i); iIMDShape *pMuzzleFlash = (flashBaseModel) ? flashBaseModel->displayModel() : nullptr; drawMuzzleFlash(psDroid->asWeaps[i], psShape, pMuzzleFlash, brightness, pieFlag, iPieData, localModelMatrix, viewMatrix, localHeightAboveTerrain); @@ -827,6 +858,12 @@ static bool displayCompObj(DROID *psDroid, bool bButton, const glm::mat4& modelM { didDrawSomething = true; } + if (!bButton && psDroid->shieldPoints > 0) { + if (pie_Draw3DShape(psShapeProp->displayModel(), 0, colour, brightness, shieldPieFlag, iShieldPieData, modifiedModelMatrix, viewMatrix, -(psDroid->heightAboveMap))) + { + didDrawSomething = true; + } + } } return didDrawSomething;