[Unity Shader]Shader前述
什么是Shader
- Surface Shaders —— 也称为表面着色器。这大概是Unity的骄傲。它去除了大部分“麻烦的工作”,可以适用于很多情况下
- Fragment Shaders —— 片段着色器。它允许你做更多的工作,但也更难写,而且它还让我们可以做低层的一些东西,像顶点光照,这对于移动设备和多个通道(passes)所必需的更高级的效果会非常有用。
Surface Shaders的代码需要看起来像这样:
你可以使用Pass中的语句来控制这个Z方向的缓存是否对你的着色器代码有影响,或者你的Shader是否写入该缓冲区内,例如: Zwrite Off表明不会更新你的任何输出像素的Z方向的缓存区。
您可以使用这种技术来在其他对象上打孔 —— 通过写入Z缓冲区,但不输出任何实际的像素颜色,那么使用这个Shader的模型背后的对象将不能被写入(因为Z缓冲区中有距离更近的像素了),这样看起来这个对象就像是被打了洞一样。
下面展示了一个最简单的Surface Shader:
Shader "Custom/Hello" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
理解Shader代码
Properties
_Name ( "Displayed Name", type ) = default value {options}
- _Name:程序中引用的名字,和我们一般理解的变量名称是一样的。
- Displayed Name:这个字符串将会出现在Unity材质的编辑面板上。
- type:该属性的类型。Unity支持以下几种属性类型:
- Color:表示一个单一的RGBA颜色值;
- 2D: 表示一张大小为2的次方的纹理贴图,可以使用基于模型UV坐标来进行采样;
- Rect:表示一张纹理不是2的次方的纹理贴图;
- Cube:表示一个可用于反射的3D立方体映射贴图,可以进行采样;
- Range(min, max):一个取值范围在min到max之间的浮点值;
- Float: 一个可以为任意值的浮点值;
- Vector:一个4维度的向量。
- default value:该属性的默认值。
- Color:使用浮点值表示的(r, g, b, a),例如(1,1,1,1);
- 2D/Rect/Cube:对于贴图类型的属性,默认值可以是一个空字符串,或者"white", "black", "gray", "bump"这样的字符串;
- Float/Range:在此范围内的值即可;
- Vector:以(x,y,z,w)形式表示的4D向量;
- { options }:只和纹理类型的2D、Rect和Cube相关,它必须至少被指定为{ }。你可以使用空格分隔多个选项,有如下选择:
- TexGen贴图生成模式:该纹理的自动纹理坐标生成模式。可以为ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal。这些直接对应了OpenGL中的texgen modes。注意,如果你编写了一个顶点函数,那么可以忽略TexGen。
//Define a color with a default value of semi-transparent red
_MainColor ("Main Color", Color) = (1,0,0,0.5)
//Define a texture with a default of white
_Texture ("Texture", 2D) = "white" {}
Tags
Shader结构
Shader "Custom/Hello" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
//Lambert定义了光照模型
#pragma surface surf Lambert
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
//Define a float variable
vec2 coordinate;
//Define a color variable
float4 color;
//Multiply out a color
float3 multipliedColor = color.rgb * coordinate.x;
我们可以使用.xyzw和.rgba符号访问存储在这些变量中的值(颜色、位置、法线等)。
从Surface Shader输出信息
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
显然,我们是为SurfaceOutput中的Albedo属性进行了设置。SurfaceOutput是Unity为我们定义的一种结构体,它的结构定义如下:
struct SurfaceOutput {
half3 Albedo; //颜色纹理
half3 Normal; //法线
half3 Emission; //自发光,不受照明的影响
half Specular; //高光指数
half Gloss; //光泽度
half Alpha; //Alpha通道
};
只需要通过Input结构体,我们就可以告诉系统,为当前正在处理的像素得到在MainTex中对应的纹理坐标。如果不止一张纹理,例如还有一张_OtherTexture,我们只需要添加如下代码:
struct Input {
float2 uv_MainTex;
float2 uv_OtherTexture;
};
struct Input {
float2 uv_MainTex;
float2 uv2_OtherTexture;
};
Input结构体
- float3 viewDir:视角方向,用于计算视差效果和边缘照明等;
- 使用COLOR语义的float4:包含了插值后的逐顶点颜色;
- float4 screenPos:屏幕空间中的位置;
- float3 worldPos:世界空间中的位置;
- float3 worldRefl:如果Surface Shader没有改写o.Normal,将包含了环境反射向量;
- float3 worldNormal:如果Surface Shader没有改写o.Normal,将包含了环境法线向量;
- INTERNAL_DATA:当我们需要改写o.Normal时,一些函数,如WorldNormalVector等,需要该变量进行计算;
Shader "Custom/Hello" {
Properties {
//1、_MainTex变量名
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD
CGPROGRAM
#pragma surface surf Lambert
//2、_MainTex变量名
sampler2D _MainTex;
struct Input {
//3、uv_MainTex变量名
float2 uv_MainTex;
};
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
当该属性是一张文字,而你需要在Input结构中得到对应的uv坐标时,uv或者uv2后面的名称也必须和属性名相同。
在上图中,_MainTex对应了一张纹理贴图,它对应的变量类型就是sampler2D类型,只要得到了一个uv坐标,我们就可以在贴图上进行采样得到颜色值。
surf函数中仅用了一个函数:
o.Albedo = tex2d( _MainTex, IN.uv_MainTex).rgb;
它使用Input中得到的该像素对应的_MainTex中的uv坐标,在_MainTex进行采样,得到一个float4类型的颜色值(包括了透明通道)。如果我们需要得到透明通道的值,可以这样做:
float4 texColor = tex2d( _MainTex, IN.uv_MainTex );
o.Albedo = texColor.rgb;
o.Alpha = texColor.a;
[Unity Shader]Shader前述的更多相关文章
- 【淡墨Unity3D Shader计划】五 圣诞用品: Unity在Shader三种形式的控制&混合操作编译
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/42060963 作者:毛星云(浅墨) ...
- [Unity Shader]Shader分类
Shader的分类: Shader按管线分类一般分为固定渲染管线与可编程渲染管线 (1)固定渲染管线 ——这是标准的几何&光照(Transforming&Lighting)管线,功能是 ...
- Unity的shader学习1
先来看一段我们项目常见的Shader代码,这个是Vertex&Fragment shader,目前已经不常用了,不过还是适合我们理解一些基础知识和理解一些比较老的shader 代码.下次我们再 ...
- unity之shader
渲染流程分为三个阶段:应用阶段,几何阶段,光栅化阶段. Unity Shader的分类: 使用的是ShaderLab编写unity中的的shader 1 表面着色器 Surface Shader 2 ...
- unity, change shader for me and all my children
public void changeShaderForMeAndAllMyChildren(){ Transform[] childrenTransformList = GetComponentsIn ...
- 详解Paint的setShader(Shader shader)
一.概述 setShader(Shader shader)中传入的自然是shader对象了,shader类是Android在图形变换中非常重要的一个类.Shader在三维软件中我们称之为着色器,其作用 ...
- Unity Built-in Shader详解二
这次主要讨论Unity自带的Shader中Transparent Shader Family 这个家族的Shader一共7种,原理和类型与Normal中的上差不多,只不过这些Shader是用在半透明或 ...
- 对Unity一个Shader编译Bug的分析(Unrecognized sampler 'samplerunity_lightmap)
写在前面 Unity的用户量越来越大,越来越有钱,这几年摊子也铺的越来越大,所以各个版本总是有很多Bug.对于一些Bug官方在ReleaseNote里的说明是很不详细的,而对于一些渲染相关的Bug,有 ...
- 关于Unity中Shader的使用
在游戏的开发过程中,程序员不太会自己去写shader,因为写起来很麻烦,而且只有Unity会报错,编译器也没有什么提示. 通常是拿别人的shader改一改,当然,程序员还是要能看懂和会一点shader ...
随机推荐
- ASP MVC之参数传递
1.URL获取参数 Request.QueryString["XqType"]; 2.表单提交,control层获取参数:Request.Form["XXX" ...
- web配置文件的<load-on-startup>0</load-on-startup>
在servlet的配置当中,<load-on-startup>5</load-on-startup>的含义是:标记容器是否在启动的时候就加载这个servlet.当值为0或者大于 ...
- Android简单逐帧动画Frame的实现(三)
android之动画(三)通过AnimationDrawable控制逐帧动画 android与逐帧动画: 效果图: 当我们点击按钮时,该图片会不停的旋转,当再次点击按钮时,会停止在当前的状态. ...
- Jenkins设置Poll SCM
*/5 * * * * (每5分钟执行一次) 0 20 * * * 每天 20点执行定时build # every fifteen minutes (perhaps at :07, :22, : ...
- android:contentDescription的作用是什么
在写Android的XML布局文件时,在ImageView或ImageButton中经常会碰到一个提示: Missing contentDescription attribute on image. ...
- CF div2 D BFS
http://codeforces.com/contest/676/problem/D 题目大意: 勇者去迷宫杀恶龙.迷宫是有n*m的方格子组成的.迷宫上有各种记号,这些记号表达着能走的方向.当且仅当 ...
- activemq学习
一.特性及优势 1.实现JMS1.1规范,支持J2EE1.4以上2.可运行于任何jvm和大部分web容器(ActiveMQ works great in any JVM)3.支持多种语言客户端(jav ...
- java thread park
http://agapple.iteye.com/blog/970055 apidoc中说,park/unpark用来阻塞/激活线程,但是没有弃用方法suspend/resume的缺点,suspend ...
- 转 Linux进程状态分析
众所周知,现在的分时操作系统能够在一个CPU上运行多个程序,让这些程序表面上看起来是在同时运行的.linux就是这样的一个操作系统.在linux系统中,每个被运行的程序实例对应一个或多个进程.l ...
- 整理书本(book)
整理书本(book) 题目描述 小A想把他满屋子的书整理一下.书本分成若干堆.每一堆的书本都有质量w和价值V.小A的任务是将所有书合成一堆.因为小A认为合并i,j两堆的书所需要的力为w[i]-v[i] ...