轻量封装WebGPU渲染系统示例<29>- 深度模糊DepthBlur(源码)

82 篇文章 4 订阅
75 篇文章 3 订阅
本文介绍了如何使用WebGPU和WGSL(WebGPUShadingLanguage)实现实时渲染目标纹理(RTT)的模糊效果,包括颜色和深度数据的处理,以及通过微调代码参数来调整模糊效果。示例代码展示了TypeScript中创建渲染系统和应用模糊passes的过程。
摘要由CSDN通过智能技术生成

实现方式:

step1. 通过mrt机制,输出颜色和深度相关数据的两张rtt纹理。

step2. 基于上述颜色纹理,生成一张模糊之后的新rtt纹理。

setp3. 基于深度(也就是距离摄像机的远近)数据,合成颜色和模糊纹理数据,并最终输出。

当前示例源码github地址:

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

当前示例运行效果:

微调一点代码,即可获得下述效果:

代码微调方式:

        第一处, 将下述片段着色器中的 f = 1.0 - f * f; 改为 f = f * f;

        第二处, 将

const attachment1 = {
			texture: vposRTTTex,
			clearValue: [0.2, 0.25, 0.2, 1.0]
		};

        改为

const attachment1 = {
			texture: vposRTTTex,
			clearValue: [800, 800, 800, 1]
		};

当然也可以通过第四个分量,来做实际的区分参数,统一处理。

合成模糊效果的WGSL片段着色器代码:

@group(0) @binding(0) var<uniform> param: vec4f;
@group(0) @binding(1) var colorSampler0: sampler;
@group(0) @binding(2) var colorTexture0: texture_2d<f32>;
@group(0) @binding(3) var blurSampler1: sampler;
@group(0) @binding(4) var blurTexture1: texture_2d<f32>;
@group(0) @binding(5) var vposSampler1: sampler;
@group(0) @binding(6) var vposTexture1: texture_2d<f32>;

fn calcColor(uv: vec2f) -> vec4f {

    var color = textureSample(colorTexture0, colorSampler0, uv) * param;
    var blurColor = textureSample(blurTexture1, blurSampler1, uv);
    var vpos = textureSample(vposTexture1, vposSampler1, uv);
	var f = clamp((length(vpos.xyz) - 300.0)/200.0, 0.0, 1.0);
	f = 1.0 - f * f;
	var result = vec4f(color.xyz * (1.0 - f) + f * blurColor.xyz, 1.0);

    return result;
}

@fragment
fn main(
	@location(0) uv: vec2f
	) -> @location(0) vec4f {
	var color4 = calcColor( uv );
    return color4;
}

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

const blurRTTTex0 = { diffuse: { uuid: "rtt0", rttTexture: {} } };
const blurRTTTex1 = { diffuse: { uuid: "rtt1", rttTexture: {} } };
const rtts = [blurRTTTex0, blurRTTTex1];
const attachment = {
	texture: blurRTTTex0,
	clearValue: [] as ColorDataType,
	loadOp: "clear",
	storeOp: "store"
} as WGRPassColorAttachment;
const colorAttachments = [attachment];

const colorRTTTex = { diffuse: { uuid: "colorRTT", rttTexture: {} } };
const vposRTTTex = { diffuse: { uuid: "floatRTT", rttTexture: {}, format: 'rgba16float' } };

class PassGraph extends WGRPassNodeGraph {
	blurEntity: FixScreenPlaneEntity;
	srcEntity: FixScreenPlaneEntity;
	constructor() {
		super();
	}

	run(): void {
		let pass = this.passes[0];

		const entity = this.blurEntity;
		let ms = entity.materials;

		for (let i = 0; i < 11; ++i) {
			const ia = i % 2;
			const ib = (i + 1) % 2;
			pass.colorAttachments[0].clearEnabled = i < 1;
			this.srcEntity.visible = i < 1;
			this.blurEntity.visible = i > 0;
			attachment.texture = rtts[ia];
			ms[ia].visible = false;
			ms[ib].visible = true;
			pass.render();
		}
	}
}

export class DepthBlur {

	private mRscene = new RendererScene();
	private mGraph = new PassGraph();
	private uniformValues = [{ data: new Float32Array([512, 512, 3.0, 0]) }];

