当前位置:   article > 正文

Unity图形学之三种自定义Shader(八)_unityshader画虚线扇形

unityshader画虚线扇形

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

Properties 属性

Material 材质

Lighting光照

Settexture设置纹理

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

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

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

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

 代码如下:

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

注意:

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

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

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

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

下面是详细代码: 

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

补充如何创建Cubemap

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/107716?site
推荐阅读
相关标签
  

闽ICP备14008679号