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

发表于2017-06-24
评论0 2.8k浏览

前言


shadertoy.png-286.5kB

第2章 渲染流水线


流水线.png-83.4kB

图2.1 真实生活中的流水线


概念流水线.png-16.9kB

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


CopyDataToGPU.png-86.5kB

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


SetRenderState.png-157.1kB

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


DrawCall.png-59.1kB

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


GPU流水线.png-82.2kB

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


VertexShaderProcess.png-43kB

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


Vertex Shader.png-34.9kB

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


Clipping.png-25.5kB

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


ScreenMapping.png-22.6kB

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


Screen Mapping_OpenGL_DirectX.png-26.9kB

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


TriangleSetupAndTraversal.png-80kB

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


FragmentShader.png-42.4kB

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


Per-fragment Operations.png-23.1kB

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


Stencil Test_Depth Test.png-93.5kB

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


Blending.png-67.6kB

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


why_early_depth_test.png-18.7kB

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


OpenGL和DirectX.png-56.1kB

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


CommandBuffer.png-49.9kB

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


SmallCommand.png-107.7kB

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


Batching.png-70.3kB

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

第3章 Unity Shader基础


material_shader.png-125.8kB

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


mesh_renderer.png-41kB

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


material_inspector.png-119.4kB

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


shader_import_settings.png-38kB

图3.4 Unity Shader的导入设置面板


shader_compile_code.png-35.9kB

图3.5 Gompile and show code下拉列表


shaderlab_abstract.png-63.4kB

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


shader_name.png-55.5kB

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


shaderlab_properties.png-33.2kB

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


shader_compile_code.png-35.9kB

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

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


little_cow.png-293.5kB

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


cartersian_fly.png-28kB

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


cow_camera.png-180.1kB

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


2d_cartesian_opengl_directx.png-33.1kB

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


cow_cartesian.png-211.8kB

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


3d_cartesian.png-22.7kB

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


space_handness.png-75.6kB

图4.7 左手坐标系


right_hand.png-40kB

left_right_hand_rule.png-75.3kB

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


cow_left_right.png-254.3kB

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


cow_left_right_hand.png-295.8kB

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


unity_cartesian.png-173.2kB

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


unity_camera_cartesian.png-25.1kB

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


exercise_3.png-130.8kB

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


vector.png-8.9kB

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


point_vector.png-16.1kB

图4.16 点和矢量之间的关系


vector_scalar.png-53.9kB

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


vector_add_sub.png-52.8kB

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


vector_displacement.png-22.5kB

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


vector_magnitude.png-8.2kB

图4.20 矢量的模


unit_vector.png-30.7kB

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


projection.png-17.7kB

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


dot_sign.png-22.9kB

图4.23 点积的符号


dot_cos.png-14.1kB

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


vector_cross_diagram.png-32.1kB

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


vector_cross_length.png-13kB

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


vector_cross.png-27.2kB

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


vector_cross_right_hand.png-46.6kB

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


exercise_cross.png-26.1kB

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


matrix_mul.png-25kB

图4.30 计算c23的过程


niuniu.png-273.2kB

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


object_space.png-84.5kB

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


unity_transform.png-151.9kB

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


world_space.png-378.7kB

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


camera_space.png-346.2kB

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


camera_projection.png-299.3kB

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


camera_frustum.png-301.2kB

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


projection_frustum.png-67.3kB

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


projection_matrix0.png-135.1kB

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


orthographic_frustum.png-33.5kB

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


orthographic_matrix0.png-129.6kB

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


cow_camera.png-180.1kB

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


projection_matrix1.png-131kB

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


orthographic_matrix1.png-105.6kB

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


vertex_conversion.png-100.9kB

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


space_handness.png-75.6kB

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


normal_tangent.png-167.3kB

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


transform_normal.png-40.6kB

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


screen_coord.png-9kB

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


difference_between_left_right.png-54.6kB

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


difference_between_left_right_2.png-59.4kB

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


exercise_cross2.png-34.4kB

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

第5章 开始Unity Shader学习之旅


new_scene.png-74.3kB

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


simple_shader.png-25.4kB

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


cginclude.png-27kB

图5.3 Unity的内置着色器


false_color.png-192.9kB

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


color_picker.png-53.8kB

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


frame_debugger.png-218.7kB

图5.6 帧调试器


frame_debugger_0.png-164.5kB

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


2d_cartesian_opengl_directx.png-33.1kB

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

第6章 Unity中的基础光照


irradiance.png-60.3kB

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


scattering.png-37.1kB

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


specular.png-31.2kB

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


Blinn.png-32.1kB

图6.4 Blinn模型


ambient.png-35.3kB

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


diffuse_vertex_level.png-40.4kB

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


diffuse_pixel_level.png-40.1kB

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


diffuse_compare_all.png-86.9kB

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


reflect.png-9.2kB

图6.9 CG的reflect函数


specular_vertex_level.png-41.5kB

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


specular_pixel_level.png-40.8kB

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


specular_compare_all.png-82.5kB

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

第7章 基础纹理


texture_coordinate.png-349.3kB

图7.1 Unity中的纹理坐标


single_texture.png-71.3kB

图7.2 使用单张纹理


texture_tiling_offset.png-16.9kB

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


texture_properties.png-29kB

图7.4 纹理的属性


wrap_mode.png-68.9kB

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


texture_offset.png-68.4kB

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


magnification.png-256.2kB

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


mipmap.png-35.9kB

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


minification.png-271.9kB

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


texture_quality.png-31.7kB

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


heightmap.png-134.5kB

