当前位置: 首页 > 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;打破了传统计算机程序的局限性。而低代码开发则以简化软件开发过程为目标&…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

ui框架-文件列表展示

ui框架-文件列表展示 介绍 UI框架的文件列表展示组件&#xff0c;可以展示文件夹&#xff0c;支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项&#xff0c;适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...