2018-08-30

转载自 VR设计云课堂 Unity Shader入门精要》随书彩色插图

《Unity Shader入门精要》随书彩色插图(上)

 

VR设计云课堂 关注

2017.06.15 12:08* 字数 252 阅读 1002评论 1喜欢 18

Unity Shader入门精要》随书彩色插图

说明:本页面是书籍《Unity Shader入门精要》的随书彩图集锦,包含了书中所有的插图,使用时可通过图片编号进行搜索。 作者:冯乐乐 邮箱:[email protected]

前言

2018-08-30_第1张图片

shadertoy.png-286.5kB

第2章 渲染流水线

2018-08-30_第2张图片

流水线.png-83.4kB

图2.1 真实生活中的流水线

2018-08-30_第3张图片

概念流水线.png-16.9kB

图2.2 渲染流水线中的三个概念阶段

2018-08-30_第4张图片

CopyDataToGPU.png-86.5kB

图2.3 渲染所需的数据(两张纹理以及3个网格)从硬盘最终加载到显存中。在渲染时,GPU可以快速访问这些数据

2018-08-30_第5张图片

SetRenderState.png-157.1kB

图2.4 在同一状态下渲染三个网格。由于没有更改渲染状态,因此三个网格的外观看起来像是同一种材质的物体。

2018-08-30_第6张图片

DrawCall.png-59.1kB

图2.5 CPU通过调用Draw Call来告诉GPU开始进行一个渲染过程。一个Draw Call会指向本次调用需要渲染的图元列表

2018-08-30_第7张图片

GPU流水线.png-82.2kB

图2.6 GPU的渲染流水线实现。颜色表示了不同阶段的可配置性或可编程性:绿色表示该流水线阶段是完全可编程控制的,黄色表示该流水线阶段可以配置但不是可编程的,蓝色表示该流水线阶段是由GPU固定实现的,开发者没有任何控制权。实线表示该shader必须由开发者编程实现,虚线表示该Shader是可选的

2018-08-30_第8张图片

VertexShaderProcess.png-43kB

图2.7 GPU在每个输入的网格顶点上都会调用顶点着色器。顶点着色器必须进行顶点的坐标变换,需要时还可以计算和输出顶点的颜色。例如,我们可能需要进行逐顶点的光照

2018-08-30_第9张图片

Vertex Shader.png-34.9kB

图2.8 顶点着色器会将模型顶点的位置变换到齐次裁剪坐标空间下,进行输出后再由硬件做透视除法得到NDC下的坐标

2018-08-30_第10张图片

Clipping.png-25.5kB

图2.9 只有在单位立方体的图元才需要被继续处理。因此,完全在单位立方体外部的图元(红色三角形)被舍弃,完全在单位立方体内部的图元(绿色三角形)将被保留。和单位立方体相交的图元(黄色三角形)会被裁剪,新的顶点会被生成,原来在外部的顶点会被舍弃

2018-08-30_第11张图片

ScreenMapping.png-22.6kB

图2.10 屏幕映射将x、y坐标从(-1, 1)范围转换到屏幕坐标系中

2018-08-30_第12张图片

Screen Mapping_OpenGL_DirectX.png-26.9kB

图2.11 OpenGL和DirectX的屏幕坐标系差异。对于一张512*512大小的图像,在OpenGL中其(0, 0)点在左下角,而在DirectX中其(0, 0)点在左上角

2018-08-30_第13张图片

TriangleSetupAndTraversal.png-80kB

图2.12 三角形遍历的过程。根据几何阶段输出的顶点信息,最终得到该三角网格覆盖的像素位置。对应像素会生成一个片元,而片元中的状态是对三个顶点的信息进行插值得到的。例如,对图2.12中三个顶点的深度进行插值得到其重心位置对应的片元的深度值为-10.0

2018-08-30_第14张图片

FragmentShader.png-42.4kB

图2.13 根据上一步插值后的片元信息,片元着色器计算该片元的输出颜色

Per-fragment Operations.png-23.1kB

图2.14 逐片元操作阶段所做的操作。只有通过了所有的测试后,新生成的片元才能和颜色缓冲区中已经存在的像素颜色进行混合,最后再写入颜色缓冲区中

2018-08-30_第15张图片

Stencil Test_Depth Test.png-93.5kB

图2.15 模板测试和深度测试的简化流程图。

2018-08-30_第16张图片

Blending.png-67.6kB

图2.16 混合操作的简化流程图

2018-08-30_第17张图片

why_early_depth_test.png-18.7kB

图2.17 图示场景中包含了两个对象:球和长方体,绘制顺序是先绘制球(在屏幕上显示为圆),再绘制长方体(在屏幕上显示为长方形)。如果深度测试在片元着色器之后执行,那么在渲染长方体时,虽然它的大部分区域都被遮挡在球的后面,即它所覆盖的绝大部分片元根本无法通过深度测试,但是我们仍然需要对这些片元执行片元着色器,造成了很大的性能浪费

2018-08-30_第18张图片

OpenGL和DirectX.png-56.1kB

图2.18 CPU、OpenGL/DirectX、显卡驱动和GPU之间的关系

2018-08-30_第19张图片

CommandBuffer.png-49.9kB

图2.19 命令缓冲区。CPU通过图像编程接口向命令缓冲区中添加命令,而GPU从中读取命令并执行。黄色方框内的命令就是Draw Call,而红色方框内的命令用于改变渲染状态。我们使用红色方框来表示改变渲染状态的命令,是因为这些命令往往更加耗时

2018-08-30_第20张图片

SmallCommand.png-107.7kB

图2.20 命令缓冲区中的虚线方框表示GPU已经完成的命令。此时,命令缓冲区中没有可以执行的命令了,GPU处于空闲状态,而CPU还没有准备好下一个渲染命令。

2018-08-30_第21张图片

Batching.png-70.3kB

图2.21 利用批处理,CPU在RAM把多个网格合并成一个更大的网格,再发送给GPU,然后在一个Draw Call中渲染它们。但要注意的是,使用批处理合并的网格将会使用同一种渲染状态。也就是说,如果网格之间需要使用不同的渲染状态,那么就无法使用批处理技术

第3章 Unity Shader基础

2018-08-30_第22张图片

material_shader.png-125.8kB

图3.1 Unity Shader和材质。首先创建需要的Unity Shader和材质,然后把Unity Shader赋给材质,并在材质面板上调整属性(如使用的纹理、漫反射系数等)。最后,将材质赋给相应的模型来查看最终的渲染效果

2018-08-30_第23张图片

mesh_renderer.png-41kB

图3.2 将材质直接拖曳到模型的Mesh Renderer组件中

2018-08-30_第24张图片

material_inspector.png-119.4kB

图3.3 材质提供了一种可视化的方式来调整着色器中使用的参数

2018-08-30_第25张图片

shader_import_settings.png-38kB

图3.4 Unity Shader的导入设置面板

2018-08-30_第26张图片

shader_compile_code.png-35.9kB

图3.5 Gompile and show code下拉列表

2018-08-30_第27张图片

shaderlab_abstract.png-63.4kB

图3.6 Unity Shader为控制渲染过程提供了一层抽象。如果没有使用Unity Shader(左图),开发者需要和很多文件和设置打交道,才能让画面呈现出想要的效果;而在Unity Shader的帮助下(右图),开发者只需要使用ShaderLab来编写Unity Shader文件就可以完成所有的工作

2018-08-30_第28张图片

shader_name.png-55.5kB

图3.7 在Unity Shader的名称定义中利用斜杠来组织在材质面板中的位置

2018-08-30_第29张图片

shaderlab_properties.png-33.2kB

图3.8 不同属性类型在材质面板中的显示结果

2018-08-30_第30张图片

shader_compile_code.png-35.9kB

图3.9 在Unity Shader的导入设置面板中可以通过Compile and show code按钮来查看Unity对CG片段编译后的代码。通过单击Compile and show code按钮右端的倒三角可以打开下拉菜单,在这个下拉菜单中可以选择编译的平台种类,如只为当前的显卡设备编译特定的汇编代码,或为所有的平台编译汇编代码,我们也可以自定义选择编译到哪些平台上

第4章 学习Shader所需的数学基础

2018-08-30_第31张图片

little_cow.png-293.5kB

图4.1 我们的农场游戏。我们的主角妞妞是一头长得最壮、好奇心很强的奶牛

2018-08-30_第32张图片

cartersian_fly.png-28kB

图4.2 传说,笛卡尔坐标系来源于笛卡尔对天花板上一只苍蝇的运动轨迹的观察。笛卡尔发现,可以使用苍蝇距不同墙面的距离来描述它的当前位置

2018-08-30_第33张图片

cow_camera.png-180.1kB

图4.3 一个二维笛卡尔坐标系

2018-08-30_第34张图片

2d_cartesian_opengl_directx.png-33.1kB

图4.4 在屏幕映射时,OpenGL和DirectX使用了不同方向的二维笛卡尔坐标系

2018-08-30_第35张图片

cow_cartesian.png-211.8kB

图4.5 笛卡尔坐标系可以让妞妞精确表述自己的位置

2018-08-30_第36张图片

3d_cartesian.png-22.7kB

图4.6 一个三维笛卡尔坐标系

2018-08-30_第37张图片

space_handness.png-75.6kB

图4.7 左手坐标系

2018-08-30_第38张图片

right_hand.png-40kB

2018-08-30_第39张图片

left_right_hand_rule.png-75.3kB

图4.9 用左手法则和右手法则来判断旋转正方向

2018-08-30_第40张图片

cow_left_right.png-254.3kB

