Browse Source

Shaders: fix distance attentuation calculation in Phong.

Not that either way would be more correct than the other (this is what
three.js uses I think), but it was documented everywhere to be

    1/(1 + d^2)

but the calculation instead did

   1/(1 + d)^2

This now also means the analytical test equation works. I should have
paid more attention to it not matching before, because that obviously
pointed to this problem.

Point lights are now significantly brighter than before, the tests were
updated to use a larger distance to avoid issues with overflows. Does
not affect the (default) directional lights in any way.
pull/481/head
Vladimír Vondruš 6 years ago
parent
commit
1eb1eec271
  1. 4
      src/Magnum/Shaders/Phong.frag
  2. 2
      src/Magnum/Shaders/Test/CMakeLists.txt
  3. 44
      src/Magnum/Shaders/Test/PhongGLTest.cpp
  4. BIN
      src/Magnum/Shaders/Test/PhongTestFiles/light-point-attenuated-specular.tga
  5. BIN
      src/Magnum/Shaders/Test/PhongTestFiles/light-point-intensity10-range0.5.tga
  6. BIN
      src/Magnum/Shaders/Test/PhongTestFiles/light-point-intensity10-range1.0.tga
  7. BIN
      src/Magnum/Shaders/Test/PhongTestFiles/light-point-range1.5.tga
  8. BIN
      src/Magnum/Shaders/Test/PhongTestFiles/light-point-specular-color.tga
  9. BIN
      src/Magnum/Shaders/Test/PhongTestFiles/light-point.tga
  10. BIN
      src/Magnum/Shaders/Test/PhongTestFiles/low-light-angle.tga

4
src/Magnum/Shaders/Phong.frag

@ -270,8 +270,8 @@ void main() {
/* If range is 0 for whatever reason, clamp it to a small value to /* If range is 0 for whatever reason, clamp it to a small value to
avoid a NaN when dist is 0 as well (which is the case for avoid a NaN when dist is 0 as well (which is the case for
directional lights). */ directional lights). */
highp float attenuation = clamp(1.0 - pow(dist/max(lightRanges[i], 0.0001), 4.0), 0.0, 1.0)/(1.0 + dist); highp float attenuation = clamp(1.0 - pow(dist/max(lightRanges[i], 0.0001), 4.0), 0.0, 1.0);
attenuation = attenuation*attenuation; attenuation = attenuation*attenuation/(1.0 + dist*dist);
highp vec3 normalizedLightDirection = normalize(lightDirections[i].xyz); highp vec3 normalizedLightDirection = normalize(lightDirections[i].xyz);
lowp float intensity = max(0.0, dot(normalizedTransformedNormal, normalizedLightDirection))*attenuation; lowp float intensity = max(0.0, dot(normalizedTransformedNormal, normalizedLightDirection))*attenuation;

2
src/Magnum/Shaders/Test/CMakeLists.txt

@ -244,7 +244,7 @@ if(BUILD_GL_TESTS)
PhongTestFiles/light-directional.tga PhongTestFiles/light-directional.tga
PhongTestFiles/light-none.tga PhongTestFiles/light-none.tga
PhongTestFiles/light-point-attenuated-specular.tga PhongTestFiles/light-point-attenuated-specular.tga
PhongTestFiles/light-point-intensity10-range0.5.tga PhongTestFiles/light-point-intensity10-range1.0.tga
PhongTestFiles/light-point-range1.5.tga PhongTestFiles/light-point-range1.5.tga
PhongTestFiles/light-point-specular-color.tga PhongTestFiles/light-point-specular-color.tga
PhongTestFiles/light-point.tga PhongTestFiles/light-point.tga

44
src/Magnum/Shaders/Test/PhongGLTest.cpp

