diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index 30d2e2415b..994e1a0b98 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -751,16 +751,16 @@ namespace SceneUtil std::string generateDummyShader(int maxLightsInScene) { return "#version 120\n" - "#extension GL_ARB_uniform_buffer_object : require\n" - "struct LightData {\n" - " ivec4 packedColors;\n" - " vec4 position;\n" - " vec4 attenuation;\n" - "};\n" - "uniform LightBufferBinding {\n" + "#extension GL_ARB_uniform_buffer_object : require \n" + "struct LightData { \n" + " ivec4 packedColors; \n" + " vec4 position; \n" + " vec4 attenuation; \n" + "}; \n" + "uniform LightBufferBinding { \n" " LightData LightBuffer[" + std::to_string(mLightManager->getMaxLightsInScene()) + "];\n" - "};\n" - "void main() { gl_Position = vec4(0.0); }\n"; + "}; \n" + "void main() { gl_Position = vec4(0.0); } \n"; } LightManager* mLightManager; @@ -917,9 +917,9 @@ namespace SceneUtil if (getLightingMethod() == LightingMethod::PerObjectUniform) { auto* prevUniform = getStateSet()->getUniform("LightBuffer"); - osg::ref_ptr newUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "LightBuffer", getMaxLights() + 1); + osg::ref_ptr newUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, "LightBuffer", getMaxLights()); - for (int i = 0; i < getMaxLights() + 1; ++i) + for (int i = 0; i < getMaxLights(); ++i) { osg::Matrixf prevLightData; prevUniform->getElement(i, prevLightData); @@ -993,7 +993,7 @@ namespace SceneUtil setLightingMethod(LightingMethod::PerObjectUniform); setMaxLights(std::clamp(targetLights, mMaxLightsLowerLimit, LightManager::mMaxLightsUpperLimit)); - stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "LightBuffer", getMaxLights() + 1)); + stateset->addUniform(new osg::Uniform(osg::Uniform::FLOAT_MAT4, "LightBuffer", getMaxLights())); } void LightManager::initSingleUBO(int targetLights) @@ -1047,14 +1047,14 @@ namespace SceneUtil void LightManager::setStartLight(int start) { - if (!usingFFP()) return; - mStartLight = start; + if (!usingFFP()) return; + // Set default light state to zero // This is necessary because shaders don't respect glDisable(GL_LIGHTX) so in addition to disabling // we'll have to set a light state that has no visible effect - for (int i = start; i < getMaxLights(); ++i) + for (int i = start; i < getMaxLights(); ++i) { osg::ref_ptr defaultLight (new DisableLight(i)); getOrCreateStateSet()->setAttributeAndModes(defaultLight, osg::StateAttribute::OFF); @@ -1156,18 +1156,15 @@ namespace SceneUtil osg::BoundingSphere viewBound = osg::BoundingSphere(osg::Vec3f(0,0,0), radius * mPointLightRadiusMultiplier); transformBoundingSphere(worldViewMat, viewBound); - if (!isReflectionCamera) + if (!isReflectionCamera && mPointLightFadeEnd != 0.f) { - static const float fadeDelta = mPointLightFadeEnd - mPointLightFadeStart; - if (mPointLightFadeEnd != 0.f) - { - float fade = 1 - std::clamp((viewBound.center().length() - mPointLightFadeStart) / fadeDelta, 0.f, 1.f); - if (fade == 0.f) - continue; + const float fadeDelta = mPointLightFadeEnd - mPointLightFadeStart; + float fade = 1 - std::clamp((viewBound.center().length() - mPointLightFadeStart) / fadeDelta, 0.f, 1.f); + if (fade == 0.f) + continue; - auto* light = transform.mLightSource->getLight(frameNum); - light->setDiffuse(light->getDiffuse() * fade); - } + auto* light = transform.mLightSource->getLight(frameNum); + light->setDiffuse(light->getDiffuse() * fade); } LightSourceViewBound l; diff --git a/components/sceneutil/lightmanager.hpp b/components/sceneutil/lightmanager.hpp index 27716861f3..1ed87ad7c2 100644 --- a/components/sceneutil/lightmanager.hpp +++ b/components/sceneutil/lightmanager.hpp @@ -228,6 +228,7 @@ namespace SceneUtil float mPointLightRadiusMultiplier; float mPointLightFadeEnd; float mPointLightFadeStart; + float mPointLightFadeDelta; int mMaxLights; diff --git a/files/shaders/lighting.glsl b/files/shaders/lighting.glsl index 5863c24ec5..23b3f94fff 100644 --- a/files/shaders/lighting.glsl +++ b/files/shaders/lighting.glsl @@ -75,25 +75,26 @@ uniform int PointLightCount; void perLightSun(out vec3 ambientOut, out vec3 diffuseOut, vec3 viewPos, vec3 viewNormal) { -#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM - vec3 lightDir = normalize(getLight[0][0].xyz); -#else - vec3 lightDir = normalize(getLight[0].position.xyz); -#endif - #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); -#else + 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 float lambert = dot(viewNormal.xyz, lightDir); + #ifndef GROUNDCOVER lambert = max(lambert, 0.0); #else @@ -105,6 +106,7 @@ void perLightSun(out vec3 ambientOut, out vec3 diffuseOut, vec3 viewPos, vec3 vi } lambert *= clamp(-8.0 * (1.0 - 0.3) * eyeCosine + 1.0, 0.3, 1.0); #endif + diffuseOut = sunDiffuse * lambert; } @@ -118,6 +120,7 @@ void perLightPoint(out vec3 ambientOut, out vec3 diffuseOut, int lightIndex, vec 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]; @@ -181,53 +184,54 @@ void doLighting(vec3 viewPos, vec3 viewNormal, out vec3 diffuseLight, out vec3 a #endif { vec3 ambientOut, diffuseOut; - // This light gets added a second time in the loop to fix Mesa users' slowdown, so we need to negate its contribution here. - perLightSun(ambientOut, diffuseOut, viewPos, viewNormal); + ambientLight = gl_LightModel.ambient.xyz; +// sun light + perLightSun(ambientOut, diffuseOut, viewPos, viewNormal); + ambientLight += ambientOut; #if PER_PIXEL_LIGHTING - diffuseLight = diffuseOut * shadowing - diffuseOut; + diffuseLight = diffuseOut * shadowing; #else shadowDiffuse = diffuseOut; - diffuseLight = -diffuseOut; + diffuseLight = diffuseOut; #endif - ambientLight = gl_LightModel.ambient.xyz; - - perLightSun(ambientOut, diffuseOut, viewPos, viewNormal); - ambientLight += ambientOut; - diffuseLight += diffuseOut; +// 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) { perLightPoint(ambientOut, diffuseOut, PointLightIndex[i], viewPos, viewNormal); -#endif ambientLight += ambientOut; diffuseLight += diffuseOut; } +#endif } vec3 getSpecular(vec3 viewNormal, vec3 viewDirection, float shininess, vec3 matSpec) { -#if @lightingModel == LIGHTING_MODEL_PER_OBJECT_UNIFORM - vec3 sunDir = getLight[0][0].xyz; -#else - vec3 sunDir = getLight[0].position.xyz; -#endif - #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 lightDir = normalize(sunDir);