Howto:Shader programming in FlightGear: Difference between revisions

Jump to navigation Jump to search
ALS Landing-Spotlight effects and fragment shader documentation wrapup
No edit summary
(ALS Landing-Spotlight effects and fragment shader documentation wrapup)
Line 666: Line 666:


texel color - what is the base color of the pixel fully lit and unfogged
texel color - what is the base color of the pixel fully lit and unfogged
lighting - how is this color changed by the light falling onto that pixel, usually the relation is something like fragColor equals texel times light
lighting - how is this color changed by the light falling onto that pixel, usually the relation is something like fragColor equals texel * light
fogging - how much is the color hidden by haze, usually the relation is something like gl_FragColor = mix(fragColor, hazeColor, transmission_factor);
fogging - how much is the color hidden by haze, usually the relation is something like gl_FragColor equals mix(fragColor, hazeColor, transmission_factor);
what is displayed on the screen in the end is whatever gl_FragColor is set to
what is displayed on the screen in the end is whatever gl_FragColor is set to
But the location where this happens isn't always obvious - often (part) of the light is computed in the vertex shader already, in which case it typically enters the fragment shader as gl_Color.
But the location where this happens isn't always obvious - often (part) of the light is computed in the vertex shader already, in which case it typically enters the fragment shader as gl_Color.


So, the lighting equation in tree-haze.frag is indeed
So, the lighting equation in tree-haze.frag is indeed
vec4 fragColor equals vec4 (gl_Color.xyz,1.0) times texel;
vec4 fragColor equals vec4 (gl_Color.xyz,1.0) * texel;
and your change to the light should happen just before that. But you can't do
and your change to the light should happen just before that. But you can't do
gl_Color.rgb equals gl_Color.rgb plus my_light;
gl_Color.rgb equals gl_Color.rgb + my_light;
because gl_Color.rgb is a varying variable type, and you can't assign new values to them inside the shader, so you need to either make a new variable or just do
because gl_Color.rgb is a varying variable type, and you can't assign new values to them inside the shader, so you need to either make a new variable or just do
vec4 fragColor equals vec4 ((gl_Color.rgb plus my_light),1.0) times texel;
vec4 fragColor equals vec4 ((gl_Color.rgb + my_light),1.0) * texel;
(note that color.rgb is the same as color.xyz, GLSL doesn't really care which convention you use, but I took a few months to learn that, so early code by myself often uses xyz indexing convention for color vectors as well).<ref>{{cite web |url=http://forum.flightgear.org/viewtopic.php?f=47&t=24226&start=15#p220075  
(note that color.rgb is the same as color.xyz, GLSL doesn't really care which convention you use, but I took a few months to learn that, so early code by myself often uses xyz indexing convention for color vectors as well).<ref>{{cite web |url=http://forum.flightgear.org/viewtopic.php?f=47&t=24226&start=15#p220075  
|title=ALS landing lights
|title=ALS landing lights
Line 713: Line 713:
{{cquote|So, in old times when rendering textures was slow and complicated, we rendered objects with monochromatic surface colors. Then the (schematic) lighting equation (without specular, and the sum of ambient and diffuse already computed) was
{{cquote|So, in old times when rendering textures was slow and complicated, we rendered objects with monochromatic surface colors. Then the (schematic) lighting equation (without specular, and the sum of ambient and diffuse already computed) was


visibleColor.rgb = objectColor.rgb * light.rgb + objectEmissive.rgb
visibleColor.rgb equals objectColor.rgb * light.rgb + objectEmissive.rgb


Now, we have textures and so we get
Now, we have textures and so we get


visibleColor.rgb = objectColor.rgb * texel.rgb * light.rgb + objectEmissive.rgb + lightMapTexel.rgb
visibleColor.rgb equals objectColor.rgb * texel.rgb * light.rgb + objectEmissive.rgb + lightMapTexel.rgb


Since we can have the full color information in the texture, objectColor.rgb is usually (1.0,1.0,1.0) because the info is redundant. But if you don't use a texture, of course objectColor.rgb has the actual color value (incidentially, I think we shouldn't texture with monochromatic surfaces at all, it creates a jarring visual impression which can be cured by using even a small texture...)
Since we can have the full color information in the texture, objectColor.rgb is usually (1.0,1.0,1.0) because the info is redundant. But if you don't use a texture, of course objectColor.rgb has the actual color value (incidentially, I think we shouldn't texture with monochromatic surfaces at all, it creates a jarring visual impression which can be cured by using even a small texture...)


But if you do, the rendering pipeline is set up to compute color.rgb = objectColor * light.rgb in the vertex shader, so the equation we have in the fragment shader is something like
But if you do, the rendering pipeline is set up to compute color.rgb equals objectColor * light.rgb in the vertex shader, so the equation we have in the fragment shader is something like


visibleColor.rgb = color.rgb * texel.rgb + objectEmissive.rgb + lightMapTexel.rgb
visibleColor.rgb equals color.rgb * texel.rgb + objectEmissive.rgb + lightMapTexel.rgb


and if we add a secondary light like
and if we add a secondary light like


visibleColor.rgb = (color.rgb + secLight.rgb) * texel.rgb
visibleColor.rgb equals (color.rgb + secLight.rgb) * texel.rgb


it of course can never recover the color information, because color.rgb is zero at night since you multiplied the actual color with zero sunlight and the texel doesn't carry information for an untextured object.
it of course can never recover the color information, because color.rgb is zero at night since you multiplied the actual color with zero sunlight and the texel doesn't carry information for an untextured object.
330

edits

Navigation menu