本文由@唐三十胖子出品,转载请注明出处。
文章链接:https://blog.csdn.net/iceSony/article/details/84587428
这篇文章将总结和提炼《Unity Shader入门精要》的第七章“基础纹理”的内容。
通过这篇文章,你可以知道
1)UV贴图概念与使用
2)纹理相关概念的介绍
3)简单的单张纹理的应用
4)前9章Shader常见函数总结
一.UV贴图概念与使用
虽然模型与贴图(包含UV贴图,法线贴图,渐变贴图,遮罩贴图)的制作是美工的活,但是程序需要知道相关的知识以及简单使用来进行shader的开发,其中最常见的修改就是下一章要涉及的法线贴图的shader开发。
上图来自网络,很明显这是个角色UV贴图,包含头部躯干四肢
首先美工在3Dmax制作模型导出的时候会有UV贴图的导出选项,美工需要进行模型的拆分
就像一个纸箱子,通过拆分会变成这样
UV贴图包含对模型上色的相关位置信息,之后可以在PS中进行相关上色修改
至于最终怎么穿上这层皮,是模型的事情:)
模型包含了与贴图的对应信息,本篇不涉及。
二.简单的单张纹理的应用
在以后的开发我们会用到上面那样的模型uv贴图,现在用简单的入门
左边是使用漫反射的模型,右边是使用了材质贴图的模型
在shader中我们需要获取纹理颜色在法线上的影响,并最终与漫反射颜色进行混合
由于是漫反射的替换,我们这里使用之前写过的漫反射顶点着色器举例
对之前代码我们进行了修改,首先修改结构体
struct a2v { float4 pos : POSITION; float3 normal : NORMAL; float4 texcoord:TEXCOORD0; }; struct v2f { float4 pos : SV_POSITION; float3 worldNormal : NORMAL; float2 uv : TEXCOORD0; };
v2f多添加uv属性,从a2v新添加的属性texcoord中转化
顶点着色器
v2f vert(a2v v) { v2f o; o.pos = UnityObjectToClipPos(v.pos); o.worldNormal = UnityObjectToWorldNormal(v.normal); o.uv = v.texcoord.xy*_MainTex_ST.xy + _MainTex_ST.zw; return o; }
函数中添加一行o.uv = v.texcoord.xy*_MainTex_ST.xy + _MainTex_ST.zw;
翻译过来就是: uv坐标=材质uv坐标*材质uv缩放+材质uv偏移
事实上在以后的开发中你会遇到这个函数TRANSFORM_TEX,本质也是这句话
片元着色器
fixed4 frag(v2f i) : SV_Target { float3 worldNormal = i.worldNormal; float3 worldLightDir = UnityWorldSpaceLightDir(worldNormal); float3 albedo = tex2D(_MainTex, i.uv).rgb; float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz*albedo; float3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir)) * albedo; return fixed4(ambient+diffuse,1.0); }
函数中添加float3 albedo = tex2D(_MainTex, i.uv).rgb;
float3 diffuse=_LightColor0.rgb*_Diffuse.rgb*max(0,dot(worldNormal, worldLightDir))*halfLambert*albedo;
albedo的获取用到了tex2D函数对纹理进行采样,返回的albedo是该顶点下的材质颜色,在最后漫反射颜色结尾*albedo
完整代码如下
Shader "sony/Shader158" { Properties { _Diffuse("漫反射系数",Color) = (1.0,1.0,1.0,1.0) _MainTex("主纹理",2D) = "white"{} } SubShader { Pass { Tags{ "LightMode" = "ForwardBase" } CGPROGRAM #include "lighting.cginc" #pragma vertex vert #pragma fragment frag float4 _Diffuse; sampler2D _MainTex; float4 _MainTex_ST; struct a2v { float4 pos : POSITION; float3 normal : NORMAL; float4 texcoord:TEXCOORD0; }; struct v2f { float4 pos : SV_POSITION; float3 worldNormal : TEXCOORD0; float2 uv : TEXCOORD2; }; v2f vert(a2v v) { v2f o; o.pos = UnityObjectToClipPos(v.pos); o.worldNormal = UnityObjectToWorldNormal(v.normal); o.uv = v.texcoord.xy*_MainTex_ST.xy + _MainTex_ST.zw; return o; } fixed4 frag(v2f i) : SV_Target { float3 worldNormal = i.worldNormal; float3 worldLightDir = UnityWorldSpaceLightDir(worldNormal); float3 albedo = tex2D(_MainTex, i.uv).rgb; float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz*albedo; float3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir)) * albedo; return fixed4(ambient+diffuse,1.0); } ENDCG } } }
三.前九章Shader常见函数总结
坐标与法线的空间坐标转换
o.vert_pos = UnityObjectToClipPos(v.vert_pos);
o.normal = (mul(v.normal, (float3x3)unity_WorldToObject));
获取环境光颜色
float3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
获取光线方向,颜色
float3 lightDir = UnityWorldSpaceLightDir(o.vert_pos);
获取视角方向 normalize必须加
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - o.normal);
获取反射光线方向
float3 reflectDir = -reflect(lightDir,o.normal);
UV坐标的设置与获取纹理信息
o.uv = v.texcoord.xy*_MainTex_ST.xy + _MainTex_ST.zw;
float3 albedo = tex2D(_MainTex, o.uv).rgb;
获取纹理属性
Properties中定义了_MainTex ,那么在CGPROGRAM中声明为:_MainTex_ST
下一章我们会介绍低模变高模的神奇应用:法线纹理
Thanks♪(・ω・)ノ感谢阅读