	initialize(): void {

		let multisampleEnabled = true;
		let depthTestEnabled = false;
		let rpassparam = { multisampleEnabled, depthTestEnabled };
		this.mRscene.initialize({ rpassparam });

		this.initEvent();
		this.initScene();
	}

	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 => {}

	private createMaterial(shadinguuid: string, textures: WGTextureDataDescriptor[], type: number): WGMaterial {
		let shaderCodeSrc = {
			vert: { code: vertWGSL, uuid: "vert" },
			frag: { code: type > 0 ? blurVWGSL : blurHWGSL, uuid: "frag" }
		};
		shadinguuid += "-" + type;
		let pipelineDefParam = {
			depthWriteEnabled: false
		};
		const material = new WGMaterial({
			shadinguuid,
			shaderCodeSrc,
			pipelineDefParam
		});
		material.uniformValues = this.uniformValues;
		material.addTextures(textures);
		return material;
	}
	private applyBlurPass(clearColor: ColorDataType, extent: number[]): void {
		let rs = this.mRscene;

		const graph = this.mGraph;

		attachment.clearValue = clearColor;

		let rPass = rs.createRenderPass({ separate: true, colorAttachments });
		graph.passes = [rPass];

		let materials = [this.createMaterial("shd-00", [blurRTTTex0], 0), this.createMaterial("shd-01", [blurRTTTex1], 1)];

		let rttEntity = new FixScreenPlaneEntity({ extent: [-1, -1, 2, 2], flipY: true, textures: [colorRTTTex] });
		rttEntity.uuid = "src-entity";
		rPass.addEntity(rttEntity);
		graph.srcEntity = rttEntity;

		rs.setPassNodeGraph(graph);

		let entity = new FixScreenPlaneEntity({ extent, flipY: true, materials });
		entity.materials[0].visible = false;
		entity.uuid = "blur-entity";
		rPass.addEntity(entity);
		graph.blurEntity = entity;

		let shaderSrc = {
			vert: { code: vertWGSL, uuid: "vert" },
			frag: { code: depthBlurFragWGSL, uuid: "depthBlur" }
		};
		
		// display blur rendering result
		let textures = [colorRTTTex, blurRTTTex0, vposRTTTex];
		extent = [-0.8, -0.8, 1.6, 1.6];
		entity = new FixScreenPlaneEntity({ extent, flipY: false, shaderSrc, textures, shadinguuid: "smallImgMaterial" });
		rs.addEntity(entity);

	}

	private applyMRTPass(extent: number[]): void {
		let rs = this.mRscene;

		const attachment0 = {
			texture: colorRTTTex,
			clearValue: [0.15, 0.15, 0.15, 1.0]
		};
		const attachment1 = {
			texture: vposRTTTex,
			clearValue: [0.2, 0.25, 0.2, 1.0]
		};

		const colorAttachments = [attachment0, attachment1];

		let rPass = rs.createRenderPass({ separate: true, colorAttachments });

		let shaderSrc = {
			vert: { code: entityVertWGSL, uuid: "vertMRT" },
			frag: { code: entityFragWGSL, uuid: "fragMRT" }
		};

		let torus = new TorusEntity({shaderSrc, radius: 150});
		torus.setAlbedo([0.7,0.02,0.1]);
		rPass.addEntity(torus);

		shaderSrc = {
			vert: { code: vertWGSL, uuid: "vert" },
			frag: { code: vposReadFragWGSL, uuid: "readNromal" }
		};
		
		// display depth value drawing result
		extent = [-0.95, -0.95, 0.6, 0.6];
		let entity = new FixScreenPlaneEntity({ extent, shaderSrc, textures: [vposRTTTex], shadinguuid: "readDepth" });
		rs.addEntity(entity);

		// display albedo drawing result
		extent = [-0.33, -0.95, 0.6, 0.6];
		entity = new FixScreenPlaneEntity({ extent, textures: [colorRTTTex] });
		rs.addEntity(entity);


		// display blur drawing result
		extent = [0.3, -0.95, 0.6, 0.6];
		entity = new FixScreenPlaneEntity({ extent, textures: [blurRTTTex0] });
		rs.addEntity(entity);
	}
	private initScene(): void {
		this.applyBlurPass([0.0, 0.0, 0.03, 1.0], [-1, -1, 2, 2]);
		this.applyMRTPass( [-1, -1, 2, 2] );
	}

	run(): void {
		this.mRscene.run();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值