Meta-programming - examples

janderson askme at me.com
Fri Feb 16 08:47:32 PST 2007


Here's another example:

.fx shaders contain shader constants which include float(1,2,3,4), 
int(1,2,3,4), textures, matrices and other constants.  To access these 
parameters you can use a bulky interface (i'm doing this from memory so 
the syntax may be 100%):

DXHANDLE ambient; //Create handle
effect->GetHandle(ambient, "ambient");
//ect..

//Get the value.
float[4] amb = effect->GetValue(ambient, sizeof(float[4]));

//Set the value
effect->SetFloat(ambient, amb, sizeof(float[4]));


Typically, you need to write this for ever shader.  This can really 
start to add up when you have 100's of shaders.  These values are 
normally data driven from some file (ie material).  Also the rendering 
code for each shader is typically boilerplate.  Its even worse if you 
try to optimize it into some sort of state-scene-graph to minimize state 
switches.  You can also get things like meta data from data types which 
are useful for building gui's which represent the shader.

If you could wrap all this into a mixin that pulls information out from 
the shader, it would be an awesome time saver.  The boilerplate C++ code 
(which would take me to long to design here) would still be written 
mostly in C++.

//In D
mixin(shader!(import("boilerplateShader.d"), import("shader1.fx")));

...

//Shader.fx
float4 k_a  <
	string UIName = "Ambient";
	> = float4( 0.47f, 0.47f, 0.47f, 1.0f );    // ambient
	

ect...


// transformations
float4x4 World      : 		WORLD;
float4x4 View       : 		VIEW;
float4x4 Projection : 		PROJECTION;
float4x4 WorldViewProj : 	WORLDVIEWPROJECTION;
float4x4 WorldView : 		WORLDVIEW;

//...

VS_OUTPUT VS(
     float3 Pos  : POSITION,
     float3  col	: COLOR,
     float3 Norm : NORMAL,
     float2 Tex  : TEXCOORD0)
{
	return ambient;
}

float4 PS(
     float4 Diff : COLOR0,
     float4 Spec : COLOR1,
     float2 Tex  : TEXCOORD0,
     float2 Tex1 : TEXCOORD1 ) : COLOR
{
     float4 color =  Diff + Spec;
     return  color;
}

technique DefaultTechnique
{
     pass P0
     {
         // shaders
         VertexShader = compile vs_1_1 VS();
         PixelShader  = compile ps_1_1 PS();
     }
}

Then you could interact with it like:

shader1 shader = StateTree.getShader1();
shader.ambient = {1, 0, 1};

//...
foreach (shadertype shtype; shader.types)
{
	AddToGui(shtype);
}

ect...
Note that this would mean, that adding/removing properties for an fx 
shader compiled at run-time would not be reflected however you normally 
don't care (and you can still modify the shader real-time).

-Joel



More information about the Digitalmars-d mailing list