Light classes, gathering materials
This commit is contained in:
parent
3824c8f0c5
commit
537f70ef88
@ -1,4 +1,10 @@
|
||||
import { Matrix4x4Object, Vector2Object, Vector3Object, Vector4Object } from "./data";
|
||||
/*!
|
||||
* 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 { ColorObject, Matrix4x4Object, Vector2Object, Vector3Object, Vector4Object } from "./data";
|
||||
|
||||
export class _BinaryWriter {
|
||||
|
||||
@ -103,6 +109,13 @@ export class _BinaryWriter {
|
||||
return this;
|
||||
}
|
||||
|
||||
writeColorF32(value: ColorObject): _BinaryWriter {
|
||||
this.writeF32(value.r);
|
||||
this.writeF32(value.g);
|
||||
this.writeF32(value.b);
|
||||
return this;
|
||||
}
|
||||
|
||||
alloc(byteLength: number): DataView {
|
||||
this.ensureUnusedCapacity(byteLength);
|
||||
const dataView = new DataView(this._buffer, this._length, byteLength);
|
||||
|
29
src/_Mapping.ts
Normal file
29
src/_Mapping.ts
Normal file
@ -0,0 +1,29 @@
|
||||
/*!
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
export class _Mapping<T> {
|
||||
table: T[];
|
||||
map: Map<T, number>;
|
||||
|
||||
constructor() {
|
||||
this.table = [];
|
||||
this.map = new Map();
|
||||
}
|
||||
|
||||
add(item: T) {
|
||||
if (this.map.has(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = this.table.length;
|
||||
this.table.push(item);
|
||||
this.map.set(item, id);
|
||||
}
|
||||
|
||||
get(item: T): number | undefined {
|
||||
return this.map.get(item);
|
||||
}
|
||||
}
|
@ -6,9 +6,9 @@
|
||||
|
||||
import { Node } from ".";
|
||||
|
||||
export type Camera = CameraOrthographic | CameraPerspective;
|
||||
export type Camera = OrthographicCamera | PerspectiveCamera;
|
||||
|
||||
export interface CameraOrthographicProps {
|
||||
export interface OrthographicCameraProps {
|
||||
readonly name?: string;
|
||||
|
||||
readonly verticalSize: number;
|
||||
@ -16,7 +16,7 @@ export interface CameraOrthographicProps {
|
||||
readonly farPlane: number;
|
||||
}
|
||||
|
||||
export interface CameraPerspectiveProps {
|
||||
export interface PerspectiveCameraProps {
|
||||
readonly name?: string;
|
||||
|
||||
readonly verticalFovRad: number;
|
||||
@ -24,9 +24,9 @@ export interface CameraPerspectiveProps {
|
||||
readonly farPlane: number;
|
||||
}
|
||||
|
||||
export class CameraOrthographic {
|
||||
export class OrthographicCamera {
|
||||
|
||||
readonly type!: "CameraOrthographic";
|
||||
readonly type!: "OrthographicCamera";
|
||||
|
||||
_name: string;
|
||||
|
||||
@ -42,7 +42,7 @@ export class CameraOrthographic {
|
||||
verticalSize,
|
||||
nearPlane,
|
||||
farPlane,
|
||||
}: CameraOrthographicProps) {
|
||||
}: OrthographicCameraProps) {
|
||||
this._name = name;
|
||||
|
||||
this._verticalSize = verticalSize;
|
||||
@ -64,7 +64,7 @@ export class CameraOrthographic {
|
||||
set farPlane(value: number) { this._farPlane = value; }
|
||||
get farPlane(): number { return this._farPlane; }
|
||||
|
||||
attach(node: Node): CameraOrthographic {
|
||||
attach(node: Node): OrthographicCamera {
|
||||
if (this._node !== null) {
|
||||
this._node._camera = null;
|
||||
}
|
||||
@ -78,7 +78,7 @@ export class CameraOrthographic {
|
||||
return this;
|
||||
}
|
||||
|
||||
detach(): CameraOrthographic {
|
||||
detach(): OrthographicCamera {
|
||||
if (this._node === null) {
|
||||
return this;
|
||||
}
|
||||
@ -89,11 +89,9 @@ export class CameraOrthographic {
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(CameraOrthographic.prototype, "type", { value: "CameraOrthographic" });
|
||||
export class PerspectiveCamera {
|
||||
|
||||
export class CameraPerspective {
|
||||
|
||||
readonly type!: "CameraPerspective";
|
||||
readonly type!: "PerspectiveCamera";
|
||||
|
||||
_name: string;
|
||||
|
||||
@ -109,7 +107,7 @@ export class CameraPerspective {
|
||||
verticalFovRad,
|
||||
nearPlane,
|
||||
farPlane,
|
||||
}: CameraPerspectiveProps) {
|
||||
}: PerspectiveCameraProps) {
|
||||
this._name = name;
|
||||
|
||||
this._verticalFovRad = verticalFovRad;
|
||||
@ -128,7 +126,7 @@ export class CameraPerspective {
|
||||
set farPlane(value: number) { this._farPlane = value; }
|
||||
get farPlane(): number { return this._farPlane; }
|
||||
|
||||
attach(node: Node): CameraPerspective {
|
||||
attach(node: Node): PerspectiveCamera {
|
||||
if (this._node !== null) {
|
||||
this._node._camera = null;
|
||||
}
|
||||
@ -142,7 +140,7 @@ export class CameraPerspective {
|
||||
return this;
|
||||
}
|
||||
|
||||
detach(): CameraPerspective {
|
||||
detach(): PerspectiveCamera {
|
||||
if (this._node === null) {
|
||||
return this;
|
||||
}
|
||||
@ -153,12 +151,14 @@ export class CameraPerspective {
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(CameraPerspective.prototype, "type", { value: "CameraPerspective" });
|
||||
Object.defineProperty(OrthographicCamera.prototype, "type", { value: "OrthographicCamera" });
|
||||
|
||||
export function isCameraOrthographic(value: unknown): value is CameraOrthographic {
|
||||
return Boolean(value) && (value as CameraOrthographic).type === "CameraOrthographic";
|
||||
Object.defineProperty(PerspectiveCamera.prototype, "type", { value: "PerspectiveCamera" });
|
||||
|
||||
export function isOrthographicCamera(value: unknown): value is OrthographicCamera {
|
||||
return Boolean(value) && (value as OrthographicCamera).type === "OrthographicCamera";
|
||||
}
|
||||
|
||||
export function isCameraPerspective(value: unknown): value is CameraPerspective {
|
||||
return Boolean(value) && (value as CameraPerspective).type === "CameraPerspective";
|
||||
export function isPerspectiveCamera(value: unknown): value is PerspectiveCamera {
|
||||
return Boolean(value) && (value as PerspectiveCamera).type === "PerspectiveCamera";
|
||||
}
|
||||
|
151
src/data/Light.ts
Normal file
151
src/data/Light.ts
Normal file
@ -0,0 +1,151 @@
|
||||
/*!
|
||||
* 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 { Color, ColorObject, Node } from ".";
|
||||
|
||||
export type Light = DirectionalLight | PointLight;
|
||||
|
||||
export interface DirectionalLightProps {
|
||||
readonly name?: string;
|
||||
|
||||
readonly color: ColorObject;
|
||||
}
|
||||
|
||||
export interface PointLightProps {
|
||||
readonly name?: string;
|
||||
|
||||
readonly color: ColorObject;
|
||||
}
|
||||
|
||||
export class DirectionalLight {
|
||||
|
||||
readonly type!: "DirectionalLight";
|
||||
|
||||
_name: string;
|
||||
|
||||
_color: Color;
|
||||
|
||||
/** backreference */
|
||||
_node: Node | null;
|
||||
|
||||
constructor({
|
||||
name = "",
|
||||
color,
|
||||
}: DirectionalLightProps) {
|
||||
this._name = name;
|
||||
|
||||
this._color = Color.fromObject(color);
|
||||
|
||||
this._node = null;
|
||||
}
|
||||
|
||||
set name(value: string) { this._name = value; }
|
||||
get name(): string { return this._name; }
|
||||
|
||||
setColor(value: ColorObject): DirectionalLight {
|
||||
this._color.setObject(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
getColor(res: Color): Color {
|
||||
return res.setObject(this._color);
|
||||
}
|
||||
|
||||
attach(node: Node): DirectionalLight {
|
||||
if (this._node !== null) {
|
||||
this._node._light = null;
|
||||
}
|
||||
|
||||
if (node._light !== null) {
|
||||
node._light._node = null;
|
||||
}
|
||||
|
||||
node._light = this;
|
||||
this._node = node;
|
||||
return this;
|
||||
}
|
||||
|
||||
detach(): DirectionalLight {
|
||||
if (this._node === null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this._node._light = null;
|
||||
this._node = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export class PointLight {
|
||||
|
||||
readonly type!: "PointLight";
|
||||
|
||||
_name: string;
|
||||
|
||||
_color: Color;
|
||||
|
||||
/** backreference */
|
||||
_node: Node | null;
|
||||
|
||||
constructor({
|
||||
name = "",
|
||||
color,
|
||||
}: PointLightProps) {
|
||||
this._name = name;
|
||||
|
||||
this._color = Color.fromObject(color);
|
||||
|
||||
this._node = null;
|
||||
}
|
||||
|
||||
set name(value: string) { this._name = value; }
|
||||
get name(): string { return this._name; }
|
||||
|
||||
setColor(value: ColorObject): PointLight {
|
||||
this._color.setObject(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
getColor(res: Color): Color {
|
||||
return res.setObject(this._color);
|
||||
}
|
||||
|
||||
attach(node: Node): PointLight {
|
||||
if (this._node !== null) {
|
||||
this._node._light = null;
|
||||
}
|
||||
|
||||
if (node._light !== null) {
|
||||
node._light._node = null;
|
||||
}
|
||||
|
||||
node._light = this;
|
||||
this._node = node;
|
||||
return this;
|
||||
}
|
||||
|
||||
detach(): PointLight {
|
||||
if (this._node === null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this._node._light = null;
|
||||
this._node = null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(DirectionalLight.prototype, "type", { value: "DirectionalLight" });
|
||||
|
||||
Object.defineProperty(PointLight.prototype, "type", { value: "PointLight" });
|
||||
|
||||
export function isDirectionalLight(value: unknown): value is DirectionalLight {
|
||||
return Boolean(value) && (value as DirectionalLight).type === "DirectionalLight";
|
||||
}
|
||||
|
||||
export function isPointLight(value: unknown): value is PointLight {
|
||||
return Boolean(value) && (value as PointLight).type === "PointLight";
|
||||
}
|
@ -4,9 +4,8 @@
|
||||
* obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { Texture2D } from ".";
|
||||
import { Color, ColorObject } from "../data";
|
||||
import { Renderer } from "../oktaeder";
|
||||
import { Color, ColorObject } from ".";
|
||||
import { Texture2D } from "../resources";
|
||||
|
||||
export const UNIFORM_BUFFER_SIZE = 64;
|
||||
|
||||
@ -26,7 +25,7 @@ export interface MaterialProps {
|
||||
|
||||
baseColorPartialCoverageTexture?: Texture2D | null;
|
||||
occlusionTexture?: Texture2D | null;
|
||||
metallicRoughnessTexture?: Texture2D | null;
|
||||
roughnessMetallicTexture?: Texture2D | null;
|
||||
normalTexture?: Texture2D | null;
|
||||
emissiveTexture?: Texture2D | null;
|
||||
transmissionCollimationTexture?: Texture2D | null;
|
||||
@ -38,7 +37,6 @@ export interface MaterialProps {
|
||||
export class Material {
|
||||
|
||||
readonly type!: "Material";
|
||||
_renderer: Renderer;
|
||||
|
||||
_name: string;
|
||||
|
||||
@ -55,7 +53,7 @@ export class Material {
|
||||
|
||||
_baseColorPartialCoverageTexture: Texture2D | null;
|
||||
_occlusionTexture: Texture2D | null;
|
||||
_metallicRoughnessTexture: Texture2D | null;
|
||||
_roughnessMetallicTexture: Texture2D | null;
|
||||
_normalTexture: Texture2D | null;
|
||||
_emissiveTexture: Texture2D | null;
|
||||
_transmissionCollimationTexture: Texture2D | null;
|
||||
@ -63,7 +61,7 @@ export class Material {
|
||||
_transparent: boolean;
|
||||
_doubleSided: boolean;
|
||||
|
||||
constructor(renderer: Renderer, {
|
||||
constructor({
|
||||
name = "",
|
||||
baseColor,
|
||||
partialCoverage = 1,
|
||||
@ -77,15 +75,13 @@ export class Material {
|
||||
ior = 1.45,
|
||||
baseColorPartialCoverageTexture = null,
|
||||
occlusionTexture = null,
|
||||
metallicRoughnessTexture = null,
|
||||
roughnessMetallicTexture = null,
|
||||
normalTexture = null,
|
||||
emissiveTexture = null,
|
||||
transmissionCollimationTexture = null,
|
||||
transparent = false,
|
||||
doubleSided = false,
|
||||
}: MaterialProps) {
|
||||
this._renderer = renderer;
|
||||
|
||||
this._name = name;
|
||||
|
||||
this._baseColor = baseColor !== undefined ? Color.fromObject(baseColor) : Color.white();
|
||||
@ -101,7 +97,7 @@ export class Material {
|
||||
|
||||
this._baseColorPartialCoverageTexture = baseColorPartialCoverageTexture;
|
||||
this._occlusionTexture = occlusionTexture;
|
||||
this._metallicRoughnessTexture = metallicRoughnessTexture;
|
||||
this._roughnessMetallicTexture = roughnessMetallicTexture;
|
||||
this._normalTexture = normalTexture;
|
||||
this._emissiveTexture = emissiveTexture;
|
||||
this._transmissionCollimationTexture = transmissionCollimationTexture;
|
||||
@ -109,15 +105,6 @@ export class Material {
|
||||
this._transparent = transparent;
|
||||
this._doubleSided = doubleSided;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys owned GPU resources. The material should not be used after
|
||||
* calling this method.
|
||||
* @returns `this` for chaining
|
||||
*/
|
||||
dispose(): Material {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(Material.prototype, "type", { value: "Material" });
|
@ -4,8 +4,7 @@
|
||||
* obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { Camera, Matrix4x4, Mesh, Quaternion, QuaternionObject, Vector3, Vector3Object } from ".";
|
||||
import { Material } from "../resources";
|
||||
import { Camera, Light, Material, Matrix4x4, Mesh, Quaternion, QuaternionObject, Vector3, Vector3Object } from ".";
|
||||
|
||||
export interface NodeProps {
|
||||
readonly name?: string;
|
||||
@ -15,6 +14,7 @@ export interface NodeProps {
|
||||
readonly scale?: Vector3Object;
|
||||
|
||||
readonly camera?: Camera | null;
|
||||
readonly light?: Light | null;
|
||||
readonly mesh?: Mesh | null;
|
||||
readonly materials?: Material[];
|
||||
|
||||
@ -33,6 +33,8 @@ export class Node {
|
||||
|
||||
/** unique */
|
||||
_camera: Camera | null;
|
||||
/** unique */
|
||||
_light: Light | null;
|
||||
/** shared */
|
||||
_mesh: Mesh | null;
|
||||
/** shared */
|
||||
@ -56,6 +58,7 @@ export class Node {
|
||||
rotation,
|
||||
scale,
|
||||
camera = null,
|
||||
light = null,
|
||||
mesh = null,
|
||||
materials = [],
|
||||
children = [],
|
||||
@ -67,6 +70,7 @@ export class Node {
|
||||
this._scale = scale !== undefined ? Vector3.fromObject(scale) : Vector3.one();
|
||||
|
||||
this._camera = camera;
|
||||
this._light = light;
|
||||
this._mesh = mesh;
|
||||
this._materials = materials;
|
||||
|
||||
@ -94,6 +98,10 @@ export class Node {
|
||||
this._camera._node = this;
|
||||
}
|
||||
|
||||
if (this._light !== null) {
|
||||
this._light._node = this;
|
||||
}
|
||||
|
||||
if (this._children !== null) {
|
||||
for (const child of this._children) {
|
||||
child._parent = this;
|
||||
@ -101,6 +109,9 @@ export class Node {
|
||||
}
|
||||
}
|
||||
|
||||
set name(value: string) { this._name = value; }
|
||||
get name(): string { return this._name; }
|
||||
|
||||
setTranslation(value: Vector3Object): Node {
|
||||
this._translation.setObject(value);
|
||||
this._localMatrixNeedsUpdate = true;
|
||||
@ -109,8 +120,7 @@ export class Node {
|
||||
}
|
||||
|
||||
getTranslation(res: Vector3): Vector3 {
|
||||
res.setObject(this._translation);
|
||||
return res;
|
||||
return res.setObject(this._translation);
|
||||
}
|
||||
|
||||
setRotation(value: QuaternionObject): Node {
|
||||
@ -121,8 +131,7 @@ export class Node {
|
||||
}
|
||||
|
||||
getRotation(res: Quaternion): Quaternion {
|
||||
res.setObject(this._rotation);
|
||||
return res;
|
||||
return res.setObject(this._rotation);
|
||||
}
|
||||
|
||||
setScale(value: Vector3Object): Node {
|
||||
@ -133,8 +142,7 @@ export class Node {
|
||||
}
|
||||
|
||||
getScale(res: Vector3): Vector3 {
|
||||
res.setObject(this._scale);
|
||||
return res;
|
||||
return res.setObject(this._scale);
|
||||
}
|
||||
|
||||
set camera(value: Camera | null) {
|
||||
@ -172,6 +180,41 @@ export class Node {
|
||||
return this;
|
||||
}
|
||||
|
||||
set light(value: Light | null) {
|
||||
if (value !== null) {
|
||||
this.attachLight(value);
|
||||
} else {
|
||||
this.detachLight();
|
||||
}
|
||||
}
|
||||
get light(): Light | null { return this._light; }
|
||||
|
||||
attachLight(light: Light): Node {
|
||||
if (this._light !== null) {
|
||||
this._light._node = null;
|
||||
}
|
||||
|
||||
this._light = light;
|
||||
|
||||
if (light._node !== null) {
|
||||
light._node._light = null;
|
||||
}
|
||||
|
||||
light._node = this;
|
||||
this._light = light;
|
||||
return this;
|
||||
}
|
||||
|
||||
detachLight(): Node {
|
||||
if (this._light === null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this._light._node = null;
|
||||
this._light = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
set mesh(value: Mesh | null) { this._mesh = value; }
|
||||
get mesh(): Mesh | null { return this._mesh; }
|
||||
|
||||
@ -269,3 +312,10 @@ Object.defineProperty(Node.prototype, "type", { value: "Node" });
|
||||
export function isNode(value: unknown): value is Node {
|
||||
return Boolean(value) && (value as Node).type === "Node";
|
||||
}
|
||||
|
||||
export function* preOrder(nodes: Iterable<Node>): Generator<Node, void, undefined> {
|
||||
for (const node of nodes) {
|
||||
yield node;
|
||||
yield* node._children;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
export * from "./Camera";
|
||||
export * from "./Color";
|
||||
export * from "./Light";
|
||||
export * from "./Material";
|
||||
export * from "./Matrix4x4";
|
||||
export * from "./Mesh";
|
||||
export * from "./Node";
|
||||
|
112
src/oktaeder.ts
112
src/oktaeder.ts
@ -8,8 +8,9 @@ export * from "./_BinaryWriter";
|
||||
export * from "./shader";
|
||||
|
||||
import { _BinaryWriter as BinaryWriter } from "./_BinaryWriter";
|
||||
import { Camera, Scene } from "./data";
|
||||
import { IndexBuffer, IndexBufferProps, Material, MaterialProps, Texture2D, Texture2DProps, VertexBuffer, VertexBufferProps } from "./resources";
|
||||
import { _Mapping as Mapping } from "./_Mapping";
|
||||
import { Camera, Material, Node, Scene, preOrder } from "./data";
|
||||
import { IndexBuffer, IndexBufferProps, Texture2D, Texture2DProps, VertexBuffer, VertexBufferProps } from "./resources";
|
||||
import { ShaderFlagKey, ShaderFlags, createPipeline, shaderFlagsKey } from "./shader";
|
||||
|
||||
export class Renderer {
|
||||
@ -36,6 +37,13 @@ export class Renderer {
|
||||
_pipelineCache: Map<ShaderFlagKey, GPURenderPipeline>;
|
||||
|
||||
_uniformWriter: BinaryWriter;
|
||||
_uniformBuffer: GPUBuffer;
|
||||
_directionalLightBuffer: GPUBuffer;
|
||||
_pointLightBuffer: GPUBuffer;
|
||||
|
||||
_sampler: GPUSampler;
|
||||
|
||||
_objectBindGroup: GPUBindGroup;
|
||||
|
||||
/**
|
||||
* This constructor is intended primarily for internal use. Consider using
|
||||
@ -204,6 +212,37 @@ export class Renderer {
|
||||
this._pipelineCache = new Map();
|
||||
|
||||
this._uniformWriter = new BinaryWriter();
|
||||
this._uniformBuffer = device.createBuffer({
|
||||
size: 4 * 1024 * 1024,
|
||||
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM,
|
||||
label: "Uniform",
|
||||
});
|
||||
this._directionalLightBuffer = device.createBuffer({
|
||||
size: 1024 * 32,
|
||||
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE,
|
||||
});
|
||||
this._pointLightBuffer = device.createBuffer({
|
||||
size: 1024 * 32,
|
||||
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.STORAGE,
|
||||
});
|
||||
|
||||
this._sampler = device.createSampler({
|
||||
addressModeU: "repeat",
|
||||
addressModeV: "repeat",
|
||||
addressModeW: "repeat",
|
||||
magFilter: "linear",
|
||||
minFilter: "linear",
|
||||
mipmapFilter: "linear",
|
||||
maxAnisotropy: 16,
|
||||
});
|
||||
|
||||
this._objectBindGroup = device.createBindGroup({
|
||||
layout: this._objectBindGroupLayout,
|
||||
entries: [
|
||||
{ binding: 0, resource: { buffer: this._uniformBuffer } },
|
||||
],
|
||||
label: "Object",
|
||||
});
|
||||
}
|
||||
|
||||
static async init(canvas: HTMLCanvasElement): Promise<Renderer> {
|
||||
@ -242,6 +281,9 @@ export class Renderer {
|
||||
this._textureBlack.dispose();
|
||||
this._textureNormal.dispose();
|
||||
this._depthBuffer.dispose();
|
||||
this._uniformBuffer.destroy();
|
||||
this._directionalLightBuffer.destroy();
|
||||
this._pointLightBuffer.destroy();
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -249,10 +291,6 @@ export class Renderer {
|
||||
return new IndexBuffer(this, props);
|
||||
}
|
||||
|
||||
createMaterial(props: MaterialProps): Material {
|
||||
return new Material(this, props);
|
||||
}
|
||||
|
||||
createTexture(props: Texture2DProps): Texture2D {
|
||||
return new Texture2D(this, props);
|
||||
}
|
||||
@ -299,8 +337,66 @@ export class Renderer {
|
||||
},
|
||||
});
|
||||
|
||||
void scene;
|
||||
void camera;
|
||||
this._uniformWriter.clear();
|
||||
|
||||
// material gather
|
||||
|
||||
const materialMapping = new Mapping<Material>();
|
||||
for (const node of preOrder(scene._nodes)) {
|
||||
for (const material of node._materials) {
|
||||
materialMapping.add(material);
|
||||
}
|
||||
}
|
||||
|
||||
const materialBindGroups = materialMapping.table.map((material) => {
|
||||
const offset = this._uniformWriter._length;
|
||||
this._uniformWriter.writeColorF32(material._baseColor);
|
||||
this._uniformWriter.writeF32(material._partialCoverage);
|
||||
this._uniformWriter.writeColorF32(material._transmission);
|
||||
this._uniformWriter.writeF32(material._collimation);
|
||||
this._uniformWriter.writeF32(material._occlusionTextureStrength);
|
||||
this._uniformWriter.writeF32(material._roughness);
|
||||
this._uniformWriter.writeF32(material._metallic);
|
||||
this._uniformWriter.writeF32(material._normalScale);
|
||||
this._uniformWriter.writeColorF32(material._emissive);
|
||||
this._uniformWriter.writeF32(material._ior);
|
||||
|
||||
const bindGroup = this._device.createBindGroup({
|
||||
layout: this._materialBindGroupLayout,
|
||||
entries: [
|
||||
{ binding: 0, resource: { buffer: this._uniformBuffer } },
|
||||
{ binding: 1, resource: this._sampler },
|
||||
{ binding: 2, resource: material._baseColorPartialCoverageTexture?._textureView ?? this._textureWhite._textureView },
|
||||
{ binding: 3, resource: material._occlusionTexture?._textureView ?? this._textureWhite._textureView },
|
||||
{ binding: 4, resource: material._roughnessMetallicTexture?._textureView ?? this._textureWhite._textureView },
|
||||
{ binding: 5, resource: material._normalTexture?._textureView ?? this._textureNormal._textureView },
|
||||
{ binding: 6, resource: material._emissiveTexture?._textureView ?? this._textureWhite._textureView },
|
||||
{ binding: 7, resource: material._transmissionCollimationTexture?._textureView ?? this._textureBlack._textureView },
|
||||
],
|
||||
label: material._name,
|
||||
});
|
||||
return { offset, bindGroup };
|
||||
});
|
||||
|
||||
// object gather
|
||||
|
||||
const objectMapping = new Mapping<Node>();
|
||||
for (const node of preOrder(scene._nodes)) {
|
||||
if (node._mesh !== null) {
|
||||
objectMapping.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
const objectOffsets = objectMapping.table.map((object) => {
|
||||
const offset = this._uniformWriter._length;
|
||||
object._updateWorldMatrix();
|
||||
this._uniformWriter.writeMatrix4x4(object._worldMatrix);
|
||||
|
||||
return offset;
|
||||
});
|
||||
|
||||
void materialBindGroups;
|
||||
void objectOffsets;
|
||||
|
||||
pass.end();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user