在书写HLSL shader程序时,输入和输出变量需要拥有他们 含义来表明语义。这在HLSL shader中是一个标准的做法。

Vertex shader 输入语义

主顶点着色器函数(被指令 #pragma vertex 标记)需要在所有的输入参数中加上语义。这些对应于单个网格数据元素,比如顶点位置,网格法线,还有贴图坐标等。简单例子如下:

Shader "Unlit/Show UVs"
{
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag struct v2f {
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
}; v2f vert (
float4 vertex : POSITION, // vertex position input
float2 uv : TEXCOORD0 // first texture coordinate input
)
{
v2f o;
o.pos = UnityObjectToClipPos(vertex);
o.uv = uv;
return o;
} fixed4 frag (v2f i) : SV_Target
{
return fixed4(i.uv, 0, 0);
}
ENDCG
}
}
}

Fragment shader 输出语义

大多数情况下,片段着色器输出一个额颜色,并且含有 SV_Target语义。就比如:

fixed4 frag(v2f i): SV_Target

函数 frag 有一个返回类型为 fixed4 的值。因为它只会返回一个值,那么语义就可以直接定义在函数上。

当然,输出返回一个结构体也是可以的。上面的片段着色器可以被重写为下面这个样子,并且他们的功能一致:

struct fragOutput
{
fixed4 color : SV_Target;
}; fragOutput frag(v2f i)
{
fragOutput o;
o.color = fixed4(i.uv,0,0);
return o;
}

从片段着色器中返回结构体,对于那些不单单返回一个颜色的着色器非常有用。支持片段着色器输出的额外的语义如下:

SV_TargetN: 多个渲染目标

  SV_Target1,SV_Target2等等:这些是shader输出的额外的颜色。这种做法在一次性渲染多个目标时使用(也叫作多重渲染目标渲染技术,MRT)。当然,SV_Target0 就等于SV_Target

SV_Depth:像素着色器深度输出

  通常情况,片段着色器不会覆写 Z 缓冲区的值,在三角形光栅化阶段,一般都用的是默认值。然而,对于一些特效,对每个像素使用自己的z缓冲区值是非常有帮助的。

  注意在许多GPU上,深度缓冲优化是关闭了的,所以在没有必须的理由时,最好不要重写深度缓冲区的值。由 SV_Depth 引发的性能消耗 根据GPU架构不同而不同,但是总体上来说这个消耗与alpha 测试相当。

Vertex shader 输出和 fragment shader 输入

一个vertex shader需要输出 一个顶点的 最终剪切空间坐标,这样GPU才知道在屏幕上的哪个地方、多少深度来光栅化它,这个输出需要有 SV_POSITION 语义,而且它的类型是一个 float4类型的数据。

vertex shader产生的任何其他输出都是你特殊着色器所需要的。从顶点着色器输出的值将被用来渲染三角形面,并且每个像素的值将被会作为输入数据传给片段着色器。

许多现代的GPU不需要真正关心这些变量有哪些语义;然而一些老系统却是需要一些特别的语义:

  TEXCOORD0,TEXCOORD1等等用来表明任意高精度数据,比如坐标或者位置。

  COLOR0,COLOR1 语义在顶点着色器输出和片段着色器输入中代表 低精度,0-1范围内的数据。

为了最好的跨平台支持, 在顶点着色器的输出与片段说色器的输入中,最好打上 TEXCOORDn语义标签。

插入器数量限制

