Unity Shaders学习笔记之表面着色器
Posted 程序员小毛驴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Shaders学习笔记之表面着色器相关的知识,希望对你有一定的参考价值。
一、表面着色器
1.1 简介
表面着色器代码直接在SubShader中编写,不需要使用Pass,编译器会将代码编译到合适的Pass中
1.2 标签
硬件将通过判定标签来决定什么时候调用该着色器
属性RenderType:
值Opaque:在渲染非透明物体时调用
值Transparent:表示渲染含有透明效果的物体时调用
例:Tags "RenderType"="Opaque"
1.3 申明变量
#pragma surface surfaceFunction lightModel [optionalparams] //声明写一个表面Shader
名字 | 说明 |
surface | 申明这是表面着色器 |
surfaceFunction | 着色方法的名字,如surf,在下面会出现surf函数 |
lightModel | 使用的光照模型,如Lambert(就是普通的diffuse) |
顶点处理函数 -> 表面处理函数 -> 光照模型函数 ->颜色值
sampler2D _MainTex;
sampler2D就是GLSL中的2D贴图的类型,相应的还有sampler1D,sampler3D,samplerCube等格式
提问:在property中已经定义过_MainTex了,这里为什么又要声明一次呢?答:这个shader是由两个相对独立的块组成的,外层的属性、回滚等是Unity可以使用和编译的ShaderLab;CGPROGRAM...ENDCG代码块是一段CG程序。对于这段CG程序,要想访问在Properties中定义的变量,必须使用和之前变量相同的名字进行声明。sampler2D _MainTex; 再次声明并链接了_MainTex,使得接下来的CG程序能够使用这个变量
1.4 函数定义
在#pragma段已经指出了着色方法的名字叫做surf,这段surf代码就是着色器的工作核心。着色器就是给定了输入,然后给出输出进行着色的代码CG规定了声明为表面着色器的方法(这里是surf函数)的参数类型和名字,因此我们没有权利决定surf的输入输出参数的类型,只能按照规定写。这个规定就是第一个参数是一个Input结构,第二个参数是一个inout的SurfaceOutput结构接下来分别介绍Input、SurfaceOutput结构。1.5 Input结构
Input是需要我们去定义的结构,可以把所需要参与计算的数据都放到这个Input结构中,传入surf函数使用作为输入的结构体必须命名为Inputfloat和vec都可以在之后加入一个2到4的数字,来表示被打包在一起的2到4个同类型数,如float2表示由两个float数构成的一个数据变量的访问:可以只使用名称来获得整组值,也可以使用下标的方式(比如.xyzw,.rgba或它们的部分比如.x等)来获得某个值。在CG程序中约定,在一个贴图变量(如_MainTex)之前加上uv两个字母,就代表提取它的uv值UV mapping的作用是将一个2D贴图上的点按照一定规则映射到3D模型上,是3D渲染中最常见的一种顶点处理手段。
1.5 SurfaceOutput结构
着色函数已经定义好了输出结构,但内容是空白的,需要向里面填写输出,这样就可以完成着色了
truct SurfaceOutput
half3 Albedo; //像素的颜色,反射值
half3 Normal; //像素的法向值
half3 Emission; //像素的发散颜色
half Specular; //像素的镜面高光
half Gloss; //像素的发光强度
half Alpha; //像素的透明度
;
half指的是半精度浮点数,精度最低,运算性能相对比高精度浮点数高一些,因此被大量使用
1.5 表面着色函数
在计算输出时Shader会多次调用surf函数,每次给入一个贴图上的点坐标,来计算输出,然后把输出结构填上函数tex2d:这是CG程序中用来在一张贴图中对一个点进行采样的方法,返回一个float4。这里对_MainTex在输入点上进行了采样,并将其颜色的rbg值赋予了输出的像素颜色,将a值赋予透明度。于是,着色器就明白了应当怎样工作:即找到贴图上对应的uv点,直接使用颜色信息来进行着色Unity中cg函数的路径: C:\\ProgramFiles\\Unity\\Editor\\Data\\CGIncludes ,查看UnityCG.cginc文件二、代码示例
1.在Unity编辑器的Project面板上,点击Assets文件,选择Create|Folder,命名为Materials 2.创建另一个文件夹Create|Shader 3.创建一个Shader文件 命名为BasicDiffuse 如下图4.创建一个材质球 命名为BasicDiffuse 如下图
5.双击BasicDiffuse着色器,打开MonoDevelop,你会看到Unity已经为我们添加了一些基本的着色器代码。
Shader "liulongling/BasicDiffuse"
Properties
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white"
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
SubShader
Tags "RenderType"="Opaque"
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input
float2 uv_MainTex;
;
half _Glossiness;
half _Metallic;
fixed4 _Color;
void surf (Input IN, inout SurfaceOutputStandard o)
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
ENDCG
FallBack "Diffuse"
6.现在我们需要给着色器一个自定义文件夹路径。着色器代码中的第一行是对着色器的自定义描述,这样我们可以在着色器的下拉列表中找到它,并且将它赋给在第四步创建BasicDiffuse材质球。如图所示:
7.选中BasicDiffuse材质球,在Inspector面板点击select,给它添加一张纹理图片
8.创建3个Sphere,我们把BasicDiffuse材质球拖到其中一个Sphere上 看看有什么效果 参考资料:
<< Unity Shaders and Effects Cookbook>>
作者: 小毛驴,一个游戏人
梦想:世界和平
原文地址: http://blog.csdn.net/liulongling 本博客中未标明转载的文章归作者 小毛驴所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
以上是关于Unity Shaders学习笔记之表面着色器的主要内容,如果未能解决你的问题,请参考以下文章
Unity Shaders学习笔记之为创建自定义慢反射光照模型
Unity Shaders and Effects Cookbook (6-1) 使用 alpha 参数的 半透明着色器