• Advertisement
Sign in to follow this  

GLSL per pixel question

This topic is 4412 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have found a bunch of nice tutorials for GLSL but none of them explain the lighting equation so that I understand. and none of them use textures on the objects. I have tried without any success to modify a vertex&fragment shader to use material properties when calculating a fragment color altough I don't understand what I'm doing.

Share this post


Link to post
Share on other sites
Advertisement
vertex shader

varying vec3 normal, lightDir, halfVector;

void main()
{
vec4 worldPos;

normal = normalize(gl_NormalMatrix * gl_Normal);

worldPos = gl_ModelViewMatrix * gl_Vertex;
lightDir = normalize(vec3(gl_LightSource[0].position - worldPos));

halfVector = normalize(gl_LightSource[0].halfVector.xyz);

gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}




fragment shader

varying vec3 normal, lightDir, halfVector;

void main()
{
vec4 diffuseLight, specularLight;
float shine = 64.0;
vec3 n = normalize(normal);

float lightIntensity = max(dot(n, normalize(lightDir)), 0.0);

diffuseLight = lightIntensity * gl_LightSource[0].diffuse;
specularLight = pow(max(dot(n, normalize(halfVector)), 0.0), shine) * gl_LightSource[0].specular;

gl_FragColor = diffuseLight + specularLight + gl_LightSource[0].ambient;
}




EDIT: Forgot to write my question. I have the above shaders. I found them in a tutorial some where the shader looks like it works as it should but I don't know how to get the texture (have only one at the moment) into the light calculation or the material color and how to add more lights.

Share this post


Link to post
Share on other sites
I don't use GLSL much and havn't in quite a while so let's see how badly I do here. :D

You get textures into your fragment program by using samplers. For example, if you are interested in using 2D textures, you would use the sampler2D type. So before main at the top, you would say "uniform sampler2D texture;".

gl_LightSource is how you access each light. In the program you have, it's accessing the first light, gl_LightSource[0]. The second light would be accessed by using gl_LightSource[1] and so on (up to 8 lights).

To access the material info, use gl_FrontMaterial or gl_BackMaterial. You will probably only be interested in gl_FrontMaterial right now.

Finally, to access your texture and add in the lighting do this:

float4 texColor = texture2D( texture, coords );
float4 shade = diffuseLight + specularLight;

gl_FragColor = shade * texColor + gl_LightSource[0].ambient;


EDIT: had ambient in the wrong place. :)

-SirKnight

Share this post


Link to post
Share on other sites
Thank you.

so to add more lights I just add them with +

like this:
gl_FragColor = shade * texColor + gl_LightSource[0].ambient + gl_LightSource[1].ambient;

and is it the same for the diffuse and specular of the light?

Share this post


Link to post
Share on other sites
eviltwigflipper > I'm trying. and I have successfully created my own fragment shader that added the texture to the world. But I failed to combine light and texture.


So I have added the lines that SirKnight wrote. And now the textures is there and lighting but there is some kind of "fog" on everything now.

Share this post


Link to post
Share on other sites
Any way you can upload a screenshot somewhere?

Just remember that lights are additive so all you do is compute the lighting for each light and add the results together (then multiply that by the texture).

Also I recommend you pick up the "Orange Book" (OpenGL Shading Language Programming Guide). It's a good reference for the GLSL language and how it works.

So a shader for multiple lights would be something along these lines:


float diffuseLight, specularLight;
float shine = 64.0;
vec3 n = normalize(normal);
float light = 0;
for( int i = 0; i < NUM_LIGHTS; ++i )
{
vec3 lightDir = normalize( gl_LightSource.position - gl_Vertex.xyz );
float lightIntensity = max(dot(n, lightDir), 0.0);

diffuseLight = lightIntensity * gl_LightSource.diffuse;
specularLight = pow(max(dot(n, normalize(gl_LightSource.halfVector.xyz)), 0.0), shine) * gl_LightSource.specular;

light += (diffuseLight + specularLight);
}

gl_FragColor = light * texture;





-SirKnight

