我是靠谱客的博主 糊涂衬衫,这篇文章主要介绍Unity图形学之三种自定义Shader(八)                二、Unity中的三种Shader介绍                       三、Unity中的三种自定义Shader代码编写                   ,现在分享给大家,希望可以做个参考。

       Unity中的Shader都是要通过ShaderLab的基本语法进行编写。

        一、  下面我们先从Shaderlab基本语法开始入手

ShaderLab基本结构大致3个代码块儿(一、二、三)

(一) 属性  【Properties】

Shader “name”{

                          【Properties】//属性
                           }

属性模块允许我们在可视化面板当中为材质添加要使用的原材料。

(二) Subshader算法   

        SubShader是专门为GPU渲染所编写的Shader的片段在ShaderLab中至少有一个SubShader,当然也可多个。

但是,显卡每次渲染处理的时候只能选择一个SubShaders执行。那多个SubShader的作用是为了不同硬件的渲染支持,为了Shader能在比较老的图形显卡中也能支持。一般比较越往下的SubShader要简化,运算指令要简单。

(三) 【FallBack】//后退

  作用是:如果SubShader里的所有算法都不能执行的话,就会后退回到最初始的状态 可以认为是默认(一般是所有硬件都支持的渲染方式)     

比如:  FallBack "Diffuse"   返回到漫反射的状态   

                二、Unity中的三种Shader介绍

 

 

 (一) surface shaders, 表面着色器(默认创建的Shader类型)

      Unity当中被推荐和鼓励使用的Shader,当你在Unity当中创建一个Shader时,默认的就是Surface Shader 。由于图型管线只识别vertex shaders   and  fragment shader这两种形式。Surface Shader 是在vertex shaders   and  fragment shader上面的的一种包装,最 终Unity 引擎还是会把Surface Shader 编译成能够被硬件识别和调用的vertex shaders   and  fragment shader.。Surface Shader 让我们可以不用去关心这些顶点和片段程序的细节,可以直接得到我们想要的着色器。这个着色器处理了很多光照细节。

 

   (二)vertex and fragment shaders 顶点和片元着色器

      针对于比较细节上的处理,偏向于底层,可编程图形管线当中能够编写Shader的部分有两个:vertex shaders和 fragment shader。

 

