《U3D_Shader编程》
##《U3D_Shader编程》发布说明:
++++Shader一个高大上的领域,不管怎么样,我来了。
++++立钻哥哥从2018年开始正式对Shader进行战略布局。
++++《U3D_Shader编程》将从零开始,循序渐进探索,还是先探索一段时间吧,后期根据需要再推出一个精品博文,这篇就算一个杂谈吧。
##《U3D_Shader编程》目录:
#第一篇:快速入门篇
#第二篇:基础夯实篇
#第三篇:基础进阶篇
#第四篇:中级挑战篇
#第五篇:高级成魔篇
#第一篇:快速入门篇
#第一篇:快速入门篇
++++第一章:Shader着色器
++++第二章:Surface/Vertex Shader
++++第三章:Shader案例
##第一章:Shader着色器
++第一章:Shader着色器
++++1.1、什么是Shader
++++1.2、什么是渲染管线
++++1.3、Shader和材质,贴图的关系
++++1.4、三大主流的高级编程语言
++++1.5、Unity Shader的组织形式
++++1.6、固定管线Shader
++1.1、什么是Shader
++++Shader,中文翻译即着色器,是一种较为短小的程序片段,用于告诉图形硬件如何计算和输出图像。(过去由汇编语言编写,现在可以使用高级语言来编写。)
++++Shader就是可编程图形管线的算法片段。
++++Shader主要分为两类:Vertex Shader(顶点着色)和Fragment Shader(片段着色)。
++1.2、什么是渲染管线
++++渲染管线也称为渲染流水线,是显示芯片内部处理图形信号相互独立的并行处理单元。(一个流水线是一系列可以并行和按照固定顺序进行的阶段。)(每个阶段都从它的前一阶段接收输入,然后把输出发给随后的阶段。)
++++渲染管线包括:应用程序阶段(Application State)、几何阶段(Geometry Stage)、光栅化阶段(Rasterizer Stage)、后期缓冲(Back Buffer)等阶段。
++++应用程序阶段(Application State):
--准备场景数据:将数据(摄像机位置、视锥体、场景中的模型、光源等)加载到显存中;
--粗粒度剔除(culling);
--设置模型的渲染状态:指定材质(漫反射颜色、高光颜色)、指定纹理、指定Shader(指定顶点着色器(Vertex Shader)、指定片元着色器(Fragment Shader))、指定光源属性。
--调用DrawCall:发起方CPU、接收方GPU、命令缓冲区(Command Buffer,可放入改变渲染状态、DrawCall在内的多种命令。)
=>>>>输出渲染图元(rendering primitives):进入下一阶段(几何阶段(Geometry Stage))
++++几何阶段(Geometry Stage):
--顶点着色器(Vertex Shader):完全可编程,通常用于实现顶点的空间变换、顶点着色等功能。
----坐标变换:对顶点坐标进行某种变换(可模拟水面、布料等);把顶点坐标从模型空间转换到齐次裁剪空间,接着通常再由硬件做透视除法后,最终得到归一化的设备坐标(NDC:Normalized Device Coordinates)。
----逐顶点光照。
----输出后续阶段所需的数,如纹理坐标。
--曲面细分着色器(tessellation Shader):用于细分图元。
--几何着色器(geometry Shader):执行逐图元(perPrimitive)的着色操作或产生更多图元。
--裁剪(Clipping):将摄像机视野外的顶点裁剪掉,并剔除某些三角图元的面片。
--屏幕映射(Screen Mapping):把每个图元的坐标转换到屏幕坐标中。(只将x和y坐标缩放到屏幕坐标系(Screen Coordinates),z值保留,屏幕坐标系和z坐标一起构成了窗口坐标系(Window Coordinates))
=>>>>输出屏幕空间的顶点信息:进入下一阶段(光栅化阶段(Rasterizer Stage))
++++光栅化阶段(Rasterizer Stage):
--三角形设置(Triangle Setup):计算光栅化一个三角网格所需的信息。
--三角形遍历(Triangle Traversal):检查每个像素是否被一个三角网格覆盖,如果被覆盖的话,就生成一个片元(fragment)。(一个片元并不是像素,而是包含了很多状态的集合。)
--片元着色器(Fragment Shader):用于实现逐片元(Per-Fragment)的着色操作。(纹理采样)
--逐片元操作(Per-Fragment Operations,OpenGL的说法)或称输出合并阶段(Output-Merger,DirectX的说法)
----模板测试(Stencil Test):该片元的模板值(使用读取掩码在模板缓冲区(Stencil Buffer)中读取)、参考值(reference value:使用读取掩码)。(使用开发者指定的比较函数决定是否舍弃该片元:不管通过与否都能修改模板缓冲区的值)
----深度测试(Depth Test):该片元深度值、深度缓冲区的深度值。(使用开发者指定的比较函数决定是否通过:通过才有资格修改深度缓冲区的值。(通过开启/关闭深度写入实现))
----混合(Blend):源颜色(片元着色器得到的颜色)、模板颜色(颜色缓冲区中的颜色)。(使用混合函数进行混合操作)
=>>>>输出图形:进入下一阶段(后置缓冲(Back Buffer))
++++后置缓冲(Back Buffer):使用双重缓冲(Double Buffering)策略避免看到正在进行光栅化的图元。(渲染完成后通过一个swap交换操作将前置缓冲(Front Buffer)和后置缓冲中的内容交换。)
++1.3、Shader和材质,贴图的关系
++++Shader是图形可编程方案的程序片段。Shader实际上就是一小段程序,它负责将输入的顶点数据以指定的方式和输入的贴图或者颜色等组合起来,然后输出。(绘图单元可以根据这个输出来将图像绘制到屏幕上。)
++++渲染管线是一种计算机从数据到最终图形成像的描述。输入的贴图或颜色等,加上对应的Shader,以及对Shader的特定的参数设置,将这些内容打包存储到一起得到的就是一个Material(材质)。(之后我们便可以将材质赋予三维物体来进行渲染(输出)了。)
++++材质是商品,Shader是方法,贴图是材料。(材质好比引擎最终使用的商品,Shader好比是生产这种商品的加工方法,而贴图就是原材料。)
++1.4、三大主流的高级编程语言(GLSL、HLSL、Cg)
++++目前Shader Language有三种语言:GLSL(基于OpenGL的OpenGL Shading Language)、HLSL(基于DirectX的High Level Shading Language)、Cg语言(NVIDIA公司的C for Graphic)。
++++OpenGL(Open Graphics Library):定义了一个跨编程语言、跨平台的编程接口规范的专业的图形程序接口。(它用于三维图像(二维亦可),是一个功能强大,调用方便的底层图形库。)(顶点数组的特性:提高顶点位置、法线、颜色、色彩指数、纹理坐标、多形边缘标识的传输速度。)(OpenGLShading Language:用于着色对象、顶点着色以及片段着色技术的扩展功能。)
++++DirectX(Direct eXtension,简称DX):是由微软公司创建的多媒体编程接口。(由C++编程语言实现,遵循COM。)
++++Cg语言(C for Graphics):是为GPU编程设计的高级着色器语言。(由NVIDIA公司开发。)(Cg极力保留C语言的大部分语义,并让开发者从硬件细节中解脱出来,Cg同时也有一个高级语言的其他好处,如代码的易重用性,可读性得到提高,编译器代码优化等。)
++1.5、Unity Shader的组织形式(ShaderLab基本结构)
++++Unity中的Shader称之为ShaderLab,语法结构:
Shader “name”{
[Properties] //可选(在Inspector面板上显示)
SubShaders //必选(Shader的核心代码)
[Fallback] //可选(默认Shader)
}
++++【Properties】:属性定义,用来定义着色器中使用的贴图资源或者数值参数等,这些属性会在Inspector视图的材质界面中显示,可以方便的进行设置和修改。
++++【SubShader】:子着色器,一个着色器中包含有一个或者多个子着色器,Unity会从上到下遍历子着色器,找到第一个能被用户设备支持的子着色器,并使用该着色器渲染,如果都不能使用,则使用备用着色器。
++++【Fallback】:备用着色器,是对硬件要求最低的着色器。
++++ShaderLab基本结构:
Shader “MyShader”{
Properties{
_MyTexture(“My Texture”, 2D) = “white”{ };
//这里还可以写其他属性,如颜色等。
}
SubShader{
//立钻哥哥:这里才是真正的Shader代码
//--表面着色器(SurfaceShader)
//--顶点片段着色器(Vertex and Fragment Shader)
//--固定管线着色器(Fixed Function Shader)
}
SubShader{
//立钻哥哥:这里可以写简化版的Shader
//当由于设备性能不够,上面的SubShader无法运行时,就会运行这个Shader
}
}
++++内建Shader:
--Unlit:不发光(这只是一个纹理,不被任何光照影响。)
--VertexLit:顶点光照。
--Diffuse:漫反射。
--Normal mapped:法线贴图。(比漫反射更昂贵:增加了一个或多个纹理(法线贴图)和几个着色器结构。)
--Specular:高光。(这增加了特殊的高光计算。)
--Normal Mapped Specular:高光法线贴图。(这比高光更昂贵一点。)
--Parallax Normal mapped:视差法线贴图。(这增加了视差法线贴图计算。)
--Parallax Normal Mapped Specular:视差高光法线贴图。(这增加了视差法线贴图和镜面高光计算。)
++1.6、固定管线Shader
++++固定管线Shader:propeties、material、lighting、set texture、Alpha通道。
++++properties:
Properties{
//立钻哥哥:定义属性(将显示在inspector中)
_Color(“Main Color”, color) = (1,1,1,1) //颜色
_Ambient(“Ambient”, color)=(0.3,0.3,0.3,0.3) //环境光
_Specular(“Specular”, color)=(1,1,1,1) //高光
_Shininess(“Shininess”, range(0,8))=4 //默认为4,高光部分的范围大小
_Emission(“Emission”, color)=(1,1,1,1) //自发光
_Maintex(“MainTex”,2d)=”” //第一张纹理图
_Secondtex(“Secondtex”,2d)=”” //第二张纹理图
}
++++material:
material{
//使用属性
diffuse[_Color]
ambient[_Ambient]
specular[_Specular]
shininess[_Shininess]
emission[_Emission]
}
++++lighting:
--lighting on
--separatespecular on
++++set texture:
//设置纹理图片
settexture[_Maintex]{
//合并贴图与之前设置好的颜色/高光等信息
//double表示高亮度提高2倍
//primary表示material里面的信息
combine texture * primary double
}
++++Alpha通道:
_Constant(“ConstantColor”, color)=(1,1,1,0.3)
SubShader{
//渲染队列
Tags{ “Queue” = “Transparent”}
Pass{
//Alpha通道处理
Blend SrcAlpha OneMinusSrcAlpha
//previous之前的
settexture[_Secondtex]{
constantColor[_Constant]
//合并第二张贴图与之前设置的所有信息
combine texture * previous double, texture
//,后面加texture表示使用贴图本身的alpha信息
}
}
}
++Shader简单示例:
Shader “YlzShaderDemo/shader1”{
Properties{
//立钻哥哥:定义属性,将显示在inspector中
_Color(“Main Color”, color)=(1,1,1,1) //颜色
_Ambient(“Ambient”, color)=(0.3,0.3,0.3,0.3) //环境光
_Specular(“Specular”, color)=(1,1,1,1) //高光
_Shininess(“Shininess”, range(0,8))=4 //默认为4(高光部分的范围大小)
_Emission(“Emission”, color)=(1,1,1,1) //自发光
_Constant(“ConstantColor”, color)=(1,1,1,0.3)
_Maintex(“MainTex”,2d)=”” //第一张纹理图
_Secondtex(“Secondtex”,2d)=”” //第二张纹理图
}
SubShader{
Tags{ “Queue” = “Transparent”} //渲染队列
Pass{
Blend SrcAlpha OneMinusSrcAlpha //Alpha通道处理
material{
//使用属性
diffuse[_Color]
ambient[_Ambient]
specular[_Specular]
shininess[_Shininess]
emission[_Emission]
}
lighting on
spearatespecular on
//设置纹理图片
settexture[_Maintex]{
//合并贴图与之前设置好的颜色/高光等信息
//double表示亮度提高2倍
//primary表示material里面的信息
combine texture * primary double
}
//previous之前的
settexture[_Secondtex]{
constantColor[_Constant]