Share this post


Link to post
Share on other sites
Here is a screenshot


EDIT: Here is a screenshot without shader

Share this post


Link to post
Share on other sites
What's your ambient set to? An ambient too large can give a washed-out look like that.



-SirKnight

Share this post


Link to post
Share on other sites
My ambient is 0.2,0.2,0.2 and I have one light for now.

Share this post


Link to post
Share on other sites
I can't get it work with the loop so I can have more lights.

Vertex:

varying vec3 normal, pos;

void main()
{
vec4 worldPos;

normal = normalize(gl_NormalMatrix * gl_Normal);

worldPos = gl_ModelViewMatrix * gl_Vertex;
pos = worldPos.xyz;

gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}




Fragment:

varying vec3 normal, pos;
uniform sampler2D textureID;
uniform int nrLights;

void main()
{
vec4 diffuse=vec4(0), specular=vec4(0), ambient=vec4(0);
vec4 ambientLight=vec4(0), diffuseLight=vec4(0), specularLight=vec4(0);
float shine = 128.0;
vec3 n = normalize(normal);
vec3 halfVector = normalize(gl_LightSource[0].halfVector.xyz);

shine = gl_FrontMaterial.shininess;

vec4 texColor = texture2D( textureID, vec2(gl_TexCoord[0]) );

// int i=0;

for( int i=0; i<2; ++i )
{
vec3 LD = normalize( vec3(gl_LightSource.position.xyz - pos) );
float NdotL = max(dot(n, normalize(LD)), 0.0);

float spotEffect = dot(normalize(gl_LightSource.spotDirection), normalize(-LD));

ambientLight += gl_LightSource.ambient;
diffuseLight += spotEffect * NdotL * gl_LightSource.diffuse;
specularLight += pow(max(dot(n, halfVector), 0.0), shine) * gl_LightSource.specular;
}

ambient = gl_FrontMaterial.ambient * ambientLight;
diffuse = gl_FrontMaterial.diffuse * diffuseLight;
specular = gl_FrontMaterial.specular * specularLight;

vec4 light = ambient + diffuse + specular;

gl_FragColor = clamp(light,0.0, 1.0);
}




EDIT: Updated shaders

[Edited by - McZ on January 19, 2006 7:45:32 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by McZ
eviltwigflipper > I'm trying. and I have successfully created my own fragment shader that added the texture to the world. But I failed to combine light and texture.


I still think you should read up more on what your doing, but anyway just taking a quick glance at it I can see a couple things your not doing(these are probley not your direct probley though).

1) You need to have a TBN(Tangent Binormal Normal) matrix, or your lighting will either just effect walls or not the walls and just the floor and ceiling(depending on how your coordinate system is set up).

2) If I remember GLSL had a really bad implmenation of loops. What I would do is just try to get a single light to work. Because the way your doing it just seems wierd. The vec4 light you should be adding the results at the end of the loop instead of after it which is what your doing now.

3)Instead of using "spot direction",try to make a point light. Try to replace that with distance attenuation( 1-(LD/lightRadius)*2) ).

4)Try to take out the ambient and the texture and see what results you get. And what tutorial are you trying to follow?

Share this post


Link to post
Share on other sites
I have been readingThis and This and I have found a few other examples that I downloaded but don't have any URL to them.

Why do I need a TBN matrix? none of the tutorials I have seen have written anything about the TBN matrix (maybe they have but with another name).

I had one single light working (maybe not correct though) so I would like to see if I could extend the shader to use 2 lights all tutorials I have found only handle one light.

Share this post


Link to post
Share on other sites

Why do I need a TBN matrix
[/QUOTE]

Exactlly what I said before...you need to read up on what your actually doing. ; ).

If you have a single light working(probley not correctlly sinse your not using a TBN matrix) then I believe you can use loops without the NV_Fragment_Program2 extension(GF6 or higher) if you have a non variable as a counter for your loops. But your still doing it wrong...

If you have Quake 4 I would recommend looking at how they did there stuff in GLSL.

