Unity Shader - Shader semantics 着色器语义

2023-11-02 10:10

本文主要是介绍Unity Shader - Shader semantics 着色器语义,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录:Unity Shader - 知识点目录(先占位,后续持续更新)
原文:Shader semantics
版本:2019.1

Shader semantics

着色器语义

当编写HLSL的shader programs着色器程序时,输入和输出变量需要了解他们的用意,使用 semantics (语义)来代表。这是HLSL着色器语言中的一个标准概念;查看 Semantics documentation on MSDN 了解更多详情。

你可以下载下面已展示的例子 zipped Unity project相关项目。
(如果下载不了,或是下载很慢,可以点击(提取码: vddu)这里,从百度网盘下载)

Vertex shader input semantics

顶点着色器输入语义

顶点着色器函数(使用 #pragma vertex 编译指令指定的函数)的所有输入参数都需要指定语义。这对应着Mesh的单个顶点的数据,如:顶点坐标,法线,纹理坐标。查看 vertex program inputs 了解更多详情。

这里有个简单的顶点着色器,带有顶点坐标和纹理坐标作为输入参数。像素着色器将纹理坐标直接作为颜色显示。

Shader "Unlit/Show UVs"
{SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment fragstruct v2f {float2 uv : TEXCOORD0;float4 pos : SV_POSITION;};v2f vert (float4 vertex : POSITION, // 输入的顶点坐标float2 uv : TEXCOORD0 // 输入的纹理坐标,通过语义指定在 TEXCOORD0 寄存器){v2f o;o.pos = UnityObjectToClipPos(vertex);o.uv = uv;return o;}fixed4 frag (v2f i) : SV_Target{return fixed4(i.uv, 0, 0);}ENDCG}}
}

在这里插入图片描述
在顶点着色器中我们是在函数参数中一个个的定义声明的,也可以在顶点着色器函数中传入结构体,然后再结构体中一个个的声明变量,和语义指定。查看 shader program examples 学习如何实现。

Fragment shader output semantics

片段着色器输出的语义

大多数片段(像素)着色器都会输出一个颜色值,并使用 SV_Target 语义指定。像上面的例子中片段着色器是这么声明定义的:

fixed4 frag (v2f i) : SV_Target

frag 函数返回 fixed4 类型(低精度 RGBA 颜色)数据。因为仅仅返回一个参数,所以在函数后面加上 SV_Target

也有可能输出的返回是个结构体数据。像上面的着色器可以改写成这样的方式:

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

从片段着色器返回的结构体通常用于返回的数据不只一个参数的时候是相同有用的方式。片段着色器输出支持的其他语义如下。

SV_TargetN: Multiple render targets

SV_Target: 多渲染目标

SV_Target1SV_Target2,等等:这些是着色器编写的额外颜色。这用于一次性渲染到多目标(就是我们说的:Multiple Render Targets(多渲染目标)的渲染技术,简称:MRT)。SV_Target0SV_Target 一样的意思。

SV_Depth: Pixel shader depth output

SV_Depth: 像素着色器深度输出

通常片段着色器不会去覆盖 Z-Buffer的值,Z-Buffer的默认值是从常规的三角形光栅化时就得到的。然而,有些特殊的效果使用自定义输出逐像素的Z-Buffer深度值是很有用的。

在不了解用法意图的时候不要去覆盖原始的Z-Buffer数值。SV_Depth 的消耗因GPU架构的不同而不同,但总体上它与alpha测试的消耗相当类似(使用HLSL中的内置clip()函数)。渲染着色器在渲染常规不透明对象后将会修改深度(例如,使用 AlphaTest 的 rendering queue(渲染队列))。

输出的深度值占用一个单精度 float 数值类型。

Vertex shader outputs and fragment shader inputs

顶点着色器的输出与片段着色器的输入

一个顶点着色器需要输出顶点最终裁剪空间的坐标,这样GPU才知道对应屏幕中光栅化的位置与深度。输出这些数值需要 SV_POSITION 语义来指定给一个 float4 类型的数值。

其它的输出根据你自己的着色器来定。顶点着色器输出的数值,将会被渲染出来三角面上对应的插值像素处理,然后这些所有插值出来的像素都将会传入到片段着色器中。

许多现代 GPU 都不太关心变量语义的指定;然而在一些老旧的系统(最值得注意的是,DX9的SM 2.0(着色器模型 2.0))中语义会有一些特定的规则:

  • TEXCOORD0TEXCOORD1 等等用于表示高精度的数据,如:纹理坐标或是其他顶点坐标。
  • COLOR0COLOR1 语义在顶点输出和片段输入中用于低精度,0-1范围的数据(如:简单的颜色数值)。

为了能够跨平台支持,顶点输出和片段输入都是用 TEXCOORDn 的语义来指定。

查看 shader program examples 例子。

Interpolator count limits

插值器的数量限制

将用于顶点传到片段着色器的变量插值器的数量是有限的。具体限制数量依赖于平台和GPU,通常参考如下:

  • Up to 8 interpolators (8个):OpenGL ES 2.0(iOS/Android),Direct3D 11 9.X 级别的(Windows Phone) 和 Direct3D 9 shader model 2.0(旧版PC)。所以插值器的数量是有限的,但没有插值器向量都有4个分量,shader中通常会充分利用这些分量,将打包数据放满到分量中使用。例如,两个纹理坐标可以传入到一个 float4 的变量中(.xy是第一个坐标的,.zw是第二个坐标的)。
  • Up to 10 interpolators (10个):Direct3D 9 shader model 3.0 (#pragma target 3.0)。
  • Up to 16 interpolators (16个): OpenGL ES 3.0(iOS/Android),Metal(iOS)。
  • Up to 32 interpolators (32个):Direct3D 10 shader model 4.0(#pragma target 4.0)。

不论你的具体的目标硬件是怎么样的,通常为了性能原因尽可能使用少量的插值器来处理。

Other special semantics

其他特殊的语义

Screen space pixel position: VPOS

屏幕空间像素的坐标:VPOS

片段着色器能接收一个渲染为特定的语义 VPOS 的像素坐标。这个功能仅从 shader model 3.0 开始才有的,所有需要 shader 指定 #pragma target 3.0 编译指令。

在不同平台下屏幕空间坐标输入变量的类型也有会有所不同,所以为了最大化的可移植性,使用 UNITY_VPOS_TYPE 类型(在多数平台使用的是 float4,且在 Direct3D 9使用的是 float2)。

此外,使用像素坐标语义使剪辑空间位置(SV_POSITION)和VPOS很难同时位于同一个vertext -to-fragment结构体中。所以顶点着色器应该输出裁剪空间坐标为 “out” 变量。查看下面的shader例子:

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 structstruct v2f {float2 uv : TEXCOORD0;};v2f vert (float4 vertex : POSITION, // vertex position inputfloat2 uv : TEXCOORD0, // texture coordinate inputout 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 将包含像素的整数坐标值。// 用它们实现棋盘团来,替代渲染4x4的像素块(4x4纹理)// 棋盘图案每个格将使用4x4的像素块screenPos.xy = floor(screenPos.xy * 0.25) * 0.5;float checker = -frac(screenPos.r + screenPos.g);// 如果checker为负数,则使用HLSL 内置函数 clip 来停止绘制该像素clip(checker);// 保持绘制的像素将采样纹理值并输出fixed4 c = tex2D (_MainTex, i.uv);return c;}ENDCG}}
}

在这里插入图片描述

Face orientation: VFACE

面的朝向: VFACE

片段着色器能接收一个代表当前渲染出来的表面是否朝向相机的变量。当渲染的几何体需要显示双面时是很有用的,通常用于树叶或是其他类似很薄的对象。 VFACE 语义指定给输入变量后,正值代表该光栅出来的三角面是正面,负值是背面。

这个功能是再shader model 3.0或之后才有的,所以shader需要 #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 // 关闭背面剔除CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma target 3.0float4 vert (float4 vertex : POSITION) : SV_POSITION{return UnityObjectToClipPos(vertex);}fixed4 _ColorFront;fixed4 _ColorBack;fixed4 frag (fixed facing : VFACE) : SV_Target{// VFACE 输入值 正值代表正面,负值代表背面。// 输出正面颜色_ColorFont 还是背面颜色_ColorBack 取决于 facing值得正负return facing > 0 ? _ColorFront : _ColorBack;}ENDCG}}
}

上面的shader使用了 Cull 状态设置来关闭背面剔除(默认三角面的背面是不渲染的)。这里该shader 应用于一堆旋转朝向不一的四边形网格。
在这里插入图片描述

Vertex ID: SV_VertexID

顶点ID: SV_VertexID

顶点着色器能接收一个代表顶点编号的无符号整数。当你想从纹理或ComputeBuffers (计算缓存数据)中获取其他的顶点数据时是很有用的。

这个功能仅在 DX10(shader model 4.0)和 GLCore / OpenGL ES 3中存在,所以shader需要 #pragma target 3.5 编译指令。

Shader "Unlit/VertexID"
{SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma target 3.5struct v2f {fixed4 color : TEXCOORD0;float4 pos : SV_POSITION;};v2f vert (float4 vertex : POSITION, // 输入的顶点坐标uint vid : SV_VertexID // 顶点ID,必须为uint类型){v2f o;o.pos = UnityObjectToClipPos(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}}
}

在这里插入图片描述
你可以下载上面已展示的例子 zipped Unity project相关项目。
(如果下载不了,或是下载很慢,可以点击(提取码: vddu)这里,从百度网盘下载)

这篇关于Unity Shader - Shader semantics 着色器语义的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/329889

相关文章

理解分类器(linear)为什么可以做语义方向的指导?(解纠缠)

Attribute Manipulation(属性编辑)、disentanglement(解纠缠)常用的两种做法:线性探针和PCA_disentanglement和alignment-CSDN博客 在解纠缠的过程中,有一种非常简单的方法来引导G向某个方向进行生成,然后我们通过向不同的方向进行行走,那么就会得到这个属性上的图像。那么你利用多个方向进行生成,便得到了各种方向的图像,每个方向对应了很多

Unity Post Process Unity后处理学习日志

Unity Post Process Unity后处理学习日志 在现代游戏开发中,后处理(Post Processing)技术已经成为提升游戏画面质量的关键工具。Unity的后处理栈(Post Processing Stack)是一个强大的插件,它允许开发者为游戏场景添加各种视觉效果,如景深、色彩校正、辉光、模糊等。这些效果不仅能够增强游戏的视觉吸引力,还能帮助传达特定的情感和氛围。 文档

Unity协程搭配队列开发Tips弹窗模块

概述 在Unity游戏开发过程中,提示系统是提升用户体验的重要组成部分。一个设计良好的提示窗口不仅能及时传达信息给玩家,还应当做到不干扰游戏流程。本文将探讨如何使用Unity的协程(Coroutine)配合队列(Queue)数据结构来构建一个高效且可扩展的Tips弹窗模块。 技术模块介绍 1. Unity协程(Coroutines) 协程是Unity中的一种特殊函数类型,允许异步操作的实现

Unity 资源 之 Super Confetti FX:点亮项目的璀璨粒子之光

Unity 资源 之 Super Confetti FX:点亮项目的璀璨粒子之光 一,前言二,资源包内容三,免费获取资源包 一,前言 在创意的世界里,每一个细节都能决定一个项目的独特魅力。今天,要向大家介绍一款令人惊艳的粒子效果包 ——Super Confetti FX。 二,资源包内容 💥充满活力与动态,是 Super Confetti FX 最显著的标签。它宛如一位

Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(4)

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​​ Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(3)-CSDN博客  这节就是真正的存储数据了   理清一下思路: 1.存储路径并检查 //2进制文件类存储private static string Data_Binary_Pa

Unity Adressables 使用说明(一)概述

使用 Adressables 组织管理 Asset Addressables 包基于 Unity 的 AssetBundles 系统,并提供了一个用户界面来管理您的 AssetBundles。当您使一个资源可寻址(Addressable)时,您可以使用该资源的地址从任何地方加载它。无论资源是在本地应用程序中可用还是存储在远程内容分发网络上,Addressable 系统都会定位并返回该资源。 您

Unity Adressables 使用说明(六)加载(Load) Addressable Assets

【概述】Load Addressable Assets Addressables类提供了加载 Addressable assets 的方法。你可以一次加载一个资源或批量加载资源。为了识别要加载的资源,你需要向加载方法传递一个键或键列表。键可以是以下对象之一: Address:包含你分配给资源的地址的字符串。Label:包含分配给一个或多个资源的标签的字符串。AssetReference Obj

在Unity环境中使用UTF-8编码

为什么要讨论这个问题         为了避免乱码和更好的跨平台         我刚开始开发时是使用VS开发,Unity自身默认使用UTF-8 without BOM格式,但是在Unity中创建一个脚本,使用VS打开,VS自身默认使用GB2312(它应该是对应了你电脑的window版本默认选取了国标编码,或者是因为一些其他的原因)读取脚本,默认是看不到在VS中的编码格式,下面我介绍一种简单快

Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(3)

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​​ Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(2) (*****生成数据结构类的方式特别有趣****)-CSDN博客 做完了数据结构类,该做一个存储类了,也就是生成一个字典类(只是声明)  实现和上一节的数据结构类的方式大同小异,所

【Unity小技巧】URP管线遮挡高亮效果

前言 在URP渲染管线环境下实现物体遮挡高亮显示效果,效果如下: Unity URP遮挡高亮 实现步骤 创建层级,为需要显示高亮效果的物体添加层级,比如Player 创建一个材质球,也就是高亮效果显示的材质球找到Universal Renderer Data Assets 4.在Assets上添加两个Render Objects组件 第一个做如下三处设置 指定遮挡层级指