Game Development Community

Rendering a Mesh with a CusomMaterial from a Custom RenderBinMgr

by Ryan Mounts · in Torque 3D Professional · 03/19/2010 (10:11 am) · 3 replies

I have a custom RenderBinMgr-derived manager that processes tsMeshes that have a special flag set. I've got it processing in the correct order and handling the right meshes. Rendering the meshes in a custom way is the problem. I want each mesh it handles to use one particular CustomMaterial, but can't get that working. The shaders should transform the verts into screenspace, sample the backbuffer for the pixel color, and write the pixel depth to the depthbuffer. I just don't know enough about shaders and how T3D hooks into them to get this working. Here's my horrible attempt at accomplishing this...

myOccluderV.hlsl
struct VertData
{
   float3 position        : POSITION;
};

struct ConnectData
{
   float4 hpos            : POSITION;
};

uniform float4x4 modelview;

ConnectData main( VertData IN )
{
   ConnectData OUT;

   OUT.hpos = mul(worldview, float4(IN.position.xyz,1)).xzyw;
   
   return OUT;
}

myOccluderP.hlsl
uniform sampler2D backbuffer : register(S0);
// Where is the depthBuffer located???

struct ConnectData
{
   float4 hpos             : POSITION;
};

float4 main( ConnectData IN ) : COLOR   
{      
   float4 color = tex2D( backbuffer, IN.hpos.xy );
   
   float depth = IN.hpos.z / IN.hpos.w;
   
   // Need to write depth to the depthBuffer!
         
   return color;      
}

myOccluder.cs
singleton ShaderData( MyOccluderShader )
{
   DXVertexShaderFile   = "shaders/common/myOccluderV.hlsl";
   DXPixelShaderFile    = "shaders/common/myOccluderP.hlsl";

   pixVersion = 2.0;
};

//The render states used when rendering the post effect
singleton GFXStateBlockData( MyOccluderBlock )
{
   samplersDefined = true;
   samplerStates[0] = SamplerClampPoint;  // BackBuffer
//   cullDefined = true;
//   cullMode = "GFXCullCCW";
};

singleton CustomMaterial(myOccluder)
{
   version = 2;
   shader = MyOccluderShader;
   stateBlock = MyOccluderBlock;
   isOccluder = 1;
   sampler0 = "$backbuff";
   // Which sampler contains the depthbuffer?
};

For one thing, I don't know where the depthBuffer is stored. Second, the above code does not compile. T3D complains about "modelview" being undefined in the vertex shader. Also, do I need to do some setup in MyOccluderBinMgr::render() to pass the shaders any relevant data?

#1
03/19/2010 (10:32 am)
ahh,position is consumed by the rasterizer ,so you can not expose it this way to the pixel shader.

struct ConnectData
{
float4 hpos : POSITION;
float3 texc : TEXCOORD0;
};

then

OUT.texc = OUT.hpos;

now in PS copy again your connection:

struct ConnectData
{
float3 texc : TEXCOORD0;
};

also:
float depth = IN.texc.z / 2000;
// where 2000 is your far plane Zdistance from the eye

Also you need to set all shader constants (modelview,..) in order to compile the shader.
#2
03/19/2010 (11:11 am)
Hey Ivan, thanks for the reminder! Just goes to show how inexperienced I am with shaders. I also moved the worldview matrix into the main() argument list:

ConnectData main( VertData IN,
		  uniform float4x4 worldViewOnly )
{

Now it compiles fine, but I get no output, which I kinda expected. :) Do you know how to get MyOccluderBinMgr::render() to pass in the worldview matrix to the vertex shader?
#3
03/19/2010 (11:31 am)
the render instance,scene state and GFX is used for transformation
modelview = world * view * projection (this is pseudocode!)

world = GFX->getWorldMatrix()
view = GFX->getViewMatrix()
projection = GFX->getProjectionMatrix()

mul all of them,then set this as a shader constant.
you need to set the shader also

GFX->setShader( YourShader );
but I am not really sure how you process your shader code since you mentioned a custom material