Here is a screen shot:
[attachment=9405:flarecube.PNG]
Clearly this is not what I wanted.
Basically what I am doing is this: I create two D3DXVECTOR2s to be used as offsets. One for both textures. I then rotate them a bit each frame(at different rates). Lastly, I add both offsets in the vertex shader, and store the results in the cooresponding members of the outVS structure like this:
OutputVS TerrainMultiTexVS(float3 posL : POSITION0,
float3 normalL : NORMAL0,
float2 tex0: TEXCOORD0)
{
//
//omitted code
//
outVS.tex0 = tex0 + gTexOffset;
outVS.tex1 = tex0 + gBlendOffset;
// Done--return the output.
return outVS;
}
Note how "tex0" is used in both additions. That is because "tex0" is the only set of texture coordinates that is fed into the vertex shader.
Again, I don't want them orbiting the center of the faces in a circle. I want them to simply rotate about their own axes. (which is of course the center of each face)
Here is some source code...
// this is from Vertex.h
struct VertexPNT
{
VertexPNT()
:pos(0.0f, 0.0f, 0.0f),
normal(0.0f, 0.0f, 0.0f),
tex0(0.0f, 0.0f){}
VertexPNT(float x, float y, float z,
float nx, float ny, float nz,
float u, float v):pos(x,y,z), normal(nx,ny,nz), tex0(u,v){}
VertexPNT(const D3DXVECTOR3& v, const D3DXVECTOR3& n, const D3DXVECTOR2& uv)
:pos(v),normal(n), tex0(uv){}
D3DXVECTOR3 pos;
D3DXVECTOR3 normal;
D3DXVECTOR2 tex0;
static IDirect3DVertexDeclaration9* Decl;
};
// this is from Vertex.cpp
D3DVERTEXELEMENT9 VertexPNTElements[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};
HR(gd3dDevice->CreateVertexDeclaration(VertexPNTElements, &VertexPNT::Decl));
// found in class definition
D3DXHANDLE mhTexOffset;
D3DXHANDLE mhBlendOffset;
D3DXVECTOR2 mTexOffset;
D3DXVECTOR2 mBlendOffset;
float angle_Tex;
float angle_Blend;
D3DXMATRIX Mt;
D3DXMATRIX Mb;
// found in constructor
angle_Tex = 0.0f;
angle_Blend = 0.0f;
mTexOffset = D3DXVECTOR2(0.0f, 0.0f);
mBlendOffset = D3DXVECTOR2(0.0f, 0.0f);
HR(D3DXCreateTextureFromFile(gd3dDevice, "flare.dds", &mTex));
HR(D3DXCreateTextureFromFile(gd3dDevice, "flarealpha.bmp", &mBlend));
void FlareCubeDemo::updateScene(float dt)
{
mGfxStats->update(dt);
// Get snapshot of input devices.
gDInput->poll();
// Check input.
if( gDInput->keyDown(DIK_W) )
mCameraHeight += 25.0f * dt;
if( gDInput->keyDown(DIK_S) )
mCameraHeight -= 25.0f * dt;
// Divide by 50 to make mouse less sensitive.
mCameraRotationY += gDInput->mouseDX() / 100.0f;
mCameraRadius += gDInput->mouseDY() / 25.0f;
// If we rotate over 360 degrees, just roll back to 0
if( fabsf(mCameraRotationY) >= 2.0f * D3DX_PI )
mCameraRotationY = 0.0f;
// Don't let radius get too small.
if( mCameraRadius < 5.0f )
mCameraRadius = 5.0f;
angle_Tex = 0.001;
angle_Blend = 0.005;
// The camera position/orientation relative to world space can
// change every frame based on input, so we need to rebuild the
// view matrix every frame with the latest changes.
buildViewMtx();
mTexOffset += D3DXVECTOR2(-0.5f, -0.5f);
mBlendOffset += D3DXVECTOR2(-0.5f, -0.5f);
D3DXMatrixRotationZ(&Mt, angle_Tex);
D3DXMatrixRotationZ(&Mb, angle_Blend);
D3DXVec2TransformCoord(&mTexOffset, &mTexOffset, &Mt);
D3DXVec2TransformCoord(&mBlendOffset, &mBlendOffset, &Mb);
mTexOffset += D3DXVECTOR2(0.5f, 0.5f);
mBlendOffset += D3DXVECTOR2(0.5f, 0.5f);
}
void FlareCubeDemo::drawScene()
{
// Clear the backbuffer and depth buffer.
HR(gd3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffeeeeee, 1.0f, 0));
HR(gd3dDevice->BeginScene());
// Setup the rendering FX
HR(mFX->SetTechnique(mhTech));
HR(mFX->SetMatrix(mhWVP, &(mWorld*mView*mProj)));
D3DXMATRIX worldInvTrans;
D3DXMatrixInverse(&worldInvTrans, 0, &mWorld);
D3DXMatrixTranspose(&worldInvTrans, &worldInvTrans);
HR(mFX->SetMatrix(mhWorldInvTrans, &worldInvTrans));
HR(mFX->SetValue(mhLightVecW, &mLightVecW, sizeof(D3DXVECTOR3)));
HR(mFX->SetValue(mhDiffuseMtrl, &mDiffuseMtrl, sizeof(D3DXCOLOR)));
HR(mFX->SetValue(mhDiffuseLight, &mDiffuseLight, sizeof(D3DXCOLOR)));
HR(mFX->SetValue(mhAmbientMtrl, &mAmbientMtrl, sizeof(D3DXCOLOR)));
HR(mFX->SetValue(mhAmbientLight, &mAmbientLight, sizeof(D3DXCOLOR)));
HR(mFX->SetValue(mhSpecularLight, &mSpecularLight, sizeof(D3DXCOLOR)));
HR(mFX->SetValue(mhSpecularMtrl, &mSpecularMtrl, sizeof(D3DXCOLOR)));
HR(mFX->SetFloat(mhSpecularPower, mSpecularPower));
HR(mFX->SetMatrix(mhWorld, &mWorld));
HR(mFX->SetTexture(mhTex, mTex));
HR(mFX->SetTexture(mhBlend, mBlend));
HR(mFX->SetValue(mhTexOffset, &mTexOffset, sizeof(D3DXVECTOR2)));
HR(mFX->SetValue(mhBlendOffset, &mBlendOffset, sizeof(D3DXVECTOR2)));
HR(gd3dDevice->SetVertexDeclaration(VertexPNT::Decl));
HR(gd3dDevice->SetStreamSource(0, mBoxVB, 0, sizeof(VertexPNT)));
HR(gd3dDevice->SetIndices(mBoxIB));
// Begin passes.
UINT numPasses = 0;
HR(mFX->Begin(&numPasses, 0));
for(UINT i = 0; i < numPasses; ++i)
{
HR(mFX->BeginPass(i));
HR(gd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12));
HR(mFX->EndPass());
}
HR(mFX->End());
mGfxStats->display();
HR(gd3dDevice->EndScene());
// Present the backbuffer.
HR(gd3dDevice->Present(0, 0, 0, 0));
}
void FlareCubeDemo::buildBoxGeometry()
{
// Create the vertex buffer.
HR(gd3dDevice->CreateVertexBuffer(24 * sizeof(VertexPNT), D3DUSAGE_WRITEONLY,
0, D3DPOOL_MANAGED, &mBoxVB, 0));
// Write box vertices to the vertex buffer.
VertexPNT* v = 0;
HR(mBoxVB->Lock(0, 0, (void**)&v, 0));
// Fill in the front face vertex data.
v[0] = VertexPNT(-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
v[1] = VertexPNT(-1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
v[2] = VertexPNT( 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
v[3] = VertexPNT( 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);
// Fill in the back face vertex data.
v[4] = VertexPNT(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
v[5] = VertexPNT( 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f);
v[6] = VertexPNT( 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
v[7] = VertexPNT(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f);
// Fill in the top face vertex data.
v[8] = VertexPNT(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
v[9] = VertexPNT(-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
v[10] = VertexPNT( 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);
v[11] = VertexPNT( 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f);
// Fill in the bottom face vertex data.
v[12] = VertexPNT(-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f);
v[13] = VertexPNT( 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f);
v[14] = VertexPNT( 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f);
v[15] = VertexPNT(-1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);
// Fill in the left face vertex data.
v[16] = VertexPNT(-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
v[17] = VertexPNT(-1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f);
v[18] = VertexPNT(-1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f);
v[19] = VertexPNT(-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
// Fill in the right face vertex data.
v[20] = VertexPNT( 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
v[21] = VertexPNT( 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f);
v[22] = VertexPNT( 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f);
v[23] = VertexPNT( 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
HR(mBoxVB->Unlock());
// Create the vertex buffer.
HR(gd3dDevice->CreateIndexBuffer(36 * sizeof(WORD), D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16, D3DPOOL_MANAGED, &mBoxIB, 0));
// Write box indices to the index buffer.
WORD* i = 0;
HR(mBoxIB->Lock(0, 0, (void**)&i, 0));
// Fill in the front face index data
i[0] = 0; i[1] = 1; i[2] = 2;
i[3] = 0; i[4] = 2; i[5] = 3;
// Fill in the back face index data
i[6] = 4; i[7] = 5; i[8] = 6;
i[9] = 4; i[10] = 6; i[11] = 7;
// Fill in the top face index data
i[12] = 8; i[13] = 9; i[14] = 10;
i[15] = 8; i[16] = 10; i[17] = 11;
// Fill in the bottom face index data
i[18] = 12; i[19] = 13; i[20] = 14;
i[21] = 12; i[22] = 14; i[23] = 15;
// Fill in the left face index data
i[24] = 16; i[25] = 17; i[26] = 18;
i[27] = 16; i[28] = 18; i[29] = 19;
// Fill in the right face index data
i[30] = 20; i[31] = 21; i[32] = 22;
i[33] = 20; i[34] = 22; i[35] = 23;
HR(mBoxIB->Unlock());
}
And finally, the effect file in its entirety...
// CHAPTER 11 11.13 EXERCISE 6
// ANIMATED FLARE ON CUBE
uniform extern float4x4 gWorld;
uniform extern float4x4 gWorldInvTrans;
uniform extern float4x4 gWVP;
uniform extern float4 gAmbientMtrl;
uniform extern float4 gAmbientLight;
uniform extern float4 gDiffuseMtrl;
uniform extern float4 gDiffuseLight;
uniform extern float4 gSpecularMtrl;
uniform extern float4 gSpecularLight;
uniform extern float gSpecularPower;
uniform extern float3 gLightVecW;
uniform extern float3 gEyePosW;
uniform extern texture gTex;
uniform extern texture gBlend;
uniform extern float2 gTexOffset;
uniform extern float2 gBlendOffset;
// Use Anisotropic filtering since when we are low to the ground, the
// ground plane is near a 90 degree angle with our view direction.
sampler Tex0S = sampler_state
{
Texture = <gTex>;
MinFilter = Anisotropic;
MagFilter = LINEAR;
MipFilter = LINEAR;
MaxAnisotropy = 8;
AddressU = WRAP;
AddressV = WRAP;
};
sampler BlendS = sampler_state
{
Texture = <gBlend>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
struct OutputVS
{
float4 posH : POSITION0;
float4 diffuse : COLOR0;
float4 spec : COLOR1;
float2 tex0 : TEXCOORD0;
float2 tex1 : TEXCOORD1;
};
OutputVS MultiTexVS(float3 posL : POSITION0,
float3 normalL : NORMAL0,
float2 tex0: TEXCOORD0)
{
// Zero out our output.
OutputVS outVS = (OutputVS)0;
// Transform normal to world space.
float3 normalW = mul(float4(normalL, 0.0f), gWorldInvTrans).xyz;
normalW = normalize(normalW);
// Transform vertex position to world space.
float3 posW = mul(float4(posL, 1.0f), gWorld).xyz;
//=======================================================
// Compute the color: Equation 10.3.
// Compute the vector from the vertex to the eye position.
float3 toEye = normalize(gEyePosW - posW);
// Compute the reflection vector.
float3 r = reflect(-gLightVecW, normalW);
// Determine how much (if any) specular light makes it into the eye.
float t = pow(max(dot(r, toEye), 0.0f), gSpecularPower);
// Determine the diffuse light intensity that strikes the vertex.
float s = max(dot(gLightVecW, normalW), 0.0f);
// Compute the ambient, diffuse and specular terms separatly.
float3 spec = t*(gSpecularMtrl*gSpecularLight).rgb;
float3 diffuse = s*(gDiffuseMtrl*gDiffuseLight).rgb;
float3 ambient = gAmbientMtrl*gAmbientLight;
// Sum all the terms together and copy over the diffuse alpha.
outVS.diffuse.rgb = ambient + diffuse;
outVS.diffuse.a = gDiffuseMtrl.a;
outVS.spec = float4(spec, 0.0f);
//=======================================================
// Transform to homogeneous clip space.
outVS.posH = mul(float4(posL, 1.0f), gWVP);
outVS.tex0 = tex0 + gTexOffset;
outVS.tex1 = tex0 + gBlendOffset;
// Done--return the output.
return outVS;
}
float4 MultiTexPS(float4 diffuse : COLOR0,
float4 spec : COLOR1,
float2 tex0 : TEXCOORD0,
float2 tex1 : TEXCOORD1) : COLOR
{
// Layer maps are tiled
float3 c0 = tex2D(Tex0S, tex0).rgb;
// Blendmap is not tiled.
float3 B = tex2D(BlendS, tex1).rgb;
// Scale the colors by each layer by its corresponding weight
// stored in the blendmap.
c0 *= B;
// Sum the colors and modulate with the lighting color.
float3 final = (c0) * diffuse.rgb;
return float4(final + spec, diffuse.a);
}
technique MultiTexTech
{
pass P0
{
// Specify the vertex and pixel shader associated with this pass.
vertexShader = compile vs_2_0 TerrainMultiTexVS();
pixelShader = compile ps_2_0 TerrainMultiTexPS();
}
}
What am I doing wrong? Do I have to redesign the whole thing usings two sets of texture coordinates instead of using offsets?