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 的选择:

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

Unity Shader基础的更多相关文章

  1. Unity Shader 基础(4) 由深度纹理重建坐标

    在PostImage中经常会用到物体本身的位置信息,但是Image Effect自身是不包含这些信息的,因为屏幕后处其实是使用特定的材质渲染一个刚好填满屏幕的四边形面片(四个角对应近剪裁面的四个角). ...

  2. Unity Shader入门精要学习笔记 - 第3章 Unity Shader 基础

    来源作者:candycat   http://blog.csdn.net/candycat1992/article/ 概述 总体来说,在Unity中我们需要配合使用材质和Unity Shader才能达 ...

  3. 第二章 Unity Shader基础

    [TOC] 1. Unity Shader 的基础: ShaderLab 学习和编写着色器的过程一直是一个学习曲线很陡峭的过程,通常情况下为了自定义渲染效果往往要和很多文件和设置打交道,这些设置很容易 ...

  4. Unity Shader 基础

    推荐: https://www.cnblogs.com/nanwei/p/7277417.html 上面链接作者的整个系列都写的不错 https://www.cnblogs.com/nanwei/ca ...

  5. Unity Shader 基础(3) 获取深度纹理

    Unity提供了很多Image Effect效果,包含Global Fog.DOF.Boom.Blur.Edge Detection等等,这些效果里面都会使用到摄像机深度或者根据深度还原世界坐标实现各 ...

  6. Unity Shader 基础(1): RenderType & ReplacementShader

    很多Shader中都会定义RenderType这个类型,但是一直搞不明白到底是干嘛的,官方文档是这样结解释的:Rendering with Replaced Shaders Rendering wit ...

  7. Unity Shader基础(1):基础

    一.Shaderlab语法 1.给Shader起名字 Shader "Custom/MyShader" 这个名称会出现在材质选择使用的下拉列表里 2. Properties (属性 ...

  8. Unity Shader 基础(2) Image Effect

    Unity中 Image Effect 是Post Processing的一种方,Unity自身也提供很多Effect效果供使用.Image Effect的使用官方文档做了很多介绍,这里重点Post ...

  9. Unity Shader基础:编译指令

    UntiyShader中,编译指令分为两种: 1.顶点片元着色器(Vetex & Fragment Shader)使用的编译指令 2.表面着色器(Surface Shader)使用的编译指令 ...

随机推荐

  1. User-Agent大全

    一.基础知识篇: Http Header之User-Agent User Agent中文名为用户代理,是Http协议中的一部分,属于头域的组成部分,User Agent也简称UA.它是一个特殊字符串头 ...

  2. Intellij IDEA 快捷键整理(转)

    Ctrl+Shift + Enter,语句完成 “!”,否定完成,输入表达式时按 “!”键 Ctrl+E,最近的文件 Ctrl+Shift+E,最近更改的文件 Shift+Click,可以关闭文件 C ...

  3. 《JavaScript 实战》:JavaScript 实现拖拽缩放效果

    拖拉缩放效果,实现通过鼠标拖动来调整层的面积(宽高)大小,例如选框效果.这里的拖拉缩放比一般的选框复杂一点,能设置八个方位(方向)的固定触发点,能设置最小范围,最大范围和比例缩放. 跟拖放效果一样,程 ...

  4. 【LibreOJ】#6298. 「CodePlus 2018 3 月赛」华尔兹 BFS

    [题意]给定n*m的网格,起点和终点位置,一些格指定下一步的方向,一些格任意.要求为方向任意的格确定方向,使起点可以走到终点.n,m<=50. [算法]BFS [题解]这道题最好用BFS,因为D ...

  5. 【leetcode 简单】第十六题 二进制求和

    给定两个二进制字符串,返回他们的和(用二进制表示). 输入为非空字符串且只包含数字 1 和 0. 示例 1: 输入: a = "11", b = "1" 输出: ...

  6. thinkphp博客项目纪录

    项目地址:http://files.cnblogs.com/files/wordblog/blog.zip

  7. MySQL-索引工作原理及使用注意事项

    1.为什么需要索引(Why is it needed)? 当数据保存在磁盘类存储介质上时,它是作为数据块存放.这些数据块是被当作一个整体来访问的,这样可以保证操作的原子性.硬盘数据块存储结构类似于链表 ...

  8. CTSC 2017 游记

    惨啊,弱菜选手只报上了CTSC,去不了APIO. day -1 晚上的时候,坐上了去帝都的卧铺. 由于第二天就是luogu月赛round1,还得在火车上赶工出题... 颓了好长时间,把题面写出来了,用 ...

  9. 在Ubuntu上安装Redis MySQL MongoDB memcached Nginx

    1.安装Redis sudo apt-get install redis-server 2.安装MySQL sudo apt-get install mysql-server 3.安装MongoDB ...

  10. C/C++——C语言数组名与指针

    版权声明:原创文章,转载请注明出处. 1. 一维数组名与指针 对于一维数组来说,数组名就是指向该数组首地址的指针,对于: ]; array就是该数组的首地址,如果我们想定义一个指向该数组的指针,我们可 ...