目录

  • 1 Summary
  • 2 Conversion to simple Surface Shader
  • 3 Standard Lighting Properties
  • 4 Implement a few Lighting Properties
  • 5 Minor Improvements

原文链接:
Shader Tutorials by Ronja


表面着色器基础。

1 Summary

概要。
除了几乎从头开始编写着色器之外,unity 还允许我们定义一些参数并让 unity 生成执行复杂光计算的代码。 这些着色器称为“表面着色器”。

要了解表面着色器,最好先了解基本的无光照着色器,我在这里有关于它们的教程。

2 Conversion to simple Surface Shader

转换为简单的表面着色器。
使用表面着色器时,我们不必做其他一些必须做的事情,因为 unity 会为我们生成它们。 为了转换为表面着色器,我们完全删除我们的顶点着色器。 删除顶点和片段函数的编译指示定义(如:#pragma vertex vert)。删除顶点着色器到片元着色的输入结构体,删除用于纹理缩放的 MainTex_ST 变量,删除包含 UnityCG 包含文件的内容。 同时删除Pass的开始结束括号,因为Unity 会为我们自动生成Pass。删除完成之后我们的着色器应该是这样的:

Shader "Tutorial/005_surface" {Properties {_Color ("Tint", Color) = (0, 0, 0, 1)_MainTex ("Texture", 2D) = "white" {}}SubShader {Tags{ "RenderType"="Opaque" "Queue"="Geometry"}CGPROGRAMsampler2D _MainTex;fixed4 _Color;fixed4 frag (v2f i) : SV_TARGET {fixed4 col = tex2D(_MainTex, i.uv);col *= _Color;return col;}ENDCG}FallBack "Standard"
}

我们的着色器被我们破坏了,但是我们可以添加一些东西让它作为表面着色器重新工作。
首先,我们添加一个新结构并将其命名为 Input,这将包含我们设置表面颜色所需的所有信息。 对于这个简单的着色器,只需要 UV 坐标。UV坐标的数据类型之前的着色器一样是一个二维浮点数(float2)。需要注意UV坐标的命名很重要,我们将其命名为 uv_MainTex,这样这个UV坐标(uv_MainTex)就已经拥有 MainTex 纹理的平铺和偏移。 如果纹理有不同的名称,我们必须使用 uvTextureName 来获取适合该纹理的坐标。

struct Input {float2 uv_MainTex;
};

接下来,我们将片元函数更改为表面函数。为了使更改显而易见,我们将其重命名为 surf。同时将返回类型(函数名前面的数据类型)替换为void,这样函数就什么都不返回了。
接下来我们将surf函数的输入参数扩展为采用 2 个。第一个参数为我们刚刚定义的输入结构,这样我们可以访问基于每个顶点定义的信息。第二个参数是一个名为 SurfaceOutputStandard 的结构体。顾名思义,我们将使用它来将信息返回到着色器的生成部分。为了让“返回”起作用,我们必须在它前面写上 inout 关键字。第二个结构体是 unity 将用于其照明计算的所有数据。光照计算是基于物理的(我将在本文后面解释参数)。
接下来,我们将从方法中删除 sv_target 属性,因为和其余的一样,它是由unity在其他地方完成的。
为了使表面方法起作用,我们必须进行的最后一次更改是删除 return 语句(这就是我们将返回类型更改为 void 的原因)。相反,我们将输出结构的albedo(反照率)部分设置为我们的颜色值。

void surf (Input i, inout SurfaceOutputStandard o) {fixed4 col = tex2D(_MainTex, i.uv_MainTex);col *= _Color;o.Albedo = col.rgb;
}

使着色器再次工作并使其正确处理光线的最后一步是添加 pragma 语句,声明着色器的类型和使用的方法。 (类似于我们在基本着色器中声明顶点和片段方法的方式)。
语句以#pragma 开头,然后是我们声明的着色器类型(surface),然后是表面方法的名称(surf),最后是我们希望它使用的光照模型(Standard)。
有了所有这些,我们的着色器应该可以再次工作并显示正确的照明。

Shader "Tutorial/005_surface" {Properties {_Color ("Tint", Color) = (0, 0, 0, 1)_MainTex ("Texture", 2D) = "white" {}}SubShader {Tags{ "RenderType"="Opaque" "Queue"="Geometry"}CGPROGRAM#pragma surface surf Standardsampler2D _MainTex;fixed4 _Color;struct Input {float2 uv_MainTex;};void surf (Input i, inout SurfaceOutputStandard o) {fixed4 col = tex2D(_MainTex, i.uv_MainTex);col *= _Color;o.Albedo = col.rgb;}ENDCG}
}

3 Standard Lighting Properties

为了扩展着色器,我们现在可以更多地使用材质属性。 输出结构(SurfaceOutputStandard)中的不同值分别如下:

  • Albedo - (漫反射率)Albedo 是材质的基色。 它将被照着它的灯光的颜色着色,并且在阴影中变暗(正如我们所期望的)。 反照率颜色不会影响镜面光,因此您可以制作仍然有明显光泽的黑色材料。 它存储为 3 维颜色向量(fixed3)。
  • Normal-(法线)这是材质(Material)的法线。 法线在“切线空间”中,这意味着返回它们后,它们将变为相对于世界的法线。 将法线置于切线空间意味着如果我们将 (0,1,0) 写入该变量,则法线实际上不会指向上方,而是远离表面(这是将法线编码为法线贴图的方式,因此我们可以直接从法线贴图Normal Map复制法线信息到这个变量)。 法线存储为 3 维方向向量(vector3)。
  • Emission- (自发光)有了这个,你可以让你的材料发光。 如果你只使用它,你的着色器看起来像我们之前制作的无光着色器一样,但更性能消耗更高。自发光的颜色不受光的影响,因此你可以制作始终明亮的斑点。 如果您使用 HDR 颜色进行渲染(您可以在相机设置中设置),您可以将值大于 1 的值写入发射通道,在使用bloom屏幕后处理效果时,物体看起来会非常亮,同时向外扩散更多。自发光颜色也存储为 3维颜色向量(vector3)。
  • Metallic-(金属度)金属材料与非金属材料看起来是非常不同的。 要使材质看起来更像金属,您可以调高此值。 它将使对象以不同的方式反射,并且Albedo(反照率)值将为反射着色,而不是非金属时的漫反射。 Metallic(金属度值)存储为标量(一维)值,其中 0 表示非金属材料,1 表示完全金属材料。
  • Smoothness-(平滑度)使用此值,我们可以指定材质的平滑程度。 平滑度为 0 的材质看起来很粗糙,光线会反射到各个方向,我们看不到镜面高光或环境反射。 具有 1 平滑度的材料看起来非常抛光。 当你正确设置你的环境时,你可以看到它反映在你的材料上。 它也非常抛光,你也看不到镜面高光,因为镜面高光变得无限小。 当您将平滑度设置为略低于 1 的值时,您开始看到周围灯光的镜面高光。 当您降低平滑度时,高光会变大并变得不那么强烈。 平滑度也存储为标量值。
  • Occlusion-(遮罩)遮罩将从您的材质中去除光线。 有了它,您可以假装光线不会进入模型的裂缝,但您可能几乎不会使用它,除非您追求超写实风格。 遮挡也存储为标量值,但违反直觉的是 1 表示像素具有完全亮度,而 0 表示它处于黑暗中。
  • Alpha-(透明度)Alpha 是材质的透明度。 我们当前的材质是“不透明的”,这意味着不能有任何透明像素,并且 alpha 值不会做任何事情。 在制作透明着色器时,alpha 将定义我们可以在该像素处看到多少材质,1 是完全可见的,而 0 是完全透明的。 Alpha 也存储为标量值。

4 Implement a few Lighting Properties

实现一些灯光属性。
我们现在可以将其中一些功能添加到我们的着色器中。 我现在将使用发射、金属和平滑度值,但您显然也可以实现其他值。
首先,我们添加 2 个标量值,平滑度和金属度。 我们首先将值作为half类型(即表面输出结构中使用的数据类型)添加到我们的全局范围中(在函数或结构之外)。

half _Smoothness;
half _Metallic;

然后我们还将这些值添加到我们的Properties中,以便能够在Inspector(检视面板)中更改它们。 Properties没有half 类型,所以我们告诉它们变量是 float 类型。 这已经可以让变量显示在Inspector中,但我们还没有使用它们。

Properties {_Color ("Tint", Color) = (0, 0, 0, 1)_MainTex ("Texture", 2D) = "white" {}_Smoothness ("Smoothness", float) = 0_Metallic ("Metalness", float) = 0
}

类似于我们如何将颜色变量分配给材质的反照率,我们现在可以将平滑度分配给输出结构的平滑度,将金属度分配给输出结构的金属度。

void surf (Input i, inout SurfaceOutputStandard o) {fixed4 col = tex2D(_MainTex, i.uv_MainTex);col *= _Color;o.Albedo = col.rgb;o.Metallic = _Metallic;o.Smoothness = _Smoothness;
}

这很好用,但是很容易将大于 1 或小于 0 的值分配给这些值并得到非常错误的结果,并且很难看出一个值有多高。 为了解决这个问题,我们可以将值分配为Range属性而不是浮点属性。Range属性允许我们定义最小值和最大值,并且 unity 将在它们之间显示一个滑块。

Properties {_Color ("Tint", Color) = (0, 0, 0, 1)_MainTex ("Texture", 2D) = "white" {}_Smoothness ("Smoothness", Range(0, 1)) = 0_Metallic ("Metalness", Range(0, 1)) = 0
}


接下来我们添加自发光颜色。 首先添加 hlsl 代码中的变量,然后添加Properties。 Properties类型我们像 tint 一样使用 color 类型。 变量我们使用 half3类型 ,因为它是没有 alpha 的 RGB 颜色,并且它的值可以大于 1(输出结构也使用 half3)。 然后我们也像其他属性一样将变量指指定给表面输出中的值。

// ..._Emission ("Emission", Color) = (0,0,0,1)// ...half3 _Emission;// ...o.Emission = _Emission;


除了到处发光的物体看起来有点奇怪之外,我们还只能为我们的材质指定正常颜色,而不是值超过 1 的 HDR 颜色。为了解决这个问题,我们在发射属性前面添加了 hdr 标签。 通过这些更改,我们现在可以将亮度设置为更高的值。 为了更好地利用发射,您可能应该使用纹理,您可以像实现我们用于反照率值的主纹理一样实现其他纹理。

[HDR] _Emission ("Emission", Color) = (0,0,0,1)

5 Minor Improvements

小改进。
最后,我将向您展示两个让您的着色器看起来更好的小东西。 首先,您可以在子着色器下添加回退着色器。 这允许 unity 使用其他着色器的功能,而我们不必自己实现它们。 为此,我们将标准着色器设置为备用着色器,Unity 将从中借用“阴影通道”,使我们的材质在其他对象上投射阴影。 接下来我们可以扩展我们的 pragma 指令。 我们将 fullforwardshadows 参数添加到表面着色器指令中,这样我们就可以获得更好的阴影。 我们还添加了一个指令,将构建目标设置为 3.0,这意味着 unity 将使用更高的精度值,这会有更漂亮的光照。

Shader "Tutorial/005_surface" {Properties {_Color ("Tint", Color) = (0, 0, 0, 1)_MainTex ("Texture", 2D) = "white" {}_Smoothness ("Smoothness", Range(0, 1)) = 0_Metallic ("Metalness", Range(0, 1)) = 0[HDR] _Emission ("Emission", color) = (0,0,0)}SubShader {Tags{ "RenderType"="Opaque" "Queue"="Geometry"}CGPROGRAM#pragma surface surf Standard fullforwardshadows#pragma target 3.0sampler2D _MainTex;fixed4 _Color;half _Smoothness;half _Metallic;half3 _Emission;struct Input {float2 uv_MainTex;};void surf (Input i, inout SurfaceOutputStandard o) {fixed4 col = tex2D(_MainTex, i.uv_MainTex);col *= _Color;o.Albedo = col.rgb;o.Metallic = _Metallic;o.Smoothness = _Smoothness;o.Emission = _Emission;}ENDCG}FallBack "Standard"
}


博主本文博客链接

[译]Unity3D Shader教程(五)Surface Shader Basics相关推荐

  1. Shader教程系列XNA

     Shader教程系列 XNA Shader编程教程1-环境光照 原文地址:http://digierr.spaces.live.com/blog/cns!2B7007E9EC2AE37B!424 ...

  2. 【Unity3D Shader编程】之六 暗黑城堡篇: 表面着色器(Surface Shader)的写法(一)

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/42215079 作者:毛星云(浅墨) ...

  3. 【Unity3D Shader编程】之六 暗黑城堡篇 表面着色器 Surface Shader 的写法 一

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 本系列文章由@浅墨 ...

  4. Unity3D Shader编程】之六 暗黑城堡篇: 表面着色器(Surface Shader)的写法(一)

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/42215079 作者:毛星云(浅墨) ...

  5. 【浅墨Unity3D Shader编程】之六 暗黑城堡篇: 表面着色器(Surface Shader)的写法(一)

    本文主要讲解了Unity中SurfaceShader的具体写法,以及几个常用的CG函数的用法. 在这里先说明一下,表面着色器将分为两次讲解,本文介绍表面着色器的基本概念和一些写法,用内置的兰伯特光照模 ...

  6. Unity3d shader 教程一 准备

    Cg编程 游戏引擎中的Cg编程对于OpenGL或Direct3D应用程序,Unity比Cg编程要容易得多.网格和图像(即纹理)的导入由图形用户界面支持; mipmap和法线贴图可以自动计算; 最常见的 ...

  7. Catlike Coding Unity教程系列 中文翻译 Basics篇(五)Compute Shaders

    计算着色器 渲染一百万个立方体 原文地址:https://catlikecoding.com/unity/tutorials/basics/compute-shaders/ 在计算缓冲区中存储位置. ...

  8. 表面着色器(Surface Shader)的写法(一)

    一.表面着色器的标准输出结构(Surface Output) 要书写Surface Shader,了解表面着色器的标准输出结构必不可少.此为表面着色器书写的第一个要素. 而定义一个"表面函数 ...

  9. 【Unity3D Shader编程】之十三 单色透明Shader 标准镜面高光Shader

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

最新文章

  1. 终极方案!解决正确设置LaunchImage后仍然不显示的问题
  2. 无法去掉自增标识_为什么 MySQL 的自增主键不单调也不连续
  3. Java Review - 并发编程_ScheduledThreadPoolExecutor原理源码剖析
  4. boost::iterator_range相关的测试程序
  5. 随机地址生成器_随机连接神经网络性能超过人工设计!何恺明等人发布新研究...
  6. 推广的euclid_欧几里德(Euclid)贴近度评价法在人类进化上的应用
  7. 信息学奥赛一本通(2060:【例1.1】计算机输出)
  8. 【算法】数组与矩阵问题——找到无序数组中最小的k个数
  9. 编写高效优雅Java程序
  10. django uWSGI nginx搭建一个web服务器 确定可用
  11. 分享15款免费好用的中文字体
  12. 上海市计算机应用基础答案,计算机应用基础10统考(附答案)
  13. 脑肿瘤的影像组学:图像评估、定量特征描述和机器学习方法
  14. mysql格式化到年月日_格式化MySQL日期并转换为年-月-日
  15. 在Excel中插入行并复制单元格格式
  16. 移动端网页站点调用拨打电话发送短信等功能
  17. 第六课:图层蒙版和快速蒙版
  18. [小黄书小程序]微信授权登录
  19. 干支记年法 在我国古代和近代,一直采用干支法纪年。它采用10天干和12地支配合,一个循环周期为60年。
  20. SAP FICO 内部往来对账功能开发说明书(包括测试样例、程序代码仅作参考,不保证一定可以运行)

热门文章

  1. oracle ebcdic 转换,sql - oracle ebcdic sqlldr问题 - 堆栈内存溢出
  2. 视频图像色彩增强的主要方法与落地实践
  3. GAN“家族”又添新成员——EditGAN,不但能自己修图,还修得比你我都好
  4. mysql中的declare_sql中declare是什么意思
  5. Android逆向案例:干掉梆梆加固免费版的反调试检测
  6. mx250是什么_MX250和150有什么区别 MX250和MX150区别对比介绍
  7. webp文件怎么打开?webp压缩工具推荐
  8. JavaBean的书写规范
  9. html模仿 商城 静态页面,HTML+CSS简单实现凡客商城静态网页
  10. intel固态硬盘误删文件该如何进行恢复