如何用WebGPU流畅渲染百万级2D物体?

本文介绍了如何使用WebGPU和光线追踪技术,从渲染500个2D物体到流畅渲染4百万个的过程。通过选择光追算法、优化内存占用、构建和优化BVH、启用局部单位等步骤,最终实现高性能的2D物体渲染。通过引入LBVH算法,构造时间显著缩短。文章详细探讨了各个优化阶段的技术细节和效果。
摘要由CSDN通过智能技术生成

🚀 优质资源分享 🚀

学习路线指引(点击解锁) 知识定位 人群定位
🧡 Python实战微信订餐小程序 🧡 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
💛Python量化交易实战💛 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

大家好~本文使用WebGPU和光线追踪算法,从0开始实现和逐步优化Demo,展示了从渲染500个2D物体都吃力到流畅渲染4百万个2D物体的优化过程和思路

目录* 需求

需求

我们对Demo提出下面的要求:

  • 渲染1百万个以上的2D物体时达到30FPS以上
    暂时只渲染一种2D物体:圆环
  • 内存占用小
  • 剔除被遮挡的物体
  • 放大物体时无锯齿,达到矢量渲染的效果

成果

我们最终能够流畅渲染4百万个圆环

性能指标:

  • 45 FPS左右,也就是每帧花费21毫秒
  • 内存占用211MB

下面让我们从0开始,介绍实现和优化的步骤:

1、选择渲染的算法

思考如何实现与渲染相关的需求

现在,我们来回顾下与渲染相关的需求,从而确定渲染算法:

放大物体时无锯齿,达到矢量渲染的效果

要实现该需求,可以用参数化的方法来表示物体,如用圆心坐标、半径、圆环宽度 来表示一个圆环;
然后可以根据下面的公式判断一个点是否在圆环上:

let distanceSquare = Math.pow((点-圆心坐标), 2)

let isPointInRing =  distanceSquare >= Math.pow(半径, 2) && distanceSquare <= Math.pow(半径 + 圆环宽度, 2)

因为圆环是2D的,是直接绘制在屏幕上的,所以这里的一个点就是屏幕上的一个像素

从上面的分析可知,通过“如果一个像素在圆环上则渲染”的逻辑,就可以实现需求

剔除被遮挡的物体

要实现该需求,首先圆环加上“层”的数据;
然后遍历所有圆环,判断像素在哪些圆环上;
最后取出最大“层”的圆环,将它的颜色作为像素的颜色

选择渲染的算法
有两种渲染算法可选择:光栅化渲染、光追渲染

根据我们之前对渲染需求的思考,我们应该选择光追渲染作为渲染算法

典型的光追渲染会依次执行下面两个pass:
1、光追pass
从相机向每个像素发射射线,经过多次射线弹射,计算每个像素的颜色
2、屏幕pass
将屏幕光栅化,渲染每个像素的颜色

其中光追pass是在CS(计算着色器)中进行,屏幕pass是在VS(顶点着色器)和FS(片元着色器)中进行

因为这里是2D物体,所以需要对光追算法做一些简化:
射线不需要弹射,因为不需要计算间接光照;
因为物体直接就在屏幕上,所以不需要计算射线与物体相交,而是按照参数化公式计算像素是否在2D物体上

2、实现内存需求

现在来考虑如何实现“内存占用小”的需求

这里只考虑CPU端内存,它主要存放了场景数据,包括圆环的transform、geometry、material的数据

我们使用ECS架构,将物体建模为gameObject+components
这里的components具体就是transform、geometry、material这些组件

按照Data Oriented的思想,每种组件就是一个ArrayBuffer,连续地存放组件数据(如transform buffer连续地存放圆环的localPositionX, localPostionY, layer(层)数据)

component为对应buffer中数据的索引

通过ECS的设计,我们就将场景数据都放在buffer中了。在初始化时,只根据最大的组件数量,创建一次对应的组件buffer。这样就实现了内存占用最小的目标

3、渲染1个圆环

现在来渲染出一个圆环,也不考虑剔除

我们依次实现下面两个pass:

光追pass

我们需要传入下面的场景数据到CS中,CS中对应的数据结构如下:

struct AccelerationStructure {
  worldMin : vec2,
 worldMax : vec2,

 instanceIndex: f32,
 pad\_0: f32,
 pad\_1: f32,
 pad\_2: f32,
}

struct Instance {
 geometryIndex: f32,
 materialIndex: f32,

 localPosition: vec2,
}


struct Geometry {
 c: vec2,
 w: f32,
 r: f32,
}

struct Material {
 color: vec3,
 pad\_0: f32,
}

 struct AccelerationStructures {
 accelerationStructures : array,
}

 struct Instances {
 instances : array,
}

 struct Geometrys {
 geometrys : array,
}

 struct Materials {
 materials : array,
}

 struct Pixels {
 pixels : array>
}

 struct ScreenDimension {
 resolution : vec2
}

@binding(0) @group(0) var sceneAccelerationStructure : AccelerationStructures;
@binding(1) @group(0) var sceneInstanceData : Instances;
@binding(2) @group(0) var sceneGeometryData : Geometrys;
@binding(3) @group(0) var sceneMaterialData : Materials;

@binding(4) @group(0) var pixelBuffer : Pixels;

@binding(5) @group(0) var screenDimension : ScreenDimension;
折叠 

struct中的pad用于对齐

sceneAccelerationStructure包含圆环的包围盒数据,作为加速相交检测的加速结构。其中worldMin、wor

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值