• 【Unity3D】固定管线着色器一


    1 前言

            着色器(Shader)是渲染管线中最重要的一环,Unity3D 底层基于 OpenGL 实现,读者可以通过 渲染管线 了解 Unity3D 渲染流程。

            OpenGL 1.x 为固定管线,2.x 之后才支持可编程管线,Unity3D 固定管线着色器使用 ShaderLab 语言实现。ShaderLab 是 Unity Shader 的服务语言,是基于命令的语言

            每个游戏对象需要绑定至少一个材质(Material)才能渲染,即使材质为 None,系统也会绑定一个默认的材质。每个材质都需要绑定一个Shader,系统一般默认绑定 Standard Shader,用户也可以绑定到自定义的 Shader 上。当用户创建好 Material 和 Shader 后,选中 Material,在 Inspector 窗口通过如下方式绑定到自定义 Shader 上:

    2  Shader 代码框架

            在 Assets 窗口右键,依次选择【Create→Shader→Unity Shader】创建 Shader 脚本,其代码框架如下:

            FixedShader.shader

    1. Shader "MyShader/ShaderTest"
    2. {
    3. Properties
    4. {
    5. // 定义外部属性
    6. }
    7. SubShader
    8. {
    9. Pass
    10. {
    11. Color(1, 0, 0, 1) // 固定渲染颜色
    12. }
    13. }
    14. Fallback "Diffuse"
    15. }

            将 ShaderTest 绑定到一个 Material 上,并将该 Material 拖拽到一个 Cube 和 Sphere 游戏对象上,显示效果如下:

    3 Shader 外部属性

            1)定义外部属性

            在 Properties 模块中可以定义外部属性如下:

    1. Properties
    2. {
    3. // 属性名 ("面板显示名称", 类型) = 默认值
    4. _FloatValue ("浮点数", Float) = 0.4
    5. _RangeValue ("浮点数范围", Range(0, 1)) = 0.5
    6. _VectorValue ("四维数", Vector) = (1, 2, 3, 4)
    7. _ColorValue ("颜色", Color) = (1, 0, 0, 1)
    8. _Texture2D ("2阶贴图", 2D) = "white" {}
    9. _TextureRect ("非二阶贴图", Rect) = "white" {}
    10. _TextureCube ("立方体贴图", Cube) = "" {}
    11. }

            选中绑定的 Material,查看 Inspector 窗口如下,用户可以在这里调整 Properties 里定义的变量的值。

            2)使用外部属性

            在 Pass 模块,用户可以通过 "[属性名]" 使用 Properties 里定义的变量,如下:

    1. Pass
    2. {
    3. Color[_ColorValue]
    4. Color([_ColorR], [_ColorG], [_ColorB], [_ColorA])
    5. }

            3)案例

            FixedShader.shader 

    1. Shader "MyShader/ShaderTest"
    2. {
    3. Properties
    4. {
    5. // 属性名 ("面板显示名称", 类型) = 默认值
    6. _ColorR ("Color_R", Range(0, 1)) = 0.5
    7. _ColorG ("Color_G", Range(0, 1)) = 0.5
    8. _ColorB ("Color_B", Range(0, 1)) = 0.5
    9. _ColorA ("Color_A", Range(0, 1)) = 0.5
    10. }
    11. SubShader
    12. {
    13. Pass
    14. {
    15. Blend SrcAlpha OneMinusSrcAlpha // Alpha混合
    16. Color([_ColorR], [_ColorG], [_ColorB], [_ColorA])
    17. }
    18. }
    19. Fallback "Diffuse"
    20. }

            4)代码控制外部属性

            在 MonoBehaviour 脚本组件中获取和保存 Shader 中变量值的方法如下:

    1. private void GetColor() { // 获取颜色
    2. color[0] = meshRenderer.material.GetFloat("_ColorR");
    3. color[1] = meshRenderer.material.GetFloat("_ColorG");
    4. color[2] = meshRenderer.material.GetFloat("_ColorB");
    5. color[3] = meshRenderer.material.GetFloat("_ColorA");
    6. }
    7. private void SaveColor() { // 保存颜色
    8. meshRenderer.material.SetFloat("_ColorR", color[0]);
    9. meshRenderer.material.SetFloat("_ColorG", color[1]);
    10. meshRenderer.material.SetFloat("_ColorB", color[2]);
    11. meshRenderer.material.SetFloat("_ColorA", color[3]);
    12. }

            说明:_ColorR、_ColorG、_ColorB、_ColorA 是 Shader 中定义的 Range 类型外部属性。  

            5)代码控制纹理缩放和偏移

            在 Shader 中定义 2D 类型外部属性,选中 Material 后,在 Inspector 窗口可以看到出现了 Tiling 和 Offset 属性,如下,这两个属性分别用于纹理缩放和偏移。

            在 MonoBehaviour 脚本组件中设置纹理缩放和偏移的方法如下:

    1. meshRenderer.material.SetTexture("_Texture2D", texture) // 设置纹理
    2. meshRenderer.material.SetTextureScale("_Texture2D", new Vector2(2, 2)) // 设置Tiling
    3. meshRenderer.material.SetTextureOffset("_Texture2D", new Vector2(Time.time, 0)) // 设置Offset

            说明:_Texture2D 是 Shader 中定义的 2D 类型外部属性。

    4 光照

            光照原理见→Blinn改进的冯氏光照模型

            FixedShader.shader 

    1. Shader "MyShader/ShaderTest"
    2. {
    3. Properties
    4. {
    5. // 属性名 ("面板显示名称", 类型) = 默认值
    6. _AmbientColor ("环境光颜色", Color) = (1, 1, 1, 1)
    7. _DiffuseColor ("漫反射光颜色", Color) = (1, 1, 1, 1)
    8. _SpecularColor ("镜面反射光颜色", Color) = (1, 1, 1, 1)
    9. _EmissionColor ("自发光颜色", Color) = (1, 1, 1, 1)
    10. _Shininess ("光泽度", Range(0, 1)) = 0.5
    11. }
    12. SubShader
    13. {
    14. Pass
    15. {
    16. Lighting On // 开启顶点光照
    17. SeparateSpecular On // 开启镜面反射光照
    18. Material
    19. {
    20. Ambient[_AmbientColor] // 环境光颜色
    21. Diffuse[_DiffuseColor] // 漫反射光颜色
    22. Specular[_SpecularColor] // 镜面反射光颜色
    23. // Emission[_EmissionColor] // 自发光颜色
    24. Shininess[_Shininess] // 光泽度, 用于调整镜面反射范围
    25. }
    26. }
    27. }
    28. Fallback "Diffuse"
    29. }

            选中绑定的 Material,在 Inspector 窗口调整 Shader 中光照颜色,显示效果如下:

    5 贴图

            1)贴图简单应用

            FixedShader.shader 

    1. Shader "MyShader/ShaderTest"
    2. {
    3. Properties
    4. {
    5. // 属性名 ("面板显示名称", 类型) = 默认值
    6. _Texture2D ("2阶贴图", 2D) = "white" {}
    7. }
    8. SubShader
    9. {
    10. Pass
    11. {
    12. SetTexture[_Texture2D]
    13. {
    14. Combine Texture
    15. }
    16. }
    17. }
    18. Fallback "Diffuse"
    19. }

            选中绑定的 Material,在 Inspector 窗口选择贴图图片,显示效果如下:

            2)贴图与固定颜色混合

            FixedShader.shader 

    1. Shader "MyShader/ShaderTest"
    2. {
    3. Properties
    4. {
    5. // 属性名 ("面板显示名称", 类型) = 默认值
    6. _ConstantColor ("固定颜色", Color) = (1, 1, 1, 1)
    7. _Texture2D ("2阶贴图", 2D) = "white" {}
    8. }
    9. SubShader
    10. {
    11. Pass
    12. {
    13. SetTexture[_Texture2D]
    14. {
    15. // 可以用"+"号, 也可以用"*"号, "+"号偏亮, "*"号偏暗, 可以使用Double(2倍数)、Quad(4倍)调整亮度
    16. ConstantColor[_ConstantColor]
    17. Combine Texture + Constant // Constant指上面的固定颜色
    18. }
    19. }
    20. }
    21. Fallback "Diffuse"
    22. }

            选中绑定的 Material,在 Inspector 窗口选择贴图图片,并调整固定颜色,显示效果如下:

            3)贴图与光照混合

            FixedShader.shader 

    1. Shader "MyShader/ShaderTest"
    2. {
    3. Properties
    4. {
    5. // 属性名 ("面板显示名称", 类型) = 默认值
    6. _DiffuseColor ("漫反射光颜色", Color) = (1, 1, 1, 1)
    7. _Texture2D ("2阶贴图", 2D) = "white" {}
    8. }
    9. SubShader
    10. {
    11. Pass
    12. {
    13. Lighting On // 开启顶点光照
    14. Material
    15. {
    16. Diffuse[_DiffuseColor] // 漫反射光颜色
    17. }
    18. SetTexture[_Texture2D]
    19. {
    20. // 可以用"+"号, 也可以用"*"号, "+"号偏亮, "*"号偏暗, 可以使用Double(2倍数)、Quad(4倍)调整亮度
    21. Combine Texture * Primary Quad // Primary指上面的Material
    22. }
    23. }
    24. }
    25. Fallback "Diffuse"
    26. }

            选中绑定的 Material,在 Inspector 窗口选择贴图图片,并调整漫反射颜色,显示效果如下:

            4)多图混合

            FixedShader.shader 

    1. Shader "MyShader/ShaderTest"
    2. {
    3. Properties
    4. {
    5. // 属性名 ("面板显示名称", 类型) = 默认值
    6. _MainTexture2D ("主贴图", 2D) = "white" {}
    7. _SecondTexture2D ("次贴图", 2D) = "white" {}
    8. }
    9. SubShader
    10. {
    11. Pass
    12. {
    13. SetTexture[_MainTexture2D]
    14. {
    15. Combine Texture
    16. }
    17. SetTexture[_SecondTexture2D]
    18. {
    19. // 可以用"+"号, 也可以用"*"号, "+"号偏亮, "*"号偏暗, 可以使用Double(2倍数)、Quad(4倍)调整亮度
    20. Combine Texture * Previous Double // Previous指上面的_MainTexture2D
    21. }
    22. }
    23. }
    24. Fallback "Diffuse"
    25. }

            选中绑定的 Material,在 Inspector 窗口选择 2 个贴图图片,显示效果如下:

             5)多图渐变混合

            FixedShader.shader 

    1. Shader "MyShader/ShaderTest"
    2. {
    3. Properties
    4. {
    5. // 属性名 ("面板显示名称", 类型) = 默认值
    6. _MainTexture2D ("主贴图", 2D) = "white" {}
    7. _SecondTexture2D ("次贴图", 2D) = "white" {}
    8. _Lerp ("插值", Range(0, 1)) = 0.5
    9. }
    10. SubShader
    11. {
    12. Pass
    13. {
    14. SetTexture[_MainTexture2D]
    15. {
    16. Combine Texture
    17. }
    18. SetTexture[_SecondTexture2D]
    19. {
    20. ConstantColor(0, 0, 0, [_Lerp])
    21. Combine Texture lerp(Constant) Previous // Previous指上面的_MainTexture2D
    22. }
    23. }
    24. }
    25. Fallback "Diffuse"
    26. }

            选中绑定的 Material,在 Inspector 窗口选择 2 个贴图图片。

            LerpController.cs

    1. using UnityEngine;
    2. public class LerpController : MonoBehaviour {
    3. private MeshRenderer meshRenderer;
    4. private float lerp;
    5. private float increateSpeed = 0.15f;
    6. private void Start () {
    7. meshRenderer = GetComponent();
    8. lerp = meshRenderer.material.GetFloat("_Lerp");
    9. }
    10. private void Update () {
    11. OperateLerp();
    12. }
    13. private void OperateLerp() { // 操作插值
    14. float ver = Input.GetAxis("Vertical");
    15. if (Mathf.Abs(ver) > 0.1) {
    16. lerp = Camp(lerp + ver * increateSpeed * Time.deltaTime, 0, 1);
    17. meshRenderer.material.SetFloat("_Lerp", lerp);
    18. }
    19. }
    20. private float Camp(float value, float min, float max) {
    21. return Mathf.Max(Mathf.Min(value, max), min);
    22. }
    23. }

            将 LerpController 脚本组件挂在 Cube 和 Sphere 上,运行后通过↑ ↓ 按键调整插值比例,效果如下:

  • 相关阅读:
    尼莫地平纳米脂质体包载小干扰RNA(siRNA)|低分子肝素纳米脂质体包载信使RNA(mRNA)|齐岳生物
    lvgl 转换和使用新字体
    【故障公告】cc攻击又来了,雪上加霜的三月
    大数据项目之电商数仓、业务数据介绍、MySQL安装、更改MySQL密码策略
    计算机毕业设计源代码java项目开发实例基于SSM的车库停车计费系统|停车场[包运行成功]
    什么是多态?
    Linux学习-44-虚拟内存、物理内存和swap分区的作用
    springboot中实现权限认证的两个框架
    java毕业设计——基于java+EVENODD编码的基于纠错码的冗余技术设计与实现(毕业论文+程序源码)——基于纠错码的冗余技术
    openEuler 22.03 LTS SP3(华为欧拉)一键安装 Oracle 12CR2 RAC(220118) 数据库
  • 原文地址:https://blog.csdn.net/m0_37602827/article/details/126811503