Shader functions pow and log glitch: fragment shader output color flickers to black [deferred r.]

Edit: see reply #9 Shader functions pow and log glitch: fragment shader output color flickers to black [deferred r.] - Unity Engine - Unity Discussions

custom shader:

outputColor.rgb = lerp(_Color.rgb, _LightColor.rgb, value);

and

outputColor.rgb = _Color.rgb + (_LightColor.rgb - _Color.rgb) * value;

fragment output flickers between color and black over frames [deferred rendering].

_Color is constant property, _LightColor varies over time, value is continuous from 0 to 1 over time.

outputColor.rgb = _Color.rgb;  // constant
outputColor.rgb = value;  // continous shades of grey over time
outputColor.rgb = _LightColor.rgb;  // varies over time
outputColor.rgb = (_LightColor.rgb - _Color.rgb) * value;  // "delta color" "modulated" as expected
outputColor.rgb = _Color.rgb * value;  // even this color "modulated" continuously

but “sum of all parts” flickers.

Anyone an idea why this is? which?

Hoping for a finding.

2021.1.1

_LightColor isn’t supposed to be valid during deferred rendering. The fact it shows something at all is kind of the bug.

The whole idea behind deferred rendering is when you’re rendering the objects themselves, you don’t know anything about the lighting of the scene. Most real time games modify this a bit such that they’ll know about fully baked direct / baked ambient lighting, but any real time lights the shader intentionally has no knowledge of. If something like _LightColor is still set with any value during the rendering of an object during deferred rendering it’s because it wasn’t unset from the previous time it was set to something. But that doesn’t mean it’ll be at all valid.

Or it means the object you’re rendering isn’t opaque, thus its being rendered using forward rendering and not deferred.

Sure? See attachment. But perhaps i forgot to include the cginc

Is the custom shader one you have directly on an object, or is it a copy of Internal-DeferredShading.shader that you’re overriding in the Graphics settings. If it’s on the object, then you can’t rely on _LightColor. If it’s an override of the internal shader, then what you have should work, though you’d need to be setting _Color as a shader global.

The shader is on a material which is the single material assigned to a meshrenderer of a mesh on a GameObject

are you implying unitys documentation is unsuited to the case the title of the category the documentation is in implies it is suited for? The shader is a vertex / fragment shader and the code is in the fragment part.

thank you for (attempting to) help!

The entire premise behind deferred rendering techniques is that the lighting and the object rendering are separated into different unrelated shaders. The “lighting pass shader” mentioned in the documentation is specifically referring to the Internal-DeferredShading.shader I mentioned above. I’ll agree the documentation isn’t terribly clear about that.

Thank you! I‘ll try various changes and report back

I also replaced _LightDir,

the issue is caused by the pow function. I use pow to power decimal exponents for calculation of the value.

pow(x, y) expressed as exp(log(x) * y) experiences the same issue.

The issue is the log function.

The log function used in a shader (conditions see original post) causes flicker.

Btw.: the reference implementation on pow is either wrong or pow(x,y) == y^x

For 0 <= x <=1 a good approximation of the Cg log function (which calculates the natural logarithm (ln) of its parameter) is:

y = 1.5 - 2 / (x + .32);

That’s the reference implementation for Cg.

Unity doesn’t use Cg, it uses HLSL. And even then, the reference implementation isn’t necessarily the required implementation. The “reference” is just an “example” implementation that GPUs can implement any way they choose. HLSL doesn’t even include any reference for it in their spec.

Yes, the Unity shader code uses CGPROGRAM and there are .cginc files everywhere. But Unity delete the last uses of Cg about 5 years ago and actively stopped using Cg as the main shader language about 8 years ago when Nvidia themselves ceased development on Cg. They just never bothered to update the shader code and file extensions to reflect that fact until the Post Processing Stack and Scriptable Render Pipelines, all of which use HLSLPROGRAM and .hlsl files. But really CGPROGRAM and HLSLPROGRAM are interchangeable and both are running HLSL.

Thank you for the elaboration.

Approximating log(x) (delivering the natural logarithm of x) for x between 0 and 1:

using a similar looking easy function (-1/x) offset in x (by c) and y (by a) and scaled (by b):

y = a - b / (x + c)

with y(1) = log(1) = 0:

b = a * (1 + c)

y becomes

y = a * ((x - 1) / (x + c))

Determining a and c to minimize the difference area between y and log:

absolute of integral from 0 to 1 of (log(x) - y(x)) dx:

with the help of wolframalpha.com:

area = abs(-1 - a - a * log((c / (c + 1)) ^ (c+1)))

liking to minimize area for a and c or simpler, try area = 0:

a = -1 / (log((c / (c + 1)) ^ (c + 1)) + 1)

yields

y = -(1 / (log((c / (c + 1)) ^ (c + 1)) + 1)) * ((x - 1) / (x + c))

c > 0 freely choosable, note log(…c…) is a pre-calculatable value

“y and log even out between 0 and 1”

but intersecting 1 or 2 times, parts inbetween can be large, only cancelling each other.

Better to minimize the sum of the areas inbetween the intersections.

Visually, used geogebra.org:

quality | range of quality | c | a
*** | .75 to 1.0 | .4 | 1.326
** | .66 to 1.0 | .39 | 1.304

  • | .5 to 1.0 | .34 | 1.193
    o | .33 to 1.0 | .28 | 1.057
  • | .25 to 1.0 | .26 | 1.011
    – | .0 to 1.0 | .24 | 0.964

to reduce the number of shader operations, using the original approximation form

y = a - b / (x + c)

giving b for the values in the table in my previous post row by row from *** to --:

| b
| 1.857
| 1.813
| 1.599
| 1.353
| 1.274
| 1.196

to approximate log(x), the natural logarithm of x

has this been fixed? The Shader log function corrupting the shader?

i don’t have the need for it myself anymore right now but if not i like to draw Units attention to it.