I'm feeling pretty stuck here. When I dug into this some more and read up on compositors and materials, I couldn't see any reason why I should be porting this to a compositor. I want to highlight a single model at a time, not apply a full-screen effect.
So I tried porting the DilateErode to a .material script. Below is the exported .fx
Code: Select all
//--------------------------------------------------------------//
// DilateErode
//--------------------------------------------------------------//
//--------------------------------------------------------------//
// DrawObject
//--------------------------------------------------------------//
string NPR_DilateErode_DrawObject_Elephant : ModelData = "..\\..\\..\\..\\Program Files (x86)\\AMD\\RenderMonkey 1.82\\Examples\\Media\\Models\\ElephantBody.3ds";
texture ImageRT_Tex : RenderColorTarget
<
float2 ViewportRatio={1.0,1.0};
string Format="D3DFMT_A8R8G8B8";
float ClearDepth=1.000000;
int ClearColor=0;
>;
float4x4 view_proj_matrix : ViewProjection;
struct VS_OUTPUT {
float4 Pos: POSITION;
};
VS_OUTPUT NPR_DilateErode_DrawObject_Vertex_Shader_main(float4 Pos: POSITION){
VS_OUTPUT Out;
// Standard mvp transform
Out.Pos = mul(view_proj_matrix, Pos);
return Out;
}
float4 NPR_DilateErode_DrawObject_Pixel_Shader_main() : COLOR {
// Output white
return 1;
}
//--------------------------------------------------------------//
// Dilate
//--------------------------------------------------------------//
string NPR_DilateErode_Dilate_ScreenAlignedQuad : ModelData = "..\\..\\..\\..\\Program Files (x86)\\AMD\\RenderMonkey 1.82\\Examples\\Media\\Models\\ScreenAlignedQuad.3ds";
float pixelSize
<
string UIName = "pixelSize";
string UIWidget = "Numeric";
bool UIVisible = true;
float UIMin = 0.00;
float UIMax = 0.01;
> = float( 0.00 );
struct NPR_DilateErode_Dilate_Vertex_Shader_VS_OUTPUT {
float4 Pos: POSITION;
float2 texCoord: TEXCOORD;
};
NPR_DilateErode_Dilate_Vertex_Shader_VS_OUTPUT NPR_DilateErode_Dilate_Vertex_Shader_main(float4 Pos: POSITION){
NPR_DilateErode_Dilate_Vertex_Shader_VS_OUTPUT Out;
// Clean up inaccuracies
Pos.xy = sign(Pos.xy);
Out.Pos = Pos;
Out.texCoord.x = 0.5 * (1 + Pos.x + pixelSize);
Out.texCoord.y = 0.5 * (1 - Pos.y + pixelSize);
return Out;
}
float NPR_DilateErode_Dilate_Pixel_Shader_pixelSize
<
string UIName = "NPR_DilateErode_Dilate_Pixel_Shader_pixelSize";
string UIWidget = "Numeric";
bool UIVisible = true;
float UIMin = 0.00;
float UIMax = 0.01;
> = float( 0.00 );
sampler ImageRT = sampler_state
{
Texture = (ImageRT_Tex);
ADDRESSU = CLAMP;
ADDRESSV = CLAMP;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
// The surrounding pixels
float2 samples[8] = {
-1, -1,
0, -1,
1, -1,
-1, 0,
1, 0,
-1, 1,
0, 1,
1, 1,
};
float4 NPR_DilateErode_Dilate_Pixel_Shader_main(float2 texCoord: TEXCOORD) : COLOR {
// Simple dilate operation, find the maximum
// pixel in the neighborhood.
float4 maxSamp = tex2D(ImageRT, texCoord);
for (int i = 0; i < 8; i++){
float4 sample = tex2D(ImageRT, texCoord + NPR_DilateErode_Dilate_Pixel_Shader_pixelSize * samples[i]);
maxSamp = max(maxSamp, sample);
}
return maxSamp;
}
//--------------------------------------------------------------//
// Erode
//--------------------------------------------------------------//
string NPR_DilateErode_Erode_ScreenAlignedQuad : ModelData = "..\\..\\..\\..\\Program Files (x86)\\AMD\\RenderMonkey 1.82\\Examples\\Media\\Models\\ScreenAlignedQuad.3ds";
float NPR_DilateErode_Erode_Vertex_Shader_pixelSize
<
string UIName = "NPR_DilateErode_Erode_Vertex_Shader_pixelSize";
string UIWidget = "Numeric";
bool UIVisible = true;
float UIMin = 0.00;
float UIMax = 0.01;
> = float( 0.00 );
struct NPR_DilateErode_Erode_Vertex_Shader_VS_OUTPUT {
float4 Pos: POSITION;
float2 texCoord: TEXCOORD;
};
NPR_DilateErode_Erode_Vertex_Shader_VS_OUTPUT NPR_DilateErode_Erode_Vertex_Shader_main(float4 Pos: POSITION){
NPR_DilateErode_Erode_Vertex_Shader_VS_OUTPUT Out;
// Clean up inaccuracies
Pos.xy = sign(Pos.xy);
Out.Pos = Pos;
Out.texCoord.x = 0.5 * (1 + Pos.x + NPR_DilateErode_Erode_Vertex_Shader_pixelSize);
Out.texCoord.y = 0.5 * (1 - Pos.y + NPR_DilateErode_Erode_Vertex_Shader_pixelSize);
return Out;
}
float NPR_DilateErode_Erode_Pixel_Shader_pixelSize
<
string UIName = "NPR_DilateErode_Erode_Pixel_Shader_pixelSize";
string UIWidget = "Numeric";
bool UIVisible = true;
float UIMin = 0.00;
float UIMax = 0.01;
> = float( 0.00 );
sampler NPR_DilateErode_Erode_Pixel_Shader_ImageRT = sampler_state
{
Texture = (ImageRT_Tex);
ADDRESSU = CLAMP;
ADDRESSV = CLAMP;
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
};
// We are using reverse subtract blending, so the result will
// be dilate - erode, which is a basic edge-detecting operator.
// The surrounding pixels
float2 NPR_DilateErode_Erode_Pixel_Shader_samples[8] = {
-1, -1,
0, -1,
1, -1,
-1, 0,
1, 0,
-1, 1,
0, 1,
1, 1,
};
float4 NPR_DilateErode_Erode_Pixel_Shader_main(float2 texCoord: TEXCOORD) : COLOR {
// Simple erode operation, find the minimum
// pixel in the neighborhood.
float4 minSamp = tex2D(NPR_DilateErode_Erode_Pixel_Shader_ImageRT, texCoord);
for (int i = 0; i < 8; i++){
float4 sample = tex2D(NPR_DilateErode_Erode_Pixel_Shader_ImageRT, texCoord + NPR_DilateErode_Erode_Pixel_Shader_pixelSize * NPR_DilateErode_Erode_Pixel_Shader_samples[i]);
minSamp = min(minSamp, sample);
}
return minSamp;
}
//--------------------------------------------------------------//
// Technique Section for Effect Workspace.NPR.DilateErode
//--------------------------------------------------------------//
technique DilateErode
{
pass DrawObject
<
string Script = "RenderColorTarget0 = ImageRT_Tex;"
"ClearColor = (0, 0, 0, 0);"
"ClearDepth = 1.000000;";
>
{
ALPHABLENDENABLE = FALSE;
VertexShader = compile vs_1_1 NPR_DilateErode_DrawObject_Vertex_Shader_main();
PixelShader = compile ps_2_0 NPR_DilateErode_DrawObject_Pixel_Shader_main();
}
pass Dilate
{
CULLMODE = NONE;
ALPHABLENDENABLE = FALSE;
ZENABLE = FALSE;
VertexShader = compile vs_1_1 NPR_DilateErode_Dilate_Vertex_Shader_main();
PixelShader = compile ps_2_0 NPR_DilateErode_Dilate_Pixel_Shader_main();
}
pass Erode
{
SRCBLEND = ONE;
DESTBLEND = ONE;
CULLMODE = NONE;
ALPHABLENDENABLE = TRUE;
BLENDOP = REVSUBTRACT;
VertexShader = compile vs_1_1 NPR_DilateErode_Erode_Vertex_Shader_main();
PixelShader = compile ps_2_0 NPR_DilateErode_Erode_Pixel_Shader_main();
}
}
And here's the .material I created (it should be obvious I haven't done this before)
Code: Select all
vertex_program hlslDrawWhiteVS hlsl
{
source hlslDrawWhiteVS.txt
entry_point main
target vs_1_1
}
fragment_program hlslDrawWhitePS hlsl
{
source hlslDrawWhitePS.txt
entry_point main
target ps_2_0
}
vertex_program hlslDilateVS hlsl
{
source hlslDilateVS.txt
entry_point main
target vs_1_1
}
fragment_program hlslDilatePS hlsl
{
source hlslDilatePS.txt
entry_point main
target ps_2_0
}
vertex_program hlslErodeVS hlsl
{
source hlslErodeVS.txt
entry_point main
target vs_1_1
}
fragment_program hlslErodePS hlsl
{
source hlslErodePS.txt
entry_point main
target ps_2_0
}
material DilateErodeShader
{
technique
{
pass DrawWhite
{
depth_check off
// scene_blend add is default
vertex_program_ref hlslDrawWhiteVS
{
}
fragment_program_ref hlslDrawWhitePS
{
}
texture_unit RT
{
tex_coord_set 0
tex_address_mode clamp
filtering linear linear linear
}
}
pass Dilate
{
depth_check off
// depth_write off?
cull_hardware none
cull_software none
vertex_program_ref hlslDilateVS
{
}
fragment_program_ref hlslDilatePS
{
}
texture_unit RT
{
tex_coord_set 0
tex_address_mode clamp
filtering linear linear linear
}
}
pass Erode
{
depth_check off
// depth_write off?
cull_hardware none
cull_software none
scene_blend alpha_blend
scene_blend_op reverse_subtract
vertex_program_ref hlslErodeVS
{
}
fragment_program_ref hlslErodePS
{
}
texture_unit RT
{
tex_coord_set 0
tex_address_mode clamp
filtering linear linear linear
}
}
}
}
Each .txt has the respective HLSL code in it.
At runtime if I use this material on my model there's no result (invisible model). Ogre.log doesn't have any complaints about my material.
I found this post here:
http://www.ogre3d.org/forums/viewtopic.php?f=5&t=35259
But the link, code, and images are all broken for me, so it's not very useful, but apparently this has been done before.
EDIT: I've identified some possible sources of error, so if anyone says "tl;dr" to the post maybe this will help:
- The "texture_unit RT" seems like it might only need to exist in the Dilate and Erode passes, not the DrawWhite, but despite reading the manual on this, I can't figure out what the crap this does.
- There's a lot of ambiguity between the .fx and the .material pass parameters, like "SRCBLEND" and stuff. I really don't know if I transferred them properly.