Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Hseptic

Member Since 21 May 2012
Offline Last Active Aug 03 2012 10:26 AM

Topics I've Started

Billboarding trees are not visible

01 July 2012 - 04:54 PM

I'm trying to billboard four trees in the vertex shader, but they are not visible when running the program.
Here is some source code:

TreeDemo::TreeDemo(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP)
: D3DApp(hInstance, winCaption, devType, requestedVP)
{
if(!checkDeviceCaps())
{
  MessageBox(0, "checkDeviceCaps() Failed", 0, 0);
  PostQuitMessage(0);
}
mGfxStats = new GfxStats();

mCameraRadius	= 6.0f;
mCameraRotationY = 1.2 * D3DX_PI;
mCameraHeight	= 3.0f;
mLightVecW	 = D3DXVECTOR3(0.0, 0.707f, -0.707f);
mDiffuseLight  = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
mAmbientLight  = D3DXCOLOR(0.6f, 0.6f, 0.6f, 1.0f);
mSpecularLight = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
mGroundMtrl.ambient   = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
mGroundMtrl.diffuse   = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
mGroundMtrl.spec	  = D3DXCOLOR(0.4f, 0.4f, 0.4f, 1.0f);
mGroundMtrl.specPower = 8.0f;
mGateMtrl.ambient   = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
mGateMtrl.diffuse   = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
mGateMtrl.spec	  = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
mGateMtrl.specPower = 8.0f;
mTreeMtrl.ambient   = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
mTreeMtrl.diffuse   = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
mTreeMtrl.spec	  = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
mTreeMtrl.specPower = 8.0f;
D3DXMatrixIdentity(&mGroundWorld);
D3DXMatrixIdentity(&mGateWorld);
D3DXMatrixIdentity(&mTreeWorld);
HR(D3DXCreateTextureFromFile(gd3dDevice, "tree.dds", &mTreeTex));
HR(D3DXCreateTextureFromFile(gd3dDevice, "ground0.dds", &mGroundTex));
HR(D3DXCreateTextureFromFile(gd3dDevice, "gatea.dds", &mGateTex));
buildGridGeometry();
buildGateGeometry();
buildTreeGeometry();
mGfxStats->addVertices(mNumGridVertices);
mGfxStats->addTriangles(mNumGridTriangles);
// Add gate quad vertices.
mGfxStats->addVertices(4);
mGfxStats->addTriangles(2);
buildFX();
onResetDevice();
InitAllVertexDeclarations();
}
void TreeDemo::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->SetValue(mhLightVecW, &mLightVecW, sizeof(D3DXVECTOR3)));
HR(mFX->SetValue(mhDiffuseLight, &mDiffuseLight, sizeof(D3DXCOLOR)));
HR(mFX->SetValue(mhAmbientLight, &mAmbientLight, sizeof(D3DXCOLOR)));
HR(mFX->SetValue(mhSpecularLight, &mSpecularLight, sizeof(D3DXCOLOR)));

drawGround();

drawTrees();

