PrefaceOne of the most interesting features introduced to Direct3D in DirectX 6 was multiple texturing. In previous versions of DirectX, the texture mapping phase of the Direct3D pixel pipeline had only involved fetching texels from a single texture. DirectX 6 introduced the concept of a texture operation unit. Get the source here. To compile the source, take a look at "The Basics" Tutorial. To switch between the examples use the #defines at the beginning of the source:
Texture Replaces LightMost effects that modify the appearance of a surface are calculated on what's called a "per-vertex" basis. This means that the actual calculations are done for each vertex of a triangle, as opposed to each pixel that gets rendered. Sometimes with this technique you get noticeable artifacts. Think of a large triangle with a light source close to the surface. As long as the light is close to one of the vertices of the triangle, you can see the lighting effects on the triangle. When it moves towards the center of the triangle, then the triangle gradually loses the lighting effect. In the worst case, the light is directly in the middle of the triangle and you see a triangle with very little light shining on it, instead of a triangle with a bright spot in the middle. If no light shines on the vertices, the surface properties are not calculated as properly. The best way to generate the illusion of pixel-based lighting is to use a texture map of the desired type of light shining on a dark surface. Multipass Rendering/Multitexturing/Bump mappingThe three main texture-blending techniques are multipass rendering, multiple-texture blending or multitexturing and bump mapping. Multipass texturing is the process of applying more than one texture to a primitive in several passes. Brian Hook tells us in his course 29 notes at SIGGRAPH '98, that Quake III uses 10 passes:
Only on the fastest machines can up to 10 passes be done to render a single frame. If the graphics accelerator cannot maintain a reasonable framerate, various passes (those in parantheses) can be eleminated. It's obvious that the more passes a renderer must take, the lower its overall performance will be. To reduce the number of passes, some graphics accelerators support multitexturing, in which two or more textures are accessed during the same pass. Bump mapping is a texture-blending method that models a realistic rough surface on primitives. The bump map contains depth information in the form of values indicating high and low spots on the surface. Watch out for a tutorial on bump mapping, coming soon. The Texture Operation UnitBefore Direct3D 6 the pipeline stages determined the texel color and blended this color with the color of the primitive interpolated from the vertices (multipass texturing). From Direct3D 6 up to 8 texture operation units can be cascaded together to apply multiple textures to a common primitive in a single pass (multitexturing). The results of each stage carry over to the next one, and the result of the final stage is rasterized on the polygon. This process is called "texture blending cascade". Each texture operation unit has six associated render states, which control the flow of pixels through the unit, as well as additional render states associated with filtering, clamping and so on.
Three of the render states in each texture operation unit are associated with RGB (color), and another three are associated with alpha.
Multitexturing SupportFirst, you have to check your 3D hardware's multitexturing support in the framework call ConfirmDevice():
Dark MappingThe D3DTSS_COLORx render states control the flow of an RGB vector, while the D3DTSS_ALPHAx render states govern the flow of the scalar alpha through parallel segments of the pixel pipeline. In Render() we use:
In Detail:
This code combines the following textures: x= This kind of multitexturing is called dark mapping, because the resulting texel is a darker version of the unlit texel of the primary map. This technique is used a lot in 3D shooters. You can see it in GLQuake1. Nothing interesting is being done with the alpha channel of the pipeline in this case. There are no D3DTSS_ALPHAx render state calls. For RGB color, the render states D3DTSS_COLORARG1 and D3DTSS_COLORARG2 control arguments, while D3DTSS_COLORUP controls the operation on the arguments. The first texture operation unit passes the data from texture 0 to the next stage. The control argument D3DTA_TEXTURE means: The texture argument is the texture color for this texture stage. The second texture operation unit receives these texels via Arg2. It modulates (D3DTOP_MODULATE) the texels from texture 0 with the texels from texture 1, which were received via Arg1. There are two other modulation operations:
The D3DTEXTUREOP structure shows the possible per-stage texture-blending operations. Just take a look at your DirectX 7 documentation. The default value for the first texture stage (stage 0) is D3DTOP_MODULATE, and for all other stages the default is D3DTOP_DISABLE. The IDirect3DDevice7::SetTexture method assigns a texture to a given stage for a device. The first parameter must be a number in the range of 0-7 inclusive. Pass the texture interface pointer as the second parameter. This method increments the reference count of the texture surface being assigned. When the texture is no longer needed, you should set the texture at the appropriate stage to NULL. If you fail to do this, the surface will not be released, resulting in a memory leak. Since version 6, Direct3D maintains a list of up to eight current textures. So Direct3D supports the blending of up to eight textures onto a primitive at once. It blends these textures onto all of the primitives it renders. Only textures created as texture interface pointers can be used in the set of current textures.
When your application selects a texture as the current texture, it instructs the Direct3D device to apply the texture to all primitives that are rendered from that time until the current texture is changed again. If each primitive in a 3-D scene has its own texture, the texture must be set before each primitive is rendered.
I've made an animated sample with the three modulation types:
Blending a texture with diffuse color lightingSometimes the sun shines so bright that the colors on things get brighter. You can immitate that effect by blending the texture with diffuse color lighting:
In Detail:
Darkmap blended with diffuse color lightingNow we're combining the two effects:
I think this is self-explaining for an old multitexturing freak like you. You should play around with D3DTOP_ADDSIGNED, D3DTOP_SUBTRACT and D3DTOP_ADDSIGNED2X as the color operation of the first texture stage. My favorites are D3DTOP_ADDSIGNED and D3DTOP_SUBTRACT. The latter is really cool. The Alpha operationsAs Direct3D renders a scene, it can integrate color information from several sources: vertex color, the current material, texture map and the color previously written to the render target. It can blend several of these colors. A factor called alpha, which could be stored in vertices, materials and texture maps, can be used to indicate how blending should be weighted. An alpha value of 0 means full transparency, an alpha value of 1 means some level of semitransparency. Modulate AlphaIn 1992 I played Comanche from Novalogic the first time. I wondered about making the night flight feature in some missions. The whole terrain, the clouds and the horizon were green. They looked like modulating a green ambient light with the textures by alpha. For this example, I switched from a directional light to a green ambient light. This light is modulated with the texture colour:
To modulate the ambient color with the texture:
Alpha blending with the Frame BufferYou can use alpha blending to combine the primitive's color with the color previously stored in that pixel of the frame buffer. That's called blending with the frame buffer. Using this form of alpha blending, you can simulate semitransparent objects, combine two images, and add special effects such as force fields, flames, plasma beams and light mapping. Direct3D uses the following formula to compute the final color for each pixel in the rendered primitive: FinalColor = SourcePixelColor * SourceBlendFactor + DestPixelColor * DestBlendFactor It lets you change the SourceBlendFactor and DestBlendFactor flags to generate the effect you want. I set the following RenderStates in InitDeviceObjects():
As a result of the calls in the preceding code fragment, Direct3D performs a linear blend between the source color (the color of the primitive being rendered at the current location) and the destination color (the color at the current location in the frame buffer). This gives an appearance similar to tinted glass. Some of the color of the destination object seems to be transmitted through the source object. The rest of it appears to be absorbed. Alpha blending requires a fair bit of extra math and memory access, so turning it on and off with ALPHABLENDENABLE is worth the effort. In the Render() method, there's only a call to set the texture:
I hope you enjoyed our small trip into the word of the Direct3D 7 IM Framework. If you disliked or liked it, give me a sign at wolf@direct3d.net. Discuss this article in the forums
See Also: © 1999-2011 Gamedev.net. All rights reserved. Terms of Use Privacy Policy
|