一、GLSL内置变量
Unity 作为渲染引擎,内置了一些shader变量以及一些数据结构,方便Unity自身的一些函数计算,同时也开放给开发者使用,我们开发者同时也可以将这些视为某种规范和标准,详细参考UnityShaderVariables.cginc(Unity的内置Shader可以在官网可以下载到)。
同时Unity的文档也对内置变量做了说明,可以参考Built-in shader variables。
Unity 内置Shader 基本上通过Cg来编写的,所以GLSL内置的变量比较少,主要关注UnityCG.glslinc和GLSLSupport.glslinc。
首先来看看UnityCG.glslinc
Unity引擎会在cpu提交gpu渲染请求时为这些变量赋值,开发者只需要知道如何使用即可。
再看GLSLSupport.glslinc
这里主要看gl_前缀的变量:
变量名 | 类型 | 值 |
---|---|---|
gl_ModelViewProjectionMatrix | mat4 | MVP矩阵,将对象空间中的顶点转换到裁剪空间 |
gl_ModelViewMatrix | mat4 | MV矩阵,将对象空间中的顶点转换到相机空间 |
gl_ModelViewMatrixTranspose | mat4 | MV矩阵的转置 |
gl_ModelViewMatrixInverseTranspose | mat4 | MV矩阵逆的转置 |
gl_NormalMatrix | mat4 | 法线矩阵,将对象空间中的法线转换到世界空间 |
gl_ProjectionMatrix | mat4 | 投影矩阵,将相机空间的顶点转换到裁剪空间 |
另外还有
变量名 | 类型 | 值 |
---|---|---|
gl_Vertex | vec4 | 对象空间的顶点坐标 |
gl_Position | vec4 | 顶点着色器的输出到片元着色器的位置(裁剪空间) |
gl_FragColor | vec4 | 最终输出到屏幕像素的颜色值 |
gl_Normal | vec4 | 顶点法线 |
gl_MultiTexCoord0 | vec4 | uv |
这些是OpenGLES预定义的变量(未确认,Unity 内置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
}
}
}