mGfxStats->display();
HR(gd3dDevice->EndScene());
// Present the backbuffer.
HR(gd3dDevice->Present(0, 0, 0, 0));
}
void TreeDemo::buildGridGeometry()
{
std::vector<D3DXVECTOR3> verts;
std::vector<DWORD> indices;
GenTriGrid(100, 100, 1.0f, 1.0f,
  D3DXVECTOR3(0.0f, 0.0f, 0.0f), verts, indices);
// Save vertex count and triangle count for DrawIndexedPrimitive arguments.
mNumGridVertices  = 100*100;
mNumGridTriangles = 99*99*2;
// Obtain a pointer to a new vertex buffer.
HR(gd3dDevice->CreateVertexBuffer(mNumGridVertices * sizeof(VertexPNT),
  D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &mGridVB, 0));
// Now lock it to obtain a pointer to its internal data, and write the
// grid's vertex data.
VertexPNT* v = 0;
HR(mGridVB->Lock(0, 0, (void**)&v, 0));
float texScale = 0.2f;
for(int i = 0; i < 100; ++i)
{
  for(int j = 0; j < 100; ++j)
  {
   DWORD index = i * 100 + j;
   v[index].pos	= verts[index];
   v[index].normal = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
   v[index].tex0 = D3DXVECTOR2((float)j, (float)i) * texScale;
  }
}
HR(mGridVB->Unlock());

// Obtain a pointer to a new index buffer.
HR(gd3dDevice->CreateIndexBuffer(mNumGridTriangles*3*sizeof(WORD), D3DUSAGE_WRITEONLY,
  D3DFMT_INDEX16, D3DPOOL_MANAGED, &mGridIB, 0));
// Now lock it to obtain a pointer to its internal data, and write the
// grid's index data.
WORD* k = 0;
HR(mGridIB->Lock(0, 0, (void**)&k, 0));
for(DWORD i = 0; i < mNumGridTriangles*3; ++i)
  k[i] = (WORD)indices[i];
HR(mGridIB->Unlock());
}
void TreeDemo::buildTreeGeometry()
{

HR(gd3dDevice->CreateVertexBuffer(16* sizeof(VertexPNT),
  D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &mTreeVB, 0));
VertexPNT* v = 0;
HR(mTreeVB->Lock(0, 0, (void**)&v, 0));
v[0] = VertexPNT(-0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
v[1] = VertexPNT(-0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
v[2] = VertexPNT( 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
v[3] = VertexPNT( 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f);
v[4] = VertexPNT(-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
v[5] = VertexPNT(-0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f);
v[6] = VertexPNT( 0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f);
v[7] = VertexPNT( 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f);
v[8] = VertexPNT(-0.5f, 0.0f, 0.0f, 2.0f, 0.0f, 2.0f, 0.0f, 1.0f);
v[9] = VertexPNT(-0.5f, 1.0f, 0.0f, 2.0f, 0.0f, 2.0f, 0.0f, 0.0f);
v[10] = VertexPNT( 0.5f, 1.0f, 0.0f, 2.0f, 0.0f, 2.0f, 1.0f, 0.0f);
v[11] = VertexPNT( 0.5f, 0.0f, 0.0f, 2.0f, 0.0f, 2.0f, 1.0f, 1.0f);
v[12] = VertexPNT(-0.5f, 0.0f, 0.0f, -2.0f, 0.0f, -2.0f, 0.0f, 1.0f);
v[13] = VertexPNT(-0.5f, 1.0f, 0.0f, -2.0f, 0.0f, -2.0f, 0.0f, 0.0f);
v[14] = VertexPNT( 0.5f, 1.0f, 0.0f, -2.0f, 0.0f, -2.0f, 1.0f, 0.0f);
v[15] = VertexPNT( 0.5f, 0.0f, 0.0f, -2.0f, 0.0f, -2.0f, 1.0f, 1.0f);
HR(mTreeVB->Unlock());

HR(gd3dDevice->CreateIndexBuffer(24*sizeof(WORD), D3DUSAGE_WRITEONLY,
  D3DFMT_INDEX16, D3DPOOL_MANAGED, &mTreeIB, 0));

WORD* k = 0;
HR(mTreeIB->Lock(0, 0, (void**)&k, 0));
k[0] = 0;  k[1] = 1;  k[2] = 2; // Triangle 0
k[3] = 0;  k[4] = 2;  k[5] = 3; // Triangle 1
k[6] = 4;  k[7] = 5;  k[8] = 6; // Triangle 2
k[9] = 4;  k[10] = 5;  k[11] = 7; // Triangle 3
k[12] = 8;  k[13] = 9;  k[14] = 10; // Triangle 4
k[15] = 8;  k[16] = 9;  k[17] = 11; // Triangle 5
k[18] = 12;  k[19] = 13;  k[20] = 14; // Triangle 6
k[21] = 12;  k[22] = 13;  k[23] = 15; // Triangle 7
HR(mTreeIB->Unlock());
}
void TreeDemo::buildFX()
{
// Create the FX from a .fx file.
ID3DXBuffer* errors = 0;
HR(D3DXCreateEffectFromFile(gd3dDevice, "DirLightTex.fx",
  0, 0, D3DXSHADER_DEBUG, 0, &mFX, &errors));
if( errors )
  MessageBox(0, (char*)errors->GetBufferPointer(), 0, 0);
// Obtain handles.
mhTech		  = mFX->GetTechniqueByName("DirLightTexTech");
mhWVP		   = mFX->GetParameterByName(0, "gWVP");
mhWorldInvTrans = mFX->GetParameterByName(0, "gWorldInvTrans");
mhLightVecW	 = mFX->GetParameterByName(0, "gLightVecW");
mhDiffuseMtrl   = mFX->GetParameterByName(0, "gDiffuseMtrl");
mhDiffuseLight  = mFX->GetParameterByName(0, "gDiffuseLight");
mhAmbientMtrl   = mFX->GetParameterByName(0, "gAmbientMtrl");
mhAmbientLight  = mFX->GetParameterByName(0, "gAmbientLight");
mhSpecularMtrl  = mFX->GetParameterByName(0, "gSpecularMtrl");
mhSpecularLight = mFX->GetParameterByName(0, "gSpecularLight");
mhSpecularPower = mFX->GetParameterByName(0, "gSpecularPower");
mhEyePos		= mFX->GetParameterByName(0, "gEyePosW");
mhWorld		 = mFX->GetParameterByName(0, "gWorld");
mhTex		   = mFX->GetParameterByName(0, "gTex");
}
void TreeDemo::drawGround()
{
HR(mFX->SetValue(mhAmbientMtrl, &mGroundMtrl.ambient, sizeof(D3DXCOLOR)));
HR(mFX->SetValue(mhDiffuseMtrl, &mGroundMtrl.diffuse, sizeof(D3DXCOLOR)));
HR(mFX->SetValue(mhSpecularMtrl, &mGroundMtrl.spec, sizeof(D3DXCOLOR)));
HR(mFX->SetFloat(mhSpecularPower, mGroundMtrl.specPower));
HR(mFX->SetMatrix(mhWVP, &(mGroundWorld*mView*mProj)));
D3DXMATRIX worldInvTrans;
D3DXMatrixInverse(&worldInvTrans, 0, &mGroundWorld);
D3DXMatrixTranspose(&worldInvTrans, &worldInvTrans);
HR(mFX->SetMatrix(mhWorldInvTrans, &worldInvTrans));
HR(mFX->SetMatrix(mhWorld, &mGroundWorld));
HR(mFX->SetTexture(mhTex, mGroundTex));
HR(gd3dDevice->SetVertexDeclaration(VertexPNT::Decl));
HR(gd3dDevice->SetStreamSource(0, mGridVB, 0, sizeof(VertexPNT)));
HR(gd3dDevice->SetIndices(mGridIB));
// Begin passes.
UINT numPasses = 0;
HR(mFX->Begin(&numPasses, 0));
HR(mFX->BeginPass(0));
HR(gd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mNumGridVertices, 0, mNumGridTriangles));
HR(mFX->EndPass());

HR(mFX->End());
}
void TreeDemo::drawTrees()
{
  // Enable alpha test.
HR(gd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, true));
//HR(gd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL));
//HR(gd3dDevice->SetRenderState(D3DRS_ALPHAREF, 100));
// Turn off backface culling so you can see both sides of the gate.
//HR(gd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE));
//HR(mFX->SetValue(mhAmbientMtrl, &mTreeMtrl.ambient, sizeof(D3DXCOLOR)));
//HR(mFX->SetValue(mhDiffuseMtrl, &mTreeMtrl.diffuse, sizeof(D3DXCOLOR)));
//HR(mFX->SetValue(mhSpecularMtrl, &mTreeMtrl.spec, sizeof(D3DXCOLOR)));
//HR(mFX->SetFloat(mhSpecularPower, mTreeMtrl.specPower));
HR(mFX->SetMatrix(mhWVP, &(mTreeWorld*mView*mProj)));
//D3DXMATRIX worldInvTrans;
//D3DXMatrixInverse(&worldInvTrans, 0, &mGateWorld);
//D3DXMatrixTranspose(&worldInvTrans, &worldInvTrans);
//HR(mFX->SetMatrix(mhWorldInvTrans, &worldInvTrans));
//HR(mFX->SetMatrix(mhWorld, &mGateWorld));
HR(mFX->SetTexture(mhTex, mTreeTex));
HR(gd3dDevice->SetVertexDeclaration(VertexPNT::Decl));
HR(gd3dDevice->SetStreamSource(0, mTreeVB, 0, sizeof(VertexPNT)));
HR(gd3dDevice->SetIndices(mTreeIB));
// Begin passes.
UINT numPasses = 0;
HR(mFX->Begin(&numPasses, 0));
HR(mFX->BeginPass(1));
HR(gd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 16, 0, 8));
HR(mFX->EndPass());

HR(mFX->End());
// Disable alpha test.
HR(gd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false));
// Turn culling back on.
// HR(gd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW));
}

