@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
150 lines (117 loc) • 4.79 kB
JavaScript
import {
Box3,
InstancedBufferAttribute,
InstancedBufferGeometry,
OctahedronBufferGeometry,
ShaderMaterial,
Sphere
} from "three";
import { BinaryDataType } from "../../../../../../../core/binary/type/BinaryDataType.js";
import { AABB3 } from "../../../../../../../core/geom/3d/aabb/AABB3.js";
import { aabb3_from_v3_array } from "../../../../../../../core/geom/3d/aabb/aabb3_from_v3_array.js";
import { v3_length } from "../../../../../../../core/geom/vec3/v3_length.js";
import Entity from "../../../../../../ecs/Entity.js";
import { Transform } from "../../../../../../ecs/transform/Transform.js";
import { ShadedGeometry } from "../../../../../ecs/mesh-v2/ShadedGeometry.js";
import { ShadedGeometryFlags } from "../../../../../ecs/mesh-v2/ShadedGeometryFlags.js";
import { AttributeSpec } from "../../../../../geometry/AttributeSpec.js";
import { geometry_copy } from "../../../../../geometry/instancing/geometry_copy.js";
import { AttributeDataTexture } from "../../../../../texture/AttributeDataTexture.js";
import { makeOctahedralDepthAtlas } from "../../../../gi/material/makeOctahedralDepthAtlas.js";
import { octahedral_depth_to_atlas, vector_buffer_to_attribute_texture } from "../../../probe_volume_to_textures.js";
import fragment from './visualise.frag.glsl'
import vertex from './visualise.vert.glsl'
/**
*
* @param {LightProbeVolume} lpv
*/
function makeMaterial(lpv) {
const depth_atlas = makeOctahedralDepthAtlas();
const positions = new AttributeDataTexture(
AttributeSpec.fromJSON({
name: "positions",
type: BinaryDataType.Float32,
itemSize: 3,
normalized: false
}),
256, 1
);
vector_buffer_to_attribute_texture(positions, lpv.points, lpv.count, 3);
octahedral_depth_to_atlas(lpv, depth_atlas.image.data, depth_atlas.image.width);
const material = new ShaderMaterial({
fragmentShader: [fragment].join('\n'),
vertexShader: vertex,
lights: false,
uniforms: {
lpv_t_probe_positions: {
value: positions.texture
},
lpv_t_probe_depth: {
value: depth_atlas
},
lpv_u_probe_depth_resolution:{
value: lpv.depth_map_resolution
}
}
});
return material;
}
/**
*
* @param {THREE.BufferGeometry} geometry
* @param {AABB3} bounds
*/
function buffer_geometry_set_bounds_by_aabb3(geometry, bounds) {
geometry.boundingBox = new Box3()
geometry.boundingSphere = new Sphere()
geometry.boundingBox.min.set(bounds.x0, bounds.y0, bounds.z0);
geometry.boundingBox.max.set(bounds.x1, bounds.y1, bounds.z1);
bounds.getCenter(geometry.boundingSphere.center);
geometry.boundingSphere.radius = v3_length(bounds.getHalfExtentsX(), bounds.getHalfExtentsY(), bounds.getHalfExtentsZ());
}
export class VLPDepthMapVisualisation {
/**
* @type {LightProbeVolume}
*/
#volume
set volume(lpv) {
this.#volume = lpv;
}
/**
*
* @param {LightProbeVolume} lpv
* @returns {VLPDepthMapVisualisation}
*/
static from(lpv) {
const r = new VLPDepthMapVisualisation();
r.volume = lpv;
return r;
}
build() {
const geometry = new InstancedBufferGeometry();
const volume = this.#volume;
geometry.instanceCount = volume.count;
geometry_copy(geometry, new OctahedronBufferGeometry(0.4, 4));
const positions_attribute = new InstancedBufferAttribute(new Float32Array(volume.points), 3);
geometry.setAttribute("instancePosition", positions_attribute);
const bounds = new AABB3();
aabb3_from_v3_array(bounds, volume.points, volume.points.length);
const instance_bounds = new AABB3();
const geo_position_data = geometry.getAttribute('position').array;
aabb3_from_v3_array(instance_bounds, geo_position_data, geo_position_data.length);
// extend by bounds of a single instance
bounds.x0 += instance_bounds.x0;
bounds.y0 += instance_bounds.y0;
bounds.z0 += instance_bounds.z0;
bounds.x1 += instance_bounds.x1;
bounds.y1 += instance_bounds.y1;
bounds.z1 += instance_bounds.z1;
buffer_geometry_set_bounds_by_aabb3(geometry, bounds);
const sg = ShadedGeometry.from(geometry, makeMaterial(volume));
sg.setFlag(ShadedGeometryFlags.DrawMethodLocked);
const entity = new Entity();
entity.add(new Transform());
entity.add(sg);
return entity;
}
}