From ab9c6a1ffbd6ce23a696e323b0f1af2c226b309e Mon Sep 17 00:00:00 2001 From: Beherith Date: Thu, 12 Dec 2024 21:22:13 +0100 Subject: [PATCH] Add another VBO for selected aircraft to draw them after water (#3965) Aircraft, due to often being much higher up in Z, are now drawn in DrawWorld instead of DrawWorldPreUnit to prevent water distortion from affecting them. Note that this causes subtle other rendering problems later, but meh. --- luaui/Widgets/Include/DrawPrimitiveAtUnit.lua | 5 ++- .../Shaders/DrawPrimitiveAtUnit.geom.glsl | 6 +++ .../gui_ground_ao_plates_features_gl4.lua | 2 +- luaui/Widgets/gui_ground_ao_plates_gl4.lua | 3 +- luaui/Widgets/gui_selectedunits_gl4.lua | 42 +++++++++++++++---- luaui/Widgets/gui_unit_energy_icons.lua | 2 +- luaui/Widgets/gui_unit_idlebuilder_icons.lua | 2 +- 7 files changed, 48 insertions(+), 14 deletions(-) diff --git a/luaui/Widgets/Include/DrawPrimitiveAtUnit.lua b/luaui/Widgets/Include/DrawPrimitiveAtUnit.lua index fd50c48d0c0..e1b6a2986db 100644 --- a/luaui/Widgets/Include/DrawPrimitiveAtUnit.lua +++ b/luaui/Widgets/Include/DrawPrimitiveAtUnit.lua @@ -19,7 +19,8 @@ local shaderConfig = { BILLBOARD = 0, -- 1 if you want camera facing billboards, 0 is flat on ground POST_ANIM = " ", -- what you want to do in the animation post function (glsl snippet, see shader source) POST_VERTEX = "v_color = v_color;", -- noop - POST_GEOMETRY = "gl_Position.z = (gl_Position.z) - 256.0 / (gl_Position.w);", --"g_uv.zw = dataIn[0].v_parameters.xy;", -- noop + ZPULL = 256.0, -- how much to pull the z (depth) value towards the camera , 256 is about 16 elmos + POST_GEOMETRY = "", --"g_uv.zw = dataIn[0].v_parameters.xy;", -- noop POST_SHADING = "fragColor.rgba = fragColor.rgba;", -- noop MAXVERTICES = 64, -- The max number of vertices we can emit, make sure this is consistent with what you are trying to draw (tris 3, quads 4, corneredrect 8, circle 64 USE_CIRCLES = 1, -- set to nil if you dont want circles @@ -64,7 +65,7 @@ local function InitDrawPrimitiveAtUnit(shaderConfig, DPATname) shaderSourceCache.shaderName = DPATname .. "Shader GL4" - DrawPrimitiveAtUnitShader = LuaShader.CheckShaderUpdates(shaderSourceCache) + DrawPrimitiveAtUnitShader = LuaShader.CheckShaderUpdates(shaderSourceCache) or DrawPrimitiveAtUnitShader if not DrawPrimitiveAtUnitShader then Spring.Echo("Failed to compile shader for ", DPATname) diff --git a/luaui/Widgets/Shaders/DrawPrimitiveAtUnit.geom.glsl b/luaui/Widgets/Shaders/DrawPrimitiveAtUnit.geom.glsl index 995ce1d6fb1..b805d9b64f2 100644 --- a/luaui/Widgets/Shaders/DrawPrimitiveAtUnit.geom.glsl +++ b/luaui/Widgets/Shaders/DrawPrimitiveAtUnit.geom.glsl @@ -49,6 +49,12 @@ void offsetVertex4(float x, float y, float z, float u, float v, float addRadiusC vec3 vecnorm = normalize(primitiveCoords); PRE_OFFSET gl_Position = cameraViewProj * vec4(centerpos.xyz + rotY * (addRadius * addRadiusCorr * vecnorm + primitiveCoords ), 1.0); + #ifdef ZPULL + // Note that this is a hack that can be used to make sure that the geometry is drawn in front of the unit + // or behind the unit. Positive values will draw the geometry in front of the unit, negative values will draw + // the value is approximately elmos squared, so 512 is 16 elmos + gl_Position.z = (gl_Position.z) - ZPULL / (gl_Position.w); // send 16 elmos forward in depth buffer + #endif g_uv.zw = dataIn[0].v_parameters.zw; POST_GEOMETRY EmitVertex(); diff --git a/luaui/Widgets/gui_ground_ao_plates_features_gl4.lua b/luaui/Widgets/gui_ground_ao_plates_features_gl4.lua index 8489ed80558..e46741a5695 100644 --- a/luaui/Widgets/gui_ground_ao_plates_features_gl4.lua +++ b/luaui/Widgets/gui_ground_ao_plates_features_gl4.lua @@ -232,7 +232,7 @@ function widget:Initialize() shaderConfig.CLIPTOLERANCE = 1.2 -- MATCH CUS position as seed to sin, then pass it through geoshader into fragshader --shaderConfig.POST_VERTEX = "v_parameters.w = max(-0.2, sin(timeInfo.x * 2.0/30.0 + (v_centerpos.x + v_centerpos.z) * 0.1)) + 0.2; // match CUS glow rate" - shaderConfig.POST_GEOMETRY = " gl_Position.z = (gl_Position.z) - 512.0 / (gl_Position.w); // send 16 elmos forward in depth buffer" + shaderConfig.ZPULL = 512.0 -- send 16 elmos forward in depth buffer" shaderConfig.POST_SHADING = "fragColor.rgba = vec4(texcolor.rgb, pow(texcolor.a,0.5) * g_uv.z);" shaderConfig.MAXVERTICES = 4 shaderConfig.USE_CIRCLES = nil diff --git a/luaui/Widgets/gui_ground_ao_plates_gl4.lua b/luaui/Widgets/gui_ground_ao_plates_gl4.lua index 47e3768850a..2efc5cd82de 100644 --- a/luaui/Widgets/gui_ground_ao_plates_gl4.lua +++ b/luaui/Widgets/gui_ground_ao_plates_gl4.lua @@ -118,7 +118,8 @@ function widget:Initialize() shaderConfig.ANIMATION = 0 -- MATCH CUS position as seed to sin, then pass it through geoshader into fragshader shaderConfig.POST_VERTEX = "v_parameters.w = max(-0.2, sin((timeInfo.x + timeInfo.w) * 2.0/30.0 + float(UNITID) * 0.1)) + 0.2; // match CUS glow rate" - shaderConfig.POST_GEOMETRY = "g_uv.w = dataIn[0].v_parameters.w; gl_Position.z = (gl_Position.z) - 512.0 / (gl_Position.w); // send 16 elmos forward in depth buffer" + shaderConfig.ZPULL = 512.0 -- send 16 elmos forward in depth buffer" + shaderConfig.POST_GEOMETRY = "g_uv.w = dataIn[0].v_parameters.w;" -- pass the glow rate to the frag shader shaderConfig.POST_SHADING = "fragColor.rgba = vec4(texcolor.rgb* (1.0 + g_uv.w), texcolor.a * g_uv.z);" shaderConfig.MAXVERTICES = 4 shaderConfig.USE_CIRCLES = nil diff --git a/luaui/Widgets/gui_selectedunits_gl4.lua b/luaui/Widgets/gui_selectedunits_gl4.lua index 9dcc7d249d8..c41813e0bf4 100644 --- a/luaui/Widgets/gui_selectedunits_gl4.lua +++ b/luaui/Widgets/gui_selectedunits_gl4.lua @@ -20,7 +20,11 @@ local selectionHighlight = true local mouseoverHighlight = true ---- GL4 Backend Stuff---- -local selectionVBO = nil +local selectionVBOGround = nil +local selectionVBOAir = nil + +local mapHasWater = (Spring.GetGroundExtremes() < 0) + local selectShader = nil local luaShaderDir = "LuaUI/Widgets/Include/" @@ -103,7 +107,7 @@ local function AddPrimitiveAtUnit(unitID) end --Spring.Echo(unitID,radius,radius, Spring.GetUnitTeam(unitID), numvertices, 1, gf) pushElementInstance( - selectionVBO, -- push into this Instance VBO Table + (unitCanFly[unitDefID] and selectionVBOAir) or selectionVBOGround, -- push into this Instance VBO Table { length, width, cornersize, additionalheight, -- lengthwidthcornerheight unitTeam[unitID], -- teamID @@ -119,9 +123,8 @@ local function AddPrimitiveAtUnit(unitID) ) end -local drawFrame = 0 -function widget:DrawWorldPreUnit() - drawFrame = drawFrame + 1 + +local function DrawSelections(selectionVBO, isAir) if selectionVBO.usedElements > 0 then if hasBadCulling then gl.Culling(false) @@ -131,7 +134,7 @@ function widget:DrawWorldPreUnit() selectShader:Activate() selectShader:SetUniform("iconDistance", 99999) -- pass glStencilTest(true) --https://learnopengl.com/Advanced-OpenGL/Stencil-testing - glDepthTest(true) + glDepthTest(true) -- One really interesting thing is that the depth test does not seem to be obeyed within DrawWorldPreUnit glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE) -- Set The Stencil Buffer To 1 Where Draw Any Polygon this to the shader glClear(GL_STENCIL_BUFFER_BIT ) -- set stencil buffer to 0 @@ -165,7 +168,21 @@ function widget:DrawWorldPreUnit() end end +if mapHasWater then + function widget:DrawWorld() + DrawSelections(selectionVBOAir, true) + end +end + +function widget:DrawWorldPreUnit() + DrawSelections(selectionVBOGround, false) +end + local function RemovePrimitive(unitID) + local selectionVBO + if selectionVBOGround.instanceIDtoIndex[unitID] then selectionVBO = selectionVBOGround end + if selectionVBOAir.instanceIDtoIndex[unitID] then selectionVBO = selectionVBOAir end + if selectionVBO.instanceIDtoIndex[unitID] then if selectionHighlight then unitBufferUniformCache[1] = 0 @@ -287,9 +304,18 @@ local function init() shaderConfig.TEAMCOLORIZATION = teamcolorOpacity -- not implemented, doing it via POST_SHADING below instead shaderConfig.HEIGHTOFFSET = 4 shaderConfig.POST_SHADING = "fragColor.rgba = vec4(mix(g_color.rgb * texcolor.rgb + addRadius, vec3(1.0), "..(1-teamcolorOpacity)..") , texcolor.a * TRANSPARENCY + addRadius);" - selectionVBO, selectShader = InitDrawPrimitiveAtUnit(shaderConfig, "selectedUnits") + selectionVBOGround, selectShader = InitDrawPrimitiveAtUnit(shaderConfig, "selectedUnitsGround") + if mapHasWater then + selectionVBOAir = InitDrawPrimitiveAtUnit(shaderConfig, "selectedUnitsAir") + else + selectionVBOAir = selectionVBOGround + end ClearLastMouseOver() - if selectionVBO == nil then + if selectionVBOGround == nil then + widgetHandler:RemoveWidget() + return false + end + if selectionVBOAir == nil then widgetHandler:RemoveWidget() return false end diff --git a/luaui/Widgets/gui_unit_energy_icons.lua b/luaui/Widgets/gui_unit_energy_icons.lua index 23b8e8f10af..06e52b5cf68 100644 --- a/luaui/Widgets/gui_unit_energy_icons.lua +++ b/luaui/Widgets/gui_unit_energy_icons.lua @@ -104,7 +104,7 @@ local function initGL4() shaderConfig.BREATHESIZE = 0.1 -- MATCH CUS position as seed to sin, then pass it through geoshader into fragshader --shaderConfig.POST_VERTEX = "v_parameters.w = max(-0.2, sin(timeInfo.x * 2.0/30.0 + (v_centerpos.x + v_centerpos.z) * 0.1)) + 0.2; // match CUS glow rate" - shaderConfig.POST_GEOMETRY = " gl_Position.z = (gl_Position.z) - 512.0 / (gl_Position.w); // send 16 elmos forward in depth buffer" + shaderConfig.ZPULL = 512.0 -- send 32 elmos forward in depth buffer" shaderConfig.POST_SHADING = "fragColor.rgba = vec4(texcolor.rgb, texcolor.a * g_uv.z);" shaderConfig.MAXVERTICES = 4 shaderConfig.USE_CIRCLES = nil diff --git a/luaui/Widgets/gui_unit_idlebuilder_icons.lua b/luaui/Widgets/gui_unit_idlebuilder_icons.lua index 0ec2e1c165c..cfe8ab1b758 100644 --- a/luaui/Widgets/gui_unit_idlebuilder_icons.lua +++ b/luaui/Widgets/gui_unit_idlebuilder_icons.lua @@ -62,7 +62,7 @@ local function initGL4() shaderConfig.BREATHESIZE = 0--0.1 -- MATCH CUS position as seed to sin, then pass it through geoshader into fragshader --shaderConfig.POST_VERTEX = "v_parameters.w = max(-0.2, sin(timeInfo.x * 2.0/30.0 + (v_centerpos.x + v_centerpos.z) * 0.1)) + 0.2; // match CUS glow rate" - shaderConfig.POST_GEOMETRY = " gl_Position.z = (gl_Position.z) - 512.0 / (gl_Position.w); // send 16 elmos forward in depth buffer" + shaderConfig.ZPULL = 512.0 -- send 16 elmos forward in depth buffer" shaderConfig.POST_SHADING = "fragColor.rgba = vec4(texcolor.rgb, texcolor.a * g_uv.z);" shaderConfig.MAXVERTICES = 4 shaderConfig.USE_CIRCLES = nil