Unity shader入门精要学习笔记-初级篇(unityshader简单制作/unity基础光照/基础纹理/透明效果)

目录

一、unityshader简单制作

1.顶点/片元着色器

基本结构

顶点/片元着色器简单代码

结构体与模型数据

顶点着色器和片元着色器间的通信

属性使用

2.Unity提供的内置文件和变量

3.Unity提供的CG/HLSL语义

unity支持的语义

4.debug

5.渲染平台差异

二、unity基础光照

1.光照模型

1.BRDF光照模型

2.标准光照模型(经验模型)

3.计算:逐像素还是逐顶点

2.unity中的环境光和自发光

1.漫反射光照模型

2.高光反射光照模型

3.使用unity内置的函数

三、基础纹理

1.单张纹理

2.凹凸映射

3.渐变纹理

4.遮罩纹理

四、透明效果

1.Unity Shader的渲染顺序

2.透明度测试

3.透明度混合

4.开启深度写入的半透明效果

5.shaderlab的混合命令


一、unityshader简单制作

1.顶点/片元着色器

基本结构

shader ”MyShader“ {//命名

Properties{

        Name{"display name",PropertyType}=DefaultValue//属性名字:Name 显示名字:display name  类型:PropertyType  默认值:DefaultValue

}

SubShader{

        [Tags]//可选的标签,仅可在subshadeer中声明

        Tags{"TagName1"="Value1"  "TagName2"="Value2" }

        [RenderSetup]//可选的状态,Cull、ZTest、ZWrite、Blend

        Pass{

                [Name]

                Name "MyPassName"

                [Tags]//LightMode/RequireOptions

                [RenderSetup]

               CGPROGRAM

               #pragma vertex vert

               #pragma fragment frag

               ENDCG

        }

//UsePass 使用其他shader中的Pass,UsePass ”MyShader/MYPASSNAME“

//GrabPass负责抓取屏幕并将结果存储在一张纹理中

Fallback “name” / Fallback Off

}


顶点/片元着色器简单代码

        Pass{

               CGPROGRAM

               #pragma vertex vert//哪个告诉unity,哪个函数包含了顶点着色器的代码:vert

               #pragma fragment frag

              float4 vert(float4 v :POSITION):SV_POSITION{//把模型顶点坐标填充到输入参数v,SV_POSITION告诉unity顶点着色器的输出是裁剪空间中的顶点坐标

                            return mul (UNITY _MATRIX_MVP,v);//顶点坐标从模型空间转换到裁剪空间,模型观察投影矩阵

              }

              fixed4 frag():SV_Target{//没有输入,输出是 fixed4 类型变量使用SV_Target语义限定,将用户的输出颜色存储到一个渲染目标中

                           return fixed4 (1.0,1.0,1.0,1.0);//表示白色的变量

              }

               ENDCG

        }


结构体与模型数据

        Pass{

               CGPROGRAM

               #pragma vertex vert//哪个告诉unity,哪个函数包含了顶点着色器的代码:vert

               #pragma fragment frag

               struct a2v{

                              float4 vertex:POSITION;//POSITION告诉unity用模型空间的顶点坐标填充vertex

                              float3 normal:NORMAL;//NORMAL告诉unity用模型空间的法线方向填充normal

                              float4 texcoord:TEXCOORD0;//TEXCOORD0告诉unity用模型的第一套纹理坐标填充texcoord

               }

              float4 vert(a2v v):SV_POSITION{//SV_POSITION告诉unity顶点着色器的输出是裁剪空间中的顶点坐标

                            return mul (UNITY _MATRIX_MVP,v.vertex;//v.vertex来访问模型空间的顶点坐标

              }

              fixed4 frag():SV_Target{//没有输入,输出是 fixed4 类型变量使用SV_Target语义限定,将用户的输出颜色存储到一个渲染目标中

                           return fixed4 (1.0,1.0,1.0,1.0);//表示白色的变量

              }

               ENDCG

        }


顶点着色器和片元着色器间的通信

        Pass{

               CGPROGRAM

               #pragma vertex vert//哪个告诉unity,哪个函数包含了顶点着色器的代码:vert

               #pragma fragment frag

               struct a2v{

                              float4 vertex:POSITION;//POSITION告诉unity用模型空间的顶点坐标填充vertex

                              float3 normal:NORMAL;//NORMAL告诉unity用模型空间的法线方向填充normal

                              float4 texcoord:TEXCOORD0;//TEXCOORD0告诉unity用模型的第一套纹理坐标填充texcoord

               }

 

               struct v2f{

                              float4 pos:SV_POSITION;

                             fixed3 color:COLOR0;

               }

              v2f vert(a2v v):SV_POSITION{//SV_POSITION告诉unity顶点着色器的输出是裁剪空间中的顶点坐标

                           v2f o;

                           o.pos=mul(UNITY_MATRIX_MVP,v.vertex);

                           o.color=v.normal*0.5+fixed3(0.5,0.5,0.5);

                           return o; 

             }

              fixed4 frag(v2f i):SV_Target{

                           return fixed4 (i.color,1.0);

              }

               ENDCG

        }


属性使用

shader ”MyShader“ {//命名

Properties{

        _Color("Color Tint",Color)=(1.0,1.0,1.0,1.0);

}

SubShader{ 

        Pass{           

               CGPROGRAM

               #pragma vertex vert

               #pragma fragment frag

               fixed4 _Color;

               struct a2v{

                              float4 vertex:POSITION;//POSITION告诉unity用模型空间的顶点坐标填充vertex

                              float3 normal:NORMAL;//NORMAL告诉unity用模型空间的法线方向填充normal

                              float4 texcoord:TEXCOORD0;//TEXCOORD0告诉unity用模型的第一套纹理坐标填充texcoord

               }

 

               struct v2f{

                              float4 pos:SV_POSITION;

                             fixed3 color:COLOR0;

               }

              v2f vert(a2v v):SV_POSITION{//SV_POSITION告诉unity顶点着色器的输出是裁剪空间中的顶点坐标

                           v2f o;

                           o.pos=mul(UNITY_MATRIX_MVP,v.vertex);

                           o.color=v.normal*0.5+fixed3(0.5,0.5,0.5);

                           return o; 

             }

              fixed4 frag(v2f i):SV_Target{

                           fixed3 c=i.color;

                           c*=_Color.rgb;

                           return fixed4 (c,1.0);

              }

               ENDCG

        }

}


2.Unity提供的内置文件和变量

内置的包含文件

CGPROGRAM

#include “UnityCG.cginc"

ENDCG

CGincludes文件夹包含了所有的内置包含文件

Unity shader入门精要学习笔记-初级篇(unityshader简单制作/unity基础光照/基础纹理/透明效果)_第1张图片

Unity shader入门精要学习笔记-初级篇(unityshader简单制作/unity基础光照/基础纹理/透明效果)_第2张图片


3.Unity提供的CG/HLSL语义

语义:赋给shader输入和输出的字符串,这个字符串表达了这个参数的含义,可以让shader知道从哪里读取数据,并把数据输出到哪里。

unity并不支持所有的语义。

系统数值语义SV_开头,被修饰的变量包含了可用于光栅化的变换胡的顶点坐标(即齐次裁剪空间中的坐标),默认会经过光栅化后显示在屏幕上

unity支持的语义

Unity shader入门精要学习笔记-初级篇(unityshader简单制作/unity基础光照/基础纹理/透明效果)_第3张图片


4.debug

1.使用假彩色图像

把需要调试的变量映射到[0,1],作为颜色输出到屏幕上,然后通过屏幕上的像素颜色来判断这个值是否正确。

2.vs Graphics Debugger

3.帧调试器

window-Frame Debugger打开

5.渲染平台差异

1.渲染纹理的坐标差异

openGL进行屏幕映射 左下角为原点

DirectX右上角为原点

2.shader语法差异

3.shader语义差异

4.其他平台差异

5.float/half/fixed

Unity shader入门精要学习笔记-初级篇(unityshader简单制作/unity基础光照/基础纹理/透明效果)_第4张图片


二、unity基础光照

辐照度:对于平行光,可通过计算在垂直于l的单位面积上单位时间内穿过的能量来得到。

散射:只改变光线的方向,但不改变光线的密度和颜色。

              折射/透射(漫反射diffuse):散射到物体内部,与内部颗粒进行相交

              反射(高光反射specular):散射到物体外部,

吸收(漫反射diffuse):只改变光线的密度和颜色,不改变方向

着色:根据材质属性、光源信息,使用一个等式去计算沿着某个观察方向的出射度的过程。这个等式称作光照模型lighting model


1.光照模型

1.BRDF光照模型

图形学中大多使用一个数学公式来表达,并且提供了一些参数来调整材质属性。

当给定入射光线的方向和辐照度后BRDF可以给出在某个出射方向上的光照能量分布。

2.标准光照模型(经验模型)

              自发光(emissive):Cmissive 当给定一个方向时,一个表面本身会向该方向发射多少辐射量。如果没有使用全局光照,并不会照亮周围的物体只是本身更亮。

              高光反射(specular):Cspecular 当光线从光源照射到模型表面时,该表面会在完全镜面反射方向散射多少辐射量。

                            phong模型  r=2(n•I)n-I  表面法线n、视角方向v、光源方向I、反射方向r

                            Cspecular=(Clight•mspecular)max(0,v•r)^{\mathbf{m}gloss}  mgloss是材质的光泽度也称为反光度mspecular是材质的高光反射颜色,Clight光源颜色

                            Blinn模型 引入矢量h h=v+I/(|v+I|)    Cspecular=(Clight•mspecular)max(0,n•h)^{\mathbf{m}gloss}  //摄像机和光源足够远会快于phong,

                            //不能表现菲涅耳反射 各项同性:固定视角和光源反射不变,

              漫反射(diffuse):Cdiffuse 当光线从光源照射到模型表面时,该表面会向每个方向散射多少辐射量。 

                           兰伯特模型  Cdiffuse=(Clight•mdiffuse)max(0,n•I)   n表面法线,I指向光源的单位矢量,mdiffuse材质漫反射颜色,Clight光源颜色

                           半兰伯特模型 :Cdiffuse=(Clight•mdiffuse)(a(n•I)+β)  没有使用max来防止点积为负而是使用一个a倍缩放加上一个β偏移,一般都取0.5

                                                     Cdiffuse=(Clight•mdiffuse)(0.5(n•I)+0.5)

              环境光(ambient):Cambient 描述其他所有的间接光照。

3.计算:逐像素还是逐顶点

逐像素光照:片元着色器计算,以每个像素为基础,得到它的法线进行光照模型计算。Phong着色

逐顶点光照:顶点着色器,每个顶点上计算光照,渲染图元内部线性插值。高洛德着色Gouraud//计算量小但是不适合非线性计算,产生棱角


2.unity中的环境光和自发光

具体写在代码篇里了  https://blog.csdn.net/louxiasang/article/details/114458670

环境光控制:Window-lighting-Ambient Source/Ambient Color/Ambient Intensity

内置变量:UNITY_LIGHTMODEL_AMBIENT

1.漫反射光照模型

2.高光反射光照模型

3.使用unity内置的函数


三、基础纹理

具体写在代码篇里了 https://blog.csdn.net/louxiasang/article/details/114549162

利用纹理展开技术把纹理映射坐标存储在每个顶点上,纹理映射坐标(UV坐标)定义了该顶点在纹理中对应的2D坐标,使用(u,v)来表示。

1.单张纹理

我们在之前的Blinn-Phong光照模型基础上计算光照。

1.纹理面板中的第一个属性是纹理类型,Alpha form Grayscale复选框,勾选后透明通道的值会由每个像素的灰度值生成。

2.Wrap Mode它决定了当纹理坐标超过[0,1]范围后将会如何平铺:

Repeat、Clamp

3.Tilling平铺属性。

4.Filter Mode属性:当纹理由于变换而产生拉伸时将会采用哪种滤波模式。

Point Bilinear Trilinear三种模式效果依次提升但是耗费性能也依次增大,会影响放大缩小时纹理得到的图片质量。

Point:最近邻滤波,采样像素只有一个,看起来有像素风格

Bilinear:找到四个邻近像素进行线性插值混合,看起来被模糊了(常用)

Trilinear:比Bilinear多了一个在多级渐远纹理之间进行混合

纹理缩小更为复杂,多级渐远纹理技术:原纹理提前用滤波处理来得到更多更小的图像,当物体远离摄像机时可以直接使用较小的纹理。缺点是要空间存储这些纹理,通常是33%。

多级渐远纹理开启:纹理类型advanced勾选Generate Mip Maps。可以选择是否使用线性空间以及采用的滤波器。

5.纹理的最大尺寸和纹理模式

2.凹凸映射

凹凸映射使用一张纹理来修改模型表面的法线。

1.高度纹理height map

模拟表面位移displacement然后得到一个修改后的法线,也称为高度映射。

高度图中存储的是强度值intensity,用于表示模型表面局部的海拔高度。

颜色越浅越向外凸起,颜色越深越凹。好处:直观 缺点:复杂,实时计算不能直接得到表面法线要根据灰度值计算。

2.法线纹理

存储表面法线方向,法线方向的分量范围[-1,1],而像素是[0,1]所以我们需要做一个映射。

pixel=(normal+1)/2   normal=pixel*2-1

模型空间的法线纹理(直接想法,更符合直观认识)、切线空间的法线纹理(实际制作,简单直观、在纹理坐标的缝合处和尖锐边角部分可见的突变较少更为平滑、自由度很高、可进行UV动画、可以重用法线纹理、可压缩)

3.Unity中的法线纹理类型

把纹理设置成normal map时,可以让unity根据不同平台对纹理进行压缩在通过UnpackNormal函数来针对不同的压缩格式对法线纹理进行正确的采样。

从高度图中生成法线纹理:导入高度图,设置成Normal map勾选Create from Grayscale。

3.渐变纹理

使用渐变纹理来控制漫反射光照的结果。

4.遮罩纹理

遮罩允许我们保护某些区域,应用于某些反光强烈某些弱或者只做地形时混合多张图片。

一般流程:通过采样得到遮罩纹理纹素值,使用某个或几个通道的值来与某种表面属性进行相乘,当通道值为0就可以不受影响。

我们可以利用一张纹理的RDBA四个通道用以存储不同属性,例如高光反射强度在R,边缘光照强度在G,高光反射指数在B,自发光强度在A


四、透明效果

具体写在代码篇里了https://blog.csdn.net/louxiasang/article/details/114681917

透明通道,当开启透明混合后,当一个物体被渲染到屏幕上时,每个片元除了颜色值和深度值还有透明度,透明度为1完全不透明0完全不现实。

两种方法:透明度测试、透明度混合

不透明物体:深度缓冲 z-buffer 用于解决可见性问题,基本思想是根据深度缓存中的值来判断该片元距离摄像机的距离,当渲染一个片元时,需要把它的深度值和已经存在于深度缓存中的值进行比较,更远的话不渲染,更近的话覆盖颜色缓冲中的值并更新到深度值。

透明度测试:片元透明值不满足条件就舍弃,否则就按不透明物体处理。透明度测试不需要关闭深度写入,只是根据透明度来舍弃一些片元。效果极端,要么完全透明要么不透明。

透明度混合:使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色。需要关闭深度写入没有关闭深度测试。

渲染引擎一般会对物体进行排序再渲染:1.先渲染所有不透明物体并开启它们的深度测试和深度写入。2.把半透明物体按照它们距离摄像机的远近进行排序,按照从后向前的顺序渲染这些半透明,开启深度测试,关闭深度写入。

但是循环重叠的物体会出问题,凸面体、拆分成子模型、分割网格、开启深度写入的半透明效果可以减少错误。

1.Unity Shader的渲染顺序

渲染队列:用Subshader的Queue标签来决定我们的模型将归于哪个渲染队列。

索引号越小表示越早被渲染。

透明度测试:

Subshader{

  Tags{“Queue”=“Transparent”}

  Pass{

}

}

透明度混合:

Subshader{

  Tags{“Queue”=“AlphaTest”}

  Pass{

Zwrite Off;

}

}

2.透明度测试

3.透明度混合

4.开启深度写入的半透明效果

5.shaderlab的混合命令

混合是一个逐片元且不可编程但是可以高度可配置的。

混合等式:一个用于混合RGB通道、一个用于混合A通道。默认使用加操作。

1.Blend 混合因子A 混合因子B :使用同样的混合因子来混合RGB通道和A通道

2.Blend 混合因子A 混合因子B,混合因子C 混合因子D :Orgb=混合因子A x Srgb+混合因子B x Drgb;Oa=混合因子A x Sa+混合因子B x Da

Unity shader入门精要学习笔记-初级篇(unityshader简单制作/unity基础光照/基础纹理/透明效果)_第5张图片


 

你可能感兴趣的:(UnityShader,shader)