图4.10 为了移动到新的位置,妞妞需要首先向某个方向平移1个单位,再向另一个方向平移4个单位,最后再向一个方向旋转60°

2018-08-30_第41张图片

cow_left_right_hand.png-295.8kB

图4.11 左图和右图分别表示了在左手坐标系和右手坐标系中描述妞妞这次运动的结果,得到的数学描述是不同的

2018-08-30_第42张图片

unity_cartesian.png-173.2kB

图4.12 在模型空间和世界空间中,Unity使用的是左手坐标系。图中,球的坐标轴显示了它在模型空间中的3个坐标轴(红色为x轴,绿色是y轴,蓝色是z轴)

2018-08-30_第43张图片

unity_camera_cartesian.png-25.1kB

图4.13 在Unity中,观察空间使用的是右手坐标系,摄像机的前向是z轴的负方向,z轴越小,物体的深度越大,离摄像机越远

2018-08-30_第44张图片

exercise_3.png-130.8kB

图4.14 摄像机的位置是(0, 1, -10),球体的位置是(0, 1, 0)

2018-08-30_第45张图片

vector.png-8.9kB

图4.15 一个二维向量以及它的头和尾

2018-08-30_第46张图片

point_vector.png-16.1kB

图4.16 点和矢量之间的关系

2018-08-30_第47张图片

vector_scalar.png-53.9kB

图4.17 二维矢量和一些标量的乘法和除法

2018-08-30_第48张图片

vector_add_sub.png-52.8kB

图4.18 二维矢量的加法和减法

2018-08-30_第49张图片

vector_displacement.png-22.5kB

图4.19 使用矢量减法来计算从点a到点b的位移

2018-08-30_第50张图片

vector_magnitude.png-8.2kB

图4.20 矢量的模

2018-08-30_第51张图片

unit_vector.png-30.7kB

图4.21 二维空间的单位矢量都会落在单位圆上

2018-08-30_第52张图片

projection.png-17.7kB

图4.22 矢量b在单位矢量a方向上的投影

2018-08-30_第53张图片

dot_sign.png-22.9kB

图4.23 点积的符号

2018-08-30_第54张图片

dot_cos.png-14.1kB

图4.24 两个单位矢量进行点积

2018-08-30_第55张图片

vector_cross_diagram.png-32.1kB

图4.25 三维矢量叉积的计算规律。不同颜色的线表示了计算结果矢量中对应颜色的分量的计算路径。以红色为例,即结果矢量的第一个分量,它是从第一个矢量的y分量出发乘以第二个矢量的z分量,再减去第一个矢量的z分量和第二矢量的y分量的乘积

2018-08-30_第56张图片

vector_cross_length.png-13kB

图4.26 使用矢量a和矢量b构建一个平行四边形

2018-08-30_第57张图片

vector_cross.png-27.2kB

图4.27 分别使用左手坐标系和右手坐标系得到的叉积结果

2018-08-30_第58张图片

vector_cross_right_hand.png-46.6kB

图4.28 使用右手法则判断右手坐标系中a×b的方向

2018-08-30_第59张图片

exercise_cross.png-26.1kB

图4.29 三角形的三个顶点位于xy平面上,人眼位于z轴负方向,向z轴正方向观察

2018-08-30_第60张图片

matrix_mul.png-25kB

图4.30 计算c23的过程

2018-08-30_第61张图片

niuniu.png-273.2kB

图4.31 场景中的妞妞(左图)和屏幕上的妞妞(右图)。妞妞想知道,自己的鼻子是如何被画到屏幕上的

2018-08-30_第62张图片

object_space.png-84.5kB

图4.32 在我们的农场游戏中,每个奶牛都有自己的模型坐标系。在模型坐标系中妞妞鼻子的位置是(0, 2, 4, 1)

2018-08-30_第63张图片

unity_transform.png-151.9kB

图4.33 Unity的Transform组件可以调节模型的位置.如果Transform有父节点,如图中的“Mesh”,那么Position将是在其父节点(这里是“Cow”)的模型空间中的位置;如果没有父节点,Position就是在世界空间中的位置

2018-08-30_第64张图片

world_space.png-378.7kB

图4.34 农场游戏中的世界空间。世界空间的原点被放置在农场的中心。左下角显示了妞妞在世界空间中所做的变换。我们想要把妞妞的鼻子从模型空间变换到世界空间中

2018-08-30_第65张图片

camera_space.png-346.2kB

图4.35 农场游戏中摄像机的观察空间。观察空间的原点位于摄像机处。注意在观察空间中,摄像机的前向是z轴的负方向(图中只画出了z轴正方向),这是因为Unity在观察空间中使用了右手坐标系。左下角显示了摄像机在世界空间中所做的变换。我们想要把妞妞的鼻子从世界空间变换到观察空间中

2018-08-30_第66张图片

camera_projection.png-299.3kB

图4.36 透视投影(左图)和正交投影(右图)。左下角分别显示了当前摄像机的投影模式和相关属性

2018-08-30_第67张图片

camera_frustum.png-301.2kB

图4.37 视锥体和裁剪平面。左图显示了透视投影的视锥体,右图显示了正交投影的视锥体

2018-08-30_第68张图片

projection_frustum.png-67.3kB

图4.38 透视摄像机的参数对透视投影视锥体的影响

2018-08-30_第69张图片

projection_matrix0.png-135.1kB

图4.39 在透视投影中,投影矩阵对顶点进行了缩放。图3.38中标注了4个关键点经过投影矩阵变换后的结果。从这些结果可以看出x、y、z和w分量的范围发生的变化

2018-08-30_第70张图片

orthographic_frustum.png-33.5kB

图4.40 正交摄像机的参数对正交投影视锥体的影响

2018-08-30_第71张图片

orthographic_matrix0.png-129.6kB

图4.41 在正交投影中,投影矩阵对顶点进行了缩放。图中标注了4个关键点经过投影矩阵变换后的结果。从这些结果可以看出x、y、z和w分量范围发生的变化

2018-08-30_第72张图片

cow_camera.png-180.1kB

图4.42 农场游戏使用的摄像机参数和游戏画面的横纵比

2018-08-30_第73张图片

projection_matrix1.png-131kB

图4.43 经过齐次除法后,透视投影的裁剪空间会变换到一个立方体

2018-08-30_第74张图片

orthographic_matrix1.png-105.6kB

图4.44 经过齐次除法后,正交投影的裁剪空间会变换到一个立方体

2018-08-30_第75张图片

vertex_conversion.png-100.9kB

图4.45 渲染流水线中顶点的空间变换过程

2018-08-30_第76张图片

space_handness.png-75.6kB

图4.46 Unity中各个坐标空间的旋向性

2018-08-30_第77张图片

normal_tangent.png-167.3kB

图4.47 顶点的切线和法线。切线和法线互相垂直

2018-08-30_第78张图片

transform_normal.png-40.6kB

图4.48 进行非统一缩放时,如果使用和变换顶点相同的变换矩阵来变换法线,就会得到错误的结果,即变换后的法线方向与平面不再垂直

2018-08-30_第79张图片

screen_coord.png-9kB

图4.49 由片元的像素位置得到的图像

2018-08-30_第80张图片

difference_between_left_right.png-54.6kB

图4.50 图中两个坐标系的x轴和y轴是重合的,区别仅在于z轴的方向。左手坐标系的(0, 0, 1)点和右手坐标系中的(0, 0, 1)点是不同的,但它们旋转后的点却对应到了同一点

2018-08-30_第81张图片

difference_between_left_right_2.png-59.4kB

图4.51 绝对空间中的同一点,在左手和右手坐标系中进行同样角度的旋转,其旋转方向是不一样的。在左手坐标系中将按顺时针方向旋转,在右手坐标系中将按逆时针方向旋转

2018-08-30_第82张图片

exercise_cross2.png-34.4kB

图4.52 在左手坐标系中,如果叉积结果为负,那么3点的顺序是顺时针方向

第5章 开始Unity Shader学习之旅

2018-08-30_第83张图片

new_scene.png-74.3kB

图5.1 在Unity 5中新建一个场景得到的效果

need-to-insert-img

simple_shader.png-25.4kB

图5.2 用一个最简单的顶点/片元着色器得到一个白色的球

need-to-insert-img

cginclude.png-27kB

图5.3 Unity的内置着色器

need-to-insert-img

false_color.png-192.9kB

图5.4 用假彩色对Unity Shader进行调试

need-to-insert-img

color_picker.png-53.8kB

图5.5 使用颜色拾取器来查看调试信息

need-to-insert-img

frame_debugger.png-218.7kB

图5.6 帧调试器

need-to-insert-img

frame_debugger_0.png-164.5kB

图5.7 单击Knot的深度图渲染事件,在Game视图会显示该事件的效果,在Hierarchy视图中会高亮显示Knot对象,在帧调试器的右侧窗口会显示出该事件的细节

need-to-insert-img

2d_cartesian_opengl_directx.png-33.1kB

图5.8 OpenGL和DirectX使用了不同的屏幕空间坐标

第6章 Unity中的基础光照

need-to-insert-img

irradiance.png-60.3kB

图6.1 在左图中,光是垂直照射到物体表面,因此光线之间的垂直距离保持不变;而在右图中,光是斜着照射到物体表面,在物体表面光线之间的距离是d/cosθ,因此单位面积上接收到的光线数目要少于左图

need-to-insert-img

scattering.png-37.1kB

图6.2 散射时,光线会发生折射和反射现象。对于不透明物体,折射的光线会在物体内部继续传播,最终有一部分光线会重新从物体表面被发射出去

need-to-insert-img