...and the shader:

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;
sampler TexS = sampler_state
{
Texture = <gTex>;
MinFilter = Anisotropic;
MagFilter = LINEAR;
MipFilter = LINEAR;
MaxAnisotropy = 8;
AddressU  = WRAP;
	AddressV  = WRAP;
};

struct OutputVS
{
	float4 posH	: POSITION0;
	float4 diffuse : COLOR0;
	float4 spec	: COLOR1;
	float2 tex0	: TEXCOORD0;
};
OutputVS DirLightTexVS(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);

// Pass on texture coordinates to be interpolated in rasterization.
outVS.tex0 = tex0;

// Done--return the output.
	return outVS;
}
OutputVS AABillBoardVS(float3 posL : POSITION0, float3 bbOffset : TEXCOORD0, float2 tex0: TEXCOORD1)
{
OutputVS outVS = (OutputVS)0;
float3 tempPosW = posL + bbOffset;
float3 look = gEyePosW - tempPosW;
look.y = 0.0f;
look = normalize(look);
float3 up = float3(0.0f, 1.0f, 0.0f);
float3 right = cross(up, look);
float3x3 R;
R[0] = right;
R[1] = up;
R[2] = look;
float3 posW = mul(posL, R) + bbOffset;
outVS.posH = mul(float4(posW, 1.0f), gWVP);
outVS.tex0 = tex0;
return outVS;
}
float4 DirLightTexPS(float4 c : COLOR0, float4 spec : COLOR1, float2 tex0 : TEXCOORD0) : COLOR
{
float4 texColor = tex2D(TexS, tex0);
float3 diffuse = c.rgb * texColor.rgb;
	return float4(diffuse + spec.rgb, texColor.a*c.a);
}
float4 AABillBoardPS(float2 tex0 : TEXCOORD0) : COLOR
{
float4 texColor = tex2D(TexS, tex0);
	return (texColor.rgb, texColor.a);
}
technique DirLightTexTech
{
	pass P0
	{
		// Specify the vertex and pixel shader associated with this pass.
		vertexShader = compile vs_2_0 DirLightTexVS();
		pixelShader  = compile ps_2_0 DirLightTexPS();
	}
pass P1
{
		vertexShader = compile vs_2_0 AABillBoardVS();
		pixelShader  = compile ps_2_0 AABillBoardPS();
}
}

