PDA

View Full Version : Sign function not producing expected results

Kerndog73
02-17-2017, 10:49 PM
I'm trying to use the sign function instead of an if becuase it is faster. But it isnt working as expected. This code...

if (sign(max(0,shininess)) == 0) {
specCoef *= 0;
} else if (sign(max(0, shininess)) == 1) {
specCoef *= 1;
}

...behaves as expected. specCoef is set to 0 when shininess is zero and left as is otherwise. But this code...

specCoef *= sign(max(0, shininess));

...doesn't behave as expected. specCoef is sometimes (during the same draw call) set to 0 and sometimes isn't which doesn't make any sense. The sign of 0 should always be 0.

This almost seems like a problem with my OpenGL implementation.

Machine: mid-2013, 13-inch MacBook Air
OS: MacOS El Capitan
OpenGL version: 4.1 INTEL-10.20.23
GLSL version: 4.10
GPU: Intel HD Graphics 5000

Silence
02-19-2017, 03:58 AM
According to this (https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/sign.xhtml), sign can be -1, 0 or +1.

The fact that it can change during the same draw call seems to indicate that shininess value changes.

So, what is shininess ? An uniform ? In that case, it looks strange, right. A varying ? In that case, it looks less strange. A simple variable ? In that case, is it well initialized and/or calculated ?

mhagain
02-19-2017, 04:32 AM
The sign of 0 should always be 0.

-0 is a valid floating-point number.

john_connor
02-19-2017, 04:36 AM
by the way, "shininess" (or as it is named in the wavefront .obj format: Ns) is not allowed to be smaller than 1
so you dont need "sign" or "if", just use:
float shininess = max(1, material.Ns);
vec3 specularIntensity = pow(..., shininess);

Silence
02-19-2017, 07:21 AM
-0 is a valid floating-point number.

Haven't tried it thought, however I would expect that the GLSL sign function would return 0 both when given +0 or -0 as argument. Otherwise this function will be far less attractive.

Kerndog73
02-20-2017, 01:34 PM
John, when shininess is zero, the specular component shouldn't be used. i.e. multiplied by zero.

john_connor
02-20-2017, 03:47 PM
John, when shininess is zero, the specular component shouldn't be used. i.e. multiplied by zero.

i would use the specular component anyway, but i'd make sure that only "reasonable" values are calculated
for example use the GLSL function "clamp(..., 0, 1)" for each light source's base intensity, and "max(0, ...)" for the diffuse / specular factor (the calculated cosine of any angle) as well as for the shininess

why would you discard the specular light ?

Kerndog73
02-21-2017, 12:02 AM
The CPU side sets shininess to 0 when it wants an object to be rendered with lambertian shading.

GClements
02-21-2017, 04:50 AM
But this code...

specCoef *= sign(max(0, shininess));

...doesn't behave as expected. specCoef is sometimes (during the same draw call) set to 0 and sometimes isn't which doesn't make any sense. The sign of 0 should always be 0.

The sign of 0 is zero but the sign of 0.000001 is 1. So any rounding errors will be magnified enormously. Given that a valid shininess shouldn't be less than one, I'd suggest just using clamp() or smoothstep().