Lecture 04 Rendering on Game Engine

news/2024/11/15 21:25:38/文章来源:https://www.cnblogs.com/Tellulu/p/18391253

Lecture 04 Rendering on Game Engine

Challenges on Game Rendering

  • 成千上万不同类型的物体
  • 在现代计算机上跑(CPU、GPU的复杂结合)
  • 稳定帧率
    • 帧率
    • 分辨率
  • 限制CPU带宽和内存
    • 渲染只占20%左右,剩下留给Game logic、网络、动画、物理和AI系统等等

Outline of Rendering

  • Basics of Game Engine
    • 硬件结构
    • 渲染数据组织
    • Visibility
  • Materials、Shaders and Lighting
    • PBR (SG, MR)
    • Shader模型
    • Lighting
      • Point / Directional lighting
      • IBL / Simple GI
  • Special Rendering
    • Terrain
    • Sky / Fog
    • PostProcess
  • Pipeline
    • Forward, deferred rendering, forward plus
    • Real pipeline with mixed effects
    • Ring buffer and V-Sync
    • Tiled-based rendering

Building blocks of Rendering

渲染管线相关内容见GAMES101,不再赘述

  • GPU

    • SIMD Single Instruction Multiple Data

      一个指令完成多维加减法

      比如矩阵运算、坐标运算下会使用

    • SIMT Single Instruction Multiple Thread

      一条指令在许多核上做同样指令操作

      比如计算着色器、CUDA

      所以绘制时尽可能用同样的代码,使用自己的数据来运算

    • 现代GPU架构

      • GPC Graphics Processing Cluster

        图形处理集群,用于计算、光栅化、着色和纹理

      • SM Streaming Multiprocessor

        用来跑CUDA kernels

        不同SM含有Shared Memory

      • Texture Units

        纹理处理单元,可以fetch和filter纹理

      • CUDA Core

        并行运算单元

      • Warp

        线程集合

  • Data Flow from CPU to GPU

    • CPU与内存
      • 数据加载/卸载
      • 数据预备
    • CPU to GPU
    • 高延迟
    • 带宽限制
    • 因此尽可能单向从CPU往GPU送数据,而不要从GPU读数据
    • GPU和显存
      • 高性能并行渲染
  • Be Aware of Cache Efficiency

    数据恰好在缓存上叫Cache hit,否则叫Cache miss,就要等很久

    • 全力利用硬件并行计算的优势
    • 避免冯诺依曼瓶颈
  • GPU Bounds and Performance

    应用程序性能被以下限制

    • Memory Bounds
    • ALU Bounds
    • TMU (Texture Mapping Unit) Bound
    • BW (Bandwidth) Bound
  • Modern Hardware Pipeline

    • D3D12的mesh shader
  • 其他架构

    • 比如主机UMA架构(内存是共享的)

    • 移动端架构

      考虑到功耗和芯片性能,发展出了Tile-Based Rendering

      two-pass渲染,pass one中不被剔除的图元才在pass two中执行fragment shader

      # Pass one
      for draw in renderpass:for primitive in draw:for vertex in primitive:execute_vertex_shader(vertex)if primitive not culled:append_tile_list(primitive)#Pass two
      for tile in renderpass:for primitive in tile:for fragment in primitve:execute_fragment_shader(fragment)
      

Mesh Render Component

  • Everything is a game object in the game world

  • Game object could be described in component-based way

  • game object中表达的游戏对象和真实要绘制的是两个东西(mesh component)

  • 在mesh component中会存renderable,拿到renderable就可以绘制出来

  • renderable

    • mesh

    • material

    • texture

    • normal

    • ...

Mesh

  • Mesh包含

    • 顶点位置
    • 法向朝向
    • UV
    • ...
  • Mesh表达

    存顶点索引值,因为顶点会被共用

    • Vertex Data

      • Vertex declaration
      • Vertex buffer
    • Index Data

      • Index declaration

      • Index buffer

        实际上可以不存储Index buffer,可以每个三角形的顶点索引记为一组(triangle stripe)

Materials

在现代引擎中,一般在绘制系统中只定义视觉材质,物理材质单独定义

包含Shader和Texture

  • Phong模型
  • PBR
  • ...

Texture

  • Albedo
  • Normal
  • Metallic
  • Roughness
  • AO
  • ...

Variety of Shaders

现代游戏引擎中shader既可以看作源代码也可以看作Assets

绘制时,需要给一小段代码,叫作blob (二进制数据块),是编译好的shader代码

  • Shader Graph

    连连看生成shader代码

Render Objects in Engine

Coordinate System and Transformation

模型Asset在局部坐标系定义,最终需要渲染到屏幕空间

Object with Many Materials

  • Mesh

    • Vertex Data

      • positions
      • uv
      • ...
    • Index Data

      用Submesh管理,根据材质不同,切分成submesh,对应自己的材质、纹理、shader,但是会把顶点放在一个大的buffer中,这样只需要用offset和count去取就好

      • Submesh
        • offset
        • count
  • Material

    • Shader
    • Textures

Instance: Use Handle to Reuse Resources