What am I missing?

Multi pass texturing

25 June 2012 - 12:31 PM

I am trying to do multi texturing using a pass for each texture as opposed to just one pass with multiple samplers. I'm using a blend map where each color channel is supposed to act as an 8 bit alpha channel that dictates what portions of the corresponding texture remains visible after each pass:

Attached File  blendmap.jpg   2.06MB   43 downloads

Here is a screenshot:
As you can see, only the stone texture remains visible. The grass and ground textures are not. I don't know why the rest is black.
Attached File  terrain.PNG   456.52KB   36 downloads


Here is a screenshot of what it is supposed to look like:
Attached File  terrain0.PNG   917.52KB   35 downloads


Here is some code:
void MultiTexDemo::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(mhBlendMap, mBlendMap));
HR(gd3dDevice->SetVertexDeclaration(VertexPNT::Decl));
HR(gd3dDevice->SetStreamSource(0, mGridVB, 0, sizeof(VertexPNT)));
HR(gd3dDevice->SetIndices(mGridIB));
HR(gd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true));
HR(gd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA));
HR(gd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA));

// Begin passes.
UINT numPasses = 0;
HR(mFX->Begin(&numPasses, 0));
for(UINT i = 0; i < numPasses; ++i)
{
  HR(mFX->BeginPass(i));
  if(i == 0)HR(mFX->SetTexture(mhTex, mTex0));
  if(i == 1)HR(mFX->SetTexture(mhTex, mTex1));
  if(i == 2)HR(mFX->SetTexture(mhTex, mTex2));
  HR(gd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, mNumGridVertices, 0, mNumGridTriangles));
  HR(mFX->EndPass());
}
HR(mFX->End());