将信息从顶点着色器传递到片段着色器中时,插入器变量可以使用的总量有着数量限制。限制数量与平台和GPU有关:

  • 最高8个:OpenGL ES 2.0 (iOS/Android), Direct3D 11 9.x level (Windows Phone) and Direct3 9 shader model 2.0 (old PCs).虽然插入器数量被限制了,但是每个插入器可以是一个4分量的向量,一些着色器将数据打包到一起来不超过限制。比如,两个贴图坐标可以被一个float4变量传递。
  • 最高10个:Direct3D 9 shader model 3.0 (#pragma target 3.0).
  • 最高16个:OpenGL ES 3.0 (iOS/Android), Metal (iOS).
  • 最高32个:Direct3D 10 shader model 4.0 (#pragma target 4.0).

为了性能着想,不管你是啥平台,最好都尽量使用更低数量的插入器。

其它特别的语义

Screen space pixel position:VPOS

一个片段着色器可以接受一个作为特别 VPOS语义呈现的像素的位置。这个特性只有在以 model 3.0开头的着色器中才存在。所以着色器需要编译指令:#pragma target 3.0

在不同的平台,屏幕空间位置的输入在底层上是不同的,所以为了最大限度的可移植性,在使用屏幕空间位置时,使用 UNITY_VPOS_TYPE标签。(大多数情况为float4,但是在D3D9 为float2)。

此外, 使用像素位置语义让在一个顶点到片段的结构体 同时拥有 剪切空间位置(SV_POSITION)和VPOS(屏幕空间位置)变得困难。所以顶点着色器需要将 剪切空间位置(SV_POSITION)作为一个单独的输出变量。请看下面的例子:

Shader "Unlit/Screen Position"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0 // note: no SV_POSITION in this struct
struct v2f {
float2 uv : TEXCOORD0;
}; v2f vert (
float4 vertex : POSITION, // vertex position input
float2 uv : TEXCOORD0, // texture coordinate input
out float4 outpos : SV_POSITION // clip space position output
)
{
v2f o;
o.uv = uv;
outpos = UnityObjectToClipPos(vertex);
return o;
} sampler2D _MainTex; fixed4 frag (v2f i, UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target
{
// screenPos.xy will contain pixel integer coordinates.
// use them to implement a checkerboard pattern that skips rendering
// 4x4 blocks of pixels // checker value will be negative for 4x4 blocks of pixels
// in a checkerboard pattern
screenPos.xy = floor(screenPos.xy * 0.25) * 0.5;
float checker = -frac(screenPos.r + screenPos.g); // clip HLSL instruction stops rendering a pixel if value is negative
clip(checker); // for pixels that were kept, read the texture and output it
fixed4 c = tex2D (_MainTex, i.uv);
return c;
}
ENDCG
}
}
}

Face Orientation:VFACE

片段着色器可以接受一个变量,这个变量表明当前渲染的表面是否面对着摄像机,或者背对着摄像机。这一点在渲染那些两面都可以被看到的几何体时非常有用-比如渲染叶子。语义 VFACE修饰的 输入变量将会包含一个正值表明正对着的三角形,一个负数来表明背对这的三角形。

这个特性只有在 model 3.0 的着色器中才有,所以着色器必须包含编译指令: #pragma target 3.0,例子如下:

Shader "Unlit/Face Orientation"
{
Properties
{
_ColorFront ("Front Color", Color) = (1,0.7,0.7,1)
_ColorBack ("Back Color", Color) = (0.7,1,0.7,1)
}
SubShader
{
Pass
{
Cull Off // turn off backface culling CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0 float4 vert (float4 vertex : POSITION) : SV_POSITION
{
return UnityObjectToClipPos(vertex);
} fixed4 _ColorFront;
fixed4 _ColorBack; fixed4 frag (fixed facing : VFACE) : SV_Target
{
// VFACE input positive for frontbaces,
// negative for backfaces. Output one
// of the two colors depending on that.
return facing > 0 ? _ColorFront : _ColorBack;
}
ENDCG
}
}
}

  

Vertex ID: SV_VertexID

顶点着色器可以接收一个具有顶点数作为无符号整数的变量。当你想从贴图或者计算缓冲区中拿到额外的每个顶点数据时,这样就非常有用。

这个特性只有在DX10 和GLCore/OpenGL ES 3中才支持,所以需要引入编译指令 #pragma target 3.5,例子如下:

Shader "Unlit/VertexID"
{
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.5 struct v2f {
fixed4 color : TEXCOORD0;
float4 pos : SV_POSITION;
}; v2f vert (
float4 vertex : POSITION, // vertex position input
uint vid : SV_VertexID // vertex ID, needs to be uint
)
{
v2f o;
o.pos = UnityObjectToClipPos(vertex);
// output funky colors based on vertex ID
float f = (float)vid;
o.color = half4(sin(f/10),sin(f/100),sin(f/1000),0) * 0.5 + 0.5;
return o;
} fixed4 frag (v2f i) : SV_Target
{
return i.color;
}
ENDCG
}
}
}

  