图7.11 高度图


tangent_space.png-165.3kB

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


object_tangent_space_normal.png-320.3kB

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


normal_map.png-92.2kB

图7.14 使用法线纹理


bump_scale.png-140.5kB

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


texture_type_normal.png-29.8kB

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


texture_type_heightmap.png-293.4kB

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


ramp_texture.png-119.2kB

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


ramp_texture_wrap_mode.png-114.2kB

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


mask_specular.png-142.4kB

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


mask.png-671.4kB

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

第8章 透明效果


render_order_0.png-10.7kB

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


render_order_1.png-10.5kB

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


render_order_3.png-15.3kB

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


render_order_2.png-30.4kB

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


transparent_texture.png-71.9kB

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


alpha_test.png-55.9kB

图8.6 透明度测试


alpha_test_0.png-166.4kB

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


alpha_blend.png-55.1kB

图8.8 透明度混合


alpha_blend_0.png-138.7kB

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


transparent_order_wrong.png-94.7kB

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


alpha_blend_zwrite.png-87.9kB

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


blend.png-74.1kB

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


alpha_test_both_sided.png-60.7kB

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


alpha_blend_both_sided.png-66.2kB

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

第9章 更复杂的光照


rendering_path_setting.png-30kB

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


rendering_path_camera.png-37.8kB

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


light_type_mode.png-30.6kB

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


forward_rendering.png-175.5kB

图9.4 前向渲染的两种Pass


directional_ligth.png-51.6kB

图9.5 平行光


point_ligtht.png-89.4kB

图9.6 点光源


enable_light.png-63.6kB

图9.7 开启Scene视图中的光照


spot_light.png-74.5kB

图9.8 聚光灯


two_lights.png-79.4kB

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


multi_lights.png-56.6kB

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


frame_debugger.png-103.3kB

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


multi_lights_0.png-218.4kB

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


multi_lights_1.png-100.8kB

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


light_not_important.png-70.8kB

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


light_shadow.png-32.8kB

图9.15 开启光源的阴影效果


mesh_renderer.png-20.3kB

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


shadow_0.png-34.4kB

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


shadow_1.png-89kB

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


shadow_2.png-40.5kB

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


shadow_frame_debugger.png-81.6kB

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


shadow_frame_debugger_0.png-83.1kB

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


shadow_frame_debugger_1.png-88.6kB

图9.22 屏幕空间的阴影图


shadow_frame_debugger_2.png-175.1kB

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


alpha_test_shadow_0.png-62.8kB

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


alpha_test_shadow_1.png-66.2kB

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


alpha_test_shadow_2.png-75.7kB

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


alpha_blend_shadow0.png-88.6kB

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


alpha_blend_shadow1.png-94.9kB

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

第10章 高级纹理


cubemap_sample.png-20.1kB

图10.1 对立方体纹理的采样


skybox_mat.png-159kB

图10.2 天空盒子材质


lighting_skybox.png-28.7kB

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


skybox_scene.png-346.5kB

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


render_into_cubemap.png-123kB

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


render_to_cubemap.png-133.8kB

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


reflection.png-400.5kB

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


snell_law.png-28.6kB

图10.8 斯涅尔定律


refraction.png-377.1kB

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


fresnel.png-64.6kB

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


mirror.png-342.1kB

图10.11 镜子效果


render_texture.png-113.3kB

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


glass.png-462.9kB

图10.13 玻璃效果


glass_cubemap.png-140.2kB

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


procedural_texture.png-111.3kB

图10.15 脚本生成的程序纹理


procedural_texture_multi.png-62.8kB

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


subtance_material.png-41.1kB

图10.17 后缀为.sbsar的Substance材质


subtance_material_asset.png-78.8kB

图10.18 程序纹理资源


subtance_material_multi.png-183.5kB

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

第11章 让画面动起来


boom.png-140.2kB

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


boom_sequence.png-37.6kB

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


scroll_background.png-228.5kB

图11.3 无限滚动的背景(纹理来源:forest-background © 2012-2013 Julien Jorge julien.jorge@stuff-o-matic.com)


river.png-242.7kB

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


basis_vector.png-76.2kB

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


billboard.png-86.8kB

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


wrong_shadow.png-147.3kB

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


right_shadow.png-43.8kB

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

第12章 屏幕后处理效果


brtsatcon.png-651.1kB

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


script_shader.png-16.6kB

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


edge_detection.png-717.9kB

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


convolution.png-15.1kB

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


edge_detection_kernel.png-19.8kB

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


edge_only.png-266.5kB

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


gaussian_blur.png-703.8kB

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


gaussian_kernel.png-21.2kB

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


800px-Elephants_Dream_-_Emo_and_Proog.jpg-41.9kB

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


bloom.png-772.3kB

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


motion_blur.png-770.9kB

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

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


projection_matrix.png-150.4kB

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


orthographic_matrix.png-129.6kB

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


check_texture.png-161.3kB

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


check_texture_code.png-84kB

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


fog.png-627.5kB

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


frustum.png-33.5kB

图13.6 计算interpolatedRay


world_dist.png-18.6kB

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


over_edge.png-819kB

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


edge_detect.png-452.9kB

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


Roberts.png-15.7kB

图13.10 Roberts算子

第14章 非真实感渲染


okami_announce_screens6.jpg-169.9kB

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


toon_shading.png-74.1kB

图14.2 卡通风格的渲染效果


antialiasing.png-138.4kB

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


TAM.png-127.6kB

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


hatching.png-268.1kB

图14.5 素描风格的渲染效果

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引