specular.png-31.2kB

图6.3 使用Phong模型计算高光反射

need-to-insert-img

Blinn.png-32.1kB

图6.4 Blinn模型

need-to-insert-img

ambient.png-35.3kB

图6.5 在Unity的Window -> Lighting面板中,我们可以通过Ambient Source/Ambient Color/Ambient Intensity来控制场景中的环境光的颜色和强度

need-to-insert-img

diffuse_vertex_level.png-40.4kB

图6.6 逐顶点的漫反射光照效果

2018-08-30_第84张图片

diffuse_pixel_level.png-40.1kB

图6.7 逐像素的漫反射光照效果

2018-08-30_第85张图片

diffuse_compare_all.png-86.9kB

图6.8 逐顶点漫反射光照、逐像素漫反射光照、半兰伯特光照的对比效果

2018-08-30_第86张图片

reflect.png-9.2kB

图6.9 CG的reflect函数

2018-08-30_第87张图片

specular_vertex_level.png-41.5kB

图6.10 逐顶点的高光反射光照效果

2018-08-30_第88张图片

specular_pixel_level.png-40.8kB

图6.11 逐像素的高光反射光照效果

2018-08-30_第89张图片

specular_compare_all.png-82.5kB

图6.12 逐顶点的高光反射光照、逐像素的高光反射光照(Phong光照模型)和Blinn-Phong高光反射光照的对比结果

第7章 基础纹理

2018-08-30_第90张图片

texture_coordinate.png-349.3kB

图7.1 Unity中的纹理坐标

need-to-insert-img

single_texture.png-71.3kB

图7.2 使用单张纹理

need-to-insert-img

texture_tiling_offset.png-16.9kB

图7.3 调节纹理的平铺(缩放)和偏移(平移)属性

need-to-insert-img

texture_properties.png-29kB

图7.4 纹理的属性

2018-08-30_第91张图片

wrap_mode.png-68.9kB

图7.5 Wrap Mode决定了当纹理坐标超过[0, 1]范围后将会如何被平铺

2018-08-30_第92张图片

texture_offset.png-68.4kB

图7.6 偏移(Offset)属性决定了纹理坐标的偏移量

2018-08-30_第93张图片

magnification.png-256.2kB

图7.7 在放大纹理时,分别使用三种Filter Mode得到的结果

2018-08-30_第94张图片

mipmap.png-35.9kB

图7.8 在Advanced模式下可以设置多级渐远纹理的相关属性

2018-08-30_第95张图片

minification.png-271.9kB

图7.9 从上到下: Point滤波 + 多级渐远纹理技术,Bilinear滤波 + 多级渐远纹理技术,Trilinear滤波 + 多级渐远纹理技术

2018-08-30_第96张图片

texture_quality.png-31.7kB

图7.10 选择纹理的最大尺寸和纹理模式

2018-08-30_第97张图片

heightmap.png-134.5kB

图7.11 高度图

2018-08-30_第98张图片

tangent_space.png-165.3kB

图7.12 模型顶点的切线空间。其中,原点对应了顶点坐标,x轴是切线方向(t),y轴是副切线方向(b),z轴是法线方向(n)

2018-08-30_第99张图片

object_tangent_space_normal.png-320.3kB

图7.13 左图:模型空间下的法线纹理。右图:切线空间下的法线纹理

2018-08-30_第100张图片

normal_map.png-92.2kB

图7.14 使用法线纹理

2018-08-30_第101张图片

bump_scale.png-140.5kB

图7.15 使用Bump Scale属性来调整模型的凹凸程度

2018-08-30_第102张图片

texture_type_normal.png-29.8kB

图7.16 当使用UnpackNormal函数计算法线纹理中的法线方向时,需要把纹理类型标识为Normal map

2018-08-30_第103张图片

texture_type_heightmap.png-293.4kB

图7.17 当勾选了Create from Grayscale后,Unity会根据高度图来生成一张切线空间下的法线纹理

2018-08-30_第104张图片

ramp_texture.png-119.2kB

图7.18 使用不同的渐变纹理控制漫反射光照,左下角给出了每张图使用的渐变纹理

2018-08-30_第105张图片

ramp_texture_wrap_mode.png-114.2kB

图7.19 Wrap Mode分别为Repeat和Clamp模式的效果对比

2018-08-30_第106张图片

mask_specular.png-142.4kB

图7.20 使用高光遮罩纹理。从左到右:只包含漫反射,未使用遮罩的高光反射,使用遮罩的高光反射

2018-08-30_第107张图片

mask.png-671.4kB

图7.21 本节使用的高光遮罩纹理

第8章 透明效果

need-to-insert-img

render_order_0.png-10.7kB

图8.1 场景中有两个物体,其中A(黄色)是半透明物体,B(紫色)是不透明物体

need-to-insert-img

render_order_1.png-10.5kB

图8.2 场景中有两个物体,其中A和B都是半透明物体

2018-08-30_第108张图片

render_order_3.png-15.3kB

图8.3 循环重叠的半透明物体总是无法得到正确的半透明效果

2018-08-30_第109张图片

render_order_2.png-30.4kB

图8.4 使用哪个深度对物体进行排序。红色点分别标明了网格上距离摄像机最近的点、最远的点以及网格中点

2018-08-30_第110张图片

transparent_texture.png-71.9kB

图8.5 一张透明纹理,其中每个方格的透明度都不同

2018-08-30_第111张图片

alpha_test.png-55.9kB

图8.6 透明度测试

2018-08-30_第112张图片

alpha_test_0.png-166.4kB

图8.7 随着Alpha cutoff参数的增大,更多的像素由于不满足透明度测试条件而被剔除

2018-08-30_第113张图片

alpha_blend.png-55.1kB

图8.8 透明度混合

2018-08-30_第114张图片

alpha_blend_0.png-138.7kB

图8.9 随着Alpha Scale参数的增大,模型变得越来越透明

2018-08-30_第115张图片

transparent_order_wrong.png-94.7kB

图8.10 当模型网格之间有互相交叉的结构时,往往会得到错误的半透明效果

2018-08-30_第116张图片

alpha_blend_zwrite.png-87.9kB

图8.11 开启了深度写入的半透明效果

2018-08-30_第117张图片

blend.png-74.1kB

图8.12 不同混合状态设置得到的效果

2018-08-30_第118张图片

alpha_test_both_sided.png-60.7kB

图8.13 双面渲染的透明度测试的物体

2018-08-30_第119张图片

alpha_blend_both_sided.png-66.2kB

图8.14 双面渲染的透明度混合的物体

第9章 更复杂的光照

2018-08-30_第120张图片

rendering_path_setting.png-30kB

图9.1 设置Unity项目的渲染路径

2018-08-30_第121张图片

rendering_path_camera.png-37.8kB

图9.2 摄像机组件的Rendering Path中的设置可以覆盖Project Settings中的设置

2018-08-30_第122张图片

light_type_mode.png-30.6kB

图9.3 设置光源的类型和渲染模式

2018-08-30_第123张图片

forward_rendering.png-175.5kB

图9.4 前向渲染的两种Pass

2018-08-30_第124张图片

directional_ligth.png-51.6kB

图9.5 平行光

2018-08-30_第125张图片

point_ligtht.png-89.4kB

图9.6 点光源

2018-08-30_第126张图片

enable_light.png-63.6kB

图9.7 开启Scene视图中的光照

2018-08-30_第127张图片

spot_light.png-74.5kB

图9.8 聚光灯

2018-08-30_第128张图片

two_lights.png-79.4kB

图9.9 使用一个平行光和一个点光源共同照亮物体。右图显示了胶囊体、平行光和点光源在场景中的相对位置

2018-08-30_第129张图片

multi_lights.png-56.6kB

图9.10 使用1个平行光 + 4个点光源照亮一个物体

2018-08-30_第130张图片

frame_debugger.png-103.3kB

图9.11 打开帧调试器查看场景的绘制事件

2018-08-30_第131张图片

multi_lights_0.png-218.4kB

图9.12 本例中的6个渲染事件,绘制顺序是从左到右、从上到下进行的

2018-08-30_第132张图片

multi_lights_1.png-100.8kB

图9.13 如果物体不在一个光源的光照范围内(从右图可以看出,胶囊体不在最左方的点光源的照明范围内),Unity是不会调用Additional Pass来为该物体处理该光源的

2018-08-30_第133张图片

light_not_important.png-70.8kB

图9.14 当把光源的Render Mode设为Not Important时,这些光源就不会按逐像素光来处理

2018-08-30_第134张图片

light_shadow.png-32.8kB

图9.15 开启光源的阴影效果

2018-08-30_第135张图片

mesh_renderer.png-20.3kB

图9.16 Mesh Renderer组件的Cast Shadows和Receive Shadows属性可以控制该物体是否投射/接收阴影

2018-08-30_第136张图片

shadow_0.png-34.4kB

图9.17 开启Cast Shadows和Receive Shadows,从而让正方体可以投射和接收阴影

2018-08-30_第137张图片

shadow_1.png-89kB

图9.18 把Cast Shadows设置为Two Sided可以让右侧平面的背光面也产生阴影

2018-08-30_第138张图片

shadow_2.png-40.5kB

图9.19 正方体可以接收来自右侧平面的阴影

2018-08-30_第139张图片

shadow_frame_debugger.png-81.6kB

图9.20 使用帧调试器查看阴影绘制过程

2018-08-30_第140张图片

shadow_frame_debugger_0.png-83.1kB

图9.21 正方体对深度纹理的更新结果

2018-08-30_第141张图片

shadow_frame_debugger_1.png-88.6kB

