mirror of
https://github.com/Terncode/pixel.horse.git
synced 2026-09-25 06:05:52 +02:00
Archive commit
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
import { Sprite, Batch, SpriteBatchBase, SpriteSheet } from '../common/interfaces';
|
||||
import { WHITE } from '../common/colors';
|
||||
import { colorToFloat, colorToFloatAlpha } from '../common/color';
|
||||
import { BaseStateBatch } from './baseStateBatch';
|
||||
import { VAO, createVAO } from './webgl/glVao';
|
||||
import { VAOAttributeDefinition, getVAOAttributesSize, createVAOAttributes } from './webgl/vaoAttributes';
|
||||
import { timeStart, timeEnd } from '../client/timing';
|
||||
import { isIdentity } from '../common/mat2d';
|
||||
|
||||
// const BATCH_BUFFER_SIZE = 2048; // 8kb
|
||||
// const BATCH_BUFFER_POOL_SIZE = 5;
|
||||
|
||||
// const pool: ArrayBuffer[] = [];
|
||||
|
||||
// function aquireBuffer(size: number): Float32Array | undefined {
|
||||
// if (size <= BATCH_BUFFER_SIZE) {
|
||||
// if (!pool.length) console.log('alloc');
|
||||
// const buffer = pool.pop() || new ArrayBuffer(BATCH_BUFFER_SIZE);
|
||||
// return new Float32Array(buffer, 0, size);
|
||||
// } else {
|
||||
// DEVELOPMENT && console.warn(`Failed to aquire buffer of size: ${size}`);
|
||||
// return undefined;
|
||||
// }
|
||||
// }
|
||||
|
||||
// function releaseBuffer(buffer: Float32Array) {
|
||||
// if (pool.length < BATCH_BUFFER_POOL_SIZE) {
|
||||
// pool.push(buffer.buffer);
|
||||
// } else {
|
||||
// console.log('delete');
|
||||
// }
|
||||
// }
|
||||
|
||||
const WHITE_FLOAT = colorToFloat(WHITE);
|
||||
|
||||
export function getColorFloat(color: number, alpha: number) {
|
||||
return (color === WHITE && alpha === 1) ? WHITE_FLOAT : colorToFloatAlpha(color, alpha);
|
||||
}
|
||||
|
||||
export abstract class BaseSpriteBatch extends BaseStateBatch implements SpriteBatchBase {
|
||||
tris = 0;
|
||||
flushes = 0;
|
||||
index = 0;
|
||||
spritesCount = 0;
|
||||
vertices!: Float32Array;
|
||||
verticesUint32!: Uint32Array;
|
||||
vao: VAO | undefined = undefined;
|
||||
rectSprite: Sprite | undefined = undefined;
|
||||
vertexBuffer: WebGLBuffer | undefined = undefined;
|
||||
indexBuffer: WebGLBuffer | undefined = undefined;
|
||||
spriteSheet: SpriteSheet | undefined = undefined;
|
||||
floatsPerSprite: number;
|
||||
batching = false;
|
||||
private startBatchIndex = 0;
|
||||
private startBatchSprites = 0;
|
||||
constructor(
|
||||
public gl: WebGLRenderingContext,
|
||||
public capacity: number,
|
||||
buffer: ArrayBuffer,
|
||||
vertexBuffer: WebGLBuffer,
|
||||
indexBuffer: WebGLBuffer,
|
||||
public attributes: VAOAttributeDefinition[],
|
||||
) {
|
||||
super();
|
||||
this.floatsPerSprite = getVAOAttributesSize(gl, attributes);
|
||||
this.vertices = new Float32Array(buffer, 0, capacity * this.floatsPerSprite);
|
||||
this.verticesUint32 = new Uint32Array(buffer, 0, capacity * this.floatsPerSprite);
|
||||
this.vertexBuffer = vertexBuffer;
|
||||
this.indexBuffer = indexBuffer;
|
||||
this.vao = createVAO(gl, createVAOAttributes(gl, attributes, vertexBuffer), indexBuffer);
|
||||
}
|
||||
dispose() {
|
||||
disposeBuffers(this.gl, this);
|
||||
}
|
||||
begin() {
|
||||
if (!this.vao) {
|
||||
throw new Error('Disposed');
|
||||
}
|
||||
|
||||
this.batching = false;
|
||||
this.vao.bind();
|
||||
}
|
||||
end() {
|
||||
if (!this.vao) {
|
||||
throw new Error('Disposed');
|
||||
}
|
||||
|
||||
this.flush();
|
||||
this.vao.unbind();
|
||||
}
|
||||
drawBatch(batch: Batch) {
|
||||
if (DEVELOPMENT && !isIdentity(this.transform)) {
|
||||
throw new Error('Cannot transform batch');
|
||||
}
|
||||
|
||||
const batchSpriteCount = (batch.length / this.floatsPerSprite) | 0;
|
||||
|
||||
if (this.capacity < (this.spritesCount + batchSpriteCount)) {
|
||||
this.flush();
|
||||
}
|
||||
|
||||
this.vertices.set(batch, this.index);
|
||||
this.index += batch.length;
|
||||
this.spritesCount += batchSpriteCount;
|
||||
this.tris += batchSpriteCount * 2;
|
||||
}
|
||||
startBatch() {
|
||||
if (this.batching) {
|
||||
throw new Error('Cannot start new batch');
|
||||
}
|
||||
|
||||
this.startBatchIndex = this.index;
|
||||
this.startBatchSprites = this.spritesCount;
|
||||
this.batching = true;
|
||||
}
|
||||
finishBatch(): Batch | undefined {
|
||||
if (!this.batching) {
|
||||
throw new Error('Cannot finish batch');
|
||||
}
|
||||
|
||||
this.batching = false;
|
||||
|
||||
try {
|
||||
// const batch = aquireBuffer(this.index - this.startBatchIndex);
|
||||
|
||||
// if (batch) {
|
||||
// batch.set(this.vertices.subarray(this.startBatchIndex, this.index));
|
||||
// }
|
||||
|
||||
// return batch;
|
||||
return this.vertices.slice(this.startBatchIndex, this.index);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
releaseBatch(_batch: Batch) {
|
||||
// releaseBuffer(batch);
|
||||
}
|
||||
flush() {
|
||||
if (this.index === 0)
|
||||
return;
|
||||
|
||||
if (!this.vao || !this.vertexBuffer) {
|
||||
throw new Error('Disposed');
|
||||
}
|
||||
|
||||
const gl = this.gl;
|
||||
|
||||
if (this.batching) {
|
||||
TIMING && timeStart('bufferSubData');
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
||||
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices.subarray(0, this.startBatchIndex));
|
||||
TIMING && timeEnd();
|
||||
|
||||
TIMING && timeStart('vao.draw');
|
||||
this.vao.draw(this.gl.TRIANGLES, this.startBatchSprites * 6, 0);
|
||||
TIMING && timeEnd();
|
||||
|
||||
this.spritesCount -= this.startBatchSprites;
|
||||
this.index -= this.startBatchIndex;
|
||||
this.vertices.copyWithin(0, this.startBatchIndex, this.startBatchIndex + this.index);
|
||||
this.startBatchIndex = 0;
|
||||
this.startBatchSprites = 0;
|
||||
} else {
|
||||
TIMING && timeStart('bufferSubData');
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
||||
gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertices.subarray(0, this.index));
|
||||
TIMING && timeEnd();
|
||||
|
||||
TIMING && timeStart('vao.draw');
|
||||
this.vao.draw(this.gl.TRIANGLES, this.spritesCount * 6, 0);
|
||||
TIMING && timeEnd();
|
||||
|
||||
this.spritesCount = 0;
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
this.flushes++;
|
||||
}
|
||||
}
|
||||
|
||||
function disposeBuffers(gl: WebGLRenderingContext, batch: BaseSpriteBatch) {
|
||||
try {
|
||||
if (batch.vao) {
|
||||
batch.vao.dispose();
|
||||
}
|
||||
|
||||
if (batch.vertexBuffer) {
|
||||
gl.deleteBuffer(batch.vertexBuffer);
|
||||
}
|
||||
|
||||
if (batch.indexBuffer) {
|
||||
gl.deleteBuffer(batch.indexBuffer);
|
||||
}
|
||||
} catch (e) {
|
||||
DEVELOPMENT && console.error(e);
|
||||
}
|
||||
|
||||
batch.vao = undefined;
|
||||
batch.vertexBuffer = undefined;
|
||||
batch.indexBuffer = undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user