@ -392,30 +392,30 @@ const struct {
{{40, 40}, 0x222222_rgb + 0xff8080_rgb*dot(Vector3{1.0f, -1.5f, 0.5f}.normalized(), Vector3::zAxis())*2.0f} {{40, 40}, 0x222222_rgb + 0xff8080_rgb*dot(Vector3{1.0f, -1.5f, 0.5f}.normalized(), Vector3::zAxis())*2.0f}
}}}, }}},
{"point", "light-point.tga", {"point", "light-point.tga",
{0.75f, -0.75f, -1.25f, 1.0f}, Color3{1.0f}, Color3{1.0f}, {0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, Color3{1.0f},
1.0f, Constants::inf(), 1.0f, Constants::inf(),
{Containers::InPlaceInit, { {Containers::InPlaceInit, {
/* The range is inf, so it doesn't get fully ambient even at the /* The range is inf, so it doesn't get fully ambient even at the
edge */ edge */
{{8, 71}, 0x242324_rgb}, {{8, 71}, 0x2c2727_rgb},
/* Closest to the light. TODO figure out the equation, sigh */ /* Closest to the light */
{{63, 16}, 0xc57474_rgb /*0x222222_rgb + 0xff8080_rgb/(1 + 0.25f*0.25f)*/}, {{63, 16}, 0x222222_rgb + 0xff8080_rgb/(1 + 0.75f*0.75f)},
/* Specular highlight */ /* Specular highlight */
{{60, 19}, 0xfefefe_rgb} {{60, 19}, 0xc47575_rgb}
}}}, }}},
{"point, specular material color", "light-point-specular-color.tga", {"point, specular material color", "light-point-specular-color.tga",
{0.75f, -0.75f, -1.25f, 1.0f}, 0x80ff80_rgbf, Color3{1.0f}, {0.75f, -0.75f, -0.75f, 1.0f}, 0x80ff80_rgbf, Color3{1.0f},
1.0f, Constants::inf(), 1.0f, Constants::inf(),
{Containers::InPlaceInit, { {Containers::InPlaceInit, {
/* Colored specular highlight */ /* Colored specular highlight */
{{60, 19}, 0xf2fcb0_rgb} {{60, 19}, 0xc27573_rgb}
}}}, }}},
{"point, specular light color", "light-point-specular-color.tga", {"point, specular light color", "light-point-specular-color.tga",
{0.75f, -0.75f, -1.25f, 1.0f}, Color3{1.0f}, 0x80ff80_rgbf, {0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, 0x80ff80_rgbf,
1.0f, Constants::inf(), 1.0f, Constants::inf(),
{Containers::InPlaceInit, { {Containers::InPlaceInit, {
/* Colored specular highlight */ /* Colored specular highlight */
{{60, 19}, 0xf2fcb0_rgb} {{60, 19}, 0xc27573_rgb}
}}}, }}},
{"point, attenuated specular", "light-point-attenuated-specular.tga", {"point, attenuated specular", "light-point-attenuated-specular.tga",
{1.0f, -1.0f, -0.25f, 1.0f}, Color3{1.0f}, Color3{1.0f}, {1.0f, -1.0f, -0.25f, 1.0f}, Color3{1.0f}, Color3{1.0f},
@ -423,10 +423,10 @@ const struct {
{Containers::InPlaceInit, { {Containers::InPlaceInit, {
/* Specular highlight shouldn't be brighter than the attenuated /* Specular highlight shouldn't be brighter than the attenuated
intensity */ intensity */
{{57, 22}, 0x665656_rgb} {{57, 22}, 0xa68787_rgb}
}}}, }}},
{"point, range=1.5, specular color", "light-point-range1.5.tga", {"point, range=1.5, specular color", "light-point-range1.5.tga",
{0.75f, -0.75f, -1.25f, 1.0f}, Color3{1.0f}, 0x80ff80_rgbf, {0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, 0x80ff80_rgbf,
1.0f, 1.5f, 1.0f, 1.5f,
{Containers::InPlaceInit, { {Containers::InPlaceInit, {
/* Color goes back to ambient at distance = 1.5 */ /* Color goes back to ambient at distance = 1.5 */
@ -434,25 +434,25 @@ const struct {
{{29, 50}, 0x222222_rgb}, {{29, 50}, 0x222222_rgb},
{{19, 14}, 0x222222_rgb}, {{19, 14}, 0x222222_rgb},
/* But the center and specular stays ~ the same */ /* But the center and specular stays ~ the same */
{{63, 16}, 0xc57474_rgb}, {{63, 16}, 0xb16a6a_rgb},
{{60, 19}, 0xf2fcb0_rgb} {{60, 19}, 0xad6a69_rgb}
}}}, }}},
{"point, intensity=10, range=0.5", "light-point-intensity10-range0.5.tga", {"point, intensity=10, range=1.0", "light-point-intensity10-range1.0.tga",
{0.75f, -0.75f, -1.25f, 1.0f}, Color3{1.0f}, Color3{1.0f}, {0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, Color3{1.0f},
10.0f, 0.5f, {}}, 10.0f, 1.0f, {}},
/* Range ends right at the surface, so no contribution */ /* Range ends right at the surface, so no contribution */
{"point, range=0.25", "light-none.tga", {"point, range=0.75", "light-none.tga",
{0.75f, -0.75f, -1.25f, 1.0f}, Color3{1.0f}, Color3{1.0f}, {0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, Color3{1.0f},
1.0f, 0.25f, {}}, 1.0f, 0.75f, {}},
/* Zero range should not cause any NaNs, so the ambient contribution is /* Zero range should not cause any NaNs, so the ambient contribution is
still there */ still there */
{"point, range=0.0", "light-none.tga", {"point, range=0.0", "light-none.tga",
{0.75f, -0.75f, -1.25f, 1.0f}, Color3{1.0f}, Color3{1.0f}, {0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, Color3{1.0f},
1.0f, 0.0f, {}}, 1.0f, 0.0f, {}},
/* Distance is 0, which means the direction is always prependicular and /* Distance is 0, which means the direction is always prependicular and
thus contributes nothing */ thus contributes nothing */
{"point, distance=0", "light-none.tga", {"point, distance=0", "light-none.tga",
{0.75f, -0.75f, -1.25f, 1.0f}, Color3{1.0f}, Color3{1.0f}, {0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, Color3{1.0f},
1.0f, 0.0f, {}} 1.0f, 0.0f, {}}
}; };
@ -1559,7 +1559,7 @@ void PhongGLTest::renderLightsSetOneByOne() {
/* First light is directional, from back, so it shouldn't affect the /* First light is directional, from back, so it shouldn't affect the
output at all -- we only want to test that the ID is used properly */ output at all -- we only want to test that the ID is used properly */
.setLightPosition(0, {-1.0f, 1.5f, -0.5f, 0.0f}) .setLightPosition(0, {-1.0f, 1.5f, -0.5f, 0.0f})
.setLightPosition(1, {0.75f, -0.75f, -1.25f, 1.0f}) .setLightPosition(1, {0.75f, -0.75f, -0.75f, 1.0f})
.setLightColor(0, 0x00ffff_rgbf) .setLightColor(0, 0x00ffff_rgbf)
.setLightColor(1, 0xff8080_rgbf) .setLightColor(1, 0xff8080_rgbf)
.setLightSpecularColor(0, 0x0000ff_rgbf) .setLightSpecularColor(0, 0x0000ff_rgbf)

BIN
src/Magnum/Shaders/Test/PhongTestFiles/light-point-attenuated-specular.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/PhongTestFiles/light-point-intensity10-range0.5.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/PhongTestFiles/light-point-intensity10-range1.0.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/PhongTestFiles/light-point-range1.5.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/PhongTestFiles/light-point-specular-color.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/PhongTestFiles/light-point.tga

Binary file not shown.

BIN
src/Magnum/Shaders/Test/PhongTestFiles/low-light-angle.tga

Binary file not shown.
Loading…
Cancel
Save