PDA

View Full Version : Rendering DirectX9 Model with HLSL ambient light


Phlex
12-15-2008, 07:29 AM
Right, I've come into a spot of bother that I can't seem to solve. I have a function as shown below:

HRESULT RenderScene()
{
UINT uiPassCount, uiPass;

HRESULT hr;

// Set up Teapot matricies
D3DXMatrixIdentity(&m_matTeapot);
D3DXMatrixRotationYawPitchRoll(&m_matTeapot,
D3DXToRadian(g_fSpinX),
D3DXToRadian(g_fSpinY),
0.0f);

GetRealTimeUserInput();
UpdateViewMatrix();

// Render the teapot mesh
g_pd3dDevice->SetTransform(D3DTS_WORLD, &m_matTeapot);

for(unsigned long n = 0; n < g_dwTeapotNumMtrls; ++n)
{
g_pd3dDevice->SetMaterial(&g_pTeapotMtrls[n]);
g_pd3dDevice->SetTexture(0, g_pTeapotTextures[n]);
g_pTeapotMesh->DrawSubset(n);
}

// Draw the floor by rendering a 25 x 25 grouping of textured quads.
g_pd3dDevice->SetTexture(0, g_pFloorTex);
g_pd3dDevice->SetMaterial(&g_pFloorMtrl);
g_pd3dDevice->SetStreamSource(0, g_pFloorVB, 0, sizeof(FloorVertex));
g_pd3dDevice->SetFVF(FloorVertex::FVF_Flags);

D3DXMATRIX matFloor;
float x = 0.0f;
float z = 0.0f;

for(int i = 0; i < 25; ++i)
{
for(int j = 0; j < 25; ++j)
{
D3DXMatrixTranslation( &matFloor, x - 25.0f, -3.0f, z - 25.0f );
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matFloor );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2);

x += 2.0f;
}
x = 0.0f;
z += 2.0f;
}

// Sample textures with anisotropic filtering 8x
for(DWORD i = 0; i < 8; i++)
{
g_pd3dDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
g_pd3dDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
g_pd3dDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_ANISOTROPIC);
}

return S_OK;
}
This function is called from another function (Render) as there are several render stages and post process effects to deal with. Any way, I want to replace the D3DLIGH9 struct that I was using with HLSL programmed lighting, so I've started with a simple ambient light rendering algorithm which is contained in the following hlsl code:

float4x4 matWorldViewProj;

struct VS_OUTPUT
{
float4 Pos: POSITION;
};

VS_OUTPUT TransformScene( float4 Pos: POSITION )
{
VS_OUTPUT Out = (VS_OUTPUT) 0;
Out.Pos = mul(Pos, matWorldViewProj); // transform Position
return Out;
}

float4 AmbientLight() : COLOR
{
return float4(0.5, 0.075, 0.075, 1.0);
}

/************************************************** ********************************
Techniques
************************************************** ********************************/



/************************************************** ********************************
RenderScene
************************************************** ********************************/
technique RenderScene
{
pass P0
{
VertexShader = compile vs_2_0 TransformScene();
PixelShader = compile ps_2_0 AmbientLight();
}
}

I set up my effect like this

g_pEffect->SetTechnique("RenderScene");
g_pEffect->SetMatrix("matWorldViewProj", &view);

hr = g_pEffect->Begin(&uiPassCount, 0);
if(FAILED(hr))
return hr;

for(uiPass = 0; uiPass < uiPassCount; uiPass++)
{
g_pEffect->BeginPass(uiPass);
// what goes here though?!

g_pEffect->EndPass();
}

g_pEffect->End();

I don't know where to put stuff so that it will render the goemetry with the ambient light specified in the shader, it all compiles fine, but after searching and trying for around 3 hours, I've given up trying on my own. All and any help would be much appreciated.

starstutter
12-15-2008, 07:49 AM
g_pEffect->SetTechnique("RenderScene");
g_pEffect->SetMatrix("matWorldViewProj", &view);

hr = g_pEffect->Begin(&uiPassCount, 0);
if(FAILED(hr))
return hr;

for(uiPass = 0; uiPass < uiPassCount; uiPass++)
{
g_pEffect->BeginPass(uiPass);
// what goes here though?!

g_pEffect->EndPass();
}

g_pEffect->End();


