After the disappointment of not getting my effect files to load properly this
morning, I was determined to get it to work by the next work day. I want to get
to the TRON style blur!
After much frustration, I finally decided to start from scratch again and do
what I always do. Examine, deconstruct, and copy an example. I decided to look
at the shaders in my "DirectX 9 Programmable Graphics Pipeline" book. A crappy
book, but it's got great resources on disk.
I had to hack into Political Machine because that was the only project I was
working on that currently supports DX9. Just wait though pretty soon, all our
projects that use 3d will. Isn't power wonderful?
Anyways, here's where I hope this development journal really pays off. Most
books and articles discuss theories. I'm here to put practice these theories and
put them to the test. Here are my results.
1) I started to add a generic CEffectObject. Any object that has an effect
associated with it. Basically, for this type of thing, we need a mesh object
with some extra data to hold the effects. Here's my class.
class CEffectObject
{
// typedefs
typedef std::vector<D3DMATERIAL9> MaterialArray;
typedef std::vector<LPDIRECT3DTEXTURE9> TexturePtrArray;
public:
CEffectObject();
virtual ~CEffectObject();
// Attributes
public:
void SetPath(const std::string& strPath);
void SetMesh(const std::string& strMesh);
void SetEffect(const std::string& strEffect);
void SetTransforms(LPD3DXMATRIX pMatWorld,
;
LPD3DXMATRIX pMatView,
;
LPD3DXMATRIX pMatProj);
void SetPosition(D3DXVECTOR3 vPos);
// Operations
public:
HRESULT Init(LPDIRECT3DDEVICE9 pDevice);
HRESULT Render(LPDIRECT3DDEVICE9 pDevice);
HRESULT Restore(LPDIRECT3DDEVICE9 pDevice);
protected:
void DestroyDeviceObjects();
// Implementation
protected:
// Texture vertex shader
std::string m_strEffect;
LPD3DXEFFECT m_pEffect;
// Mesh
std::string m_strMesh;
LPD3DXMESH m_pMesh;
MaterialArray m_aMaterials;
TexturePtrArray m_aTexturePtrs;
// Transforms
D3DXMATRIXA16 m_matWorld;
D3DXMATRIXA16 m_matView;
D3DXMATRIXA16 m_matProj;
// Misc
std::string m_strPath;
D3DXVECTOR3 m_vPos;
};
As you can see, it's really just a mesh object with the extra effect
data. I also added the matrices in the class because effects are often dependant
on them.
2) Define the load function. I'm going to trim from here on down because it's
late and I'm getting tired of typing. (So much for full examples)
HRESULT CEffectObject::Init(LPDIRECT3DDEVICE9
pDevice)
{
HRESULT hr;
// Snip....
// Just do the basic object loading...
// Here's the meat. Load the effect and validate the technique
// Here's where I lost interest in making it generic. I only handle
// the first technique.
strFullPath = m_strPath + "/" + m_strEffect;
hr = D3DXCreateEffectFromFile(pDevice,
;
strFullPath.data(),
;
NULL, // D3DXMACROs
;
NULL, // #includes
;
D3DXSHADER_DEBUG,
;
NULL, // memory pool
;
&m_pEffect,
;
NULL); // compilation errors
D3DXHANDLE hTech = m_pEffect->GetTechnique(0);
hr = m_pEffect->ValidateTechnique(hTech);
return hr;
}
A lot of powerful stuff happens in those three calls. Believe me. Another
reason I love my DX9. According to docs, the ValidateTechnique is needed before
an effect an be rendered. I'm not sure of that. I haven't tested it without.
Sounds like a good thing to do anyways.
3) Define the Render function. Just like my last daily really. I'll add it
here for completeness.
HRESULT CEffectObject::Render(LPDIRECT3DDEVICE9
pDevice)
{
HRESULT hr = S_OK;
if(m_pEffect)
{
// Snip...
// A bunch of matrix transforms to get the object
// In the right place, orientation, and scale.
// If you really want the stuff, drop me a line.
D3DXMATRIX matWorldView;
D3DXMatrixMultiply(&matWorldView, &matWorld, &m_matView);
m_pEffect->SetMatrix("WorldView", &matWorldView);
m_pEffect->SetMatrix("Projection", &m_matProj);
m_pEffect->SetTechnique(m_pEffect->GetTechnique(0));
UINT numPasses;
int i;
hr = m_pEffect->Begin(&numPasses, 0);
hr = m_pEffect->Pass(0);
for( i=0; i < m_aMaterials.size(); i++ )
{
// Set the material and texture
for this subset
pDevice->SetMaterial(&m_aMaterials[i]);
pDevice->SetTexture(0,
m_aTexturePtrs[i]);
// Draw the mesh subset
m_pMesh->DrawSubset(i);
}
hr = m_pEffect->End();
}
return hr;
}
Simple dimple eh? Took me long enough to get to this point.
4) Finally, create the effect. This effect has some defintions at the
top to satisfy EffectEdit. There's a hidden beauty here. Those defs don't effect
how the effect works outside of effect edit. That means that they can stay there
without worrying about screwing up the version for the game.
// EffectEdit defs
string XFile = "ColonyShip.x";
texture CSTexture < string name = "ColonyShipDiffuseMap.dds"; >;
float4x3 WorldView : WORLDVIEW;
float4x4 Projection : PROJECTION;
sampler CSSampler =
sampler_state
{
Texture = <CSTexture>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Diffuse : COLOR;
float2 TexCoord : TEXCOORD0;
};
VS_OUTPUT VS_Texture(float4 Position : POSITION,
;
float3 Normal : NORMAL,
;
float2 TexCoord : TEXCOORD0)
{
VS_OUTPUT Out = (VS_OUTPUT)0;
Out.Position = mul(float4(P, 1), Projection);
Out.Diffuse = float4(1, 0, 0, 1);
Out.TexCoord = TexCoord;
return Out;
}
technique Tech0
{
pass Texture
{
Lighting = False;
Sampler[0] = <CSSampler>;
// Stage0
ColorOp[0] = BlendTextureAlpha;
ColorArg1[0] = Texture;
ColorArg2[0] = Diffuse;
AlphaOp[0] = Disable;
// Stage1
ColorOp[1] = Disable;
AlphaOp[1] = Disable;
VertexShader = compile vs_1_1 VS_Texture();
}
}
Simple shader, but think of the possibilities. In this one file, we can
define the shader for the low, medium, and high detail graphics. We can reuse
passes and techniques. The possibilities are almost endless. I think 
Here's the payoff. I can run the application that uses this effect and load
it up in the EffectEdit program at the SAME time! This also means that the
effect can now be edited on the fly in the EffectEdit and just run in the
program without a compile or link. I guess for ultimate completeness, there
should be an option to reload the fx from the file so that the changes can be
seen immediately in the program without shutting it down. Wouldn't that be kewl!


Here's the US being attacked by a bunch of red colony
ships while simultaneously modifying the effect in EffectEdit. I love this
stuff!
It may be simple enough for the artists to even hack around the
shader file. After a little education of course. No offense to the artists 