160 likes | 285 Views
Vertex Shading : Do- It - Yourself Transform , Lighting , and Texgen. Vertex Shader. Every shader should at the very least output a clip-space vertex coordinate. You must output a color (at least copy the incoming color into the outgoing color ). // simple .vs //
E N D
VertexShader • Every shader should at the very least output a clip-space vertex coordinate. • Youmustoutput a color (at leastcopy the incoming color into the outgoing color).
// simple.vs // // Genericvertextransformation, // copyprimarycolor voidmain(void) { // multiply object-space position by MVP matrix gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; // Copytheprimarycolor gl_FrontColor = gl_Color; } • The modelview and projection matrices are traditionally two separate matrices againstwhich the incoming object-space vertex position is multiplied. • GLSL convenientlyprovides a shortcut calledgl_ModelViewProjectionMatrix, a concatenation of the twomatrices, which we refer to as the MVP matrix.
DiffuseLighting • Cdiff = max{N • L, 0} * C_mat * C_li • N is the vertex’s unit normal, and L is the unit vector representing the direction from thevertex to the light source. • Cmat is the color of the surface material, and Cli is the color ofthelight. • Cdiff is the resulting diffuse color.
DiffuseLighting • uniform vec3 lightPos[1]; • voidmain(void) • { • // normal MVP transform • gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; • vec3 N = normalize(gl_NormalMatrix * gl_Normal); • vec4 V = gl_ModelViewMatrix * gl_Vertex; • vec3 L = normalize(lightPos[0] - V.xyz); • // outputthediffusecolor • floatNdotL = dot(N, L); • gl_FrontColor = gl_Color * vec4(max(0.0, NdotL)); • }
DiffuseLighting • Allthelightingcalculationsare performed in eye space, so you need to transform the normal vector from objectspace to eye space as well. • GLSL provides the gl_NormalMatrixbuilt-in uniform matrix asa convenience for this purpose. It is simply the inverse transpose of the modelviewmatrix’supper-left 3×3 elements. • Both the normal and the light vectors must be unit vectors, so you normalize them beforecontinuing. GLSL supplies a built-in function, normalize, to perform this common task.
SpecularLighting • Cspec = max{N • H, 0}_Sexp* Cmat* Cli • H is the unit vector representing the direction halfway between the light vector and theview vector, known as the half-angle vector. • S_exp is the specular exponent, controlling thetightness of the specular highlight. • C_spec is the resulting specular color.
SpecularLighting • uniform vec3 lightPos[1]; • voidmain(void) • { • // normal MVP transform • gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; • vec3 N = normalize(gl_NormalMatrix * gl_Normal); • vec4 V = gl_ModelViewMatrix * gl_Vertex; • vec3 L = normalize(lightPos[0] - V.xyz); • vec3 H = normalize(L + vec3(0.0, 0.0, 1.0)); • constfloatspecularExp = 128.0; • // calculatediffuselighting • floatNdotL = max(0.0, dot(N, L)); • vec4 diffuse = gl_Color * vec4(NdotL); • // calculatespecularlighting • float NdotH = max(0.0, dot(N, H)); • vec4 specular = vec4(0.0); • if (NdotL > 0.0) • specular = vec4(pow(NdotH, specularExp)); • // sum the diffuse and specular components • gl_FrontColor = diffuse + specular; • }
ImprovedSpecularLighting • Specular highlights change rapidly over the surface of an object. Trying to compute themper-vertex and then interpolating the result across a triangle gives relatively poor results. • Instead of a nice circular highlight, you end up with a muddy polygonal-shaped highlight. • One way you can improve the situation is to separate the diffuse lighting result from thespecular lighting result, outputting one as the vertex’s primary color and the other as thesecondarycolor.
ImprovedSpecularLighting • By adding the diffuse and specular colors together, you effectively saturatethe color (that is, exceed a value of 1.0) wherever a specular highlight appears. • Ifyoutry to interpolate the sum of these colors, the saturation will more broadly affect theentiretriangle. • However, if you interpolate the two colors separately and then sum themper-fragment, the saturation will occur only where desired, cleaning up some of themuddiness. • When using fixed functionality fragment processing, this sum per-fragment isachieved by simply enabling GL_COLOR_SUM.
ImprovedSpecularLighting // put diffuse into primary color floatNdotL = max(0.0, dot(N, L)); gl_FrontColor = gl_Color * vec4(NdotL); // put specular into secondary color float NdotH = max(0.0, dot(N, H)); gl_FrontSecondaryColor = (NdotL > 0.0) ? vec4(pow(NdotH, specularExp)) : vec4(0.0);
Per-VertexFog • Though fog is specified as a per-fragment rasterization stage that follows texturing, oftenimplementations perform most of the necessary computation per-vertex and then interpolatethe results across the primitive. • Thefollowingis the equation for a second-order exponential fog factor, which controls the blendingbetween the fog color and the unfogged fragment color: • ff = e_–(d*fc)_2 • In this equation, ff is the computed fog factor. d is the density constant that controls the“thickness” of the fog. fc is the fog coordinate, which is usually the distance from thevertextotheeye.
uniform vec3 lightPos[1]; • voidmain(void) • { • // normal MVP transform • gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; • vec3 N = normalize(gl_NormalMatrix * gl_Normal); • vec4 V = gl_ModelViewMatrix * gl_Vertex; • vec3 L = normalize(lightPos[0] - V.xyz); • vec3 H = normalize(L + vec3(0.0, 0.0, 1.0)); • constfloatspecularExp = 128.0; • // calculatediffuselighting • floatNdotL = max(0.0, dot(N, L)); • vec4 diffuse = gl_Color * vec4(NdotL); • // calculatespecularlighting • float NdotH = max(0.0, dot(N, H)); • vec4 specular = vec4(0.0); • if (NdotL > 0.0) • specular = vec4(pow(NdotH, specularExp)); • // calculate fog coordinate: distance from eye • gl_FogFragCoord = length(V); • // sum the diffuse and specular components • gl_FrontColor = diffuse + specular; • } Fog by using fixed functionality • Fo
Or do it your self uniformfloatdensity; ... // calculate 2nd order exponential fog factor constfloat e = 2.71828; floatfogFactor = (density * length(V)); fogFactor *= fogFactor; fogFactor = clamp(pow(e, -fogFactor), 0.0, 1.0); // sum the diffuse and specular components, then // blend with the fog color based on fog factor const vec4 fogColor = vec4(0.5, 0.8, 0.5, 1.0); gl_FrontColor = mix(fogColor, clamp(diffuse + specular, 0.0, 1.0), fogFactor);