Weirdest bug ever? Something to do with D3DXEffect::CommitChanges()?

Started by
1 comment, last by Buckeye 13 years ago
In my scene i'm rendering Meshes with textures using my first Shader. I begin a pass, for each mesh set the texture and call CommitChanges(), then render the mesh.
Next i render other Meshes without textures but with lighting using a different Shader. I begin a pass, and render them.

Now this causes a bug where the meshes rendered with the second shader wiggle whenever i rotate/move the camera. A lot. After spending ages debugging, the problem somehow disappeared. I had a huge WTF moment. A day later, the problem re-appeared. Only some meshes wiggled while others didn't. Another WTF moment. The next day, this bug started to affect all the meshes.

I finally found out that when i omit the CommitChanges() calls when rendering with the first shader, the problem disappears. But since i need those, i added one CommitChanges() call to the second Shader before rendering any meshes.. and the problem was solved.

Now would someone tell me WTF is going on?

Here's any relevent code that i can think of:

The render function:
void CFramework::Render()
{
m_d3ddev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(50, 50, 80), 1.0f, 0);

m_d3ddev->BeginScene();

D3DXMATRIX World, View, Projection;

D3DXMatrixPerspectiveFovLH(&Projection,
D3DXToRadian(45),
(float)m_ScreenSize.cx / m_ScreenSize.cy,
1.0f,
100.0f);

D3DXMatrixIdentity(&World);
Cam.GetViewMatrix(&View);
D3DXMATRIX WVP = World * View * Projection;

// draw w/o texture
m_d3ddev->SetVertexDeclaration(_VertexDecl::PositionNormal::Decl);
Effect->Begin(NULL, 0);
Effect->BeginPass(0);

Effect->SetMatrix("WorldViewProj", &WVP);
Effect->SetFloatArray("MatAmbient", (float*)(&Mesh[3].m_Mats[0].Ambient), 3);
D3DXMATRIX WIT;
D3DXMatrixInverse(&WIT, 0, &World);
D3DXMatrixTranspose(&WIT, &WIT);

Effect->SetInt("nLights", 1);
Effect->SetMatrix("World", &World);
Effect->SetFloatArray("CamPosition", (float*)(&Cam.Position), 3);
Effect->SetFloatArray("MatDiffuse", (float*)(&Mesh[3].m_Mats[0].Diffuse), 4);
Effect->SetFloatArray("MatSpecular", (float*)(&Mesh[3].m_Mats[0].Specular), 3);
Effect->SetFloat("MatPower", 40.0f);
Effect->SetFloatArray("SpecularLight[0]", (float*)(&Color3(1.0f, 1.0f, 1.0f)), 3);
Effect->SetFloatArray("DiffuseLight[0]", (float*)(&Color4(1.0f, 0.5f, 0.5f, 1.0f)), 4);
Effect->SetFloatArray("AmbientLight", (float*)(&Color3(0.5f, 0.2f, 0.2f)), 3);

D3DXVECTOR3 LightPos(3.0f, 4.0f, -20.0f);
D3DXVECTOR3 LightPos2(-10.0f, 4.0f, 10.0f);
D3DXVECTOR3 Origin(0.0f, 0.0f, 0.0f);
Effect->SetFloatArray("LightDirection[0]", (float*)&(LightPos - Origin), 3);

Effect->CommitChanges(); // <-------- The Extra CommitChanges()

Mesh[3].Render(Effect);;
Mesh[4].Render(Effect);

Effect->EndPass();
Effect->End();

// draw w/ textures
EffectTex->Begin(NULL, 0);
EffectTex->BeginPass(0);

m_d3ddev->SetVertexDeclaration(_VertexDecl::PositionNormalTextured::Decl);
EffectTex->SetMatrix("WorldViewProj", &WVP);

for (int i = 0; i < 3; i++)
Mesh.Render(EffectTex);

m_d3ddev->SetVertexDeclaration(_VertexDecl::PreTransformedColourTextured::Decl);
RenderText();

EffectTex->EndPass();
EffectTex->End();

m_d3ddev->EndScene();

// Present the scene to the buffer
HRESULT hResult = m_d3ddev->Present(NULL, NULL, NULL, NULL);

// If the device is lost
if (FAILED(hResult))
{
// Handle the lost device.
hResult = HandleLostDevice(hResult);
if (FAILED(hResult))
{
LOG_ERROR(hResult);
m_Quit = true;
}
}
}


