TOC: Of Effects and Shaders
Back: Vertex Data
Next: Geometry Morphing
VVVV有一个帮助的模版来显示模型网格上的面法线:Normals (EX9)
我们能够修改这个帮助的程序片来使模型网格上的面法线更好的显示出来:
在你把模型网格传递到着色器之前,如果你的模型网格没有储存法线你可以使用Normals (EX9.Geometry Mesh)这个节点在程序片中计算出来使用Smoothing Angle引脚在顶点位置平均化法线。
因为大多数的着色模型(如phone)在视点空间中需要法线,它得随着顶点的位置变换法线。但是你要注意法线是一个3位浮点数,如果它是4位浮点数的话,那法线上的第4位w元素的是0(而不是对于位置来说的1),这个元素仅获取旋转的值,而不是移动值。一个典型的顶点着色器做如下的转换:
... //normal in view space Out.NormV = normalize(mul(NormO, tWV)); //position (projected) Out.PosWVP = mul(PosO, tWVP); ...
像我们在"抖动先生“或函数打印这两个教程里一样,如果你在顶点着色其中改变顶点的位置这会变得更加复杂。因为顶点的位置移动改变了表面的曲率,前面在模型网格中储存的法线将不在有用。因此着色计算就会出错。
因此,如果你需要在像素着色器中计算灯光,你就必须找到一个方法从新计算法线。但是这是一个十分具体的问题,它取决于你移动顶点位置使用的方法。
大多数通常的情况,不是如此精确的方法去获得新的顶点法线的位置是计算另外两个附近的点,获得两个向量,它们的正切面与这个顶点不是平行的。从这个两个正切的向量你能够通过叉积计算法线的位置:
使用圆锥的例子函数打印如下:
float NeighbourOffset = 0.001; vs2ps VS( float4 PosO : POSITION, float4 TexCd : TEXCOORD0) { //declare output struct vs2ps Out; //calc new position float3 p = Cone(PosO.xy); //calc neighbour pos in u direction float3 n1 = Cone(PosO.xy + float2(NeighbourOffset, 0)); //calc neighbour pos in v direction float3 n2 = Cone(PosO.xy + float2(0, NeighbourOffset)); //get tangent vector 1 float3 t1 = p - n1; //get tangent vector 2 float3 t2 = p - n2; //get normal float3 NormO = cross(t1, t2); //set new pos PosO.xyz = p; ...
现在,为了实际的使用法线我们可以以Phong函数为例,这个可以在vvvv的effects文件夹PhongDirectional.fxh文件中找到。为此拷贝这个文件除了你的着色器,然后看一看PhongDirectional.fx着色器,去提取必要的命令行使得phone着色器能够运行。我们需要把法线,灯光,视角都放进视点空间,让后把它们在vs2ps结构中都传递到像素着色器里。让我们同样拷贝材质的代码去得到一个很好的着色设定,这里你仅仅需要使用所有的uv-参数表面(你可以在网找到)替换圆锥的函数:
// ---------------------------------------------------------------------------- // PARAMETERS: // ---------------------------------------------------------------------------- //transforms float4x4 tW: WORLD; //the models world matrix as via the shader float4x4 tV: VIEW; //view matrix as set via Renderer (EX9) float4x4 tP: PROJECTION; //projection matrix as set via Renderer (EX9) float4x4 tWV : WORLDVIEW; float4x4 tWVP: WORLDVIEWPROJECTION; //all 3 premultiplied //texture transformation marked with semantic TEXTUREMATRIX //to achieve symmetric transformations float4x4 tTex: TEXTUREMATRIX <string uiname="Texture Transform";>; //texture texture Tex <string uiname="Texture";>; sampler Samp = sampler_state //sampler for doing the texture-lookup { Texture = (Tex); //apply a texture to the sampler MipFilter = LINEAR; //sampler states MinFilter = LINEAR; MagFilter = LINEAR; }; //the data structure: "vertexshader to pixelshader" //used as output data of the VS function //and as input data of the PS function struct vs2ps { float4 Pos : POSITION; float2 TexCd : TEXCOORD0; float3 LightDirV: TEXCOORD1; float3 NormV: TEXCOORD2; float3 ViewDirV: TEXCOORD3; }; #include "PhongDirectional.fxh" // ---------------------------------------------------------------------------- // VERTEXSHADERS // ---------------------------------------------------------------------------- #define twopi 6.28318531 float2 Scale = 1; float2 Offset = 0; float3 Cone(float2 uv) { uv *= Scale; uv += Offset; float u = uv.x * twopi; float v = uv.y; float3 newPos; newPos.x = v * cos(u); newPos.y = v * sin(u); newPos.z = v; return newPos; } float NeighbourOffset = 0.001; vs2ps VS( float4 PosO : POSITION, float4 TexCd : TEXCOORD0) { //declare output struct vs2ps Out; //calc new position float3 p = Cone(PosO.xy); //calc neighbour pos in u direction float3 n1 = Cone(PosO.xy + float2(NeighbourOffset, 0)); //calc neighbour pos in v direction float3 n2 = Cone(PosO.xy + float2(0, NeighbourOffset)); //get tangent vector 1 float3 t1 = p - n1; //get tangent vector 2 float3 t2 = p - n2; //get normal float3 NormO = cross(t1, t2); //set new pos PosO.xyz = p; //put normal in view space and normalize it Out.NormV = normalize(mul(NormO, tWV)); //inverse light direction in view space Out.LightDirV = normalize(-mul(lDir, tV)); //inverse view dir in view space Out.ViewDirV = -normalize(mul(PosO, tWV)); //transform position (projected) Out.Pos = mul(PosO, tWVP); //transform texturecoordinates Out.TexCd = mul(TexCd, tTex); return Out; } // ---------------------------------------------------------------------------- // PIXELSHADERS // ---------------------------------------------------------------------------- float Alpha <float uimin=0.0; float uimax=1.0;> = 1; float4 PS(vs2ps In) : COLOR { float4 col = tex2D(Samp, In.TexCd); col.rgb *= PhongDirectional(In.NormV, In.ViewDirV, In.LightDirV); col.a *= Alpha; return col; } // ---------------------------------------------------------------------------- // TECHNIQUES: // ---------------------------------------------------------------------------- technique TFunctionWithPhong { pass P0 { VertexShader = compile vs_1_1 VS(); PixelShader = compile ps_2_0 PS(); } }
TOC: Of Effects and Shaders
Back: Vertex Data
Next: Geometry Morphing
anonymous user login
~3d ago
~10d ago
~10d ago
~11d ago
~24d ago
~1mth ago
~1mth ago
~1mth ago
~1mth ago
~2mth ago