初识Shader

HLSL

高阶着色器语言(High Level Shader Language,简称HLSL),由微软拥有及开发的一种语言,HLSL 独立的工作在 Windows 平台上,只能供微软的Direct3D使用。 HLSL是微软抗衡GLSL的产品,同时不能与OpenGL标准兼容。

GLSL

OpenGL着色语言(OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分,使渲染管线中不同层次具有可编程性。

初识Shader_第1张图片
图片2.png

CG

初识Shader_第2张图片
Paste_Image.png

GPU语言

由于GPU采用不同于CPU的运行运算结构,因此需要一种适用于GPU的编程语言。
1、微软基于Direct3D图形库的HLSL(High Level Shading Language)
2、OpenGL ARB定义基于OpenGL图形库的GLSL(OpenGL Shading Language)
3、NVIDIA(英伟达)与微软合作研发的Cg(C for Graphics).

Cg能够同时兼容Direct3D和OpenGL图形接口。

Unity所有的渲染都需要shader来完成,内置的着色器超过80个,可以轻松利用其内置的着色器来完成各种画面效果,并且还提供了自定义shader,方便扩展。Unity使用shaderLab开发语言来组织shader内容,并会针对不同的平台进行编译,类似微软的FX文件或者NAIDIA的CgFX.

Shader,可以分为VertexShader 和PixelShader/FragmentShader两部分,简称VS,PS。学名顶点着色器和像素着色器。一旦你使用了VS和PS,则渲染过程会将VB(顶点缓冲)的数据按照IB索引(顶点索引缓冲)将每个顶点结构值分量传入VS,VS进行相应的计算和顶点变化,并将VS返回的结果再交由PS进行像素着色,输出相应的图像。概念上来说 FragmentShader会比PixelShader大很多..
这两个东西由于DX用PixelShader的缘故,其实是一个东西

Unity中可以编写3种不同的着色器:表面着色器(Surface Shader)、顶点和片段着色器(Vertex and Fragment Shaders)和固定功能管线着色器(Fixed Function Shaders).
Unity5.0,内建了基于物理渲染的StandardShader,同时还引入了完全延迟着色(FullDeferredRendering)和烘焙反射探头(Baked Reflection Probes)用于以真实环境为基础的镜面高光

物理着色:PBS (physically Based Shading):新的工业标准,用于电影产品
遵从了Conservation of Energy(能量守恒定律),只有这样才能够正真让场景里面的光源依据能量传递的方式,产生一种自然和谐的光照效果。


初识Shader_第3张图片
Paste_Image.png

Standard Surface Shader (Instanced):标准表面材质(实例化)
Unlit Shader:未点燃的材质
Image Effect Shader:图像效果材质
Compute Shader:计算着色器
Shader Variant Collection:着色器变量集合

内建Shader介绍

4.X版本提供超过80个内建Shader、包括顶点光照效果到高光、发现、反射等游戏常用的材质效果。

内建Shader分类:
普通(Normal):用于不透明对象
透明(Transparent):用于半透明和全透明对象
透明镂空效果(TransparentCutOut):用于完全透明和完全不透明部分组成(不含半透明部分)的对象,像栅栏一样。
自发光(Self-llluminated shader Family):用于能反射环境立方体贴图的不透明对象
反射(Reflective Shader Family):用于能反射环境立方体贴图的不透明对象

每个类别下包含若干复杂性各异的shader


初识Shader_第4张图片
Paste_Image.png

以光照效果计算开销从低到高排序:
Unlit : 仅使用纹理,不受光照影响
VertexLit:顶点光照
Diffuse:漫发射
Specular: 在漫反射基础上增加高光计算
Nomal Mapped : 法线贴图,增加了一张法线贴图和几个着色器指令。
Nomal Mapped Specular : 带高光法线贴图
Parallax Nomal Mapped : 视差法线贴图,增加了视差贴图计算开销
Parallax Nomal Mapped :带高光视差法线贴图

5.X版本新增加了一种基于物理着色的内建着色器,即StandardShader(标准着色器)
物理着色:PBS (physically Based Shading):新的工业标准,用于电影产品
遵从了Conservation of Energy(能量守恒定律),只有这样才能够正真让场景里面的光源依据能量传递的方式,产生一种自然和谐的光照效果。


初识Shader_第5张图片
Paste_Image.png

初识Shader_第6张图片
Paste_Image.png

StandardShader是基于物理的着色器,也就是说不管你选择什么样的贴图都会与光照产生反应,这些贴图可以是同一张图片,Unity会使用必要的资源进行计算。

原理:
遵从了Conservation of Energy(能量守恒定律),只有这样才能够正真让场景里面的光源依据能量传递的方式,产生一种自然和谐的光照效果。
表面反射的光线不会比它们收到的更多
光滑的表面会有更强的反射
醋糟的表面反射会更弱一些
高光强度会随着漫反射的强度而改变
所有的表面从某一特定角度看上去会有或多或少的高光
所有的表面在掠射角会有更多的反射

初识Shader_第7张图片
图片3.png
能量守恒:光能=漫反射+反射+折射

编写自己的Shader(详细解答Shader的各种属性及用法)

Shader "Custom/firstsharder" {//这里是Shader的名字
    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)所修饰
    //硬件将通过判定这些标签来决定什么时候调用该着色器
    //标签
        Tags
        {

        "Queue" = "Opaque"//渲染顺序 
        //Background--最早被调用的渲染,用来渲染天空盒或者背景 
        //Geometry--默认值,用来渲染非透明物体(普通情况下,场景中的绝大多数物体应该是非透明的)
        //AlphaTest--用来渲染经过Alpha Test的像素,单独为AlphaTest设定一个Queue是出于对效率的考虑
        //Overlay--用来渲染叠加的效果,是渲染的最后阶段(比如镜头光晕等特效)
         //Transparent--以从后往前的顺序渲染透明物体
          //预设的队列本质就是定义的整数(有点像枚举值)
        //Background=1000,Geometry=2000,AlphaTest=2450
        //Transparent=3000,最后Overlay=4000


        "RenderType" = "Transparent" //着色器替换功能  "Transparent" 渲染透明物体调用 "Opaqu"渲染非透明的物体
        "DisableBatching" = "True"//是否进行合批
        "ForceNoShadowCasting" = "True"//是否投射阴影
        "IgnoreProjector" = "True"//受不受projector的影响,通常用于透明物体
        "CanUseSpriteAltas" = "False"//是否用于图片的Shader,通常用于UI
        "PreviewType" = "Plane"//用作Shader面板预览的类型
         }
        //预设的队列本质就是定义的整数(有点像枚举值)
        //Background=1000,Geometry=2000,AlphaTest=2450
        //Transparent=3000,最后Overlay=4000

        //如何自定义列表
        Tags{ "Queue"="Transparent+100" }//通过调用Queue值,确保渲染的先后顺序

        //Unity的内建Diffuse着色器的设定值,这个数值决定了我们能用什么样的Shader
        //这个数值可以在unity中的质量设定中设定
//Cull off/back/front //选择渲染哪个面
        //ZTest Always/Less Greater/LEqual/Gequal/Equal/NotEqual  //深度测试
        //Zwrite off/on   //深度写入
        //Blend ScFactor DstFactor  //混合
        LOD 200//着色器的设定值
        //关于VertexLit及其系列 = 100
        //Decal, Reflective VertexLit = 150
        //Diffuse = 200
       //Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
      //Bumped, Specular = 300
      //Bumped Specular = 400
     //Parallax = 500
     //Parallax Specular = 600

    Pass
        {
             Name "PassName"//Pass 通道名称 可以在其他地方Use 该pass通道Name, Use 通道的时候名称必须大写

             Tags
            {
            "LightMode"="ForwardBase"//定义该Pass通道在unity渲染流水中的角色
            //"RequireOptions"="SoftVegetation"//用于满足某些条件时才渲染该Pass通道
            }//可以在每个Pass通道里面进行定义
        //Shader字体:也就是将输入转变成输出的代码部分
        CGPROGRAM//开始CG语言的编写
        // Physically based Standard lighting model, and enable shadows on all light types
        //surface:申明的是一个表面着色器
        //surf:着色器代码的方法的名字,下方的代码有这个函数
        //Standard:标准
        //fullforwardshadows:光照模型
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
        //在CG中,sampler2D就是和texture所绑定的一个数据容器接口
        //其实就是内存存储的RGB通道,sampler2D:就是GLSL中的2D贴图的类型
        //其他类型:sampler1D,sampler3D,samplerCube
        // 图片
        sampler2D _MainTex;
        // 用来获取MainTex的UV信息
        struct Input {
            float2 uv_MainTex;//float2:浮点数的float后面紧跟一个数字2
            vec2 coordinate;//float和vec都可以在之后加入一个2到4的数字,来表示被打包在一起的2到4个同类型数
            float4 color;
        };

        half _Glossiness;//half指的是半精度浮点数,精度最低,运算性能相对比高精度浮点数高一些
        half _Metallic;
        // 颜色属性
        fixed4 _Color;
        // SurfaceOutputStandard 表面着色器输出一个标准的结构体
        //着色器的工作核心,着色器就是给定了输入,然后给出输出进行着色的代码,第一个参数是Input结果,第二个参数是一个inout的SurfaceOutput结构
        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            // 获取图片 * 我们选定的颜色
            //fixed4:定点书:整形数据类型,作用就是把所有数进行转换,得到相应类型的整形表达
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            // 输出的像素的颜色 = 图像的颜色(RGB)
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            // 输出的颜色效果(金属方面) = 设定的金属值
            o.Metallic = _Metallic;
            // 输出的光滑粗糙程度 = 设置的光滑粗燥程度
            o.Smoothness = _Glossiness;
            // 输出的透明通道 = 图像的透明通道
            o.Alpha = c.a;
        }
}
        ENDCG//结束CG语言的编写
    }
    FallBack "Diffuse"
}
初识Shader_第8张图片
642887-57f1485a1e706ea0.png

