介绍
unity shader里会内置一些用于矩阵计算的变量和函数
但是有时候我们需要传入一些自定义计算的的矩阵用于shader中计算,但是发现Properties
中没有矩阵类型的数据传入,因此引出本文。
两种方式引入uniform
1.单独的material引入uniform
2.全局material都引入uniform
1.单独方式引入
Shader "Unlit/shader01"
{
Properties
{
_MyColor("color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
fixed4 _MyColor;
// 注意这里的pvmMat会从外面传入
float4x4 pvmMat;
// 传入物体的模型矩阵
float4x4 modelMatrix;
v2f vert (appdata v)
{
v2f o;
//o.vertex = UnityObjectToClipPos(v.vertex);
// 下面的代码使用了自己构建的pvm矩阵,就是将对象顶点从本地坐标系转到裁剪坐标系,等同与UnityObjectToClipPos函数的作用,或者等于UNITY_MATRIX_MVP
// 使用完全自己传入的pvm矩阵的话会导致scene窗口和game窗口不统一,而且渲染有问题,原因未知,比如下面这种
// o.vertex = mul(pvmMat, v.vertex);
// 建议使用下面这种
o.vertex = mul(UNITY_MATRIX_VP, mul(modelMatrix, v.vertex));
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return _MyColor;
}
ENDCG
}
}
}
脚本 例子中是挂载到相机上的
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class test01 : MonoBehaviour
{
void Update()
{
Matrix4x4 projectionMatrix = Camera.main.projectionMatrix;
Matrix4x4 worldToCameraMatrix = Camera.main.worldToCameraMatrix;
GameObject box = GameObject.Find("Cube");
Matrix4x4 modelMatrix = box.transform.localToWorldMatrix;
Matrix4x4 MVPMat = projectionMatrix * worldToCameraMatrix * modelMatrix;
// 直接传方式不推荐
box.GetComponent<Renderer>().material.SetMatrix("pvmMat", MVPMat);
box.GetComponent<Renderer>().material.SetMatrix("modelMatrix", modelMatrix);
}
}
2.全局方式引入
shader
Shader "Unlit/shader01"
{
Properties
{
_MyColor("color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
fixed4 _MyColor;
// 注意这里的pvmMat会从外面全局传入
float4x4 pvmMat;
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_VP, mul(modelMatrix, v.vertex));
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return _MyColor;
}
ENDCG
}
}
}
脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class test01 : MonoBehaviour
{
void Update()
{
Matrix4x4 projectionMatrix = Camera.main.projectionMatrix;
Matrix4x4 worldToCameraMatrix = Camera.main.worldToCameraMatrix;
Matrix4x4 pvMat = projectionMatrix * worldToCameraMatrix;
Matrix4x4 modelMatrix = Matrix4x4.identity ;
modelMatrix[0] = 3;
Shader.SetGlobalMatrix("pvmMat", pvMat* modelMatrix);
box.GetComponent<Renderer>().material.SetMatrix("modelMatrix", modelMatrix);
}
}