图9.22 屏幕空间的阴影图

2018-08-30_第142张图片

shadow_frame_debugger_2.png-175.1kB

图9.23 Unity绘制屏幕阴影的过程

2018-08-30_第143张图片

alpha_test_shadow_0.png-62.8kB

图9.24 可以投射阴影的使用透明度测试的物体

2018-08-30_第144张图片

alpha_test_shadow_1.png-66.2kB

图9.25 正确设置了Fallback的使用透明度测试的物体

2018-08-30_第145张图片

alpha_test_shadow_2.png-75.7kB

图9.26 正确设置了Cast Shadow属性的使用透明度测试的物体

2018-08-30_第146张图片

alpha_blend_shadow0.png-88.6kB

图9.27 把使用了透明度混合的Unity Shader的Fallback设置为内置的Transparent/VertexLit。半透明物体不会向下方的平面投射阴影,也不会接收来自右侧平面的阴影,它看起来就像是完全透明一样

need-to-insert-img

alpha_blend_shadow1.png-94.9kB

图9.28 把Fallback设为VertexLit来强制为半透明物体生成阴影

第10章 高级纹理

need-to-insert-img

cubemap_sample.png-20.1kB

图10.1 对立方体纹理的采样

2018-08-30_第147张图片

skybox_mat.png-159kB

图10.2 天空盒子材质

2018-08-30_第148张图片

lighting_skybox.png-28.7kB

图10.3 为场景使用自定义的天空盒子

2018-08-30_第149张图片

skybox_scene.png-346.5kB

图10.4 使用了天空盒子的场景

2018-08-30_第150张图片

render_into_cubemap.png-123kB

图10.5 使用脚本创建立方体纹理

2018-08-30_第151张图片

render_to_cubemap.png-133.8kB

图10.6 使用脚本渲染立方体纹理

2018-08-30_第152张图片

reflection.png-400.5kB

图10.7 使用了反射效果的Teapot模型

2018-08-30_第153张图片

snell_law.png-28.6kB

图10.8 斯涅尔定律

2018-08-30_第154张图片

refraction.png-377.1kB

图10.9 使用了折射效果的Teapot模型

2018-08-30_第155张图片

fresnel.png-64.6kB

图10.10 使用了菲涅耳反射的Teapot模型

need-to-insert-img

mirror.png-342.1kB

图10.11 镜子效果

2018-08-30_第156张图片

render_texture.png-113.3kB

图10.12 左图:把摄像机的Target Texture设置成自定义的渲染纹理。右图:渲染纹理使用的纹理设置

2018-08-30_第157张图片

glass.png-462.9kB

图10.13 玻璃效果

2018-08-30_第158张图片

glass_cubemap.png-140.2kB

图10.14 本例使用的立方体纹理

2018-08-30_第159张图片

procedural_texture.png-111.3kB

图10.15 脚本生成的程序纹理

2018-08-30_第160张图片

procedural_texture_multi.png-62.8kB

图10.16 调整程序纹理的参数来得到不同的程序纹理

2018-08-30_第161张图片

subtance_material.png-41.1kB

图10.17 后缀为.sbsar的Substance材质

2018-08-30_第162张图片

subtance_material_asset.png-78.8kB

图10.18 程序纹理资源

2018-08-30_第163张图片

subtance_material_multi.png-183.5kB

图10.19 调整程序纹理属性可以得到看似完全不同的程序材质效果

第11章 让画面动起来

2018-08-30_第164张图片

boom.png-140.2kB

图11.1 本节使用的序列帧图像

2018-08-30_第165张图片

boom_sequence.png-37.6kB

图11.2 使用序列帧动画来实现爆炸效果

2018-08-30_第166张图片

scroll_background.png-228.5kB