(三)fixed function shaders.固定功能管线着色器

   比如光照、纹理采样。 所有硬件平台都可支持,针对硬件能够执行的基本命令的Shader,当然,功能有限,但是,速度最快。

 

 

 

 

           

           三、Unity中的三种自定义Shader代码编写                   

     (一)我们以fixed function shaders固定功能管线着色器

 首先物体受光照影响表现:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Shader "MyCustom/MyShader" { Properties {//属性 // 属性名字 界面显示名 类型 值 _Color("MyColor",color) = (1,0,0,1) _AmbientColor("AmbientColor",color) = (1,0,0,1) _SpecularColor("SpecularColor",color) = (1,0,0,1) _Shininess("Shininess",range(0,8)) = 3 _Emission("EmissionColor",color) = (1,1,1,1) _MainTexture("MainTexture",2d) = "" } SubShader {//shader算法 pass//通道(存储图像的色彩) { //color(1,0,0,1) //()表示直接赋值,固定值 //color[_Color]//【】中括号表示使用参数值 material { //漫反射 必须依照光照,与灯光配合,将光打到物体表面反射光,我们才能看到物体 diffuse[_Color]//漫反射命令,要想受光照影响,必须启用光照 lighting on ambient[_AmbientColor]//环境光 specular[_SpecularColor]//高光 shininess[_Shininess]//滑动条高光反射系数,配合启用高光的命令separateSpecular on emission[_Emission]//自发光 } lighting on//启动光照 separateSpecular on //启用高光 SetTexture[_MainTexture]//设置纹理 { //与材质效果混合 double 是图片亮度的表现 combine Texture*primary double } } } // Fallback "Diffuse" //固定功能管线着色器,几乎所有硬件都支持,所以这句话可以不要 }

Properties 属性

Material 材质

Lighting光照

Settexture设置纹理

Pass通道(存储图像的色彩,色彩为什么是RGB,因为RGB是计算机颜色的三原色

表面着色器surface shaders没有Pass通道,因为它是vertex and fragment shaders 的包装,vertex and fragment shaders顶点片元着色器有Pass通道

      (二)表面着色器surface shaders的Shader代码案例

       如果想要实现些稍微复杂的效果, 就要用到表面着色器。表面着色器一般会用到CG代码块儿。

 代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Shader "Custom/NewSurfaceShader" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} ///_Normalmap ("Normalmap", 2D) = "Normal" {} _Cubemap ("Cubemap", CUBE) = "Cube" {}//CUBE unity的立方体贴图 _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 } SubShader { Tags { "RenderType"="Opaque" }//描述渲染类型,当前是不透明的物体//Tags {"queue" = "transparent"}//透明的物体 LOD 200 //层级细节 CGPROGRAM//代表当前是CG代码块,开始写CG语言了 // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows//编译指令 //#pragma编译指令告诉我们surface关键词是一个表面着色器 , //surf是调用的方法 ,下面有一个surf方法 //Standard 光照表现 基于物理的光照模型,就是我们现在所说的全局光照,物体与物体之间的影响, //(5.0之前是漫反射 Lambert只是受到光照而已,5.0之后实现了次时代的效果) //fullforwardshadows 阴影表现(平行光、点光、聚光都是有阴影的) // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 //表示GPU硬件支持3.0 不写这句话默认是2.0 sampler2D _MainTex;//CG 中的图片类型,sampler2D是CG语言的一个类, //上面 属性Properties 里面声明属性_MainTex时图片表现是2D, sampler2D _Normalmap; //但是在CG里面,如果想让CG认识_MainTex,必须在CG代码块儿里面重新声明成sampler2D类型 samplerCUBE _Cubemap; struct Input { // 类似于有一个传入值 float2 uv_MainTex;//记录uv纹理坐标,在CG中使用图片需要记录uv纹理坐标 /// float2 uv_Normalmap; float3 worldRelfect;//牵扯到反射效果,记录XYZ轴的相关影像效果 }; half _Glossiness;//CG中的浮点型 half _Metallic; fixed4 _Color;//CG中的四阶向量 //5.0之后光照用的Standard,所以用SurfaceOutputStandard ,如果不是Standard用SurfaceOutput就可以了 void surf (Input IN, inout SurfaceOutputStandard o) {//IN传进来(UV的传入),inout声明的o值传出去 // 下面是一个公式 (主纹理,uv信息),Color表示把颜色应用在uv的所有的点上,有相应的表现 fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; //在表面着色器里使物体受到光照的话用o.Albedo,它表示漫反射, //把拿到的图片的rgb信息应用到漫反射表现效果上 o.Emission=texCUBE(_Cubemap,IN.worldRelfect).rgb; //是立方体贴图反射周围环境的命令,这是没有法线贴图时反射效果的代码写法 o.Normal=UnpackNormal(tex2D (Normalmap, IN.uv_Normalmap)); //是法线贴图 // Metallic and smoothness come from slider variables o.Metallic = _Metallic;//金属光泽表现 o.Smoothness = _Glossiness;//高光光泽度 o.Alpha = c.a; } ENDCG //CG语言代码块儿结束 } FallBack "Diffuse"//如果SubShader里的所有算法都不能执行的话,就会后退回到最初始的状态      }

注意:

Properties属性里面的所有东西都是Shaderlab结构,Shaderlab知道这些属性你可以在外面调节,但是如果要在表面着色器的CG代码块里进行Shader使用的话都需要重新声明

上面说到Shader中法线贴图与CubeMap贴图(反射)只能用一个。

为什么呢?是因为如果两个都想用到的时候需要引INTERNAL_DATA的命令

      如果没有用到法线贴图,想要实现反射时物体表面把图片直接反射过来就可以了,但是如果牵扯到法线、物体表面、又要牵扯到反射效果的话,就不仅仅是物体表面把图片反射过来就行了,还要考虑到法线贴图里面的凹凸细节里面的像素,反射效果就比普通平面效果稍微复杂一些,这时就要借助WorldReflectionVector。

下面是详细代码: 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Shader "Custom/NewSurfaceShader" { Properties{ _Color("Color", Color) = (1,1,1,1) _MainTex("Albedo (RGB)", 2D) = "white" {} _Normalmap ("Normalmap", 2D) = "Normal" {} _Cubemap("Cubemap", CUBE) = "Cube" {} _Glossiness("Smoothness", Range(0,1)) = 0.5 _Metallic("Metallic", Range(0,1)) = 0.0 } SubShader{ Tags{ "RenderType" = "Opaque" } LOD 200 CGPROGRAM #pragma surface surf Standard fullforwardshadows//编译指令 #pragma target 3.0 sampler2D _MainTex; sampler2D _Normalmap; samplerCUBE _Cubemap; struct Input { float2 uv_MainTex; float2 uv_Normalmap; float3 worldRefl; //法线与反射效果配合需要将添加到Input结构中 INTERNAL_DATA }; half _Glossiness;//CG中的浮点型 half _Metallic; fixed4 _Color; void surf(Input IN, inout SurfaceOutputStandard o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; //不需要法线的反射效果 // o.Emission=texCUBE(_Cubemap,IN.worldRefl).rgb; //下面是法线与反射效果配合,编写完法线命令输出后并结合WorldReflectionVector函数将计算像素中的逐个向量 o.Normal = UnpackNormal(tex2D(_Normalmap, IN.uv_Normalmap)); //是法线贴图 o.Emission = texCUBE(_Cubemap, WorldReflectionVector(IN, o.Normal)).rgb; o.Metallic = _Metallic;//金属光泽表现 o.Smoothness = _Glossiness;//高光光泽度 o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }

补充如何创建Cubemap

 

最后

以上就是糊涂衬衫最近收集整理的关于Unity图形学之三种自定义Shader(八)                二、Unity中的三种Shader介绍                       三、Unity中的三种自定义Shader代码编写                   的全部内容,更多相关Unity图形学之三种自定义Shader(八) 内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部