mGfxStats->display();
HR(gd3dDevice->EndScene());
// Present the backbuffer.
HR(gd3dDevice->Present(0, 0, 0, 0));
}

... and the shader:
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 gBlendMap;

sampler TexS = sampler_state
{
Texture = <gTex>;
MinFilter = Anisotropic;
MagFilter = LINEAR;
MipFilter = LINEAR;
MaxAnisotropy = 8;
AddressU  = WRAP;
	AddressV  = WRAP;
};
sampler BlendMapS = sampler_state
{
Texture = <gBlendMap>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
AddressU  = WRAP;
	AddressV  = WRAP;
};

struct OutputVS
{
	float4 posH		 : POSITION0;
	float4 diffuse	  : COLOR0;
	float4 spec		 : COLOR1;
	float2 tiledTexC	: TEXCOORD0;
	float2 nonTiledTexC : TEXCOORD1;
};
OutputVS TerrainMultiTexVS(float3 posL : POSITION0,
						   float3 normalL : NORMAL0,
						   float2 tex0: TEXCOORD0)
{
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);

// Pass on texture coordinates to be interpolated in rasterization.
outVS.tiledTexC	= tex0 * 16.0f; // Scale tex-coord to tile 16 times.
outVS.nonTiledTexC = tex0;

// Done--return the output.
	return outVS;
}
float4 TerrainMultiTexPS0(float4 diffuse : COLOR0,
	   float4 spec	: COLOR1,
						 float2 tiledTexC : TEXCOORD0,
						 float2 nonTiledTexC : TEXCOORD1) : COLOR
{
// Layer maps are tiled
	float3 c = tex2D(TexS, tiledTexC).rgb;
  
	// Blendmap is not tiled.
	float3 B = tex2D(BlendMapS, nonTiledTexC).rgb;
// Find the inverse of all the blend weights so that we can
// scale the total color to the range [0, 1].
	float totalInverse = 1.0f / (B.r + B.g + B.b);
  
	// Scale the colors by each layer by its corresponding weight
	// stored in the blendmap.
	c *= B.r; //* totalInverse;
  
	// Sum the colors and modulate with the lighting color.
	float3 final = c * diffuse.rgb;
  
	return float4(final + spec, diffuse.a);
}
float4 TerrainMultiTexPS1(float4 diffuse : COLOR0,
	   float4 spec	: COLOR1,
						 float2 tiledTexC : TEXCOORD0,
						 float2 nonTiledTexC : TEXCOORD1) : COLOR
{
// Layer maps are tiled
	float3 c = tex2D(TexS, tiledTexC).rgb;
  
	// Blendmap is not tiled.
	float3 B = tex2D(BlendMapS, nonTiledTexC).rgb;
// Find the inverse of all the blend weights so that we can
// scale the total color to the range [0, 1].
	float totalInverse = 1.0f / (B.r + B.g + B.b);
  
	// Scale the colors by each layer by its corresponding weight
	// stored in the blendmap.
	c *= B.g; //* totalInverse;
	
	// Sum the colors and modulate with the lighting color.
	float3 final = c * diffuse.rgb;
  
	return float4(final + spec, diffuse.a);
}
float4 TerrainMultiTexPS2(float4 diffuse : COLOR0,
	   float4 spec	: COLOR1,
						 float2 tiledTexC : TEXCOORD0,
						 float2 nonTiledTexC : TEXCOORD1) : COLOR
{
// Layer maps are tiled
	float3 c = tex2D(TexS, tiledTexC).rgb;
  
	// Blendmap is not tiled.
	float3 B = tex2D(BlendMapS, nonTiledTexC).rgb;
// Find the inverse of all the blend weights so that we can
// scale the total color to the range [0, 1].
	float totalInverse = 1.0f / (B.r + B.g + B.b);
  
	// Scale the colors by each layer by its corresponding weight
	// stored in the blendmap.
	c *= B.b; //* totalInverse;
  
	// Sum the colors and modulate with the lighting color.
	float3 final = c * diffuse.rgb;
  
	return float4(final + spec, diffuse.a);
}
technique TerrainMultiTexTech
{
	pass P0
	{
		// Specify the vertex and pixel shader associated with this pass.
		vertexShader = compile vs_2_0 TerrainMultiTexVS();
		pixelShader  = compile ps_2_0 TerrainMultiTexPS0();
	}
	pass P1
	{
		// Specify the vertex and pixel shader associated with this pass.
		vertexShader = compile vs_2_0 TerrainMultiTexVS();
		pixelShader  = compile ps_2_0 TerrainMultiTexPS1();
	}
pass P2
	{
		// Specify the vertex and pixel shader associated with this pass.
		vertexShader = compile vs_2_0 TerrainMultiTexVS();
		pixelShader  = compile ps_2_0 TerrainMultiTexPS2();
	}
}

