From d4e7d25d1467b0b031c71e8c015fee42f7387914 Mon Sep 17 00:00:00 2001 From: "glassmancody.info" Date: Thu, 8 Apr 2021 12:42:11 -0700 Subject: [PATCH] Make life not suck for whoever wants to edit lighting shaders --- apps/launcher/advancedpage.cpp | 17 ++- components/sceneutil/lightmanager.cpp | 13 +- files/shaders/CMakeLists.txt | 1 + files/shaders/lighting.glsl | 177 +++----------------------- files/shaders/lighting_util.glsl | 131 +++++++++++++++++++ files/shaders/water_fragment.glsl | 14 +- 6 files changed, 171 insertions(+), 182 deletions(-) create mode 100644 files/shaders/lighting_util.glsl diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index 0aa378805..20cd38cbb 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -1,5 +1,7 @@ #include "advancedpage.hpp" +#include + #include #include #include @@ -7,7 +9,6 @@ #include #include #include -#include #include @@ -126,10 +127,12 @@ bool Launcher::AdvancedPage::loadSettings() loadSettingBool(activeGridObjectPagingCheckBox, "object paging active grid", "Terrain"); viewingDistanceComboBox->setValue(convertToCells(mEngineSettings.getInt("viewing distance", "Camera"))); - auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(mEngineSettings.getString("lighting method", "Shaders")); - if (lightingMethod == SceneUtil::LightingMethod::Undefined) - lightingMethod = SceneUtil::LightingMethod::PerObjectUniform; - lightingMethodComboBox->setCurrentIndex(static_cast(lightingMethod)); + int lightingMethod = 1; + if (mEngineSettings.getString("lighting method", "Shaders") == "legacy") + lightingMethod = 0; + else if (mEngineSettings.getString("lighting method", "Shaders") == "shaders") + lightingMethod = 2; + lightingMethodComboBox->setCurrentIndex(lightingMethod); } // Camera @@ -253,8 +256,8 @@ void Launcher::AdvancedPage::saveSettings() mEngineSettings.setInt("viewing distance", "Camera", convertToUnits(viewingDistance)); } - auto lightingMethodStr = SceneUtil::LightManager::getLightingMethodString(static_cast(lightingMethodComboBox->currentIndex())); - mEngineSettings.setString("lighting method", "Shaders", lightingMethodStr); + static std::unordered_map lightingMethodMap = {{0, "legacy"}, {1, "shaders compatibility"}, {2, "shaders"}}; + mEngineSettings.setString("lighting method", "Shaders", lightingMethodMap[lightingMethodComboBox->currentIndex()]); } // Camera diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index 994e1a0b9..8e330ac1c 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -551,7 +551,7 @@ namespace SceneUtil stateset->setAttributeAndModes(new LightStateAttributePerObjectUniform(std::move(lights), mLightManager), osg::StateAttribute::ON); - stateset->addUniform(new osg::Uniform("PointLightCount", static_cast(lightList.size()))); + stateset->addUniform(new osg::Uniform("PointLightCount", static_cast(lightList.size() + 1))); return stateset; } @@ -894,10 +894,15 @@ namespace SceneUtil defines["maxLights"] = std::to_string(getMaxLights()); defines["maxLightsInScene"] = std::to_string(getMaxLightsInScene()); - defines["lightingModel"] = std::to_string(static_cast(mLightingMethod)); - defines["useUBO"] = std::to_string(mLightingMethod == LightingMethod::SingleUBO); + defines["lightingMethodFFP"] = getLightingMethod() == LightingMethod::FFP ? "1" : "0"; + defines["lightingMethodPerObjectUniform"] = getLightingMethod() == LightingMethod::PerObjectUniform ? "1" : "0"; + defines["lightingMethodUBO"] = getLightingMethod() == LightingMethod::SingleUBO ? "1" : "0"; + defines["useUBO"] = std::to_string(getLightingMethod() == LightingMethod::SingleUBO); // exposes bitwise operators - defines["useGPUShader4"] = std::to_string(mLightingMethod == LightingMethod::SingleUBO); + defines["useGPUShader4"] = std::to_string(getLightingMethod() == LightingMethod::SingleUBO); + defines["getLight"] = getLightingMethod() == LightingMethod::FFP ? "gl_LightSource" : "LightBuffer"; + defines["startLight"] = getLightingMethod() == LightingMethod::SingleUBO ? "0" : "1"; + defines["endLight"] = getLightingMethod() == LightingMethod::FFP ? defines["maxLights"] : "PointLightCount"; return defines; } diff --git a/files/shaders/CMakeLists.txt b/files/shaders/CMakeLists.txt index e06dfe56a..c4a863776 100644 --- a/files/shaders/CMakeLists.txt +++ b/files/shaders/CMakeLists.txt @@ -18,6 +18,7 @@ set(SHADER_FILES terrain_vertex.glsl terrain_fragment.glsl lighting.glsl + lighting_util.glsl parallax.glsl s360_fragment.glsl s360_vertex.glsl diff --git a/files/shaders/lighting.glsl b/files/shaders/lighting.glsl index 23b3f94ff..ff8fa8969 100644 --- a/files/shaders/lighting.glsl +++ b/files/shaders/lighting.glsl @@ -1,98 +1,9 @@ -#define LIGHTING_MODEL_FFP 0 -#define LIGHTING_MODEL_PER_OBJECT_UNIFORM 1 -#define LIGHTING_MODEL_SINGLE_UBO 2 +#include "lighting_util.glsl" -#if @lightingModel != LIGHTING_MODEL_FFP -#define getLight LightBuffer - -float quickstep(float x) -{ - x = clamp(x, 0.0, 1.0); - x = 1.0 - x*x; - x = 1.0 - x*x; - return x; -} - -#if @lightingModel == LIGHTING_MODEL_SINGLE_UBO - -const int mask = int(0xff); -const ivec4 shift = ivec4(int(0), int(8), int(16), int(24)); - -vec3 unpackRGB(int data) -{ - return vec3( (float(((data >> shift.x) & mask)) / 255.0) - ,(float(((data >> shift.y) & mask)) / 255.0) - ,(float(((data >> shift.z) & mask)) / 255.0)); -} - -vec4 unpackRGBA(int data) -{ - return vec4( (float(((data >> shift.x) & mask)) / 255.0) - ,(float(((data >> shift.y) & mask)) / 255.0) - ,(float(((data >> shift.z) & mask)) / 255.0) - ,(float(((data >> shift.w) & mask)) / 255.0)); -} - -/* Layout: -packedColors: 8-bit unsigned RGB packed as (diffuse, ambient, specular). - sign bit is stored in unused alpha component -attenuation: constant, linear, quadratic, light radius (as defined in content) -*/ -struct LightData -{ - ivec4 packedColors; - vec4 position; - vec4 attenuation; -}; - -uniform int PointLightIndex[@maxLights]; -uniform int PointLightCount; - -// Defaults to shared layout. If we ever move to GLSL 140, std140 layout should be considered -uniform LightBufferBinding +void perLightSun(out vec3 diffuseOut, vec3 viewPos, vec3 viewNormal) { - LightData LightBuffer[@maxLightsInScene]; -}; - -#else - -/* Layout: ---------------------------------------- ----------- -| pos_x | ambi_r | diff_r | spec_r | -| pos_y | ambi_g | diff_g | spec_g | -| pos_z | ambi_b | diff_b | spec_b | -| att_c | att_l | att_q | radius/spec_a | - -------------------------------------------------- -*/ -uniform mat4 LightBuffer[@maxLights]; -uniform int PointLightCount; - -#endif - -#else -#define getLight gl_LightSource -#endif - -void perLightSun(out vec3 ambientOut, out vec3 diffuseOut, vec3 viewPos, vec3 viewNormal) -{ -#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM - ambientOut = getLight[0][1].xyz; - - vec3 sunDiffuse = getLight[0][2].xyz; - vec3 lightDir = normalize(getLight[0][0].xyz); -#elif @lightingModel == LIGHTING_MODEL_SINGLE_UBO - ivec4 data = getLight[0].packedColors; - ambientOut = unpackRGB(data.y); - - vec3 sunDiffuse = unpackRGB(data.x); - vec3 lightDir = normalize(getLight[0].position.xyz); -#else // LIGHTING_MODEL_SINGLE_UBO - ambientOut = getLight[0].ambient.xyz; - - vec3 sunDiffuse = getLight[0].diffuse.xyz; - vec3 lightDir = normalize(getLight[0].position.xyz); -#endif - + vec3 sunDiffuse = lcalcDiffuse(0).xyz; + vec3 lightDir = normalize(lcalcPosition(0).xyz); float lambert = dot(viewNormal.xyz, lightDir); #ifndef GROUNDCOVER @@ -112,21 +23,12 @@ void perLightSun(out vec3 ambientOut, out vec3 diffuseOut, vec3 viewPos, vec3 vi void perLightPoint(out vec3 ambientOut, out vec3 diffuseOut, int lightIndex, vec3 viewPos, vec3 viewNormal) { -#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM - vec3 lightPos = getLight[lightIndex][0].xyz - viewPos; -#else - vec3 lightPos = getLight[lightIndex].position.xyz - viewPos; -#endif - + vec3 lightPos = lcalcPosition(lightIndex) - viewPos; float lightDistance = length(lightPos); // cull non-FFP point lighting by radius, light is guaranteed to not fall outside this bound with our cutoff -#if @lightingModel != LIGHTING_MODEL_FFP -#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM - float radius = getLight[lightIndex][3][3]; -#else - float radius = getLight[lightIndex].attenuation.w; -#endif +#if !@lightingMethodFFP + float radius = lcalcRadius(lightIndex); if (lightDistance > radius * 2.0) { @@ -138,22 +40,8 @@ void perLightPoint(out vec3 ambientOut, out vec3 diffuseOut, int lightIndex, vec lightPos = normalize(lightPos); -#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM - float illumination = clamp(1.0 / (getLight[lightIndex][0].w + getLight[lightIndex][1].w * lightDistance + getLight[lightIndex][2].w * lightDistance * lightDistance), 0.0, 1.0); - illumination *= 1.0 - quickstep((lightDistance / radius) - 1.0); - - ambientOut = getLight[lightIndex][1].xyz * illumination; -#elif @lightingModel == LIGHTING_MODEL_SINGLE_UBO - float illumination = clamp(1.0 / (getLight[lightIndex].attenuation.x + getLight[lightIndex].attenuation.y * lightDistance + getLight[lightIndex].attenuation.z * lightDistance * lightDistance), 0.0, 1.0); - illumination *= 1.0 - quickstep((lightDistance / radius) - 1.0); - - ivec4 data = getLight[lightIndex].packedColors; - ambientOut = unpackRGB(data.y) * illumination; -#else - float illumination = clamp(1.0 / (getLight[lightIndex].constantAttenuation + getLight[lightIndex].linearAttenuation * lightDistance + getLight[lightIndex].quadraticAttenuation * lightDistance * lightDistance), 0.0, 1.0); - ambientOut = getLight[lightIndex].ambient.xyz * illumination; -#endif - + float illumination = lcalcIllumination(lightIndex, lightDistance); + ambientOut = lcalcAmbient(lightIndex) * illumination; float lambert = dot(viewNormal.xyz, lightPos) * illumination; #ifndef GROUNDCOVER @@ -168,13 +56,7 @@ void perLightPoint(out vec3 ambientOut, out vec3 diffuseOut, int lightIndex, vec lambert *= clamp(-8.0 * (1.0 - 0.3) * eyeCosine + 1.0, 0.3, 1.0); #endif -#if @lightingModel == LIGHTING_MODEL_SINGLE_UBO - diffuseOut = unpackRGB(data.x) * lambert * float(int(data.w)); -#elif @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM - diffuseOut = getLight[lightIndex][2].xyz * lambert; -#else - diffuseOut = getLight[lightIndex].diffuse.xyz * lambert; -#endif + diffuseOut = lcalcDiffuse(lightIndex) * lambert; } #if PER_PIXEL_LIGHTING @@ -186,9 +68,7 @@ void doLighting(vec3 viewPos, vec3 viewNormal, out vec3 diffuseLight, out vec3 a vec3 ambientOut, diffuseOut; ambientLight = gl_LightModel.ambient.xyz; -// sun light - perLightSun(ambientOut, diffuseOut, viewPos, viewNormal); - ambientLight += ambientOut; + perLightSun(diffuseOut, viewPos, viewNormal); #if PER_PIXEL_LIGHTING diffuseLight = diffuseOut * shadowing; #else @@ -196,43 +76,22 @@ void doLighting(vec3 viewPos, vec3 viewNormal, out vec3 diffuseLight, out vec3 a diffuseLight = diffuseOut; #endif -// point lights -#if @lightingModel == LIGHTING_MODEL_FFP - for (int i=1; i < @maxLights; ++i) - { - perLightPoint(ambientOut, diffuseOut, i, viewPos, viewNormal); - ambientLight += ambientOut; - diffuseLight += diffuseOut; - } -#elif @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM - for (int i=1; i <= PointLightCount; ++i) - { - perLightPoint(ambientOut, diffuseOut, i, viewPos, viewNormal); - ambientLight += ambientOut; - diffuseLight += diffuseOut; - } -#else - for (int i=0; i < PointLightCount; ++i) + for (int i = @startLight; i < @endLight; ++i) { +#if @lightingMethodUBO perLightPoint(ambientOut, diffuseOut, PointLightIndex[i], viewPos, viewNormal); +#else + perLightPoint(ambientOut, diffuseOut, i, viewPos, viewNormal); +#endif ambientLight += ambientOut; diffuseLight += diffuseOut; } -#endif } vec3 getSpecular(vec3 viewNormal, vec3 viewDirection, float shininess, vec3 matSpec) { -#if @lightingModel == LIGHTING_MODEL_SINGLE_UBO - vec3 sunDir = getLight[0].position.xyz; - vec3 sunSpec = unpackRGB(getLight[0].packedColors.z); -#elif @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM - vec3 sunDir = getLight[0][0].xyz; - vec3 sunSpec = getLight[0][3].xyz; -#else - vec3 sunSpec = getLight[0].specular.xyz; - vec3 sunDir = getLight[0].position.xyz; -#endif + vec3 sunDir = lcalcPosition(0); + vec3 sunSpec = lcalcSpecular(0).xyz; vec3 lightDir = normalize(sunDir); float NdotL = dot(viewNormal, lightDir); diff --git a/files/shaders/lighting_util.glsl b/files/shaders/lighting_util.glsl new file mode 100644 index 000000000..6277d9d0b --- /dev/null +++ b/files/shaders/lighting_util.glsl @@ -0,0 +1,131 @@ +#if !@lightingMethodFFP +float quickstep(float x) +{ + x = clamp(x, 0.0, 1.0); + x = 1.0 - x*x; + x = 1.0 - x*x; + return x; +} +#endif + +#if @lightingMethodUBO + +const int mask = int(0xff); +const ivec4 shift = ivec4(int(0), int(8), int(16), int(24)); + +vec3 unpackRGB(int data) +{ + return vec3( (float(((data >> shift.x) & mask)) / 255.0) + ,(float(((data >> shift.y) & mask)) / 255.0) + ,(float(((data >> shift.z) & mask)) / 255.0)); +} + +vec4 unpackRGBA(int data) +{ + return vec4( (float(((data >> shift.x) & mask)) / 255.0) + ,(float(((data >> shift.y) & mask)) / 255.0) + ,(float(((data >> shift.z) & mask)) / 255.0) + ,(float(((data >> shift.w) & mask)) / 255.0)); +} + +/* Layout: +packedColors: 8-bit unsigned RGB packed as (diffuse, ambient, specular). + sign bit is stored in unused alpha component +attenuation: constant, linear, quadratic, light radius (as defined in content) +*/ +struct LightData +{ + ivec4 packedColors; + vec4 position; + vec4 attenuation; +}; + +uniform int PointLightIndex[@maxLights]; +uniform int PointLightCount; + +// Defaults to shared layout. If we ever move to GLSL 140, std140 layout should be considered +uniform LightBufferBinding +{ + LightData LightBuffer[@maxLightsInScene]; +}; + +#elif @lightingMethodPerObjectUniform + +/* Layout: +--------------------------------------- ----------- +| pos_x | ambi_r | diff_r | spec_r | +| pos_y | ambi_g | diff_g | spec_g | +| pos_z | ambi_b | diff_b | spec_b | +| att_c | att_l | att_q | radius/spec_a | + -------------------------------------------------- +*/ +uniform mat4 LightBuffer[@maxLights]; +uniform int PointLightCount; + +#endif + +#if !@lightingMethodFFP +float lcalcRadius(int lightIndex) +{ +#if @lightingMethodPerObjectUniform + return @getLight[lightIndex][3].w; +#else + return @getLight[lightIndex].attenuation.w; +#endif +} +#endif + +float lcalcIllumination(int lightIndex, float lightDistance) +{ +#if @lightingMethodPerObjectUniform + float illumination = clamp(1.0 / (@getLight[lightIndex][0].w + @getLight[lightIndex][1].w * lightDistance + @getLight[lightIndex][2].w * lightDistance * lightDistance), 0.0, 1.0); + return (illumination * (1.0 - quickstep((lightDistance / lcalcRadius(lightIndex)) - 1.0))); +#elif @lightingMethodUBO + float illumination = clamp(1.0 / (@getLight[lightIndex].attenuation.x + @getLight[lightIndex].attenuation.y * lightDistance + @getLight[lightIndex].attenuation.z * lightDistance * lightDistance), 0.0, 1.0); + return (illumination * (1.0 - quickstep((lightDistance / lcalcRadius(lightIndex)) - 1.0))); +#else + return clamp(1.0 / (@getLight[lightIndex].constantAttenuation + @getLight[lightIndex].linearAttenuation * lightDistance + @getLight[lightIndex].quadraticAttenuation * lightDistance * lightDistance), 0.0, 1.0); +#endif +} + +vec3 lcalcPosition(int lightIndex) +{ +#if @lightingMethodPerObjectUniform + return @getLight[lightIndex][0].xyz; +#else + return @getLight[lightIndex].position.xyz; +#endif +} + +vec3 lcalcDiffuse(int lightIndex) +{ +#if @lightingMethodPerObjectUniform + return @getLight[lightIndex][2].xyz; +#elif @lightingMethodUBO + return unpackRGB(@getLight[lightIndex].packedColors.x) * float(int(@getLight[lightIndex].packedColors.w)); +#else + return @getLight[lightIndex].diffuse.xyz; +#endif +} + +vec3 lcalcAmbient(int lightIndex) +{ +#if @lightingMethodPerObjectUniform + return @getLight[lightIndex][1].xyz; +#elif @lightingMethodUBO + return unpackRGB(@getLight[lightIndex].packedColors.y); +#else + return @getLight[lightIndex].ambient.xyz; +#endif +} + +vec4 lcalcSpecular(int lightIndex) +{ +#if @lightingMethodPerObjectUniform + return @getLight[lightIndex][3]; +#elif @lightingMethodUBO + return unpackRGBA(@getLight[lightIndex].packedColors.z); +#else + return @getLight[lightIndex].specular; +#endif +} diff --git a/files/shaders/water_fragment.glsl b/files/shaders/water_fragment.glsl index 9bc156705..24c93d11a 100644 --- a/files/shaders/water_fragment.glsl +++ b/files/shaders/water_fragment.glsl @@ -203,11 +203,7 @@ void main(void) normal3 * midWaves.y + normal4 * smallWaves.x + normal5 * smallWaves.y + rippleAdd); normal = normalize(vec3(-normal.x * bump, -normal.y * bump, normal.z)); -#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM - vec3 lVec = normalize((gl_ModelViewMatrixInverse * vec4(getLight[0][0].xyz, 0.0)).xyz); -#else - vec3 lVec = normalize((gl_ModelViewMatrixInverse * vec4(getLight[0].position.xyz, 0.0)).xyz); -#endif + vec3 lVec = normalize((gl_ModelViewMatrixInverse * vec4(lcalcPosition(0).xyz, 0.0)).xyz); vec3 cameraPos = (gl_ModelViewMatrixInverse * vec4(0,0,0,1)).xyz; vec3 vVec = normalize(position.xyz - cameraPos.xyz); @@ -242,13 +238,7 @@ void main(void) vec3 waterColor = WATER_COLOR * sunFade; -#if @lightingModel == LIGHTING_MODEL_SINGLE_UBO - vec4 sunSpec = unpackRGBA(getLight[0].packedColors.z); -#elif @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM - vec4 sunSpec = getLight[0][3]; -#else - vec4 sunSpec = getLight[0].specular; -#endif + vec4 sunSpec = lcalcSpecular(0); #if REFRACTION // refraction