Просмотр исходного кода

Add RootScene.autoGPUInstanceMeshes, GLTFMeshGpuInstancingExporter extension to GLTFExporter2, add shadow map type to render manager ui

master
Palash Bansal 1 год назад
Родитель
Сommit
5a318d9182
Аккаунт пользователя с таким Email не найден

+ 2
- 0
src/assetmanager/export/GLTFExporter2.ts Просмотреть файл

@@ -14,6 +14,7 @@ import {
GLTFObject3DExtrasExtension,
GLTFViewerConfigExtension,
} from '../gltf'
import {GLTFMeshGpuInstancingExporter} from '../../three/utils/gpu-instancing'

export interface GLTFExporter2Options {
/**
@@ -201,6 +202,7 @@ export class GLTFExporter2 extends GLTFExporter implements IExportParser {
GLTFMaterialsDisplacementMapExtension.Export,
GLTFMaterialsLightMapExtension.Export,
GLTFMaterialsAlphaMapExtension.Export,
(w)=>new GLTFMeshGpuInstancingExporter(w),
]

setup(viewer: ThreeViewer, extraExtensions?: ((parser: GLTFWriter2) => GLTFExporterPlugin)[]): this {

+ 10
- 2
src/core/object/RootScene.ts Просмотреть файл

@@ -1,4 +1,5 @@
import {
BufferGeometry,
Color,
EquirectangularReflectionMapping,
EventListener,
@@ -10,7 +11,7 @@ import {
} from 'three'
import type {IObject3D, IObjectProcessor} from '../IObject'
import {type ICamera} from '../ICamera'
import {bindToValue, Box3B} from '../../three'
import {autoGPUInstanceMeshes, bindToValue, Box3B} from '../../three'
import {AnyOptions, onChange2, onChange3, serialize} from 'ts-browser-helpers'
import {PerspectiveCamera2} from '../camera/PerspectiveCamera2'
import {ThreeSerialization} from '../../utils'
@@ -282,7 +283,7 @@ export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements I
this.setDirty({refreshScene: true})
}

@uiButton(undefined, {sendArgs: false})
@uiButton('Center All Geometries', {sendArgs: false})
centerAllGeometries(keepPosition = true, obj?: IObject3D) {
const geoms = new Set<IGeometry>()
;(obj ?? this.modelRoot).traverse((o) => o.geometry && geoms.add(o.geometry))
@@ -450,6 +451,13 @@ export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements I
})
}

@uiButton('Auto GPU Instance Meshes')
autoGPUInstanceMeshes() {
const geoms = new Set<BufferGeometry>()
this.modelRoot.traverse((o) => o.geometry && geoms.add(o.geometry))
geoms.forEach((g: any) => autoGPUInstanceMeshes(g))
}

private _v1 = new Vector3()
private _v2 = new Vector3()


+ 17
- 3
src/rendering/RenderManager.ts Просмотреть файл

@@ -10,13 +10,14 @@ import {
NormalBlending,
NoToneMapping,
PCFShadowMap,
ShadowMapType,
Texture,
Vector2,
Vector4,
WebGLMultipleRenderTargets,
WebGLRenderer,
WebGLRenderTarget,
WebGLRenderTargetOptions,
WebGLRenderTargetOptions, WebGLShadowMap,
} from 'three'
import {EffectComposer2, IPassID, IPipelinePass, sortPasses} from '../postprocessing'
import {IRenderTarget} from './RenderTarget'
@@ -42,8 +43,8 @@ import {
serialize,
ValOrArr,
} from 'ts-browser-helpers'
import {uiButton, uiConfig, uiFolderContainer, uiMonitor, uiSlider, uiToggle} from 'uiconfig.js'
import {generateUUID, textureDataToImageData} from '../three'
import {uiButton, uiConfig, uiDropdown, uiFolderContainer, uiMonitor, uiSlider, uiToggle} from 'uiconfig.js'
import {bindToValue, generateUUID, textureDataToImageData} from '../three'
import {BlobExt, EXRExporter2} from '../assetmanager'
import {RendererBlitOptions} from '../core/IRenderer'

@@ -68,6 +69,19 @@ export class RenderManager<TEvent extends BaseEvent = IRenderManagerEvent, TEven
}
}

@serialize()
@uiDropdown('Shadow Map Type', ['BasicShadowMap', 'PCFShadowMap', 'PCFSoftShadowMap', 'VSMShadowMap'].map((v, i) => ({label: v, value: i})))
@bindToValue({obj: 'shadowMap', key: 'type', onChange: RenderManager.prototype._shadowMapTypeChanged})
shadowMapType: ShadowMapType

@bindToValue({obj: 'renderer', key: 'shadowMap'})
shadowMap: WebGLShadowMap

private _shadowMapTypeChanged() {
this.resetShadows()
this.reset()
}

@uiConfig(undefined, {label: 'Passes'})
private _passes: IPipelinePass[] = []
private _pipeline: IPassID[] = []

+ 61
- 1
src/three/utils/gpu-instancing.ts Просмотреть файл

@@ -1,7 +1,9 @@
import {IGeometry, IMaterial, IObject3D} from '../../core'
import {BufferAttribute, InstancedMesh} from 'three'
import {BufferAttribute, InstancedMesh, Matrix4, Quaternion, Vector3} from 'three'
// noinspection ES6PreferShortImport
import {copyObject3DUserData} from '../../utils/serialization'
import {GLTFWriter2} from '../../assetmanager'
import {GLTFExporterPlugin} from 'three/examples/jsm/exporters/GLTFExporter'

export function autoGPUInstanceMeshes(matOrGeom: IMaterial|IGeometry) {
if (!(<IMaterial>matOrGeom).isMaterial && !(<IGeometry>matOrGeom).isBufferGeometry) return
@@ -84,3 +86,61 @@ export function autoGPUInstanceMeshes(matOrGeom: IMaterial|IGeometry) {
;(parent as any).setDirty()
}
}

export class GLTFMeshGpuInstancingExporter implements GLTFExporterPlugin {
name = 'EXT_mesh_gpu_instancing'
constructor(public writer: GLTFWriter2) {
}

writeNode(object: any, nodeDef: any): void {
if (!object.isInstancedMesh) return

const writer = this.writer

const mesh = object as InstancedMesh

// @ts-expect-error not in ts
let attributes: any = mesh.sourceTrs
if (!attributes) {
const translationAttr = new Float32Array(mesh.count * 3)
const rotationAttr = new Float32Array(mesh.count * 4)
const scaleAttr = new Float32Array(mesh.count * 3)

const matrix = new Matrix4()
const position = new Vector3()
const quaternion = new Quaternion()
const scale = new Vector3()

for (let i = 0; i < mesh.count; i++) {
mesh.getMatrixAt(i, matrix)
matrix.decompose(position, quaternion, scale)

position.toArray(translationAttr, i * 3)
quaternion.toArray(rotationAttr, i * 4)
scale.toArray(scaleAttr, i * 3)
}
attributes = {
TRANSLATION: new BufferAttribute(translationAttr, 3),
ROTATION: new BufferAttribute(rotationAttr, 4),
SCALE: new BufferAttribute(scaleAttr, 3),
}
}

attributes = {
// @ts-expect-error todo add to ts
TRANSLATION: writer.processAccessor(attributes.TRANSLATION),
ROTATION: (writer as any).processAccessor(attributes.ROTATION),
SCALE: (writer as any).processAccessor(attributes.SCALE),
}

if (mesh.instanceColor)
attributes._COLOR_0 = (writer as any).processAccessor(mesh.instanceColor)

writer.extensionsUsed[ this.name ] = true
// @ts-expect-error todo add to ts
writer.extensionsRequired[ this.name ] = true

nodeDef.extensions = nodeDef.extensions || {}
nodeDef.extensions[ this.name ] = {attributes}
}
}

+ 2
- 0
src/utils/browser-helpers.ts Просмотреть файл

@@ -4,6 +4,8 @@ export type {AnyFunction, AnyOptions, Class, IDisposable, IJSONSerializable, Par
export type {Serializer} from 'ts-browser-helpers'

export {PointerDragHelper} from 'ts-browser-helpers'
export {JSUndoManager} from 'ts-browser-helpers'
export type {JSUndoManagerCommand2, JSUndoManagerCommand, JSUndoManagerOptions, JSUndoManagerCommand1} from 'ts-browser-helpers'
export {Damper} from 'ts-browser-helpers'
export {SimpleEventDispatcher} from 'ts-browser-helpers'


Загрузка…
Отмена
Сохранить