Shader 语义的更多相关文章

  1. Unity Shader入门精要学习笔记 - 第5章 开始 Unity Shader 学习之旅

    一个顶点/片元 着色器的结构大概如下: Shader "MyShaderName" { Properties { //属性 } SubShader { //针对显卡A的SubSha ...

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

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

  3. 第四章 开始Unity Shader学习之旅(1)

    1. 一个最简单的顶点/片元着色器 现在,我们正式开始学习如何编写Unity Shader,更准确的说是,学习如何编写顶点/片元着色器 2.顶点/片元着色器的基本结构 我们在以前已经讲过了Unity ...

  4. 第二章 Unity Shader基础

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

  5. Unity Shader概述

    一.概述 在Unity中需要配合使用材质和Unity Shader才能达到需要的效果.常见的流程:(1)创建一个材质:(2)创建一个Unity Shader,并把它赋给创建的材质:(3)把材质赋给要渲 ...

  6. Unity3D学习笔记3——Unity Shader的初步使用

    目录 1. 概述 2. 详论 2.1. 创建材质 2.2. 着色器 2.2.1. 名称 2.2.2. 属性 2.2.3. SubShader 2.2.3.1. 标签(Tags) 2.2.3.2. 渲染 ...

  7. 【Unity Shader】二、顶点函数(vertex)和片元函数(fragment)传递数据,及各阶段可使用的语义(semantic)

    学习资料:http://www.sikiedu.com/course/37/task/433/show 本节学习目标: 学习Shader中结构体struct的使用. 学习在片元函数(vertex)和顶 ...

  8. [Unity Shader] 常用的数值类型和语义

    书看到第八章,跟随写了一些例子,但有些数值类型的使用还是需要特别注意,经常需要查阅,在这里做一下总结. 1 ShaderLab属性类型和Cg变量类型的匹配关系 Color.Vector:float4, ...

  9. Shader 结构体中语义的理解

    Shader编写通常会遇到语义 1 float4 vert(float4:POSITION):SV_POSITION 2 { 3 return mul(UNITY_MATRIX_MVP,v); 4 } ...

随机推荐

  1. Android html5和Android之间的交互

    今天补充了会昨天的问题,然后搞半天又出现莫名其妙的问题. 今天讲的是交互,先说html5在Android的调用. 上面的hello world上面的部分都是安卓里的布局 然后按这些布局自动生成代码. ...

  2. Android SP的具体内容

    过了这么久了,看看自己的园龄都17天了,一直在总结,从未缺席,我还是很开心的,踏踏实实的完成自己能学到的. 今天学习SP SP:全称SharedPreferences,别问我为啥知道,因为打了好多遍了 ...

  3. CSS漂亮盒子(下)

    4.多重背景 CSS支持一个元素设置多个背景图片. 每个背景属性有相应的多值语法,多个值由逗号分隔. .multi-bg-shorthand { width: 300px; height: 200px ...

  4. gym102586 部分题解

    目录 Evacuation Sum Modulo Count Modulo 2 Robots Construct Points Amidakuji Yosupo's Algorithm link 出于 ...

  5. java Iterator迭代器

    一 Iterator迭代器概述 java中提供了很多个集合,它们在存储元素时,采用的存储方式不同.我们要取出这些集合 中的元素,可通过一种通用的获取方式来完成. Collection集合元素的通用获取 ...

  6. C#LeetCode刷题之#507-完美数(Perfect Number)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3879 访问. 对于一个 正整数,如果它和除了它自身以外的所有正因 ...

  7. Java中的策略模式,完成一个简单地购物车,两种付款策略实例教程

    策略模式是一种行为模式.用于某一个具体的项目有多个可供选择的算法策略,客户端在其运行时根据不同需求决定使用某一具体算法策略. 策略模式也被称作政策模式.实现过程为,首先定义不同的算法策略,然后客户端把 ...

  8. JavaFX桌面应用-视频转码工具(支持爱奇艺qsv转mp4)

    最近由于需要将在爱奇艺下载的视频(qsv)转化了mp4,用JavaFX开发一个视频转码工具,算是JavaFX开发的第一个应用吧. 支持qsv转码mp4,理论上支持各种格式,仅测试了flv,qsv格式. ...

  9. excel表格,根据某一列的值对整行进行颜色填充

    1.选中要影响的表格范围,选择 “条件格式”,选择 “新建规则” (2)选择 “使用公式确定要设置格式的单元格”,录入公式,选择 “ 格式”,注意: 公式为:=$H1="待解决" ...

  10. JDK1.8源码学习-String

    JDK1.8源码学习-String 目录 一.String简介 String类是Java中最常用的类之一,所有字符串的字面量都是String类的实例,字符串是常量,在定义之后不能被改变. 二.定义 p ...