Jump to content


Rendering DirectX9 Model with HLSL ambient light


7 replies to this topic

#1 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 15 December 2008 - 03:29 PM

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.

#2 starstutter

    Senior Member

  • Members
  • PipPipPipPip
  • 1039 posts

Posted 15 December 2008 - 03:49 PM

Phlex said:


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)
(\__/)
(='.'=)
This is Bunny. Copy and paste bunny into
(")_(") your signature to help him gain world domination.
bunny also wants to fight spam: Click Here Bots!

#3 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 16 December 2008 - 02:15 AM

starstutter said:

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

#4 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 16 December 2008 - 02:24 AM

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;
}


#5 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 12 January 2009 - 04:49 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...ex_shaders.html

#6 Goz

    Senior Member

  • Members
  • PipPipPipPip
  • 574 posts

Posted 14 January 2009 - 09:56 PM

Phlex said:

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...ex_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 ...

#7 Goz

    Senior Member

  • Members
  • PipPipPipPip
  • 574 posts

Posted 14 January 2009 - 09: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 ...

#8 Phlex

    Member

  • Members
  • PipPip
  • 53 posts

Posted 17 January 2009 - 02:06 AM

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





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users