The Mesh render function
void CMesh::Render(LPD3DXEFFECT pEffect)
{
m_vb.ReadyBuffer();

int StartIndex = 0;
for (UINT i = 0; i < m_nSubMeshes; i++)
{
if (m_Mats.Texture)
{
pEffect->SetTexture("Tex", m_Mats.Texture);
pEffect->CommitChanges();
}

m_vb.Render(D3DPT_TRIANGLELIST, m_nVertices, StartIndex, m_Mats.nFaces);
StartIndex += m_Mats.nFaces * 3;
}
}



Shader 1:
float4x4 WorldViewProj;

texture Tex;

sampler Sampler = sampler_state
{
Texture = (Tex);
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
};

struct VS_OUTPUT
{
float4 Pos : POSITION;
float4 Col : COLOR0;
float2 UV : TEXCOORD0;
};

struct PS_OUTPUT
{
float4 Col : COLOR0;
};

VS_OUTPUT VShader(float4 Pos : POSITION, float3 Nor : NORMAL, float2 UV : TEXCOORD0)
{
VS_OUTPUT OUT;

OUT.Pos = mul(Pos, WorldViewProj);
OUT.Col = float4(0.7, 0.7, 0.7, 1);
OUT.UV = UV;

return OUT;
}

PS_OUTPUT PShader(VS_OUTPUT IN)
{
PS_OUTPUT OUT;

OUT.Col = tex2D(Sampler, IN.UV) * IN.Col;
return OUT;
}

technique FirstTechnique
{
pass FirstPass
{
Lighting = false;
CullMode = None;

VertexShader = compile vs_2_0 VShader();
PixelShader = compile ps_2_0 PShader();
}
}



Shader 2:
float4x4 WorldViewProj;
float4x4 World;

float4 MatDiffuse;
float3 MatAmbient;
float3 MatSpecular;
float MatPower;

#define MAX_LIGHTS 3

float3 AmbientLight;
float4 DiffuseLight[MAX_LIGHTS];
float3 SpecularLight[MAX_LIGHTS];
float3 LightDirection[MAX_LIGHTS];
float3 CamPosition;
int nLights;

struct VS_IN
{
float4 Position : POSITION;
float3 Normal : NORMAL;
};

struct VS_OUT
{
float4 Position : POSITION;
float3 Light[MAX_LIGHTS] : TEXCOORD0;
float3 Normal : TEXCOORD3;
float3 CamView : TEXCOORD4;
};

struct PS_OUT
{
float4 Colour : COLOR;
};

VS_OUT VShader(VS_IN input)
{
VS_OUT output = (VS_OUT)0;

output.Position = mul(input.Position, WorldViewProj);
output.Normal = mul(float4(input.Normal, 0.0f), World).xyz;
output.CamView = CamPosition - mul(input.Position, World);

return output;
}

PS_OUT PShader(VS_OUT input)
{
PS_OUT output = (PS_OUT)0;

float3 Normal = normalize(input.Normal);

float3 TotalDiffuse = float3(0,0,0);
float3 TotalSpecular = float3(0,0,0);

for (int i = 0; i < nLights; i++)
{
input.Light = normalize(LightDirection);
float3 Half = normalize(input.Light + normalize(input.CamView));
TotalSpecular += (MatSpecular * SpecularLight) * pow(saturate(dot(Normal, Half)), MatPower);
TotalDiffuse += (MatDiffuse * DiffuseLight).rgb * saturate(dot(input.Light, Normal));
}

output.Colour.rgb = (MatAmbient * AmbientLight) + TotalDiffuse + TotalSpecular;
output.Colour.a = MatDiffuse.a;

return output;
}

technique FirstTechnique
{
pass FirstPass
{
Lighting = false;
CullMode = None;

VertexShader = compile vs_2_0 VShader();
PixelShader = compile ps_2_0 PShader();
}
}

"Spending your life waiting for the messiah to come save the world is like waiting around for the straight piece to come in Tetris...even if it comes, by that time you've accumulated a mountain of shit so high that you're fucked no matter what you do. "
Advertisement
bump
"Spending your life waiting for the messiah to come save the world is like waiting around for the straight piece to come in Tetris...even if it comes, by that time you've accumulated a mountain of shit so high that you're fucked no matter what you do. "
I'm not sure if it has anything to do with the "wiggle," but you should set your effect parameters ( matrices, lights, etc. ) before you begin the pass, even before effect->Begin(). Then you don't need to call CommitChanges at all for those parameters. You only need to call CommitChanges when you change an effect parameter between BeginPass and EndPass, such as when you change the texture.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement