轻量封装WebGPU渲染系统示例<46>- 材质组装管线(MaterialPipeline)灯光、阴影、雾以及多Pass(源码)

当前示例源码github地址:

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

当前示例运行效果:

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

javascript 复制代码
export class MaterialPipelineMultiPasses {
	private mRscene = new RendererScene();
	initialize(): void {

		this.mRscene.initialize({
			canvasWith: 512,
			canvasHeight: 512,
			mtplEnabled: true,
			rpassparam:
			{
				multisampled: true
			}
		});
		this.initScene();
		this.initEvent();
	}

	private hdrEnvtex = new SpecularEnvBrnTexture();
	private createMaskTextures(ns: string, maskns = 'displacement_01.jpg'): WGTextureDataDescriptor[] {

		const albedoTex = { albedo: { url: `static/assets/pbr/${ns}/albedo.jpg` } };
		const normalTex = { normal: { url: `static/assets/pbr/${ns}/normal.jpg` } };
		const aoTex = { ao: { url: `static/assets/pbr/${ns}/ao.jpg` } };
		const roughnessTex = { roughness: { url: `static/assets/pbr/${ns}/roughness.jpg` } };
		const metallicTex = { metallic: { url: `static/assets/pbr/${ns}/metallic.jpg` } };
		// mask texture
		const opacityTex = { opacity: { url: `static/assets/${maskns}` } };

		let textures = [
			this.hdrEnvtex,
			albedoTex,
			normalTex,
			aoTex,
			roughnessTex,
			metallicTex,
			opacityTex
		] as WGTextureDataDescriptor[];
		return textures;
	}

	private createBaseTextures(): 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[];
		return textures;
	}

	private initScene(): void {

		let rc = this.mRscene;

		let mtpl = rc.renderer.mtpl;

		mtpl.light.data = createLightData([0, 300, 0], 600, 5.0);
		mtpl.shadow.param.intensity = 0.7;
		mtpl.fog.fogColor.value = [0.3, 0.7, 0.2];

		let position = [0, 50, 180];
		let materials = this.createMaterials(true);
		let sphere = new SphereEntity(
			{
				radius: 150.0,
				materials,
				transform: { position }
			}
		);
		rc.addEntity(sphere);

		position =  [0, 50, -180];
		materials = this.createMaterials(true, true, 'back', [4, 1]);
		let torus = new TorusEntity({
			axisType: 1,
			materials,
			transform: { position }
		});
		rc.addEntity(torus);

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

		position = [0, 0, 0];
		materials = this.createMaterials(false, false, 'front', [2, 2]);
		let envBox = new CubeEntity(
			{
				cubeSize: 2050.0,
				normalScale: -1.0,
				materials,
				transform: { position }
			}
		);
		rc.addEntity(envBox);

	}
	private createMaterials(shadowReceived = false, shadow = true, faceCullMode = 'back', uvParam?: number[]): BaseMaterial[] {
		let textures0 = this.createBaseTextures();
		let textures1 = this.createMaskTextures("plastic");
		let textures2 = this.createMaskTextures("wall", 'circleWave_disp.png');

		let material0 = this.createMaterial(textures0, ["solid"], 'less', faceCullMode);
		this.applyMaterialPPt(material0, shadowReceived, shadow);

		let material1 = this.createMaterial(textures1, ["transparent"], 'less-equal', faceCullMode);
		material1.property.inverseMask = false;
		this.applyMaterialPPt(material1, shadowReceived, shadow);

		let material2 = this.createMaterial(textures2, ["transparent"], 'less-equal', faceCullMode);
		material2.property.inverseMask = true;
		this.applyMaterialPPt(material2, shadowReceived, shadow);
		let list = [material0, material1, material2];

		// let list = [material0, material1];
		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.0, 0.2, 0.2];
		ppt.albedo.value = [0.7, 0.7, 0.3];
		ppt.arms.roughness = 0.8;
		ppt.armsBase.value = [0, 0, 0];
		ppt.param.scatterIntensity = 32;
		
		ppt.shadow = shadow;
		ppt.lighting = true;

		ppt.shadowReceived = shadowReceived;
		ppt.exp2Fogging = true;
	}
	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();
	}
}
相关推荐
雨田哥2 天前
3D 数字人的成长养成记
3d·数字人·3d数字人·陪伴·数伴·成长养成·3d数伴
天空之城--2 天前
Claude Code 高效开发 Web 2D/3D 完全指南:心法、自定义 Skill 体系与社区技能包实战
前端·3d
清风笑烟语3 天前
rustfs 集群部署
3d
还是大剑师兰特3 天前
Unity 从零搭建简易3D场景(新手分步教程)
3d·unity·游戏引擎
EQ-雪梨蛋花汤3 天前
Android 3D 开发教程(三):Sceneform-EQR 配置 PBR 材质、光照、相机与实时阴影
android·3d·材质
弈语道破AI3 天前
3D渲染不再熬时间!即梦 Seedance 2.5 具备3D白模渲染功能的AI视频生成工具
人工智能·3d·音视频
答案—answer3 天前
VibeCoding 能做到什么程度?我用它做了一座 3D 数字博物馆
3d·ai编程·threejs·vibecoding
3D小将3 天前
3D格式转换之PROE转换为IGS格式技术
3d·格式转换·stl模型·stp模型·迪威模型网
玖玥拾4 天前
Unity3D RPG 入门项目(四)背包拖拽、物品悬浮提示、项目开发思维
3d·unity·游戏引擎
cyadyx5 天前
【Three.js】Three.js 中加载 3D 模型
前端·javascript·3d