本系列文章系学习 唐福幸《Unity ShaderLab 新手宝典》的笔记,包含个人理解,如有错误欢迎批评指出
顶点-片段着色器基础
4.3.4 在CG中调用属性变量
4.3.4.1声明属性变量
之前展示的简单shader,最终效果是纯红色。如果要改变颜色只能修改代码,我们可以通过属性让颜色变量在材质面板中开放,便于随意调整。
新建一个材质,新建一个Shader,代码如下:
Shader "Chapter4/NewUnlitShader1"
{
Properties
{
_MyFloat ("Float Type", Float) = 1
_MyRange ("Range Type", Range(0,1)) = 0.1
_MyColor ("Color Type", Color) = (1,1,0,1)
_MyVector ("Vector Type", Vector) = (0,1,0,0)
_MyTex("Texture Type", 2D) = "white" {}
_MyCube("Cube Type",Cube) = "" {}
_My3D("3D Type",3D) = "" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
float _MyFloat;
float _MyRange;
fixed4 _MyColor;
float4 _MyVector;
sampler2D _MyLuoLuo;
samplerCUBE _MyCube;
sampler3D _Mp3D;
void vert()
{
}
void frag()
{
}
ENDCG
}
}
}
材质面板中显示如下:这些数值是可以任意调整的,但是还没有具体效果
4.3.4.2在shader中使用颜色
新建一个材质,新建一个Shader,代码如下:
Shader "Chapter4/NewUnlitShaderColor"
{
Properties
{
//开放颜色属性
_MainColor("Color Type", Color) = (1,0,1,1)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 声明属性变量
float4 _MainColor;
float4 vert (in float4 v : POSITION) : SV_POSITION
{
return UnityObjectToClipPos(v);//把顶点坐标从模型空间转换成剪裁空间,如果不转换,后面颜色根本无法显示
}
fixed4 frag () : SV_Target
{
//调用颜色变量
return _MainColor;
}
ENDCG
}
}
}
4.3.4.3在shader中使用贴图
代码中将贴图与颜色混和,代码如下:
Shader "Chapter4/NewUnlitShaderTex"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_MainColor ("MainColor",Color) = (1,1,1,1)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
sampler2D _MainTex;
float4 _MainTex_ST;//表示uv的缩放和平移
float4 _MainColor;
void vert(in float4 vertex : POSITION, in float2 uv : TEXCOORD0, out float4 position : SV_POSITION, out float2 texcoord : TEXCOORD0)
{
position = UnityObjectToClipPos(vertex);
texcoord = uv * _MainTex_ST.xy + _MainTex_ST.zw;//纹理坐标的计算公式
}
void frag(in float4 position : SV_POSITION, in float2 texcoord : TEXCOORD0, out fixed4 color : SV_TARGET)
{
color = tex2D(_MainTex, texcoord) * _MainColor;//使用纹理坐标texcoord对纹理_MainTex进行采样,结果与_MainColor颜色混合
//tex2D:https://blog.csdn.net/yuanerjiang/article/details/88681589
}
ENDCG
}
}
}
Tiling:表示平铺(放大缩小)
Offset:偏移
texcoord = uv * _MainTex_ST.xy + _MainTex_ST.zw;
xy表示Tiling的X、Y;zw表示Offset的X、Y
计算纹理坐标一定要先乘平铺值,再加偏移值,避免偏移后对原坐标放大错误比例
4.3.4.4在shader中使用立方体贴图
新建一个材质,新建一个Shader,代码如下:
Shader "Chapter4/NewUnlitShaderCube"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_MainColor ("Color", Color) = (1,1,1,1)
_MainCubemap ("Cubemap Type", Cube) = "" {}
_Reflection ("Reflection", Range(0,1)) = 0
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
sampler _MainTex;
float4 _MainTex_ST;
fixed4 _MainColor;
samplerCUBE _MainCubemap;
fixed _Reflection;
void vert (in float4 verte :POSITION, in float3 normal : NORMAL,in float4 uv : TEXCOORD0,
out float4 position : SV_POSITION, out float4 worldPos : TEXCOORD0, out float3 worldNormal : TEXCOORD1, out float2 texcoord : TEXCOORD2)
{
position = UnityObjectToClipPos(verte);
worldPos = mul(unity_ObjectToWorld, verte); //将顶点坐标变换到世界空间
worldNormal = mul(normal,(float3x3)unity_WorldToObject);//将法线向量变换到世界空间
worldNormal = normalize(worldNormal);//法线归一化
texcoord = uv * _MainTex_ST.xy + _MainTex_ST.wz;
}
void frag (in float4 position : SV_POSITION, in float4 worldPos : TEXCOORD0, in float3 worldNormal : TEXCOORD1, in float2 texcoord : TEXCOORD2,
out fixed4 colo : SV_TARGET)
{
fixed4 main = tex2D(_MainTex, texcoord)*_MainColor;
float3 ViewDir = worldPos.xyz - _WorldSpaceCameraPos;//计算世界空间中从摄像机指向顶点方向向量
ViewDir = normalize(ViewDir);//标准化向量
float3 refDir = 2 * dot(-ViewDir, worldNormal) *worldNormal +ViewDir;//套用公式计算反射向量
refDir = normalize(refDir);//标准化向量
fixed4 reflection = texCUBE(_MainCubemap,refDir);//对Cubemap采样
colo = lerp(main,reflection,_Reflection);//使用_Reflection对颜色和反射进行线性插值计算
}
ENDCG
}
}
}
再贴图属性面板中把Texture Shape从2D改成Cube,点击下方的Apply
之后就可以把图片放到材质上了