🔒 Locked
HLSL Effect Framework-headaces
Advertisement
Original Post
Hi! Got s stupid problem; can't wrap my head around the HLSL Effects and framework. Please correct me if I'm wrong but in my head the Effect framework, together with techniques and passes, makes creating shaders from the App obsolete (since they are created from within a pass), thus abstracting the effects more. Problem is, I get a drawing-error when trying to use a effect-file. It's really the DrawSubset-method that failes and I'm sure I made some elementary misstake somewhere down the line. Could some please enlighten me? Sample-code could be appretiated. I'll post the test-app code and the effect-code in the two following posts. // Thanks in advance
App Code (don't mind the "Main.h", it only contains forward declarations):
/*------------------------------------------------------------------------*/
[/source]
And the effect file
-------------------------------------
[Edited by - Bangladesh on January 4, 2007 7:08:58 AM]
/*------------------------------------------------------------------------*/
[Source]// Windows#include <windows.h>#include <stdio.h>// DirectX#include <d3d9.h>#include <d3dx9.h>// App#include "Main.h"HWND g_hWnd = NULL;bool g_bDone = false;bool g_bIsActive = false;bool g_bUseEffect = true;float fWidth = 500, fHeight = 480;D3DXMATRIX mWorldViewProj;IDirect3D9 *g_pD3D = NULL;IDirect3DDevice9 *g_pDevice = NULL;ID3DXMesh *g_pMesh = NULL;ID3DXEffect *g_pEffect = NULL;IDirect3DVertexDeclaration9 *g_pVertexDecl = NULL;int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd){ MSG msg; WNDCLASS wc; char chAppName[] = "Effect Test"; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); wc.hInstance = hInstance; wc.lpfnWndProc = WndProc; wc.lpszClassName = chAppName; wc.lpszMenuName = NULL; wc.style = CS_VREDRAW | CS_HREDRAW; RegisterClass(&wc); g_hWnd = CreateWindow(chAppName, chAppName, WS_OVERLAPPEDWINDOW | WS_VISIBLE, GetSystemMetrics(SM_CXSCREEN) / 2 - (fWidth / 2), GetSystemMetrics(SM_CYSCREEN) / 2 - (fHeight / 2), (int)fWidth, (int)fHeight, NULL, NULL, hInstance, NULL); ShowWindow(g_hWnd, nShowCmd); UpdateWindow(g_hWnd); g_bIsActive = true; // Start Effect if(FAILED(StartEffect("Effect.fx"))) EndEffect(); while(!g_bDone) { if(PeekMessage(&msg, g_hWnd, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } if(g_bIsActive) { DrawEffect(); } } EndEffect(); UnregisterClass(chAppName, hInstance); return 0;};/*----------------------------------*/LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg) { // Application focus case WM_ACTIVATE: {g_bIsActive = (bool)wParam;} break; // Key events case WM_KEYDOWN: { switch(wParam) { case VK_ESCAPE: { g_bDone = true; PostMessage(hWnd, WM_CLOSE, 0, 0); return 0; } break; } } break; // Destroy window case WM_DESTROY: { g_bDone = true; PostQuitMessage(0); return 1; } break; default: break; } return DefWindowProc(hWnd, msg, wParam, lParam);};/*----------------------------------*/HRESULT StartEffect(char *chEffectFile){ // Create g_pD3D if(!(g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))){ MessageBox(NULL, "Error Create g_pD3D", "Error", 0); return E_FAIL;} // Fill out present parameters D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS)); d3dpp.BackBufferWidth = (UINT)fWidth; d3dpp.BackBufferHeight = (UINT)fHeight; d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; d3dpp.BackBufferCount = 0; d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp.MultiSampleQuality = D3DMULTISAMPLE_NONE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = g_hWnd; d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; d3dpp.EnableAutoDepthStencil = true; d3dpp.Windowed = true; d3dpp.Flags = NULL; d3dpp.FullScreen_RefreshRateInHz = 0; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; // Create Device if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &g_pDevice))){ MessageBox(NULL, "Error Create g_pDevice", "Error", 0); return E_FAIL;} // Create Mesh if(FAILED(D3DXCreateTeapot(g_pDevice, &g_pMesh, NULL))){ MessageBox(NULL, "Error Create Teapot", "Error", 0); return E_FAIL;} DWORD *pAdjArray = new DWORD[3 * g_pMesh->GetNumFaces()]; if(FAILED(g_pMesh->GenerateAdjacency(0.0001f, pAdjArray))) MessageBox(NULL, "Error Generate Adjacency", "Error", 0); if(FAILED(g_pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, pAdjArray, NULL, NULL, NULL))) MessageBox(NULL, "Error OptimizeInPlace", "Error", 0); // Material D3DMATERIAL9 mtrl; ZeroMemory( &mtrl, sizeof(mtrl) ); mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f; mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f; mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f; mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f; if(FAILED(g_pDevice->SetMaterial( &mtrl ))){ MessageBox(NULL, "Error Set Lights", "Error", 0); return E_FAIL;} // Light D3DLIGHT9 light; ZeroMemory( &light, sizeof(light) ); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse.r = 1.0f; light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; light.Range = 1000.0f; D3DXVECTOR3 vecDir(1.0f, 0.0f, 0.0f); light.Direction = vecDir; g_pDevice->SetLight( 0, &light ); g_pDevice->LightEnable( 0, TRUE); g_pDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); g_pDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 ); g_pDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD ); // Set viewmatrix D3DXMATRIX mView; D3DXVECTOR3 vEyePt ( 0.0f, 3.0f,-5.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec ( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtLH( &mView, &vEyePt, &vLookatPt, &vUpVec ); g_pDevice->SetTransform( D3DTS_VIEW, &mView ); // Set ProjectionMatrix D3DXMATRIX mProjection; D3DXMatrixPerspectiveFovLH(&mProjection, D3DX_PI/4, 1.0f, 1.0f, 1000.0f ); g_pDevice->SetTransform(D3DTS_PROJECTION, &mProjection); if(g_bUseEffect) { D3DVERTEXELEMENT9 Decl[3]; if(FAILED(g_pMesh->GetDeclaration(Decl))) MessageBox(NULL, "Could not get declaration", "Error", 0); if(FAILED(g_pDevice->CreateVertexDeclaration(Decl, &g_pVertexDecl)) || !Decl) MessageBox(NULL, "Could not create vertexDecl", "Error", 0); if(FAILED(g_pDevice->SetVertexDeclaration(g_pVertexDecl))) MessageBox(NULL, "Could not set declaration", "Error", 0); // Create Effect from file DWORD dwShaderFlags = 0; dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT; dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT; dwShaderFlags |= D3DXSHADER_NO_PRESHADER; if(FAILED(D3DXCreateEffectFromFile( g_pDevice, chEffectFile, NULL,NULL, dwShaderFlags, NULL, &g_pEffect, NULL))){ MessageBox(NULL, "Error Load and Create Effect", "Error", 0); return E_FAIL;} // Construct WorldViewProjection-matrix D3DXMATRIX mWorldViewProj; D3DXMatrixIdentity(&mWorldViewProj); D3DXMatrixMultiply(&mWorldViewProj, &mWorldViewProj, &mView); D3DXMatrixMultiply(&mWorldViewProj, &mWorldViewProj, &mProjection); D3DXMatrixTranspose(&mWorldViewProj, &mWorldViewProj); } return S_OK;};/*----------------------------------*/HRESULT DrawEffect(void){ if(!g_pDevice || !g_pMesh){ MessageBox(NULL, "Objects are missing needed in drawcall", "Error", 0); return E_FAIL;} // Prepare to start drawing g_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(100,100,100), 1.0f, 0 ); g_pDevice->BeginScene(); // Use Effect if(g_bUseEffect || g_pEffect) { // Get handle and set matrix D3DXHANDLE hWorldViewProj = g_pEffect->GetParameterBySemantic(NULL, "WORLDVIEWPROJECTION"); g_pEffect->SetMatrix(hWorldViewProj, &mWorldViewProj); D3DXHANDLE hTechnique; hTechnique = g_pEffect->GetTechniqueByName("Test"); if(hTechnique == NULL){ MessageBox(NULL, "Handle is empty", "Error", 0); return E_FAIL;} if(FAILED(g_pEffect->ValidateTechnique(hTechnique))) MessageBox(NULL, "Could not validate technique", "Error", 0); if(FAILED(g_pEffect->SetTechnique(hTechnique))){ MessageBox(NULL, "Could not set technique", "Error", 0); return E_FAIL;} UINT nNumPasses; g_pEffect->Begin(&nNumPasses, 0); for(UINT i=0; i<nNumPasses; i++) { if(FAILED(g_pEffect->BeginPass(i))) MessageBox(NULL, "Could not begin pass", "Error", 0); if(FAILED(g_pEffect->CommitChanges())) MessageBox(NULL, "Could not commit changes", "Error", 0); if(FAILED(g_pMesh->DrawSubset(0))) MessageBox(NULL, "Could not draw subset", "Error", 0); g_pEffect->EndPass(); } g_pEffect->End(); } // Use Regular else { if(FAILED(g_pMesh->DrawSubset(0))) MessageBox(NULL, "Could not draw subset", "Error", 0); } g_pDevice->EndScene(); g_pDevice->Present( NULL, NULL, NULL, NULL ); return S_OK;};/*----------------------------------*/HRESULT EndEffect(void){ if(g_pD3D){ g_pD3D->Release(); g_pD3D = NULL;} if(g_pDevice){ g_pDevice->Release(); g_pDevice = NULL;} if(g_pEffect){ g_pEffect->Release(); g_pEffect = NULL; } if(g_pMesh){ g_pMesh->Release(); g_pMesh = NULL; } g_bDone = true; g_bIsActive = false; return S_OK;};/*----------------------------------*/[/Source]And the effect file
-------------------------------------
// GLOBALSfloat4x4 mWorldViewProj : WORLDVIEWPROJECTION : register(c0);struct VSIN{float4 Position : POSITION;float4 Normal : NORMAL;};// SHADERSfloat4 VSSimple(VSIN IN) : POSITION{return mul( float4(IN.Position.xyz, 1.0f), mWorldViewProj);};float4 PSSimple(float4 Position : POSITION) : COLOR{return float4(1.0f, 1.0f, 1.0f, 1.0f);};// TECHNIQUEStechnique Test{pass p0{VertexShader = compile vs_1_1 VSSimple();PixelShader = compile ps_1_1 PSSimple();}}[Edited by - Bangladesh on January 4, 2007 7:08:58 AM]
Removed for easier reading. =)
[Edited by - Bangladesh on January 4, 2007 7:09:46 AM]
[Edited by - Bangladesh on January 4, 2007 7:09:46 AM]
To be truthful; I don't know where I can find info from Debug Runtime errors. I'm using Visual Studio 2005 but app builds without errors.
What is really the problem? From your first post you don't say what the problem is? Do you get a blank screen, no screen, or just an error message when the app runs? To view the errors in VS 2005 goto View->Other Windows->Error List, highlight the 'Errors' and 'Warnings' tab.
Oh, there is no errors, just three warnings about type-casting so the app runs. But if you look at the code, it's littered with if's to see if some of the methods fails and two of them do: the ValidateTechnique()-method and the DrawSubset()-method. (Found in the DrawEffect-function. The first method is somewhat vague since I can successfully set the technique without errors. But the DrawSubset just refuses to work.)
If those are commented out (the if's) the app just clears the backbuffer and draws nothing. But setting the global bool g_bUseEffect the effect-stuff is skipped and the fixed pipe is used instead, and that works.
Maybe you could tell me the steps, in psydo-code if that's ok, one haveto take to get effects running?
If those are commented out (the if's) the app just clears the backbuffer and draws nothing. But setting the global bool g_bUseEffect the effect-stuff is skipped and the fixed pipe is used instead, and that works.
Maybe you could tell me the steps, in psydo-code if that's ok, one haveto take to get effects running?
Quote:
HRESULT DrawEffect(void)
{
if(!g_pDevice || !g_pMesh){
MessageBox(NULL, "Objects are missing needed in drawcall", "Error", 0);
return E_FAIL;}
// Prepare to start drawing
g_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(100,100,100), 1.0f, 0 );
g_pDevice->BeginScene();
// Use Effect
if(g_bUseEffect || g_pEffect)
{
// Get handle and set matrix
D3DXHANDLE hWorldViewProj = g_pEffect->GetParameterBySemantic(NULL, "WORLDVIEWPROJECTION");
g_pEffect->SetMatrix(hWorldViewProj, &mWorldViewProj);
D3DXHANDLE hTechnique;
hTechnique = g_pEffect->GetTechniqueByName("Test");
if(hTechnique == NULL){
MessageBox(NULL, "Handle is empty", "Error", 0);
return E_FAIL;}
if(FAILED(g_pEffect->ValidateTechnique(hTechnique)))
MessageBox(NULL, "Could not validate technique", "Error", 0);
if(FAILED(g_pEffect->SetTechnique(hTechnique))){
MessageBox(NULL, "Could not set technique", "Error", 0);
return E_FAIL;}
UINT nNumPasses;
g_pEffect->Begin(&nNumPasses, 0);
for(UINT i=0; i{
if(FAILED(g_pEffect->BeginPass(i)))
MessageBox(NULL, "Could not begin pass", "Error", 0);
if(FAILED(g_pEffect->CommitChanges()))
MessageBox(NULL, "Could not commit changes", "Error", 0);
if(FAILED(g_pMesh->DrawSubset(0)))
MessageBox(NULL, "Could not draw subset", "Error", 0);
g_pEffect->EndPass();
}
g_pEffect->End();
}
// Use Regular
else
{
if(FAILED(g_pMesh->DrawSubset(0)))
MessageBox(NULL, "Could not draw subset", "Error", 0);
}
g_pDevice->EndScene();
g_pDevice->Present( NULL, NULL, NULL, NULL );
return S_OK;
};
Your: if(FAILED(g_pMesh->DrawSubset(0))) // <------Change to DrawSubset(i)
MessageBox(NULL, "Could not draw subset", "Error", 0);
Quote:
Original post by GrasshopperDotNet
Your: if(FAILED(g_pMesh->DrawSubset(0))) // <------Change to DrawSubset(i)
MessageBox(NULL, "Could not draw subset", "Error", 0);
No, passes and mesh subsets are independent of each other. I'm guessing drawing one subset of the mesh was only a test to see if it drew anything at all. The i-iterator goes over all passes of the effect, each pass rendering one part of the mesh (0).
Quote:
Original post by Todo I'm guessing drawing one subset of the mesh was only a test to see if it drew anything at all.
Yes, the above was my intention. Funny enough, most of the effect-methods report no errors, but the DrawSubset does, yet that is the method mostly used in the SDK tutorials.
Another stage of debugging you could do is test what the HRESULT hr value is and not just check for a success. Knowing which error code is being returned may help identify the cause.
I take it without the effect file being used the mesh draws correctly ? And only when both effect and mesh being drawn it goes wrong ? How about if you draw a simple triangle with the effect ?
Just some extra tests to confirm whether the mesh or effect is at fault or only if used together.
I don't use meshes myself yet so haven't had that problem but my primitive class handles my simple effect file quite fine. But here's my draw code anyway in case it helps.
Set Constants just has this code set up:
m_pD3DEffect->SetMatrix(m_pD3DEffect->GetParameterByName(NULL,"matWorldViewProj"),&m_WorldViewProjection );
The program just sets the variable up for the Effect Class to utilise.
As I said very simple so far.
I started off with the Simple.fx example in Engel's book and progressed from there. As I learn more I can build the project to do more snazzy stuff.
Not sure if its the reason but my WVP section of the effect file is different from yours. Here's the one I've been using to color my GUI controls.
I take it without the effect file being used the mesh draws correctly ? And only when both effect and mesh being drawn it goes wrong ? How about if you draw a simple triangle with the effect ?
Just some extra tests to confirm whether the mesh or effect is at fault or only if used together.
I don't use meshes myself yet so haven't had that problem but my primitive class handles my simple effect file quite fine. But here's my draw code anyway in case it helps.
if (m_bHasEffects) { m_pEffect->UseTechnique(); int passes = m_pEffect->Begin(); for (int i = 0; i < passes; i++) { m_pEffect->SetConstants(); m_pEffect->BeginPass(i); if (!DrawPrimitive(type,vFrom,vCount,iFrom,pCount)) return false; m_pEffect->EndPass(); } m_pEffect->End(); }Set Constants just has this code set up:
m_pD3DEffect->SetMatrix(m_pD3DEffect->GetParameterByName(NULL,"matWorldViewProj"),&m_WorldViewProjection );
The program just sets the variable up for the Effect Class to utilise.
As I said very simple so far.
I started off with the Simple.fx example in Engel's book and progressed from there. As I learn more I can build the project to do more snazzy stuff.
Not sure if its the reason but my WVP section of the effect file is different from yours. Here's the one I've been using to color my GUI controls.
// -------------------------------------------------------------// UIObjects Shading Functions// -------------------------------------------------------------// -------------------------------------------------------------// variables that are provided by the application// -------------------------------------------------------------float4x4 matWorldViewProj; // ----------------------------------------------------------------// Vertex Shader Function to set the World/View/Projection Matrix// ----------------------------------------------------------------float4 VS_WorldViewProjection( float4 Input : POSITION) : POSITION{ float4 Output; Output = mul(Input, matWorldViewProj); // transform Position return Output;}// -------------------------------------------------------------// Pixel Shader (input channels):output channel// -------------------------------------------------------------float4 PS_Colorise() : COLOR{ float4 colColor; colColor.r = 0.7f; colColor.g = 0.7f; colColor.b = 0.7f; colColor.a = 0.0f; return colColor; }float4 PS_ColoriseBlue() : COLOR{ float4 colColor; colColor.r = 0.0f; colColor.g = 0.0f; colColor.b = 0.7f; colColor.a = 0.0f; return colColor; }float4 PS_Highlight() : COLOR{ float4 colColor; colColor.r = 0.9f; colColor.g = 0.9f; colColor.b = 0.9f; colColor.a = 1.0f; return colColor; }float4 PS_Shadow() : COLOR{ float4 colColor; colColor.r = 0.5f; colColor.g = 0.5f; colColor.b = 0.5f; colColor.a = 1.0f; return colColor; }// -------------------------------------------------------------// Name technique | pass | how to compile // -------------------------------------------------------------technique Control{ pass P0 { // compiler directives AlphaTestEnable = false; VertexShader = compile vs_2_0 VS_WorldViewProjection(); PixelShader = compile ps_2_0 PS_Colorise(); }}technique Shadow{ pass P0 { // compiler directives AlphaTestEnable = false; VertexShader = compile vs_2_0 VS_WorldViewProjection(); PixelShader = compile ps_2_0 PS_Shadow(); }}technique Highlight{ pass P0 { // compiler directives AlphaTestEnable = false; VertexShader = compile vs_2_0 VS_WorldViewProjection(); PixelShader = compile ps_2_0 PS_Highlight(); }}technique Transparent{ pass P0 { // compiler directives AlphaTestEnable = true; AlphaFunc = Greater; AlphaRef = 0x000000; VertexShader = compile vs_2_0 VS_WorldViewProjection(); PixelShader = compile ps_2_0 PS_Colorise(); }}technique Opaque{ pass P0 { // compiler directives AlphaTestEnable = false; VertexShader = compile vs_2_0 VS_WorldViewProjection(); PixelShader = compile ps_2_0 PS_Colorise(); }}
This is off the subject but important. Can someone tell me how to use those code boxes in my posts? Pleeeese!
Quote:
I don't use meshes myself yet so haven't had that problem but my primitive class handles my simple effect file quite fine. But here's my draw code anyway in case it helps.
Is using primitives any faster, or better?
Is using primitives any faster, or better?
[/Quote]
Personally I don't know. I just haven't got round to implementing a Mesh Conversion option to my primitive class for drawing purposes. Once I am happy with everything drawing at its simplest level. Primitives with Vertex and Index Buffers I can move onto creating a Mesh Object for them and drawing using that.
This is off the subject but important. Can someone tell me how to use those code boxes in my posts? Pleeeese!
[/Quote]
For larger source code place Source and /Source in [ ] around the code you want to window up for us.
For smaller source code place Code and /Code in the [ ] around the code.
edit:
Hmm obviously my manual quoting isn' working right :D
Thanks, ever so much!
Further down the line: Passes not involving shaders work from within the effectfile; so the ff pipeline renders ok. So something haveto go wrong when the shaders are brough into play.
I haven't seen it, but I suppose a effect need to set a vertex-declaraion just as a shader would do. Or no?
I haven't seen it, but I suppose a effect need to set a vertex-declaraion just as a shader would do. Or no?
From what I've read if you have a multiple pass system the earlier passes are rendered to a texture which is then passed on to each subsequent pass so that multi-texturing occurs. Not played with that side of it yet but I'm sure someone here has.
I think thats what you were asking ? If not I apologise .. just woke up :P
I think thats what you were asking ? If not I apologise .. just woke up :P
Not quite Xrystal, not quite. I've yet to make the damn thing work! ;)
I mean; how hard can it be? =D
The output of each pass is drawn to a rendertarget of your choosing, so you could have multiple rendertargets and compose them on the final pixel-shader or work with the main rendertarget if that is an option.
I mean; how hard can it be? =D
The output of each pass is drawn to a rendertarget of your choosing, so you could have multiple rendertargets and compose them on the final pixel-shader or work with the main rendertarget if that is an option.
Ok, I figured it out; the problem was a faulty WVP matrix-setting. =)
Now everything works just fine. Thanks a bunch everyone.
Now everything works just fine. Thanks a bunch everyone.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement