轻量封装WebGPU渲染系统示例<9>- 基本光照(源码)

当前示例源码github地址:

https://github.com/vilyLei/voxwebgpu/blob/main/src/voxgpu/sample/SimpleLightTest.ts

此示例渲染系统实现的特性:

1. 用户态与系统态隔离。

         细节请见:引擎系统设计思路 - 用户态与系统态隔离-CSDN博客

2. 高频调用与低频调用隔离。

3. 面向用户的易用性封装。

4. 渲染数据和渲染机制分离。

5. 用户操作和渲染系统调度并行机制。

当前示例运行效果:

顶点shader:

@group(0) @binding(0) var<uniform> objMat : mat4x4<f32>;
@group(0) @binding(1) var<uniform> viewMat : mat4x4<f32>;
@group(0) @binding(2) var<uniform> projMat : mat4x4<f32>;

struct VertexOutput {
  @builtin(position) Position : vec4<f32>,
  @location(0) pos: vec4<f32>,
  @location(1) uv : vec2<f32>,
  @location(2) normal : vec3<f32>
}

fn inverseM33(m: mat3x3<f32>)-> mat3x3<f32> {
    let a00 = m[0][0]; let a01 = m[0][1]; let a02 = m[0][2];
    let a10 = m[1][0]; let a11 = m[1][1]; let a12 = m[1][2];
    let a20 = m[2][0]; let a21 = m[2][1]; let a22 = m[2][2];
    let b01 = a22 * a11 - a12 * a21;
    let b11 = -a22 * a10 + a12 * a20;
    let b21 = a21 * a10 - a11 * a20;
    let det = a00 * b01 + a01 * b11 + a02 * b21;
    return mat3x3<f32>(
		vec3<f32>(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11)) / det,
                vec3<f32>(b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10)) / det,
                vec3<f32>(b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det);
}
fn m44ToM33(m: mat4x4<f32>) -> mat3x3<f32> {
	return mat3x3(m[0].xyz, m[1].xyz, m[2].xyz);
}
@vertex
fn main(
  @location(0) position : vec3<f32>,
  @location(1) uv : vec2<f32>,
  @location(2) normal : vec3<f32>
) -> VertexOutput {
  var output : VertexOutput;
  output.Position = projMat * viewMat * objMat * vec4(position.xyz, 1.0);
  output.uv = uv;

  let invMat33 = inverseM33( m44ToM33( objMat ) );
  output.normal = normalize( normal * invMat33 );

  var pv: vec4<f32>;
  pv = vec4<f32>(position, 1.0);
  output.pos = pv;
  return output;
}

片段shader:

@group(0) @binding(3) var<storage> param: vec4f;
@group(0) @binding(4) var sampler0: sampler;
@group(0) @binding(5) var texture0: texture_2d<f32>;

const lightDirec = vec3<f32>(0.3,0.6,0.9);

@fragment
fn main(
  @location(0) pos: vec4<f32>,
  @location(1) uv: vec2<f32>,
  @location(2) normal: vec3<f32>
) -> @location(0) vec4<f32> {

  let nDotL = max(dot(normal, lightDirec), 0.0);
  var color4 = textureSample(texture0, sampler0, uv) * param;
  color4 = vec4(color4.xyz * (vec3<f32>(1.0 - param.w) + vec3<f32>((param.w) * nDotL) * param.xyz), color4.w);
  return color4;
}

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

export class SimpleLightTest {
	private mObjs: TransObject[] = [];

	private mRscene = new RendererScene();

	geomData = new GeomDataBuilder();

	initialize(): void {
		console.log("SimpleLightTest::initialize() ...");

		this.initEvent();
		
		const shdSrc = {
			vertShaderSrc: { code: vertWGSL, uuid: "vertShdCode" },
			fragShaderSrc: { code: fragWGSL, uuid: "fragShdCode" }
		};

		let geom = this.createGeom(this.geomData.createCube(100), true);

		let texList = [new WGImage2DTextureData("static/assets/white.jpg")];
		let tot = 4;
		const size = new Vector3(150, 150, 150);
		const pos = new Vector3().copyFrom(size).scaleBy(-0.5 * (tot - 1));

		for (let i = 0; i < tot; ++i) {
			for (let j = 0; j < tot; ++j) {
				for (let k = 0; k < tot; ++k) {
					let material = this.createMaterial(shdSrc, texList, new Color4().randomRGB(1.0, 0.2));
					let scale = Math.random() * 0.2 + 0.3;
					const entity = this.createEntity(geom, [material]);
					const obj = new TransObject();
					obj.entity = entity;
					obj.scale.setXYZ(scale, scale, scale);
					obj.rotationSpdv.setXYZ(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5);
					obj.position.setXYZ(i * size.x, j * size.y, k * size.z).addBy(pos);
					this.mObjs.push(obj);
				}
			}
		}
	}
	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 => {
		console.log("mousedown evt call ...");
	}
	private createMaterial(
		shdSrc: WGRShderSrcType,
		texDatas?: WGImage2DTextureData[],
		color?: Color4,
		blendModes: string[] = ["solid"],
		faceCullMode = "back"
	): WGMaterial {
		let pipelineDefParam = {
			depthWriteEnabled: true,
			faceCullMode,
			blendModes: [] as string[]
		};

		if (!color) color = new Color4(1.0, 1.0, 1.0);

		pipelineDefParam.blendModes = blendModes;

		const texTotal = texDatas ? texDatas.length : 0;

		const material = new WGMaterial({
			shadinguuid: "base-material-tex" + texTotal,
			shaderCodeSrc: shdSrc,
			pipelineDefParam
		});

		let ufv = new WGRStorageValue(new Float32Array([color.r, color.g, color.b, 0.9]));
		material.uniformValues = [ufv];
		material.addTextureWithDatas(texDatas);

		return material;
	}

	private createGeom(rgd: GeomRDataType, normalEnabled = false): WGGeometry {
		const geometry = new WGGeometry()
			.addAttribute({ position: rgd.vs })
			.addAttribute({ uv: rgd.uvs })
			.setIndices(rgd.ivs);
		if (normalEnabled) {
			geometry.addAttribute({ normal: rgd.nvs });
		}
		return geometry;
	}
	private createEntity(geometry: WGGeometry, materials: WGMaterial[], pv?: Vector3): Entity3D {

		const rc = this.mRscene;
		const entity = new Entity3D();
		entity.materials = materials;
		entity.geometry = geometry;
		if (pv) entity.transform.setPosition(pv);

		rc.addEntity(entity);
		return entity;
	}

	run(): void {
		for (let i = 0; i < this.mObjs.length; ++i) {
			this.mObjs[i].run();
		}
		this.mRscene.run();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值