diff --git a/cont/base/springcontent/shaders/GLSL/ModelFragProg.glsl b/cont/base/springcontent/shaders/GLSL/ModelFragProg.glsl index 58480a69772..acc08ec82b3 100644 --- a/cont/base/springcontent/shaders/GLSL/ModelFragProg.glsl +++ b/cont/base/springcontent/shaders/GLSL/ModelFragProg.glsl @@ -22,7 +22,8 @@ // contains a distance fading factor [for features], and alphaPass is 1.0 // texture alpha-masking is done in both passes uniform vec4 teamColor; - uniform float alphaPass; + uniform vec4 nanoColor; + // uniform float alphaPass; varying vec4 vertexWorldPos; varying vec3 cameraDir; @@ -50,6 +51,43 @@ float GetShadowCoeff(vec4 shadowCoors) #endif } +vec3 DynamicLighting(vec3 normal, vec3 diffuse, vec3 specular) { + vec3 rgb; + + for (int i = 0; i < MAX_DYNAMIC_MODEL_LIGHTS; i++) { + vec3 lightVec = gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].position.xyz - vertexWorldPos.xyz; + vec3 halfVec = gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].halfVector.xyz; + + float lightRadius = gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].constantAttenuation; + float lightDistance = length(lightVec); + float lightScale = float(lightDistance <= lightRadius); + + float lightCosAngDiff = clamp(dot(normal, lightVec / lightDistance), 0.0, 1.0); + float lightCosAngSpec = clamp(dot(normal, normalize(halfVec)), 0.0, 1.0); + #ifdef OGL_SPEC_ATTENUATION + float lightAttenuation = + (gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].constantAttenuation) + + (gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].linearAttenuation * lightDistance) + + (gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].quadraticAttenuation * lightDistance * lightDistance); + + lightAttenuation = 1.0 / max(lightAttenuation, 1.0); + #else + float lightAttenuation = 1.0 - min(1.0, ((lightDistance * lightDistance) / (lightRadius * lightRadius))); + #endif + + float vectorDot = dot((-lightVec / lightDistance), gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].spotDirection); + float cutoffDot = gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].spotCosCutoff; + + lightScale *= float(vectorDot >= cutoffDot); + + rgb += (lightScale * gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].ambient.rgb); + rgb += (lightScale * lightAttenuation * (diffuse.rgb * gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].diffuse.rgb * lightCosAngDiff)); + rgb += (lightScale * lightAttenuation * (specular.rgb * gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].specular.rgb * pow(lightCosAngSpec, 4.0))); + } + + return rgb; +} + void main(void) { #ifdef use_normalmapping @@ -89,40 +127,13 @@ void main(void) #endif #if (DEFERRED_MODE == 0 && MAX_DYNAMIC_MODEL_LIGHTS > 0) - for (int i = 0; i < MAX_DYNAMIC_MODEL_LIGHTS; i++) { - vec3 lightVec = gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].position.xyz - vertexWorldPos.xyz; - vec3 halfVec = gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].halfVector.xyz; - - float lightRadius = gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].constantAttenuation; - float lightDistance = length(lightVec); - float lightScale = (lightDistance > lightRadius)? 0.0: 1.0; - float lightCosAngDiff = clamp(dot(normal, lightVec / lightDistance), 0.0, 1.0); - float lightCosAngSpec = clamp(dot(normal, normalize(halfVec)), 0.0, 1.0); - #ifdef OGL_SPEC_ATTENUATION - float lightAttenuation = - (gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].constantAttenuation) + - (gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].linearAttenuation * lightDistance) + - (gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].quadraticAttenuation * lightDistance * lightDistance); - - lightAttenuation = 1.0 / max(lightAttenuation, 1.0); - #else - float lightAttenuation = 1.0 - min(1.0, ((lightDistance * lightDistance) / (lightRadius * lightRadius))); - #endif - - float vectorDot = dot((-lightVec / lightDistance), gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].spotDirection); - float cutoffDot = gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].spotCosCutoff; - - lightScale *= ((vectorDot < cutoffDot)? 0.0: 1.0); - - gl_FragColor.rgb += (lightScale * gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].ambient.rgb); - gl_FragColor.rgb += (lightScale * lightAttenuation * (diffuse.rgb * gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].diffuse.rgb * lightCosAngDiff)); - gl_FragColor.rgb += (lightScale * lightAttenuation * (specular.rgb * gl_LightSource[BASE_DYNAMIC_MODEL_LIGHT + i].specular.rgb * pow(lightCosAngSpec, 4.0))); - } + gl_FragColor.rgb += DynamicLighting(normal, diffuse, specular); #endif #if (DEFERRED_MODE == 1) gl_FragData[GBUFFER_NORMTEX_IDX] = vec4((normal + vec3(1.0, 1.0, 1.0)) * 0.5, 1.0); gl_FragData[GBUFFER_DIFFTEX_IDX] = vec4(mix(diffuse.rgb, teamColor.rgb, diffuse.a), extraColor.a * teamColor.a); + gl_FragData[GBUFFER_DIFFTEX_IDX] = mix(gl_FragData[GBUFFER_DIFFTEX_IDX], nanoColor, float(nanoColor.a != 0.0)); // do not premultiply reflection, leave it to the deferred lighting pass // gl_FragData[GBUFFER_DIFFTEX_IDX] = vec4(mix(diffuse.rgb, teamColor.rgb, diffuse.a) * reflection, extraColor.a * teamColor.a); // allows standard-lighting reconstruction by lazy LuaMaterials using us @@ -132,6 +143,10 @@ void main(void) #else gl_FragColor.rgb = mix(gl_Fog.color.rgb, gl_FragColor.rgb, fogFactor); // fog gl_FragColor.a = extraColor.a * teamColor.a; // apply one-bit mask + + // wireframe or polygon color + gl_FragColor.rgb *= float(nanoColor.a == 0.0); + gl_FragColor.rgb += (nanoColor.rgb * float(nanoColor.a != 0.0)); #endif } diff --git a/doc/changelog.txt b/doc/changelog.txt index 63fd8d9344c..cc0896d32cc 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -32,7 +32,7 @@ Save/Load: Rendering: - reduce number of team-color updates for custom shaders - use frame-extrapolation for smoother feature movement - - skip drawing being-built units in deferred pass (requires custom shaders) + - draw all model nanoframe stages with shaders by default - skip drawing icons for void-space units AI: @@ -49,6 +49,7 @@ Misc: Bugfixes: - fix invisible OBJ models - fix gl.DeleteShader allowing repeated deletion + - fix drawing of being-built units during deferred pass - fix invisible ground on voidwater maps when AdvMapShading=0 (in L-view) - fix Spring.SetSunLighting crash when AdvMapShading=0 - fix Spring.ValidUnitID to accept nils again diff --git a/rts/Rendering/UnitDrawer.cpp b/rts/Rendering/UnitDrawer.cpp index 883582e5a0a..16c0ee68023 100644 --- a/rts/Rendering/UnitDrawer.cpp +++ b/rts/Rendering/UnitDrawer.cpp @@ -520,8 +520,6 @@ bool CUnitDrawer::CanDrawOpaqueUnit( return false; if (unit->isIcon) return false; - if (unit->beingBuilt && !drawBeingBuiltModels) - return false; if (!(unit->losStatus[gu->myAllyTeam] & LOS_INLOS) && !gu->spectatingFullView) return false; @@ -712,8 +710,6 @@ void CUnitDrawer::SetupAlphaDrawing(bool deferredPass) unitDrawerStates[DRAWER_STATE_SEL] = const_cast(GetWantedDrawerState(true)); unitDrawerStates[DRAWER_STATE_SEL]->Enable(this, deferredPass && false, true); - drawBeingBuiltModels = !deferredPass; - glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -724,8 +720,6 @@ void CUnitDrawer::SetupAlphaDrawing(bool deferredPass) void CUnitDrawer::ResetAlphaDrawing(bool deferredPass) { - drawBeingBuiltModels = true; - unitDrawerStates[DRAWER_STATE_SEL]->Disable(this, deferredPass && false); glPopAttrib(); @@ -958,9 +952,6 @@ void CUnitDrawer::SetupOpaqueDrawing(bool deferredPass) unitDrawerStates[DRAWER_STATE_SEL] = const_cast(GetWantedDrawerState(false)); unitDrawerStates[DRAWER_STATE_SEL]->Enable(this, deferredPass, false); - // should never execute DrawUnitModelBeingBuilt* in a deferred pass - drawBeingBuiltModels = !deferredPass; - // NOTE: // when deferredPass is true we MUST be able to use the SSP render-state // all calling code (reached from DrawOpaquePass(deferred=true)) should @@ -971,8 +962,6 @@ void CUnitDrawer::SetupOpaqueDrawing(bool deferredPass) void CUnitDrawer::ResetOpaqueDrawing(bool deferredPass) { - drawBeingBuiltModels = true; - unitDrawerStates[DRAWER_STATE_SEL]->Disable(this, deferredPass); glPopAttrib(); @@ -1269,6 +1258,7 @@ static const void DrawModelWireBuildStage( glClipPlane(GL_CLIP_PLANE1, lowerPlane); } + // FFP-only drawing still needs raw colors glColorf3(stageColor); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); CUnitDrawer::DrawUnitModel(unit, noLuaCall); @@ -1309,6 +1299,7 @@ static const void DrawModelFillBuildStage( glClipPlane(GL_CLIP_PLANE0, upperPlane); } + glColorf3(stageColor); glPolygonOffset(1.0f, 1.0f); glEnable(GL_POLYGON_OFFSET_FILL); CUnitDrawer::DrawUnitModel(unit, noLuaCall); @@ -1335,9 +1326,6 @@ void CUnitDrawer::DrawUnitModelBeingBuiltShadow(const CUnit* unit, bool noLuaCal void CUnitDrawer::DrawUnitModelBeingBuiltOpaque(const CUnit* unit, bool noLuaCall) { - // could allow the last stage in deferred context, but KISS - assert(unitDrawer->DrawBeingBuiltModels()); - const S3DModel* model = unit->model; const CTeam* team = teamHandler->Team(unit->team); const SColor color = team->color; @@ -1374,25 +1362,31 @@ void CUnitDrawer::DrawUnitModelBeingBuiltOpaque(const CUnit* unit, bool noLuaCal DrawModelBuildStageFunc stageFunc = nullptr; IUnitDrawerState* selState = unitDrawer->GetDrawerState(DRAWER_STATE_SEL); - selState->DisableShaders(unitDrawer); - selState->DisableTextures(unitDrawer); - glPushAttrib(GL_CURRENT_BIT); glEnable(GL_CLIP_PLANE0); glEnable(GL_CLIP_PLANE1); - // wireframe (FFP), unconditional + + selState->SetNanoColor(float4(stageColors[0] * wireColorMult, 1.0f)); + selState->DisableTextures(unitDrawer); + + // wireframe, unconditional stageFunc = drawModelBuildStageFuncs[(STAGE_WIRE + 1) * true]; stageFunc(unit, &upperPlanes[STAGE_WIRE * 4], &lowerPlanes[STAGE_WIRE * 4], stageColors[0] * wireColorMult, noLuaCall); - // flat-colored (FFP), conditional + + selState->SetNanoColor(float4(stageColors[1] * flatColorMult, 1.0f)); + + // flat-colored, conditional stageFunc = drawModelBuildStageFuncs[(STAGE_FLAT + 1) * (stageBounds.z > 0.333f)]; stageFunc(unit, &upperPlanes[STAGE_FLAT * 4], &lowerPlanes[STAGE_FLAT * 4], stageColors[1] * flatColorMult, noLuaCall); glDisable(GL_CLIP_PLANE1); + + // pass alpha=0 so shader will ignore nanoColor + selState->SetNanoColor(float4(stageColors[2], 0.0f)); selState->EnableTextures(unitDrawer); - selState->EnableShaders(unitDrawer); // fully-shaded, conditional stageFunc = drawModelBuildStageFuncs[(STAGE_FILL + 1) * (stageBounds.z > 0.666f)]; @@ -1429,11 +1423,9 @@ void CUnitDrawer::DrawUnitNoTrans( // if called from LuaObjectDrawer, unit has a custom material // - // DrawUnitBeingBuilt effectively disables the current state - // (killing *any* shader that is currently active) while we - // want Lua-material shaders to have full control over build - // visualisation, so keep it simple and make LOD-calls draw - // the full model + // we want Lua-material shaders to have full control over build + // visualisation, so keep it simple and make LOD-calls draw the + // full model // // NOTE: "raw" calls will no longer skip DrawUnitBeingBuilt // diff --git a/rts/Rendering/UnitDrawer.h b/rts/Rendering/UnitDrawer.h index 26f6b770fd2..6e7e7a34947 100644 --- a/rts/Rendering/UnitDrawer.h +++ b/rts/Rendering/UnitDrawer.h @@ -148,8 +148,6 @@ class CUnitDrawer: public CEventClient bool UseAdvShading() const { return advShading; } bool& UseAdvShadingRef() { return advShading; } - bool DrawBeingBuiltModels() const { return drawBeingBuiltModels; } - public: struct TempDrawUnit { const UnitDef* unitDef; diff --git a/rts/Rendering/UnitDrawerState.cpp b/rts/Rendering/UnitDrawerState.cpp index 1e68bf135bd..b93296b5bd4 100644 --- a/rts/Rendering/UnitDrawerState.cpp +++ b/rts/Rendering/UnitDrawerState.cpp @@ -330,12 +330,13 @@ bool UnitDrawerStateGLSL::Init(const CUnitDrawer* ud) { modelShaders[n]->SetUniformLocation("cameraMat"); // idx 7 modelShaders[n]->SetUniformLocation("cameraMatInv"); // idx 8 modelShaders[n]->SetUniformLocation("teamColor"); // idx 9 - modelShaders[n]->SetUniformLocation("sunAmbient"); // idx 10 - modelShaders[n]->SetUniformLocation("sunDiffuse"); // idx 11 - modelShaders[n]->SetUniformLocation("shadowDensity"); // idx 12 - modelShaders[n]->SetUniformLocation("shadowMatrix"); // idx 13 - modelShaders[n]->SetUniformLocation("shadowParams"); // idx 14 - modelShaders[n]->SetUniformLocation("alphaPass"); // idx 15 + modelShaders[n]->SetUniformLocation("nanoColor"); // idx 10 + modelShaders[n]->SetUniformLocation("sunAmbient"); // idx 11 + modelShaders[n]->SetUniformLocation("sunDiffuse"); // idx 12 + modelShaders[n]->SetUniformLocation("shadowDensity"); // idx 13 + modelShaders[n]->SetUniformLocation("shadowMatrix"); // idx 14 + modelShaders[n]->SetUniformLocation("shadowParams"); // idx 15 + // modelShaders[n]->SetUniformLocation("alphaPass"); // idx 16 modelShaders[n]->Enable(); modelShaders[n]->SetUniform1i(0, 0); // diffuseTex (idx 0, texunit 0) @@ -344,10 +345,10 @@ bool UnitDrawerStateGLSL::Init(const CUnitDrawer* ud) { modelShaders[n]->SetUniform1i(3, 3); // reflectTex (idx 3, texunit 3) modelShaders[n]->SetUniform1i(4, 4); // specularTex (idx 4, texunit 4) modelShaders[n]->SetUniform3fv(5, &sky->GetLight()->GetLightDir().x); - modelShaders[n]->SetUniform3fv(10, &sunLighting->unitAmbientColor[0]); - modelShaders[n]->SetUniform3fv(11, &sunLighting->unitDiffuseColor[0]); - modelShaders[n]->SetUniform1f(12, sky->GetLight()->GetUnitShadowDensity()); - modelShaders[n]->SetUniform1f(15, 0.0f); // alphaPass + modelShaders[n]->SetUniform3fv(11, &sunLighting->unitAmbientColor[0]); + modelShaders[n]->SetUniform3fv(12, &sunLighting->unitDiffuseColor[0]); + modelShaders[n]->SetUniform1f(13, sky->GetLight()->GetUnitShadowDensity()); + // modelShaders[n]->SetUniform1f(16, 0.0f); // alphaPass modelShaders[n]->Disable(); modelShaders[n]->Validate(); } @@ -374,8 +375,8 @@ void UnitDrawerStateGLSL::Enable(const CUnitDrawer* ud, bool deferredPass, bool modelShaders[MODEL_SHADER_ACTIVE]->SetUniform3fv(6, &camera->GetPos()[0]); modelShaders[MODEL_SHADER_ACTIVE]->SetUniformMatrix4fv(7, false, camera->GetViewMatrix()); modelShaders[MODEL_SHADER_ACTIVE]->SetUniformMatrix4fv(8, false, camera->GetViewMatrixInverse()); - modelShaders[MODEL_SHADER_ACTIVE]->SetUniformMatrix4fv(13, false, shadowHandler->GetShadowMatrixRaw()); - modelShaders[MODEL_SHADER_ACTIVE]->SetUniform4fv(14, &(shadowHandler->GetShadowParams().x)); + modelShaders[MODEL_SHADER_ACTIVE]->SetUniformMatrix4fv(14, false, shadowHandler->GetShadowMatrixRaw()); + modelShaders[MODEL_SHADER_ACTIVE]->SetUniform4fv(15, &(shadowHandler->GetShadowParams().x)); const_cast(ud->GetLightHandler())->Update(modelShaders[MODEL_SHADER_ACTIVE]); } @@ -397,9 +398,9 @@ void UnitDrawerStateGLSL::UpdateCurrentShaderSky(const CUnitDrawer* ud, const IS for (unsigned int n = MODEL_SHADER_NOSHADOW_STANDARD; n <= MODEL_SHADER_SHADOWED_DEFERRED; n++) { modelShaders[n]->Enable(); modelShaders[n]->SetUniform3fv(5, &skyLight->GetLightDir().x); - modelShaders[n]->SetUniform3fv(10, &sunLighting->unitAmbientColor[0]); - modelShaders[n]->SetUniform3fv(11, &sunLighting->unitDiffuseColor[0]); - modelShaders[n]->SetUniform1f(12, skyLight->GetUnitShadowDensity()); + modelShaders[n]->SetUniform3fv(11, &sunLighting->unitAmbientColor[0]); + modelShaders[n]->SetUniform3fv(12, &sunLighting->unitDiffuseColor[0]); + modelShaders[n]->SetUniform1f(13, skyLight->GetUnitShadowDensity()); modelShaders[n]->Disable(); } } @@ -410,6 +411,11 @@ void UnitDrawerStateGLSL::SetTeamColor(int team, const float2 alpha) const { assert(modelShaders[MODEL_SHADER_ACTIVE]->IsBound()); modelShaders[MODEL_SHADER_ACTIVE]->SetUniform4fv(9, std::move(GetTeamColor(team, alpha.x))); - modelShaders[MODEL_SHADER_ACTIVE]->SetUniform1f(15, alpha.y); + // modelShaders[MODEL_SHADER_ACTIVE]->SetUniform1f(16, alpha.y); +} + +void UnitDrawerStateGLSL::SetNanoColor(const float4& color) const { + assert(modelShaders[MODEL_SHADER_ACTIVE]->IsBound()); + modelShaders[MODEL_SHADER_ACTIVE]->SetUniform4fv(10, color); } diff --git a/rts/Rendering/UnitDrawerState.hpp b/rts/Rendering/UnitDrawerState.hpp index 117f808b372..32ad613c3e0 100644 --- a/rts/Rendering/UnitDrawerState.hpp +++ b/rts/Rendering/UnitDrawerState.hpp @@ -52,6 +52,7 @@ struct IUnitDrawerState { virtual void UpdateCurrentShaderSky(const CUnitDrawer*, const ISkyLight*) const {} virtual void SetTeamColor(int team, const float2 alpha) const = 0; + virtual void SetNanoColor(const float4& color) const {} void SetActiveShader(unsigned int shadowed, unsigned int deferred) { // shadowed=1 --> shader 1 (deferred=0) or 3 (deferred=1) @@ -135,6 +136,7 @@ struct UnitDrawerStateGLSL: public IUnitDrawerState { void UpdateCurrentShaderSky(const CUnitDrawer*, const ISkyLight*) const; void SetTeamColor(int team, const float2 alpha) const; + void SetNanoColor(const float4& color) const; }; #endif