找回密码
 立即注册
查看: 249|回复: 0

【Unity3D】固定管线着色器一

[复制链接]
发表于 2023-3-9 15:22 | 显示全部楼层 |阅读模式
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
Shader "MyShader/ShaderTest"{    Properties    {        // 定义外部属性    }    SubShader    {        Pass        {            Color(1, 0, 0, 1) // 固定渲染颜色        }    }    Fallback "Diffuse"}
将 ShaderTest 绑定到一个 Material 上,并将该 Material 拖拽到一个 Cube 和 Sphere 游戏对象上,显示效果如下:

3 Shader 外部属性


1)定义外部属性

在 Properties 模块中可以定义外部属性如下:
Properties{    // 属性名 ("面板显示名称", 类型) = 默认值    _FloatValue ("浮点数", Float) = 0.4    _RangeValue ("浮点数范围", Range(0, 1)) = 0.5    _VectorValue ("四维数", Vector) = (1, 2, 3, 4)    _ColorValue ("颜色", Color) = (1, 0, 0, 1)    _Texture2D ("2阶贴图", 2D) = "white" {}    _TextureRect ("非二阶贴图", Rect) = "white" {}    _TextureCube ("立方体贴图", Cube) = "" {}}
选中绑定的 Material,查看 Inspector 窗口如下,用户可以在这里调整 Properties 里定义的变量的值。

2)使用外部属性

在 Pass 模块,用户可以通过 "[属性名]" 使用 Properties 里定义的变量,如下:
Pass{    Color[_ColorValue]    Color([_ColorR], [_ColorG], [_ColorB], [_ColorA])}
3)案例

