Multi Texture Demo
Multi-texturing
is a technique that is used to display multiple textures on one
surface. In Direct3D 10 this can be done by loading a second texture
image and sending it to the pixel shader. Inside the pixel shader both
shaders are sampled, and the results are blended together. How you blend
them is up to you. You can multiply the colors together, add them,
interpolate between them, and so forth. An example of multi-texturing is
shown in Figure 2.
In the Multi Texture demo’s shader file we declare a second Texture2D
object. Inside the pixel shader we sample from both shaders using the
same sampler state and the same texture coordinates. This is shown in Listing 7.
If you wanted, you could use different sampler states and even
different texture coordinates. In the pixel shader we combine colors by
multiplying them together. Since colors are in the range of 0.0 to 1.0,
two white colors will be white, two black colors will be black, and
anything in between will be a blend. We could also have added them
together to get a different effect, subtracted, linearly interpolated,
and so forth.
Listing 7. The Shader from the Multi Texture Demo
Texture2D decal2;
SamplerState DecalSampler { Filter = MIN_MAG_MIP_LINEAR; AddressU = Wrap; AddressV = Wrap; };
cbuffer cbChangesEveryFrame { matrix World; matrix View; };
cbuffer cbChangeOnResize { matrix Projection; };
struct VS_INPUT { float4 Pos : POSITION; float2 Tex : TEXCOORD; };
struct PS_INPUT { float4 Pos : SV_POSITION; float2 Tex : TEXCOORD0; };
PS_INPUT VS(VS_INPUT input) { PS_INPUT output = (PS_INPUT)0;
output.Pos = mul(input.Pos, World); output.Pos = mul(output.Pos, View); output.Pos = mul(output.Pos, Projection);
output.Tex = input.Tex;
return output; }
float4 PS(PS_INPUT input) : SV_Target { return decal1.Sample(DecalSampler, input.Tex) * decal2.Sample(DecalSampler, input.Tex); }
technique10 MultiTextureMapping { pass P0 { SetVertexShader(CompileShader(vs_4_0, VS())); SetGeometryShader(NULL); SetPixelShader(CompileShader(ps_4_0, PS())); } }
|
The
source code from the Multi Texture demo builds directly off of the code
from the Texture Mapping demo. In the global section another shader
resource view and shader resource variable were added for the second
texture. This addition is shown in Listing 8. In the InitializeDemo() function the second texture is loaded along with binding to the shader variable decal2, which is shown in Listing 9.
Listing 8. The Altered Globals in the Multi Texture Demo from Texture Mapping
ID3D10ShaderResourceView *g_squareDecal1 = NULL; ID3D10ShaderResourceView *g_squareDecal2 = NULL;
ID3D10EffectShaderResourceVariable *g_decalEffectVar1 = NULL; ID3D10EffectShaderResourceVariable *g_decalEffectVar2 = NULL;
|
Listing 6.9. The altered InitializeDemo() function from the Multi Texture demo.
bool InitializeDemo() { …
g_textureMapTech = g_shader->GetTechniqueByName( "MultiTextureMapping");
g_worldEffectVar = g_shader->GetVariableByName( World")->AsMatrix();
g_viewEffectVar = g_shader->GetVariableByName( "View")->AsMatrix();
g_projEffectVar = g_shader->GetVariableByName( "Projection")->AsMatrix();
g_decalEffectVar1 = g_shader->GetVariableByName( "decal1")->AsShaderResource();
g_decalEffectVar2 = g_shader->GetVariableByName( "decal2")->AsShaderResource(); // Load the textures. hr = D3DX10CreateShaderResourceViewFromFile(g_d3dDevice, "brick.dds", NULL, NULL, &g_squareDecal1, NULL);
if(FAILED(hr)) return false;
hr = D3DX10CreateShaderResourceViewFromFile(g_d3dDevice, "wavystars.dds", NULL, NULL, &g_squareDecal2, NULL);
if(FAILED(hr)) return false;
… }
|
The last modified code in the Multi Texture demo from the Texture Mapping demo can be seen in the RenderScene() and Shutdown() functions. In the RenderScene() function a new line of code is added to send the second texture to the decal2 shader variable. In the Shutdown()
function the second shader resource view and its texture object are
released from memory directly under the first texture. Both of these
functions are shown in Listing 10. A screenshot of the application is shown in Figure 3.
Listing 10. The RenderScene() and Shutdown() Functions from the Multi Texture Demo
void RenderScene() { float col[4] = { 0, 0, 0, 1 };
g_d3dDevice->ClearRenderTargetView(g_renderTargetView, col);
g_worldEffectVar->SetMatrix((float*)&g_worldMat); g_decalEffectVar1->SetResource(g_squareDecal1); g_decalEffectVar2->SetResource(g_squareDecal2); unsigned int stride = sizeof(DX10Vertex); unsigned int offset = 0;
g_d3dDevice->IASetInputLayout(g_layout); g_d3dDevice->IASetVertexBuffers(0, 1, &g_squareVB, &stride, &offset); g_d3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D10_TECHNIQUE_DESC techDesc; g_textureMapTech->GetDesc(&techDesc);
for(unsigned int i = 0; i < techDesc.Passes; i++) { g_textureMapTech->GetPassByIndex(i)->Apply(0); g_d3dDevice->Draw(6, 0); }
g_swapChain->Present(0, 0); }
void Shutdown() { if(g_d3dDevice) g_d3dDevice->ClearState(); if(g_swapChain) g_swapChain->Release(); if(g_renderTargetView) g_renderTargetView->Release();
if(g_shader) g_shader->Release(); if(g_layout) g_layout->Release(); if(g_squareVB) g_squareVB->Release();
if(g_squareDecal1) { ID3D10Resource *pRes; g_squareDecal1->GetResource(&pRes);
pRes->Release(); g_squareDecal1->Release(); }
if(g_squareDecal2) { ID3D10Resource *pRes; g_squareDecal2->GetResource(&pRes);
pRes->Release(); g_squareDecal2->Release(); }
if(g_d3dDevice) g_d3dDevice->Release(); }
|