Unity Shader基础

Unity Shader基础

先上代码,代码一般是这样的。

void Initialization(){
	//先从硬盘加载代码再加载到GPU中
	string vertexShaderCode = LoadShaderFormFile(VertexShader.shader);
	string fragmentShaderCode = LoadShaderFormFile(FragmentShader.shader);
	LoadVertexShaderFromString(vertexShaderCode);
	LoadVertexShaderFromString(fragmentShaderCode);
	//设置各种属性输入
	SetVertexShaderProperty("vertexPosition", vertices);
	SetVertexShaderProperty("MainTex", someTexture);
	SetVertexShaderProperty("MVP", MVP);
	Disable(Blend);			/关闭混合
	Enable(ZText);			//设置深度测试
	SetZTextFunction(LessOrEqual);
	//其他
}
void Onrendering(){
	//调用渲染命令
	DrawCall();
}

VertexShader.shader

in float3 vertexPosition;
in sampler2D MainTex;
in Mateix4x4 MVP;

out float4 position;

void main(){
	position = MVP * vertexPosition;
}

FragmentShader.shader

in float4 position;

out float4 fragColor;

void main(){
	fragColor = float4(1.0, 1.0, 1.0, 1.0);
}

Unity Shader 概述

Unity中shader需要和材质(Material)】配合使用才能达到需要的效果,一般流程:

  • 创建一个材质
  • 创建一个Unity Shader,并把它赋给上一步的材质
  • 把材质赋给给需要渲染的对象
  • 在材质面板中调整Unity Shader的属性,以得到满意的效果

单独的shader是无法发挥任何作用的,它必须和材质结合起来,才能产生效果。

ShaderLab

ShaderLab 是Unity提供的一种专门为Unity Shader服务的语言。

一般结构如下:

 Shader "Example/Diffuse Simple" {
    Properties {
    	//属性
    }
    SubShader {
    	//显卡A使用的子着色器
    }
    SubShader {
    	//显卡B使用的子着色器
    }
    Fallback "Diffuse"
}

材质和Unity Shader 的桥梁:Properties

Properties语义块的定义通常如下:

Properties {
	_Name ("Display Name", PropertyType) = DefaultValue
}

_Name 是属性的名字,在Shader中访问,通常以一个下划线开始。
"Display Name" 是显示的名称,会在材质面板中显示。
PropertyType 是指定它的类型,类型表如下:

属性类型 默认定义语法 例子
Int number _Int("Int", Int) = 2
Float number _Float("Float", Float) = 1.5
Range(min, max) number _Range("Range", Range(0.0, 5.0)) = 3.0
Color (number,number,number, number) _Color("Color", Color) = (1.0, 1.0, 1.0, 1.0)
Vector (number,number,number, number) _Vector("Vector", Vector) = (2, 3, 4, 5)
2D "defaulttexture"{} _2D("2D", 2D) = "white" {}
Cube "defaulttexture"{} _Cube("Cube", Cube) = "white" {}
3D "defaulttexture"{} _3D("3D", 3D) = "white" {}

SubShader语义块

定义模板:

SubShader {
	[Tags] //可选

	[RenderSetup]

	Pass {
	}
}

** 状态设置 **

ShaderLab中常见渲染状态设置选项

状态名称 设置指令 解释
Cull Cull Back/Front/Off 设置提出模式:剔除背面/正面/关闭剔除
ZTest ZTest Less Greater/LEqual/GEqual/NotEqual/Always 设置深度测试时使用的函数
ZWrite ZWriteON/Off 开启/关闭深度写入
Blend Blend SrcFactor DstFactor 开启并设置混合模式

** SubShader **

SubShader的标签(Tags)是一个键值对(Key/Value Pair),它的键和值都是字符串类型。
标签的结构如下:

Tags { "TagNamel" = "Valuel" "TagName2" = "Value2" }

SubShader的标签列表:

