Улучшение безопасности PBO

This commit is contained in:
2026-08-08 06:12:46 +04:00
parent a4cdfb0c9c
commit cfc9bccb89
4 changed files with 241 additions and 224 deletions
@@ -23,6 +23,7 @@ public final class FogChunkStreamer {
// Битовые маски вместо массивов статусов // Битовые маски вместо массивов статусов
private static final AtomicLongArray pendingMask = new AtomicLongArray(TOTAL_WORDS); private static final AtomicLongArray pendingMask = new AtomicLongArray(TOTAL_WORDS);
private static final AtomicLongArray readyMask = new AtomicLongArray(TOTAL_WORDS); private static final AtomicLongArray readyMask = new AtomicLongArray(TOTAL_WORDS);
private static final Object sharedStateLock = new Object();
// Pre-allocated массивы данных // Pre-allocated массивы данных
private static final byte[][] preparedData = new byte[TOTAL_CHUNKS][CHUNK_DATA_SIZE]; private static final byte[][] preparedData = new byte[TOTAL_CHUNKS][CHUNK_DATA_SIZE];
@@ -130,66 +131,68 @@ public final class FogChunkStreamer {
int newOriginChunkX, int newOriginChunkZ, int newOriginChunkX, int newOriginChunkZ,
int ringChunkOffsetX, int ringChunkOffsetZ int ringChunkOffsetX, int ringChunkOffsetZ
) { ) {
currentOriginChunkX = newOriginChunkX; synchronized (sharedStateLock) {
currentOriginChunkZ = newOriginChunkZ; currentOriginChunkX = newOriginChunkX;
currentRingChunkOffsetX = ringChunkOffsetX; currentOriginChunkZ = newOriginChunkZ;
currentRingChunkOffsetZ = ringChunkOffsetZ; currentRingChunkOffsetX = ringChunkOffsetX;
currentRingChunkOffsetZ = ringChunkOffsetZ;
if (firstUpdate) { if (firstUpdate) {
markAllPending(); markAllPending();
firstUpdate = false; firstUpdate = false;
return; return;
}
int dx = newOriginChunkX - oldOriginChunkX;
int dz = newOriginChunkZ - oldOriginChunkZ;
if (dx == 0 && dz == 0) {
return;
}
if (Math.abs(dx) >= FogWorldVolume.CHUNKS_X ||
Math.abs(dz) >= FogWorldVolume.CHUNKS_Z) {
markAllPending();
return;
}
regionCount = 0;
if (dx > 0) {
int worldX = newOriginChunkX + FogWorldVolume.CHUNKS_X - dx;
int worldZ = newOriginChunkZ;
collectRegions(worldX, worldZ, dx, FogWorldVolume.CHUNKS_Z);
markPendingRange(worldX, worldZ, dx, FogWorldVolume.CHUNKS_Z);
}
if (dx < 0) {
int worldX = newOriginChunkX;
int worldZ = newOriginChunkZ;
collectRegions(worldX, worldZ, -dx, FogWorldVolume.CHUNKS_Z);
markPendingRange(worldX, worldZ, -dx, FogWorldVolume.CHUNKS_Z);
}
if (dz > 0) {
int worldX = newOriginChunkX;
int worldZ = newOriginChunkZ + FogWorldVolume.CHUNKS_Z - dz;
collectRegions(worldX, worldZ, FogWorldVolume.CHUNKS_X, dz);
markPendingRange(worldX, worldZ, FogWorldVolume.CHUNKS_X, dz);
}
if (dz < 0) {
int worldX = newOriginChunkX;
int worldZ = newOriginChunkZ;
collectRegions(worldX, worldZ, FogWorldVolume.CHUNKS_X, -dz);
markPendingRange(worldX, worldZ, FogWorldVolume.CHUNKS_X, -dz);
}
if (regionCount > 0) {
FogWorldVolume.clearRegions(regionPhysX, regionPhysZ, regionWidth, regionDepth, regionCount);
FogDensityTextures.clearRegions(regionPhysX, regionPhysZ, regionWidth, regionDepth, regionCount);
}
uploadReadyData();
} }
int dx = newOriginChunkX - oldOriginChunkX;
int dz = newOriginChunkZ - oldOriginChunkZ;
if (dx == 0 && dz == 0) {
return;
}
if (Math.abs(dx) >= FogWorldVolume.CHUNKS_X ||
Math.abs(dz) >= FogWorldVolume.CHUNKS_Z) {
markAllPending();
return;
}
regionCount = 0;
if (dx > 0) {
int worldX = newOriginChunkX + FogWorldVolume.CHUNKS_X - dx;
int worldZ = newOriginChunkZ;
collectRegions(worldX, worldZ, dx, FogWorldVolume.CHUNKS_Z);
markPendingRange(worldX, worldZ, dx, FogWorldVolume.CHUNKS_Z);
}
if (dx < 0) {
int worldX = newOriginChunkX;
int worldZ = newOriginChunkZ;
collectRegions(worldX, worldZ, -dx, FogWorldVolume.CHUNKS_Z);
markPendingRange(worldX, worldZ, -dx, FogWorldVolume.CHUNKS_Z);
}
if (dz > 0) {
int worldX = newOriginChunkX;
int worldZ = newOriginChunkZ + FogWorldVolume.CHUNKS_Z - dz;
collectRegions(worldX, worldZ, FogWorldVolume.CHUNKS_X, dz);
markPendingRange(worldX, worldZ, FogWorldVolume.CHUNKS_X, dz);
}
if (dz < 0) {
int worldX = newOriginChunkX;
int worldZ = newOriginChunkZ;
collectRegions(worldX, worldZ, FogWorldVolume.CHUNKS_X, -dz);
markPendingRange(worldX, worldZ, FogWorldVolume.CHUNKS_X, -dz);
}
if (regionCount > 0) {
FogWorldVolume.clearRegions(regionPhysX, regionPhysZ, regionWidth, regionDepth, regionCount);
FogDensityTextures.clearRegions(regionPhysX, regionPhysZ, regionWidth, regionDepth, regionCount);
}
uploadReadyData();
} }
private static void markPendingRange(int worldX, int worldZ, int countX, int countZ) { private static void markPendingRange(int worldX, int worldZ, int countX, int countZ) {
@@ -305,75 +308,79 @@ public final class FogChunkStreamer {
} }
public static void processPending() { public static void processPending() {
int originX = currentOriginChunkX; synchronized (sharedStateLock) {
int originZ = currentOriginChunkZ; int originX = currentOriginChunkX;
int ringOffsetX = currentRingChunkOffsetX; int originZ = currentOriginChunkZ;
int ringOffsetZ = currentRingChunkOffsetZ; int ringOffsetX = currentRingChunkOffsetX;
int ringOffsetZ = currentRingChunkOffsetZ;
int processedCount = 0; int processedCount = 0;
int index = 0; int index = 0;
int limit = MAX_CHUNKS_PER_TICK + (burstFrames > 0 ? MAX_CHUNKS_PER_TICK : 0); int limit = MAX_CHUNKS_PER_TICK + (burstFrames > 0 ? MAX_CHUNKS_PER_TICK : 0);
while (processedCount < limit) { while (processedCount < limit) {
index = nextSetBit(pendingMask, index); index = nextSetBit(pendingMask, index);
if (index < 0) break; if (index < 0) break;
int physicalX = index % FogWorldVolume.CHUNKS_X; int physicalX = index % FogWorldVolume.CHUNKS_X;
int physicalZ = index / FogWorldVolume.CHUNKS_X; int physicalZ = index / FogWorldVolume.CHUNKS_X;
int worldChunkX = originX + floorMod(physicalX - ringOffsetX, FogWorldVolume.CHUNKS_X); int worldChunkX = originX + floorMod(physicalX - ringOffsetX, FogWorldVolume.CHUNKS_X);
int worldChunkZ = originZ + floorMod(physicalZ - ringOffsetZ, FogWorldVolume.CHUNKS_Z); int worldChunkZ = originZ + floorMod(physicalZ - ringOffsetZ, FogWorldVolume.CHUNKS_Z);
if (FogChunkProvider.fillChunkIntoArray(worldChunkX, worldChunkZ, preparedData[index])) { if (FogChunkProvider.fillChunkIntoArray(worldChunkX, worldChunkZ, preparedData[index])) {
preparedWorldChunkX[index] = worldChunkX; preparedWorldChunkX[index] = worldChunkX;
preparedWorldChunkZ[index] = worldChunkZ; preparedWorldChunkZ[index] = worldChunkZ;
setBit(readyMask, index); setBit(readyMask, index);
clearBit(pendingMask, index); clearBit(pendingMask, index);
processedCount++; processedCount++;
}
index++;
} }
index++; if (burstFrames > 0) burstFrames--;
} }
if (burstFrames > 0) burstFrames--;
} }
public static void uploadReadyData() { public static void uploadReadyData() {
int originX = currentOriginChunkX; synchronized (sharedStateLock) {
int originZ = currentOriginChunkZ; int originX = currentOriginChunkX;
int ringOffsetX = currentRingChunkOffsetX; int originZ = currentOriginChunkZ;
int ringOffsetZ = currentRingChunkOffsetZ; int ringOffsetX = currentRingChunkOffsetX;
int ringOffsetZ = currentRingChunkOffsetZ;
int processed = 0; int processed = 0;
int index = 0; int index = 0;
int limit = MAX_READY_CHUNK_UPLOADS_PER_TICK + (burstFrames > 0 ? MAX_READY_CHUNK_UPLOADS_PER_TICK : 0); int limit = MAX_READY_CHUNK_UPLOADS_PER_TICK + (burstFrames > 0 ? MAX_READY_CHUNK_UPLOADS_PER_TICK : 0);
FogWorldVolume.beginUpload(); FogWorldVolume.beginUpload();
while (processed < limit) { while (processed < limit) {
index = nextSetBit(readyMask, index); index = nextSetBit(readyMask, index);
if (index < 0) break; if (index < 0) break;
int physicalX = index % FogWorldVolume.CHUNKS_X; int physicalX = index % FogWorldVolume.CHUNKS_X;
int physicalZ = index / FogWorldVolume.CHUNKS_X; int physicalZ = index / FogWorldVolume.CHUNKS_X;
int currentWorldX = originX + floorMod(physicalX - ringOffsetX, FogWorldVolume.CHUNKS_X); int currentWorldX = originX + floorMod(physicalX - ringOffsetX, FogWorldVolume.CHUNKS_X);
int currentWorldZ = originZ + floorMod(physicalZ - ringOffsetZ, FogWorldVolume.CHUNKS_Z); int currentWorldZ = originZ + floorMod(physicalZ - ringOffsetZ, FogWorldVolume.CHUNKS_Z);
if (preparedWorldChunkX[index] == currentWorldX && if (preparedWorldChunkX[index] == currentWorldX &&
preparedWorldChunkZ[index] == currentWorldZ) { preparedWorldChunkZ[index] == currentWorldZ) {
FogWorldVolume.uploadChunkFromArrayNoBind(physicalX, physicalZ, preparedData[index]); FogWorldVolume.uploadChunkFromArrayNoBind(physicalX, physicalZ, preparedData[index]);
clearBit(readyMask, index); clearBit(readyMask, index);
processed++; processed++;
} else { } else {
// Координаты изменились — помечаем как pending заново // Координаты изменились — помечаем как pending заново
clearBit(readyMask, index); clearBit(readyMask, index);
setBit(pendingMask, index); setBit(pendingMask, index);
}
index++;
} }
index++; FogWorldVolume.endUpload();
if (burstFrames > 0) burstFrames--;
} }
FogWorldVolume.endUpload();
if (burstFrames > 0) burstFrames--;
} }
public static void setBurst(int frames) { public static void setBurst(int frames) {
@@ -18,6 +18,7 @@ public final class FogLightStreamer {
private static final AtomicLongArray readySkyMask = new AtomicLongArray(TOTAL_WORDS); private static final AtomicLongArray readySkyMask = new AtomicLongArray(TOTAL_WORDS);
private static final AtomicLongArray initialBlockMask = new AtomicLongArray(TOTAL_WORDS); private static final AtomicLongArray initialBlockMask = new AtomicLongArray(TOTAL_WORDS);
private static final AtomicLongArray initialSkyMask = new AtomicLongArray(TOTAL_WORDS); private static final AtomicLongArray initialSkyMask = new AtomicLongArray(TOTAL_WORDS);
private static final Object sharedStateLock = new Object();
// Flat массивы для мировых координат // Flat массивы для мировых координат
private static final int[] preparedBlockWorldX = new int[TOTAL_SECTIONS]; private static final int[] preparedBlockWorldX = new int[TOTAL_SECTIONS];
@@ -159,50 +160,52 @@ public final class FogLightStreamer {
int newOriginChunkX, int newOriginChunkZ, int newOriginChunkX, int newOriginChunkZ,
int ringChunkOffsetX, int ringChunkOffsetZ int ringChunkOffsetX, int ringChunkOffsetZ
) { ) {
currentOriginChunkX = newOriginChunkX; synchronized (sharedStateLock) {
currentOriginChunkZ = newOriginChunkZ; currentOriginChunkX = newOriginChunkX;
currentRingChunkOffsetX = ringChunkOffsetX; currentOriginChunkZ = newOriginChunkZ;
currentRingChunkOffsetZ = ringChunkOffsetZ; currentRingChunkOffsetX = ringChunkOffsetX;
currentRingChunkOffsetZ = ringChunkOffsetZ;
if (firstUpdate) { if (firstUpdate) {
markAllPending(); markAllPending();
firstUpdate = false; firstUpdate = false;
return; return;
} }
int dx = newOriginChunkX - oldOriginChunkX; int dx = newOriginChunkX - oldOriginChunkX;
int dz = newOriginChunkZ - oldOriginChunkZ; int dz = newOriginChunkZ - oldOriginChunkZ;
if (dx == 0 && dz == 0) return; if (dx == 0 && dz == 0) return;
if (Math.abs(dx) >= FogLightVolume.CHUNKS_X || Math.abs(dz) >= FogLightVolume.CHUNKS_Z) { if (Math.abs(dx) >= FogLightVolume.CHUNKS_X || Math.abs(dz) >= FogLightVolume.CHUNKS_Z) {
markAllPending(); markAllPending();
return; return;
} }
regionCount = 0; regionCount = 0;
if (dx > 0) { if (dx > 0) {
int worldX = newOriginChunkX + FogLightVolume.CHUNKS_X - dx; int worldX = newOriginChunkX + FogLightVolume.CHUNKS_X - dx;
collectRegions(worldX, newOriginChunkZ, dx, FogLightVolume.CHUNKS_Z); collectRegions(worldX, newOriginChunkZ, dx, FogLightVolume.CHUNKS_Z);
addInitialLoadForRange(worldX, newOriginChunkZ, dx, FogLightVolume.CHUNKS_Z); addInitialLoadForRange(worldX, newOriginChunkZ, dx, FogLightVolume.CHUNKS_Z);
} }
if (dx < 0) { if (dx < 0) {
collectRegions(newOriginChunkX, newOriginChunkZ, -dx, FogLightVolume.CHUNKS_Z); collectRegions(newOriginChunkX, newOriginChunkZ, -dx, FogLightVolume.CHUNKS_Z);
addInitialLoadForRange(newOriginChunkX, newOriginChunkZ, -dx, FogLightVolume.CHUNKS_Z); addInitialLoadForRange(newOriginChunkX, newOriginChunkZ, -dx, FogLightVolume.CHUNKS_Z);
} }
if (dz > 0) { if (dz > 0) {
int worldZ = newOriginChunkZ + FogLightVolume.CHUNKS_Z - dz; int worldZ = newOriginChunkZ + FogLightVolume.CHUNKS_Z - dz;
collectRegions(newOriginChunkX, worldZ, FogLightVolume.CHUNKS_X, dz); collectRegions(newOriginChunkX, worldZ, FogLightVolume.CHUNKS_X, dz);
addInitialLoadForRange(newOriginChunkX, worldZ, FogLightVolume.CHUNKS_X, dz); addInitialLoadForRange(newOriginChunkX, worldZ, FogLightVolume.CHUNKS_X, dz);
} }
if (dz < 0) { if (dz < 0) {
collectRegions(newOriginChunkX, newOriginChunkZ, FogLightVolume.CHUNKS_X, -dz); collectRegions(newOriginChunkX, newOriginChunkZ, FogLightVolume.CHUNKS_X, -dz);
addInitialLoadForRange(newOriginChunkX, newOriginChunkZ, FogLightVolume.CHUNKS_X, -dz); addInitialLoadForRange(newOriginChunkX, newOriginChunkZ, FogLightVolume.CHUNKS_X, -dz);
} }
if (regionCount > 0) { if (regionCount > 0) {
FogLightVolume.clearRegions(regionPhysX, regionPhysZ, regionWidth, regionDepth, regionCount); FogLightVolume.clearRegions(regionPhysX, regionPhysZ, regionWidth, regionDepth, regionCount);
}
} }
} }
@@ -290,90 +293,94 @@ public final class FogLightStreamer {
* обрабатываем и initial, и pending параллельно, чтобы избежать пиков. * обрабатываем и initial, и pending параллельно, чтобы избежать пиков.
*/ */
public static void prepareAllSections() { public static void prepareAllSections() {
int processedBlock = 0; synchronized (sharedStateLock) {
int processedSky = 0; int processedBlock = 0;
int processedSky = 0;
// Чередование: немного initial block, немного pending block, // Чередование: немного initial block, немного pending block,
// немного initial sky, немного pending sky // немного initial sky, немного pending sky
int index = 0; int index = 0;
int initialLimit = MAX_INITIAL_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_INITIAL_SECTIONS_PER_TICK : 0); int initialLimit = MAX_INITIAL_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_INITIAL_SECTIONS_PER_TICK : 0);
while (processedBlock < initialLimit) { while (processedBlock < initialLimit) {
index = nextSetBit(initialBlockMask, index); index = nextSetBit(initialBlockMask, index);
if (index < 0) break; if (index < 0) break;
if (prepareBlockLight(index)) { if (prepareBlockLight(index)) {
clearBit(initialBlockMask, index); clearBit(initialBlockMask, index);
processedBlock++; processedBlock++;
}
index++;
} }
index++;
}
index = 0; index = 0;
int pendingLimit = MAX_INITIAL_SECTIONS_PER_TICK + MAX_PENDING_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_PENDING_SECTIONS_PER_TICK : 0); int pendingLimit = MAX_INITIAL_SECTIONS_PER_TICK + MAX_PENDING_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_PENDING_SECTIONS_PER_TICK : 0);
while (processedBlock < pendingLimit) { while (processedBlock < pendingLimit) {
index = nextSetBit(pendingBlockMask, index); index = nextSetBit(pendingBlockMask, index);
if (index < 0) break; if (index < 0) break;
if (prepareBlockLight(index)) { if (prepareBlockLight(index)) {
clearBit(pendingBlockMask, index); clearBit(pendingBlockMask, index);
processedBlock++; processedBlock++;
}
index++;
} }
index++;
}
index = 0; index = 0;
int initialSkyLimit = MAX_INITIAL_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_INITIAL_SECTIONS_PER_TICK : 0); int initialSkyLimit = MAX_INITIAL_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_INITIAL_SECTIONS_PER_TICK : 0);
while (processedSky < initialSkyLimit) { while (processedSky < initialSkyLimit) {
index = nextSetBit(initialSkyMask, index); index = nextSetBit(initialSkyMask, index);
if (index < 0) break; if (index < 0) break;
if (prepareSkyLight(index)) { if (prepareSkyLight(index)) {
clearBit(initialSkyMask, index); clearBit(initialSkyMask, index);
processedSky++; processedSky++;
}
index++;
} }
index++;
}
index = 0; index = 0;
int pendingSkyLimit = MAX_INITIAL_SECTIONS_PER_TICK + MAX_PENDING_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_PENDING_SECTIONS_PER_TICK : 0); int pendingSkyLimit = MAX_INITIAL_SECTIONS_PER_TICK + MAX_PENDING_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_PENDING_SECTIONS_PER_TICK : 0);
while (processedSky < pendingSkyLimit) { while (processedSky < pendingSkyLimit) {
index = nextSetBit(pendingSkyMask, index); index = nextSetBit(pendingSkyMask, index);
if (index < 0) break; if (index < 0) break;
if (prepareSkyLight(index)) { if (prepareSkyLight(index)) {
clearBit(pendingSkyMask, index); clearBit(pendingSkyMask, index);
processedSky++; processedSky++;
}
index++;
} }
index++; if (burstFrames > 0) burstFrames--;
} }
if (burstFrames > 0) burstFrames--;
} }
public static void uploadReadySections() { public static void uploadReadySections() {
int processedBlock = 0; synchronized (sharedStateLock) {
int processedSky = 0; int processedBlock = 0;
int index = 0; int processedSky = 0;
FogLightVolume.beginUpload(FogLightVolume.getBlockLightTexture()); int index = 0;
int blockLimit = MAX_READY_BLOCK_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_READY_BLOCK_SECTIONS_PER_TICK : 0); FogLightVolume.beginUpload(FogLightVolume.getBlockLightTexture());
while (processedBlock < blockLimit) { int blockLimit = MAX_READY_BLOCK_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_READY_BLOCK_SECTIONS_PER_TICK : 0);
index = nextSetBit(readyBlockMask, index); while (processedBlock < blockLimit) {
if (index < 0) break; index = nextSetBit(readyBlockMask, index);
if (uploadBlockLight(index)) { if (index < 0) break;
processedBlock++; if (uploadBlockLight(index)) {
processedBlock++;
}
index++;
} }
index++; FogLightVolume.endUpload();
}
FogLightVolume.endUpload();
index = 0; index = 0;
FogLightVolume.beginUpload(FogLightVolume.getSkyLightTexture()); FogLightVolume.beginUpload(FogLightVolume.getSkyLightTexture());
int skyLimit = MAX_READY_SKY_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_READY_SKY_SECTIONS_PER_TICK : 0); int skyLimit = MAX_READY_SKY_SECTIONS_PER_TICK + (burstFrames > 0 ? MAX_READY_SKY_SECTIONS_PER_TICK : 0);
while (processedSky < skyLimit) { while (processedSky < skyLimit) {
index = nextSetBit(readySkyMask, index); index = nextSetBit(readySkyMask, index);
if (index < 0) break; if (index < 0) break;
if (uploadSkyLight(index)) { if (uploadSkyLight(index)) {
processedSky++; processedSky++;
}
index++;
} }
index++; FogLightVolume.endUpload();
if (burstFrames > 0) burstFrames--;
} }
FogLightVolume.endUpload();
if (burstFrames > 0) burstFrames--;
} }
public static void setBurst(int frames) { public static void setBurst(int frames) {
@@ -42,8 +42,9 @@ public final class FogWorldVolume {
// PBO для быстрой очистки регионов // PBO для быстрой очистки регионов
private static int clearPBO = -1; private static int clearPBO = -1;
// PBO для загрузки чанков // Ring of PBOs for chunk uploads to avoid overwriting a buffer while the GPU is still using it
private static int uploadPBO = -1; private static final int[] uploadPBOs = new int[3];
private static int uploadPBOIndex = 0;
private static final int MAX_CLEAR_SIZE = SIZE_X * SIZE_Y * SIZE_Z; private static final int MAX_CLEAR_SIZE = SIZE_X * SIZE_Y * SIZE_Z;
private FogWorldVolume() { private FogWorldVolume() {
@@ -213,10 +214,11 @@ public final class FogWorldVolume {
int textureChunkZ, int textureChunkZ,
byte[] data byte[] data
) { ) {
// Use PBO to upload without stalling the driver // Use a ring of PBOs so one upload never overwrites another still pending on the GPU
if (uploadPBO != -1) { if (uploadPBOs[0] != 0) {
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, uploadPBO); int pbo = uploadPBOs[uploadPBOIndex % uploadPBOs.length];
// Orphan and allocate uploadPBOIndex++;
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, pbo);
GL15.glBufferData(GL31.GL_PIXEL_UNPACK_BUFFER, CHUNK_SIZE * SIZE_Y * CHUNK_SIZE, GL15.GL_STREAM_DRAW); 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); ByteBuffer mapped = GL15.glMapBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, GL15.GL_WRITE_ONLY);
if (mapped != null) { if (mapped != null) {
@@ -263,10 +265,11 @@ public final class FogWorldVolume {
} }
private static void initUploadPBO() { private static void initUploadPBO() {
if (uploadPBO != -1) return; for (int i = 0; i < uploadPBOs.length; i++) {
uploadPBO = GL15.glGenBuffers(); uploadPBOs[i] = GL15.glGenBuffers();
GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, uploadPBO); GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, uploadPBOs[i]);
GL15.glBufferData(GL31.GL_PIXEL_UNPACK_BUFFER, CHUNK_SIZE * SIZE_Y * CHUNK_SIZE, GL15.GL_STREAM_DRAW); 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); GL15.glBindBuffer(GL31.GL_PIXEL_UNPACK_BUFFER, 0);
} }
@@ -43,7 +43,7 @@ const float SCATTERING_COEFF = 1.0;
const float AMBIENT_INTENSITY = 0.10; const float AMBIENT_INTENSITY = 0.10;
const float MIN_TRANSMITTANCE = 0.01; const float MIN_TRANSMITTANCE = 0.01;
const float AMBIENT_FOG = 0.01; const float AMBIENT_FOG = 0.0025;
//------------------------------------------------------------ //------------------------------------------------------------
@@ -99,7 +99,7 @@ float density(vec3 worldPos)
{ {
vec3 uv = worldToUV(worldPos); vec3 uv = worldToUV(worldPos);
if (uv.x < 0.0) return 0.0; if (uv.x < 0.0) return 0.0;
return max(texture(BlockLightVolume, uv).r, 1.0-texture(SkyLightVolume, uv).r)*0.1; return max(texture(FogVolume, uv).r, AMBIENT_FOG*texture(SkyLightVolume, uv).r);
} }
vec2 light(vec3 worldPos) vec2 light(vec3 worldPos)