轻量封装WebGPU渲染系统示例<51>- 视差贴图(Parallax Map)(源码)

news2024/11/27 1:32:40

视差纹理是一种片段着色阶段增强材质表面凹凸细节的技术。

当前示例源码github地址:

https://github.com/vilyLei/voxwebgpu/blob/feature/material/src/voxgpu/sample/ParallaxTexTest.ts

当前示例运行效果:

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

export class ParallaxTexTest {
	private mRscene = new RendererScene();
	initialize(): void {
		console.log("ParallaxTexTest::initialize() ...");
		this.loadImg();
	}
	initSys(): void {

		this.mRscene.initialize({
			canvasWith: 512,
			canvasHeight: 512,
			mtplEnabled: true,
			rpassparam:
			{
				multisampled: true
			}
		});
		this.initScene();
		this.initEvent();
	}
	private mPixels: Uint8ClampedArray;
	private mPixelsW = 128;
	private mPixelsH = 128;
	getRandomColor(s?: number): ColorDataType {
		if (s === undefined) {
			s = 1.0;
		}
		let i = 5;
		let j = Math.floor(Math.random() * this.mPixelsW);
		let k = i * this.mPixelsW + j;
		let vs = this.mPixels;
		k *= 4;
		let cs = [s * vs[k] / 255.0, s * vs[k + 1] / 255.0, s * vs[k + 2] / 255.0];
		return cs;
	}
	private loadImg(): void {
		let img = new Image();
		img.onload = evt => {
			this.mPixelsW = img.width;
			this.mPixelsH = img.height;
			let canvas = document.createElement("canvas");
			canvas.width = img.width;
			canvas.height = img.height;
			let ctx = canvas.getContext('2d');
			ctx.drawImage(img, 0, 0);
			this.mPixels = ctx.getImageData(0, 0, img.width, img.height).data;
			this.initSys();
		}
		img.src = 'static/assets/colorPalette.jpg';
	}
	private mLightData: MtLightDataDescriptor;
	private createLightData(): MtLightDataDescriptor {
		let ld = { pointLights: [], directionLights: [], spotLights: [] } as MtLightDataDescriptor;

		let total = 5;
		let scale = 3.0;
		for (let i = 0; i < total; ++i) {
			for (let j = 0; j < total; ++j) {
				let position = [-500 + 250 * j, 290 + Math.random() * 30, -500 + 250 * i];
				position[0] += Math.random() * 60 - 30;
				position[2] += Math.random() * 60 - 30;
				let color = this.getRandomColor(scale);
				let factor1 = 0.00001;
				let factor2 = 0.00002;
				let pLight = new PointLight({ color, position, factor1, factor2 });
				ld.pointLights.push(pLight);
				if (Math.random() > 0.5) {
					position = [-500 + 150 * j, 290 + Math.random() * 50, -500 + 150 * i];
					position[0] += Math.random() * 160 - 80;
					position[2] += Math.random() * 160 - 80;
					color = this.getRandomColor(scale);
					let direction = [(Math.random() - 0.5) * 8, -1, (Math.random() - 0.5) * 8];
					let degree = Math.random() * 10 + 5;
					let spLight = new SpotLight({ position, color, direction, degree, factor1, factor2 });
					ld.spotLights.push(spLight);
				}
			}
		}
		let dLight = new DirectionLight({ color: [0.5, 0.5, 0.5], direction: [-1, -1, 0] });
		ld.directionLights.push(dLight);
		return ld;
	}
	private createBillboard(pv: Vector3DataType, c: ColorDataType, type: number): void {
		let rc = this.mRscene;
		let diffuseTex0 = { diffuse: { url: "static/assets/flare_core_03.jpg" } };
		if (type > 1) {
			diffuseTex0 = { diffuse: { url: "static/assets/circleWave_disp.png" } };
		}
		let billboard = new BillboardEntity({ size: 10, textures: [diffuseTex0] });
		billboard.color = c;
		billboard.alpha = 1;
		billboard.transform.setPosition(pv);
		rc.addEntity(billboard);
	}
	private createBillboards(): void {
		let lightData = this.mLightData;
		let pls = lightData.pointLights;
		for (let i = 0; i < pls.length; i++) {
			let lp = pls[i];
			this.createBillboard(lp.position, lp.color, 1);
		}
		let spls = lightData.spotLights;
		for (let i = 0; i < spls.length; i++) {
			let lp = spls[i];
			this.createBillboard(lp.position, lp.color, 2);
		}
	}
	private initScene(): void {

		let rc = this.mRscene;

		let mtpl = rc.renderer.mtpl;

		this.mLightData = this.createLightData();

		mtpl.light.lightData = this.mLightData;
		mtpl.shadow.param.intensity = 0.4;
		mtpl.shadow.param.radius = 4;

		let position = [-30, 220, -50];
		let materials = this.createMaterials(true);

		let sphere: SphereEntity;
		let total = 3;
		let py = 150;
		for (let i = 0; i < total; ++i) {
			for (let j = 0; j < total; ++j) {
				if (total > 2) {
					position = [-350 + 350 * j, py, -350 + 350 * i];
				} else {
					position = [0, py, 0];
				}
				let rotation = [0, Math.random() * 360, 0];
				let materials = this.createMaterials(true);
				if (sphere) {
					let sph = new SphereEntity(
						{
							geometry: sphere.geometry,
							materials,
							transform: { position, rotation }
						}
					);
					rc.addEntity(sph);
				} else {
					sphere = new SphereEntity(
						{
							radius: 110.0,
							materials,
							transform: { position, rotation }
						}
					);
					rc.addEntity(sphere);
				}
			}
		}

		position = [0, 0, 0];
		materials = this.createMaterials(true, false, 'back');
		let plane = new PlaneEntity({
			axisType: 1,
			materials,
			extent: [-600, -600, 1200, 1200],
			transform: { position }
		});
		rc.addEntity(plane);

		this.createBillboards();

	}
	