图11.3 无限滚动的背景(纹理来源:forest-background © 2012-2013 Julien Jorge [email protected]

2018-08-30_第167张图片

river.png-242.7kB

图11.4 使用顶点动画来模拟2D的河流

2018-08-30_第168张图片

basis_vector.png-76.2kB

图11.5 法线固定(总是指向视角方向)时,计算广告牌技术中的三个正交基的过程

2018-08-30_第169张图片

billboard.png-86.8kB

图11.6 广告牌效果。左图显示了摄像机和5个广告牌之间的位置关系,摄像机是从斜上方向下观察它们的。中间的图显示了当Vertical Restraints属性为1,即固定法线方向为观察视角时所得到的效果,可以看出,所有的广告牌都完全面朝摄像机。右图显示了当Vertical Restraints属性为0,即固定指向上的方向为(0, 1, 0)时所得到的效果,可以看出,广告牌虽然最大限度地面朝摄像机,但其指向上的方向并未发生改变

2018-08-30_第170张图片

wrong_shadow.png-147.3kB

图11.7 当进行顶点动画时,如果仍然使用内置的ShadowCaster Pass来渲染阴影,可能会得到错误的阴影效果

2018-08-30_第171张图片

right_shadow.png-43.8kB

图11.8 使用自定义的ShadowCaster Pass为变形物体绘制正确的阴影

第12章 屏幕后处理效果

2018-08-30_第172张图片

brtsatcon.png-651.1kB

图12.1 左图:原效果。右图:调整了亮度(值为1.2)、饱和度(值为1.6)和对比度(值为1.2)后的效果

script_shader.png-16.6kB

图12.2 为脚本设置Shader的默认值

2018-08-30_第173张图片

edge_detection.png-717.9kB

图12.3 左图:12.2节得到的结果。右图:进行边缘检测后的效果

2018-08-30_第174张图片

convolution.png-15.1kB

图12.4 卷积核与卷积。使用一个3×3大小的卷积核对一张5×5大小的图像进行卷积操作,当计算图中红色方块对应的像素的卷积结果时,我们首先把卷积核的中心放置在该像素位置,翻转核之后再依次计算核中每个元素和其覆盖的图像像素值的乘积并求和,得到新的像素值

2018-08-30_第175张图片

edge_detection_kernel.png-19.8kB

图12.5 三种常见的边缘检测算子

need-to-insert-img

edge_only.png-266.5kB

图12.6 只显示边缘的屏幕效果

need-to-insert-img

gaussian_blur.png-703.8kB

图12.7 左图:原效果。右图:高斯模糊后的效果

2018-08-30_第176张图片

gaussian_kernel.png-21.2kB

图12.8 一个5×5大小的高斯核。左图显示了标准方差为1的高斯核的权重分布。我们可以把这个二维高斯核拆分成两个一维的高斯核(右图)

2018-08-30_第177张图片

800px-Elephants_Dream_-_Emo_and_Proog.jpg-41.9kB

图12.9 动画短片《大象之梦》中的Bloom效果。光线透过门扩散到了周围较暗的区域中

2018-08-30_第178张图片

bloom.png-772.3kB

图12.10 左图:原效果。右图:Bloom处理后的效果

2018-08-30_第179张图片

motion_blur.png-770.9kB

图12.11 左图:原效果。右图:应用运动模糊后的效果

第13章 使用深度和法线纹理

2018-08-30_第180张图片

projection_matrix.png-150.4kB

图13.1 在透视投影中,投影矩阵首先对顶点进行了缩放。在经过齐次除法后,透视投影的裁剪空间会变换到一个立方体。图中标注了4个关键点经过投影矩阵变换后的结果

2018-08-30_第181张图片

orthographic_matrix.png-129.6kB

图13.2 在正交投影中,投影矩阵对顶点进行了缩放。在经过齐次除法后,正交投影的裁剪空间会变换到一个立方体。图中标注了4个关键点经过投影矩阵变换后的结果

2018-08-30_第182张图片

check_texture.png-161.3kB

图13.3 使用Frame Debugger查看深度纹理(左)和深度+法线纹理(右)。如果当前摄像机需要生成深度和法线纹理,帧调试器的面板中就会出现相应的渲染事件。只要单击对应的事件就可以查看得到的深度和法线纹理

2018-08-30_第183张图片

check_texture_code.png-84kB

图13.4 左图:线性空间下的深度纹理。右图:解码后并且被映射到[0, 1]范围内的视角空间下的法线纹理

2018-08-30_第184张图片

fog.png-627.5kB

图13.5 左图:原效果。右图:添加全局雾效后的效果

2018-08-30_第185张图片

frustum.png-33.5kB

图13.6 计算interpolatedRay

2018-08-30_第186张图片

world_dist.png-18.6kB

图13.7 采样得到的深度值并非是点到摄像机的欧式距离

2018-08-30_第187张图片

over_edge.png-819kB

图13.8 左图:原效果。右图:直接对颜色图像进行边缘检测的结果

2018-08-30_第188张图片

edge_detect.png-452.9kB

图13.9 在深度和法线纹理上进行更健壮的边缘检测。左图:在原图上描边的效果。右图:只显示描边的效果

2018-08-30_第189张图片

Roberts.png-15.7kB

图13.10 Roberts算子

第14章 非真实感渲染

2018-08-30_第190张图片

okami_announce_screens6.jpg-169.9kB

图14.1 游戏《大神》(英文名:Okami)的游戏截图

2018-08-30_第191张图片

toon_shading.png-74.1kB

图14.2 卡通风格的渲染效果

2018-08-30_第192张图片

antialiasing.png-138.4kB

图14.3 左图:未对高光区域进行抗锯齿处理。右图:使用fwidth函数对高光区域进行抗锯齿处理

2018-08-30_第193张图片

TAM.png-127.6kB

图14.4 一个TAM的例子(来源:Praun E, et al. Real-time hatching4)

2018-08-30_第194张图片

hatching.png-268.1kB

图14.5 素描风格的渲染效果《Unity Shader入门精要》随书彩色插图(上)

 

VR设计云课堂 关注

2017.06.15 12:08* 字数 252 阅读 1002评论 1喜欢 18

Unity Shader入门精要》随书彩色插图

说明:本页面是书籍《Unity Shader入门精要》的随书彩图集锦,包含了书中所有的插图,使用时可通过图片编号进行搜索。 作者:冯乐乐 邮箱:[email protected]

前言

2018-08-30_第195张图片

shadertoy.png-286.5kB

第2章 渲染流水线

2018-08-30_第196张图片

流水线.png-83.4kB

图2.1 真实生活中的流水线

2018-08-30_第197张图片

概念流水线.png-16.9kB

图2.2 渲染流水线中的三个概念阶段

2018-08-30_第198张图片

CopyDataToGPU.png-86.5kB

图2.3 渲染所需的数据(两张纹理以及3个网格)从硬盘最终加载到显存中。在渲染时,GPU可以快速访问这些数据

2018-08-30_第199张图片

SetRenderState.png-157.1kB

图2.4 在同一状态下渲染三个网格。由于没有更改渲染状态,因此三个网格的外观看起来像是同一种材质的物体。

2018-08-30_第200张图片

DrawCall.png-59.1kB

图2.5 CPU通过调用Draw Call来告诉GPU开始进行一个渲染过程。一个Draw Call会指向本次调用需要渲染的图元列表

2018-08-30_第201张图片

GPU流水线.png-82.2kB

图2.6 GPU的渲染流水线实现。颜色表示了不同阶段的可配置性或可编程性:绿色表示该流水线阶段是完全可编程控制的,黄色表示该流水线阶段可以配置但不是可编程的,蓝色表示该流水线阶段是由GPU固定实现的,开发者没有任何控制权。实线表示该shader必须由开发者编程实现,虚线表示该Shader是可选的

2018-08-30_第202张图片

VertexShaderProcess.png-43kB

图2.7 GPU在每个输入的网格顶点上都会调用顶点着色器。顶点着色器必须进行顶点的坐标变换,需要时还可以计算和输出顶点的颜色。例如,我们可能需要进行逐顶点的光照

2018-08-30_第203张图片

Vertex Shader.png-34.9kB

图2.8 顶点着色器会将模型顶点的位置变换到齐次裁剪坐标空间下,进行输出后再由硬件做透视除法得到NDC下的坐标

2018-08-30_第204张图片

Clipping.png-25.5kB

图2.9 只有在单位立方体的图元才需要被继续处理。因此,完全在单位立方体外部的图元(红色三角形)被舍弃,完全在单位立方体内部的图元(绿色三角形)将被保留。和单位立方体相交的图元(黄色三角形)会被裁剪,新的顶点会被生成,原来在外部的顶点会被舍弃

2018-08-30_第205张图片

ScreenMapping.png-22.6kB

图2.10 屏幕映射将x、y坐标从(-1, 1)范围转换到屏幕坐标系中

2018-08-30_第206张图片

Screen Mapping_OpenGL_DirectX.png-26.9kB

图2.11 OpenGL和DirectX的屏幕坐标系差异。对于一张512*512大小的图像,在OpenGL中其(0, 0)点在左下角,而在DirectX中其(0, 0)点在左上角

2018-08-30_第207张图片

TriangleSetupAndTraversal.png-80kB

图2.12 三角形遍历的过程。根据几何阶段输出的顶点信息,最终得到该三角网格覆盖的像素位置。对应像素会生成一个片元,而片元中的状态是对三个顶点的信息进行插值得到的。例如,对图2.12中三个顶点的深度进行插值得到其重心位置对应的片元的深度值为-10.0

2018-08-30_第208张图片

FragmentShader.png-42.4kB

图2.13 根据上一步插值后的片元信息,片元着色器计算该片元的输出颜色

Per-fragment Operations.png-23.1kB

图2.14 逐片元操作阶段所做的操作。只有通过了所有的测试后,新生成的片元才能和颜色缓冲区中已经存在的像素颜色进行混合,最后再写入颜色缓冲区中

2018-08-30_第209张图片

Stencil Test_Depth Test.png-93.5kB

图2.15 模板测试和深度测试的简化流程图。

2018-08-30_第210张图片

Blending.png-67.6kB

图2.16 混合操作的简化流程图

2018-08-30_第211张图片

why_early_depth_test.png-18.7kB

图2.17 图示场景中包含了两个对象:球和长方体,绘制顺序是先绘制球(在屏幕上显示为圆),再绘制长方体(在屏幕上显示为长方形)。如果深度测试在片元着色器之后执行,那么在渲染长方体时,虽然它的大部分区域都被遮挡在球的后面,即它所覆盖的绝大部分片元根本无法通过深度测试,但是我们仍然需要对这些片元执行片元着色器,造成了很大的性能浪费

2018-08-30_第212张图片

OpenGL和DirectX.png-56.1kB

图2.18 CPU、OpenGL/DirectX、显卡驱动和GPU之间的关系

2018-08-30_第213张图片

CommandBuffer.png-49.9kB

图2.19 命令缓冲区。CPU通过图像编程接口向命令缓冲区中添加命令,而GPU从中读取命令并执行。黄色方框内的命令就是Draw Call,而红色方框内的命令用于改变渲染状态。我们使用红色方框来表示改变渲染状态的命令,是因为这些命令往往更加耗时

2018-08-30_第214张图片

SmallCommand.png-107.7kB

图2.20 命令缓冲区中的虚线方框表示GPU已经完成的命令。此时,命令缓冲区中没有可以执行的命令了,GPU处于空闲状态,而CPU还没有准备好下一个渲染命令。

2018-08-30_第215张图片

Batching.png-70.3kB

图2.21 利用批处理,CPU在RAM把多个网格合并成一个更大的网格,再发送给GPU,然后在一个Draw Call中渲染它们。但要注意的是,使用批处理合并的网格将会使用同一种渲染状态。也就是说,如果网格之间需要使用不同的渲染状态,那么就无法使用批处理技术

第3章 Unity Shader基础

2018-08-30_第216张图片

material_shader.png-125.8kB

图3.1 Unity Shader和材质。首先创建需要的Unity Shader和材质,然后把Unity Shader赋给材质,并在材质面板上调整属性(如使用的纹理、漫反射系数等)。最后,将材质赋给相应的模型来查看最终的渲染效果

2018-08-30_第217张图片

mesh_renderer.png-41kB

图3.2 将材质直接拖曳到模型的Mesh Renderer组件中

2018-08-30_第218张图片

material_inspector.png-119.4kB

图3.3 材质提供了一种可视化的方式来调整着色器中使用的参数

2018-08-30_第219张图片

shader_import_settings.png-38kB

图3.4 Unity Shader的导入设置面板

2018-08-30_第220张图片

shader_compile_code.png-35.9kB

图3.5 Gompile and show code下拉列表

2018-08-30_第221张图片

shaderlab_abstract.png-63.4kB

图3.6 Unity Shader为控制渲染过程提供了一层抽象。如果没有使用Unity Shader(左图),开发者需要和很多文件和设置打交道,才能让画面呈现出想要的效果;而在Unity Shader的帮助下(右图),开发者只需要使用ShaderLab来编写Unity Shader文件就可以完成所有的工作

2018-08-30_第222张图片

shader_name.png-55.5kB

图3.7 在Unity Shader的名称定义中利用斜杠来组织在材质面板中的位置

2018-08-30_第223张图片

shaderlab_properties.png-33.2kB

图3.8 不同属性类型在材质面板中的显示结果

2018-08-30_第224张图片

shader_compile_code.png-35.9kB

图3.9 在Unity Shader的导入设置面板中可以通过Compile and show code按钮来查看Unity对CG片段编译后的代码。通过单击Compile and show code按钮右端的倒三角可以打开下拉菜单,在这个下拉菜单中可以选择编译的平台种类,如只为当前的显卡设备编译特定的汇编代码,或为所有的平台编译汇编代码,我们也可以自定义选择编译到哪些平台上

第4章 学习Shader所需的数学基础

2018-08-30_第225张图片

little_cow.png-293.5kB

图4.1 我们的农场游戏。我们的主角妞妞是一头长得最壮、好奇心很强的奶牛

2018-08-30_第226张图片

cartersian_fly.png-28kB

图4.2 传说,笛卡尔坐标系来源于笛卡尔对天花板上一只苍蝇的运动轨迹的观察。笛卡尔发现,可以使用苍蝇距不同墙面的距离来描述它的当前位置

2018-08-30_第227张图片

cow_camera.png-180.1kB

图4.3 一个二维笛卡尔坐标系

2018-08-30_第228张图片

2d_cartesian_opengl_directx.png-33.1kB

图4.4 在屏幕映射时,OpenGL和DirectX使用了不同方向的二维笛卡尔坐标系

2018-08-30_第229张图片

cow_cartesian.png-211.8kB

图4.5 笛卡尔坐标系可以让妞妞精确表述自己的位置

2018-08-30_第230张图片

3d_cartesian.png-22.7kB

图4.6 一个三维笛卡尔坐标系

2018-08-30_第231张图片

space_handness.png-75.6kB

图4.7 左手坐标系

2018-08-30_第232张图片

right_hand.png-40kB

2018-08-30_第233张图片

left_right_hand_rule.png-75.3kB

图4.9 用左手法则和右手法则来判断旋转正方向

2018-08-30_第234张图片

cow_left_right.png-254.3kB

图4.10 为了移动到新的位置,妞妞需要首先向某个方向平移1个单位,再向另一个方向平移4个单位,最后再向一个方向旋转60°

2018-08-30_第235张图片

cow_left_right_hand.png-295.8kB

图4.11 左图和右图分别表示了在左手坐标系和右手坐标系中描述妞妞这次运动的结果,得到的数学描述是不同的

2018-08-30_第236张图片

unity_cartesian.png-173.2kB

图4.12 在模型空间和世界空间中,Unity使用的是左手坐标系。图中,球的坐标轴显示了它在模型空间中的3个坐标轴(红色为x轴,绿色是y轴,蓝色是z轴)

2018-08-30_第237张图片

unity_camera_cartesian.png-25.1kB

图4.13 在Unity中,观察空间使用的是右手坐标系,摄像机的前向是z轴的负方向,z轴越小,物体的深度越大,离摄像机越远

2018-08-30_第238张图片

exercise_3.png-130.8kB

图4.14 摄像机的位置是(0, 1, -10),球体的位置是(0, 1, 0)

2018-08-30_第239张图片

vector.png-8.9kB

图4.15 一个二维向量以及它的头和尾

2018-08-30_第240张图片

point_vector.png-16.1kB

图4.16 点和矢量之间的关系

2018-08-30_第241张图片

vector_scalar.png-53.9kB

图4.17 二维矢量和一些标量的乘法和除法

2018-08-30_第242张图片

vector_add_sub.png-52.8kB

图4.18 二维矢量的加法和减法

2018-08-30_第243张图片

vector_displacement.png-22.5kB

图4.19 使用矢量减法来计算从点a到点b的位移

2018-08-30_第244张图片

vector_magnitude.png-8.2kB

图4.20 矢量的模

2018-08-30_第245张图片

unit_vector.png-30.7kB

图4.21 二维空间的单位矢量都会落在单位圆上

2018-08-30_第246张图片

projection.png-17.7kB

图4.22 矢量b在单位矢量a方向上的投影

2018-08-30_第247张图片

dot_sign.png-22.9kB

图4.23 点积的符号

2018-08-30_第248张图片

dot_cos.png-14.1kB

图4.24 两个单位矢量进行点积

2018-08-30_第249张图片

vector_cross_diagram.png-32.1kB

图4.25 三维矢量叉积的计算规律。不同颜色的线表示了计算结果矢量中对应颜色的分量的计算路径。以红色为例,即结果矢量的第一个分量,它是从第一个矢量的y分量出发乘以第二个矢量的z分量,再减去第一个矢量的z分量和第二矢量的y分量的乘积

2018-08-30_第250张图片

vector_cross_length.png-13kB

图4.26 使用矢量a和矢量b构建一个平行四边形

2018-08-30_第251张图片

vector_cross.png-27.2kB

图4.27 分别使用左手坐标系和右手坐标系得到的叉积结果

2018-08-30_第252张图片

vector_cross_right_hand.png-46.6kB

图4.28 使用右手法则判断右手坐标系中a×b的方向

2018-08-30_第253张图片

exercise_cross.png-26.1kB

图4.29 三角形的三个顶点位于xy平面上,人眼位于z轴负方向,向z轴正方向观察

2018-08-30_第254张图片

matrix_mul.png-25kB

图4.30 计算c23的过程

2018-08-30_第255张图片

niuniu.png-273.2kB

图4.31 场景中的妞妞(左图)和屏幕上的妞妞(右图)。妞妞想知道,自己的鼻子是如何被画到屏幕上的

2018-08-30_第256张图片

object_space.png-84.5kB

图4.32 在我们的农场游戏中,每个奶牛都有自己的模型坐标系。在模型坐标系中妞妞鼻子的位置是(0, 2, 4, 1)

2018-08-30_第257张图片

unity_transform.png-151.9kB

图4.33 Unity的Transform组件可以调节模型的位置.如果Transform有父节点,如图中的“Mesh”,那么Position将是在其父节点(这里是“Cow”)的模型空间中的位置;如果没有父节点,Position就是在世界空间中的位置

2018-08-30_第258张图片

world_space.png-378.7kB

图4.34 农场游戏中的世界空间。世界空间的原点被放置在农场的中心。左下角显示了妞妞在世界空间中所做的变换。我们想要把妞妞的鼻子从模型空间变换到世界空间中

2018-08-30_第259张图片

camera_space.png-346.2kB

图4.35 农场游戏中摄像机的观察空间。观察空间的原点位于摄像机处。注意在观察空间中,摄像机的前向是z轴的负方向(图中只画出了z轴正方向),这是因为Unity在观察空间中使用了右手坐标系。左下角显示了摄像机在世界空间中所做的变换。我们想要把妞妞的鼻子从世界空间变换到观察空间中

2018-08-30_第260张图片

camera_projection.png-299.3kB

图4.36 透视投影(左图)和正交投影(右图)。左下角分别显示了当前摄像机的投影模式和相关属性

2018-08-30_第261张图片

camera_frustum.png-301.2kB

图4.37 视锥体和裁剪平面。左图显示了透视投影的视锥体,右图显示了正交投影的视锥体

2018-08-30_第262张图片

projection_frustum.png-67.3kB

图4.38 透视摄像机的参数对透视投影视锥体的影响

2018-08-30_第263张图片

projection_matrix0.png-135.1kB

图4.39 在透视投影中,投影矩阵对顶点进行了缩放。图3.38中标注了4个关键点经过投影矩阵变换后的结果。从这些结果可以看出x、y、z和w分量的范围发生的变化

2018-08-30_第264张图片

orthographic_frustum.png-33.5kB

图4.40 正交摄像机的参数对正交投影视锥体的影响

2018-08-30_第265张图片

orthographic_matrix0.png-129.6kB

图4.41 在正交投影中,投影矩阵对顶点进行了缩放。图中标注了4个关键点经过投影矩阵变换后的结果。从这些结果可以看出x、y、z和w分量范围发生的变化

2018-08-30_第266张图片

cow_camera.png-180.1kB

图4.42 农场游戏使用的摄像机参数和游戏画面的横纵比

2018-08-30_第267张图片

projection_matrix1.png-131kB

图4.43 经过齐次除法后,透视投影的裁剪空间会变换到一个立方体

2018-08-30_第268张图片

orthographic_matrix1.png-105.6kB

图4.44 经过齐次除法后,正交投影的裁剪空间会变换到一个立方体

2018-08-30_第269张图片

vertex_conversion.png-100.9kB

图4.45 渲染流水线中顶点的空间变换过程

2018-08-30_第270张图片

space_handness.png-75.6kB

图4.46 Unity中各个坐标空间的旋向性

2018-08-30_第271张图片

normal_tangent.png-167.3kB

图4.47 顶点的切线和法线。切线和法线互相垂直

2018-08-30_第272张图片

transform_normal.png-40.6kB

图4.48 进行非统一缩放时,如果使用和变换顶点相同的变换矩阵来变换法线,就会得到错误的结果,即变换后的法线方向与平面不再垂直

2018-08-30_第273张图片

screen_coord.png-9kB

图4.49 由片元的像素位置得到的图像

2018-08-30_第274张图片

difference_between_left_right.png-54.6kB

图4.50 图中两个坐标系的x轴和y轴是重合的,区别仅在于z轴的方向。左手坐标系的(0, 0, 1)点和右手坐标系中的(0, 0, 1)点是不同的,但它们旋转后的点却对应到了同一点

2018-08-30_第275张图片

difference_between_left_right_2.png-59.4kB

图4.51 绝对空间中的同一点,在左手和右手坐标系中进行同样角度的旋转,其旋转方向是不一样的。在左手坐标系中将按顺时针方向旋转,在右手坐标系中将按逆时针方向旋转

2018-08-30_第276张图片

exercise_cross2.png-34.4kB

图4.52 在左手坐标系中,如果叉积结果为负,那么3点的顺序是顺时针方向

第5章 开始Unity Shader学习之旅

2018-08-30_第277张图片

new_scene.png-74.3kB

图5.1 在Unity 5中新建一个场景得到的效果

need-to-insert-img

simple_shader.png-25.4kB

图5.2 用一个最简单的顶点/片元着色器得到一个白色的球

need-to-insert-img

cginclude.png-27kB

图5.3 Unity的内置着色器

need-to-insert-img

false_color.png-192.9kB

图5.4 用假彩色对Unity Shader进行调试

need-to-insert-img

color_picker.png-53.8kB

图5.5 使用颜色拾取器来查看调试信息

need-to-insert-img

frame_debugger.png-218.7kB

图5.6 帧调试器

need-to-insert-img

frame_debugger_0.png-164.5kB

图5.7 单击Knot的深度图渲染事件,在Game视图会显示该事件的效果,在Hierarchy视图中会高亮显示Knot对象,在帧调试器的右侧窗口会显示出该事件的细节

need-to-insert-img

2d_cartesian_opengl_directx.png-33.1kB

图5.8 OpenGL和DirectX使用了不同的屏幕空间坐标

第6章 Unity中的基础光照

need-to-insert-img

irradiance.png-60.3kB

图6.1 在左图中,光是垂直照射到物体表面,因此光线之间的垂直距离保持不变;而在右图中,光是斜着照射到物体表面,在物体表面光线之间的距离是d/cosθ,因此单位面积上接收到的光线数目要少于左图

need-to-insert-img

scattering.png-37.1kB

图6.2 散射时,光线会发生折射和反射现象。对于不透明物体,折射的光线会在物体内部继续传播,最终有一部分光线会重新从物体表面被发射出去

need-to-insert-img

specular.png-31.2kB

图6.3 使用Phong模型计算高光反射

need-to-insert-img

Blinn.png-32.1kB

图6.4 Blinn模型

need-to-insert-img

ambient.png-35.3kB

图6.5 在Unity的Window -> Lighting面板中,我们可以通过Ambient Source/Ambient Color/Ambient Intensity来控制场景中的环境光的颜色和强度

need-to-insert-img

diffuse_vertex_level.png-40.4kB

图6.6 逐顶点的漫反射光照效果

2018-08-30_第278张图片

diffuse_pixel_level.png-40.1kB

图6.7 逐像素的漫反射光照效果

2018-08-30_第279张图片

diffuse_compare_all.png-86.9kB

图6.8 逐顶点漫反射光照、逐像素漫反射光照、半兰伯特光照的对比效果

2018-08-30_第280张图片

reflect.png-9.2kB

图6.9 CG的reflect函数

2018-08-30_第281张图片

specular_vertex_level.png-41.5kB

图6.10 逐顶点的高光反射光照效果

2018-08-30_第282张图片

specular_pixel_level.png-40.8kB

图6.11 逐像素的高光反射光照效果

2018-08-30_第283张图片

specular_compare_all.png-82.5kB

图6.12 逐顶点的高光反射光照、逐像素的高光反射光照(Phong光照模型)和Blinn-Phong高光反射光照的对比结果

第7章 基础纹理

2018-08-30_第284张图片

texture_coordinate.png-349.3kB

图7.1 Unity中的纹理坐标

need-to-insert-img

single_texture.png-71.3kB

图7.2 使用单张纹理

need-to-insert-img

texture_tiling_offset.png-16.9kB

图7.3 调节纹理的平铺(缩放)和偏移(平移)属性

need-to-insert-img

texture_properties.png-29kB

图7.4 纹理的属性

2018-08-30_第285张图片

wrap_mode.png-68.9kB

图7.5 Wrap Mode决定了当纹理坐标超过[0, 1]范围后将会如何被平铺

2018-08-30_第286张图片

texture_offset.png-68.4kB

图7.6 偏移(Offset)属性决定了纹理坐标的偏移量

2018-08-30_第287张图片

magnification.png-256.2kB

图7.7 在放大纹理时,分别使用三种Filter Mode得到的结果

2018-08-30_第288张图片

mipmap.png-35.9kB

图7.8 在Advanced模式下可以设置多级渐远纹理的相关属性

2018-08-30_第289张图片

minification.png-271.9kB

图7.9 从上到下: Point滤波 + 多级渐远纹理技术,Bilinear滤波 + 多级渐远纹理技术,Trilinear滤波 + 多级渐远纹理技术

2018-08-30_第290张图片

texture_quality.png-31.7kB

图7.10 选择纹理的最大尺寸和纹理模式

2018-08-30_第291张图片

heightmap.png-134.5kB

图7.11 高度图

2018-08-30_第292张图片

tangent_space.png-165.3kB

图7.12 模型顶点的切线空间。其中,原点对应了顶点坐标,x轴是切线方向(t),y轴是副切线方向(b),z轴是法线方向(n)

2018-08-30_第293张图片

object_tangent_space_normal.png-320.3kB

图7.13 左图:模型空间下的法线纹理。右图:切线空间下的法线纹理

2018-08-30_第294张图片

normal_map.png-92.2kB

图7.14 使用法线纹理

2018-08-30_第295张图片

bump_scale.png-140.5kB

图7.15 使用Bump Scale属性来调整模型的凹凸程度

2018-08-30_第296张图片

texture_type_normal.png-29.8kB

图7.16 当使用UnpackNormal函数计算法线纹理中的法线方向时,需要把纹理类型标识为Normal map

2018-08-30_第297张图片

texture_type_heightmap.png-293.4kB

图7.17 当勾选了Create from Grayscale后,Unity会根据高度图来生成一张切线空间下的法线纹理

2018-08-30_第298张图片

ramp_texture.png-119.2kB

图7.18 使用不同的渐变纹理控制漫反射光照,左下角给出了每张图使用的渐变纹理

2018-08-30_第299张图片

ramp_texture_wrap_mode.png-114.2kB

图7.19 Wrap Mode分别为Repeat和Clamp模式的效果对比

2018-08-30_第300张图片

mask_specular.png-142.4kB

图7.20 使用高光遮罩纹理。从左到右:只包含漫反射,未使用遮罩的高光反射,使用遮罩的高光反射

2018-08-30_第301张图片

mask.png-671.4kB

图7.21 本节使用的高光遮罩纹理

第8章 透明效果

need-to-insert-img

render_order_0.png-10.7kB

图8.1 场景中有两个物体,其中A(黄色)是半透明物体,B(紫色)是不透明物体

need-to-insert-img

render_order_1.png-10.5kB

图8.2 场景中有两个物体,其中A和B都是半透明物体

2018-08-30_第302张图片

render_order_3.png-15.3kB

图8.3 循环重叠的半透明物体总是无法得到正确的半透明效果

2018-08-30_第303张图片

render_order_2.png-30.4kB

图8.4 使用哪个深度对物体进行排序。红色点分别标明了网格上距离摄像机最近的点、最远的点以及网格中点

2018-08-30_第304张图片

transparent_texture.png-71.9kB

图8.5 一张透明纹理,其中每个方格的透明度都不同

2018-08-30_第305张图片

alpha_test.png-55.9kB

图8.6 透明度测试

2018-08-30_第306张图片

alpha_test_0.png-166.4kB

图8.7 随着Alpha cutoff参数的增大,更多的像素由于不满足透明度测试条件而被剔除

2018-08-30_第307张图片

alpha_blend.png-55.1kB

图8.8 透明度混合

2018-08-30_第308张图片

alpha_blend_0.png-138.7kB

图8.9 随着Alpha Scale参数的增大,模型变得越来越透明

2018-08-30_第309张图片

transparent_order_wrong.png-94.7kB

图8.10 当模型网格之间有互相交叉的结构时,往往会得到错误的半透明效果

2018-08-30_第310张图片

alpha_blend_zwrite.png-87.9kB

图8.11 开启了深度写入的半透明效果

2018-08-30_第311张图片

blend.png-74.1kB

图8.12 不同混合状态设置得到的效果

2018-08-30_第312张图片

alpha_test_both_sided.png-60.7kB

图8.13 双面渲染的透明度测试的物体

2018-08-30_第313张图片

alpha_blend_both_sided.png-66.2kB

图8.14 双面渲染的透明度混合的物体

第9章 更复杂的光照

2018-08-30_第314张图片

rendering_path_setting.png-30kB

图9.1 设置Unity项目的渲染路径

2018-08-30_第315张图片

rendering_path_camera.png-37.8kB

图9.2 摄像机组件的Rendering Path中的设置可以覆盖Project Settings中的设置

2018-08-30_第316张图片

light_type_mode.png-30.6kB

图9.3 设置光源的类型和渲染模式

2018-08-30_第317张图片

forward_rendering.png-175.5kB

图9.4 前向渲染的两种Pass

2018-08-30_第318张图片

directional_ligth.png-51.6kB

图9.5 平行光

2018-08-30_第319张图片

point_ligtht.png-89.4kB

图9.6 点光源

2018-08-30_第320张图片

enable_light.png-63.6kB

图9.7 开启Scene视图中的光照

2018-08-30_第321张图片

spot_light.png-74.5kB

图9.8 聚光灯

2018-08-30_第322张图片

two_lights.png-79.4kB

图9.9 使用一个平行光和一个点光源共同照亮物体。右图显示了胶囊体、平行光和点光源在场景中的相对位置

2018-08-30_第323张图片

multi_lights.png-56.6kB

图9.10 使用1个平行光 + 4个点光源照亮一个物体

2018-08-30_第324张图片

frame_debugger.png-103.3kB

图9.11 打开帧调试器查看场景的绘制事件

2018-08-30_第325张图片

multi_lights_0.png-218.4kB

图9.12 本例中的6个渲染事件,绘制顺序是从左到右、从上到下进行的

2018-08-30_第326张图片

multi_lights_1.png-100.8kB

图9.13 如果物体不在一个光源的光照范围内(从右图可以看出,胶囊体不在最左方的点光源的照明范围内),Unity是不会调用Additional Pass来为该物体处理该光源的

2018-08-30_第327张图片

light_not_important.png-70.8kB

图9.14 当把光源的Render Mode设为Not Important时,这些光源就不会按逐像素光来处理

2018-08-30_第328张图片

light_shadow.png-32.8kB

图9.15 开启光源的阴影效果

2018-08-30_第329张图片

mesh_renderer.png-20.3kB

图9.16 Mesh Renderer组件的Cast Shadows和Receive Shadows属性可以控制该物体是否投射/接收阴影

2018-08-30_第330张图片

shadow_0.png-34.4kB

图9.17 开启Cast Shadows和Receive Shadows,从而让正方体可以投射和接收阴影

2018-08-30_第331张图片

shadow_1.png-89kB

图9.18 把Cast Shadows设置为Two Sided可以让右侧平面的背光面也产生阴影

2018-08-30_第332张图片

shadow_2.png-40.5kB

图9.19 正方体可以接收来自右侧平面的阴影

2018-08-30_第333张图片

shadow_frame_debugger.png-81.6kB

图9.20 使用帧调试器查看阴影绘制过程

2018-08-30_第334张图片

shadow_frame_debugger_0.png-83.1kB

图9.21 正方体对深度纹理的更新结果

2018-08-30_第335张图片

shadow_frame_debugger_1.png-88.6kB

图9.22 屏幕空间的阴影图

2018-08-30_第336张图片

shadow_frame_debugger_2.png-175.1kB

图9.23 Unity绘制屏幕阴影的过程

2018-08-30_第337张图片

alpha_test_shadow_0.png-62.8kB

图9.24 可以投射阴影的使用透明度测试的物体

2018-08-30_第338张图片

alpha_test_shadow_1.png-66.2kB

图9.25 正确设置了Fallback的使用透明度测试的物体

2018-08-30_第339张图片

alpha_test_shadow_2.png-75.7kB

图9.26 正确设置了Cast Shadow属性的使用透明度测试的物体

2018-08-30_第340张图片

alpha_blend_shadow0.png-88.6kB

图9.27 把使用了透明度混合的Unity Shader的Fallback设置为内置的Transparent/VertexLit。半透明物体不会向下方的平面投射阴影,也不会接收来自右侧平面的阴影,它看起来就像是完全透明一样

need-to-insert-img

alpha_blend_shadow1.png-94.9kB

图9.28 把Fallback设为VertexLit来强制为半透明物体生成阴影

第10章 高级纹理

need-to-insert-img

cubemap_sample.png-20.1kB

图10.1 对立方体纹理的采样

2018-08-30_第341张图片

skybox_mat.png-159kB

图10.2 天空盒子材质

2018-08-30_第342张图片

lighting_skybox.png-28.7kB

图10.3 为场景使用自定义的天空盒子

2018-08-30_第343张图片

skybox_scene.png-346.5kB

图10.4 使用了天空盒子的场景

2018-08-30_第344张图片

render_into_cubemap.png-123kB

图10.5 使用脚本创建立方体纹理

2018-08-30_第345张图片

render_to_cubemap.png-133.8kB

图10.6 使用脚本渲染立方体纹理

2018-08-30_第346张图片

reflection.png-400.5kB

图10.7 使用了反射效果的Teapot模型

2018-08-30_第347张图片

snell_law.png-28.6kB

图10.8 斯涅尔定律

2018-08-30_第348张图片

refraction.png-377.1kB

图10.9 使用了折射效果的Teapot模型

2018-08-30_第349张图片

fresnel.png-64.6kB

图10.10 使用了菲涅耳反射的Teapot模型

need-to-insert-img

mirror.png-342.1kB

图10.11 镜子效果

2018-08-30_第350张图片

render_texture.png-113.3kB

图10.12 左图:把摄像机的Target Texture设置成自定义的渲染纹理。右图:渲染纹理使用的纹理设置

2018-08-30_第351张图片

glass.png-462.9kB

图10.13 玻璃效果

2018-08-30_第352张图片

glass_cubemap.png-140.2kB

图10.14 本例使用的立方体纹理

2018-08-30_第353张图片

procedural_texture.png-111.3kB

图10.15 脚本生成的程序纹理

2018-08-30_第354张图片

procedural_texture_multi.png-62.8kB

图10.16 调整程序纹理的参数来得到不同的程序纹理

2018-08-30_第355张图片

subtance_material.png-41.1kB

图10.17 后缀为.sbsar的Substance材质

2018-08-30_第356张图片

subtance_material_asset.png-78.8kB

图10.18 程序纹理资源

2018-08-30_第357张图片

subtance_material_multi.png-183.5kB

图10.19 调整程序纹理属性可以得到看似完全不同的程序材质效果

第11章 让画面动起来

2018-08-30_第358张图片

boom.png-140.2kB

图11.1 本节使用的序列帧图像

2018-08-30_第359张图片

boom_sequence.png-37.6kB

图11.2 使用序列帧动画来实现爆炸效果

2018-08-30_第360张图片

scroll_background.png-228.5kB

图11.3 无限滚动的背景(纹理来源:forest-background © 2012-2013 Julien Jorge [email protected]

2018-08-30_第361张图片

river.png-242.7kB

图11.4 使用顶点动画来模拟2D的河流

2018-08-30_第362张图片

basis_vector.png-76.2kB

图11.5 法线固定(总是指向视角方向)时,计算广告牌技术中的三个正交基的过程

2018-08-30_第363张图片

billboard.png-86.8kB

图11.6 广告牌效果。左图显示了摄像机和5个广告牌之间的位置关系,摄像机是从斜上方向下观察它们的。中间的图显示了当Vertical Restraints属性为1,即固定法线方向为观察视角时所得到的效果,可以看出,所有的广告牌都完全面朝摄像机。右图显示了当Vertical Restraints属性为0,即固定指向上的方向为(0, 1, 0)时所得到的效果,可以看出,广告牌虽然最大限度地面朝摄像机,但其指向上的方向并未发生改变

2018-08-30_第364张图片

wrong_shadow.png-147.3kB

图11.7 当进行顶点动画时,如果仍然使用内置的ShadowCaster Pass来渲染阴影,可能会得到错误的阴影效果

2018-08-30_第365张图片

right_shadow.png-43.8kB

图11.8 使用自定义的ShadowCaster Pass为变形物体绘制正确的阴影

第12章 屏幕后处理效果

2018-08-30_第366张图片

brtsatcon.png-651.1kB

图12.1 左图:原效果。右图:调整了亮度(值为1.2)、饱和度(值为1.6)和对比度(值为1.2)后的效果

script_shader.png-16.6kB

图12.2 为脚本设置Shader的默认值

2018-08-30_第367张图片

edge_detection.png-717.9kB

图12.3 左图:12.2节得到的结果。右图:进行边缘检测后的效果

2018-08-30_第368张图片

convolution.png-15.1kB

图12.4 卷积核与卷积。使用一个3×3大小的卷积核对一张5×5大小的图像进行卷积操作,当计算图中红色方块对应的像素的卷积结果时,我们首先把卷积核的中心放置在该像素位置,翻转核之后再依次计算核中每个元素和其覆盖的图像像素值的乘积并求和,得到新的像素值

2018-08-30_第369张图片

edge_detection_kernel.png-19.8kB

图12.5 三种常见的边缘检测算子

need-to-insert-img

edge_only.png-266.5kB

图12.6 只显示边缘的屏幕效果

need-to-insert-img

gaussian_blur.png-703.8kB

图12.7 左图:原效果。右图:高斯模糊后的效果

2018-08-30_第370张图片

gaussian_kernel.png-21.2kB

图12.8 一个5×5大小的高斯核。左图显示了标准方差为1的高斯核的权重分布。我们可以把这个二维高斯核拆分成两个一维的高斯核(右图)

2018-08-30_第371张图片

800px-Elephants_Dream_-_Emo_and_Proog.jpg-41.9kB

图12.9 动画短片《大象之梦》中的Bloom效果。光线透过门扩散到了周围较暗的区域中

2018-08-30_第372张图片

bloom.png-772.3kB

图12.10 左图:原效果。右图:Bloom处理后的效果

2018-08-30_第373张图片

motion_blur.png-770.9kB

图12.11 左图:原效果。右图:应用运动模糊后的效果

第13章 使用深度和法线纹理

2018-08-30_第374张图片

projection_matrix.png-150.4kB

图13.1 在透视投影中,投影矩阵首先对顶点进行了缩放。在经过齐次除法后,透视投影的裁剪空间会变换到一个立方体。图中标注了4个关键点经过投影矩阵变换后的结果

2018-08-30_第375张图片

orthographic_matrix.png-129.6kB

图13.2 在正交投影中,投影矩阵对顶点进行了缩放。在经过齐次除法后,正交投影的裁剪空间会变换到一个立方体。图中标注了4个关键点经过投影矩阵变换后的结果

2018-08-30_第376张图片

check_texture.png-161.3kB

图13.3 使用Frame Debugger查看深度纹理(左)和深度+法线纹理(右)。如果当前摄像机需要生成深度和法线纹理,帧调试器的面板中就会出现相应的渲染事件。只要单击对应的事件就可以查看得到的深度和法线纹理

2018-08-30_第377张图片

check_texture_code.png-84kB

图13.4 左图:线性空间下的深度纹理。右图:解码后并且被映射到[0, 1]范围内的视角空间下的法线纹理

2018-08-30_第378张图片

fog.png-627.5kB

图13.5 左图:原效果。右图:添加全局雾效后的效果

2018-08-30_第379张图片

frustum.png-33.5kB

图13.6 计算interpolatedRay

2018-08-30_第380张图片

world_dist.png-18.6kB

图13.7 采样得到的深度值并非是点到摄像机的欧式距离

2018-08-30_第381张图片

over_edge.png-819kB

图13.8 左图:原效果。右图:直接对颜色图像进行边缘检测的结果

2018-08-30_第382张图片

edge_detect.png-452.9kB

图13.9 在深度和法线纹理上进行更健壮的边缘检测。左图:在原图上描边的效果。右图:只显示描边的效果

2018-08-30_第383张图片

Roberts.png-15.7kB

图13.10 Roberts算子

第14章 非真实感渲染

2018-08-30_第384张图片

okami_announce_screens6.jpg-169.9kB

图14.1 游戏《大神》(英文名:Okami)的游戏截图

2018-08-30_第385张图片

toon_shading.png-74.1kB

图14.2 卡通风格的渲染效果

2018-08-30_第386张图片

antialiasing.png-138.4kB

图14.3 左图:未对高光区域进行抗锯齿处理。右图:使用fwidth函数对高光区域进行抗锯齿处理

2018-08-30_第387张图片

TAM.png-127.6kB

图14.4 一个TAM的例子(来源:Praun E, et al. Real-time hatching4)

2018-08-30_第388张图片

hatching.png-268.1kB

图14.5 素描风格的渲染效果

你可能感兴趣的:(2018-08-30)