leftnoteasy:
请教一下各位大大关于Shader的RenderToTarget的问题
我看到很多Post-Screen的程序都是使用了RenderToTarget,我也使用过这种方法
但是我觉得这样有点麻烦,主要是如果要用的话,就需要在程序中反复的调用RenderToTarget,而且要在cpp文件中设置很多的参数,这样使得cpp文件改动起来挺麻烦的,我目前觉得使用FX Composer 2.5开发shader比较舒服,能不能把RenderToTarget都放在Shader中实现了.这样我使用FX Composer 2.5开发的程序可以直接在DirectX程序中使用.
谢谢了 :-)
qrli
不可能
leftnoteasy
请教一下,为什么不可能呢,还有就是版本的问题,DXSAS在SDK只是寥寥提了几句,没有一个具体的例子.如果FX Composer的程序可以直接拿来用的话,Shader的开发周期就真正减少了很多了
在Nvida的文档中有这个例子:
Shader code
在Nvida的文档中有这个例子:
// Relative filter weights indexed by distance (in texels) from "home" texel
// (WT_0 is the "home" or center of the filter, WT_4 is four texels away)
// Try changing these around for different filter patterns.
#define WT_0 1.0
#define WT_1 0.8
#define WT_2 0.6
#define WT_3 0.4
#define WT_4 0.2
// these ones are based on the above.
#define WT_NORMALIZE (WT_0+2.0*(WT_1+WT_2+WT_3+WT_4))
#define KW_0 (WT_0/WT_NORMALIZE)
#define KW_1 (WT_1/WT_NORMALIZE)
#define KW_2 (WT_2/WT_NORMALIZE)
#define KW_3 (WT_3/WT_NORMALIZE)
#define KW_4 (WT_4/WT_NORMALIZE)
float Script : STANDARDSGLOBAL <
string UIWidget = "none";
string ScriptClass = "scene";
string ScriptOrder = "postprocess";
string ScriptOutput = "color";
string Script = "Technique=BloomExtract;"
"Technique=BloomCombine;";
> = 0.8;
float4 ClearColor
<
string UIWidget = "color";
string UIName = "Clear (Bg) Color";
> = {0,0,0,1.0};
float2 ViewportSize : VIEWPORTPIXELSIZE
<
string UIName="Screen Size";
string UIWidget="None";
>;
static float2 ViewportOffset = (float2(0.5,0.5)/ViewportSize);
texture g_texBase : RENDERCOLORTARGET
<
float2 ViewPortRatio = {1.0,1.0};
int MipLevels = 1;
string Format = "X8R8G8B8";
string UIWidget = "None";
>;
texture g_texBloomH : RENDERCOLORTARGET
<
float2 ViewPortRatio = {1.0,1.0};
int MipLevels = 1;
string Format = "X8R8G8B8";
string UIWidget = "None";
>;
texture g_texBloomHV : RENDERCOLORTARGET
<
float2 ViewPortRatio = {1.0,1.0};
int MipLevels = 1;
string Format = "X8R8G8B8";
string UIWidget = "None";
>;
texture DepthBuffer : RENDERDEPTHSTENCILTARGET
<
float2 ViewPortRatio = {1.0,1.0};
string Format = "D24S8";
string UIWidget = "None";
>;
float BloomThreshold = 0.9;
float BloomIntensity = 3.0;
float BaseIntensity = 1.0;
float BloomSaturation = 0.5;
float BaseSaturation = 1.0;
float g_bloomSpan <
string UIName = "Bloom Step Size (Texels)";
string UIWidget = "slider";
float UIMin = 0.2f;
float UIMax = 8.0f;
float UIStep = 0.5f;
> = 2.5f;
sampler g_sampBase =
sampler_state
{
Texture = <g_texBase>;
MipFilter = LINEAR;
MagFilter = LINEAR;
MipFilter = LINEAR;
};
sampler g_sampBloomH =
sampler_state
{
Texture = <g_texBloomH>;
AddressU = CLAMP;
AddressV = CLAMP;
MipFilter = POINT;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
sampler g_sampBloomHV =
sampler_state
{
Texture = <g_texBloomHV>;
AddressU = CLAMP;
AddressV = CLAMP;
MipFilter = POINT;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
void ScreenQuadVS( float3 Position : POSITION
, float2 UV : TEXCOORD0
, out float4 OUT_Position : POSITION
, out float2 OUT_UV : TEXCOORD0 )
{
OUT_Position = float4(Position, 1);
OUT_UV = UV;
}
// nine texcoords, to sample nine in-line texels
struct NineTexelVertex
{
float4 Position : POSITION;
float2 UV : TEXCOORD0;
float4 UV1 : TEXCOORD1; // xy AND zw used as UV coords
float4 UV2 : TEXCOORD2; // xy AND zw used as UV coords
float4 UV3 : TEXCOORD3; // xy AND zw used as UV coords
float4 UV4 : TEXCOORD4; // xy AND zw used as UV coords
};
// vertex shader to align blur samples vertically
NineTexelVertex vert9BlurVS(
float3 Position : POSITION,
float2 UV : TEXCOORD0
) {
NineTexelVertex OUT = (NineTexelVertex)0;
OUT.Position = float4(Position, 1);
float TexelIncrement = g_bloomSpan/ViewportSize.y;
float2 Coord = float2(UV.xy + ViewportOffset);
OUT.UV = Coord;
OUT.UV1 = float4(Coord.x, Coord.y + TexelIncrement,
Coord.x, Coord.y - TexelIncrement);
OUT.UV2 = float4(Coord.x, Coord.y + TexelIncrement*2,
Coord.x, Coord.y - TexelIncrement*2);
OUT.UV3 = float4(Coord.x, Coord.y + TexelIncrement*3,
Coord.x, Coord.y - TexelIncrement*3);
OUT.UV4 = float4(Coord.x, Coord.y + TexelIncrement*4,
Coord.x, Coord.y - TexelIncrement*4);
return OUT;
}
// vertex shader to align blur samples horizontally
NineTexelVertex horiz9BlurVS(
float3 Position : POSITION,
float2 UV : TEXCOORD0
) {
NineTexelVertex OUT = (NineTexelVertex)0;
OUT.Position = float4(Position, 1);
float TexelIncrement = g_bloomSpan/ViewportSize.x;
float2 Coord = float2(UV.xy + ViewportOffset);
OUT.UV = Coord;
OUT.UV1 = float4(Coord.x + TexelIncrement, Coord.y,
Coord.x - TexelIncrement, Coord.y);
OUT.UV2 = float4(Coord.x + TexelIncrement*2, Coord.y,
Coord.x - TexelIncrement*2, Coord.y);
OUT.UV3 = float4(Coord.x + TexelIncrement*3, Coord.y,
Coord.x - TexelIncrement*3, Coord.y);
OUT.UV4 = float4(Coord.x + TexelIncrement*4, Coord.y,
Coord.x - TexelIncrement*4, Coord.y);
return OUT;
}
float4 blur9PS(NineTexelVertex IN,
uniform sampler2D SrcSamp) : COLOR
{
float4 OutCol = tex2D(SrcSamp, IN.UV4.zw) * KW_4;
OutCol += tex2D(SrcSamp, IN.UV3.zw) * KW_2;
OutCol += tex2D(SrcSamp, IN.UV1.zw) * KW_1;
OutCol += tex2D(SrcSamp, IN.UV) * KW_0;
OutCol += tex2D(SrcSamp, IN.UV1.xy) * KW_1;
OutCol += tex2D(SrcSamp, IN.UV2.xy) * KW_2;
OutCol += tex2D(SrcSamp, IN.UV3.xy) * KW_3;
OutCol += tex2D(SrcSamp, IN.UV4.xy) * KW_4;
return OutCol;
}
// Helper for modifying the saturation of a color.
float4 AdjustSaturation(float4 color, float saturation)
{
// The constants 0.3, 0.59, and 0.11 are chosen because the
// human eye is more sensitive to green light, and less to blue.
float grey = dot(color, float3(0.3, 0.59, 0.11));
return lerp(grey, color, saturation);
}
float4 BloomExtract_PS(float2 texCoord : TEXCOORD0) : COLOR0
{
// ======== ORIG ============
// Look up the original image color.
// float4 c = tex2D(g_sampBase, texCoord);
// Adjust it to keep only values brighter than the specified threshold.
// return saturate((c - BloomThreshold) / (1 - BloomThreshold));
// ==========================
// DeepFar 05 24 :
// For now we are using Floating Point Texture
// there is no need to saturate the color
// we just need to ensure no negative number here
return float4( max( tex2D(g_sampBase, texCoord).xyz - BloomThreshold, 0), 1.0f );
}
float4 BloomCombine_PS(float2 texCoord : TEXCOORD0) : COLOR0
{
// ============== ORIG ======================
// Look up the bloom and original base image colors.
float4 bloom = tex2D(g_sampBloomHV, texCoord);
float4 base = tex2D(g_sampBase, texCoord);
// Adjust color saturation and intensity.
bloom = AdjustSaturation(bloom, BloomSaturation) * BloomIntensity;
base = AdjustSaturation(base, BaseSaturation) * BaseIntensity;
// Darken down the base image in areas where there is a lot of bloom,
// to prevent things looking excessively burned-out.
// base *= (1 - saturate(bloom));
// Combine the two images.
return base + bloom;
// ==========================================
}
technique BloomExtract
<
string Script =
"RenderColorTarget0=g_texBase;"
//"RenderDepthStencilTarget0=DepthBuffer;"
"ClearSetColor=ClearColor;"
"ClearSetDepth=ClearDepth;"
"Clear=Color;"
"Clear=Depth;"
"ScriptExternal=color;"
"Pass=Extract;"
"Pass=BlurH;"
"Pass=BlurV;";
>
{
pass Extract
<
string Script =
"RenderColorTarget0=g_texBloomHV;"
"RenderDepthStencilTarget0=DepthBuffer;"
"ClearSetColor=ClearColor;"
"ClearSetDepth=ClearDepth;"
"Clear=Color;"
"Clear=Depth;"
"Draw=Buffer;";
>
{
VertexShader = compile vs_2_0 ScreenQuadVS();
cullmode = none;
ZEnable = false;
ZWriteEnable = false;
AlphaBlendEnable = false;
PixelShader = compile ps_2_0 BloomExtract_PS();
}
pass BlurH
<
string Script =
"RenderColorTarget0=g_texBloomH;"
"RenderDepthStencilTarget0=DepthBuffer;"
"Draw=Buffer;";
>
{
VertexShader = compile vs_2_0 horiz9BlurVS();
cullmode = none;
ZEnable = false;
ZWriteEnable = false;
AlphaBlendEnable = false;
PixelShader = compile ps_2_0 blur9PS(g_sampBloomHV);
}
pass BlurV
<
string Script =
"RenderColorTarget0=g_texBloomHV;"
"RenderDepthStencilTarget0=DepthBuffer;"
"Draw=Buffer;";
>
{
VertexShader = compile vs_2_0 vert9BlurVS();
cullmode = none;
ZEnable = false;
ZWriteEnable = false;
AlphaBlendEnable = false;
PixelShader = compile ps_2_0 blur9PS(g_sampBloomH);
}
}
technique BloomCombine
<
string Script =
"Pass=Pass0;";
>
{
pass Pass0
<
string Script =
"RenderColorTarget0=;"
"RenderDepthStencilTarget0=;"
"ClearSetColor=ClearColor;"
"ClearSetDepth=ClearDepth;"
"Clear=Color;"
"Clear=Depth;"
"Draw=Buffer;";
>
{
cullmode = none;
ZEnable = false;
ZWriteEnable = false;
AlphaBlendEnable = false;
VertexShader = compile vs_2_0 ScreenQuadVS();
PixelShader = compile ps_2_0 BloomCombine_PS();
}
}
clayman:
你说的这个叫做 stripting annotation
本来是dxsas 0.8的一部分,可惜到1.0以后,被ms从标准里删除了
不过并不影响使用,因为dxsas里的stripting annotation实际只定义了一套标准脚本的格式和语法,以便不同程序可以解析相同的脚本,如果不考虑跨程序应用,完全可以定义一套自己的脚本格式。
实际的脚本解析,dxsas是没有做的,需要你自己编写代码来处理
基本思路是用string类型的annotation来记录脚本,比如
technique R2T
{
pass P0
<
string Script = "RenderColorTarget0 = RenderTargetTexture;"
"ClearSetColor = clearClor;"
>
{........}
}
你的c++程序发现annotation的名称是script时,就说明后面所更的是脚本
大部分脚本都以 xx = xx的方式出现,外加几条有限的指令,所以实现解析还是不太难
fx composer应该就是这样做的
不幸的是关于stripting annotation,可以找到的资料非常少,就连dx sdk里也几乎没有说:(
你可以把nvidia的dxsas标准找来看看
另外,如果你有机会看到shaderx4,那么里面有一篇叫post-processing effects scripting的文章有比较详细的讲解
good luck
clayman
另外说一下,虽然effect可以设置渲染状态,比如
cullmode = none;
ZEnable = false;
ZWriteEnable = false;
AlphaBlendEnable = false;
但最好不要使用这个功能,原因之一就是会让你的程序很难debug,当你有大量物体时,渲染状态出错以后,你的C++代码完全无法知道是哪个物体破坏或者说修改了渲染状态
tonykee
意思是说这些状态最好是在shader之外程序代码中设置了对吧
好像很有道理,值得采纳。
leftnoteasy
非常感谢clayman兄的耐心解答,这个问题我也比较明白了,原来是各个显卡公司为了在自己的工具上能够正常运行而设计的程序,而ms并没有完全支持,我非常看好这一块,如果DirectX能够很好的支持或者扩展DXSAS,那shader的编写就会大大的方便了