	private createArmTextures(): 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` } };
		const parallaxTex = { parallax: { url: `static/assets/pbrtex/rough_plaster_broken_disp_1k.jpg` } };
		let envTex = { specularEnv: {} };
		let textures = [
			envTex,
			albedoTex,
			normalTex,
			armTex,
			parallaxTex
		] as WGTextureDataDescriptor[];
		return textures;
	}
	private createMaterials(shadowReceived = false, shadow = true, faceCullMode = 'back', uvParam?: number[]): BaseMaterial[] {

		let textures0 = this.createArmTextures();

		let material0 = this.createMaterial(textures0, ["solid"], 'less', faceCullMode);
		this.applyMaterialPPt(material0, shadowReceived, shadow);
		let list = [material0];
		if (uvParam) {
			for (let i = 0; i < list.length; ++i) {
				list[i].property.uvParam.value = uvParam;
			}
		}
		return list;
	}

	private applyMaterialPPt(material: BaseMaterial, shadowReceived = false, shadow = true): void {
		let ppt = material.property;
		ppt.ambient.value = [0.2, 0.2, 0.2];
		ppt.albedo.value = this.getRandomColor(1.0);
		ppt.arms.roughness = Math.random() * 0.95 + 0.05;
		ppt.arms.metallic = 0.2;
		ppt.armsBase.value = [0, 1.0, 0];
		ppt.specularFactor.value = [0.1, 0.1, 0.1];

		ppt.shadow = shadow;
		ppt.lighting = true;

		ppt.shadowReceived = shadowReceived;
	}
	private createMaterial(textures: WGTextureDataDescriptor[], blendModes: string[], depthCompare = 'less', faceCullMode = 'back'): BaseMaterial {

		let pipelineDefParam = {
			depthWriteEnabled: true,
			faceCullMode,
			blendModes,
			depthCompare
		};
		let material = new BaseMaterial({ pipelineDefParam });
		material.addTextures(textures);
		return material;
	}
	private initEvent(): void {
		const rc = this.mRscene;
		rc.addEventListener(MouseEvent.MOUSE_DOWN, this.mouseDown);
		new MouseInteraction().initialize(rc, 0, false).setAutoRunning(true);
	}
	private mouseDown = (evt: MouseEvent): void => { };
	run(): void {
		this.mRscene.run();
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring之容器:IOC(2)

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

Docker实战案例研究:深入行业应用与最佳实践

Docker作为一种轻量级、可移植、可扩展的容器化技术&#xff0c;在各行各业都得到了广泛应用。本文将通过深入实际案例&#xff0c;介绍Docker在不同行业的应用以及相应的最佳实践&#xff0c;提供更加丰富的示例代码&#xff0c;以帮助大家更全面地理解和运用Docker的强大功能…

C#浅拷贝和深拷贝数据

目录 一、浅拷贝 二、深拷贝 一、浅拷贝 就是把原来的数据&#xff0c;复制一份&#xff0c;但是2份数据是共享地址的&#xff0c;修改第一份数据或者修改第二份数据&#xff0c;都会一起改变&#xff0c;这可能不是我们程序中需要的场景。 下面我们演示一下&#xff0c;首…

使用Halcon实现模板匹配

图片: 代码: read_image (Image, C:/Users/14348/Desktop/mobanpipei.jpg) get_image_size (Image, Width, Height) dev_close_window() dev_open_window (0, 0, Width, Height, black, WindowHandle) dev_display (Image) draw_rectangle1 (WindowHandle, Row1, Column1, Ro…

TrustZone之其他设备及可信基础系统架构

一、其他设备 最后,我们将查看系统中的其他设备,如下图所示: 我们的示例TrustZone启用的系统包括一些尚未涵盖的设备,但我们需要这些设备来构建一个实际的系统。 • 一次性可编程存储器(OTP)或保险丝 这些是一旦写入就无法更改的存储器。与每个芯片上都包含相同…

CountDownLatch实战应用——实现异步多线程业务处理,异常情况回滚全部子线程

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; CountDownLatch实战应用——实现异步多线程业务处理&#xff0c;异常情…

单片机期末复习

前言 发现很多人都写了单片机原理及接口技术课后习题的答案&#xff0c;但是也就只写了答案而已&#xff0c;可能是他们觉得太简单的缘故吧&#xff0c;我这里对此进行一下我近段时间复习的总结&#xff0c;本篇博客只展示选择题、填空题和判断题的答案&#xff0c;仅供参考&a…

MFC 程序执行流程

目录 MFC 程序启动 MFC 入口函数 程序执行流程总结 在Win32课程中WinMain由程序员自己实现&#xff0c;那么流程是程序员安排&#xff0c;但到了MFC中&#xff0c;由于MFC库实现WinMain&#xff0c;也就意味着MFC负责安排程序的流程。 MFC 程序启动 程序的启动&#xff0c;…

【JAVA】CyclicBarrier源码解析以及示例

文章目录 前言CyclicBarrier源码解析以及示例主要成员变量核心方法 应用场景任务分解与合并应用示例 并行计算应用示例 游戏开发应用示例输出结果 数据加载应用示例 并发工具的协同应用示例 CyclicBarrier和CountDownLatch的区别循环性&#xff1a;计数器的变化&#xff1a;用途…

神经网络可以计算任何函数的可视化证明

神经网络可以计算任何函数的可视化证明 对于神经网络&#xff0c;一个显著的事实就是它可以计算任何函数。 如下&#xff1a;不管该函数如何&#xff0c;总有神经网络能够对任何可能的输入x&#xff0c;输出值f&#xff08;x&#xff09; 即使函数有很多输入和输出&#xff0…

【每日一题】【12.17】746.使用最小花费爬楼梯

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_ 1.题目链接 746. 使用最小花费爬楼梯https://leetcode.cn/problems/min-cost-climbing-stairs/ 2.题目详情 今天的每日一题又…

leetcode每日一题打卡

leetcode每日一题 746.使用最小花费爬楼梯162.寻找峰值 从2023年12月17日开始打卡~持续更新 746.使用最小花费爬楼梯 2023/12/17 代码 解法一 class Solution {public int minCostClimbingStairs(int[] cost) {int n cost.length;int[] dp new int[n1];dp[0] 0;dp[1] 0;…

RocketMQ系统性学习-SpringCloud Alibaba集成RocketMQ以及批量发送消息、消息过滤实战

文章目录 批量发送消息消息过滤 批量发送消息 批量发送消息可以减少网络的 IO 开销&#xff0c;让多个消息通过 1 次网络开销就可以发送&#xff0c;提升数据发送的吞吐量 虽然批量发送消息可以减少网络 IO 开销&#xff0c;但是一次也不能发送太多消息 批量消息直接将多个消…

结构型设计模式(二)装饰器模式 适配器模式

装饰器模式 Decorator 1、什么是装饰器模式 装饰器模式允许通过将对象放入特殊的包装对象中来为原始对象添加新的行为。这种模式是一种结构型模式&#xff0c;因为它通过改变结构来改变被装饰对象的行为。它涉及到一组装饰器类&#xff0c;这些类用来包装具体组件。 2、为什…

将mjpg格式数转化成opencv Mat格式

该博客可以解决如下两个问题&#xff1a; 1、将mjpg格式数据转化成opencv Mat格式 2、v4l2_buffer 格式获取的mjpg格式数据转换成Mat格式。 要将 MJPEG 格式的数据转换为 OpenCV 的 Mat 格式&#xff0c;您可以使用 imdecode 函数。imdecode 函数可以将图像数据解码为 Mat 对象…

【MySQL】数据库和表的操作

数据库和表的操作 一、数据库的操作1. 创建数据库2. 字符集和校验规则&#xff08;1&#xff09;查看系统默认字符集以及校验规则&#xff08;2&#xff09;查看数据库支持的字符集&#xff08;3&#xff09;查看数据库支持的字符集校验规则&#xff08;4&#xff09;校验规则对…

B01、JVM与Java体系结构-01

字节码与多语言混合编程 字节码概述&#xff1a; 我们平时说的java字节码&#xff0c;指的是用java语言编译成的字节码。准确的说任何能在jvm平台上执行的字节码格式都是一样的。所以应该统称为&#xff1a;jvm字节码。不同的编译器&#xff0c;可以编译出相同的字节码文件&…

05 动态渲染数据

概述 实际上动态渲染数据&#xff0c;在《使用CDN开发Vue3项目》中就已经学习过了&#xff0c;核心代码如下&#xff1a; <div id"vue-app">{{text}}</div> <script src"https://cdn.staticfile.org/vue/3.0.5/vue.global.js"></sc…

jsp属性访问控制管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

背景&#xff1a;为了解决共享数据授权访问的管理问题&#xff0c;出现了早期的自主访问控制&#xff08;Discretionary Access Control&#xff0c;DAC&#xff09;和强制访问控制&#xff08;Mandatory Access Control&#xff0c;MAC&#xff09;&#xff0c;随着计算机和技…

STM32F103RCT6开发板M3单片机教程06--定时器中断

前言 除非特别说明&#xff0c;本章节描述的模块应用于整个STM32F103xx微控制器系列&#xff0c;因为我们使用是STM32F103RCT6开发板是mini最小系统板。本教程使用是&#xff08;光明谷SUN_STM32mini开发板&#xff09; STM32F10X定时器(Timer)基础 首先了解一下是STM32F10X…