20.CG-函数
20.1 知识点
注意
CG语法中的函数声明和使用几乎和C#中一模一样。
无返回值的函数
- 基本结构:
- void:以void开头,表示没有返回值
- name:函数的名称
- in:表示是输入参数,表示由函数外部传递给函数内部,内部不会修改该参数,只会使用该参数进行计算,允许有多个
- out:表示是输出参数,表示由函数内部传递给函数的调用者,在函数内部必须对该参数值进行初始化或修改,允许有多个
void name(in 参数类型 参数名, out 参数类型 参数名)
{
函数体
}
- 实例
// 无返回值的函数
void test(in fixed inF, out fixed outF)
{
outF = inF + 10;
}
// 调用示例
fixed f = 10;
fixed f2;
test(f, f2); // f2的值会变成20
- 注意:
- in和out都可以省略,省略后就没有了in和out相关的限制
- 虽然可以省略,但是建议大家在编写Shader时不要省略in和out,因为他们可以明确参数的传递方式,提高代码的可读性和可维护性,可以让我们更容易的理解函数是如何与参数交互的,减少潜在的误解可能
有返回值的函数
- 基本结构:
- type:返回值类型
- return:返回指定类型的数据
type name(in 参数类型 参数名)
{
函数体
return 返回值;
}
- 实例
// 有返回值的函数
float test2(in float inF, out fixed f)
{
f = inF + 2;
return inF * 2;
}
// 调用示例
float f3 = test2(11, f); // f3: 11, f: 13
- 注意:
- 虽然可以在有返回值的函数中使用out参数,但这并不是常见做法,除非是一些自定义逻辑函数。对于顶点/片元着色器函数只会使用单返回值的方式进行处理。
总结
CG当中的函数声明和函数使用和C#中基本一致。
区别主要是CG中的in和out关键字:
- in表示输入参数,用于外部传给内部,内部只会用,不会改,可以有多个。
- out表示输出参数,用于内部传给外部,内部必须初始化或修改,可以有多个。
对于有返回值的函数,要不采用返回值形式,要不采用out。
20.2 知识点代码
Lesson20_CG_函数
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson20_CG_函数 : MonoBehaviour
{
void Start()
{
#region 注意
//CG语法中的函数声明和使用几乎和C#中一模一样
#endregion
#region 知识点一 无返回值的函数
//基本结构
//void name(in 参数类型 参数名, out 参数类型 参数名)
//{
// 函数体
//}
//void:以void开头,表示没有返回值
//name:函数的名称
//in:表示是输入参数,表示由函数外部传递给函数内部,内部不会修改该参数,只会使用该参数进行计算,允许有多个
//out:表示是输出参数,表示由函数内部传递给函数的调用者,在函数内部必须对该参数值进行初始化或修改,允许有多个
//注意:
//in和out都可以省略,省略后就没有了in和out相关的限制
//虽然可以省略,但是建议大家在编写Shader时不要省略in和out
//因为他们可以明确参数的传递方式,提高代码的可读性和可维护性
//可以让我们更容易的理解函数是如何与参数交互的,减少潜在的误解可能
#endregion
#region 知识点二 有返回值的函数
//基本结构
//type name(in 参数类型 参数名)
//{
// 函数体
// return 返回值;
//}
//type:返回值类型
//return:返回指定类型的数据
//注意:
//虽然可以在有返回值的函数中使用out参数
//但是这并不是常见做法,除非是一些自定义逻辑函数
//对于顶点/片元着色器函数只会使用单返回值的方式进行处理
#endregion
#region 总结
//CG当中的函数声明和函数使用和C#中基本一致
//区别主要是CG中的in和out关键字
//1.in表示输入参数,用于外部传给内部,内部只会用,不会改,可以有多个
//2.out表示输出参数,用于内部传给外部,内部必须初始化或修改,可以有多个
//对于有返回值的函数,要不采用返回值形式,要不采用out
#endregion
}
}
Lesson20_NewUnlitShader.shader
Shader "ShaderTeach/Lesson20_NewUnlitShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
//无返回值的函数
void test(in fixed inF, out fixed outF)
{
outF = inF + 10;
}
//有返回值的函数
float test2(in float inF, out fixed f)
{
f = inF + 2;
return inF * 2;
}
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
//无返回值的函数
fixed f = 10;
fixed f2;
test(f, f2);//f2的值会变成20
//有返回值的函数
float f3 = test2(11, f);//f3:11 f:13
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
20.3 练习题
在CG中申明一个函数,要求可以得到两个返回值,请至少用5种方式完成
除了in、out两个关键字意外,CG当中还有一个不常用的inout关键字,请根据所学知识,分析它的作用
in:表示是输入参数,表示由函数外部传递给函数内部,内部不会修改该参数,只会使用该参数进行计算,允许有多个
out:表示是输出参数,表示由函数内部传递给函数的调用者,在函数内部必须对该参数值进行初始化或修改,允许有多个
inout:表示输入输出参数,既作为输入in又作为输出out。参数的值可以在函数内部被修改,并且该修改会在函数调用结束后保留在参数中。在函数外部可以继续使用修改后的内容
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com