Улучшение безопасности PBO
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user