Per pixel lighting with GLSL

Started by
7 comments, last by 3TATUK2 10 years, 1 month ago

Hello,

I am very new to GLSL and trying to implement a simple per-pixel lighting. I found a lot of resources on the internet that even propose pixel shader and fragment shader code for this, but something is always wrong: the "default" pixel and fragment shader code is missing it seems (I get pixels that are individually lit, but everything is very dark, only one light supported, colors are strange). So it seems that a shader is just a piece of a puzzle, and should be combined with other components. But how? Or where can I find the code for a per pixel lighting shader, that supports my 8 lights and will basically render my scene as previously (except for nicer per-pixel lighting)?

Is it that difficult to have a simple per-pixel shading in openGL?

Advertisement

Not sure where you are at. So you have a shader running and compiling? Does gl_FragData[0] = vec4(1,0,0,1) shade your object all red?

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

Based on your question (no offense ofcourse), I would suggest to first gather some basic knowledge on shaders and GLSL. You might use this site: http://www.lighthouse3d.com/opengl/glsl/

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Thanks Adam,

the fragment shader:


void main() {
  gl_FragData[0] = vec4(1.0,0.0,0.0,1.0);
}

as you suggest works fine and everything is red. I check for compilation and binding errors all the time, and everything is fine.

I read lot of shader tutorials (mainly on Lighthouse3D), and the presented shaders compile in my application. But they always work half-way of what they are supposed to do.

I guess I am missing a simple switch or something?

Btw, I am using Qt's QGLShaderProgram, which handles most aspects for me.

So start from here and build up. When I first started shading I had errors all the time.

Validate your data/uniforms etc. Per pixel lighting:
Calculate the normal in the vertex shader (gl_NormalMatrix*gl_Normal), in the fragment shader, output gl_FragData[0] = vec4(normal, 1); (Normal validated, dont forget negative number will be black so make sure to pass in some non-negative normals to test).

You can calculate the lightVector in the world or camera space and output to fragData, validate that the color makes sense.

To start just post your 2 shaders and we can look at those. Aside from those looking good, there could be a bad code side where you arent setting up or passing a variable properly.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

Thanks again Adam.

Maybe I didn't explain myself clearly in my first post:

Actually, all I want is a vertex and fragment shader code that would perfectly mimic the built-in functionality of openGl, with the per-pixel lighting as a plus.

So, correct me if I am wrong, but what will happen is that several pieces of code will come together. Typically:

- Code specific to ambient light

- Code specific to directional light

- Code specific to point light

- Code specific to spot light

- Code related to textures

- and probably much much more.

In the various tutorials I have seen, there are some of above's pieces of the puzzle. But if I simply want to have per-pixel lighting, do I really have to go through all that heavy code, thinking about all the details? For instance, my textures can be transparent, blurred, etc. (i.e. from the openGl settings). So if I have to write all that heavy code in order to be able to insert my per-pixel lighting, I wonder how other people do it?

Reformulated in yet a different way: if I can code my per-pixel lighting, then I will not be able to render my textures anymore... unless I write that piece of code myself too, which is very very heavy lifting...

What you want in the first place is to calculate the color of each pixel (actually named "fragment" in OpenGL because they need not correspond directly to pixels). This can be done by using fragment shaders only. If you use a fragment shader script you also need to use vertex shader script; other shader scripts are not needed for this.

What you want to do is to write a surface shader as known e.g. from RenderMan and companions. Unfortunately, GPU based shader scripts do not support surface shaders. Instead, surface shading is embedded in the vertex shader script (when doing per vertex shading) or fragment shader script (when doing per fragment shading). So you need to write both scripts in their entirety, including all fetching of material parameters (like albedo color, reflection co-efficient, …) from textures and all interaction with the wanted kinds of light sources, including dealing with the number of light sources (not to forget). You need to write all supporting stuff, too.

This is IMHO a weakness in using GPU based shader scripts. On the other hand, those things are low level anyway.

You don't want to mimic fixed function in the way you are thinking.

- Code specific to ambient light

- Code specific to directional light

Lighting for this should be:
textureColor*(ambient + dot(directionalLight, normal))

if you want to "glEnable/disable" ambient light, you simply send 0 for the variable ambient (if its colored ambient vec3(0,0,0)). I think you want your shader to be like this. It is not correct to do , it is stupid and wasted if() executions.
if(applyAibment)
{

color += ambient;

}

if(directionalLight)
{

color += dot(directionalLight, normal))
}
if(texture)
{
textureColor = texture2D();
}
else
{

textureColor = gl_FaceColor;
}

Instead, always use a texture. If you don't want texturing and just want a blue teapot, send a 2x2 texture with all blue pixels. If you don't want ambient, send 0, the equation will just be 0 + lighting color. If you only want to run 2 lights instead of 8, then pass a uniform NUM_LIGHTS to the shader, dynamically looping through them. If your next model has 4 lights, send 4 down.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

These all have various GLSL lighting sections:

http://www.arcsynthesis.org/gltut/

http://ogldev.atspace.co.uk/

http://www.opengl-tutorial.org/beginners-tutorials/tutorial-8-basic-shading/

http://antongerdelan.net/opengl/

http://www.mbsoftworks.sk/index.php?page=tutorials&series=1

http://www.rastertek.com/tutgl40.html

http://www.lighthouse3d.com/tutorials/glsl-core-tutorial/lighting/

http://www.ozone3d.net/tutorials/

This topic is closed to new replies.

Advertisement