FixedShader.shader
Shader "MyShader/ShaderTest"{    Properties    {        // 属性名 ("面板显示名称", 类型) = 默认值        _ColorR ("Color_R", Range(0, 1)) = 0.5        _ColorG ("Color_G", Range(0, 1)) = 0.5        _ColorB ("Color_B", Range(0, 1)) = 0.5        _ColorA ("Color_A", Range(0, 1)) = 0.5    }    SubShader    {        Pass        {            Blend SrcAlpha OneMinusSrcAlpha // Alpha混合            Color([_ColorR], [_ColorG], [_ColorB], [_ColorA])        }    }    Fallback "Diffuse"}
4)代码控制外部属性

在 MonoBehaviour 脚本组件中获取和保存 Shader 中变量值的方法如下:
private void GetColor() { // 获取颜色    color[0] = meshRenderer.material.GetFloat("_ColorR");    color[1] = meshRenderer.material.GetFloat("_ColorG");    color[2] = meshRenderer.material.GetFloat("_ColorB");    color[3] = meshRenderer.material.GetFloat("_ColorA");}private void SaveColor() { // 保存颜色    meshRenderer.material.SetFloat("_ColorR", color[0]);    meshRenderer.material.SetFloat("_ColorG", color[1]);    meshRenderer.material.SetFloat("_ColorB", color[2]);    meshRenderer.material.SetFloat("_ColorA", color[3]);}
说明:_ColorR、_ColorG、_ColorB、_ColorA 是 Shader 中定义的 Range 类型外部属性。

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

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

在 MonoBehaviour 脚本组件中设置纹理缩放和偏移的方法如下:
meshRenderer.material.SetTexture("_Texture2D", texture) // 设置纹理meshRenderer.material.SetTextureScale("_Texture2D", new Vector2(2, 2)) // 设置TilingmeshRenderer.material.SetTextureOffset("_Texture2D", new Vector2(Time.time, 0)) // 设置Offset
说明:_Texture2D 是 Shader 中定义的 2D 类型外部属性。
4 光照


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

FixedShader.shader
Shader "MyShader/ShaderTest"{    Properties    {        // 属性名 ("面板显示名称", 类型) = 默认值        _AmbientColor ("环境光颜色", Color) = (1, 1, 1, 1)        _DiffuseColor ("漫反射光颜色", Color) = (1, 1, 1, 1)        _SpecularColor ("镜面反射光颜色", Color) = (1, 1, 1, 1)        _EmissionColor ("自发光颜色", Color) = (1, 1, 1, 1)        _Shininess ("光泽度", Range(0, 1)) = 0.5    }    SubShader    {        Pass        {            Lighting On // 开启顶点光照            SeparateSpecular On // 开启镜面反射光照            Material            {                Ambient[_AmbientColor] // 环境光颜色                Diffuse[_DiffuseColor] // 漫反射光颜色                Specular[_SpecularColor] // 镜面反射光颜色                // Emission[_EmissionColor] // 自发光颜色                Shininess[_Shininess] // 光泽度, 用于调整镜面反射范围            }        }    }    Fallback "Diffuse"}
选中绑定的 Material,在 Inspector 窗口调整 Shader 中光照颜色,显示效果如下:

5 贴图


1)贴图简单应用

FixedShader.shader
Shader "MyShader/ShaderTest"{    Properties    {        // 属性名 ("面板显示名称", 类型) = 默认值        _Texture2D ("2阶贴图", 2D) = "white" {}    }    SubShader    {        Pass        {            SetTexture[_Texture2D]            {                Combine Texture            }        }    }    Fallback "Diffuse"}
选中绑定的 Material,在 Inspector 窗口选择贴图图片,显示效果如下:

2)贴图与固定颜色混合

FixedShader.shader
Shader "MyShader/ShaderTest"{    Properties    {        // 属性名 ("面板显示名称", 类型) = 默认值        _ConstantColor ("固定颜色", Color) = (1, 1, 1, 1)        _Texture2D ("2阶贴图", 2D) = "white" {}    }    SubShader    {        Pass        {            SetTexture[_Texture2D]            {                // 可以用"+"号, 也可以用"*"号, "+"号偏亮, "*"号偏暗, 可以使用Double(2倍数)、Quad(4倍)调整亮度                ConstantColor[_ConstantColor]                Combine Texture + Constant // Constant指上面的固定颜色            }        }    }    Fallback "Diffuse"}
选中绑定的 Material,在 Inspector 窗口选择贴图图片,并调整固定颜色,显示效果如下:

3)贴图与光照混合

FixedShader.shader
Shader "MyShader/ShaderTest"{    Properties    {        // 属性名 ("面板显示名称", 类型) = 默认值        _DiffuseColor ("漫反射光颜色", Color) = (1, 1, 1, 1)        _Texture2D ("2阶贴图", 2D) = "white" {}    }    SubShader    {        Pass        {            Lighting On // 开启顶点光照            Material            {                Diffuse[_DiffuseColor] // 漫反射光颜色            }            SetTexture[_Texture2D]            {                // 可以用"+"号, 也可以用"*"号, "+"号偏亮, "*"号偏暗, 可以使用Double(2倍数)、Quad(4倍)调整亮度                Combine Texture * Primary Quad // Primary指上面的Material            }        }    }    Fallback "Diffuse"}
选中绑定的 Material,在 Inspector 窗口选择贴图图片,并调整漫反射颜色,显示效果如下:

4)多图混合

FixedShader.shader
Shader "MyShader/ShaderTest"{    Properties    {        // 属性名 ("面板显示名称", 类型) = 默认值        _MainTexture2D ("主贴图", 2D) = "white" {}        _SecondTexture2D ("次贴图", 2D) = "white" {}    }    SubShader    {        Pass        {            SetTexture[_MainTexture2D]            {                Combine Texture            }            SetTexture[_SecondTexture2D]            {                // 可以用"+"号, 也可以用"*"号, "+"号偏亮, "*"号偏暗, 可以使用Double(2倍数)、Quad(4倍)调整亮度                Combine Texture * Previous Double // Previous指上面的_MainTexture2D            }        }    }    Fallback "Diffuse"}
选中绑定的 Material,在 Inspector 窗口选择 2 个贴图图片,显示效果如下:

5)多图渐变混合

FixedShader.shader
Shader "MyShader/ShaderTest"{    Properties    {        // 属性名 ("面板显示名称", 类型) = 默认值        _MainTexture2D ("主贴图", 2D) = "white" {}        _SecondTexture2D ("次贴图", 2D) = "white" {}        _Lerp ("插值", Range(0, 1)) = 0.5    }    SubShader    {        Pass        {            SetTexture[_MainTexture2D]            {                Combine Texture            }            SetTexture[_SecondTexture2D]            {                ConstantColor(0, 0, 0, [_Lerp])                Combine Texture lerp(Constant) Previous // Previous指上面的_MainTexture2D            }        }    }    Fallback "Diffuse"}
选中绑定的 Material,在 Inspector 窗口选择 2 个贴图图片。

LerpController.cs
using UnityEngine;public class LerpController : MonoBehaviour {    private MeshRenderer meshRenderer;    private float lerp;    private float increateSpeed = 0.15f;    private void Start () {        meshRenderer = GetComponent<MeshRenderer>();        lerp = meshRenderer.material.GetFloat("_Lerp");    }    private void Update () {        OperateLerp();    }    private void OperateLerp() { // 操作插值        float ver = Input.GetAxis("Vertical");        if (Mathf.Abs(ver) > 0.1) {            lerp = Camp(lerp + ver * increateSpeed * Time.deltaTime, 0, 1);            meshRenderer.material.SetFloat("_Lerp", lerp);        }    }    private float Camp(float value, float min, float max) {        return Mathf.Max(Mathf.Min(value, max), min);    }}
将 LerpController 脚本组件挂在 Cube 和 Sphere 上,运行后通过↑ ↓ 按键调整插值比例,效果如下:

声明:本文转自【Unity3D】固定管线着色器一

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-6-17 02:53 , Processed in 0.090035 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表