初识Shader

HLSL

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

GLSL

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

图片2.png

CG

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(能量守恒定律),只有这样才能够正真让场景里面的光源依据能量传递的方式,产生一种自然和谐的光照效果。


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


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(能量守恒定律),只有这样才能够正真让场景里面的光源依据能量传递的方式,产生一种自然和谐的光照效果。


Paste_Image.png

Paste_Image.png

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

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

图片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的影响,通常用于透明物体,如果为true,此着色器的对象将不受Projectors的影响

        "CanUseSpriteAltas" = "False"//是否用于图片的Shader,通常用于UI,`CanUseSpriteAtlas`如果着色器用于Sprite则将标签设置为“ False”

        "PreviewType" = "Plane"//用作Shader面板预览的类型
         }
        //预设的队列本质就是定义的整数(有点像枚举值)
        //Background=1000,Geometry=2000,AlphaTest=2450
        //Transparent=3000,最后Overlay=4000

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


        //Unity的内建Diffuse着色器的设定值,这个数值决定了我们能用什么样的Shader
        //这个数值可以在unity中的质量设定中设定

//Render设置 可选
//Cull off/back/front //选择渲染哪个面
Cull off//默认渲染正面,设置Cull off意思是关闭裁剪, 那就是正反两面都渲染
Cull back//只渲染背面
Cull front//只渲染前面


        //ZTest Always/Less Greater/LEqual/Gequal/Equal/NotEqual  //深度测试   默认使用小于等于
ZTest Always  //总是
ZTest Less Greater//小于
ZTest LEqual//小于等于
ZTest Gequal//大于等于
ZTest Equal//等于
ZTest NotEqual//不等于

        //Zwrite off/on   //深度写入
Zwrite off
Zwrite on
        //Blend SrcFactor DstFactor  //混合
        LOD 200//不同情况下使用不同的LOD,达到性能提升
        //关于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"
}
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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容