第1篇 初始庐山真面目 - unity 3D Shader - Unity 3D ShaderLab开发实践

第1篇 初始庐山真面目 - unity 3D Shader - Unity 3D ShaderLab开发实践

2 Unity中Shader的形态

2.1 shader基本结构

Shader "Examples/ShaderSyntax"
{
    CustomEditor = "ExampleCustomEditor"

    Properties
    {
        // Material property declarations go here
        //[optional: attribute] name("display text in Inspector", type name) = default value
    }
    SubShader
    {
        // The code that defines the rest of the SubShader goes here
        //<optional: LOD>
        //<optional: tags>
        //<optional: commands>
        //<One or more Pass definitions>
        Tags { "ExampleSubShaderTagKey" = "ExampleSubShaderTagValue" }
        LOD 100

        Pass
        {
            //<optional: name>
			//<optional: tags>
		    //<optional: commands>
   			//<optional: shader code>
           // The code that defines the Pass goes here
           Name "ExamplePassName"
           Tags { "ExamplePassTagKey" = "ExamplePassTagValue" }
           // ShaderLab commands that apply to this Pass go here.

           // HLSL code goes here.
        }
        
        Pass
        {
        	// The next pass
        }
    }

    Fallback "ExampleFallbackShader"
}

Shader包含:

  • 关于自己的信息;
  • 可选的fallback的shader对象;
  • 一个或多个subshader

subshader,不同的subshader可以用来针对不同的GPU设置,不同的硬件,不同的渲染管线,和不同的运行时设置,一个subshader,为了获取想要的渲染效果定制的一个完整的渲染过程,包含:

  • 基本信息,包括硬件,渲染管线,运行时信息;
  • 关于subshader的key-value pair信息;
  • 一个或多个passes;

passes,一个pass指的是一次操作得到一次绘制结果的过程,就好比执行了一次顶点着色器,片段着色器,并输出了一张绘制结果,SubShader下的Pass会按照从上往下的顺序依次渲染。pass中包含:

  • 关于pass的key-value tag信息;
  • shader programs前需要设定的render state;
  • shader programs;

2.3 Unity中shader的2中形态

2.3.1 vertex+fragment shader

需要实现顶点和片段着色器,可以定制平台编译目标相关的参数。

第1篇 初始庐山真面目 - unity 3D Shader - Unity 3D ShaderLab开发实践

2.3.2 Surface Shader

编写与光照交互的着色器很复杂。有不同的灯光类型,不同的阴影选项,不同的渲染路径 (前向和延迟渲染),着色器应该以某种方式处理所有这些复杂性。

第1篇 初始庐山真面目 - unity 3D Shader - Unity 3D ShaderLab开发实践

SurfaceOutput的结果如下:

struct SurfaceOutput {
	half3 Albedo; //颜色纹理
	half3 Normal; //法线,tangent space空间
	half3 Emission; //自发光,不受照明的影响
	half Specular; //高光指数,0..1范围
	half Gloss; //光泽度
	half Alpha; //Alpha通道
};

此处需要注意的是SurfaceShader中,支持的自定的函数常见的有:

#pragma surface surfaceFunction lightModel vertex:vert finalcolor:colorFunc

surfaceFunction对应的是surface函数,lightModel对应的是光照模型的函数(内置的有StandardStandardSpecularLambertBlinnPhong ),vert是自定义的顶点函数,colorFunc是自定义的最终颜色修改函数。

具体实例可以参见:Unity - Manual: Surface Shader examples (unity3d.com)

参见:Unity Shader - Writing Surface Shaders 编写表面着色器_Jave.Lin 的学习笔记-CSDN博客

2.4 属性和uniform变量

// in property
_MyColor ("Some Color", Color) = (1,1,1,1) 
_MyVector ("Some Vector", Vector) = (0,0,0,0) 
_MyFloat ("My float", Float) = 0.5 
_MyTexture ("Texture", 2D) = "white" {} 
_MyCubemap ("Cubemap", CUBE) = "" {}

// in hlsl
fixed4 _MyColor; // low precision type is usually enough for colors
float4 _MyVector;
float _MyFloat; 
sampler2D _MyTexture;
samplerCUBE _MyCubemap;

Properties支持的类型

