Shader 学习笔记
Shader "Custom/Diffuse Texture" { // Shader的开始,双引号内饰该Shader的名字
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {} // 属性块,可有可无,_属性名字("显示出来的名字", 类型) = 默认值 {选项(可选,但2D,Rect等必须要)}
}
SubShader { // 子着色器,至少一个,具体使用哪个,根据目标平台的性能自动决定,如果都不达标,则使用“Diffuse”
Tags { "RenderType"="Opaque" } // 硬件将通过判定这些标签来决定什么时候调用该着色器,这里是当系统在渲染非透明物体时调用该Shader
// 标签还有诸如"Queue"="xxx"来指定渲染顺序,值越高越靠后渲染
LOD 200 // 细节层次,在Unity中可以设定最大LOD,当设定的LOD小于SubShader所指定的LOD时,这个Sub将不可用
CGPROGRAM // 此标记到ENDCG表示这中间是一段CG语言写的Shader,如果sub里有这种代码,则说明该sub是可编程渲染
#pragma surface surf BasicDiffuse vertex:vert // 表面该sub是表面着色器,并且主函数是surf,使用我们自定的光照模型函数BasicDiffuse,使用顶点函数vert
// Lambert是默认的光照模型函数,如果我们没有自定义的,就用它。顶点函数可以省略
sampler2D _MainTex; // 在上面的属性块里设定的属性,在CG代码块里要再声明一次,将两者连接起来,因为CG代码块里不能直接使用
struct Input { // Input其实是需要我们去定义的结构,这给我们提供了一个机会,可以把所需要参与计算的数据都放到这个Input
float2 uv_MainTex; // 里,传入surf函数里使用
};
void vert(inout appdata_full v, out Input o) // 顶点函数,appdata_full是CgInclude里的结构体,存顶点的各种信息
{
//在这里修改顶点的各种信息,或者修改Input结构体,给surf函数传递信息
} /* 自定光照模型函数,函数格式必须为:Lighting + 名字, surf主函数计算输出的SurfaceOutput作为参数参传入到此函数里
* 其它两种格式的光照模型函数
* half4 LightingName_PrePass (SurfaceOutput s, half4 light)
* half4 LightingName (SurfaceOutput s, half3 lightDir, half3 viewDir, halfatten)
*/
inline float4 LightingBasicDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten) {
float difLight = max(0, dot(s.Normal, lightDir)); // 像素点的光照强度与入射光线角度有关,角度越大,像素点越亮
float4 col;
col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2); // _LightColor.rgb是U3D中的光源,如果不乘这个参数,则无法随光源变化
col.a = s.Alpha;
return col;
}
void surf (Input IN, inout SurfaceOutput o) { // 表面着色器的主函数,参数IN表示我们的输入,o表示输出到屏幕的内容,o一开始是空白的,要我们输内容进去
half4 c = tex2D (_MainTex, IN.uv_MainTex); // SurfaceOutput是一个结构体,具体内容参见下面的第七点
o.Albedo = c.rgb;
o.Alpha = c.a; // 我们将输入的内容经过变换后,赋予输出,这样就能在屏幕上改变内容了
}
ENDCG
}
FallBack "Diffuse" // 如果以上的所有sub着色器都不能使用,则默认使用该着色器
}
1.写Shader的三种语言:
HLSL -> DirectX,只有微软平台能用
GLSL -> OpenGL,由硬件编译,所以跨平台性很好
Cg -> DirectX 与 OpenGl 的上层,类似中间语言,最后会编译成GLSL或者HLSL。由于是微软参与开发,语法很像HLSL,可以无缝转换为HLSL
(Unity Shder一般用CG编写,可以选择CG/HLSL或者GLSL)
2.计算机图形渲染分为:
固定管道渲染、可编程管道渲染
3.Unity中Shader分为三种:
固定功能着色器(Fixed Function Shader)
表面着色器(Surface Shader)
顶点着色器&片段着色器 (Vertex Shader & Fragment Shader)
前者是固定管道渲染,后两者是可编程管道渲染
4.Unity中判断Shader是哪种类型的方法
- 没有嵌套CG语言,也就是代码段中没有CGPROGARAM和ENDCG关键字的,就是固定功能着色器。而且必须置于Pass块中。
- 嵌套了CG语言,代码段中有surf函数的,就是表面着色器。不必置于Pass块中
- 嵌套了CG语言,代码段中有#pragma vertex name和 #pragma fragment frag声明的,就是顶点着色器&片段着色器,置于Pass块中
5.Pass通道
执行的时候,从执行的SubShader里开始,从第一个Pass块开始执行,一个一个执行。
表面着色器没有Pass块,但在编译的时候,会被编译成若干Pass块。
6.参数类型
ShaderLab的参数类型:
- Color - 一种颜色,由RGBA(红绿蓝和透明度)四个量来定义;
- 2D - 一张2的阶数大小(256,512之类)的贴图。这张贴图将在采样后被转为对应基于模型UV的每个像素的颜色,最终被显示出来;
- Rect - 一个非2阶数大小的贴图;
- Cube - 即Cube map texture(立方体纹理),简单说就是6张有联系的2D贴图的组合,主要用来做反射效果(比如天空盒和动态反射),也会被转换为对应点的采样;
- Range(min, max) - 一个介于最小值和最大值之间的浮点数,一般用来当作调整Shader某些特性的参数(比如透明度渲染的截止值可以是从0至1的值等);
- Float - 任意一个浮点数;
- Vector - 一个四维数;
详见U3D官方文档:http://docs.unity3d.com/Manual/SL-Properties.html
CG语言中对应的类型:
- sampler2D
- samplerCube
- float
- vec
- half 精度比float还低的浮点数,当然,运算效率更高
float和vec都可以在之后加入一个2到4的数字,来表示被打包在一起的2到4个同类型数
// 定义一个2d vector
vec2 coordinate;
// 定义一个颜色值(A,R,G,B)
float4 color;
// Multiply out a color
float3 multipliedColor = color.rgb * coordinate.x;
7.SurfaceOutput的具体内容
这是Unity的CgInclude里定义的默认结构体,有需要的话,可以自己定义一个,可以在光照函数和surf函数里传递信息
struct SurfaceOutput {
half3 Albedo; //像素的颜色
half3 Normal; //像素的法向值
half3 Emission; //像素的发散颜色
half Specular; //像素的镜面高光
half Gloss; //像素的发光强度
half Alpha; //像素的透明度
};
8.Cg语言标准函数库
http://http.developer.nvidia.com/Cg/index_stdlib.html
9.Surf 与 光照模型的关系
surf函数只是接受输入(材质,颜色等),将效果设置为对象的输出(即设置对象每一个像素点应该对应的颜色)
设置完像素点的输出颜色后,我们并不能看到,应该在光照模型函数里,将像素点的颜色,在对应的光下反应后的结果输出给color并返回才能在屏幕上看到结果。
10.从本质上讲,U3D中只存在顶点/片元着色器,表面着色器,固定函数着色器最终也会被编译成若个个PASS端。
表面着色器只是Unity自己创造的一种着色器,目的在顶多/片元的基础上再封装一层,使用起来更简单,编译时会自动转为PASS,但简单使用的同时也失去一些性能优势。
12.Unity中Shader面板扩展的两种方法
http://blog.csdn.net/WPAPA/article/details/51214368
13.SurfaceShader里各函数执行顺序
渲染管线(管道):顶点着色器——>光栅化——>片段着色器——>alpha测试——>模版测试——>深度测试——>Blend——>Gbuffer——>BrontBuffer——>framebuffer——>显示器
vert -> surf -> light
vert先从appdata_full获取顶点信息,并修改(例如顶点位置,法线),然后将某些信息传递给Input结构体(例如顶点颜色)
接着进行插值,顶点间的信息进行插值,进行逐像素渲染
surf从上一步获取Input里存储的信息,开始修改像素信息(颜色,透明,高光啥的),然后将信息传递给SurfaceOutput结构体
最后处理光照信息,light函数利用上一步获取到的SurfaceOutput,当前光照方向,视野方向,光线衰减等,处理每个像素的光照效果
14.CgInclude文件
可以理解为C++里的各种头文件,包含了各种常用函数库,常量等,可以减少重复编码。
Unity自带了一个CgInclude.cginc文件,放置在Editor/Data/CGInludes里,可以直接用文本编辑器打开
例如SurfaceShader里不指定光照时,会用默认的Lambert光照函数,该函数就放在那里。
我们也可以自定义一个,但自定义的记得要在SurfaceShader的CGPROGRAM下 “#include "XX.cginc"
Shader 学习笔记的更多相关文章
- Shader学习笔记
Shader学习笔记 例子: Shader "SrfShader1"{ //定义显示在Inspector中的变量,并从Inspector中获取值 Properties{ _Colo ...
- Unity Shader学习笔记-1
本篇文章是对Unity Shader入门精要的学习笔记,插图大部分来自冯乐乐女神的github 如果有什么说的不正确的请批评指正 目录 渲染流水线 流程图 Shader作用 屏幕映射 三角形遍历 两大 ...
- u3d shader学习笔记1
促使我学习SHADER的重要原因是希望深入理解3D渲染的机制,在此基础上可以灵活达到某种效果与性能的平衡,开发出具有良好体验的VR应用. 因为VR应用体验的好坏,直接由游戏的帧率决定,而游戏的帧率则受 ...
- 【Unity Shader学习笔记】Unity基础纹理-单张纹理
1 单张纹理 1.1 纹理 使用纹理映射(Texture Mapping)技术,我们把一张图片逐纹素(Texel)地控制模型的颜色. 美术人员建模时,会在建模软件中利用纹理展开技术把纹理映射坐标(Te ...
- Unity3D Shader 学习笔记(一):初识Shader
第一节:图形处理器简史 GPU发展简史 GPU英文全称Graphic Procssing Unit. T&L变换和光照流水线 可编程GPU GPU的优点和缺点 第二节:Unity Shader ...
- Unity3D Shader 学习笔记(二):ShaderLab的结构和基本属性
(一) ShaderLab: 什么是ShaderLab: Unity3D支持的Shader种类包括: 1.Surface Shader:表面着色器 2.Vertex & Fragment Sh ...
- Unity Shader学习笔记 - 用UV动画实现沙滩上的泡沫
这个泡沫效果来自远古时代的Unity官方海岛Demo, 原效果直接复制3个材质球在js脚本中做UV动画偏移,这里尝试在shader中做动画并且一个pass中完成: // Upgrade NOTE: r ...
- Unity Shader 学习笔记(一)
_MainTex_ST (1)简单来说,TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)主要作用是拿顶点的uv去和材质球的t ...
- unity shader学习笔记(1) shader基础结构以及Properties面板
首先是shader的基础结构: Shader "Custom/Example { Properties//变量属性面板 { } SubShader { Tags { "Render ...
随机推荐
- 用修改hosts的方式来屏蔽某些网站
首先呢,来自知乎的一些问答:修改 hosts 文件可以上一些墙内屏蔽的网站,其原理是什么? (然而通过增/改hosts的方法来FQ已经失效很久了) 然后呢,也可以通过修改hosts来达到屏蔽某些网站的 ...
- 【2016-11-2】【坚持学习】【Day17】【通过反射自动将datareader转为实体info】
通过ADO.net 查询到数据库的数据后,通过DataReader转为对象Info public class BaseInfo { /// <summary> /// 填充实体 /// & ...
- RS-232, RS-422, RS-485 Serial Communication General Concepts(转载)
前面转载的几篇文章重点介绍了UART及RS-232.在工控领域除了RS-232以外,常用的串行通信还有RS-485.本文转载的文章重点介绍了RS-232.RS-422和RS-485. Overview ...
- Linux档案与目录管理
Linux档案与目录管理1. 目录与路径1.1 相对路径与绝对路径1.2 目录的相关操作: cd, pwd, mkdir, rmdir cd [相对路径或绝对路径]cd ~ [用户]: 切换家目录cd ...
- 服务器一般达到多少qps比较好[转]
你好,每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量. 原理:每天80%的访问集中在20%的时间里,这2 ...
- [[iso教程]] 《4个月ios实体教程》全网最新、最全ios视频教程
全网最新.最全ios视频教程 内容简介 <ios实体教程>主要介绍如何使用iOS提供的强大工具集创建iOS应用.全视频对iOS操作系统做了全面的介绍,首先讲解如何构建应用程序的用户界面,涵 ...
- 详解 Android Activity 生命周期
从以下几个方面详细说一下Activity的生命周期: 1.回到主屏幕再打开和退出程序的时候. 2.屏幕旋转的时候. 3.打开其它的Activity的情况. 4.打开一个Layou透明的Activity ...
- [转]iostat命令详解
iostat iostat用于输出CPU和磁盘I/O相关的统计信息. 命令格式: iostat [ -c | -d ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ devi ...
- 添加native service
原文地址:http://blog.csdn.net/zhx6044/article/details/47342227 Native Service 其实就是一个 linux 守护进程,提供一些服务,不 ...
- 微信连WiFi expired timestamp 和sign错误小坑解决
0.微信连WiFi需要时间戳毫秒,但是PHP本身没有自带这个函数.但是相对来说,Java和js获取毫秒时间戳就比较方便. 既然PHP没有,那么就自己写一个获取毫秒时间戳的函数,否则就会失败.实在懒得写 ...