You are on page 1of 3

LINEAR, NEAREST,

NEAREST_MIPMAP_NEAREST, LINEAR_MIPMAP_NEAREST,
NEAREST_MIPMAP_LINEAR, LINEAR_MIPMAP_LINEAR
The last four options require having set mipmaps by calling
gl.generateMipmap(gl.TEXTURE_2D)first. We
will cover mipmaps later on in the chapter.
Texture filter parameters can be set by calling one of:
void texParameterf(GLenum target, GLenum param_name, GLfloat param);
void texParameteri(GLenum target, GLenum param_name, GLint param);
The result of shrinking a texture of a dog and varying the TEXTURE_MIN_FILTER setting can be
seen in the
difference of sharpness of the two resulting images in Figure 3-4.
Figure 3-4. Left - NEAREST filtering; Right - LINEAR_MIPMAP_LINEAR filtering
The left image uses
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
The right image uses
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,
gl.LINEAR_MIPMAP_LINEAR);
Texture Wrapping
Texture wrapping is the way we handle coordinates (s,t) that fall outside of our normal texture
coordinate range
of [0,1]. Wrapping parameter names, pname, can be either TEXTURE_WRAP_S or
TEXTURE_WRAP_T.
The default wrapping mode is to REPEAT the texture (it uses only the fractional part of the texture
coordinate).
Two other options are CLAMP_TO_EDGE, which samples only coordinates that are within the
range [0,1], and
MIRRORED_REPEAT which is the same as REPEAT for coordinates with an even integer
component (2.3 and 4.3
are both mapped to 0.3). For odd integer components, the fractional part of the coordinate is
mapped to
(1- coordinate_fractional_value), so 1.3 and 3.3 end up being both mapped to 0.7. Adjustments to
the wrapping
modes are shown in Figures 3-5 to Figure 3-7.
To find the current value of a texture parameter, you can use this function:
getTexParameter(GLenum target, GLenum pname)
63CHAPTER 3 N TEXTURES AND LIGHTING
Figure 3-5. Left – original texture image; Center - texture application onto a triangle with default
REPEAT; Right -
multiplying the texture coordinate values in the shader to pronounce the repetition
Figure 3-6. Left - TEX_WRAP_S set to CLAMP_TO_EDGE; Center - TEX_WRAP_T set to
CLAMP_TO_EDGE; Right - both S and
T set to CLAMP_TO_EDGE
Figure 3-7. Left - TEX_WRAP_S set to MIRRORED_REPEAT; Center - TEX_WRAP_T set to
MIRRORED_REPEAT; Right - both S
and T set to MIRRORED_REPEAT
Data Storage
We can adjust the way texture data is stored in WebGL through calls to this function:
void pixelStorei(GLenum pname, GLint param);
In Listing 3-1, we flipped the texture vertically using this:
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
64CHAPTER 3 N TEXTURES AND LIGHTING
The options we have for pname are UNPACK_FLIP_Y_WEBGL,
UNPACK_PREMULTIPLY_ALPHA_WEBGL, and
UNPACK_COLORSPACE_CONVERSION_WEBGL. For the first two options, any nonzero
param value is interpreted as true.
UNPACK_FLIP_Y_WEBGL flips the source data along the vertical y-axis if set to true. This makes
the last row
of data to be the first row transferred. The reason to set this option to true is that data loaded from
other HTML
images have the y-axis naturally point in the opposite direction from WebGL. Without the call, the
image will
appear to be upside down.
If UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to true, and the source data has an alpha
channel, it will be
multiplied against all the other channels during transfer: (r,g,b,a) => (r*a, g*a, b*a, a).
Finally, UNPACK_COLORSPACE_CONVERSION_WEBGL converts the source data to the
browser’s default
colorspace. For this option, param is set to either BROWSER_DEFAULT_WEBGL or NONE.
Mipmaps
To aid in accurate texture filtering, mipmaps are a precalculated optimized set of decreasingly sized
versions of
a texture. They are one place where the power of 2 comes in to play for textures. Each image in a
mipmap is a
smaller version of the last—starting with half the dimension size, then a quarter, an eighth, and so
on.
For example, if the original texture was 256x256 pixels in dimension, we would have smaller
textures in the
mipmap of sizes 128x128, 64x64, 32x32, [...], 2x2, 1x1.
Because the size of each texture is only 25 percent (1⁄2 * 1⁄2) the size of the previous, the total size
of a mipmap
is only one-third larger than that of the original texture. Mipmaps improve accuracy when the
surface that we are
applying our texture to is smaller than our original texture.
To generate the mipmap for the currently bound texture, all you have to do is call this function:
void generateMipmap(GLenum target)
As we have shown in our code, the function looks like this:
gl.generateMipmap(gl.TEXTURE_2D);
N Note Calling generateMipmap with no WebGLTexture bound or a Non-Power-Of-Two (NPOT)
texture will gener-
ate an INVALID_OPERATION error.
The texture image of our dog along with a decreasing series of texture sizes is shown in Figure 3-8.
This image
represents a mipmap.
Figure 3-8. Mipmap representation of a dog texture
65CHAPTER 3 N TEXTURES AND LIGHTING
Texturing a 3D Object
Now that we have a background of texturing and some 2D practice, we will texture a 3-D object.
We will start with
the last example from Chapter 1, found in the 01/3D_triangles_depth_test.html file. As you may
recall, that
example is of a rotating triangular prism. We will now texture it as a first step to producing the
image on the right
of Figure 3-1. We will use a separate attribute for texture coordinates. We shall see that 3D texturing
can be more
complex than 2D texturing. The texture we will load, textures/stone-128px.jpg, will display stone
bricks.
Texture Coordinate Attribute
We need to calculate texture coordinates per vertex and send them on to our shader program. First,
we add two
new variables:
vertexTexCoordAttribute = null,
trianglesTexCoordBuffer = null,
Next we define texture coordinates for each vertex as shown in Listing 3-4.
Listing 3-4. Providing texture coordinates
var triangleTexCoords = [
//front face
0.0, 0.0,
1.0, 0.0,
2.0, 0.0,
0.5, 1.0,
1.5, 1.0,
1.0, 2.0,
//rear face
0.0, 0.0,
1.0, 0.0,
2.0, 0.0,
0.5, 1.0,
1.5, 1.0,
1.0, 2.0
];
trianglesTexCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesTexCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleTexCoords), gl.STATIC_DRAW);
Here I have been lazy and just used the x and y values of the vertex points. Note that even though
values lie
past the [0.0, 1.0] range of texture coordinates, the coordinates we provide still work. This can be
seen on the
front face of the prism in Figure 3-9. The reason it still works is because, as mentioned above, the
default WebGL
wrap mode is gl.REPEAT and we are using a seamless tiled texture.
Finally, in our drawScene method, we need to use our buffer data:
vertexTexCoordAttribute = gl.getAttribLocation(glProgram, "aVertexTexCoord");
gl.enableVertexAttribArray(vertexTexCoordAttribute);
gl.bindBuffer(gl.ARRAY_BUFFER, trianglesTexCoordBuffer);
gl.vertexAttribPointer(vertexTexCoordAttribute, 2, gl.FLOAT, false, 0, 0);
66CHAPTER 3 N TEXTURES AND LIGHTING
Adjusting Our Shaders
In our vertex shader we now have an attrib

You might also like