Type Example syntax Comment
Integer _ExampleName ("Integer display name", Integer) = 1 This type is backed by a real integer (unlike the legacy Int type described below, which is backed by a float). Use this instead of Int when you want to use an integer.
Int (legacy) _ExampleName ("Int display name", Int) = 1 Note: This legacy type is backed by a float, rather than an integer. It is supported for backwards compatibility reasons only. Use the Integer type instead.
Float _ExampleName ("Float display name", Float) = 0.5 _ExampleName ("Float with range", Range(0.0, 1.0)) = 0.5 The maximum and minimum values for the range slider are inclusive.
Texture2D _ExampleName ("Texture2D display name", 2D) = "" {} _ExampleName ("Texture2D display name", 2D) = "red" {} Put the following values in the default value string to use one of Unity’s built-in textures: “white” (RGBA: 1,1,1,1), “black” (RGBA: 0,0,0,1), “gray” (RGBA: 0.5,0.5,0.5,1), “bump” (RGBA: 0.5,0.5,1,0.5) or “red” (RGBA: 1,0,0,1). If you leave the string empty or enter an invalid value, it defaults to “gray”. Note: these default textures are not visible in the Inspector.
Texture2DArray _ExampleName ("Texture2DArray display name", 2DArray) = "" {} For more information, see Texture arrays.
Texture3D _ExampleName ("Texture3D", 3D) = "" {} The default value is a “gray” (RGBA: 0.5,0.5,0.5,1) texture.
Cubemap _ExampleName ("Cubemap", Cube) = "" {} The default value is a “gray” (RGBA: 0.5,0.5,0.5,1) texture.
CubemapArray _ExampleName ("CubemapArray", CubeArray) = "" {} See Cubemap arrays.
Color _ExampleName("Example color", Color) = (.25, .5, .5, 1) This maps to a float4 in your shader code. The Material Inspector displays a color picker. If you would rather edit the values as four individual floats, use the Vector type.
Vector _ExampleName ("Example vector", Vector) = (.25, .5, .5, 1) This maps to a float4 in your shader code. The Material Inspector displays four individual float fields. If you would rather edit the values using a color picker, use the Color type.

通过脚本控制属性:

第1篇 初始庐山真面目 - unity 3D Shader - Unity 3D ShaderLab开发实践

矩阵不能定义到Property中,只能够通过脚本的方式进行设值。

3 Shader中用到的各种空间的概念

用到的空间包括:模型空间、世界坐标空间、视空间(相机空间)、视锥体、裁剪空间。

世界空间到模型空间的变换矩阵:transform.worldToLocalMatrix, shader中是_World2Object;

模型空间到世界空间的变换矩阵:transform.localToWorldMatrix, shader中是_Object2World;

世界空间到相机空间的变换为:camera.worldToCameraMatrix,Shader中对应的是UNITY_MATRIX_MV,可以把向量从模型空间变换到相机空间;

视锥体,如下:

第1篇 初始庐山真面目 - unity 3D Shader - Unity 3D ShaderLab开发实践

裁剪空间,就是将视锥体变换成为一个长方体。

第1篇 初始庐山真面目 - unity 3D Shader - Unity 3D ShaderLab开发实践

camera.projectionMatrix, shader中对应的是UNITY_MATRIX_MVP,直接把物体上的点投影到屏幕上。

4 基本光照模型

LightingLambert计算漫反射光,Editor/Data/CGIncludes/Lighting.cginc

第1篇 初始庐山真面目 - unity 3D Shader - Unity 3D ShaderLab开发实践

乘上了atten * 2是为了更容易达到过曝;

BlinnPhong计算:

第1篇 初始庐山真面目 - unity 3D Shader - Unity 3D ShaderLab开发实践

具体参见:games101 - 2 - Shading - grassofsky - 博客园 (cnblogs.com)

其他

Unity - Manual: Built-in shader helper functions (unity3d.com)

Unity Shader内置appdata结构 - 老岳博客 - 博客园 (cnblogs.com)

Unity3d之Shader篇_风宇冲_新浪博客 (sina.com.cn)

上一篇:Graphics - 渲染状态


下一篇:OpenGL超级宝典(第7版)笔记4 渲染管线介绍 清单2.3-2.7