Hi everyone !
I’m playing with HLSL shaders and SAS scripting, trying to use these as much as possible in 3dsmax (it is an enjoyable task if you omit the lack of documentation, the somehow “original” interpretation of SAS in 3dsmax, the bugs maybe and so on…). My subject of interest nowadays is effects which need whole scene render in render targets, possibly from various view points. Using the Scene Effect Loader and patience (a lot), I succeeded to render DOF, shadow mapping for one light, etc… Yeepee.
But I came into troubles when I tried to render more than one effect at once (DOF and shadow mapping for example).
So I re-started from the beginning and tried to achieve the following:
- render a simple scene (say a teapot) in two RT cleared in blue, using two different vertex shaders (just to simulate real conditions), and two very simple pixel shaders (one which renders the objet in red and the other in green),
- then use a full screen quad render using these two RT and a compositing pixel shader (which sums up the two RT… art masterpiece).
After a few tries, the best I managed to get is this:
when I expected that:
Here are the shaders:
EnvTEST.fx
string ParamID = "0x003";
float4x4 WorldViewProj : WORLDVIEWPROJ;
struct SInputVS
{
float3 Pos : POSITION;
};
struct SOutputVS
{
float4 Pos : POSITION;
};
SOutputVS TEST_VS( SInputVS input )
{
SOutputVS output;
output.Pos = mul(float4(input.Pos, 1.0f), WorldViewProj);
return output;
}
SOutputVS TEST_Scaled_VS( SInputVS input )
{
SOutputVS output;
output.Pos = mul(float4(input.Pos*1.5f, 1.0f), WorldViewProj);
return output;
}
float4 TEST_Red_PS( SOutputVS input ) : COLOR
{
return float4(1.0f,0.0f,0.0f,1.0f);
}
float4 TEST_Green_PS( SOutputVS input ) : COLOR
{
return float4(0.0f,1.0f,0.0f,1.0f);
}
texture RedRender : RENDERCOLORTARGET
<
float2 ViewPortRatio = { 1.0f, 1.0f };
int MipLevels = 1;
string Format = "A8R8G8B8";
string UIWidget = "None";
>;
sampler RedRenderSampler = sampler_state
{
texture = <RedRender>;
AddressU = CLAMP;
AddressV = CLAMP;
MipFilter = POINT;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
texture GreenRender : RENDERCOLORTARGET
<
float2 ViewPortRatio = { 1.0f, 1.0f };
int MipLevels = 1;
string Format = "A8R8G8B8";
string UIWidget = "None";
>;
sampler GreenRenderSampler = sampler_state
{
texture = <GreenRender>;
AddressU = CLAMP;
AddressV = CLAMP;
MipFilter = POINT;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
float4 ClearColor = float4(0.0f, 0.0f, 1.0f, 1.0f);
float Script : STANDARDSGLOBAL
<
string UIWidget = "none";
string ScriptClass = "scene";
string ScriptOrder = "preprocess";
string ScriptOutput = "color";
string Script = "Technique=TEST;";
> = 0.8;
technique TEST
<
string ScriptClass = "scene";
string ScriptOrder = "preprocess";
string ScriptOutput = "color";
string Script =
"RenderColorTarget0=RedRender;"
"RenderDepthStencilTarget=;"
"ClearSetColor=ClearColor;"
"ClearSetDepth=1.0f;"
"Clear=Color;"
"Clear=Depth;"
"Pass=Red;"
"RenderColorTarget0=GreenRender;"
"RenderDepthStencilTarget=;"
"ClearSetColor=ClearColor;"
"ClearSetDepth=1.0f;"
"Clear=Color;"
"Clear=Depth;"
"Pass=Green;";
>
{
pass Red
<
string Script =
"Draw=Geometry;";
>
{
ZEnable = false;
CullMode = CW;
AlphaBlendEnable = false;
VertexShader = compile vs_3_0 TEST_Scaled_VS();
PixelShader = compile ps_3_0 TEST_Red_PS();
}
pass Green
<
string Script =
"Draw=Geometry;";
>
{
ZEnable = false;
CullMode = CW;
AlphaBlendEnable = false;
VertexShader = compile vs_3_0 TEST_VS();
PixelShader = compile ps_3_0 TEST_Green_PS();
}
}
PostTEST.fx
string ParamID = "0x003";
float4x4 WorldViewProj : WORLDVIEWPROJ;
struct SInputVS
{
float3 Pos : POSITION;
};
struct SOutputVS
{
float4 Pos : POSITION;
};
SOutputVS TEST_VS( SInputVS input )
{
SOutputVS output;
output.Pos = mul(float4(input.Pos, 1.0f), WorldViewProj);
return output;
}
SOutputVS TEST_Scaled_VS( SInputVS input )
{
SOutputVS output;
output.Pos = mul(float4(input.Pos*1.5f, 1.0f), WorldViewProj);
return output;
}
float4 TEST_Red_PS( SOutputVS input ) : COLOR
{
return float4(1.0f,0.0f,0.0f,1.0f);
}
float4 TEST_Green_PS( SOutputVS input ) : COLOR
{
return float4(0.0f,1.0f,0.0f,1.0f);
}
texture RedRender : RENDERCOLORTARGET
<
float2 ViewPortRatio = { 1.0f, 1.0f };
int MipLevels = 1;
string Format = "A8R8G8B8";
string UIWidget = "None";
>;
sampler RedRenderSampler = sampler_state
{
texture = <RedRender>;
AddressU = CLAMP;
AddressV = CLAMP;
MipFilter = POINT;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
texture GreenRender : RENDERCOLORTARGET
<
float2 ViewPortRatio = { 1.0f, 1.0f };
int MipLevels = 1;
string Format = "A8R8G8B8";
string UIWidget = "None";
>;
sampler GreenRenderSampler = sampler_state
{
texture = <GreenRender>;
AddressU = CLAMP;
AddressV = CLAMP;
MipFilter = POINT;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
float4 ClearColor = float4(0.0f, 0.0f, 1.0f, 1.0f);
float Script : STANDARDSGLOBAL
<
string UIWidget = "none";
string ScriptClass = "scene";
string ScriptOrder = "preprocess";
string ScriptOutput = "color";
string Script = "Technique=TEST;";
> = 0.8;
technique TEST
<
string ScriptClass = "scene";
string ScriptOrder = "preprocess";
string ScriptOutput = "color";
string Script =
"RenderColorTarget0=RedRender;"
"RenderDepthStencilTarget=;"
"ClearSetColor=ClearColor;"
"ClearSetDepth=1.0f;"
"Clear=Color;"
"Clear=Depth;"
"Pass=Red;"
"RenderColorTarget0=GreenRender;"
"RenderDepthStencilTarget=;"
"ClearSetColor=ClearColor;"
"ClearSetDepth=1.0f;"
"Clear=Color;"
"Clear=Depth;"
"Pass=Green;";
>
{
pass Red
<
string Script =
"Draw=Geometry;";
>
{
ZEnable = false;
CullMode = CW;
AlphaBlendEnable = false;
VertexShader = compile vs_3_0 TEST_Scaled_VS();
PixelShader = compile ps_3_0 TEST_Red_PS();
}
pass Green
<
string Script =
"Draw=Geometry;";
>
{
ZEnable = false;
CullMode = CW;
AlphaBlendEnable = false;
VertexShader = compile vs_3_0 TEST_VS();
PixelShader = compile ps_3_0 TEST_Green_PS();
}
}
As you can see the shaders are pretty simple and the SAS scripting is not complex… What I’ve found is that both targets are properly accessible and cleared to the blue color. But the red rendering pass, if actually done, is done in the wrong render target, even though the script commands are properly ordered (in my opinion at least :)). So I get a fully blue image and another with blue background and both teapots rendered: the big red with the small green inside… Sic.
Oh and I almost forgot: for that to work, the object has to be assigned a DirectX shader (say StandardFX.fx) for the above to work… Is actually don’t understand why, maybe it’s a clue ?
At a moment I thought I found the solution: an esoteric parameters of Scene Effect Loader, accessible using max scripting, numberOfPasses was supposed to be used to define the number of passes needed in environment effect (the doc says “6 if you render a cube map”). Very well, I wrote the script below (you’ve already understood it doesn’t work, but I add it here in order to be as complete as possible):
struct loadTEST
(
fn BuildFullSceneFxPath _inFxName =
(
path = "C:\Projects\depot\TEST\Media\FXs" + _inFxName
),
fn Init =
(
-- Pre-process & environment shaders
pathPre = BuildFullSceneFxPath "\EnvTEST.fx"
SceneEffectLoader.LoadSceneEffect pathPre effectType:#Env numberOfPasses:2
)
)
loadTESTInstance = loadTEST()
loadTESTInstance.Init()
That’s the point I’ve reached so far. So if anyone can give me an hint I would be really gratefull… Any solution is accepted, including a “it’s not possible dude” :). But as I’ve already been near to think that for a certain amount of old problems using SAS & 3dsmax, which I managed to solve…
Anyway, thanks to everyone who’s been patient enough to read that until the end (thanks also to all the other who gave up earlier… ;)).