PDA

View Full Version : Combining texture and light.



noncopyable
10-10-2007, 02:54 PM
Hello.

I am trying to emulate fixed OpenGL texturing and lighting in GLSL, but have some problems and don't seem to find anything useful in GLSL tutorials and books that i have, all of them inconsistent on this point.

i have attenuation, spoteffect, ambient, diffuse, specular computed for lighting;

from redbook
lighting = emmision + ambientmodel + attenuation * spoteffect * (ambient + diffuse + specular);


...
vec4 texture = texture2D(tex_base, texcoord);
vec4 lighting = attenuation * spoteffect * (ambient + diffuse + specular);

gl_FragColor = gl_LightModel.ambient * gl_FrontMaterial.ambient + lighting * texture;This is what i am doing now, and i don't think i am doing it right.
How can i combine texture and light, or at least where can i find "The Mathematics of Texturing AND Lighting" version that explains how OpenGL does this?

Thank You.

Zengar
10-10-2007, 03:29 PM
I would advice you to see the OpenGL specifications, the exact formula is written there.

BTW, your calculations seem ok to me.

CRasterImage
10-10-2007, 04:00 PM
Your specular needs to be mixed in with the fragment seprate than the diffuse.

I have always used:

(diffusepow includes attenuation and ambient factors. specularpow includes material "shininess" or gloss map factors)

gl_FragColor.r = (diffusepow * light_diffuse_color.r * texcolor.r) + (specularpow * light_specular_color.r);
gl_FragColor.g = (diffusepow * light_diffuse_color.g * texcolor.g) + (specularpow * light_specular_color.g);
gl_FragColor.b = (diffusepow * light_diffuse_color.b * texcolor.b) + (specularpow * light_specular_color.b);
gl_FragColor.a = 1.0;

noncopyable
10-10-2007, 04:30 PM
Thanks for quick responses.

After checking OpenGL 2.1 Specification and sample code, i figured that i forgot secondary color.


// For GL_SINGLE_COLOR :
vec4 primary = attenuation * spoteffect * (ambient + diffuse + specular) + gl_FrontMaterial.emission + gl_FrontMaterial.ambient * gl_LightModel.ambient;
vec4 secondary = vec4(0, 0, 0, 1);

// For GL_SEPARATE_SPECULAR_COLOR :
vec4 primary = attenuation * spoteffect * (ambient + diffuse) + gl_FrontMaterial.emission + gl_FrontMaterial.ambient * gl_LightModel.ambient;
vec4 secondary = attenuation * spoteffect * specular;

// and finally :
gl_FragColor = primary * texture + secondary;Results still don't look same. This is the exact model? Since i still trying to find exact formula.

Thanks.

Edit : code

CRasterImage
10-10-2007, 05:04 PM
I take it that the sample for GL_SEPARATE_SPECULAR_COLOR has already mixed the diffuse light color with the texture color and stored them into "ambient" and "diffuse" values?


BTW, under what circumstance would a light's specular color be different than it's diffuse color? Just out of curiousity...

noncopyable
10-10-2007, 05:20 PM
float coeff;
if(0 == spec_model) {
// blinn-phong
vec3 h = normalize(e + l);
coeff = max(dot(h, n), 0.0);
}
else {
// phong
vec3 r = normalize(reflect(-l, n));
coeff = max(dot(e, r), 0.0);
}

float ndl = dot(n, l);

ambient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;
diffuse = gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * max(ndl, 0.0);
specular = gl_LightSource[0].specular * gl_FrontMaterial.specular * pow(coeff, gl_FrontMaterial.shininess) * (ndl > 0.0 ? 1.0 : 0.0);Well... "Therefore, if you want to create a realistic effect, set the GL_SPECULAR
parameter to the same value as the GL_DIFFUSE parameter" Redbook :)

Simon Arbon
10-11-2007, 12:00 AM
BTW, under what circumstance would a light's specular color be different than it's diffuse color? Just out of curiousity... The specular reflection from most real surfaces is the color of the light source, hence the specular color should be white (or grey if its a very dull surface)
Only a few metals such as gold have a specular highlight the same color as the material, and hence these are the only materials that should use single-color mode if you want a realistic look.
For a textured surface, both the primary & secondary colors will usually be white, but you still need the separate secondary color to prevent the specular highlight being colored by the texture.

The full lighting equations are:

L = Direction of light
v = inverse of L
d = Spotlight pointing direction
s = half-angle vector
n = Vertex Normal

Light[0].Attenuation = 1/(ConstantAttenuation + (LinearAttenuation * Light[0].DistanceFromVertex) + (QuadraticAttenuation * Pow(Light[0].DistanceFromVertex,2)))

if spotlight then
if vertex outside light-cone then
Light[0].SpotlightEffect = 0
else
Light[0].SpotlightEffect = pow( max( dot(v,d),0 ), Light[0].SpotlightExponent )
else
Light[0].SpotlightEffect = 1;

NOTE: In the following equations all terms including "Light[0]" are repeated and summed for each light, while all other terms (emmisive & ambient) are only included once in the sum.

PrimaryColor = Material.Emission + (Light[0].Ambient * Material.Ambient) + ( Light[0].Attenuation * Light[0].SpotlightEffect * ((Light[0].Ambient * Material.Ambient) + (max(dot(L,n),0) * Light[0].Diffuse 8 Material.Diffuse))

SecondaryColor = Light[0].Attenuation * Light[0].SpotLightEffect * ( pow(max(dot(s,n), 0), Material.Shininess) * Light[0].Specular * Material.Specular );

(IF texturing is enabled THEN combine the texture color at the current texture coords with the PrimaryColor using the currently enabled replace, modulate, decal or blend texture function)

FragmentColor = PrimaryColor + SecondaryColor;

noncopyable
10-11-2007, 06:34 AM
I get really different(weird?) results from my implementation of phong and blinn-phong.
i am missing something in these lines?
e = normal from vertex to eye
n = vertex normal
l = normal from vertex to lightpos.

float coeff;
if(0 == spec_model) {
// blinn-phong
vec3 h = normalize(e + l);
coeff = max(dot(h, n), 0.0);
}
else if(1 == spec_model) {
// phong
vec3 r = reflect(-l, n);
coeff = max(dot(e, r), 0.0);
}
else {
// phong - test
vec3 r = reflect(-l, n);
coeff = dot(e, r);
}

// which will be used for
pow(coeff, gl_FrontMaterial.shininess)And some screenshots..
OpenGL fixed.
http://img523.imageshack.us/img523/557/fixedhj7.jpg

GLSL using blinn.
http://img340.imageshack.us/img340/2431/blinnao9.jpg

GLSL using phong.
http://img292.imageshack.us/img292/4056/phongau4.jpg

GLSL using phong(negative specular included for testing)
http://img213.imageshack.us/img213/9565/phongnegyu6.jpg

noncopyable
10-11-2007, 08:23 AM
Looks like code is right.
Problem lies in material(shininess) properties of cloth.
I couldn't figure it until now, because there is a huge difference between blinn and phong shaders, which made me think bug is in shader.

Blinn [always] gives you a positive specular coefficient if you see the vertex, because half vector lies between eye and light (h = normal(e + l)), and dot(h, n) >= 0.
This is different in Phong, because r (r = reflect(-l, n)) does not always lie between eye and light vectors(actually it does if you consider exterior angles :) ), and dot(r, e) can be negative even if you see vertex.

So, phong realistic (exact?), blinn looks same at some situations and faster specular light model?

Thanks.