如果绘制很多东西时,每个GameObject都存储Mesh、submesh,各种材质、shader、纹理,这样数据量就非常大,并且这里很多东西都是一样的

于是在现代游戏引擎中会建立一个Resource Pool

  • 所有的Mesh放在一起,形成Mesh Pool
  • 所有Texture放在一起
  • 所有Shader放在一起

这样不同Instance只是通过一个指引指向各自需要的材质、网格等等(实例化:使用Handle复用资源)

Sort by Material

每次改变参数(纹理、shader)时损耗大,因为显卡的Streaming Multiprocessor都得停下来等到改好再运转

场景中相同材质的物体有相同的参数、相同的纹理,那么将场景中的物体按照材质排序,只设置一次材质,绘制一个个Submesh,速度就会更快

比如像DX12、Vulkan会专门将GPU的状态设置专门抽象成一个Render State Object,对显卡状态先定义好,然后一次性做大量的运算

GPU Batch Rendering

很多子物体是一模一样的,那么依次设置VBIB (Vertex and Index Buffer Validation 顶点和索引缓冲区验证) 也很浪费,所以用计算着色器或者其他shader的能力,可以一个drawcall,设置依次VBIB,和它绘制的一堆位移的数据,就能一次性创建成百上千个物体

struct batchData
{SubmeshHandle m_submesh_handle;MaterialHandle m_material_handle;std::vector<PerInstanceData> p_instance_data;unsigned int m_instance_count;
}Initialize Resource Pools
Load ResourcesCollect batchData with same submesh and materialfor each BatchDataUpdate ParametersUpdate TexturesUpdate ShaderUpdate VertexBufferUpdate IndexBufferDraw Instance
end

将大量的绘制运算交给GPU而不是CPU,比如一次性要绘制几百米开外的树、草

Visibility Culling

大多数空间的物体、对象、粒子效果、地形等都不需要绘制

Visibility Culling是绘制系统一个最基础的系统

检测物体包围盒在不在视锥体

  • 包围盒

    • Sphere

    • AABB

      轴对称包围盒,轴是游戏世界中的坐标轴,那么只用存两个端点就能构建出一个AABB,计算效率仅次于Sphere包围盒

    • OBB

      贴着物体走

    • 8-DOP

    • Convex Hull

      凸包

  • 包围盒是很多计算的基础

    • intersection test消耗不高
    • Tight fitting
    • 计算开销小
    • 旋转和位移简单
    • 内存消耗小
  • Hierarchical View Frustum Culling

    • Quad Tree Culling

      四叉树Culling

    • BVH (Bounding Volume Hierarchy) Culling

      现代游戏引擎用得多,BVH效率不是最高的,但是因为动的物体多,重新构建层级结构快

    • PVS (Potential Visibility Set)

      一种思想,现在全面用PVS做Culling的游戏不多了,但是这种思想很有用,比如说线性单机游戏,在每个区域能看到区域是固定的,这样做除了Visibility Culling外还可以用作资源的加载

      在大世界中的应用可参考UE5的City Sample

      先用BSP-Tree

      先将空间分成一个个小方块,每个小方块通过一个Portal连接,在每个方块中通过Portal只能看到固定几个方块,比如图中在7号房间只能看到6、1、2、3四个房间,那么就只需要渲染这四个房间

      原理简单,但对空间的划分算法比较复杂

Texture Compression 纹理压缩

纹理压缩不能用图片上比较好的压缩方法,比如JEPG格式,因为不支持随机访问

纹理压缩一般采取的思想是Block-based,将图片切成一个个小块(比如\(4\times4\)),然后找其中颜色最亮的点和最暗的点,那么剩下的点就是这两个点的插值(因为很多图片相邻的像素都有关联),

于是就只能存一个最大值,一个最小值,然后每个像素存一个离最大值、最小值的比例关系,就能近似表达这个小色块的颜色,整个计算机图形学的纹理压缩都是基于这个思想的

  • PC

    • BC7 (modern)
    • DXTC (old)
  • mobile

    • ASTC (modern)

      分块可以不再是严格的\(4\times4\),而是任意形状,而且效果是最好的,解压缩的效率也不低,但是压缩的运算比较费性能,不能运行中进行压缩

    • ETC / PVRTC (old)

构建引擎时纹理压缩是非常重要的模块,而且加载到显卡中的基本上是压缩过的数据格式

Authoring Tools for Modeling

Comparison of Authoring Methods

  • Polymodeling
    • 灵活
    • 工作负担大
  • Sculpting
    • Creative
    • 大量volume of data
  • Scanning
    • Realistic
    • 大量volume of data
  • Procedural modeling
    • Intelligent
    • 难以实现

Cluster-Based Mesh Pipeline

将复杂模型分成一个个小的meshlet(比如32个三角形),每个meshlet固定后,计算是非常一致的、高效的