You render the object between the BeginPass() and EndPass() calls. No offense, but what on earth woud cause you to think otherwise? The name is pretty self-explainatory. Other than that your code looks fine.

Just to save yourself some near-future hassle though (because I struggled with this as well) if you make any changes to constants between those 2 calls, you will need to call the function CommitChanges() before they can take take meaningful effect (that is, before you call another render pass within the same 2 calls). It took me quite a while to figure that out the first time. Unfortunatley, HLSL "how-to's" on the internet are natoriously vauge (IMO at least).

EDIT: hmmm, maybe I missed it, but I don't see you incorperating the world matrix and projection matrix in your code. Make sure your multiplying the view matrix by them in the order of
world * view * projection
(order matters in matrix multiplication)

Phlex
12-15-2008, 06:15 PM
You render the object between the BeginPass() and EndPass() calls. No offense, but what on earth woud cause you to think otherwise? The name is pretty self-explainatory. Other than that your code looks fine.

Just to save yourself some near-future hassle though (because I struggled with this as well) if you make any changes to constants between those 2 calls, you will need to call the function CommitChanges() before they can take take meaningful effect (that is, before you call another render pass within the same 2 calls). It took me quite a while to figure that out the first time. Unfortunatley, HLSL "how-to's" on the internet are natoriously vauge (IMO at least).

EDIT: hmmm, maybe I missed it, but I don't see you incorperating the world matrix and projection matrix in your code. Make sure your multiplying the view matrix by them in the order of
world * view * projection
(order matters in matrix multiplication)
What would make me think otherwise? It didn't work.. It just cleared to the colour passed to the direct3d device when clearing. The matrix is updated in the "UpdateViewMatrix" function, view is the global variable for the view matrix, and none of the variables in the code need to change between calls at this stage so I don't need to commit them. This is why I'm so confused 0.o

Phlex
12-15-2008, 06:24 PM
Not sure if it helps, but there's the render function from which the RenderScene function is called


HRESULT Render()
{
PDIRECT3DSURFACE9 pSurfLDR; // Low dynamic range surface for final output
PDIRECT3DSURFACE9 pSurfDS; // Low dynamic range depth stencil surface
PDIRECT3DSURFACE9 pSurfHDR; // High dynamic range surface to store

// Store the old render target
g_pd3dDevice->GetRenderTarget(0, &pSurfLDR);
g_pd3dDevice->GetDepthStencilSurface(&pSurfDS);

// Set up HDR render targe
g_pTextureScene->GetSurfaceLevel(0, &pSurfHDR);
g_pd3dDevice->SetRenderTarget(0, g_pFloatMSRT);
//g_pd3dDevice->SetDepthStencilSurface(g_pFloatMSDS);

// start rendering the scene
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , D3DCOLOR_COLORVALUE(0.35f, 0.53f, 0.7, 1.0f), 1.0f, 0);

if(SUCCEEDED(g_pd3dDevice->BeginScene()))
{
{
RenderScene();
}

if(FAILED(g_pd3dDevice->EndScene()))
return E_FAIL;

}

SAFE_RELEASE(pSurfLDR);
SAFE_RELEASE(pSurfDS);
SAFE_RELEASE(pSurfHDR);

g_pd3dDevice->Present(NULL, NULL, NULL, NULL);

return S_OK;
}

Phlex
01-12-2009, 08:49 AM
Sorry to bump this, but incase anyone else has the same problem, you need to convert the FVF's into vertex elements as the shader uses a programmable pipeline where as FVF's are part of the fixed function pipeline, you can get all the info you need in this tutorial

http://toymaker.info/Games/html/vertex_shaders.html

Goz
01-14-2009, 01:56 PM
Sorry to bump this, but incase anyone else has the same problem, you need to convert the FVF's into vertex elements as the shader uses a programmable pipeline where as FVF's are part of the fixed function pipeline, you can get all the info you need in this tutorial

http://toymaker.info/Games/html/vertex_shaders.html

You can use FVFs with the programmable pipeline under DX9. I've done so for years.

Using the vertex descis definitely preferrable though ...

Goz
01-14-2009, 01:59 PM
That said ... I'm not sure if i've tried doing it under HLSL. DEfinitely done it under shader assembler LOOOOADS in the past ...

Phlex
01-16-2009, 06:06 PM
The HLSL is fairly simple (heck, it can't be hard than assembly), but it's getting the information to the shader that seems to confuse me more than anything :P