Shader编程学习笔记(四)—— Unity Shader的组织形式(ShaderLab)

2023-10-21 22:18

本文主要是介绍Shader编程学习笔记(四)—— Unity Shader的组织形式(ShaderLab),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文:http://www.cnblogs.com/maple-share/p/5418384.html

Shader编程学习笔记(四)—— Unity Shader的组织形式(ShaderLab)

Unity Shader的组织形式

 

Unity Shader的形态

  Unity官方手册上讲Unity Shader有三种不同的编写方案,这三种编写方案分别是surface shaders、vertex and fragment shaders和fixed function shaders。 从前面几篇笔记中可以了解到,可编程图形管线中能够编写shader的主要是两个部分:vertex shader和fragment shader,但Unity还有surface shaders和fixed function shaders。

  对于fixed function shaders,从表面意思来理解就是固定管线着色器,在可编程管线硬件出现之前,很多的光照流水计算都会放在硬件里进行处理,我们把这样的固定管线功能也看作是对应于固定管线硬件的操作,这种shader的功能是很保守的,比如说启用简单的光照,进行简单的纹理采样等等,对于现在绝大多数硬件都能得到很好的支持。

  surface shaders是Unity中被推荐和鼓励使用的着色器,当你在Unity(Unity5之前)中创建一个shader时,默认的代码就是使用surface shaders。那么为什么会有surface shaders这样的着色器呢?它和vertex and fragment shaders又有什么关系呢?我们可以这样理解,可编程图形管线能够识别就是两种shader程序:vertex shader和fragment shader,至于surface shader是在vertex shader和fragment shader上面的一种包装,Unity引擎最终会把surface shaders代码编译成能够被硬件识别和调用的vertex and fragment shaders。

  Unity官方推荐在学习shader时先去阅读ShaderLab syntax的基本概念,然后再去阅读surface shaders或者vertex and fragment shaders的相关内容。fixed function shaders只能够使用ShaderLab语法进行编写,而surface shaders和vertex and fragment shaders不限于ShderLab语法,是可以使用Cg/HLSL,甚至可用GLSL去编写,它是镶嵌在ShaderLab中的一种代码片段。

 

ShaderLab基本结构

  ShaderLab是Unity定制的专门编写Shader的一种方案。使用ShaderLab可以把上文提到的三种shader用同一种格式来编写,这样就不会导致编写不同的shader需要不同的语法。前文中对shader、材质和贴图等它们之间的关系做了一个形象的比喻:材质是最终要使用的对象,shader是关于如何加工和处理的一种方案,是一种程序片段,至于贴图、颜色等它们是属于这个加工方案中的材料。那么当要建立一个Shader,要把它用于在材质上去使用的时候,既需要有算法,也需要添加一些原材料,首先来了解一下ShaderLab的主要结构,以下是ShaderLab的基本结构:

shader "name"{[Properties]SubShaders[FallBack]
}

  Properties的作用是能够允许在Unity材质(material)检视面板中为材质去定义一些需要的参数,如颜色、贴图、参数等,这些都属于原材料,被shader程序使用。

  SubShader的作用就是专门为GPU渲染所编写的shader程序片段,在一个shader当中有并且至少需要一个SubShader,也可以有多个SubShader,但是在执行时只能选择其中的一个SubShader。那为什么允许多个SubShader同时存在呢?原因是shader中的某一种算法或者某一种指令可能不支持当前的硬件,比如说一个shader程序有多个SubShader,当这个shader程序被执行的时候,首先会去检测当前硬件能不能完好地支持第一个SubShader,如果第一个SubShader可以被当前硬件良好支持,那么就会使用当前SubShader,如果不能,那么就去检测下一个SubShader。在编写shader时,假如不能确定当前的SubShader在某些老旧的硬件上得到良好的支持,可以编写第二个SubShader,用来适配这些老旧的、稍差的图形硬件,当然也可以继续编写第三个、第四个、第五个等等,编写的SubShader功能要依次简化、运算指令依次简单,用来满足更多的硬件支持。如果编写的SubShader都不能支持当前的硬件时,就需要用到ShaderLab的“FallBack”功能了。

  FallBack的意思就是回滚。如果当前硬件无法支持所有的SubShader时,Unity会将当前的着色回滚,回滚到FallBack所指定的shader,因此FallBack指令后跟随的一般都是系统自带比较简单的,能够被绝大多数硬件执行的shader。以下列举了几个Unity官方的内建的shader,更加具体的信息可以查阅Unity官方手册。

 

Unity Build-In Shader

  • Unlit. This is just a texture,not affected by any lighting.(不发光。这只是一个纹理,不被任何光照影响

  这是Unity中最为简单的shader,执行效率非常快,该shader经常被用于UI系统。

  • VertexLit.(顶点光照

  该shader拥有在顶点上渲染光照的能力。

  • Diffuse.(漫反射

  漫反射也是一种光照形态,不过它不仅仅在顶点上进行光照计算,在片段程序中也要进行光照计算。

  • Normal Mapped.This is a bit more expensive than Diffuse:it adds more texture(normal map),and a couple of shader instructions.(法线贴图,比漫反射更昂贵:增加了一个或更多纹理(法线贴图)和几个着色器结构

  法线贴图技术是一种比较传统的图形渲染技术,通过一张贴图进行采样计算,但这张贴图不是一张普通的贴图,而是一张存储法向量的贴图,把这张图采样出来的数据当做法向量,然后再进行光照计算,主要目的就是当几个模型面片顶点数量不多,构成的面片细节不多的时候,为了表达丰富的细节,可以使用法线贴图去弥补这样的细节,以假乱真,因此法线贴图shader的使用率很高。

  • Specular.This adds specular highlight calculation.(高光。增加了特殊的高光计算

  Specular指的是镜面高光反射,主要用于模拟光滑物体,比如金属、玻璃等。

  • Normal Mapped Specular.Again,this is a bit more expensive than Specular.(高光法线贴图。比高光更昂贵一点

  该shader结合了以上两点,既有法线贴图,又有高光显示。

  • Parallax Normal mapped.This adds parallax normal-mapping calculation.(视差法线贴图。增加了视差法线贴图计算
  • Parallax Normal Mapped Specular.This adds both poarallax normal-mapping and specluar highlight calculation.(视差高光法线贴图。增加了视差法线贴图和镜面高光计算

  视差即视觉的差异,比较形象的解释就是当人的左眼和右眼分别去看同一个物体时,两只眼睛看到的结果是不一样的,正是由于人的左眼和右眼有三厘米左右的距离,人看到的这个世界是三维的、立体的。
  那么视差法线贴图的作用是什么呢?原因就是当法线贴图进行贴图映射的时候,是为了更好地表现物体的细节,法线数据存储在纹理当中,但是该纹理是不可变的,当物体渲染出来后,会得到一个比较好的结果,表现了物体凹凸的细节,所以法线贴图在有些教科书当中也叫作凹凸贴图,但是当把有法线贴图的物体进行旋转,照理说有些地方由于视角的偏差是看不到它的凹凸的形态或者说看到凹凸感觉会更强烈,由于法线贴图是一个固定的贴图,就会达不到这样的效果,而视差法线贴图的作用就弥补这样的缺陷。

这篇关于Shader编程学习笔记(四)—— Unity Shader的组织形式(ShaderLab)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言