JavaScript EditorFree JavaScript Editor     Ajax Editor 



Main Page
Previous Page
Next Page

9.7. Texture Coordinate Generation

OpenGL can be set up to compute texture coordinates automatically, based only on the incoming vertex positions. Five methods are defined, and each can be useful for certain purposes. The texture generation mode specified by GL_OBJECT_LINEAR is useful for cases in which a texture is to remain fixed to a geometric model, such as in a terrain modeling application. GL_EYE_LINEAR is useful for producing dynamic contour lines on an object. Examples of this usage include a scientist studying isosurfaces or a geologist interpreting seismic data. GL_SPHERE_MAP can generate texture coordinates for simple environment mapping. GL_REFLECTION_MAP and GL_NORMAL_MAP can work in conjunction with cube map textures. GL_REFLECTION_MAP passes the reflection vector as the texture coordinate. GL_NORMAL_MAP simply passes the computed eye space normal as the texture coordinate.

A function that generates sphere map coordinates according to the OpenGL specification is shown in Listing 9.20.

Listing 9.20. GL_SPHERE_MAP computation

vec2 SphereMap(in vec3 ecPosition3, in vec3 normal)
{
   float m;
   vec3 r, u;
   u = normalize(ecPosition3);
   r = reflect(u, normal);
   m = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z + 1.0) * (r.z + 1.0));
   return vec2(r.x / m + 0.5, r.y / m + 0.5);
}

A function that generates reflection map coordinates according to the OpenGL specification looks almost identical to the function shown in Listing 9.20. The difference is that it returns the reflection vector as its result (see Listing 9.21).

Listing 9.21. GL_REFLECTION_MAP computation

vec3 ReflectionMap(in vec3 ecPosition3, in vec3 normal)
{
   float NdotU, m;
   vec3 u;
   u = normalize(ecPosition3);
   return (reflect(u, normal));
}

Listing 9.22 shows the code for selecting between the five texture generation methods and computing the appropriate texture coordinate values.

Listing 9.22. Texture coordinate generation computation

// Compute sphere map coordinates if needed
if (TexGenSphere)
    sphereMap = SphereMap(ecposition3, normal);

// Compute reflection map coordinates if needed
if (TexGenReflection)
    reflection = ReflectionMap(ecposition3, normal);

// Compute texture coordinate for each enabled texture unit
for (i = 0; i < NumEnabledTextureUnits; i++)
{
    if (TexGenObject)
    {
        gl_TexCoord[i].s = dot(gl_Vertex, gl_ObjectPlaneS[i]);
        gl_TexCoord[i].t = dot(gl_Vertex, gl_ObjectPlaneT[i]);
        gl_TexCoord[i].p = dot(gl_Vertex, gl_ObjectPlaneR[i]);
        gl_TexCoord[i].q = dot(gl_Vertex, gl_ObjectPlaneQ[i]);
    }

    if (TexGenEye)
    {
        gl_TexCoord[i].s = dot(ecPosition, gl_EyePlaneS[i]);
        gl_TexCoord[i].t = dot(ecPosition, gl_EyePlaneT[i]);
        gl_TexCoord[i].p = dot(ecPosition, gl_EyePlaneR[i]);
        gl_TexCoord[i].q = dot(ecPosition, gl_EyePlaneQ[i]);
    }

    if (TexGenSphere)
        gl_TexCoord[i] = vec4(sphereMap, 0.0, 1.0);

    if (TexGenReflection)
        gl_TexCoord[i] = vec4(reflection, 1.0);

    if (TexGenNormal)
        gl_TexCoord[i] = vec4(normal, 1.0);
}

In this code, we assume that each texture unit less than NumEnabledTexture-Units is enabled. If this value is 0, the whole loop is skipped. Otherwise, each texture coordinate that is needed is computed in the loop.

Because the sphere map and reflection computations do not depend on any of the texture unit state, they can be performed once and the result is used for all texture units. For the GL_OBJECT_LINEAR and GL_EYE_LINEAR methods, there is a plane equation for each component of each set of texture coordinates. For the former case, we generate the components of gl_TexCoord[0] by multiplying the plane equation coefficients for the specified component by the incoming vertex position. For the latter case, we compute the components of gl_TexCoord[0] by multiplying the plane equation coefficients by the eye coordinate position of the vertex. Depending on what type of texture access is done during fragment processing, it may not be necessary to compute the t, p, or q texture component,[1] so these computations could be eliminated.

[1] For historical reasons, the OpenGL texture coordinate components are named s, t, r, and q. Because of the desire to have single-letter, component-selection names in the OpenGL Shading Language, components for textures are named s, t, p, and q. This lets us avoid using r, which is needed for selecting color components as r, g, b, and a.


Previous Page
Next Page




JavaScript EditorAjax Editor     JavaScript Editor