参考

https://docs.unity3d.com/Manual/SL-SurfaceShaderExamples.html
https://onevcat.com/2013/08/shader-tutorial-2/
http://www.tuicool.com/articles/JvYJ3em
http://www.itnose.net/detail/6143450.html

CG语言基础知识:

内置元类型
Float : 32bit浮点类型
Half: 16bit浮点
Int : 32bit整形
Fixed : 12bit定点
Bool : 布尔值
Sampler:纹理对象的句柄
String:不是每个都支持

cg提供内置的向量数据类型(build-in vector data types)
float1、float4,
bool2, bool3,
float1x1
float2x3
类型转换跟C是一样的,用强制转化。
类型定义的时候可以在常量后跟后缀,如2.0f,1.0h,3x。目前值有f,h,x(fixed)三种。

支持类型
1、数组
float a[10];
float4 b[10];
int length = a.length; //获取长度,上面两个返回都是10

float b[2][3] = { { }, { } };
int length1 = b.length; // length1 = 2;
int length2 = b[0].length; // length = 3;

2、结构
以struct开始,紧跟名字,内容用{};包住。不要忘记最后的分号。
结构中可以带function,是C++中的用法。
结构不支持继承。

3、特定关键字
in , out , inout,
uniform (被修饰的变量从外部传入), const ,
4、输入语义关键字
Vertex Shader的输入:

POSITION, NORMAL, BINORMAL, BLENDINDICES, BLENDWEIGHT, TANGENT, PSIZE, TEXCOORD0 ~ TEXCOORD7

如:in float4 modelPos: POSITION

Vertex Shader的输出, 也就是Pixel Shader的输入
POSITION, PSIZE, FOG,COLOR0 ~ COLOR1, TEXCOORD1 ~ TEXCOORD7
Pixel Shader的输出:

COLOR

5、入口函数
通过观察程序的输入输出语义绑定,就可以区分入口函数对应到顶点程序还是片段程序。

6、内置函数库
reflect 求发射向量
refract 求折射向量
mul 矩阵相乘
normalize 归一化

CG语言的学习资料:

http://blog.csdn.net/liu_lin_xm?viewmode=contents
https://developer.nvidia.com/cg-toolkit

你可能感兴趣的:(初识Shader)