What am I doing wrong?

Rotating texture coordinates to animate multi-textured flare

10 June 2012 - 01:32 PM

I have a "flare" texture(.dds) and an alpha texture (.bmp). I'm trying to use these with multi-texturing to create a blended flare image. I then put the final image onto each face of a cube. So far, I have accomplished this. However, the next step is what I have trouble understanding. I want to rotate both textures at different rates to create a flare animation. In turn, I must map the animation to each face of the cube like before. When I run my program, the textures are rotating in a circle instead of rotating about their own axes

Here is a screen shot:
Attached File  flarecube.PNG   162.4KB   39 downloads
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?

Back face of a pyramid is missing

07 June 2012 - 03:37 PM

I'm trying to texture map a pyramid. However, what should be the back side of the pyramid is somehow missing from view.

Here is a view from the front. This is the default orientation when my demo first executes.
Attached File  mypyramid1.PNG   81.53KB   21 downloads
As we rotate about the y axis to get a view of the back face of the pyramid, we find that the back face is missing! Instead, we see that the diagonal cross section is texture mapped. Obviously, the viewer should never be able to see inside the pyramid much less have it texture mapped.
Attached File  mypyramid2.PNG   44.88KB   24 downloads
Here is a map of the vertices for clarity.
Attached File  pyramid0.PNG   16.22KB   22 downloads
Here is some code.
void PyramidDemo::buildPyrGeometry()
{
// Create the vertex buffer.
HR(gd3dDevice->CreateVertexBuffer(24 * sizeof(VertexPNT), D3DUSAGE_WRITEONLY,
  0, D3DPOOL_MANAGED, &mPyrVB, 0));
// Write Pyr vertices to the vertex buffer.
VertexPNT* v = 0;
HR(mPyrVB->Lock(0, 0, (void**)&v, 0));
D3DXVECTOR3 pyrV0( 0.0f,  0.0f,  0.0f);
D3DXVECTOR3 pyrV1(-1.0f, -1.0f, -1.0f);
D3DXVECTOR3 pyrV2( 1.0f, -1.0f, -1.0f);
D3DXVECTOR3 pyrV3(-1.0f, -1.0f,  1.0f);
D3DXVECTOR3 pyrV4( 1.0f, -1.0f,  1.0f);
D3DXVECTOR3 fn_f;
D3DXVECTOR3 fn_b;
D3DXVECTOR3 fn_l;
D3DXVECTOR3 fn_r;
faceNormal(&pyrV0, &pyrV2, &pyrV1, &fn_f);
faceNormal(&pyrV0, &pyrV3, &pyrV4, &fn_b);
faceNormal(&pyrV0, &pyrV1, &pyrV3, &fn_l);
faceNormal(&pyrV0, &pyrV4, &pyrV2, &fn_r);

v[0] = VertexPNT(pyrV1.x, pyrV1.y, pyrV1.z, fn_f.x, fn_f.y, fn_f.z, 0.0f, 1.0f);
v[1] = VertexPNT(pyrV0.x, pyrV0.y, pyrV0.z, fn_f.x, fn_f.y, fn_f.z, 0.0f, 0.0f);
v[2] = VertexPNT(pyrV2.x, pyrV2.y, pyrV2.z, fn_f.x, fn_f.y, fn_f.z, 1.0f, 0.0f);

v[3] = VertexPNT(pyrV4.x, pyrV4.y, pyrV4.z, fn_b.x, fn_b.y, fn_b.z, 0.0f, 1.0f);
v[4] = VertexPNT(pyrV0.x, pyrV0.y, pyrV0.z, fn_b.x, fn_b.y, fn_b.z, 0.0f, 0.0f);
v[5] = VertexPNT(pyrV3.x, pyrV3.y, pyrV3.z, fn_b.x, fn_b.y, fn_b.z, 1.0f, 0.0f);

v[6] = VertexPNT(pyrV1.x, pyrV1.y, pyrV1.z, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f);
v[7] = VertexPNT(pyrV2.x, pyrV2.y, pyrV2.z, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
v[8] = VertexPNT(pyrV4.x, pyrV4.y, pyrV4.z, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
v[9] = VertexPNT(pyrV3.x, pyrV3.y, pyrV3.z, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);

v[10]= VertexPNT(pyrV4.x, pyrV4.y, pyrV4.z, fn_l.x, fn_l.y, fn_l.z, 0.0f, 1.0f);
v[11]= VertexPNT(pyrV0.x, pyrV0.y, pyrV0.z, fn_l.x, fn_l.y, fn_l.z, 0.0f, 0.0f);
v[12]= VertexPNT(pyrV1.x, pyrV1.y, pyrV1.z, fn_l.x, fn_l.y, fn_l.z, 1.0f, 0.0f);
v[13]= VertexPNT(pyrV2.x, pyrV2.y, pyrV2.z, fn_r.x, fn_r.y, fn_r.z, 0.0f, 1.0f);
v[14]= VertexPNT(pyrV0.x, pyrV0.y, pyrV0.z, fn_r.x, fn_r.y, fn_r.z, 0.0f, 0.0f);
v[15]= VertexPNT(pyrV4.x, pyrV4.y, pyrV4.z, fn_r.x, fn_r.y, fn_r.z, 1.0f, 0.0f);

HR(mPyrVB->Unlock());

// Create the vertex buffer.
HR(gd3dDevice->CreateIndexBuffer(36 * sizeof(WORD), D3DUSAGE_WRITEONLY,
  D3DFMT_INDEX16, D3DPOOL_MANAGED, &mPyrIB, 0));
// Write Pyr indices to the index buffer.
WORD* i = 0;
HR(mPyrIB->Lock(0, 0, (void**)&i, 0));

i[0]  = 0; i[1]  = 1; i[2]  = 2;
i[3]  = 3; i[4]  = 4; i[5]  = 5;
i[6]  = 6;   i[7] = 7; i[8]  = 8;
i[9]  = 8; i[10] = 9; i[11] = 6;
i[12] = 10; i[13] = 11; i[14] = 12;
i[15] = 13; i[16] = 14; i[17] = 15;

HR(mPyrIB->Unlock());
}
void PyramidDemo::faceNormal(D3DXVECTOR3* v0, D3DXVECTOR3* v1, D3DXVECTOR3* v2, D3DXVECTOR3* n)
{
D3DXVECTOR3 u = *v1 - *v0;
D3DXVECTOR3 v = *v2 - *v0;
D3DXVec3Cross(n, &u, &v);
D3DXVec3Normalize(n, n);
}
I tried to list the vertices of the back face in a counterclockwise winding order. I tried disabling culling, and it still is missing. What could be wrong?

Using partial derivatives to light circular waves

02 June 2012 - 07:50 PM

I'm doing an exercise in a book that asks to add ambient, diffuse and specular lighting to an existing demo that animates circular waves over a basic flat grid. My attempt as it stands doesn't seem to work as expected though. Instead of looking circular in tune with the waves themselves, my lighting has a strange moire like pattern to it. I've forgotten most of my calculus, but fortunately the book's exercise spoon feeds me the formula for computing the partial derivatives neccessary for calcuating the vertex normals. The way I understand it, once I compute the partial derivatives, I simply plug them into the tangent vectors u and v and take the cross product to get my vertex normal.

Here is my shader...
// CHAPTER 10 10.12 EXERCISE 6
// LIGHTING SHADER FOR WAVES

uniform extern float4x4 gWorld;
uniform extern float4x4 gWorldInverseTranspose;
uniform extern float4x4 gWVP;
uniform extern float gTime;
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;
struct OutputVS
{
	float4 posH  : POSITION0;
float3 normalW : TEXCOORD0;
	float3 posW  : TEXCOORD1;
};
// Amplitudes
static float a[3] = {0.8f, 0.2f, 0.1};

// Angular wave numbers.
static float k[3] = {1.0, 8.0f, 10.0f};

// Angular frequency.
static float w[3] = {1.0f, 8.0f, 0.6f};

// Phase shifts.
static float p[3] = {0.0f, 1.0f, 2.0f};
float SumOfRadialSineWaves(float x, float z)
{
// Distance of vertex from source of waves (which we set
// as the origin of the local space).
float d = sqrt(x*x + z*z);

// Sum the waves.
float sum = 0.0f;
for(int i = 0; i < 2; ++i)
  sum += a[i]*sin(k[i]*d - gTime*w[i] + p[i]);

return sum;
}
void Partials(float x, float z, out float dhOverdx, out float dhOverdz)
{
float d = sqrt(x*x + z*z);
dhOverdx = 0.0f;
dhOverdz = 0.0f;
for(int i = 0; i < 3; ++i)
{
  dhOverdx += (a[i]*k[i]*x*cos(k[i]*d - gTime*w[i] + p[i]))/d;
  dhOverdz += (a[i]*k[i]*z*cos(k[i]*d - gTime*w[i] + p[i]))/d;
}
}
OutputVS ColorVS(float3 posL : POSITION0, float3 normalL : NORMAL0)
{
	// Zero out our output.
OutputVS outVS = (OutputVS)0;

// Get the height of the vertex--the height is given by
// summing sine waves.
posL.y = SumOfRadialSineWaves(posL.x, posL.z);

// calc normal
float derivx;
float derivz;
Partials(posL.x, posL.z, derivx, derivz);

float3 v = float3 (1, derivx, 0);
float3 u = float3 (0, derivz, 1);
normalL = cross(u, v);
// Transform normal to world space.
outVS.normalW = mul(float4(normalL, 0.0f), gWorldInverseTranspose).xyz;
outVS.normalW = normalize(outVS.normalW);
// Transform vertex position to world space.
outVS.posW  = mul(float4(posL, 1.0f), gWorld).xyz;
// Transform to homogeneous clip space.
outVS.posH = mul(float4(posL, 1.0f), gWVP);

// Done--return the output.
	return outVS;
}
float4 ColorPS(float3 normalW : TEXCOORD0, float3 posW : TEXCOORD1) : COLOR
{
normalW = normalize(normalW);
// 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;
return float4(ambient + diffuse + spec, gDiffuseMtrl.a);
}
technique LightedWaveTech
{
	pass P0
	{
		// Specify the vertex and pixel shader associated with this pass.
		vertexShader = compile vs_2_0 ColorVS();
		pixelShader  = compile ps_2_0 ColorPS();
	}
}

What am I doing wrong?

PARTNERS