当前位置: 首页 > news >正文

轻量封装WebGPU渲染系统示例<43>- PBR材质与阴影实(源码)

原理简介:

        1. 基于rendering pass graph实现。

        2. WGSL Shader 基于文件系统和宏机制动态组装。

当前示例源码github地址:

https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/PBRShadowTest.ts

当前示例运行效果:

此示例基于此渲染系统实现,当前示例TypeScript源码如下:

class ShadowPassGraph extends WGRPassNodeGraph {private entities: Entity3D[] = [];private mDepthMaterials: WGMaterial[];shadowDepthRTT = { uuid: "rtt-shadow-depth", rttTexture: {}, shdVarName: 'shadowData' };depAttachment: WGRPassColorAttachment = {texture: this.shadowDepthRTT,clearValue: { r: 1, g: 1, b: 1, a: 1.0 },loadOp: "clear",storeOp: "store"};occVRTT = { uuid: "rtt-shadow-occV", rttTexture: {}, shdVarName: 'shadowData' };occHRTT = { uuid: "rtt-shadow-occH", rttTexture: {}, shdVarName: 'shadowData' };occVEntity: FixScreenPlaneEntity;occHEntity: FixScreenPlaneEntity;shadowBias = -0.0005;shadowRadius = 2.0;shadowMapW = 512;shadowMapH = 512;shadowViewW = 1300;shadowViewH = 1300;shadowCamera: Camera;constructor() {super();}private initMaterial(): void {const shadowDepthShdSrc = {shaderSrc: { code: shadowDepthWGSL, uuid: "shadowDepthShdSrc" }};this.mDepthMaterials = [this.createDepthMaterial(shadowDepthShdSrc)];}private createDepthMaterial(shaderSrc: WGRShderSrcType, faceCullMode = "none"): WGMaterial {let pipelineDefParam = {depthWriteEnabled: true,faceCullMode,blendModes: [] as string[]};const material = new WGMaterial({shadinguuid: "shadow-depth_material",shaderSrc,pipelineDefParam});return material;}private buildShadowCam(): void {const g = this;const cam = new Camera({eye: [600.0, 800.0, -600.0],near: 0.1,far: 1900,perspective: false,viewWidth: g.shadowViewW,viewHeight: g.shadowViewH});cam.update();g.shadowCamera = cam;}addEntity(entity: Entity3D): ShadowPassGraph {let pass = this.passes[0];let et = new Entity3D({ transform: entity.transform });et.materials = this.mDepthMaterials;et.geometry = entity.geometry;et.rstate.copyFrom(entity.rstate);this.entities.push(et);pass.addEntity(et);return this;}addEntities(entities: Entity3D[]): ShadowPassGraph {let es = entities;for (let i = 0; i < es.length; ++i) {this.addEntity(es[i]);}return this;}initialize(rc: RendererScene): ShadowPassGraph {let colorAttachments = [this.depAttachment];// create a separate rtt rendering passlet multisampleEnabled = false;let pass = rc.createRTTPass({ colorAttachments, multisampleEnabled });this.passes = [pass];rc.setPassNodeGraph(this);this.buildShadowCam();pass.node.camera = this.shadowCamera;this.initMaterial();this.initocc();return this;}private initocc(): void {let pass = this.passes[0];let extent = [-1, -1, 2, 2];let material = new ShadowOccBlurMaterial();let ppt = material.property;ppt.setShadowRadius(this.shadowRadius);ppt.setViewSize(this.shadowMapW, this.shadowMapH);material.addTextures([this.shadowDepthRTT]);this.occVEntity = new FixScreenPlaneEntity({ extent, materials: [material] });this.occVEntity.visible = false;pass.addEntity(this.occVEntity);material = new ShadowOccBlurMaterial();ppt = material.property;ppt.setShadowRadius(this.shadowRadius);ppt.setViewSize(this.shadowMapW, this.shadowMapH);ppt.toHorizonalBlur();material.addTextures([this.occVRTT]);this.occHEntity = new FixScreenPlaneEntity({ extent, materials: [material] });this.occHEntity.visible = false;pass.addEntity(this.occHEntity);}run(): void {let pass = this.passes[0];let attachment = this.depAttachment;attachment.texture = this.shadowDepthRTT;let es = this.entities;for (let i = 0; i < es.length; ++i) {es[i].visible = true;}pass.render();for (let i = 0; i < es.length; ++i) {es[i].visible = false;}attachment.texture = this.occVRTT;this.occVEntity.visible = true;pass.render();this.occVEntity.visible = false;attachment.texture = this.occHRTT;this.occHEntity.visible = true;pass.render();this.occHEntity.visible = false;}
}
export class PBRShadowTest {private mRscene = new RendererScene();private mGraph = new ShadowPassGraph();initialize(): void {this.mRscene.initialize({canvasWith: 512,canvasHeight: 512,rpassparam: { multisampleEnabled: true }});this.initShadowScene();this.initEvent();}private mEntities: Entity3D[] = [];private initShadowScene(): void {let rc = this.mRscene;let position = [-230.0, 100.0, -200.0];let materials = this.createMaterials(position);let sph = new SphereEntity({radius: 80,transform: {position},materials});this.mEntities.push(sph);rc.addEntity(sph);position = [160.0, 100.0, -210.0];materials = this.createMaterials(position);let box = new BoxEntity({minPos: [-30, -30, -30],maxPos: [130, 230, 80],transform: {position,rotation: [50, 130, 80]},materials});this.mEntities.push(box);rc.addEntity(box);position = [160.0, 100.0, 210.0];materials = this.createMaterials(position);let torus = new TorusEntity({transform: {position,rotation: [50, 30, 80]},materials});this.mEntities.push(torus);rc.addEntity(torus);this.buildShadow();}private buildShadow(): void {this.initShadowPass();this.initShadowReceiveDisp(true);this.buildShadowCamFrame();}private mShadowTransMat: Matrix4;private initShadowPass(): void {let rc = this.mRscene;const graph = this.mGraph;graph.initialize(rc).addEntities(this.mEntities);let cam = graph.shadowCamera;let transMatrix = new Matrix4();transMatrix.setScaleXYZ(0.5, -0.5, 0.5);transMatrix.setTranslationXYZ(0.5, 0.5, 0.5);let shadowMat = new Matrix4();shadowMat.copyFrom(cam.viewProjMatrix);shadowMat.append(transMatrix);this.mShadowTransMat = shadowMat;let extent = [-0.95, -0.95, 0.4, 0.4];let entity = new FixScreenPlaneEntity({ extent, flipY: true, textures: [{ diffuse: graph.shadowDepthRTT }] });rc.addEntity(entity);extent = [-0.5, -0.95, 0.4, 0.4];entity = new FixScreenPlaneEntity({ extent, flipY: true, textures: [{ diffuse: graph.occVRTT }] });rc.addEntity(entity);extent = [-0.05, -0.95, 0.4, 0.4];entity = new FixScreenPlaneEntity({ extent, flipY: true, textures: [{ diffuse: graph.occHRTT }] });rc.addEntity(entity);}private buildShadowCamFrame(): void {const graph = this.mGraph;const cam = graph.shadowCamera;const rsc = this.mRscene;let frameColors = [[1.0, 0.0, 1.0], [0.0, 1.0, 1.0], [1.0, 0.0, 0.0], [0.0, 1.0, 1.0]];let boxFrame = new BoundsFrameEntity({ vertices8: cam.frustum.vertices, frameColors });rsc.addEntity(boxFrame);}private initEvent(): void {const rc = this.mRscene;rc.addEventListener(MouseEvent.MOUSE_DOWN, this.mouseDown);new MouseInteraction().initialize(rc, 0, false).setAutoRunning(true);}private initShadowReceiveDisp(shadowReceived = false): void {let rc = this.mRscene;let position = new Vector3(0, -1, 0);let materials = this.createMaterials(position, shadowReceived);let plane = new PlaneEntity({axisType: 1,materials,extent:[-600,-600,1200,1200],transform: { position }});rc.addEntity(plane);}private hdrEnvtex = new SpecularEnvBrnTexture();private createBaseTextures(shadowReceived = false): WGTextureDataDescriptor[] {const albedoTex = { albedo: { url: `static/assets/pbrtex/rough_plaster_broken_diff_1k.jpg` } };const normalTex = { normal: { url: `static/assets/pbrtex/rough_plaster_broken_nor_1k.jpg` } };const armTex = { arm: { url: `static/assets/pbrtex/rough_plaster_broken_arm_1k.jpg` } };let textures = [this.hdrEnvtex,albedoTex,normalTex,armTex] as WGTextureDataDescriptor[];if(shadowReceived) {textures.push( this.mGraph.occHRTT );}return textures;}private createMaterials(position: Vector3DataType, shadowReceived = false, uvParam?: number[]): BasePBRMaterial[] {let textures0 = this.createBaseTextures(shadowReceived);let material0 = this.createMaterial(position, textures0, ["solid"]);this.applyMaterialPPt(material0, shadowReceived);let list = [material0];if (uvParam) {for (let i = 0; i < list.length; ++i) {list[i].property.uvParam.value = uvParam;}}return list;}private applyMaterialPPt(material: BasePBRMaterial, shadowReceived = false): void {let property = material.property;property.ambient.value = [0.0, 0.2, 0.2];property.albedo.value = [0.7, 0.7, 0.3];property.arms.roughness = 0.8;property.armsBase.value = [0, 0, 0];property.param.scatterIntensity = 32;const graph = this.mGraph;let cam = graph.shadowCamera;property.shadowReceived = shadowReceived;if(shadowReceived) {property.shadowMatrix.shadowMatrix = this.mShadowTransMat;let vsmParams = property.vsmParams;vsmParams.radius = graph.shadowRadius;vsmParams.bias = graph.shadowBias;vsmParams.setSize(graph.shadowMapW, graph.shadowMapH);vsmParams.direction = cam.nv;vsmParams.intensity = 0.5;}}private mLightParams: LightShaderDataParam[] = [];private createMaterial(position: Vector3DataType, textures: WGTextureDataDescriptor[], blendModes: string[], depthCompare = 'less', lightParam?: LightShaderDataParam): BasePBRMaterial {if (!lightParam) {lightParam = createLightData(position);this.mLightParams.push(lightParam);}let pipelineDefParam = {depthWriteEnabled: true,faceCullMode: 'back',blendModes,depthCompare};let material = new BasePBRMaterial({ pipelineDefParam });material.setLightParam(lightParam);material.addTextures(textures);return material;}private mouseDown = (evt: MouseEvent): void => {};run(): void {this.mRscene.run();}
}

相关文章:

轻量封装WebGPU渲染系统示例<43>- PBR材质与阴影实(源码)

原理简介: 1. 基于rendering pass graph实现。 2. WGSL Shader 基于文件系统和宏机制动态组装。 当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/PBRShadowTest.ts 当前示例运行效果: 此示例基于此渲染系统实现&a…...

macOS Big Sur/Mac电脑安装vscode显示您没有权限来打开应用程序‘Visual Studio Code‘ 请联系您的电脑或网络管理员问题修复

错误方法 首先我以为我的权限不足。&#xff0c;需要去用户群组里设置。结果根本不是这个的问题。 1.在系统偏好设置->用户与群组检查了一下我的用户是不是管理员 结果发现是管理员 2.根据苹果提示&#xff0c;右键我的文件夹->显示简介->最下面的共享与权限 解锁&…...

jsp 如何批量改随机人名

对比图 <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%> <%page import"java.sql.ResultSet"%> <%page import"java.sql.PreparedStatement"%> <%page import&qu…...

android项目实战之编辑器集成

引言 项目需要用到编辑器&#xff0c;采用RichEditor&#xff0c;如下效果 实现 1. 引入库2 implementation jp.wasabeef:richeditor-android:2.0.0 2. XML <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width&q…...

JAVA程序如何打jar和war问题解决

背景: 近期研究一个代码审计工具 需要jar包 jar太多了 可以将jar 打成war包 首先看下程序目录结构 pom.xml文件内容 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"ht…...

Microsoft 365 Copilot正式上线,如何稳定访问体验?

如果将微软对人工智能的投资看成一场豪赌&#xff0c;Microsoft Copilot无疑是现阶段最受瞩目的赌注。2023年9月正式发布的Microsoft Copilot是一种基于大型语言模型&#xff08;LLM&#xff09;和微软图形&#xff08;Microsoft Graph&#xff09;的数据和人工智能&#xff08…...

【安卓】安卓xTS之Media模块 学习笔记(3) VTS测试

1. 背景 接下来进行正式的VTS测试。本章节还是以Media模块相关进行介绍。 VTS主要测的是内核和HAL层&#xff0c;media的hal层是以openMax&#xff08;即将废弃&#xff0c;今日2023.12&#xff09; 和 Codec2 (后续主流) 接口为主。 这里我们只看Codec2的要求&#xff0c;CDD…...

Go实现http同步文件操作 - 增删改查

http同步文件操作 - 增删改查 http同步文件操作 - 增删改查1. 前置要求1.1. 构建结构体 文件名 文件内容1.1.1. 页面结构体1.1.2. 为Page结构体绑定方法&#xff1a;Save1.1.3. 对Page结构体支持页面内容查看方法&#xff0c;同时提供页面文件是否存在的方法 1.2. 简单验证上面…...

Spring Boot整合 Spring Security

Spring Boot整合 1、RBAC 权限模型 RBAC模型&#xff08;Role-Based Access Control&#xff1a;基于角色的访问控制&#xff09; 在RBAC模型里面&#xff0c;有3个基础组成部分&#xff0c;分别是&#xff1a;用户、角色和权限&#xff0c;它们之间的关系如下图所示 SELECT…...

浅谈低代码

低代码开发是近年来迅速崛起的软件开发方法&#xff0c;让编写应用程序变得更快、更简单。有人说它是美味的膳食&#xff0c;让开发过程高效而满足&#xff0c;但也有人质疑它是垃圾食品&#xff0c;缺乏定制性与深度。你认为低代码到底是美以下方向仅供参考。味的膳食还是垃圾…...

Innodb-ruby深入探索Innodb存储结构

达在之前已经分享过Innodb数据存储结构知识&#xff0c;但是都是基于理论原理知识理解&#xff0c;今天利用Innodb文件解析工具ruby进行探索Innodb真实的存储结构。 索引原理过程&#xff1a;【Mysql】 InnoDB引擎深入 - 数据页 | 聚集索引_innodb的聚集索引的数据插入_Surviv…...

Echarts的使用 笔记

1.数据可视化前言 1.1.什么是数据可视化 数据可视化&#xff1a; 就是把数据以更加直观的方式进行呈现. 1.2.数据可视化的好处 清晰有效地传达与沟通信息更容易洞察隐藏在数据中的信息 2.ECharts的基本使用 2.1.ECharts官网 ECharts是百度公司开源的一个使用 JavaScript 实…...

信息系统工程的基本概念

系统是由相互作用和相互依赖的若干部分&#xff0c;按一定规律结合成的、具有特定功能的有机整体。系统有下述特性&#xff1a; &#xff08;1&#xff09;集合性。系统是由许多元素有机地组成的整体。每个元素服从整体&#xff0c;追求全局最优。 &#xff08;2&#xff09;相…...

SAP UI5 walkthrough step10 Descriptor for Applications

在这一步&#xff0c;我们将会把所有的应用相关的描述性的文件独立放到manifest.json 新建一个manifest.json文件 webapp/manifest.json (New) {"_version": "1.58.0","sap.app": {"id": "ui5.walkthrough","i18n&q…...

打造专属小程序,乔拓云模板平台助力商家抢占先机

打造专属小程序&#xff0c;乔拓云模板平台助力商家抢占先机&#xff01;该平台涵盖全行业小程序模板&#xff0c;一键复制即可上线。 想要快速创建高效实用的小程序&#xff0c;乔拓云小程序模板开发平台为您提供了解决方案&#xff01;我们为您提供一系列精心设计的小程序模板…...

Vue2学习(组件的使用)

Vue中使用组件的三个步骤&#xff1a; 一、定义组件(或者叫创建组件) 使用Vue.extend(options)创建&#xff0c;其中options和new Vue(options)时传入的那个options几乎一样&#xff0c;但也有点区别&#xff1b; 区别如下&#xff1a; 1.el不要写&#xff0c;为什么&#x…...

基于Spring、SpringMVC、MyBatis开发的游乐场管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于Spring、SpringMVC、MyBatis开发的游…...

数据清洗、特征工程和数据可视化、数据挖掘与建模的应用场景

1.5 数据清洗、特征工程和数据可视化、挖掘建模的应用场景 视频为《Python数据科学应用从入门到精通》张甜 杨维忠 清华大学出版社一书的随书赠送视频讲解1.5节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。内容涵盖数据科学应…...

Qt简介、工程文件分离、创建Qt工程、Qt的帮助文档

QT 简介 core&#xff1a;核心模块&#xff0c;非图形的接口类&#xff0c;为其它模块提供支持 gui&#xff1a;图形用户接口&#xff0c;qt5之前 widgets&#xff1a;图形界面相关的类模块 qt5之后的 database&#xff1a;数据库模块 network&#xff1a;网络模块 QT 特性 开…...

机器学习与低代码开发:创新驱动的双剑合璧

引言 随着科技的日新月异&#xff0c;机器学习和低代码开发已经成为引领技术行业变革的两大重要趋势。机器学习通过模拟人类的学习方式&#xff0c;让计算机具备了自我学习和预测的能力&#xff0c;打破了传统计算机程序的局限性。而低代码开发则以简化软件开发过程为目标&…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...