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
avoid a NaN when dist is 0 as well (which is the case for
directional lights). */
highp float attenuation = clamp(1.0 - pow(dist/max(lightRanges[i], 0.0001), 4.0), 0.0, 1.0)/(1.0 + dist);
attenuation = attenuation*attenuation;
highp float attenuation = clamp(1.0 - pow(dist/max(lightRanges[i], 0.0001), 4.0), 0.0, 1.0);
attenuation = attenuation*attenuation/(1.0 + dist*dist);
highp vec3 normalizedLightDirection = normalize(lightDirections[i].xyz);
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-none.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-specular-color.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}
}}},
{"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(),
{Containers::InPlaceInit, {
/* The range is inf, so it doesn't get fully ambient even at the
edge */
{{8, 71}, 0x242324_rgb},
/* Closest to the light. TODO figure out the equation, sigh */
{{63, 16}, 0xc57474_rgb /*0x222222_rgb + 0xff8080_rgb/(1 + 0.25f*0.25f)*/},
{{8, 71}, 0x2c2727_rgb},
/* Closest to the light */
{{63, 16}, 0x222222_rgb + 0xff8080_rgb/(1 + 0.75f*0.75f)},
/* Specular highlight */
{{60, 19}, 0xfefefe_rgb}
{{60, 19}, 0xc47575_rgb}
}}},
{"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(),
{Containers::InPlaceInit, {
/* Colored specular highlight */
{{60, 19}, 0xf2fcb0_rgb}
{{60, 19}, 0xc27573_rgb}
}}},
{"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(),
{Containers::InPlaceInit, {
/* Colored specular highlight */
{{60, 19}, 0xf2fcb0_rgb}
{{60, 19}, 0xc27573_rgb}
}}},
{"point, attenuated specular", "light-point-attenuated-specular.tga",
{1.0f, -1.0f, -0.25f, 1.0f}, Color3{1.0f}, Color3{1.0f},
@ -423,10 +423,10 @@ const struct {
{Containers::InPlaceInit, {
/* Specular highlight shouldn't be brighter than the attenuated
intensity */
{{57, 22}, 0x665656_rgb}
{{57, 22}, 0xa68787_rgb}
}}},
{"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,
{Containers::InPlaceInit, {
/* Color goes back to ambient at distance = 1.5 */
@ -434,25 +434,25 @@ const struct {
{{29, 50}, 0x222222_rgb},
{{19, 14}, 0x222222_rgb},
/* But the center and specular stays ~ the same */
{{63, 16}, 0xc57474_rgb},
{{60, 19}, 0xf2fcb0_rgb}
{{63, 16}, 0xb16a6a_rgb},
{{60, 19}, 0xad6a69_rgb}
}}},
{"point, intensity=10, range=0.5", "light-point-intensity10-range0.5.tga",
{0.75f, -0.75f, -1.25f, 1.0f}, Color3{1.0f}, Color3{1.0f},
10.0f, 0.5f, {}},
{"point, intensity=10, range=1.0", "light-point-intensity10-range1.0.tga",
{0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, Color3{1.0f},
10.0f, 1.0f, {}},
/* Range ends right at the surface, so no contribution */
{"point, range=0.25", "light-none.tga",
{0.75f, -0.75f, -1.25f, 1.0f}, Color3{1.0f}, Color3{1.0f},
1.0f, 0.25f, {}},
{"point, range=0.75", "light-none.tga",
{0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, Color3{1.0f},
1.0f, 0.75f, {}},
/* Zero range should not cause any NaNs, so the ambient contribution is
still there */
{"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, {}},
/* Distance is 0, which means the direction is always prependicular and
thus contributes nothing */
{"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, {}}
};
@ -1559,7 +1559,7 @@ void PhongGLTest::renderLightsSetOneByOne() {
/* 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 */
.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(1, 0xff8080_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