Complete 3D metaverse platform with: - Three.js 3D rendering - Cannon.js physics engine - Pointer lock controls - Procedural cityscape - Floating islands - Portal system - Particle effects - WebXR/VR support ready - Multiplayer ready (Socket.io) Features: - First-person controls (WASD + mouse) - Jump and run mechanics - Chat system - Real-time HUD - Loading screen - Responsive design Built with Vite for fast builds and hot reload. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
172 lines
3.7 KiB
JavaScript
172 lines
3.7 KiB
JavaScript
import { IntType } from 'three';
|
|
|
|
class WebGLAttributeUtils {
|
|
|
|
constructor( backend ) {
|
|
|
|
this.backend = backend;
|
|
|
|
}
|
|
|
|
createAttribute( attribute, bufferType ) {
|
|
|
|
const backend = this.backend;
|
|
const { gl } = backend;
|
|
|
|
const array = attribute.array;
|
|
const usage = attribute.usage || gl.STATIC_DRAW;
|
|
|
|
const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute;
|
|
const bufferData = backend.get( bufferAttribute );
|
|
|
|
let bufferGPU = bufferData.bufferGPU;
|
|
|
|
if ( bufferGPU === undefined ) {
|
|
|
|
bufferGPU = gl.createBuffer();
|
|
|
|
gl.bindBuffer( bufferType, bufferGPU );
|
|
gl.bufferData( bufferType, array, usage );
|
|
gl.bindBuffer( bufferType, null );
|
|
|
|
bufferData.bufferGPU = bufferGPU;
|
|
bufferData.bufferType = bufferType;
|
|
bufferData.version = bufferAttribute.version;
|
|
|
|
}
|
|
|
|
//attribute.onUploadCallback();
|
|
|
|
let type;
|
|
|
|
if ( array instanceof Float32Array ) {
|
|
|
|
type = gl.FLOAT;
|
|
|
|
} else if ( array instanceof Uint16Array ) {
|
|
|
|
if ( attribute.isFloat16BufferAttribute ) {
|
|
|
|
type = gl.HALF_FLOAT;
|
|
|
|
} else {
|
|
|
|
type = gl.UNSIGNED_SHORT;
|
|
|
|
}
|
|
|
|
} else if ( array instanceof Int16Array ) {
|
|
|
|
type = gl.SHORT;
|
|
|
|
} else if ( array instanceof Uint32Array ) {
|
|
|
|
type = gl.UNSIGNED_INT;
|
|
|
|
} else if ( array instanceof Int32Array ) {
|
|
|
|
type = gl.INT;
|
|
|
|
} else if ( array instanceof Int8Array ) {
|
|
|
|
type = gl.BYTE;
|
|
|
|
} else if ( array instanceof Uint8Array ) {
|
|
|
|
type = gl.UNSIGNED_BYTE;
|
|
|
|
} else if ( array instanceof Uint8ClampedArray ) {
|
|
|
|
type = gl.UNSIGNED_BYTE;
|
|
|
|
} else {
|
|
|
|
throw new Error( 'THREE.WebGLBackend: Unsupported buffer data format: ' + array );
|
|
|
|
}
|
|
|
|
backend.set( attribute, {
|
|
bufferGPU,
|
|
type,
|
|
bytesPerElement: array.BYTES_PER_ELEMENT,
|
|
version: attribute.version,
|
|
isInteger: type === gl.INT || type === gl.UNSIGNED_INT || attribute.gpuType === IntType
|
|
} );
|
|
|
|
}
|
|
|
|
updateAttribute( attribute ) {
|
|
|
|
const backend = this.backend;
|
|
const { gl } = backend;
|
|
|
|
const array = attribute.array;
|
|
const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute;
|
|
const bufferData = backend.get( bufferAttribute );
|
|
const bufferType = bufferData.bufferType;
|
|
const updateRanges = attribute.isInterleavedBufferAttribute ? attribute.data.updateRanges : attribute.updateRanges;
|
|
|
|
gl.bindBuffer( bufferType, bufferData.bufferGPU );
|
|
|
|
if ( updateRanges.length === 0 ) {
|
|
|
|
// Not using update ranges
|
|
|
|
gl.bufferSubData( bufferType, 0, array );
|
|
|
|
} else {
|
|
|
|
for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
|
|
|
|
const range = updateRanges[ i ];
|
|
gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
|
|
array, range.start, range.count );
|
|
|
|
}
|
|
|
|
bufferAttribute.clearUpdateRanges();
|
|
|
|
}
|
|
|
|
gl.bindBuffer( bufferType, null );
|
|
|
|
bufferData.version = bufferAttribute.version;
|
|
|
|
}
|
|
|
|
async getArrayBufferAsync( attribute ) {
|
|
|
|
const backend = this.backend;
|
|
const { gl } = backend;
|
|
|
|
const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute;
|
|
const { bufferGPU } = backend.get( bufferAttribute );
|
|
|
|
const array = attribute.array;
|
|
const byteLength = array.byteLength;
|
|
|
|
gl.bindBuffer( gl.COPY_READ_BUFFER, bufferGPU );
|
|
|
|
const writeBuffer = gl.createBuffer();
|
|
|
|
gl.bindBuffer( gl.COPY_WRITE_BUFFER, writeBuffer );
|
|
gl.bufferData( gl.COPY_WRITE_BUFFER, byteLength, gl.STREAM_READ );
|
|
|
|
gl.copyBufferSubData( gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, byteLength );
|
|
|
|
await backend.utils._clientWaitAsync();
|
|
|
|
const dstBuffer = new attribute.array.constructor( array.length );
|
|
|
|
gl.getBufferSubData( gl.COPY_WRITE_BUFFER, 0, dstBuffer );
|
|
|
|
gl.deleteBuffer( writeBuffer );
|
|
|
|
return dstBuffer.buffer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
export default WebGLAttributeUtils;
|