[译]Unity3D Shader教程(一)ShaderLab结构

2023-11-25 07:40

本文主要是介绍[译]Unity3D Shader教程(一)ShaderLab结构,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 1 Shader结构
  • 2 ShaderLab
    • 2.1 创建Shader
    • 2.2 ShaderLab
    • 2.3 Shader/SubShader/Pass
    • 2.4 Properties and Tags


原文地址
Shader Tutorials by Ronja。


1 Shader结构

在用Shader实现出我们想要的效果前,我们需要先知道Shader代码的基本结构(就像我们用C#编程需要先知道C#的语法一样)。
大多数现代着色器都有一个可变的渲染管线,它至少由一个顶点着色器和一个片段着色器组成,还可以添加几何着色器和曲面细分器,但是这两者我们很少使用。

上面的管线是指什么?可以简单理解为我们工厂中的流水线,那流水线是怎么样的?原材料准备好后,先给工位1的员工进行加工,工位1加工完成后的半成品给工位2的员工继续加工,工位2的员工加工完成后的半成品继续给工位3的员工加工…直到最后一道工序加工完毕,原材料也就变成了产品。那么什么是可变的呢?这里的可变可以理解为一些工位是必需的一些工位不是必需的,可要可不要。比如之前原材料需要经过工位1、工位2、工位3的加工才能做出产品,现在我们把工位2去掉,只留工位1和工位3,但是也能加工出完整的产品。
渲染管线中的顶点着色器和片段着色器就相当于咱们上面流水线的工位1和工位3,这两个在我们的Shader代码中是必需的。而几何着色器和曲面细分器就相当于上面流水线的工位2,虽然它们不是必需的,但是写Shader时用它们可以做出一些特殊的效果,这里不再多说。

顶点着色器(也称为顶点阶段或顶点函数)的作用是将模型的数据变换到屏幕空间下,以便后面的工序(如片元着色器)使用。
模型数据是什么?包括模型网格的顶点的局部坐标、法线方向、uv坐标等。
用什么方法将模型的数据变换到屏幕空间的呢?矩阵变换。由于矩阵变换的原理不是一时半会儿能说清楚的,这就不多说了,暂且记住就行。

除了将模型的数据变换到屏幕空间这一基本功能外,我们可以用自定义的顶点着色器让顶点产生动画而不用我们手动去修改模型的网格,同时可以也将更多数据输出(比如顶点坐标对应的世界坐标等)给片段着色器。经过顶点着色器后,我们得到了屏幕空间上的顶点,顶点之间构成的三角形被光栅化器转换为像素。同时,光栅化器对顶点着色器的输出进行线性的插值,因此网格中间的像素也获得了输出值。在决定渲染哪些像素后,片段着色器(也称为像素着色器)决定像素的颜色。
光栅器的插值过程可以参考下面这张图理解:左边是顶点着色器的输出,右边是光栅器插值后的输出。
光栅化插值过程
大致的管线过程如下:
渲染流水线
从上面我们可以也看出,Shader的作用其实就是以模型的数据为顶点着色器的输入,最后通过片元着色器输出像素颜色。所以Shader代码中必须包含顶点着色器和片元着色器两部分。无论使用什么语言来编写Shader,顶点着色器和片元着色器都是必需的,即使没有顶点和片元阶段概念的基于节点的着色器(如Shader Graph)仍然会在内部生成这些阶段(顶点着色器、片元着色器)。

2 ShaderLab

2.1 创建Shader

Unity 中的着色器代码是一个文本文件,文件名以 .shader 结尾,与 C# 脚本以 .cs 结尾的方式类似。我们可以通过右键单击Assets区域 > Create > Shader > 选择一个模板 来轻松创建其中一个模板。由于我们刚开始学习,所以我们从创建一个最简单的无光照的Shader开始,右键单击 Assets> Create > Shader > Unlit Shader。长下面这个样子。

Shader "Unlit/NewUnlitShader"
{Properties{_MainTex ("Texture", 2D) = "white" {}}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag// make fog work#pragma multi_compile_fog#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;UNITY_FOG_COORDS(1)float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);UNITY_TRANSFER_FOG(o,o.vertex);return o;}fixed4 frag (v2f i) : SV_Target{// sample the texturefixed4 col = tex2D(_MainTex, i.uv);// apply fogUNITY_APPLY_FOG(i.fogCoord, col);return col;}ENDCG}}
}

2.2 ShaderLab

Unity的Shader是一种被称为“ShaderLab”的自定义语言,它定义了Shader中常用的输入输出数据以及渲染管线中的一些状态,同时用一个代码块将真正的Shader代码(顶点着色器、片元着色器等,用hlsl、glsl或cg编写)包含进来。
上面这句话可能没怎么表达清楚,看图。
在这里插入图片描述
从上面可以看出,真正的ShaderLab现在只占用我们着色器文件的一小部分。它只是以更抽象的形式描述事物,Unity最终会将ShaderLab的部分编译成hlsl、glsl或cg。

2.3 Shader/SubShader/Pass

ShaderLab文件中,由多个大括号 {} 来划分代码块。

其中Shader{}定义了整个着色器,每个Shader文件有且只能有一个Shader{}。Shader后面跟的是此Shader的名字,可以通过斜杠(/)来个各个Shader分门别类。比如我们如下设置

Shader "Tutorials/NewUnlitShader"
{// ...FallBack "VertexLit"
}

则此Shader在Unity菜单栏的位置就如下。
Shader在Menu中的位置
Shder{}代码块中有一个FallBack,其用来定义后备着色器,其作用相当于将后备着色器的所有子着色器粘贴到我们的着色器文件中。我们一般通过添加FallBack "VertexLit"来生成阴影 。为什么用“VertexLit”来生成阴影呢,因为它消耗比较少。
一个Shader{}块可以包含一个或多个SubShader{}。一般编写不同的子着色器供不同的硬件使用,但是关于如何定义以及何时使用哪个子着色器的文档非常缺乏,根据经验,大多数情况使用一个SubShader就已经足够了。
在SubShader中,我们还可以定义SubShader的标签Tags和属性Properties,这些标签和属性将作用于该SubShader中的所有Pass。

Pass 代表一次完整的渲染过程(即一个Pass就表示会完整执行一次渲染流水线,一个Pass绘制一次图像到屏幕上)。如果我们定义了多个Pass,它们将一个接一个地绘制(但URP 只会执行一次Pass)。有多个Pass的着色器被称为多Pass着色器。Pass代码块中可以设置此Pass的名称(可选的),也可以同SubShader一样设置标签Tags和属性(但Pass内的标签和属性只作用于这一个Pass,SubShader中的属性和标签作用于该SubShader中的所有Pass) ,最重要的它包含实际处理渲染的代码(即顶点着色器和片元着色器)。

2.4 Properties and Tags

现在我们来看看上面还没详细说明的Properties和Tags代码块。
Tags标签,用键值对表示。 Subshader 中的Tags标签主要定义带有着色器的材质如何在编辑器中显示,何时渲染或可以对它们应用哪些操作,而 pass 标签主要用于在遗留管道中定义哪些 pass 用于光计算的哪个步骤,SubShader的Tags和Pass的Tags具体可以设置哪些内容可以查看Unity的官方文档。
Properties属性用于在材质编辑器中显示变量。我们一旦更改这些属性的值,使用该材质的物体都将改变。如果我们想每个不同的物体都使用不同的属性,我们得用另外的方法了。由于默认情况下我们可以访问纹理坐标,并且我们可以通过这些属性设置纹理,这样我们可以实现很多效果。我将在下一个文章之一中更深入地解释属性。
总的来说,下面就是着色器的粗略结构。

Shader "Category/Name"{Properties{//Properties}Subshader{Tags{//Subshader Tags}//Settings for all passesPass{Tags{//Pass Tags}//Settings for passCGPROGRAM//shader codeENDCG}}
}

原作者的GitHub。
本文Shader

Shader "Tutorial/001-004_Basic_Unlit"{//show values to edit in inspectorProperties{
//	_Color ("Tint", Color) = (0, 0, 0, 1)
//	_MainTex ("Texture", 2D) = "white" {}}SubShader{//the material is completely non-transparent and is rendered at the same time as the other opaque geometryTags{ "RenderType"="Opaque" "Queue"="Geometry" }Pass{CGPROGRAM
//
//		//include useful shader functions
//		#include "UnityCG.cginc"
//
//		//define vertex and fragment shader functions
//		#pragma vertex vert
//		#pragma fragment frag
//
//		//texture and transforms of the texture
//		sampler2D _MainTex;
//		float4 _MainTex_ST;
//
//		//tint of the texture
//		fixed4 _Color;
//
//		//the mesh data thats read by the vertex shader
//		struct appdata{
//			float4 vertex : POSITION;
//			float2 uv : TEXCOORD0;
//		};
//
//		//the data thats passed from the vertex to the fragment shader and interpolated by the rasterizer
//		struct v2f{
//			float4 position : SV_POSITION;
//			float2 uv : TEXCOORD0;
//		};
//
//		//the vertex shader function
//		v2f vert(appdata v){
//			v2f o;
//			//convert the vertex positions from object space to clip space so they can be rendered correctly
//			o.position = UnityObjectToClipPos(v.vertex);
//			//apply the texture transforms to the UV coordinates and pass them to the v2f struct
//			o.uv = TRANSFORM_TEX(v.uv, _MainTex);
//			return o;
//		}
//
//		//the fragment shader function
//		fixed4 frag(v2f i) : SV_TARGET{
//			//read the texture color at the uv coordinate
//			fixed4 col = tex2D(_MainTex, i.uv);
//			//multiply the texture color and tint color
//			col *= _Color;
//			//return the final color to be drawn on screen
//			return col;
//
//		}ENDCG}}Fallback "VertexLit"
}

ps:感觉翻译得很垃圾啊,捂脸。
博主本文博客链接。

这篇关于[译]Unity3D Shader教程(一)ShaderLab结构的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Oracle查询表结构建表语句索引等方式

《Oracle查询表结构建表语句索引等方式》使用USER_TAB_COLUMNS查询表结构可避免系统隐藏字段(如LISTUSER的CLOB与VARCHAR2同名字段),这些字段可能为dbms_lob.... 目录oracle查询表结构建表语句索引1.用“USER_TAB_COLUMNS”查询表结构2.用“a

Python pandas库自学超详细教程

《Pythonpandas库自学超详细教程》文章介绍了Pandas库的基本功能、安装方法及核心操作,涵盖数据导入(CSV/Excel等)、数据结构(Series、DataFrame)、数据清洗、转换... 目录一、什么是Pandas库(1)、Pandas 应用(2)、Pandas 功能(3)、数据结构二、安

2025版mysql8.0.41 winx64 手动安装详细教程

《2025版mysql8.0.41winx64手动安装详细教程》本文指导Windows系统下MySQL安装配置,包含解压、设置环境变量、my.ini配置、初始化密码获取、服务安装与手动启动等步骤,... 目录一、下载安装包二、配置环境变量三、安装配置四、启动 mysql 服务,修改密码一、下载安装包安装地

电脑提示d3dx11_43.dll缺失怎么办? DLL文件丢失的多种修复教程

《电脑提示d3dx11_43.dll缺失怎么办?DLL文件丢失的多种修复教程》在使用电脑玩游戏或运行某些图形处理软件时,有时会遇到系统提示“d3dx11_43.dll缺失”的错误,下面我们就来分享超... 在计算机使用过程中,我们可能会遇到一些错误提示,其中之一就是缺失某个dll文件。其中,d3dx11_4

Linux下在线安装启动VNC教程

《Linux下在线安装启动VNC教程》本文指导在CentOS7上在线安装VNC,包含安装、配置密码、启动/停止、清理重启步骤及注意事项,强调需安装VNC桌面以避免黑屏,并解决端口冲突和目录权限问题... 目录描述安装VNC安装 VNC 桌面可能遇到的问题总结描js述linux中的VNC就类似于Window

Go语言编译环境设置教程

《Go语言编译环境设置教程》Go语言支持高并发(goroutine)、自动垃圾回收,编译为跨平台二进制文件,云原生兼容且社区活跃,开发便捷,内置测试与vet工具辅助检测错误,依赖模块化管理,提升开发效... 目录Go语言优势下载 Go  配置编译环境配置 GOPROXYIDE 设置(VS Code)一些基本

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤

Java JDK1.8 安装和环境配置教程详解

《JavaJDK1.8安装和环境配置教程详解》文章简要介绍了JDK1.8的安装流程,包括官网下载对应系统版本、安装时选择非系统盘路径、配置JAVA_HOME、CLASSPATH和Path环境变量,... 目录1.下载JDK2.安装JDK3.配置环境变量4.检验JDK官网下载地址:Java Downloads

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实