一、GLSL內(nèi)置變量
Unity 作為渲染引擎,內(nèi)置了一些shader變量以及一些數(shù)據(jù)結(jié)構(gòu),方便Unity自身的一些函數(shù)計(jì)算,同時(shí)也開放給開發(fā)者使用,我們開發(fā)者同時(shí)也可以將這些視為某種規(guī)范和標(biāo)準(zhǔn),詳細(xì)參考UnityShaderVariables.cginc(Unity的內(nèi)置Shader可以在官網(wǎng)可以下載到)。

UnityShaderVariables.cginc文件截圖
同時(shí)Unity的文檔也對內(nèi)置變量做了說明,可以參考Built-in shader variables。

內(nèi)置shader變量說明
Unity 內(nèi)置Shader 基本上通過Cg來編寫的,所以GLSL內(nèi)置的變量比較少,主要關(guān)注UnityCG.glslinc和GLSLSupport.glslinc。
首先來看看UnityCG.glslinc

UnityCG.glslinc
Unity引擎會在cpu提交gpu渲染請求時(shí)為這些變量賦值,開發(fā)者只需要知道如何使用即可。
再看GLSLSupport.glslinc

GLSLSupport.glslinc
這里主要看gl_前綴的變量:
| 變量名 | 類型 | 值 |
|---|---|---|
| gl_ModelViewProjectionMatrix | mat4 | MVP矩陣,將對象空間中的頂點(diǎn)轉(zhuǎn)換到裁剪空間 |
| gl_ModelViewMatrix | mat4 | MV矩陣,將對象空間中的頂點(diǎn)轉(zhuǎn)換到相機(jī)空間 |
| gl_ModelViewMatrixTranspose | mat4 | MV矩陣的轉(zhuǎn)置 |
| gl_ModelViewMatrixInverseTranspose | mat4 | MV矩陣逆的轉(zhuǎn)置 |
| gl_NormalMatrix | mat4 | 法線矩陣,將對象空間中的法線轉(zhuǎn)換到世界空間 |
| gl_ProjectionMatrix | mat4 | 投影矩陣,將相機(jī)空間的頂點(diǎn)轉(zhuǎn)換到裁剪空間 |
另外還有
| 變量名 | 類型 | 值 |
|---|---|---|
| gl_Vertex | vec4 | 對象空間的頂點(diǎn)坐標(biāo) |
| gl_Position | vec4 | 頂點(diǎn)著色器的輸出到片元著色器的位置(裁剪空間) |
| gl_FragColor | vec4 | 最終輸出到屏幕像素的顏色值 |
| gl_Normal | vec4 | 頂點(diǎn)法線 |
| gl_MultiTexCoord0 | vec4 | uv |
這些是OpenGLES預(yù)定義的變量(未確認(rèn),Unity 內(nèi)置shader源碼搜索不到定義,知道的大佬告知一聲),可以直接使用。
二、shading in world space

改變距離改變顏色
Shader "GLSL/GLSL shading in world space" {
Properties {
_Point ("a point in world space", Vector) = (0., 0., 0., 1.0)
_DistanceNear ("threshold distance", Float) = 5.0
_ColorNear ("color near to point", Color) = (0.0, 1.0, 0.0, 1.0)
_ColorFar ("color far from point", Color) = (1.0, 0.0, 0.0, 1.0)
}
SubShader {
Pass {
GLSLPROGRAM
// uniforms corresponding to properties
uniform vec4 _Point;
uniform float _DistanceNear;
uniform vec4 _ColorNear;
uniform vec4 _ColorFar;
#include "UnityCG.glslinc"
out vec4 position_in_world_space;
#ifdef VERTEX
void main()
{
position_in_world_space = unity_ObjectToWorld * gl_Vertex;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
#endif
#ifdef FRAGMENT
void main()
{
float dist= distance(position_in_world_space, _Point);
if (dist < _DistanceNear)
{
gl_FragColor = _ColorNear;
}
else
{
gl_FragColor = _ColorFar;
}
}
#endif
ENDGLSL
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class InWorldSpace : MonoBehaviour
{
public MeshRenderer meshRenderer;
// Start is called before the first frame update
void Start()
{
if (Application.isPlaying)
{
meshRenderer.material.SetVector("_Point", new Vector4(1.0f, 0.0f, 0.0f, 1.0f));
meshRenderer.material.SetFloat("_DistanceNear", 10.0f);
meshRenderer.material.SetColor("_ColorNear", new Color(1.0f, 0.0f, 0.0f));
meshRenderer.material.SetColor("_ColorFar", new Color(0.0f, 0.0f, 1.0f));
}
else
{
meshRenderer.sharedMaterial.SetVector("_Point", new Vector4(1.0f, 0.0f, 0.0f, 1.0f));
meshRenderer.sharedMaterial.SetFloat("_DistanceNear", 10.0f);
meshRenderer.sharedMaterial.SetColor("_ColorNear", new Color(1.0f, 0.0f, 0.0f));
meshRenderer.sharedMaterial.SetColor("_ColorFar", new Color(0.0f, 0.0f, 1.0f));
}
}
// Update is called once per frame
void Update()
{
if (Application.isPlaying)
{
meshRenderer.material.SetVector("_Point", this.transform.position); // set the shader property
}
else
{
meshRenderer.sharedMaterial.SetVector("_Point", this.transform.position); // set the shader property
}
}
}