世界空间中的着色器(关于 uniforms)
2016-08-18 15:30
239 查看
从对象空间到世界空间的转变
转载地址:http://www.omuying.com/article/91.aspx
原文链接:http://en.wikibooks.org/wiki/Cg_Programming/Unity/Shading_in_World_Space
在《在着色器中调试》章节中提到,顶点输入参数使用语义词 POSITION 指定对象的坐标,即本地对象(模型)的网格空间坐标,对象空间(对象的坐标系统)是特定于每个游戏对象的,然而,所有的游戏对象会被转换到一个共同的坐标系中(世界空间)。
如果一个对象被直接放入世界空间中,游戏对象会通过转换组件直接将对象的坐标转成世界坐标。你可以在 Scene 视图或者 Hierarchy 视图中选中一个对象,然后在 Inspector 视图中查看 Transform 组件。在 Transform 组件中包括 Position、Rotation 和 Scale 属性,这个组件用来指定从本地坐标到世界坐标的顶点转换(如果一个游戏对象拥有父级对象,那么转换组件只转换父级对象的坐标)。在《Vertex
Transformations》章节中,我们将讨论顶点的转换、旋转、缩放以及 4 x 4 矩阵组合变换的细节。
回到我们的例子中:从对象空间到世界空间的转换是通过 4 x 4 矩阵来转换的,也叫“模型矩阵”,这个矩阵在 Unity 中通过 uniform 参数 _Object2World 已经声明了:
Shader "Custom/World Space"
{
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//uniform flaot4*4 Object3World
//automatic definition of a Unity-specific uniform parameter 自动定义统一值是unity的一个特性
struct vertexOutput
{
float4 pos: SV_POSITION;
float4 position_in_world_space : TEXCOORD0;
};
vertexOutput vert(float4 vertex:POSITION)
{
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP,vertex);
output.position_in_world_space = mul(_Object2World,vertex);//物体坐标转化为世界坐标
return output;
}
float4 frag(vertexOutput input) :COLOR
{
float dist = distance(input.position_in_world_space,float4(0.0,0.0,0.0,1.0)); //计算片段位置与原点距离(第四个坐标永远是1)
if (dist < 5.0)
{
return float4(0.0, 1.0, 0.0, 1.0); //接近
}
else
return float4(0.3,0.3,0.3,1.0);//远离原点
}
ENDCG
}
}
}
更多的 Unity Uniforms
在 Unity 中,定义了几个和 _Object2World 一样的 float4x4 矩阵,下面是在系列教程中使用的 uniforms 简短列表:
用户指定 Uniforms:着色器属性
还有一个更重要的 uniform 参数:用户自定义的 uniforms。实际上,这是 Unity 的属性,你可以认为他们是着色器的用户自定义 uniform 参数。通常一个着色器不带参数只能由编写的程序员在一些特定的程序中使用,但是如果一个着色器拥有参数并且还带有描述性的说明,那么这个着色器就可以被其他人使用,另外,如果你打算出售你的着色器,为着色器的提供参数会大大增加它的价值。
因为在 Unity 的 ShaderLab 中使用《description of shader properties 》非常不错,通过下面的例子我们来了解如何使用着色器属性,首先,我们声明一个属性,然后我们再定义一个与属性名称相同、类型相同的
uniforms 。
使用 sharedMaterial 我们可以改变所有使用了这个材质的对象的参数,如果你只希望改变一个并使用了这个材质的对象的参数,那么你应该使用 material 。假如你设置 _Point 属性为另一个对象的位置信息,这样你只需要在
Unity 中移动这个对象就可以查看效果了,你可以复制/粘贴 下面的代码到一个 C# 脚本中:
然后我们只需要移动另一个对象(Sphere)就可以看到(Cube)颜色的变化,当小球离原点近时,如图:
当小球离原点远时,如图:
转载地址:http://www.omuying.com/article/91.aspx
原文链接:http://en.wikibooks.org/wiki/Cg_Programming/Unity/Shading_in_World_Space
在《在着色器中调试》章节中提到,顶点输入参数使用语义词 POSITION 指定对象的坐标,即本地对象(模型)的网格空间坐标,对象空间(对象的坐标系统)是特定于每个游戏对象的,然而,所有的游戏对象会被转换到一个共同的坐标系中(世界空间)。
如果一个对象被直接放入世界空间中,游戏对象会通过转换组件直接将对象的坐标转成世界坐标。你可以在 Scene 视图或者 Hierarchy 视图中选中一个对象,然后在 Inspector 视图中查看 Transform 组件。在 Transform 组件中包括 Position、Rotation 和 Scale 属性,这个组件用来指定从本地坐标到世界坐标的顶点转换(如果一个游戏对象拥有父级对象,那么转换组件只转换父级对象的坐标)。在《Vertex
Transformations》章节中,我们将讨论顶点的转换、旋转、缩放以及 4 x 4 矩阵组合变换的细节。
回到我们的例子中:从对象空间到世界空间的转换是通过 4 x 4 矩阵来转换的,也叫“模型矩阵”,这个矩阵在 Unity 中通过 uniform 参数 _Object2World 已经声明了:
Shader "Custom/World Space"
{
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//uniform flaot4*4 Object3World
//automatic definition of a Unity-specific uniform parameter 自动定义统一值是unity的一个特性
struct vertexOutput
{
float4 pos: SV_POSITION;
float4 position_in_world_space : TEXCOORD0;
};
vertexOutput vert(float4 vertex:POSITION)
{
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP,vertex);
output.position_in_world_space = mul(_Object2World,vertex);//物体坐标转化为世界坐标
return output;
}
float4 frag(vertexOutput input) :COLOR
{
float dist = distance(input.position_in_world_space,float4(0.0,0.0,0.0,1.0)); //计算片段位置与原点距离(第四个坐标永远是1)
if (dist < 5.0)
{
return float4(0.0, 1.0, 0.0, 1.0); //接近
}
else
return float4(0.3,0.3,0.3,1.0);//远离原点
}
ENDCG
}
}
}
更多的 Unity Uniforms
在 Unity 中,定义了几个和 _Object2World 一样的 float4x4 矩阵,下面是在系列教程中使用的 uniforms 简短列表:
uniform float4 _Time, _SinTime, _CosTime; // time values uniform float4 _ProjectionParams; // x = 1 or -1 (-1 if projection is flipped) // y = near plane; z = far plane; w = 1/far plane uniform float4 _ScreenParams; // x = width; y = height; z = 1 + 1/width; w = 1 + 1/height uniform float4 unity_Scale; // w = 1/scale; see _World2Object uniform float3 _WorldSpaceCameraPos; uniform float4x4 _Object2World; // model matrix uniform 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/range uniform float4 _WorldSpaceLightPos0; // position or direction of light source uniform float4x4 UNITY_MATRIX_MVP; // model view projection matrix uniform float4x4 UNITY_MATRIX_MV; // model view matrix uniform float4x4 UNITY_MATRIX_V; // view matrix uniform float4x4 UNITY_MATRIX_P; // projection matrix uniform float4x4 UNITY_MATRIX_VP; // view projection matrix uniform float4x4 UNITY_MATRIX_T_MV; // transpose of model view matrix uniform float4x4 UNITY_MATRIX_IT_MV; // transpose of the inverse model view matrix uniform float4x4 UNITY_MATRIX_TEXTURE0; // texture matrix uniform float4x4 UNITY_MATRIX_TEXTURE1; // texture matrix uniform float4x4 UNITY_MATRIX_TEXTURE2; // texture matrix uniform float4x4 UNITY_MATRIX_TEXTURE3; // texture matrix uniform float4 UNITY_LIGHTMODEL_AMBIENT; // ambient color
用户指定 Uniforms:着色器属性
还有一个更重要的 uniform 参数:用户自定义的 uniforms。实际上,这是 Unity 的属性,你可以认为他们是着色器的用户自定义 uniform 参数。通常一个着色器不带参数只能由编写的程序员在一些特定的程序中使用,但是如果一个着色器拥有参数并且还带有描述性的说明,那么这个着色器就可以被其他人使用,另外,如果你打算出售你的着色器,为着色器的提供参数会大大增加它的价值。
因为在 Unity 的 ShaderLab 中使用《description of shader properties 》非常不错,通过下面的例子我们来了解如何使用着色器属性,首先,我们声明一个属性,然后我们再定义一个与属性名称相同、类型相同的
uniforms 。
Shader "Cg shading in world space" { Properties { _Point ("a point in world space", Vector) = (0., 0., 0., 1.0) _DistanceNear ("threshold distance", Float) = 5.0 _ColorNear ("color near to point", Color) = (0.0, 1.0, 0.0, 1.0) _ColorFar ("color far from point", Color) = (0.3, 0.3, 0.3, 1.0) } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" // defines _Object2World and _World2Object // uniforms corresponding to properties uniform float4 _Point; uniform float _DistanceNear; uniform float4 _ColorNear; uniform float4 _ColorFar; struct 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); return output; } float4 frag(vertexOutput input) : COLOR { float dist = distance(input.position_in_world_space, _Point); // computes the distance between the fragment position // and the position _Point. if (dist < _DistanceNear) { return _ColorNear; } else { return _ColorFar; } } ENDCG } } }
使用 sharedMaterial 我们可以改变所有使用了这个材质的对象的参数,如果你只希望改变一个并使用了这个材质的对象的参数,那么你应该使用 material 。假如你设置 _Point 属性为另一个对象的位置信息,这样你只需要在
Unity 中移动这个对象就可以查看效果了,你可以复制/粘贴 下面的代码到一个 C# 脚本中:
using UnityEngine; using System.Collections; [ExecuteInEditMode] public class NewBehaviourScript : MonoBehaviour { public GameObject other; void Update() { if(other != null) { GetComponent<Renderer>().sharedMaterial.SetVector("_Point", other.transform.position); } } }
然后我们只需要移动另一个对象(Sphere)就可以看到(Cube)颜色的变化,当小球离原点近时,如图:
当小球离原点远时,如图:
相关文章推荐
- Cg Programming/Unity/Shading in World Space世界空间中的着色器
- 2.1.4 Shading in World Space (about uniforms) 在世界坐标系里着色(关于uniforms参数)
- 关于北京建设世界城市就业空间结构研究思路
- 关于 法向量 的世界空间变换矩阵
- 关于虚拟空间IIS无法配置rails的映射
- 关于Windows内核空间操作的一些说明
- 世界空间的法线映射
- 关于人、世界、精神、物质的一种思考(你不要将它当真啦^_^)
- 在这样的世界里,没人会不头晕的--关于最近的.net信任危机事件
- 关于用"独立存贮空间"存数据存在的问题
- [转]关于VC中动态申请空间大小查看的方法
- 关于xhtml中的命名空间
- 关于工作空间, ShapeFile工作空间,图元工作空间,图元类
- 关于Windows内核空间操作的一些说明
- [一篇好文章]关于索引重用空间的总结测试
- 关于栈和堆中分配空间小结
- [精华] [转帖]关于tempdb的优化---保证足够的 TempDB 空间
- C++ 第三篇 关于预处理器指示符和命名空间
- 关于xml的命名空间(转自国外一blog)
- Java和.Net 在较量中携手前进,关于2者之间的比较,几篇文章还概要性地对这2家人的世界做了介绍,是时候同时对java世界进行些了解了