这样每个Instance都能并行化绘制

  • GPU-Driven Rendering Pipeline (2015)
    • Mesh Cluster Rendering
      • Arbitrary number of meshes in single drawcall
      • GPU-culled by cluster bounds
      • Cluster depth sorting
  • Geometry Rendering Pipeline Architecture (2021)
    • Rendering primitives are divided as:
      • Batch: a single API draw (drawIndirect / DrawIndexIndirect), composed of many Surfs
      • Surf: submeshes based on materials, composed of many Clusters
      • Cluster: 64 triangles strip

Programmable Mesh Pipeline

  • 游戏引擎与硬件结构涉及深度相关
  • submesh design被用于单个模型的多材质
  • 使用culling算法减少绘制物体
  • 将更多工作移至GPU (GPU-Driven)

Q&A

  • 图形代码的Debug
    • 不要一次性写完所以代码,每次写一部分,反复验证,没问题后再继续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/790539.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

样式及结构复用

本文来自博客园,作者:jialiangzai,转载请注明原文链接:https://www.cnblogs.com/zsnhweb/p/18391257

Lecture 02 Layered Architecture of Game Engine

Lecture 02 Layered Architecture of Game Engine 渲染只是游戏引擎中不大的一部分Tool Layer 工具层 这部分不是实时的,所有可以允许多种实现方法(C++/C#开发等等)DCC Digital Content Creation 将不同文件导入成AssetsFunction Layer 功能层每个tick依次做完所有内容 多线…

Lecture 03 How to build a Game World

Lecture 03 How to build a Game World Everything is a Game Object (GO)面向对象的方式 有些GO之间并没有清晰的继承关系Unreal中的UObject、Unity中的Object并不是这里讲的GameObject概念,而是更类似如C#中的Object,用于确定任何对象的生命周期需要的句柄 Unreal中的Game…

Lecture 13 Real-time Ray Tracing 2

Lecture 13 Real-Time Ray Tracing 2 Implementing a spatial filter 这里想做的是低通滤波移除高频信号会不会丢失高频中的信息? 噪声不一定只在高频中集中在频域 这些filtering可以应用在PCSS、SSR上的降噪用$$\widetilde C$$表示有noise的图像 \[K$$表示滤波核kernel,比如…

Lecture 10 11 Real-time Physically-based Materials (surface model)

Lecture 10 Real-time Physically-based Materials (surface models and cont.) PBR and PBR MaterialsPhysically-Based Rendering (PBR) 基于物理的渲染渲染内的任何事都应该是PBR的材质、光照、相机、光线传播等等不限于材质,但常常指材质PBR materials in RTR实时渲染中材…

[笔记]Tarjan

Tarjan求强连通分量 定义 DFS树相关 我们对一个有向联通图进行DFS遍历,会得到一棵DFS树。 DFS树的形态是根据我们DFS的顺序来决定的,因此对一个有向联通图来说,它的DFS树可能有多个。我们把这棵树的边称作树边。 其他边我们分为\(3\)类:前向边:从\(u\)到它dfs树上的祖先的…

Lecture 12 Real-time Ray Tracing

Lecture 12 Real-Time Ray Tracing Basic ideasample per pixel PPS 1 SPP path tracing = $$\downarrow$$camera出发打到求出第一个交点(像素上看到的点),这一步是primary ray(工业上实际用rasterization)工业上这一步有一个技巧 将这一步改为光栅化 因为每个像素都要从c…

gcc/g++编译ZR

编译工具链我们写程序的时候用的都是集成开发环境 (IDE: Integrated Development Environment),集成开发环境可以极大地方便我们程序员编写程序,但是配置起来也相对麻烦。在 Linux 环境下,我们用的是编译工具链,又叫软件开发工具包(SDK:Software Development Kit)。Linux 环…

一种优雅的方式整合限流、幂等、防盗刷

大家在工作中肯定遇到过接口被人狂刷的经历,就算没有经历过,在接口开发的过程中,我们也需要对那些容易被刷的接口或者和会消耗公司金钱相关的接口增加防盗刷功能。例如,发送短信接口以及发送邮件等接口,我看了国内很多产品的短信登录接口,基本上都是做了防盗刷,如果不做…

Lecture 06 Real-time Environment Mapping (Precomputed Radiance Transfer)

Lecture 06 Real-time Environment Mapping (Precomputed Radiance Transfer) Shadow from environment lighting通常情况下要实时渲染非常困难 在不同观察方向上As a many-light problem: Cost of Shadow Map is linearly to #light As a sampling problem: Visibility项V会变…

Lecture 07 Real-time Global Illumination (in 3D)

Lecture 07 Real-time Global Illumination (in 3D) 实时渲染中全局光照一般只bounce两次(直接光照bounce一次,间接光照bounce两次)primary light source 真正的光源secondary light source 次级光源: 一切被直接光照照到的物体都会继续将自己作为光源想要用间接光照照亮\(…

Lecture 04 Real-time Shadows 2

Lecture 04 Real-time Shadows 2 PCF and PCSS PCF背后的数学知识 Filter / convolution: 如果对某个函数\(f\)做卷积,可以用\([\omega * f](p)=\underset{q \in \Nu (p)}{\sum}w(p,q)f(q)\)比如PCSS中对某一点q周围区域做卷积求visibility \(V(x)=\underset{q\in \Nu(p)}{\su…