Expand material data structure, renderer class
This commit is contained in:
		| @@ -35,7 +35,7 @@ export class CameraOrthographic { | |||||||
| 	_farPlane: number; | 	_farPlane: number; | ||||||
|  |  | ||||||
| 	/** backreference */ | 	/** backreference */ | ||||||
| 	_node: Node | undefined; | 	_node: Node | null; | ||||||
|  |  | ||||||
| 	constructor({ | 	constructor({ | ||||||
| 		name = "", | 		name = "", | ||||||
| @@ -51,16 +51,16 @@ export class CameraOrthographic { | |||||||
| 		this._nearPlane = nearPlane; | 		this._nearPlane = nearPlane; | ||||||
| 		this._farPlane = farPlane; | 		this._farPlane = farPlane; | ||||||
|  |  | ||||||
| 		this._node = undefined; | 		this._node = null; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	detach(): Camera { | 	detach(): Camera { | ||||||
| 		if (this._node === undefined) { | 		if (this._node === null) { | ||||||
| 			return this; | 			return this; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		this._node._camera = undefined; | 		this._node._camera = null; | ||||||
| 		this._node = undefined; | 		this._node = null; | ||||||
| 		return this; | 		return this; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -76,7 +76,7 @@ export class CameraPerspective { | |||||||
| 	_farPlane: number; | 	_farPlane: number; | ||||||
|  |  | ||||||
| 	/** backreference */ | 	/** backreference */ | ||||||
| 	_node: Node | undefined; | 	_node: Node | null; | ||||||
|  |  | ||||||
| 	constructor({ | 	constructor({ | ||||||
| 		name = "", | 		name = "", | ||||||
| @@ -92,16 +92,16 @@ export class CameraPerspective { | |||||||
| 		this._nearPlane = nearPlane; | 		this._nearPlane = nearPlane; | ||||||
| 		this._farPlane = farPlane; | 		this._farPlane = farPlane; | ||||||
|  |  | ||||||
| 		this._node = undefined; | 		this._node = null; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	detach(): Camera { | 	detach(): Camera { | ||||||
| 		if (this._node === undefined) { | 		if (this._node === null) { | ||||||
| 			return this; | 			return this; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		this._node._camera = undefined; | 		this._node._camera = null; | ||||||
| 		this._node = undefined; | 		this._node = null; | ||||||
| 		return this; | 		return this; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,20 +4,23 @@ | |||||||
|  * obtain one at http://mozilla.org/MPL/2.0/. |  * obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | import { Renderer } from "./Renderer"; | ||||||
|  |  | ||||||
| export const INDEX_SIZE = 2; | export const INDEX_SIZE = 2; | ||||||
|  |  | ||||||
| export class IndexBuffer { | export class IndexBuffer { | ||||||
|  |  | ||||||
| 	readonly type!: "IndexBuffer"; | 	readonly type!: "IndexBuffer"; | ||||||
|  | 	_renderer: Renderer; | ||||||
|  |  | ||||||
| 	_device: GPUDevice; |  | ||||||
| 	_buffer: GPUBuffer; | 	_buffer: GPUBuffer; | ||||||
|  |  | ||||||
| 	constructor(device: GPUDevice, indexCount: number) { | 	constructor(renderer: Renderer, indexCount: number) { | ||||||
| 		Object.defineProperty(this, "type", { value: "IndexBuffer" }); | 		Object.defineProperty(this, "type", { value: "IndexBuffer" }); | ||||||
|  |  | ||||||
| 		this._device = device; | 		this._renderer = renderer; | ||||||
| 		this._buffer = device.createBuffer({ |  | ||||||
|  | 		this._buffer = renderer._device.createBuffer({ | ||||||
| 			usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.INDEX, | 			usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.INDEX, | ||||||
| 			size: indexCount * INDEX_SIZE, | 			size: indexCount * INDEX_SIZE, | ||||||
| 		}); | 		}); | ||||||
| @@ -34,12 +37,12 @@ export class IndexBuffer { | |||||||
|  |  | ||||||
| 	writeArray(offset: number, indices: readonly number[]): IndexBuffer { | 	writeArray(offset: number, indices: readonly number[]): IndexBuffer { | ||||||
| 		const array = new Uint16Array(indices); | 		const array = new Uint16Array(indices); | ||||||
| 		this._device.queue.writeBuffer(this._buffer, offset * INDEX_SIZE | 0, array); | 		this._renderer._device.queue.writeBuffer(this._buffer, offset * INDEX_SIZE | 0, array); | ||||||
| 		return this; | 		return this; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	writeTypedArray(offset: number, indices: Uint16Array): IndexBuffer { | 	writeTypedArray(offset: number, indices: Uint16Array): IndexBuffer { | ||||||
| 		this._device.queue.writeBuffer(this._buffer, offset * INDEX_SIZE | 0, indices); | 		this._renderer._device.queue.writeBuffer(this._buffer, offset * INDEX_SIZE | 0, indices); | ||||||
| 		return this; | 		return this; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,69 +5,111 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import { Color, ColorObject } from "./Color"; | import { Color, ColorObject } from "./Color"; | ||||||
|  | import { Renderer } from "./Renderer"; | ||||||
|  | import { Texture2D } from "./Texture2D"; | ||||||
|  |  | ||||||
|  | export const UNIFORM_BUFFER_SIZE = 64; | ||||||
|  |  | ||||||
| export interface MaterialProps { | export interface MaterialProps { | ||||||
| 	name?: string; | 	name?: string; | ||||||
|  |  | ||||||
| 	baseColor?: ColorObject; | 	baseColor?: ColorObject; | ||||||
|  | 	partialCoverage?: number; | ||||||
|  | 	occlusionTextureStrength?: number; | ||||||
| 	metallic?: number; | 	metallic?: number; | ||||||
| 	roughness?: number; | 	roughness?: number; | ||||||
|  | 	normalScale?: number; | ||||||
| 	emissive?: ColorObject; | 	emissive?: ColorObject; | ||||||
| 	partialCoverage?: number; |  | ||||||
| 	transmission?: ColorObject; | 	transmission?: ColorObject; | ||||||
| 	collimation?: number; | 	collimation?: number; | ||||||
| 	ior?: number; | 	ior?: number; | ||||||
|  |  | ||||||
|  | 	baseColorPartialCoverageTexture?: Texture2D | null; | ||||||
|  | 	occlusionMetallicRoughnessTexture?: Texture2D | null; | ||||||
|  | 	normalTexture?: Texture2D | null; | ||||||
|  | 	emissiveTexture?: Texture2D | null; | ||||||
|  | 	transmissionCollimationTexture?: Texture2D | null; | ||||||
|  |  | ||||||
|  | 	transparent?: boolean; | ||||||
| 	doubleSided?: boolean; | 	doubleSided?: boolean; | ||||||
| } | } | ||||||
|  |  | ||||||
| export class Material { | export class Material { | ||||||
|  |  | ||||||
| 	readonly type!: "Material"; | 	readonly type!: "Material"; | ||||||
|  | 	_renderer: Renderer; | ||||||
|  |  | ||||||
| 	_name: string; | 	_name: string; | ||||||
|  |  | ||||||
| 	_baseColor: Color; | 	_baseColor: Color; | ||||||
|  | 	_partialCoverage: number; | ||||||
|  | 	_occlusionTextureStrength: number; | ||||||
| 	_metallic: number; | 	_metallic: number; | ||||||
| 	_roughness: number; | 	_roughness: number; | ||||||
|  | 	_normalScale: number; | ||||||
| 	_emissive: Color; | 	_emissive: Color; | ||||||
| 	_partialCoverage: number; |  | ||||||
| 	_transmission: Color; | 	_transmission: Color; | ||||||
| 	_collimation: number; | 	_collimation: number; | ||||||
| 	_ior: number; | 	_ior: number; | ||||||
|  |  | ||||||
|  | 	_baseColorPartialCoverageTexture: Texture2D | null; | ||||||
|  | 	_occlusionMetallicRoughnessTexture: Texture2D | null; | ||||||
|  | 	_normalTexture: Texture2D | null; | ||||||
|  | 	_emissiveTexture: Texture2D | null; | ||||||
|  | 	_transmissionCollimationTexture: Texture2D | null; | ||||||
|  |  | ||||||
|  | 	_transparent: boolean; | ||||||
| 	_doubleSided: boolean; | 	_doubleSided: boolean; | ||||||
|  |  | ||||||
| 	constructor({ | 	constructor(renderer: Renderer, { | ||||||
| 		name = "", | 		name = "", | ||||||
| 		baseColor, | 		baseColor, | ||||||
|  | 		partialCoverage = 1, | ||||||
|  | 		occlusionTextureStrength = 1, | ||||||
| 		metallic = 1, | 		metallic = 1, | ||||||
| 		roughness = 1, | 		roughness = 1, | ||||||
|  | 		normalScale = 1, | ||||||
| 		emissive, | 		emissive, | ||||||
| 		partialCoverage = 1, |  | ||||||
| 		transmission, | 		transmission, | ||||||
| 		collimation = 1, | 		collimation = 1, | ||||||
| 		ior = 1.45, | 		ior = 1.45, | ||||||
|  | 		baseColorPartialCoverageTexture = null, | ||||||
|  | 		occlusionMetallicRoughnessTexture = null, | ||||||
|  | 		normalTexture = null, | ||||||
|  | 		emissiveTexture = null, | ||||||
|  | 		transmissionCollimationTexture = null, | ||||||
|  | 		transparent = false, | ||||||
| 		doubleSided = false, | 		doubleSided = false, | ||||||
| 	}: MaterialProps) { | 	}: MaterialProps) { | ||||||
| 		Object.defineProperty(this, "type", { value: "Material" }); | 		Object.defineProperty(this, "type", { value: "Material" }); | ||||||
|  |  | ||||||
|  | 		this._renderer = renderer; | ||||||
|  |  | ||||||
| 		this._name = name; | 		this._name = name; | ||||||
|  |  | ||||||
| 		this._baseColor = baseColor !== undefined ? Color.fromObject(baseColor) : Color.white(); | 		this._baseColor = baseColor !== undefined ? Color.fromObject(baseColor) : Color.white(); | ||||||
|  | 		this._partialCoverage = partialCoverage; | ||||||
|  | 		this._occlusionTextureStrength = occlusionTextureStrength; | ||||||
| 		this._metallic = metallic; | 		this._metallic = metallic; | ||||||
| 		this._roughness = roughness; | 		this._roughness = roughness; | ||||||
|  | 		this._normalScale = normalScale; | ||||||
| 		this._emissive = emissive !== undefined ? Color.fromObject(emissive) : Color.black(); | 		this._emissive = emissive !== undefined ? Color.fromObject(emissive) : Color.black(); | ||||||
| 		this._partialCoverage = partialCoverage; |  | ||||||
| 		this._transmission = transmission !== undefined ? Color.fromObject(transmission) : Color.black(); | 		this._transmission = transmission !== undefined ? Color.fromObject(transmission) : Color.black(); | ||||||
| 		this._collimation = collimation; | 		this._collimation = collimation; | ||||||
| 		this._ior = ior; | 		this._ior = ior; | ||||||
|  |  | ||||||
|  | 		this._baseColorPartialCoverageTexture = baseColorPartialCoverageTexture; | ||||||
|  | 		this._occlusionMetallicRoughnessTexture = occlusionMetallicRoughnessTexture; | ||||||
|  | 		this._normalTexture = normalTexture; | ||||||
|  | 		this._emissiveTexture = emissiveTexture; | ||||||
|  | 		this._transmissionCollimationTexture = transmissionCollimationTexture; | ||||||
|  |  | ||||||
|  | 		this._transparent = transparent; | ||||||
| 		this._doubleSided = doubleSided; | 		this._doubleSided = doubleSided; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	get isTransparent(): boolean { | 	dispose(): Material { | ||||||
| 		return this._partialCoverage < 1 || this._transmission.r > 0 || this._transmission.g > 0 || this._transmission.b > 0; | 		return this; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								src/Mesh.ts
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/Mesh.ts
									
									
									
									
									
								
							| @@ -7,11 +7,17 @@ | |||||||
| import { IndexBuffer } from "./IndexBuffer"; | import { IndexBuffer } from "./IndexBuffer"; | ||||||
| import { VertexBuffer } from "./VertexBuffer"; | import { VertexBuffer } from "./VertexBuffer"; | ||||||
|  |  | ||||||
|  | export type Submesh = { | ||||||
|  | 	start: number, | ||||||
|  | 	length: number, | ||||||
|  | }; | ||||||
|  |  | ||||||
| export interface MeshProps { | export interface MeshProps { | ||||||
| 	readonly name?: string; | 	readonly name?: string; | ||||||
|  |  | ||||||
| 	readonly vertexBuffer: VertexBuffer; | 	readonly vertexBuffer: VertexBuffer; | ||||||
| 	readonly indexBuffer: IndexBuffer; | 	readonly indexBuffer: IndexBuffer; | ||||||
|  | 	readonly submeshes: Submesh[]; | ||||||
| } | } | ||||||
|  |  | ||||||
| export class Mesh { | export class Mesh { | ||||||
| @@ -22,11 +28,13 @@ export class Mesh { | |||||||
|  |  | ||||||
| 	_vertexBuffer: VertexBuffer; | 	_vertexBuffer: VertexBuffer; | ||||||
| 	_indexBuffer: IndexBuffer; | 	_indexBuffer: IndexBuffer; | ||||||
|  | 	_submeshes: Submesh[]; | ||||||
|  |  | ||||||
| 	constructor({ | 	constructor({ | ||||||
| 		name = "", | 		name = "", | ||||||
| 		vertexBuffer, | 		vertexBuffer, | ||||||
| 		indexBuffer, | 		indexBuffer, | ||||||
|  | 		submeshes, | ||||||
| 	}: MeshProps) { | 	}: MeshProps) { | ||||||
| 		Object.defineProperty(this, "type", { value: "Mesh" }); | 		Object.defineProperty(this, "type", { value: "Mesh" }); | ||||||
|  |  | ||||||
| @@ -34,6 +42,11 @@ export class Mesh { | |||||||
|  |  | ||||||
| 		this._vertexBuffer = vertexBuffer; | 		this._vertexBuffer = vertexBuffer; | ||||||
| 		this._indexBuffer = indexBuffer | 		this._indexBuffer = indexBuffer | ||||||
|  | 		this._submeshes = submeshes; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	get submeshCount(): number { | ||||||
|  | 		return this._submeshes.length; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								src/Node.ts
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/Node.ts
									
									
									
									
									
								
							| @@ -5,6 +5,7 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import { Camera } from "./Camera"; | import { Camera } from "./Camera"; | ||||||
|  | import { Material } from "./Material"; | ||||||
| import { Mesh } from "./Mesh"; | import { Mesh } from "./Mesh"; | ||||||
| import { Quaternion, QuaternionObject } from "./Quaternion"; | import { Quaternion, QuaternionObject } from "./Quaternion"; | ||||||
| import { Vector3, Vector3Object } from "./Vector3"; | import { Vector3, Vector3Object } from "./Vector3"; | ||||||
| @@ -16,8 +17,9 @@ export interface NodeProps { | |||||||
| 	readonly rotation?: QuaternionObject; | 	readonly rotation?: QuaternionObject; | ||||||
| 	readonly scale?: Vector3Object; | 	readonly scale?: Vector3Object; | ||||||
|  |  | ||||||
| 	readonly camera?: Camera; | 	readonly camera?: Camera | null; | ||||||
| 	readonly mesh?: Mesh; | 	readonly mesh?: Mesh | null; | ||||||
|  | 	readonly materials?: Material[]; | ||||||
|  |  | ||||||
| 	readonly children?: Node[]; | 	readonly children?: Node[]; | ||||||
| } | } | ||||||
| @@ -33,23 +35,26 @@ export class Node { | |||||||
| 	_scale: Vector3; | 	_scale: Vector3; | ||||||
|  |  | ||||||
| 	/** unique */ | 	/** unique */ | ||||||
| 	_camera: Camera | undefined; | 	_camera: Camera | null; | ||||||
| 	/** shared */ | 	/** shared */ | ||||||
| 	_mesh: Mesh | undefined; | 	_mesh: Mesh | null; | ||||||
|  | 	/** shared */ | ||||||
|  | 	_materials: Material[]; | ||||||
|  |  | ||||||
| 	/** unique */ | 	/** unique */ | ||||||
| 	_children: Node[]; | 	_children: Node[]; | ||||||
|  |  | ||||||
| 	/** backreference */ | 	/** backreference */ | ||||||
| 	_parent: Node | undefined; | 	_parent: Node | null; | ||||||
|  |  | ||||||
| 	constructor({ | 	constructor({ | ||||||
| 		name = "", | 		name = "", | ||||||
| 		translation, | 		translation, | ||||||
| 		rotation, | 		rotation, | ||||||
| 		scale, | 		scale, | ||||||
| 		camera, | 		camera = null, | ||||||
| 		mesh, | 		mesh = null, | ||||||
|  | 		materials = [], | ||||||
| 		children = [], | 		children = [], | ||||||
| 	}: NodeProps) { | 	}: NodeProps) { | ||||||
| 		Object.defineProperty(this, "type", { value: "Node" }); | 		Object.defineProperty(this, "type", { value: "Node" }); | ||||||
| @@ -62,16 +67,17 @@ export class Node { | |||||||
|  |  | ||||||
| 		this._camera = camera; | 		this._camera = camera; | ||||||
| 		this._mesh = mesh; | 		this._mesh = mesh; | ||||||
|  | 		this._materials = materials; | ||||||
|  |  | ||||||
| 		this._children = children; | 		this._children = children; | ||||||
|  |  | ||||||
| 		this._parent = undefined; | 		this._parent = null; | ||||||
|  |  | ||||||
| 		if (this._camera !== undefined) { | 		if (this._camera !== null) { | ||||||
| 			this._camera._node = this; | 			this._camera._node = this; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (this._children !== undefined) { | 		if (this._children !== null) { | ||||||
| 			for (const child of this._children) { | 			for (const child of this._children) { | ||||||
| 				child._parent = this; | 				child._parent = this; | ||||||
| 			} | 			} | ||||||
|   | |||||||
							
								
								
									
										91
									
								
								src/Renderer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/Renderer.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | |||||||
|  | /*! | ||||||
|  |  * This Source Code Form is subject to the terms of the Mozilla Public License, | ||||||
|  |  * v. 2.0. If a copy of the MPL was not distributed with this file, You can | ||||||
|  |  * obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | import { IndexBuffer } from "./IndexBuffer"; | ||||||
|  | import { Material, MaterialProps } from "./Material"; | ||||||
|  | import { Texture2D, Texture2DProps } from "./Texture2D"; | ||||||
|  | import { VertexBuffer } from "./VertexBuffer"; | ||||||
|  |  | ||||||
|  | export class Renderer { | ||||||
|  |  | ||||||
|  | 	_adapter: GPUAdapter; | ||||||
|  | 	_device: GPUDevice; | ||||||
|  | 	_context: GPUCanvasContext; | ||||||
|  | 	_format: GPUTextureFormat; | ||||||
|  |  | ||||||
|  | 	_textureWhite: Texture2D; // 1×1 rgba8unorm of [255, 255, 255, 255] | ||||||
|  | 	_textureBlack: Texture2D; // 1×1 rgba8unorm of [0, 0, 0, 255] | ||||||
|  | 	_textureNormal: Texture2D; // 1×1 rgba8unorm of [128, 128, 128, 255] | ||||||
|  |  | ||||||
|  | 	private constructor ( | ||||||
|  | 		adapter: GPUAdapter, | ||||||
|  | 		device: GPUDevice, | ||||||
|  | 		context: GPUCanvasContext, | ||||||
|  | 		format: GPUTextureFormat, | ||||||
|  | 	) { | ||||||
|  | 		this._adapter = adapter; | ||||||
|  | 		this._device = device; | ||||||
|  | 		this._context = context; | ||||||
|  | 		this._format = format; | ||||||
|  |  | ||||||
|  | 		this._textureWhite = new Texture2D(this, { | ||||||
|  | 			width: 1, | ||||||
|  | 			height: 1, | ||||||
|  | 		}); | ||||||
|  | 		this._textureWhite.writeTypedArray(new Uint8Array([255, 255, 255, 255])); | ||||||
|  |  | ||||||
|  | 		this._textureBlack = new Texture2D(this, { | ||||||
|  | 			width: 1, | ||||||
|  | 			height: 1, | ||||||
|  | 		}); | ||||||
|  | 		this._textureBlack.writeTypedArray(new Uint8Array([0, 0, 0, 255])); | ||||||
|  |  | ||||||
|  | 		this._textureNormal = new Texture2D(this, { | ||||||
|  | 			width: 1, | ||||||
|  | 			height: 1, | ||||||
|  | 		}); | ||||||
|  | 		this._textureNormal.writeTypedArray(new Uint8Array([128, 128, 128, 255])); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static async init(canvas: HTMLCanvasElement) { | ||||||
|  | 		if (!navigator.gpu) { | ||||||
|  | 			throw new Error("WebGPU is not supported"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		const adapter = await navigator.gpu.requestAdapter({ | ||||||
|  | 			powerPreference: "high-performance", | ||||||
|  | 		}); | ||||||
|  | 		if (adapter === null) { | ||||||
|  | 			throw new Error("GPUAdapter is not available"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		const device = await adapter.requestDevice(); | ||||||
|  |  | ||||||
|  | 		const context = canvas.getContext("webgpu"); | ||||||
|  | 		if (context === null) { | ||||||
|  | 			throw new Error("GPUCanvasContext is not available"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		const format = navigator.gpu.getPreferredCanvasFormat(); | ||||||
|  | 		context.configure({ device, format }); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	createTexture(props: Texture2DProps): Texture2D { | ||||||
|  | 		return new Texture2D(this, props); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	createIndexBuffer(indexCount: number): IndexBuffer { | ||||||
|  | 		return new IndexBuffer(this, indexCount); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	createMaterial(props: MaterialProps): Material { | ||||||
|  | 		return new Material(this, props); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	createVertexBuffer(vertexCount: number): VertexBuffer { | ||||||
|  | 		return new VertexBuffer(this, vertexCount); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -16,7 +16,7 @@ export class Scene { | |||||||
|  |  | ||||||
| 	readonly type!: "Scene"; | 	readonly type!: "Scene"; | ||||||
|  |  | ||||||
| 	_name: string | undefined; | 	_name: string; | ||||||
|  |  | ||||||
| 	_nodes: Node[]; | 	_nodes: Node[]; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,41 +4,47 @@ | |||||||
|  * obtain one at http://mozilla.org/MPL/2.0/. |  * obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | import { Renderer } from "./Renderer"; | ||||||
|  |  | ||||||
| export interface Texture2DProps { | export interface Texture2DProps { | ||||||
| 	name?: string; | 	name?: string; | ||||||
| 	device: GPUDevice; |  | ||||||
| 	width: number; | 	width: number; | ||||||
| 	height: number; | 	height: number; | ||||||
|  |  | ||||||
|  | 	sRGB?: boolean; | ||||||
| } | } | ||||||
|  |  | ||||||
| export class Texture2D { | export class Texture2D { | ||||||
|  |  | ||||||
| 	readonly type!: "Texture2D"; | 	readonly type!: "Texture2D"; | ||||||
|  | 	_renderer: Renderer; | ||||||
|  |  | ||||||
| 	_name: string; | 	_name: string; | ||||||
|  |  | ||||||
| 	_device: GPUDevice; |  | ||||||
| 	_texture: GPUTexture; | 	_texture: GPUTexture; | ||||||
| 	_textureView: GPUTextureView; | 	_textureView: GPUTextureView; | ||||||
|  |  | ||||||
| 	constructor({ | 	constructor(renderer: Renderer, { | ||||||
| 		name = "", | 		name = "", | ||||||
| 		device, |  | ||||||
| 		width, | 		width, | ||||||
| 		height, | 		height, | ||||||
|  | 		sRGB = false, | ||||||
| 	}: Texture2DProps) { | 	}: Texture2DProps) { | ||||||
| 		Object.defineProperty(this, "type", { value: "Texture2D" }); | 		Object.defineProperty(this, "type", { value: "Texture2D" }); | ||||||
|  |  | ||||||
|  | 		this._renderer = renderer; | ||||||
|  |  | ||||||
| 		this._name = name; | 		this._name = name; | ||||||
|  |  | ||||||
| 		this._device = device; | 		this._renderer = renderer; | ||||||
| 		this._texture = device.createTexture({ | 		this._texture = renderer._device.createTexture({ | ||||||
| 			usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST, | 			usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST, | ||||||
| 			size: { width, height }, | 			size: { width, height }, | ||||||
| 			format: "rgba8unorm", | 			format: sRGB ? "rgba8unorm-srgb" : "rgba8unorm", | ||||||
| 		}); | 		}); | ||||||
| 		this._textureView = this._texture.createView({ | 		this._textureView = this._texture.createView({ | ||||||
| 			format: "rgba8unorm", | 			format: sRGB ? "rgba8unorm-srgb" : "rgba8unorm", | ||||||
| 			dimension: "2d", | 			dimension: "2d", | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| @@ -57,7 +63,7 @@ export class Texture2D { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	writeTypedArray(data: Uint8Array): Texture2D { | 	writeTypedArray(data: Uint8Array): Texture2D { | ||||||
| 		this._device.queue.writeTexture( | 		this._renderer._device.queue.writeTexture( | ||||||
| 			{ texture: this._texture }, | 			{ texture: this._texture }, | ||||||
| 			data, | 			data, | ||||||
| 			{ bytesPerRow: 4 * this._texture.width }, | 			{ bytesPerRow: 4 * this._texture.width }, | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
|  * obtain one at http://mozilla.org/MPL/2.0/. |  * obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | import { Renderer } from "./Renderer"; | ||||||
| import { Vector3Object } from "./Vector3"; | import { Vector3Object } from "./Vector3"; | ||||||
|  |  | ||||||
| export const VERTEX_SIZE = 12; | export const VERTEX_SIZE = 12; | ||||||
| @@ -11,15 +12,16 @@ export const VERTEX_SIZE = 12; | |||||||
| export class VertexBuffer { | export class VertexBuffer { | ||||||
|  |  | ||||||
| 	readonly type!: "VertexBuffer"; | 	readonly type!: "VertexBuffer"; | ||||||
|  | 	_renderer: Renderer; | ||||||
|  |  | ||||||
| 	_device: GPUDevice; |  | ||||||
| 	_buffer: GPUBuffer; | 	_buffer: GPUBuffer; | ||||||
|  |  | ||||||
| 	constructor(device: GPUDevice, vertexCount: number) { | 	constructor(renderer: Renderer, vertexCount: number) { | ||||||
| 		Object.defineProperty(this, "type", { value: "VertexBuffer" }); | 		Object.defineProperty(this, "type", { value: "VertexBuffer" }); | ||||||
|  |  | ||||||
| 		this._device = device; | 		this._renderer = renderer; | ||||||
| 		this._buffer = device.createBuffer({ |  | ||||||
|  | 		this._buffer = renderer._device.createBuffer({ | ||||||
| 			usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.VERTEX, | 			usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.VERTEX, | ||||||
| 			size: vertexCount * VERTEX_SIZE, | 			size: vertexCount * VERTEX_SIZE, | ||||||
| 		}); | 		}); | ||||||
| @@ -42,12 +44,12 @@ export class VertexBuffer { | |||||||
| 			array[ptr++] = vertex.y; | 			array[ptr++] = vertex.y; | ||||||
| 			array[ptr++] = vertex.z; | 			array[ptr++] = vertex.z; | ||||||
| 		} | 		} | ||||||
| 		this._device.queue.writeBuffer(this._buffer, offset * VERTEX_SIZE | 0, array); | 		this._renderer._device.queue.writeBuffer(this._buffer, offset * VERTEX_SIZE | 0, array); | ||||||
| 		return this; | 		return this; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	writeTypedArray(offset: number, vertices: Float32Array): VertexBuffer { | 	writeTypedArray(offset: number, vertices: Float32Array): VertexBuffer { | ||||||
| 		this._device.queue.writeBuffer(this._buffer, offset * VERTEX_SIZE | 0, vertices); | 		this._renderer._device.queue.writeBuffer(this._buffer, offset * VERTEX_SIZE | 0, vertices); | ||||||
| 		return this; | 		return this; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ export * from "./Matrix4x4"; | |||||||
| export * from "./Mesh"; | export * from "./Mesh"; | ||||||
| export * from "./Node"; | export * from "./Node"; | ||||||
| export * from "./Quaternion"; | export * from "./Quaternion"; | ||||||
|  | export * from "./Renderer"; | ||||||
| export * from "./Scene"; | export * from "./Scene"; | ||||||
| export * from "./Texture2D"; | export * from "./Texture2D"; | ||||||
| export * from "./Vector3"; | export * from "./Vector3"; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user