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.
typedef std::vector<D3DMATERIAL9> MaterialArray;
typedef std::vector<LPDIRECT3DTEXTURE9> TexturePtrArray;
void SetPath(const std::string& strPath);
void SetMesh(const std::string& strMesh);
void SetEffect(const std::string& strEffect);
void SetTransforms(LPD3DXMATRIX pMatWorld,
void SetPosition(D3DXVECTOR3 vPos);
HRESULT Init(LPDIRECT3DDEVICE9 pDevice);
HRESULT Render(LPDIRECT3DDEVICE9 pDevice);
HRESULT Restore(LPDIRECT3DDEVICE9 pDevice);
// Texture vertex shader
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
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)
// 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,
NULL, // D3DXMACROs
NULL, // #includes
NULL, // memory pool
NULL); // compilation errors
D3DXHANDLE hTech = m_pEffect->GetTechnique(0);
hr = m_pEffect->ValidateTechnique(hTech);
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 hr = S_OK;
// 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.
D3DXMatrixMultiply(&matWorldView, &matWorld, &m_matView);
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
// Draw the mesh subset
hr = m_pEffect->End();
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 =
Texture = <CSTexture>;
MinFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
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;
Lighting = False;
Sampler = <CSSampler>;
ColorOp = BlendTextureAlpha;
ColorArg1 = Texture;
ColorArg2 = Diffuse;
AlphaOp = Disable;
ColorOp = Disable;
AlphaOp = 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
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