Evinyl's picture

Shader renders completely black?

Hello, i'm trying to make a rather basic shader that colors a fragment relative to it's position in the window.
So far, i've come up with this

uniform vec3 LowColor;
uniform vec3 HighColor;
uniform float windowHeight;
 
float GetAverage(float scaler, float lowVal, float highVal)
{
    return (lowVal + highVal) * scaler;
}
void main()
{
    float scaler = gl_FragCoord.y /windowHeight;
    float r = GetAverage(scaler, LowColor[0],HighColor[0]);
    float g = GetAverage(scaler, LowColor[1],HighColor[1]);
    float b = GetAverage(scaler, LowColor[2],HighColor[2]);
    gl_FragColor = vec4(r,g,b,1.0);
}

The uniforms are being found,

Location for Uniform windowHeight = 2
Location for Uniform LowColor = 1
Location for Uniform HighColor = 0

so I don't suspect that to be a problem.
Two things are a problem though, the bars that are rendered with the shader are completely black, ex.
When using fixed values for LowColor and HighColor, the shading seems way off, since there is only a small line across the bottom that is properly shaded, and the only way to fix it is to use a very high value for "windowHeight", such as 500000.
I'm assigning the uniforms of the shader as so,

BarShader.SetUniform("windowHeight",(float)mainGL.Height);
            BarShader.SetUniform("LowColor", new Vector3(fromColor[2], fromColor[1], fromColor[0]));
            BarShader.SetUniform("HighColor",  new Vector3(toColor[2], toColor[1], toColor[0]));
public void SetUniform(string name, Vector3 value)
        {
            int loc = GL.GetUniformLocation(iProgram, name);
            Console.WriteLine("Location for Uniform " + name + " = " + loc + ", value = " + value);
            GL.Uniform3(loc, ref value);
        }

That is contained within a shader class.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Evinyl's picture

Whoops, fixed one part, I wasn't using the program before setting the uniforms...
Now, the other part, what is the scale of the gl_FragCoord.y variable? I tried sending in the height of the GlControl, but that just shades a very small, ~10 pixel wide line at the bottom, with the remaining height of the bar being a solid color.

AndyKorth's picture

I guess there's a few things that could be odd here. I'm not 100% sure what you are trying to accomplish, but I guess you're trying to make a vertical gradient that goes from LowColor to HighColor. So I'll work form that assumption.

GetAverage is not interpolating between those two values.

float GetAverage(float scaler, float lowVal, float highVal)
{
    return (lowVal + highVal) * scaler;
}

Let's say you want to go between black and white (doing this for each channel)

GetAverage(0.5, 0.4, 0.6) // halfway between 0.4 and 0.6...  
(0.4 + 0.6) * 0.5 = 0.5 // correct!
 
GetAverage(0.0, 0.4, 0.6) // scaler of zero, should start at 0.4...
(0.4 + 0.6) * 0.0 = 0.0 // nope!
 
GetAverage(0.0, 0.4, 0.6) // scaler of one, should return 0.6...
(0.4 + 0.6) * 1.0 = 1.0 // nope!

You want to linearly interpolate between two values... or as the cool kids call it. "Lerp"ing.

float GetAverage(float scaler, float start, float end)
{
    return (end-start) * scaler + start;
}

And in fact, it's so handy, it's built in as mix(start, end, alpha)

http://www.khronos.org/opengles/sdk/docs/manglsl/xhtml/mix.xml

(mix / lerp / blend ) are sometimes used interchangeably.

Okay, so after that, I'd take a really close look to make sure all your uniforms are correct. You didn't really mention their values, but the Vec3s probably should all have values in them between 0.0 and 1.0.

The scale of gl_fragCoord starts at 0.0 at the bottom and goes up to the screen height, I guess... I guess if I was you, I'd draw a screensize quad with UVs and then grab the gl_MultiTexCoord0 so it's ranged between 0 and 1.. But that's probably a matter of personal preference.

Consider simplifying your shader for testing purposes.

    float scaler = gl_FragCoord.y /windowHeight;
    gl_FragColor = vec4(scaler,scaler,scaler,1.0);

Will let you know if your scaler variable is ranged between zero and one like you expect. It should draw a white to black gradient.

Once you know that's working, add on the rest of it.

Evinyl's picture

Okay, so I figured out what I was doing wrong. I was passing the colors as a float between 0-255. The GetAverage function was also doing nothing to help, but it was late at night so what can you expect. Regardless, I fixed it and thanks for the help.

AndyKorth's picture

Cool! Glad to hear it works now.