翻译 Cg Program in Unity - 1.4 Shading in World Space (一)

来源:互联网 发布:thinkcell mac 编辑:程序博客网 时间:2024/05/29 18:08

这章教程要我们会介绍uniform parameters.不过他需要一些前几章的知识,所以需要你看完了前几章.

我们将在shader中改变fragment color,让他的颜色基于他所在的世界坐标系中位置.这个概念并不复杂;不管怎样,这有非常重要的应用,例如光线和环境的遮罩(不确定是不是这个意思)。我们也将想想如何给非程序员使用你的shader。 

从对象空间变化到世界空间(Transforming from Object to World Space)

之前一章提到过,vertex input parameter有使用到语义POSITION来指定对象空间,即网格物体或者说对象自己的局部坐标系。每一个物体的对象空间(或者叫对象坐标系)都是特定的;但任何情况下,所有游戏中物体都可以被放置于一个统一的坐标系中,我们称它为世界空间。
如果一个物体被直接放入到世界空间中,那么这个从对象到世界空间的转换将由物体上的Transform组件来完成。如果你想看到它,你可以去Scene View或者Hierarchy View中找到物体,然后再Inspector窗体上找到Transform组件(这里就不详细描述这个组件了)。如果一个对象是一个对象组的一部分,那么你在Transform组件的看到的它的坐标就是它在它的父对象的对象空间中的坐标。关于顶点的平移,选择和缩放以及这3中操作的组合操作,我们一般都将它们用一个4*4的矩阵来代替,详细的信息将在之后的“Vertex Transformation”中讲到。
回到我们的标题,这里举一个例子:我们把从对象空间到世界空间的转换信息放入一个4*4的矩阵,这个矩阵也被叫做“model矩阵”(因为这个转换也被叫做“model转化”)。这个矩阵可以从一个名为_Ojbect2World的uniform parameter中获得,而这个变量的值是由Unity自动定义的:
uniform float4x4 _Object2World;
因为这个变量是自动定义的,我们就不需要定义它啦(实际上是我们不应该去定义它)。下面我们可以看看我们如何在shader中直接去使用它(无需定义):
Shader "Cg shading in world space" {SubShader {Pass {CGPROGRAM#pragma vertex vert#pragma fragment frag// uniform float4x4 _Object2World;// automatic definition of a Unity-specific uniform parameterstruct vertexInput {float4 vertex : POSITION;};struct vertexOutput {float4 pos : SV_POSITION;float4 position_in_world_space : TEXCOORD0;};vertexOutput vert(vertexInput input){vertexOutput output;output.pos = mul(UNITY_MATRIX_MVP, input.vertex);output.position_in_world_space = mul(_Object2World, input.vertex);// transformation of input.vertex from object// coordinates to world coordinates;return output;}float4 frag(vertexOutput input) : COLOR{float dist = distance(input.position_in_world_space, float4(0.0, 0.0, 0.0, 1.0));// computes the distance between the fragment position// and the origin (the 4th coordinate should always be// 1 for points).if (dist < 5.0){return float4(0.0, 1.0, 0.0, 1.0);// color near origin}else{return float4(0.3, 0.3, 0.3, 1.0);// color far from origin}}ENDCG}}}
通常来说,应用程序要去设置uniform parameters;不管怎样,Unity已经帮我们设置了uniform parameter的值,所以我们就不必担心了。
上面这个shader把vertex position转换为world space,然后通过output结构体把他传递给了fragment shader。对fragment shader来说,output结构体包含了fragment在世界空间中的插值位置(interpolate position)。然后我们在基于他到世界坐标系原点的位置来给他赋上不同的颜色。所以,如果你移动这个物体,那么在他靠近原点是会变绿,而离开原点会变成灰色。

更多的Unity-Specific Uniform

我们还有一系列的内置的Uniform parameter,他们都和之前提到的float4*4矩阵_Object2World一样会自动被Unity定义.下面有一个简短的表格来展示在接下来的教程中会使用哪些变量:
uniform float4 _Time, _SinTime, _CosTime; // time valuesuniform float4 _ProjectionParams;// x = 1 or -1 (-1 if projection is flipped)// y = near plane; z = far plane; w = 1/far planeuniform float4 _ScreenParams;// x = width; y = height; z = 1 + 1/width; w = 1 + 1/heightuniform float4 unity_Scale; // w = 1/scale; see _World2Objectuniform float3 _WorldSpaceCameraPos;uniform float4x4 _Object2World; // model matrixuniform float4x4 _World2Object; // inverse model matrix// (all but the bottom-right element have to be scaled// with unity_Scale.w if scaling is important)uniform float4 _LightPositionRange; // xyz = pos, w = 1/rangeuniform float4 _WorldSpaceLightPos0;// position or direction of light sourceuniform float4x4 UNITY_MATRIX_MVP; // model view projection matrixuniform float4x4 UNITY_MATRIX_MV; // model view matrixuniform float4x4 UNITY_MATRIX_P; // projection matrixuniform float4x4 UNITY_MATRIX_T_MV;// transpose of model view matrixuniform float4x4 UNITY_MATRIX_IT_MV;// transpose of the inverse model view matrixuniform float4x4 UNITY_MATRIX_TEXTURE0; // texture matrixuniform float4x4 UNITY_MATRIX_TEXTURE1; // texture matrixuniform float4x4 UNITY_MATRIX_TEXTURE2; // texture matrixuniform float4x4 UNITY_MATRIX_TEXTURE3; // texture matrixuniform float4 UNITY_LIGHTMODEL_AMBIENT; // ambient color
对于这些变量,详细的情况可以看Unity官方手册中的“ShaderLab builtin values”。这些变量大多定义在UnityShaderVariables.cginc文件中,它被UnityCG..cginc引用(这2个文件都在文件夹CGIncludes中).在Unity4.0之前我们还需要手动的在shader中#include "UnityCG.cginc",不过在更新的版本中这不是必须的了。
但是这里还有一个写其他的内置Uniform,他们是不会被自动定义的,比如说 _LightColor0.因为,我们在使用它之前需要显示的去定义它:
uniform float4 _LightColor0;
Unity也不是什么时候都会去更新这些Uniform.实际上,_WorldSpaceLightPos0和_LightColor0仅仅在shader passes中的tagged的值是适当的值时才会被赋值.比如说,在Pass{...}的第一行tags中有一个标签是{"LightMode" = "ForwardBase"}。 详细的信息请看“Diffuse Reflection”。




0 0
原创粉丝点击