But you NEED to implement a TBN matrix.

You should fix your stuff to look something like this...


vec3 result;

for(int i = 0; i < 2; i++) {
vec3 lightD = gl_LightSource.position.xyz - pos;

lightD = normalize(mul(lightD, TBN).xyz);

... <-- calculate lighting equation.

result += ambient + material_ambience + (dp + specular) * attenuation;
}

return vec4(result, 1.0);



Share this post


Link to post
Share on other sites
I'm searching the net for info about the TBN matrix altough I can't find anyone that explains so I understand yet.


I have changed my shaders so now they look like this, and now I get some light when using more than one light. But as you said, I can't have a variable as loop max counter.

vertex

varying vec3 normal, position;

void main(void)
{
position = vec3(gl_ModelViewMatrix * gl_Vertex);

normal = normalize(gl_NormalMatrix * gl_Normal);

gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}



fragment

varying vec3 normal, position;
uniform sampler2D textureID;

void main(void)
{
float shine = gl_FrontMaterial.shininess;
vec4 ambientLight=vec4(0.2), diffuseLight=vec4(0), specularLight=vec4(0);
vec4 texColor = texture2D( textureID, vec2(gl_TexCoord[0]) );
vec3 n = normalize(normal);
vec4 color = vec4(0);

// Light
for( int i=0; i<5; i++ )
{
vec3 L = normalize( vec3(gl_LightSource.position.xyz - position) );
float NdotL = max(dot(n, L), 0.0);
float NdotHV = dot(n, normalize(gl_LightSource.halfVector.xyz));

ambientLight = gl_LightSource.ambient;
diffuseLight = NdotL * gl_LightSource.diffuse;
specularLight = pow(max(NdotHV, 0.0), shine) * gl_LightSource.specular;

vec4 ambient = gl_FrontMaterial.ambient * ambientLight;
vec4 diffuse = gl_FrontMaterial.diffuse * diffuseLight;
vec4 specular = gl_FrontMaterial.specular * specularLight;

color += (ambient + diffuse + specular);
}

gl_FragColor = (gl_LightModel.ambient + color) * texColor;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by McZ
I'm searching the net for info about the TBN matrix altough I can't find anyone that explains so I understand yet.


First hit on google http://www.paulsprojects.net/tutorials/simplebump/simplebump.html. If you don't atleast get the gist of the math behind what your doing, you might want to try something more simple...but anyway read that. I would also recommend you by the OpenGL Shading Language book(Orange Book).



Share this post


Link to post
Share on other sites
I have read that one several times. But I still don't undestand why I need TBN for my lighting when I don't have any bumpmaps because every article/tutorial that mention TBN is about Bump mapping.

Share this post


Link to post
Share on other sites
http://developer.nvidia.com/object/mathematicsofperpixellighting.html

Read that whole thing..starts to go indepth on a TBN matrix around slide 33. I would actually try to explain it to you, but I think that document at least gets you on the right track.

Share this post


Link to post
Share on other sites
I dont see anywhere in that slide where it says you need a TBN matrix to calculate per pixel lighting. I do however see where it says that you need a TBN matrix for surface-local space lighting. I dont think that telling this guy he needs a TBN matrix is going to solve his problems. The tutorial he is looking at appears to be focusing on a basic phong lighting model and computing the results per fragment.

Perhaps this article on the phong lighting model will help some:

http://www.delphi3d.net/articles/viewarticle.php?article=phong.htm

Good luck!

Share this post


Link to post
Share on other sites
I may be missing the point by why does he need a TBN matrix if he's not doing tangent space lighting?

For normal texturing & lighting there is no need.


The GLSL shader gren (http://developer.3dlabs.com/downloads/shadergen/index.htm) is great place to start from if you're new to shaders and want to replicate the fixed functin pipeline.

GOCP

Share this post


Link to post
Share on other sites
The article about phong lighting that luridcortex linked to is perfect good written and easy to understand (at least for me).

and now I will download the GLSL shader gen software that GOCP linked to. looks like a nice tool to develop shaders in.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement