UnityShader·笔记

shaderlab速查手册,趟坑记录以及等等等等٩(◦`꒳´◦)۶

Shader概况

Unity支持三种Shader,surface shaderfragment and vertex shader,以及fixed function shader

Unity所用的shader语言为Cg/HLSL,相关函数可在Nvida查阅。

Shader代码结构

一个Shader文件大致长下面这样:

Shader "ShaderName"
{
 Properties
 {
  //...
 }
 
 SubShader
 {
  Tags { }

  CGPROGRAM
  // Cg / HLSL code of the shader
  // ...
  ENDCG
 }
}

 SubShader
 {
  Tags { }
  Pass {
    CGPROGRAM
    // Cg / HLSL code of the shader
    // ...
    ENDCG
  }
 }

Surf vs. Vert/Frag

两者的主要区别在于vert/frag shader没有物理语义,包括albedo,gloss,specular都不会在这个层面呈现。而surface shader的输出结构(SurfaceOutput等)则包含了这些内容。

Surface shader可以指定光照模型,shader中通常会有一个叫surf的函数,在此计算输出颜色,再将其输入光照模型获得最后的结果。所有的Surface shader被编译时都会转化成vert/frag shader,即surface shader是Unity提供的一种简易shader写法。

Vertex/Fragment则没有内置光照模型的概念,更适合用在非现实渲染、2D图形和后期处理上。(当然也可以在里头写光照只是相对不大方便)

Surface Shader

声明surface function,将需要的数据输入shader并进行计算,最终打包以SurfaceOutput格式输出。SurfaceOutput会定义有关表面的各项属性,包括albedo、normal、emission、specularity等。

一个surf shader中必须包含的内容有二:

其他常用到但不必须的:

void surf中,输入变量之一的IN是自定义的结构,通常会包含shader所需的变量信息。这个结构的中的变量命名是有要求的。

Vert/Frag Shader

TBC…

其他趟坑

  1. _MainTex_ST

如果要对贴图进行uv计算,则需要同时声明带有_ST后缀的同名贴图变量。

  1. TRANSFORM_TEX

TRANSFORM_TEX主要作用是拿顶点的uv去和材质球的tiling和offset作运算, 确保材质球里的缩放和偏移设置是正确的。在Material中的Tiling对应xy,Offset对应zw,以下两种变换是等价的:

o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;

添加这个贴图和uv坐标间的变换后,inspector中的相关tiling、offset参数调整才会生效。

  1. unity_ColorSpaceDouble

//待续…

  1. HideInInspector

如其名,声明变量但不显示在inspector中。程序相关但不希望美术碰的变量都可以这样处理。

  1. 关于UV的又一个坑

看插件代码的时候经常碰到拿amplfied shader editor制作的远古shader,代码里经常出现一些奇怪的东西,比如properties声明里经常有类似以下隐藏变量

[HideInInspector] _texcoord2("", 2D) = "white" {}
[HideInInspector] _texcoord("", 2D) = "white" {}

上述这样不明变量。用途是为后续uv_变量计算使用,但并不是直接使用上述的贴图变量,而是图一个同名(shader里的又一同名规则)。

struct Input
{
	float2 uv_texcoord;
	float2 uv2_texcoord2;
};

关于bug