首页 > 其他分享 >【Unity3D】固定管线着色器一

【Unity3D】固定管线着色器一

时间:2023-03-21 09:57:20浏览次数:60  
标签:贴图 Unity3D material Color Material Shader meshRenderer 着色器 管线

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 上:

img

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 游戏对象上,显示效果如下:

img

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 里定义的变量的值。

img

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 属性,如下,这两个属性分别用于纹理缩放和偏移。

img

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

meshRenderer.material.SetTexture("_Texture2D", texture) // 设置纹理
meshRenderer.material.SetTextureScale("_Texture2D", new Vector2(2, 2)) // 设置Tiling
meshRenderer.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 中光照颜色,显示效果如下:

img

5 贴图

1)贴图简单应用

​ FixedShader.shader

Shader "MyShader/ShaderTest"
{
	Properties
	{
		// 属性名 ("面板显示名称", 类型) = 默认值
		_Texture2D ("2阶贴图", 2D) = "white" {}
	}

	SubShader
	{
		Pass
		{
			SetTexture[_Texture2D]
			{
				Combine Texture
			}
		}
	}

	Fallback "Diffuse"
}

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

img

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 窗口选择贴图图片,并调整固定颜色,显示效果如下:

img

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 窗口选择贴图图片,并调整漫反射颜色,显示效果如下:

img

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 个贴图图片,显示效果如下:

img

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 上,运行后通过↑ ↓ 按键调整插值比例,效果如下:

img

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

标签:贴图,Unity3D,material,Color,Material,Shader,meshRenderer,着色器,管线
From: https://www.cnblogs.com/zhyan8/p/17237804.html

相关文章

  • 【Unity3D】协同程序
    1简介​1)协程概念​协同程序(Coroutine)简称协程,是伴随主线程一起运行的程序片段,是一个能够暂停执行的函数,用于解决程序并行问题。协程是C#中的概念,由于Unity3......
  • 【Unity3D】顶点和片元着色器
    1前言​上文介绍了渲染管线、固定管线着色器和表面着色器,如下:渲染管线固定管线着色器一固定管线着色器二表面着色器​固定管线着色器通过命令方式实现光......
  • 【Unity3D】表面着色器
    1前言​固定管线着色器一、固定管线着色器二中介绍了ShaderLib的基本用法,本文将接着讲解表面着色器(SurfaceShader)的用法。固定管线着色器基于ShaderLib命令实......
  • 【Unity3D】AudioSource组件
    1简介​1)AudioSource与AudioListener简介​AudioSource(音频源)组件用于控制播放AudioClip(音频片段),能够控制2D和3D(距离越远,声音越小)声音播放,它一般挂在产......
  • 【Unity3D】场景切换、全屏_恢复切换、退出游戏、截屏
    1前言​1)场景切换​场景切换可以使用SceneManager的LoadScene和LoadSceneAsync方法,如下:publicstaticvoidLoadScene(stringsceneName)publicstatic......
  • 【Unity3D】GUI控件
    1前言​Unity3D提供了GUI、NGUI、UGUI等图形系统,以增强玩家与游戏的交互性。GUI在编译时不能可视化,在运行时才能可视化。GUI代码需要在OnGUI函数中调用才能......
  • 【Unity3D】相机跟随
    1前言​相机跟随是相机指始终跟随特定游戏对象,有以下2种跟随效果:位置跟随:相机指向目标游戏对象的向量始终不变位置和姿态跟随:相机在目标游戏对象的坐标系下的坐......
  • 【Unity3D】UGUI之Text
    1Text简介​UGUI概述中介绍了Canvas渲染模式、RectTransform组件、锚点(Anchor)等,本文将介绍UGUI中的Text控件。​在Hierarchy窗口右键,选择UI列表里......
  • 【Unity3D】UGUI概述
    1UGUI与GUI区别​GUI控件在编译时不能可视化,并且界面不太美观,在实际应用中使用的较少。UGUI在编译时可视化,界面美观,实际应用较广泛。2Canvas渲染模式(Render......
  • 【Unity3D】UGUI之Button
    1Button属性面板​在Hierarchy窗口右键,选择UI列表里的Button控件,即可创建Button控件,选中创建的Button控件,按键盘【T】键,可以调整Button控件的大小和位置......