preparing the mod for future buffer caching
This commit is contained in:
@@ -124,7 +124,7 @@ public class LodBufferBuilder
|
||||
* swapped with the drawable buffers in the LodRenderer to be drawn.
|
||||
*/
|
||||
public void generateLodBuffersAsync(LodRenderer renderer, LodDimension lodDim,
|
||||
BlockPos playerBlockPos, int xAngle, int yAngle, int numbChunksWide)
|
||||
BlockPos playerBlockPos, boolean fullRegen)
|
||||
{
|
||||
// only allow one generation process to happen at a time
|
||||
if (generatingBuffers)
|
||||
@@ -158,7 +158,7 @@ public class LodBufferBuilder
|
||||
|
||||
ArrayList<Callable<Boolean>> nodeToRenderThreads = new ArrayList<>(lodDim.regions.length * lodDim.regions.length);
|
||||
|
||||
startBuffers();
|
||||
startBuffers(fullRegen, lodDim);
|
||||
|
||||
// =====================//
|
||||
// RENDERING PART //
|
||||
@@ -185,6 +185,8 @@ public class LodBufferBuilder
|
||||
{
|
||||
for (int zRegion = 0; zRegion < lodDim.regions.length; zRegion++)
|
||||
{
|
||||
//if (lodDim.regen[xRegion][zRegion])
|
||||
// ClientProxy.LOGGER.debug("Rendering region " + xRegion + " " + zRegion);
|
||||
RegionPos regionPos = new RegionPos(
|
||||
xRegion + lodDim.getCenterX() - Math.floorDiv(lodDim.getWidth(), 2),
|
||||
zRegion + lodDim.getCenterZ() - Math.floorDiv(lodDim.getWidth(), 2));
|
||||
@@ -202,15 +204,19 @@ public class LodBufferBuilder
|
||||
setsToRender[xRegion][zRegion] = new ConcurrentHashMap<LevelPos, MutableBoolean>();
|
||||
}
|
||||
ConcurrentMap<LevelPos, MutableBoolean> nodeToRender = (ConcurrentMap<LevelPos, MutableBoolean>) setsToRender[xRegion][zRegion];
|
||||
|
||||
final boolean regen = fullRegen;
|
||||
final boolean regenReg = lodDim.regen[xRegion][zRegion];
|
||||
Callable<Boolean> dataToRenderThread = () ->
|
||||
{
|
||||
lodDim.getDataToRender(
|
||||
nodeToRender,
|
||||
regionPos,
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ());
|
||||
|
||||
if (regen || regenReg)
|
||||
{
|
||||
lodDim.getDataToRender(
|
||||
nodeToRender,
|
||||
regionPos,
|
||||
playerBlockPosRounded.getX(),
|
||||
playerBlockPosRounded.getZ());
|
||||
}
|
||||
|
||||
int posX;
|
||||
int posZ;
|
||||
@@ -281,7 +287,6 @@ public class LodBufferBuilder
|
||||
|
||||
|
||||
nodeToRenderThreads.add(dataToRenderThread);
|
||||
|
||||
}// region z
|
||||
}// region z
|
||||
long renderStart = System.currentTimeMillis();
|
||||
@@ -293,20 +298,13 @@ public class LodBufferBuilder
|
||||
if (!future.get())
|
||||
{
|
||||
ClientProxy.LOGGER.warn("LodBufferBuilder ran into trouble and had to start over.");
|
||||
closeBuffers();
|
||||
closeBuffers(fullRegen, lodDim);
|
||||
return;
|
||||
}
|
||||
}
|
||||
long renderEnd = System.currentTimeMillis();
|
||||
|
||||
|
||||
// finish the buffer building
|
||||
closeBuffers();
|
||||
|
||||
// upload the new buffers
|
||||
uploadBuffers();
|
||||
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
@SuppressWarnings("unused")
|
||||
long buildTime = endTime - startTime;
|
||||
@@ -328,7 +326,6 @@ public class LodBufferBuilder
|
||||
ClientProxy.LOGGER.warn("\"LodNodeBufferBuilder.generateLodBuffersAsync\" ran into trouble: ");
|
||||
e.printStackTrace();
|
||||
} finally
|
||||
|
||||
{
|
||||
// regardless of if we successfully created the buffers
|
||||
// we are done generating.
|
||||
@@ -336,8 +333,10 @@ public class LodBufferBuilder
|
||||
|
||||
// clean up any potentially open resources
|
||||
if (buildableBuffers != null)
|
||||
closeBuffers();
|
||||
closeBuffers(fullRegen, lodDim);
|
||||
|
||||
// upload the new buffers
|
||||
uploadBuffers();
|
||||
bufferLock.unlock();
|
||||
}
|
||||
|
||||
@@ -503,22 +502,35 @@ public class LodBufferBuilder
|
||||
/**
|
||||
* Calls begin on each of the buildable BufferBuilders.
|
||||
*/
|
||||
private void startBuffers()
|
||||
private void startBuffers(boolean fullRegen, LodDimension lodDim)
|
||||
{
|
||||
for (int x = 0; x < buildableBuffers.length; x++)
|
||||
for (int z = 0; z < buildableBuffers.length; z++)
|
||||
{
|
||||
//if (fullRegen || lodDim.regen[x][z])
|
||||
//{
|
||||
//if (lodDim.regen[x][z])
|
||||
// ClientProxy.LOGGER.debug("Starting region " + x + " " + z);
|
||||
buildableBuffers[x][z].begin(GL11.GL_QUADS, LodRenderer.LOD_VERTEX_FORMAT);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls end on each of the buildable BufferBuilders.
|
||||
*/
|
||||
private void closeBuffers()
|
||||
private void closeBuffers(boolean fullRegen, LodDimension lodDim)
|
||||
{
|
||||
for (int x = 0; x < buildableBuffers.length; x++)
|
||||
for (int z = 0; z < buildableBuffers.length; z++)
|
||||
if (buildableBuffers[x][z] != null && buildableBuffers[x][z].building())
|
||||
|
||||
if (buildableBuffers[x][z] != null && buildableBuffers[x][z].building() /*&& (fullRegen || lodDim.regen[x][z])*/)
|
||||
{
|
||||
//if(lodDim.regen[x][z])
|
||||
// ClientProxy.LOGGER.debug("Closing region " + x + " " + z);
|
||||
lodDim.regen[x][z] = false;
|
||||
buildableBuffers[x][z].end();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,7 +76,7 @@ public class LodRenderer
|
||||
* it should be something different than what is used by Minecraft
|
||||
*/
|
||||
private static final int LOD_GL_LIGHT_NUMBER = GL11.GL_LIGHT2;
|
||||
|
||||
|
||||
/**
|
||||
* 64 MB by default is the maximum amount of memory that
|
||||
* can be directly allocated. <br><br>
|
||||
@@ -89,58 +89,60 @@ public class LodRenderer
|
||||
* https://stackoverflow.com/questions/50499238/bytebuffer-allocatedirect-and-xmx
|
||||
*/
|
||||
public static final int MAX_ALOCATEABLE_DIRECT_MEMORY = 64 * 1024 * 1024;
|
||||
|
||||
|
||||
/**
|
||||
* Does this computer's GPU support fancy fog?
|
||||
*/
|
||||
private static Boolean fancyFogAvailable = null;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If true the LODs colors will be replaced with
|
||||
* a checkerboard, this can be used for debugging.
|
||||
*/
|
||||
public DebugMode previousDebugMode = DebugMode.OFF;
|
||||
|
||||
|
||||
private Minecraft mc;
|
||||
private GameRenderer gameRender;
|
||||
private IProfiler profiler;
|
||||
private int farPlaneBlockDistance;
|
||||
private ReflectionHandler reflectionHandler;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is used to generate the buildable buffers
|
||||
*/
|
||||
private LodBufferBuilder lodBufferBuilder;
|
||||
|
||||
|
||||
/**
|
||||
* Each VertexBuffer represents 1 region
|
||||
*/
|
||||
private VertexBuffer[][] vbos;
|
||||
public static final VertexFormat LOD_VERTEX_FORMAT = DefaultVertexFormats.POSITION_COLOR;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is used to determine if the LODs should be regenerated
|
||||
*/
|
||||
private LevelPos previousPos = new LevelPos((byte) 0,0,0);
|
||||
private static long prevPlayerPosTime = 0;
|
||||
private static long prevVanillaChunkTime = 0;
|
||||
private static long prevChunkTime = 0;
|
||||
private LevelPos previousPos = new LevelPos((byte) 0, 0, 0);
|
||||
private int prevRenderDistance = 0;
|
||||
private long prevPlayerPosTime = 0;
|
||||
private long prevVanillaChunkTime = 0;
|
||||
private long prevChunkTime = 0;
|
||||
|
||||
|
||||
/**
|
||||
* This is used to determine if the LODs should be regenerated
|
||||
*/
|
||||
private FogDistance prevFogDistance = FogDistance.NEAR_AND_FAR;
|
||||
|
||||
|
||||
/**
|
||||
* if this is true the LOD buffers should be regenerated,
|
||||
* provided they aren't already being regenerated.
|
||||
*/
|
||||
private volatile boolean regen = false;
|
||||
|
||||
private volatile boolean partialRegen = false;
|
||||
private volatile boolean fullRegen = true;
|
||||
|
||||
/**
|
||||
* This HashSet contains every chunk that Vanilla Minecraft
|
||||
* is going to render
|
||||
@@ -148,17 +150,17 @@ public class LodRenderer
|
||||
public HashSet<ChunkPos> vanillaRenderedChunks = new HashSet<>();
|
||||
public HashSet<ChunkPos> previousVanillaRenderedChunks = new HashSet<>();
|
||||
|
||||
|
||||
|
||||
public LodRenderer(LodBufferBuilder newLodNodeBufferBuilder)
|
||||
{
|
||||
mc = Minecraft.getInstance();
|
||||
gameRender = mc.gameRenderer;
|
||||
|
||||
|
||||
reflectionHandler = new ReflectionHandler();
|
||||
lodBufferBuilder = newLodNodeBufferBuilder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Besides drawing the LODs this method also starts
|
||||
* the async process of generating the Buffers that hold those LODs.
|
||||
@@ -174,93 +176,105 @@ public class LodRenderer
|
||||
// don't try drawing anything
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// initial setup //
|
||||
//===============//
|
||||
|
||||
|
||||
profiler = newProfiler;
|
||||
profiler.push("LOD setup");
|
||||
|
||||
|
||||
|
||||
|
||||
// only check the GPU capability's once
|
||||
if (fancyFogAvailable == null)
|
||||
{
|
||||
// see if this GPU can run fancy fog
|
||||
fancyFogAvailable = GL.getCapabilities().GL_NV_fog_distance;
|
||||
|
||||
|
||||
if (!fancyFogAvailable)
|
||||
{
|
||||
ClientProxy.LOGGER.info("This GPU does not support GL_NV_fog_distance. This means that fancy fog options will not be available.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ClientPlayerEntity player = mc.player;
|
||||
|
||||
if (ClientProxy.previousLodRenderDistance != LodConfig.CLIENT.lodChunkRenderDistance.get() ||
|
||||
mc.options.renderDistance != prevRenderDistance ||
|
||||
prevFogDistance != LodConfig.CLIENT.fogDistance.get())
|
||||
{
|
||||
// yes
|
||||
fullRegen = true;
|
||||
previousPos.changeParameters((byte) 4, player.xChunk, player.zChunk);
|
||||
prevFogDistance = LodConfig.CLIENT.fogDistance.get();
|
||||
prevRenderDistance = mc.options.renderDistance;
|
||||
//should use this when it's ready
|
||||
//vanillaRenderedChunks.stream().filter(pos -> ((Math.abs(pos.x - player.xChunk) > mc.options.renderDistance) || (Math.abs(pos.z - player.zChunk) > mc.options.renderDistance)));
|
||||
vanillaRenderedChunks.clear();
|
||||
}
|
||||
// should LODs be regenerated?
|
||||
long newTime = System.currentTimeMillis();
|
||||
if(newTime - prevPlayerPosTime > 5000)
|
||||
//We check if the player has moved
|
||||
if (newTime - prevPlayerPosTime > 2000)
|
||||
{
|
||||
if (previousPos.detailLevel == 0 ||
|
||||
player.xChunk != previousPos.posX ||
|
||||
player.zChunk != previousPos.posZ ||
|
||||
ClientProxy.previousLodRenderDistance != LodConfig.CLIENT.lodChunkRenderDistance.get() ||
|
||||
prevFogDistance != LodConfig.CLIENT.fogDistance.get())
|
||||
player.xChunk != previousPos.posX ||
|
||||
player.zChunk != previousPos.posZ)
|
||||
{
|
||||
// yes
|
||||
regen = true;
|
||||
fullRegen = true;
|
||||
previousPos.changeParameters((byte) 4, player.xChunk, player.zChunk);
|
||||
prevFogDistance = LodConfig.CLIENT.fogDistance.get();
|
||||
//should use this when it's ready
|
||||
//vanillaRenderedChunks.stream().filter(pos -> ((Math.abs(pos.x - player.xChunk) > mc.options.renderDistance) || (Math.abs(pos.z - player.zChunk) > mc.options.renderDistance)));
|
||||
vanillaRenderedChunks.clear();
|
||||
}
|
||||
prevPlayerPosTime = newTime;
|
||||
}
|
||||
if(newTime - prevVanillaChunkTime > 5000)
|
||||
//We check if the vanilla rendered chunks are changed
|
||||
if (newTime - prevVanillaChunkTime > 1000)
|
||||
{
|
||||
if (previousVanillaRenderedChunks.equals(vanillaRenderedChunks)){
|
||||
regen = true;
|
||||
if (previousVanillaRenderedChunks.equals(vanillaRenderedChunks))
|
||||
{
|
||||
partialRegen = true;
|
||||
vanillaRenderedChunks = previousVanillaRenderedChunks;
|
||||
}
|
||||
prevVanillaChunkTime = newTime;
|
||||
}
|
||||
if(newTime - prevChunkTime > 5000)
|
||||
//We check if there is any newly generated terrain to show
|
||||
if (newTime - prevChunkTime > 5000)
|
||||
{
|
||||
if(lodDim.regenDimension)
|
||||
if (lodDim.regenDimension)
|
||||
{
|
||||
regen = true;
|
||||
partialRegen = true;
|
||||
lodDim.regenDimension = false;
|
||||
}
|
||||
prevChunkTime = newTime;
|
||||
}
|
||||
|
||||
// determine which LODs should not be rendered close to the player
|
||||
HashSet<ChunkPos> chunkPosToSkip = LodUtil.getNearbyLodChunkPosToSkip(lodDim, player.blockPosition());
|
||||
|
||||
for(ChunkPos pos : chunkPosToSkip){
|
||||
if(!vanillaRenderedChunks.contains(pos))
|
||||
// determine which LODs should not be rendered close to the player
|
||||
for (ChunkPos pos : chunkPosToSkip)
|
||||
{
|
||||
if (!vanillaRenderedChunks.contains(pos))
|
||||
{
|
||||
vanillaRenderedChunks.add(pos);
|
||||
lodDim.setToRegen(pos.getRegionX(),pos.getRegionZ());
|
||||
lodDim.setToRegen(pos.getRegionX(), pos.getRegionZ());
|
||||
}
|
||||
}
|
||||
|
||||
// did the user change the debug setting?
|
||||
if (LodConfig.CLIENT.debugMode.get() != previousDebugMode)
|
||||
{
|
||||
previousDebugMode = LodConfig.CLIENT.debugMode.get();
|
||||
regen = true;
|
||||
fullRegen = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// determine how far the game's render distance is currently set
|
||||
farPlaneBlockDistance = LodConfig.CLIENT.lodChunkRenderDistance.get() * LodUtil.CHUNK_WIDTH;
|
||||
|
||||
|
||||
// set how how far the LODs will go
|
||||
int numbChunksWide =LodConfig.CLIENT.lodChunkRenderDistance.get() * 2;
|
||||
int numbChunksWide = LodConfig.CLIENT.lodChunkRenderDistance.get() * 2;
|
||||
|
||||
// see if the chunks Minecraft is going to render are the
|
||||
// same as last time
|
||||
@@ -271,27 +285,28 @@ public class LodRenderer
|
||||
vanillaRenderedChunks = chunkPosToSkip;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// create the LODs //
|
||||
//=================//
|
||||
|
||||
|
||||
// only regenerate the LODs if:
|
||||
// 1. we want to regenerate LODs
|
||||
// 2. we aren't already regenerating the LODs
|
||||
// 3. we aren't waiting for the build and draw buffers to swap
|
||||
// (this is to prevent thread conflicts)
|
||||
if (regen && !lodBufferBuilder.generatingBuffers && !lodBufferBuilder.newBuffersAvaliable())
|
||||
if ((partialRegen || fullRegen) && !lodBufferBuilder.generatingBuffers && !lodBufferBuilder.newBuffersAvaliable())
|
||||
{
|
||||
// generate the LODs on a separate thread to prevent stuttering or freezing
|
||||
lodBufferBuilder.generateLodBuffersAsync(this, lodDim, player.blockPosition(), Math.floorMod((int) player.xRot,360), Math.floorMod((int) player.yRot,360), numbChunksWide);
|
||||
|
||||
lodBufferBuilder.generateLodBuffersAsync(this, lodDim, player.blockPosition(), true);
|
||||
|
||||
// the regen process has been started,
|
||||
// it will be done when lodBufferBuilder.newBuffersAvaliable
|
||||
// is true
|
||||
regen = false;
|
||||
fullRegen = false;
|
||||
partialRegen = false;
|
||||
}
|
||||
|
||||
|
||||
// replace the buffers used to draw and build,
|
||||
// this is only done when the createLodBufferGenerationThread
|
||||
// has finished executing on a parallel thread.
|
||||
@@ -299,14 +314,14 @@ public class LodRenderer
|
||||
{
|
||||
swapBuffers();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===========================//
|
||||
// GL settings for rendering //
|
||||
//===========================//
|
||||
|
||||
|
||||
// set the required open GL settings
|
||||
|
||||
|
||||
if (LodConfig.CLIENT.debugMode.get() == DebugMode.SHOW_DETAIL_WIREFRAME)
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
|
||||
else
|
||||
@@ -315,72 +330,72 @@ public class LodRenderer
|
||||
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
|
||||
|
||||
// disable the lights Minecraft uses
|
||||
GL11.glDisable(GL11.GL_LIGHT0);
|
||||
GL11.glDisable(GL11.GL_LIGHT1);
|
||||
|
||||
|
||||
// get the default projection matrix so we can
|
||||
// reset it after drawing the LODs
|
||||
float[] defaultProjMatrix = new float[16];
|
||||
GL11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, defaultProjMatrix);
|
||||
|
||||
|
||||
Matrix4f modelViewMatrix = generateModelViewMatrix(partialTicks);
|
||||
|
||||
|
||||
setupProjectionMatrix(partialTicks);
|
||||
setupLighting(lodDim, partialTicks);
|
||||
|
||||
|
||||
NearFarFogSettings fogSettings = determineFogSettings();
|
||||
|
||||
|
||||
// determine the current fog settings so they can be
|
||||
// reset after drawing the LODs
|
||||
float defaultFogStartDist = GL11.glGetFloat(GL11.GL_FOG_START);
|
||||
float defaultFogEndDist = GL11.glGetFloat(GL11.GL_FOG_END);
|
||||
int defaultFogMode = GL11.glGetInteger(GL11.GL_FOG_MODE);
|
||||
int defaultFogDistance = GL11.glGetInteger(NVFogDistance.GL_FOG_DISTANCE_MODE_NV);
|
||||
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
profiler.popPush("LOD draw");
|
||||
|
||||
|
||||
if (vbos != null)
|
||||
{
|
||||
Vector3d cameraDir = mc.cameraEntity.getLookAngle().normalize();
|
||||
cameraDir = mc.options.getCameraType().isMirrored() ? cameraDir.reverse() : cameraDir;
|
||||
|
||||
|
||||
|
||||
|
||||
// used to determine what type of fog to render
|
||||
int halfWidth = vbos.length/2;
|
||||
int quarterWidth = vbos.length/4;
|
||||
|
||||
int halfWidth = vbos.length / 2;
|
||||
int quarterWidth = vbos.length / 4;
|
||||
|
||||
for (int i = 0; i < vbos.length; i++)
|
||||
{
|
||||
for (int j = 0; j < vbos.length; j++)
|
||||
{
|
||||
RegionPos vboPos = new RegionPos(i + lodDim.getCenterX() - lodDim.getWidth()/2, j + lodDim.getCenterZ() - lodDim.getWidth()/2);
|
||||
RegionPos vboPos = new RegionPos(i + lodDim.getCenterX() - lodDim.getWidth() / 2, j + lodDim.getCenterZ() - lodDim.getWidth() / 2);
|
||||
if (RenderUtil.isRegionInViewFrustum(mc.cameraEntity.blockPosition(), cameraDir, vboPos.blockPos()))
|
||||
{
|
||||
if ((i > halfWidth - quarterWidth && i < halfWidth + quarterWidth) && (j > halfWidth - quarterWidth && j < halfWidth + quarterWidth))
|
||||
setupFog(fogSettings.near.distance, fogSettings.near.quality);
|
||||
else
|
||||
setupFog(fogSettings.far.distance, fogSettings.far.quality);
|
||||
|
||||
|
||||
|
||||
|
||||
sendLodsToGpuAndDraw(vbos[i][j], modelViewMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// cleanup //
|
||||
//=========//
|
||||
|
||||
|
||||
profiler.popPush("LOD cleanup");
|
||||
|
||||
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(LOD_GL_LIGHT_NUMBER);
|
||||
@@ -388,51 +403,50 @@ public class LodRenderer
|
||||
GL11.glEnable(GL11.GL_LIGHT0);
|
||||
GL11.glEnable(GL11.GL_LIGHT1);
|
||||
RenderSystem.disableLighting();
|
||||
|
||||
|
||||
// reset the fog settings so the normal chunks
|
||||
// will be drawn correctly
|
||||
cleanupFog(fogSettings, defaultFogStartDist, defaultFogEndDist, defaultFogMode, defaultFogDistance);
|
||||
|
||||
|
||||
// reset the projection matrix so anything drawn after
|
||||
// the LODs will use the correct projection matrix
|
||||
Matrix4f mvm = new Matrix4f(defaultProjMatrix);
|
||||
mvm.transpose();
|
||||
gameRender.resetProjectionMatrix(mvm);
|
||||
|
||||
|
||||
// clear the depth buffer so anything drawn is drawn
|
||||
// over the LODs
|
||||
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
||||
|
||||
|
||||
// end of internal LOD profiling
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is where the actual drawing happens.
|
||||
*
|
||||
*/
|
||||
private void sendLodsToGpuAndDraw(VertexBuffer vbo, Matrix4f modelViewMatrix)
|
||||
{
|
||||
if (vbo == null)
|
||||
return;
|
||||
|
||||
|
||||
vbo.bind();
|
||||
// 0L is the starting pointer
|
||||
LOD_VERTEX_FORMAT.setupBufferState(0L);
|
||||
|
||||
|
||||
vbo.draw(modelViewMatrix, GL11.GL_QUADS);
|
||||
|
||||
|
||||
VertexBuffer.unbind();
|
||||
LOD_VERTEX_FORMAT.clearBufferState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// Setup Functions //
|
||||
//=================//
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void setupFog(FogDistance fogDistance, FogQuality fogQuality)
|
||||
{
|
||||
@@ -442,13 +456,13 @@ public class LodRenderer
|
||||
RenderSystem.disableFog();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (fogDistance == FogDistance.NEAR_AND_FAR)
|
||||
{
|
||||
throw new IllegalArgumentException("setupFog doesn't accept the NEAR_AND_FAR fog distance.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// determine the fog distance mode to use
|
||||
int glFogDistanceMode;
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
@@ -460,8 +474,8 @@ public class LodRenderer
|
||||
// fast fog (frustum distance based fog)
|
||||
glFogDistanceMode = NVFogDistance.GL_EYE_PLANE_ABSOLUTE_NV;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// the multipliers are percentages
|
||||
// of the regular view distance.
|
||||
if (fogDistance == FogDistance.FAR)
|
||||
@@ -470,10 +484,10 @@ public class LodRenderer
|
||||
// is because we are using fog backwards to how
|
||||
// it is normally used, with it hiding near objects
|
||||
// instead of far objects.
|
||||
|
||||
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
{
|
||||
RenderSystem.fogStart(farPlaneBlockDistance * 0.8f);
|
||||
RenderSystem.fogStart(farPlaneBlockDistance * 0.1f);
|
||||
RenderSystem.fogEnd(farPlaneBlockDistance * 1.0f);
|
||||
} else if (fogQuality == FogQuality.FAST)
|
||||
{
|
||||
@@ -495,39 +509,39 @@ public class LodRenderer
|
||||
RenderSystem.fogStart(mc.options.renderDistance * 16 * 1.5f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
GL11.glEnable(GL11.GL_FOG);
|
||||
RenderSystem.enableFog();
|
||||
RenderSystem.setupNvFogDistance();
|
||||
RenderSystem.fogMode(GlStateManager.FogMode.LINEAR);
|
||||
GL11.glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, glFogDistanceMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Revert any changes that were made to the fog.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void cleanupFog(NearFarFogSettings fogSettings,
|
||||
float defaultFogStartDist, float defaultFogEndDist,
|
||||
int defaultFogMode, int defaultFogDistance)
|
||||
float defaultFogStartDist, float defaultFogEndDist,
|
||||
int defaultFogMode, int defaultFogDistance)
|
||||
{
|
||||
RenderSystem.fogStart(defaultFogStartDist);
|
||||
RenderSystem.fogEnd(defaultFogEndDist);
|
||||
RenderSystem.fogMode(defaultFogMode);
|
||||
GL11.glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, defaultFogDistance);
|
||||
|
||||
|
||||
// disable fog if Minecraft wasn't rendering fog
|
||||
// but we were
|
||||
if (!fogSettings.vanillaIsRenderingFog &&
|
||||
(fogSettings.near.quality != FogQuality.OFF ||
|
||||
fogSettings.far.quality != FogQuality.OFF))
|
||||
(fogSettings.near.quality != FogQuality.OFF ||
|
||||
fogSettings.far.quality != FogQuality.OFF))
|
||||
{
|
||||
GL11.glDisable(GL11.GL_FOG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create the model view matrix to move the LODs
|
||||
* from object space into world space.
|
||||
@@ -537,8 +551,8 @@ public class LodRenderer
|
||||
// get all relevant camera info
|
||||
ActiveRenderInfo renderInfo = mc.gameRenderer.getMainCamera();
|
||||
Vector3d projectedView = renderInfo.getPosition();
|
||||
|
||||
|
||||
|
||||
|
||||
// generate the model view matrix
|
||||
MatrixStack matrixStack = new MatrixStack();
|
||||
matrixStack.pushPose();
|
||||
@@ -546,11 +560,11 @@ public class LodRenderer
|
||||
matrixStack.mulPose(Vector3f.XP.rotationDegrees(renderInfo.getXRot()));
|
||||
matrixStack.mulPose(Vector3f.YP.rotationDegrees(renderInfo.getYRot() + 180));
|
||||
matrixStack.translate(-projectedView.x, -projectedView.y, -projectedView.z);
|
||||
|
||||
|
||||
return matrixStack.last().pose();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* create a new projection matrix and send it over to the GPU
|
||||
* <br><br>
|
||||
@@ -568,16 +582,16 @@ public class LodRenderer
|
||||
// Note: if the LOD objects don't distort correctly
|
||||
// compared to regular minecraft terrain, make sure
|
||||
// all the transformations in renderWorld are here too
|
||||
|
||||
|
||||
MatrixStack matrixStack = new MatrixStack();
|
||||
matrixStack.pushPose();
|
||||
|
||||
|
||||
gameRender.bobHurt(matrixStack, partialTicks);
|
||||
if (this.mc.options.bobView)
|
||||
{
|
||||
gameRender.bobView(matrixStack, partialTicks);
|
||||
}
|
||||
|
||||
|
||||
// potion and nausea effects
|
||||
float f = MathHelper.lerp(partialTicks, this.mc.player.oPortalTime, this.mc.player.portalTime) * this.mc.options.screenEffectScale * this.mc.options.screenEffectScale;
|
||||
if (f > 0.0F)
|
||||
@@ -591,8 +605,8 @@ public class LodRenderer
|
||||
float f2 = -(gameRender.tick + partialTicks) * i;
|
||||
matrixStack.mulPose(vector3f.rotationDegrees(f2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// this projection matrix allows us to see past the normal
|
||||
// world render distance
|
||||
Matrix4f projectionMatrix =
|
||||
@@ -604,14 +618,14 @@ public class LodRenderer
|
||||
// terrain, so I don't think it is much of an issue.
|
||||
mc.options.renderDistance,
|
||||
farPlaneBlockDistance * LodUtil.CHUNK_WIDTH * 2);
|
||||
|
||||
|
||||
// add the screen space distortions
|
||||
projectionMatrix.multiply(matrixStack.last().pose());
|
||||
gameRender.resetProjectionMatrix(projectionMatrix);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* setup the lighting to be used for the LODs
|
||||
*/
|
||||
@@ -623,7 +637,7 @@ public class LodRenderer
|
||||
if (this.mc.player != null)
|
||||
{
|
||||
Iterator<EffectInstance> iterator = this.mc.player.getActiveEffects().iterator();
|
||||
while(iterator.hasNext())
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
EffectInstance instance = iterator.next();
|
||||
if (instance.getEffect() == Effects.NIGHT_VISION)
|
||||
@@ -633,27 +647,27 @@ public class LodRenderer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.level.getSkyDarken(partialTicks) : 0.2f;
|
||||
sunBrightness = playerHasNightVision ? 1.0f : sunBrightness;
|
||||
float gammaMultiplyer = (float) mc.options.gamma - 0.5f;
|
||||
float lightStrength = ((sunBrightness / 2f) - 0.2f) + (gammaMultiplyer * 0.3f);
|
||||
|
||||
|
||||
float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f};
|
||||
|
||||
|
||||
// can be used for debugging
|
||||
// if (partialTicks < 0.005)
|
||||
// ClientProxy.LOGGER.debug(lightStrength);
|
||||
|
||||
|
||||
ByteBuffer temp = ByteBuffer.allocateDirect(16);
|
||||
temp.order(ByteOrder.nativeOrder());
|
||||
GL11.glLightfv(LOD_GL_LIGHT_NUMBER, GL11.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip()); // TODO, could put return null? this crashed on James' laptop
|
||||
GL11.glEnable(LOD_GL_LIGHT_NUMBER); // Enable the above lighting
|
||||
|
||||
|
||||
RenderSystem.enableLighting();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create all buffers that will be used.
|
||||
*/
|
||||
@@ -661,34 +675,34 @@ public class LodRenderer
|
||||
{
|
||||
// calculate the max amount of memory needed (in bytes)
|
||||
int bufferMemory = RenderUtil.getBufferMemoryForRegion();
|
||||
|
||||
|
||||
// if the required memory is greater than the
|
||||
// MAX_ALOCATEABLE_DIRECT_MEMORY lower the lodChunkRadiusMultiplier
|
||||
// to fit.
|
||||
if (bufferMemory > MAX_ALOCATEABLE_DIRECT_MEMORY)
|
||||
{
|
||||
ClientProxy.LOGGER.warn("setupBuffers tried to allocate too much memory for the BufferBuilders."
|
||||
+ " It tried to allocate \"" + bufferMemory + "\" bytes, when \"" + MAX_ALOCATEABLE_DIRECT_MEMORY + "\" is the max.");
|
||||
+ " It tried to allocate \"" + bufferMemory + "\" bytes, when \"" + MAX_ALOCATEABLE_DIRECT_MEMORY + "\" is the max.");
|
||||
}
|
||||
|
||||
|
||||
lodBufferBuilder.setupBuffers(numbRegionsWide, bufferMemory);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//======================//
|
||||
// Other Misc Functions //
|
||||
//======================//
|
||||
|
||||
|
||||
/**
|
||||
* If this is called then the next time "drawLODs" is called
|
||||
* the LODs will be regenerated; the same as if the player moved.
|
||||
*/
|
||||
public void regenerateLODsNextFrame()
|
||||
{
|
||||
regen = true;
|
||||
fullRegen = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Replace the current Vertex Buffers with the newly
|
||||
* created buffers from the lodBufferBuilder.
|
||||
@@ -699,7 +713,7 @@ public class LodRenderer
|
||||
// the newly created buffers from the lodBufferBuilder
|
||||
vbos = lodBufferBuilder.getVertexBuffers();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls the BufferBuilder's destroyBuffers method.
|
||||
*/
|
||||
@@ -707,124 +721,124 @@ public class LodRenderer
|
||||
{
|
||||
lodBufferBuilder.destroyBuffers();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private double getFov(float partialTicks, boolean useFovSetting)
|
||||
{
|
||||
return mc.gameRenderer.getFov(mc.gameRenderer.getMainCamera(), partialTicks, useFovSetting);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return what fog settings should be used when rendering.
|
||||
*/
|
||||
private NearFarFogSettings determineFogSettings()
|
||||
{
|
||||
NearFarFogSettings fogSettings = new NearFarFogSettings();
|
||||
|
||||
|
||||
|
||||
|
||||
FogQuality quality = reflectionHandler.getFogQuality();
|
||||
FogDrawOverride override = LodConfig.CLIENT.fogDrawOverride.get();
|
||||
|
||||
|
||||
|
||||
|
||||
if (quality == FogQuality.OFF)
|
||||
fogSettings.vanillaIsRenderingFog = false;
|
||||
else
|
||||
fogSettings.vanillaIsRenderingFog = true;
|
||||
|
||||
|
||||
|
||||
|
||||
// use any fog overrides the user may have set
|
||||
switch (override)
|
||||
{
|
||||
case ALWAYS_DRAW_FOG_FANCY:
|
||||
quality = FogQuality.FANCY;
|
||||
break;
|
||||
|
||||
case NEVER_DRAW_FOG:
|
||||
quality = FogQuality.OFF;
|
||||
break;
|
||||
|
||||
case ALWAYS_DRAW_FOG_FAST:
|
||||
quality = FogQuality.FAST;
|
||||
break;
|
||||
|
||||
case USE_OPTIFINE_FOG_SETTING:
|
||||
// don't override anything
|
||||
break;
|
||||
case ALWAYS_DRAW_FOG_FANCY:
|
||||
quality = FogQuality.FANCY;
|
||||
break;
|
||||
|
||||
case NEVER_DRAW_FOG:
|
||||
quality = FogQuality.OFF;
|
||||
break;
|
||||
|
||||
case ALWAYS_DRAW_FOG_FAST:
|
||||
quality = FogQuality.FAST;
|
||||
break;
|
||||
|
||||
case USE_OPTIFINE_FOG_SETTING:
|
||||
// don't override anything
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// only use fancy fog if the user's GPU can deliver
|
||||
if (!fancyFogAvailable && quality == FogQuality.FANCY)
|
||||
{
|
||||
quality = FogQuality.FAST;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// how different distances are drawn depends on the quality set
|
||||
switch (quality)
|
||||
{
|
||||
case FANCY:
|
||||
fogSettings.near.quality = FogQuality.FANCY;
|
||||
fogSettings.far.quality = FogQuality.FANCY;
|
||||
|
||||
switch (LodConfig.CLIENT.fogDistance.get())
|
||||
{
|
||||
case NEAR_AND_FAR:
|
||||
fogSettings.near.distance = FogDistance.NEAR;
|
||||
fogSettings.far.distance = FogDistance.FAR;
|
||||
case FANCY:
|
||||
fogSettings.near.quality = FogQuality.FANCY;
|
||||
fogSettings.far.quality = FogQuality.FANCY;
|
||||
|
||||
switch (LodConfig.CLIENT.fogDistance.get())
|
||||
{
|
||||
case NEAR_AND_FAR:
|
||||
fogSettings.near.distance = FogDistance.NEAR;
|
||||
fogSettings.far.distance = FogDistance.FAR;
|
||||
break;
|
||||
|
||||
case NEAR:
|
||||
fogSettings.near.distance = FogDistance.NEAR;
|
||||
fogSettings.far.distance = FogDistance.NEAR;
|
||||
break;
|
||||
|
||||
case FAR:
|
||||
fogSettings.near.distance = FogDistance.FAR;
|
||||
fogSettings.far.distance = FogDistance.FAR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case NEAR:
|
||||
fogSettings.near.distance = FogDistance.NEAR;
|
||||
fogSettings.far.distance = FogDistance.NEAR;
|
||||
|
||||
case FAST:
|
||||
fogSettings.near.quality = FogQuality.FAST;
|
||||
fogSettings.far.quality = FogQuality.FAST;
|
||||
|
||||
// fast fog setting should only have one type of
|
||||
// fog, since the LODs are separated into a near
|
||||
// and far portion; and fast fog is rendered from the
|
||||
// frustrum's perspective instead of the camera
|
||||
switch (LodConfig.CLIENT.fogDistance.get())
|
||||
{
|
||||
case NEAR_AND_FAR:
|
||||
fogSettings.near.distance = FogDistance.NEAR;
|
||||
fogSettings.far.distance = FogDistance.NEAR;
|
||||
break;
|
||||
|
||||
case NEAR:
|
||||
fogSettings.near.distance = FogDistance.NEAR;
|
||||
fogSettings.far.distance = FogDistance.NEAR;
|
||||
break;
|
||||
|
||||
case FAR:
|
||||
fogSettings.near.distance = FogDistance.FAR;
|
||||
fogSettings.far.distance = FogDistance.FAR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FAR:
|
||||
fogSettings.near.distance = FogDistance.FAR;
|
||||
fogSettings.far.distance = FogDistance.FAR;
|
||||
|
||||
case OFF:
|
||||
|
||||
fogSettings.near.quality = FogQuality.OFF;
|
||||
fogSettings.far.quality = FogQuality.OFF;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FAST:
|
||||
fogSettings.near.quality = FogQuality.FAST;
|
||||
fogSettings.far.quality = FogQuality.FAST;
|
||||
|
||||
// fast fog setting should only have one type of
|
||||
// fog, since the LODs are separated into a near
|
||||
// and far portion; and fast fog is rendered from the
|
||||
// frustrum's perspective instead of the camera
|
||||
switch (LodConfig.CLIENT.fogDistance.get())
|
||||
{
|
||||
case NEAR_AND_FAR:
|
||||
fogSettings.near.distance = FogDistance.NEAR;
|
||||
fogSettings.far.distance = FogDistance.NEAR;
|
||||
break;
|
||||
|
||||
case NEAR:
|
||||
fogSettings.near.distance = FogDistance.NEAR;
|
||||
fogSettings.far.distance = FogDistance.NEAR;
|
||||
break;
|
||||
|
||||
case FAR:
|
||||
fogSettings.near.distance = FogDistance.FAR;
|
||||
fogSettings.far.distance = FogDistance.FAR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case OFF:
|
||||
|
||||
fogSettings.near.quality = FogQuality.OFF;
|
||||
fogSettings.far.quality = FogQuality.OFF;
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return fogSettings;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user