地址
https://en.wikibooks.org/wiki/Cg_Programming/Unity/Shading_in_World_Space
重点
了解
uniform关键字及uniform参数
代码
<span style="font-weight: normal;">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 parameter
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);
// 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.1, 0.1, 0.1, 1.0);
// color far from origin
}
}
ENDCG
}
}
}</span>
这部分里面多了_Object2World这个参数,可是我们没有定义过,哪里来的呢?
这个又是unity预定义好的,所以直接用就好了。
在vert函数中我们从Input中取到位置信息(之前说过mul函数),把变化后的位置信息存入输出的结构体,接下来再把顶点的坐标转为世界坐标存入自定义输出结构体(记住在参考书阳春白雪中提到的顶点处理的是位置、光等信息,片段中处理的是颜色信息)
在frag函数中distance函数求出每个像素距离零点的距离,然后判断显示不同的效果,大致意思是当物体在某体范围内时显示某种颜色,超出范围是另外一种颜色。
效果如图:
当然还有更多的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 float3 _WorldSpaceCameraPos;
uniform float4x4 _Object2World; // model matrix
uniform float4x4 _World2Object; // inverse model matrix
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
可是这个距离是写死的,不方便使用,如果你要在编辑器使用怎么办?
完善代码
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
}
}
}
这里与上面不同的是多出了Properties,有了这个东西你定义的属性值就可以暴露在unity的属性面板上了,格式:
Properties {//属性
_MainTex ("Base (RGB)", 2D) = "white" {}//变量名(“面板上显示的信息,可以作为说明”,类型)= 默认值
_MainTex ("Base (RGB)", 2D) = "white" {}//变量名(“面板上显示的信息,可以作为说明”,类型)= 默认值
(需要使用的属性,类型:2D,Color ,rect,cube,range(min,max),float,Vector)
}
}
定义完了之后怎么获取呢?
uniform 通过关键字+变量名就可以取到
注意uniform 的用法(更详细的请查找参考书)
1.改关键字表示从外部获取的参数
2.不能作为局部变量的修饰来使用
这样你就可以一边在编辑器看效果,而不用改代码了
通过代码修改shader的属性值
GetComponent(Renderer).sharedMaterial.SetVector("_Point", Vector4(1.0, 0.0, 0.0, 1.0)); GetComponent(Renderer).sharedMaterial.SetFloat("_DistanceNear", 10.0); GetComponent(Renderer).sharedMaterial.SetColor("_ColorNear", Color(1.0, 0.0, 0.0)); GetComponent(Renderer).sharedMaterial.SetColor("_ColorFar", Color(1.0, 1.0, 1.0));