Хорошие оптимизации PBO
This commit is contained in:
@@ -17,6 +17,8 @@ public final class FogChunkStreamer {
|
||||
FogWorldVolume.CHUNK_SIZE;
|
||||
|
||||
private static final int MAX_CHUNKS_PER_TICK = 4;
|
||||
private static final int MAX_READY_CHUNK_UPLOADS_PER_TICK = 4;
|
||||
private static volatile int burstFrames = 0;
|
||||
|
||||
// Битовые маски вместо массивов статусов
|
||||
private static final AtomicLongArray pendingMask = new AtomicLongArray(TOTAL_WORDS);
|
||||
@@ -143,14 +145,12 @@ public final class FogChunkStreamer {
|
||||
int dz = newOriginChunkZ - oldOriginChunkZ;
|
||||
|
||||
if (dx == 0 && dz == 0) {
|
||||
uploadReadyData();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Math.abs(dx) >= FogWorldVolume.CHUNKS_X ||
|
||||
Math.abs(dz) >= FogWorldVolume.CHUNKS_Z) {
|
||||
markAllPending();
|
||||
uploadReadyData();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -313,7 +313,9 @@ public final class FogChunkStreamer {
|
||||
int processedCount = 0;
|
||||
int index = 0;
|
||||
|
||||
while (processedCount < MAX_CHUNKS_PER_TICK) {
|
||||
int limit = MAX_CHUNKS_PER_TICK + (burstFrames > 0 ? MAX_CHUNKS_PER_TICK : 0);
|
||||
|
||||
while (processedCount < limit) {
|
||||
index = nextSetBit(pendingMask, index);
|
||||
if (index < 0) break;
|
||||
|
||||
@@ -332,6 +334,7 @@ public final class FogChunkStreamer {
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (burstFrames > 0) burstFrames--;
|
||||
}
|
||||
|
||||
public static void uploadReadyData() {
|
||||
@@ -340,8 +343,13 @@ public final class FogChunkStreamer {
|
||||
int ringOffsetX = currentRingChunkOffsetX;
|
||||
int ringOffsetZ = currentRingChunkOffsetZ;
|
||||
|
||||
int processed = 0;
|
||||
int index = 0;
|
||||
while (true) {
|
||||
|
||||
int limit = MAX_READY_CHUNK_UPLOADS_PER_TICK + (burstFrames > 0 ? MAX_READY_CHUNK_UPLOADS_PER_TICK : 0);
|
||||
|
||||
FogWorldVolume.beginUpload();
|
||||
while (processed < limit) {
|
||||
index = nextSetBit(readyMask, index);
|
||||
if (index < 0) break;
|
||||
|
||||
@@ -354,8 +362,9 @@ public final class FogChunkStreamer {
|
||||
if (preparedWorldChunkX[index] == currentWorldX &&
|
||||
preparedWorldChunkZ[index] == currentWorldZ) {
|
||||
|
||||
FogWorldVolume.uploadChunkFromArray(physicalX, physicalZ, preparedData[index]);
|
||||
FogWorldVolume.uploadChunkFromArrayNoBind(physicalX, physicalZ, preparedData[index]);
|
||||
clearBit(readyMask, index);
|
||||
processed++;
|
||||
} else {
|
||||
// Координаты изменились — помечаем как pending заново
|
||||
clearBit(readyMask, index);
|
||||
@@ -363,5 +372,11 @@ public final class FogChunkStreamer {
|
||||
}
|
||||
index++;
|
||||
}
|
||||
FogWorldVolume.endUpload();
|
||||
if (burstFrames > 0) burstFrames--;
|
||||
}
|
||||
|
||||
public static void setBurst(int frames) {
|
||||
burstFrames = Math.max(burstFrames, frames);
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,11 @@ public final class FogLightStreamer {
|
||||
private static final int[] preparedSkyWorldZ = new int[TOTAL_SECTIONS];
|
||||
|
||||
// Более равномерное распределение: меньше initial за раз, больше incremental
|
||||
private static final int MAX_INITIAL_SECTIONS_PER_TICK = 32; // Было 96
|
||||
private static final int MAX_PENDING_SECTIONS_PER_TICK = 64; // Новый параметр
|
||||
private static final int MAX_INITIAL_SECTIONS_PER_TICK = 16;
|
||||
private static final int MAX_PENDING_SECTIONS_PER_TICK = 16;
|
||||
private static final int MAX_READY_BLOCK_SECTIONS_PER_TICK = 8;
|
||||
private static final int MAX_READY_SKY_SECTIONS_PER_TICK = 8;
|
||||
private static volatile int burstFrames = 0;
|
||||
|
||||
private static volatile int currentOriginChunkX;
|
||||
private static volatile int currentOriginChunkZ;
|
||||
@@ -293,7 +296,8 @@ public final class FogLightStreamer {
|
||||
// Чередование: немного initial block, немного pending block,
|
||||
// немного initial sky, немного pending sky
|
||||
int index = 0;
|
||||
while (processedBlock < MAX_INITIAL_SECTIONS_PER_TICK) {
|
||||
int initialLimit = MAX_INITIAL_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_INITIAL_SECTIONS_PER_TICK : 0);
|
||||
while (processedBlock < initialLimit) {
|
||||
index = nextSetBit(initialBlockMask, index);
|
||||
if (index < 0) break;
|
||||
if (prepareBlockLight(index)) {
|
||||
@@ -304,7 +308,8 @@ public final class FogLightStreamer {
|
||||
}
|
||||
|
||||
index = 0;
|
||||
while (processedBlock < MAX_INITIAL_SECTIONS_PER_TICK + MAX_PENDING_SECTIONS_PER_TICK) {
|
||||
int pendingLimit = MAX_INITIAL_SECTIONS_PER_TICK + MAX_PENDING_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_PENDING_SECTIONS_PER_TICK : 0);
|
||||
while (processedBlock < pendingLimit) {
|
||||
index = nextSetBit(pendingBlockMask, index);
|
||||
if (index < 0) break;
|
||||
if (prepareBlockLight(index)) {
|
||||
@@ -315,7 +320,8 @@ public final class FogLightStreamer {
|
||||
}
|
||||
|
||||
index = 0;
|
||||
while (processedSky < MAX_INITIAL_SECTIONS_PER_TICK) {
|
||||
int initialSkyLimit = MAX_INITIAL_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_INITIAL_SECTIONS_PER_TICK : 0);
|
||||
while (processedSky < initialSkyLimit) {
|
||||
index = nextSetBit(initialSkyMask, index);
|
||||
if (index < 0) break;
|
||||
if (prepareSkyLight(index)) {
|
||||
@@ -326,7 +332,8 @@ public final class FogLightStreamer {
|
||||
}
|
||||
|
||||
index = 0;
|
||||
while (processedSky < MAX_INITIAL_SECTIONS_PER_TICK + MAX_PENDING_SECTIONS_PER_TICK) {
|
||||
int pendingSkyLimit = MAX_INITIAL_SECTIONS_PER_TICK + MAX_PENDING_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_PENDING_SECTIONS_PER_TICK : 0);
|
||||
while (processedSky < pendingSkyLimit) {
|
||||
index = nextSetBit(pendingSkyMask, index);
|
||||
if (index < 0) break;
|
||||
if (prepareSkyLight(index)) {
|
||||
@@ -335,30 +342,42 @@ public final class FogLightStreamer {
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (burstFrames > 0) burstFrames--;
|
||||
}
|
||||
|
||||
public static void uploadReadySections() {
|
||||
int processed = 0;
|
||||
int processedBlock = 0;
|
||||
int processedSky = 0;
|
||||
int index = 0;
|
||||
|
||||
while (processed < MAX_PENDING_SECTIONS_PER_TICK) {
|
||||
FogLightVolume.beginUpload(FogLightVolume.getBlockLightTexture());
|
||||
int blockLimit = MAX_READY_BLOCK_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_READY_BLOCK_SECTIONS_PER_TICK : 0);
|
||||
while (processedBlock < blockLimit) {
|
||||
index = nextSetBit(readyBlockMask, index);
|
||||
if (index < 0) break;
|
||||
if (uploadBlockLight(index)) {
|
||||
processed++;
|
||||
processedBlock++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
FogLightVolume.endUpload();
|
||||
|
||||
index = 0;
|
||||
while (processed < MAX_PENDING_SECTIONS_PER_TICK * 2) {
|
||||
FogLightVolume.beginUpload(FogLightVolume.getSkyLightTexture());
|
||||
int skyLimit = MAX_READY_SKY_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_READY_SKY_SECTIONS_PER_TICK : 0);
|
||||
while (processedSky < skyLimit) {
|
||||
index = nextSetBit(readySkyMask, index);
|
||||
if (index < 0) break;
|
||||
if (uploadSkyLight(index)) {
|
||||
processed++;
|
||||
processedSky++;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
FogLightVolume.endUpload();
|
||||
if (burstFrames > 0) burstFrames--;
|
||||
}
|
||||
|
||||
public static void setBurst(int frames) {
|
||||
burstFrames = Math.max(burstFrames, frames);
|
||||
}
|
||||
|
||||
private static boolean prepareBlockLight(int index) {
|
||||
@@ -420,7 +439,7 @@ public final class FogLightStreamer {
|
||||
return false;
|
||||
}
|
||||
|
||||
FogLightVolume.uploadBlockLightSection(physicalX, localSectionY, physicalZ,
|
||||
FogLightVolume.uploadBlockLightSectionNoBind(physicalX, localSectionY, physicalZ,
|
||||
FogLightProvider.getBlockLightData(index));
|
||||
clearBit(readyBlockMask, index);
|
||||
return true;
|
||||
@@ -443,7 +462,7 @@ public final class FogLightStreamer {
|
||||
return false;
|
||||
}
|
||||
|
||||
FogLightVolume.uploadSkyLightSection(physicalX, localSectionY, physicalZ,
|
||||
FogLightVolume.uploadSkyLightSectionNoBind(physicalX, localSectionY, physicalZ,
|
||||
FogLightProvider.getSkyLightData(index));
|
||||
clearBit(readySkyMask, index);
|
||||
return true;
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
// No GL43 usage: keep compatibility with OpenGL 3.2
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -43,6 +44,8 @@ public final class FogLightVolume {
|
||||
// PBO для быстрой очистки
|
||||
private static int clearBlockPBO = -1;
|
||||
private static int clearSkyPBO = -1;
|
||||
// PBO для загрузки секций
|
||||
private static int uploadPBO = -1;
|
||||
|
||||
// Буферы для загрузки секций
|
||||
private static final ByteBuffer BLOCK_SECTION_UPLOAD_BUFFER =
|
||||
@@ -92,6 +95,7 @@ public final class FogLightVolume {
|
||||
if (blockLightTexture != -1) return;
|
||||
|
||||
initClearPBOs();
|
||||
initUploadPBO();
|
||||
|
||||
// Block light texture
|
||||
blockLightTexture = GL11.glGenTextures();
|
||||
@@ -177,20 +181,14 @@ public final class FogLightVolume {
|
||||
BLOCK_SECTION_UPLOAD_BUFFER.put(data);
|
||||
BLOCK_SECTION_UPLOAD_BUFFER.flip();
|
||||
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, blockLightTexture);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, 0);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_PIXELS, 0);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 0);
|
||||
|
||||
beginUpload(blockLightTexture);
|
||||
GL30.glTexSubImage3D(
|
||||
GL12.GL_TEXTURE_3D, 0,
|
||||
textureSectionX * CHUNK_SIZE, textureSectionY * 16, textureSectionZ * CHUNK_SIZE,
|
||||
16, 16, 16,
|
||||
GL11.GL_RED, GL11.GL_UNSIGNED_BYTE, BLOCK_SECTION_UPLOAD_BUFFER
|
||||
);
|
||||
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, 0);
|
||||
endUpload();
|
||||
}
|
||||
|
||||
public static void uploadSkyLightSection(
|
||||
@@ -200,11 +198,72 @@ public final class FogLightVolume {
|
||||
SKY_SECTION_UPLOAD_BUFFER.put(data);
|
||||
SKY_SECTION_UPLOAD_BUFFER.flip();
|
||||
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, skyLightTexture);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, 0);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_PIXELS, 0);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 0);
|
||||
beginUpload(skyLightTexture);
|
||||
GL30.glTexSubImage3D(
|
||||
GL12.GL_TEXTURE_3D, 0,
|
||||
textureSectionX * CHUNK_SIZE, textureSectionY * 16, textureSectionZ * CHUNK_SIZE,
|
||||
16, 16, 16,
|
||||
GL11.GL_RED, GL11.GL_UNSIGNED_BYTE, SKY_SECTION_UPLOAD_BUFFER
|
||||
);
|
||||
endUpload();
|
||||
}
|
||||
|
||||
public static void uploadBlockLightSectionNoBind(
|
||||
int textureSectionX, int textureSectionY, int textureSectionZ, byte[] data
|
||||
) {
|
||||
// Try to upload via PBO to avoid CPU->GPU stalls
|
||||
if (uploadPBO != -1) {
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, uploadPBO);
|
||||
GL15.glBufferData(GL31.GL_PIXEL_UNPACK_BUFFER, BLOCK_SECTION_UPLOAD_BUFFER.capacity(), GL15.GL_STREAM_DRAW);
|
||||
ByteBuffer mapped = GL15.glMapBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, GL15.GL_WRITE_ONLY);
|
||||
if (mapped != null) {
|
||||
mapped.put(data);
|
||||
GL15.glUnmapBuffer(GL31.GL_PIXEL_UNPACK_BUFFER);
|
||||
|
||||
GL30.glTexSubImage3D(
|
||||
GL12.GL_TEXTURE_3D, 0,
|
||||
textureSectionX * CHUNK_SIZE, textureSectionY * 16, textureSectionZ * CHUNK_SIZE,
|
||||
16, 16, 16,
|
||||
GL11.GL_RED, GL11.GL_UNSIGNED_BYTE, 0L
|
||||
);
|
||||
}
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
} else {
|
||||
BLOCK_SECTION_UPLOAD_BUFFER.clear();
|
||||
BLOCK_SECTION_UPLOAD_BUFFER.put(data);
|
||||
BLOCK_SECTION_UPLOAD_BUFFER.flip();
|
||||
GL30.glTexSubImage3D(
|
||||
GL12.GL_TEXTURE_3D, 0,
|
||||
textureSectionX * CHUNK_SIZE, textureSectionY * 16, textureSectionZ * CHUNK_SIZE,
|
||||
16, 16, 16,
|
||||
GL11.GL_RED, GL11.GL_UNSIGNED_BYTE, BLOCK_SECTION_UPLOAD_BUFFER
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void uploadSkyLightSectionNoBind(
|
||||
int textureSectionX, int textureSectionY, int textureSectionZ, byte[] data
|
||||
) {
|
||||
if (uploadPBO != -1) {
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, uploadPBO);
|
||||
GL15.glBufferData(GL31.GL_PIXEL_UNPACK_BUFFER, SKY_SECTION_UPLOAD_BUFFER.capacity(), GL15.GL_STREAM_DRAW);
|
||||
ByteBuffer mapped = GL15.glMapBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, GL15.GL_WRITE_ONLY);
|
||||
if (mapped != null) {
|
||||
mapped.put(data);
|
||||
GL15.glUnmapBuffer(GL31.GL_PIXEL_UNPACK_BUFFER);
|
||||
|
||||
GL30.glTexSubImage3D(
|
||||
GL12.GL_TEXTURE_3D, 0,
|
||||
textureSectionX * CHUNK_SIZE, textureSectionY * 16, textureSectionZ * CHUNK_SIZE,
|
||||
16, 16, 16,
|
||||
GL11.GL_RED, GL11.GL_UNSIGNED_BYTE, 0L
|
||||
);
|
||||
}
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
} else {
|
||||
SKY_SECTION_UPLOAD_BUFFER.clear();
|
||||
SKY_SECTION_UPLOAD_BUFFER.put(data);
|
||||
SKY_SECTION_UPLOAD_BUFFER.flip();
|
||||
|
||||
GL30.glTexSubImage3D(
|
||||
GL12.GL_TEXTURE_3D, 0,
|
||||
@@ -212,7 +271,18 @@ public final class FogLightVolume {
|
||||
16, 16, 16,
|
||||
GL11.GL_RED, GL11.GL_UNSIGNED_BYTE, SKY_SECTION_UPLOAD_BUFFER
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void beginUpload(int texture) {
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, texture);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, 0);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_PIXELS, 0);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 0);
|
||||
}
|
||||
|
||||
public static void endUpload() {
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, 0);
|
||||
}
|
||||
|
||||
@@ -229,6 +299,7 @@ public final class FogLightVolume {
|
||||
int[] widthChunks, int[] depthChunks,
|
||||
int count
|
||||
) {
|
||||
// Use PBO-based clears for OpenGL 3.2 compatibility
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, 0);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_PIXELS, 0);
|
||||
@@ -268,4 +339,12 @@ public final class FogLightVolume {
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, 0);
|
||||
}
|
||||
|
||||
private static void initUploadPBO() {
|
||||
if (uploadPBO != -1) return;
|
||||
uploadPBO = GL15.glGenBuffers();
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, uploadPBO);
|
||||
GL15.glBufferData(GL31.GL_PIXEL_UNPACK_BUFFER, BLOCK_SECTION_UPLOAD_BUFFER.capacity(), GL15.GL_STREAM_DRAW);
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,9 @@ public final class FogSystem {
|
||||
ringChunkOffsetX,
|
||||
ringChunkOffsetZ
|
||||
);
|
||||
// Boost uploads for a few frames to catch up after a window shift
|
||||
FogChunkStreamer.setBurst(8);
|
||||
FogLightStreamer.setBurst(8);
|
||||
}
|
||||
|
||||
public static int originChunkX() {
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
// No GL43 usage: keep compatibility with OpenGL 3.2
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -41,6 +42,8 @@ public final class FogWorldVolume {
|
||||
|
||||
// PBO для быстрой очистки регионов
|
||||
private static int clearPBO = -1;
|
||||
// PBO для загрузки чанков
|
||||
private static int uploadPBO = -1;
|
||||
private static final int MAX_CLEAR_SIZE = SIZE_X * SIZE_Y * SIZE_Z;
|
||||
|
||||
private FogWorldVolume() {
|
||||
@@ -72,6 +75,7 @@ public final class FogWorldVolume {
|
||||
|
||||
// Инициализируем PBO ДО создания текстуры
|
||||
initClearPBO();
|
||||
initUploadPBO();
|
||||
|
||||
texture = GL11.glGenTextures();
|
||||
|
||||
@@ -196,6 +200,76 @@ public final class FogWorldVolume {
|
||||
uploadChunk(textureChunkX, textureChunkZ, buffer);
|
||||
}
|
||||
|
||||
public static void beginUpload() {
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, texture);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, 0);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_PIXELS, 0);
|
||||
GL11.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 0);
|
||||
}
|
||||
|
||||
public static void uploadChunkFromArrayNoBind(
|
||||
int textureChunkX,
|
||||
int textureChunkZ,
|
||||
byte[] data
|
||||
) {
|
||||
// Use PBO to upload without stalling the driver
|
||||
if (uploadPBO != -1) {
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, uploadPBO);
|
||||
// Orphan and allocate
|
||||
GL15.glBufferData(GL31.GL_PIXEL_UNPACK_BUFFER, CHUNK_SIZE * SIZE_Y * CHUNK_SIZE, GL15.GL_STREAM_DRAW);
|
||||
ByteBuffer mapped = GL15.glMapBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, GL15.GL_WRITE_ONLY);
|
||||
if (mapped != null) {
|
||||
mapped.put(data);
|
||||
GL15.glUnmapBuffer(GL31.GL_PIXEL_UNPACK_BUFFER);
|
||||
|
||||
GL30.glTexSubImage3D(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
0,
|
||||
textureChunkX * CHUNK_SIZE,
|
||||
0,
|
||||
textureChunkZ * CHUNK_SIZE,
|
||||
CHUNK_SIZE,
|
||||
SIZE_Y,
|
||||
CHUNK_SIZE,
|
||||
GL30.GL_RED_INTEGER,
|
||||
GL11.GL_UNSIGNED_BYTE,
|
||||
0L
|
||||
);
|
||||
}
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
} else {
|
||||
ByteBuffer buffer = chunkBuffer();
|
||||
buffer.put(data);
|
||||
buffer.flip();
|
||||
GL30.glTexSubImage3D(
|
||||
GL12.GL_TEXTURE_3D,
|
||||
0,
|
||||
textureChunkX * CHUNK_SIZE,
|
||||
0,
|
||||
textureChunkZ * CHUNK_SIZE,
|
||||
CHUNK_SIZE,
|
||||
SIZE_Y,
|
||||
CHUNK_SIZE,
|
||||
GL30.GL_RED_INTEGER,
|
||||
GL11.GL_UNSIGNED_BYTE,
|
||||
buffer
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void endUpload() {
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, 0);
|
||||
}
|
||||
|
||||
private static void initUploadPBO() {
|
||||
if (uploadPBO != -1) return;
|
||||
uploadPBO = GL15.glGenBuffers();
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, uploadPBO);
|
||||
GL15.glBufferData(GL31.GL_PIXEL_UNPACK_BUFFER, CHUNK_SIZE * SIZE_Y * CHUNK_SIZE, GL15.GL_STREAM_DRAW);
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
public static ByteBuffer chunkBuffer() {
|
||||
CHUNK_BUFFER.clear();
|
||||
return CHUNK_BUFFER;
|
||||
@@ -214,6 +288,7 @@ public final class FogWorldVolume {
|
||||
int[] widthChunks, int[] depthChunks,
|
||||
int count
|
||||
) {
|
||||
// Use PBO-based clears for OpenGL 3.2 compatibility
|
||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, texture);
|
||||
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, clearPBO);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user