标签类型 说明 例子
Queue 控制渲染顺序 Tags { "Queue" = "Transparent" }
RenderType 对着色器分类 Tags { "RenderType" = "Opaque" }
DisableBatching Unity的SubShader批处理功能 Tags { "DisableBatching" = "True"}
ForceNoShadowCasting 控制使用该SubShader的物体是否投射阴影 Tags { "ForceNoShadowCasting" = "True"}
IgnoreProjector 使SubShader的物体不受Projector影响。通常用于半透明物体 Tags { "IgnoreProjector" = "True"}
CanUseSpriteAtlas 用于精灵时,设为false Tags { "CanUseSpriteAtlas" = "False"}
PreviewType 指明材质面板将如何预览该材质 Tags { "PreviewType" = "Plane"}

** 注意 ** 上述标签仅能在SubShader中声明,而不能在Pass中声明。Pass的标签与SubShader不同。

** Pass语义块 **

定义:

Pass {
	[Name]
	[Tags]
	[RenderSetup]
	//其他
}

Pass的标签类型:

标签类型 说明 例子
LightMode 定义该Pass在Unity的渲染流水线中的角色 Tags { "LightMode" = "ForwordBase"}
RequireOptions 用于指定当满足某些条件时才渲染该Pass,它的值是由空格分隔的字符串。目前,Unity只支持SoftVegetation Tags { "RequireOptions" = "SoftVegetation"}

** Fallback **

在SubShader后面的是一个Fallback指令,如果上面的SubShader在显卡上都不能运行,就运行这个最低级的Shader。相当于一个保险。

Unity Shader的形式

一般有三种Shader:

  • 表面着色器(Surface Shader)
  • 顶点着色器(Vertex Shader)
  • 固定函数着色器(Fixed Funtion Shader)

表面着色器

原来学OpenGL的时候,没听说个有什么表面着色器,因为这是Unity自己创建的一种着色器代码类型。

来看看官网的一个表面着色器代码:

Shader "Example/Diffuse Simple" {
    SubShader {
		Tags { "RenderType" = "Opaque" }
		CGPROGRAM
		#pragma surface surf Lambert
		struct Input {
			float4 color : COLOR;
		};
		void surf (Input IN, inout SurfaceOutput o) {
			o.Albedo = 1;
		}
		ENDCG
    }
    Fallback "Diffuse"
}

这段代码将材质的表面设置为白色。

CGPROGRRAM 和 ENDCG之间的代码是使用CG/HLSL编写的,这里需要将CG/HLSL语言嵌套在ShaderLab语言中。值得注意的是,这里的CG/HLSL语言跟原生的CG/HLSL语言有着细微的不同,例如有些原生的函数和用法Unity并没有支持。

顶点着色器

格式:

Shader "VertexAndFragment Shader" {
	  Pass {
	      // ... the usual pass state setup ...
	      
	      CGPROGRAM
	      // compilation directives for this snippet, e.g.:
	      #pragma vertex vert
	      #pragma fragment frag
	      
	      // the Cg/HLSL code itself
	      
	      ENDCG
	      // ... the rest of pass setup ...
	  }	
}

固定函数着色器

格式:

Shader "Basic" {
	Properties{
		_Color("Color", Color) = (1.0, 0.5, 0.5, 1.0)
	}
	SubShader {
		Pass {
			Material {
				Diffuse [_Color]
			}
			Lighting On
		}
	}
}

结束语:

Unity SHader 的选择:

  • 除非你有非常明确的需求必须要使用固定函数着色器,否则别用。
  • 如果要和各种灯光打交道,可能更需要表面着色器,但需要小心它在移动平台的性能表现。
  • 如果需要使用的光照数目非常少,顶点着色器是首选。
  • 最重要的是,如果有很多自定义的渲染效果,那么请选择顶点着色器。
原文地址:https://www.cnblogs.com/yoyo-sincerely/p/7898373.html