LeGreg | On ne s'est pas trop interesse a la question
parce qu'on cherche a avoir une solution qui soit
cross platform (au moins offrir une interface commune aux programmeurs des differentes plateformes).
Le support des pixel shaders n'est pas a l'ordre du jour (pour ce qui est du "fragment linker" de DirectX9).
Citation :
Fragment Linking
Fragment linking is a new shader management feature introduced in D3DX9.
Fragment linking is a way of building a shader out of smaller partial
shaders, known as shader fragments. Shader fragments are specified by
either assembly code blocks or high level shading language (HLSL) functions.
Fragment linking is designed to be light enough weight to be used at
run-time, unlike re-compilation. The goal is to provide many of the
benefits that could be gained by recompilation but in a runtime friendly
manner.
The included sample file is a set of shader fragments that can be used
to generate a glow shader. The glow shader is generated by using one of the
tranformation fragments and one "Glow" fragment. Using the provided
fragments, either a skinned glow shader or a unskinned glow shader can be
generated. Both assembly and HLSL fragments are provided to demonstrate
that linking is possible between mixed types of fragments.
Assembly fragments are defined by using descriptive names instead of
registers. There are three types of registers that need to be accessed via
name: temp registers (r0), input registers (v0), and constant registers(c0).
Each register name must be prefixed by a character to identify the register
bank for each name: all constants must start with 'c_', all temp registers
with 'r_', and all input registers with 'v_'. Constants are also special in
that the name, minus the 'c_', must be defined as a global variable in order
to provide type information. Inputs are also different in that the name
after the 'v_' must map to a semantic usage/usage index name. i.e.
v_TEXCOORD2. Temp registers have no name requirements other than name
prefix of 'r_'. All temp registers with the same name have the same "value".
All Register allocation, constant table allocation, input definitions,
etc. are deferred until fragment link time. The linker also does some basic
optimizations during the link phase. Dead code is detected and removed and
register allocation is performed.
HLSL fragments are very similar to a standard vertex shader top-level
entry point. Each paramenter must have either a semantic or be a uniform
parameter with values provided by the compile_fragment statement. The only
difference is that it is possible to specify a new type of semantic that is
used to values between shader fragments. Any semantic beginning with a 'r_'
is treated as input/output to other shaders. i.e. by specifying "in float3
r_Position", the fragment specifies that a preceding fragment must specify a
value for r_Position for this fragment to use.
(NOTE: Beta 2 limitation! Please see the comment in the included
sample file for info on the HLSL fragment Beta 2 validation bug)
Names are associated with fragments in a source file by declaring a
vertexfragment variable that has a value of either an asm_fragment block or
the output of a compile_fragment statement. When calling
D3DXAssembleFragments (D3DXGatherFragments in final DX9), all
vertexfragment variables defined in the source file are added to the
returned buffer. The shader fragment buffer is then passed to the
fragment linker by the AddFragments method. Each fragment in
the buffer is added to the list of available fragments for linking.
|
et voici l'exemple en question:
Code :
- // static consts are equivalent to DEFs for ASM Fragments
- static const float4 vDisplace = { 2, 2, 2, 2};
- static const float4 One = 1.0f;
- float4x4 mWorldView;
- float4x4 mProjection;
- float4 vGlowColor;
- float4x3 mWorld1;
- float4x3 mWorld2;
- float4x3 mWorld3;
- float4x3 mWorld4;
- vertexfragment TransformUnskinnedAsm =
- asm_fragment
- {
- vs_1_1
- m4x3 r_TransformedPosition, v_POSITION, c_mWorldView
- m3x3 r_TransformedNormal, v_NORMAL, c_mWorldView
- };
- vertexfragment ComputeGlowAsm =
- asm_fragment
- {
- vs_1_1
- // normalize normal
- dp3 r_Length.w, r_TransformedNormal.xyz,r_TransformedNormal.xyz
- rsq r_Length.w, r_Length.w
- mul r_TransformedNormal.xyz, r_TransformedNormal.xyz, r_Length.www
- mov r_Temp.x, c_One.x
- mad r_Power.z, r_TransformedNormal.z, -r_TransformedNormal.z, c_One.x
- mul r_Power.z, r_Power.z, r_Power.z
- mul oD0, c_vGlowColor, r_Power.z
- mad r_TransformedPosition.xyz, r_TransformedNormal.xyz, c_vDisplace.xxx, r_TransformedPosition.xyz
- mov r_TransformedPosition.w, c_One.x
- m4x4 oPos, r_TransformedPosition, c_mProjection
- };
- // NOTE: while HLSL fragments are supported by DX9 Beta 2, there was a last minute validation bug
- // that dramatically hinders their use. All Beta 2 HLSL fragments must contain
- // a POSITION field that is written to. If you add this to all HLSL fragments
- // they will pass validation and dead code removal will remove the redundant writes
- // I RECOMMEND that you wait for Beta 3 where it all just works though.
- #if 0
- // helper function to transform position/normal into view space
- void TransformUnskinned
- (
- float4 vPos : POSITION,
- float3 vNormal : NORMAL,
- out float3 vTransformedPosition : r_TransformedPosition,
- out float3 vTransformedNormal : r_TransformedNormal
- )
- {
- // Transform the position into view space
- vTransformedPosition = mul(vPos, mWorldView);
-
- // Tranform the normal into view space (just use the upper 3x3 of WorldView)
- vTransformedNormal = mul(vNormal, (float3x3)mWorldView);
- }
- vertexfragment TransformUnskinnedHLSL = compile_fragment vs_1_1 TransformUnskinned();
- // helper function to tranform position and normal as non-indexed blending into world space
- void TransformSkinned
- (
- float4 vPos : POSITION,
- float3 vBlendWeights : BLENDWEIGHT,
- float3 vNormal : NORMAL,
- out float3 vTransformedPosition : r_TransformedPosition,
- out float3 vTransformedNormal : r_TransformedNormal
- )
- {
- // compute the 4th blend weight from the other three
- float fFourthBlendWeight = 1.0 - (vBlendWeights.x + vBlendWeights.y + vBlendWeights.z);
-
- // transform the position/normal into world space using the first matrix
- vTransformedPosition = mul(vPos, mWorld1) * vBlendWeights.x;
- vTransformedNormal = mul(vNormal, (float3x3)mWorld1) * vBlendWeights.x;
-
- // transform the position/normal into world space using the second matrix
- vTransformedPosition += mul(vPos, mWorld2) * vBlendWeights.y;
- vTransformedNormal += mul(vNormal, (float3x3)mWorld2) * vBlendWeights.y;
- // transform the position/normal into world space using the third matrix
- vTransformedPosition += mul(vPos, mWorld3) * vBlendWeights.z;
- vTransformedNormal += mul(vNormal, (float3x3)mWorld3) * vBlendWeights.z;
- // transform the position/normal into world space using the fourth matrix
- vTransformedPosition += mul(vPos, mWorld4) * fFourthBlendWeight;
- vTransformedNormal += mul(vNormal, (float3x3)mWorld4) * fFourthBlendWeight;
-
- // assuming input normal is not normalized, otherwise this usually isn't necessary
- vTransformedNormal /= length(vTransformedNormal);
- }
- vertexfragment TransformSkinnedHLSL = compile_fragment vs_1_1 TransformSkinned();
- void ComputeGlow
- (
- float3 vTransformedPosition : r_TransformedPosition,
- float3 vTransformedNormal : r_TransformedNormal,
- out float4 Position : POSITION,
- out float4 Diffuse : COLOR
- )
- {
- float fPower;
- vTransformedNormal /= length(vTransformedNormal);
- vTransformedPosition += vTransformedNormal * vDisplace.x;
-
- // determine the strength of the color of the glow by the normal direction
- fPower = vTransformedNormal.z * -vTransformedNormal.z + 1.0f;
- fPower *= fPower;
-
- // tranform position into screen space from view space
- Position = mul(float4(vTransformedPosition, 1.0), mProjection);
-
- // output color is the compute power times the glow color
- Diffuse = vGlowColor * fPower;
- }
- vertexfragment ComputeGlowHLSL = compile_fragment vs_1_1 ComputeGlow();
- #endif
|
LeGreg ---------------
voxel terrain render engine | animation mentor
|