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——>显示器

参考:Unity3d 图形学之OpenGL渲染流程(一)

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 学习笔记的更多相关文章

  1. Shader学习笔记

    Shader学习笔记 例子: Shader "SrfShader1"{ //定义显示在Inspector中的变量,并从Inspector中获取值 Properties{ _Colo ...

  2. Unity Shader学习笔记-1

    本篇文章是对Unity Shader入门精要的学习笔记,插图大部分来自冯乐乐女神的github 如果有什么说的不正确的请批评指正 目录 渲染流水线 流程图 Shader作用 屏幕映射 三角形遍历 两大 ...

  3. u3d shader学习笔记1

    促使我学习SHADER的重要原因是希望深入理解3D渲染的机制,在此基础上可以灵活达到某种效果与性能的平衡,开发出具有良好体验的VR应用. 因为VR应用体验的好坏,直接由游戏的帧率决定,而游戏的帧率则受 ...

  4. 【Unity Shader学习笔记】Unity基础纹理-单张纹理

    1 单张纹理 1.1 纹理 使用纹理映射(Texture Mapping)技术,我们把一张图片逐纹素(Texel)地控制模型的颜色. 美术人员建模时,会在建模软件中利用纹理展开技术把纹理映射坐标(Te ...

  5. Unity3D Shader 学习笔记(一):初识Shader

    第一节:图形处理器简史 GPU发展简史 GPU英文全称Graphic Procssing Unit. T&L变换和光照流水线 可编程GPU GPU的优点和缺点 第二节:Unity Shader ...

  6. Unity3D Shader 学习笔记(二):ShaderLab的结构和基本属性

    (一) ShaderLab: 什么是ShaderLab: Unity3D支持的Shader种类包括: 1.Surface Shader:表面着色器 2.Vertex & Fragment Sh ...

  7. Unity Shader学习笔记 - 用UV动画实现沙滩上的泡沫

    这个泡沫效果来自远古时代的Unity官方海岛Demo, 原效果直接复制3个材质球在js脚本中做UV动画偏移,这里尝试在shader中做动画并且一个pass中完成: // Upgrade NOTE: r ...

  8. Unity Shader 学习笔记(一)

    _MainTex_ST (1)简单来说,TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)主要作用是拿顶点的uv去和材质球的t ...

  9. unity shader学习笔记(1) shader基础结构以及Properties面板

    首先是shader的基础结构: Shader "Custom/Example { Properties//变量属性面板 { } SubShader { Tags { "Render ...

随机推荐

  1. execve(file, argv, env)参数argv获取字符串个数

    /* Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU ...

  2. Virtualbox虚机无法启动因断电

      The virtual machine 'nn1' has terminated unexpectedly during startup with exit code 1 (0x1). More ...

  3. EF 资料

    初级部分 入门教程   Learn Entity Framework(微软官方) http://www.entityframeworktutorial.net/     Fluent API http ...

  4. 抓鼠标的猫(Win32实现,Codeblocks+GCC编译)

    程序效果: 猫的眼睛一直跟着鼠标移动: 鼠标经过猫的右脚附近时,猫会抓住鼠标.(未使用Hook) 代码: //main.cpp 1 #include <windows.h> #includ ...

  5. backbone学习总结(二)

    今天来看下backbone的路由控制的功能.其实个人感觉backbone,模块就那么几个,熟悉它的框架结构,以及组成,就差不多. 废话不多说,我们来看看还剩下的功能. 关于路由和历史管理 通过 Bac ...

  6. [No00006F]总结C#获取当前路径的各种方法

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  7. asp.net core 部署 提示DataProtectionServices 错误

    今天在部署asp.net core网站时,因为调用到阿里云的api,api的参数需要加密签名,系统报出了如下错误: warn: Microsoft.Extensions.DependencyInjec ...

  8. C#进阶系列——动态Lamada(二:优化)

    前言:前几天写了一篇动态Lamada的文章C#进阶系列——动态Lamada,受园友xiao99的启发,今天打算来重新优化下这个动态Lamada的工具类.在此做个笔记,以免以后忘了. 一.原理分析 上篇 ...

  9. .NET 常用框架

    1.Hangfire 2.Lucene.Net 3.Log4Net 4.Quartz.Net 5.Autofac 6.SqlSugar 7.NPOI 8.Senparc.Weixin.MP 9.Aut ...

  10. Spring.Net 简单入门学习

    Spring.NET IoC容器的用法. 通过简单的例子学习Spring.Net 1.先创建一个控制台程序项目. 2.添加IUserInfoDal 接口. namespace Spring.Net { ...