Made chunk loading smarter, boosted the FPS a lot
This commit is contained in:
parent
1b2cb34bb1
commit
8aeaf404ca
7 changed files with 130 additions and 123 deletions
|
@ -139,7 +139,9 @@ public class Minecraft implements Runnable {
|
|||
private long field_83002_am = -1L;
|
||||
|
||||
public int chunkUpdates = 0;
|
||||
public int chunkGeometryUpdates = 0;
|
||||
public static int debugChunkUpdates = 0;
|
||||
public static int debugChunkGeometryUpdates = 0;
|
||||
|
||||
/**
|
||||
* Set to true to keep the game loop running. Set to false by shutdown() to
|
||||
|
@ -724,6 +726,8 @@ public class Minecraft implements Runnable {
|
|||
fpsCounter = 0;
|
||||
debugChunkUpdates = chunkUpdates;
|
||||
chunkUpdates = 0;
|
||||
debugChunkGeometryUpdates = chunkGeometryUpdates;
|
||||
chunkGeometryUpdates = 0;
|
||||
secondTimer = System.currentTimeMillis();
|
||||
}
|
||||
this.mcProfiler.startSection("syncDisplay");
|
||||
|
|
|
@ -8,7 +8,7 @@ public enum EnumOptions {
|
|||
CHAT_VISIBILITY("options.chat.visibility", false, false), CHAT_COLOR("options.chat.color", false, true), CHAT_LINKS("options.chat.links", false, true), CHAT_OPACITY("options.chat.opacity", true, false),
|
||||
CHAT_LINKS_PROMPT("options.chat.links.prompt", false, true), USE_SERVER_TEXTURES("options.serverTextures", false, true), SNOOPER_ENABLED("options.snooper", false, true), USE_FULLSCREEN("options.fullscreen", false, true),
|
||||
PATCH_ANGLE("options.patchAnisotropic", false, true), ENABLE_FOG("options.fog", false, true), SHOW_CAPE("options.showCape", false, true), ANTIALIASING("options.framebufferAntialias", false, false), CHAT_SCALE("options.chat.scale", true, false), CHAT_WIDTH("options.chat.width", true, false),
|
||||
CHAT_HEIGHT_FOCUSED("options.chat.height.focused", true, false), CHAT_HEIGHT_UNFOCUSED("options.chat.height.unfocused", true, false);
|
||||
CHAT_HEIGHT_FOCUSED("options.chat.height.focused", true, false), CHAT_HEIGHT_UNFOCUSED("options.chat.height.unfocused", true, false), CHUNK_UPDATES("options.chunkUpdates", false, false);
|
||||
|
||||
private final boolean enumFloat;
|
||||
private final boolean enumBoolean;
|
||||
|
|
|
@ -87,5 +87,11 @@ class EnumOptionsHelper {
|
|||
} catch (NoSuchFieldError var10) {
|
||||
;
|
||||
}
|
||||
|
||||
try {
|
||||
enumOptionsMappingHelperArray[EnumOptions.CHUNK_UPDATES.ordinal()] = 16;
|
||||
} catch (NoSuchFieldError var10) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,6 +135,7 @@ public class GameSettings {
|
|||
public boolean allowFNAWSkins = true;
|
||||
public boolean showOtherCapes = true;
|
||||
|
||||
public int chunkUpdatePerFrame = 0;
|
||||
|
||||
public GameSettings(Minecraft par1Minecraft) {
|
||||
this.keyBindings = new KeyBinding[] { this.keyBindAttack, this.keyBindUseItem, this.keyBindForward, this.keyBindLeft, this.keyBindBack, this.keyBindRight, this.keyBindJump, this.keyBindSneak, this.keyBindDrop, this.keyBindInventory,
|
||||
|
@ -291,6 +292,10 @@ public class GameSettings {
|
|||
this.limitFramerate = (this.limitFramerate + par2 + 3) % 3;
|
||||
}
|
||||
|
||||
if (par1EnumOptions == EnumOptions.CHUNK_UPDATES) {
|
||||
this.chunkUpdatePerFrame = (this.chunkUpdatePerFrame + par2) % 5;
|
||||
}
|
||||
|
||||
if (par1EnumOptions == EnumOptions.DIFFICULTY) {
|
||||
this.difficulty = this.difficulty + par2 & 3;
|
||||
}
|
||||
|
@ -460,8 +465,9 @@ public class GameSettings {
|
|||
: (par1EnumOptions == EnumOptions.FRAMERATE_LIMIT ? var3 + getTranslation(LIMIT_FRAMERATES, this.limitFramerate)
|
||||
: (par1EnumOptions == EnumOptions.AMBIENT_OCCLUSION ? var3 + getTranslation(AMBIENT_OCCLUSIONS, this.ambientOcclusion)
|
||||
: (par1EnumOptions == EnumOptions.ANTIALIASING ? var3 + getTranslation(ANTIALIASING, this.antialiasMode)
|
||||
: (par1EnumOptions == EnumOptions.CHUNK_UPDATES ? var3 + (chunkUpdatePerFrame + 1)
|
||||
: (par1EnumOptions == EnumOptions.GRAPHICS ? (this.fancyGraphics ? var3 + var2.translateKey("options.graphics.fancy") : var3 + var2.translateKey("options.graphics.fast"))
|
||||
: var3))))))));
|
||||
: var3)))))))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,6 +525,7 @@ public class GameSettings {
|
|||
if(yee.hasKey("showSkinRightLeg")) showSkinRightLeg = yee.getBoolean("showSkinRightLeg");
|
||||
if(yee.hasKey("allowFNAWSkins")) allowFNAWSkins = yee.getBoolean("allowFNAWSkins");
|
||||
if(yee.hasKey("showOtherCapes")) showOtherCapes = yee.getBoolean("showOtherCapes");
|
||||
if(yee.hasKey("chunkUpdates")) chunkUpdatePerFrame = yee.getInteger("chunkUpdates");
|
||||
|
||||
for (int var4 = 0; var4 < this.keyBindings.length; ++var4) {
|
||||
if(yee.hasKey(keyBindings[var4].keyDescription)) this.keyBindings[var4].keyCode = yee.getInteger(keyBindings[var4].keyDescription);
|
||||
|
@ -581,6 +588,7 @@ public class GameSettings {
|
|||
yee.setBoolean("showSkinRightLeg", showSkinRightLeg);
|
||||
yee.setBoolean("allowFNAWSkins", allowFNAWSkins);
|
||||
yee.setBoolean("showOtherCapes", showOtherCapes);
|
||||
yee.setInteger("chunkUpdates", chunkUpdatePerFrame);
|
||||
|
||||
for (int var4 = 0; var4 < this.keyBindings.length; ++var4) {
|
||||
yee.setInteger(keyBindings[var4].keyDescription, keyBindings[var4].keyCode);
|
||||
|
|
|
@ -17,7 +17,7 @@ public class GuiVideoSettings extends GuiScreen {
|
|||
|
||||
/** An array of all of EnumOption's video options. */
|
||||
private static EnumOptions[] videoOptions = new EnumOptions[] { EnumOptions.GRAPHICS, EnumOptions.RENDER_DISTANCE, EnumOptions.AMBIENT_OCCLUSION, EnumOptions.FRAMERATE_LIMIT, EnumOptions.ANAGLYPH, EnumOptions.VIEW_BOBBING,
|
||||
EnumOptions.GUI_SCALE, EnumOptions.GAMMA, EnumOptions.RENDER_CLOUDS, EnumOptions.ENABLE_FOG, EnumOptions.PARTICLES, EnumOptions.PATCH_ANGLE };
|
||||
EnumOptions.GUI_SCALE, EnumOptions.GAMMA, EnumOptions.RENDER_CLOUDS, EnumOptions.ENABLE_FOG, EnumOptions.PARTICLES, EnumOptions.PATCH_ANGLE, EnumOptions.CHUNK_UPDATES };
|
||||
|
||||
public GuiVideoSettings(GuiScreen par1GuiScreen, GameSettings par2GameSettings) {
|
||||
this.parentGuiScreen = par1GuiScreen;
|
||||
|
@ -31,7 +31,7 @@ public class GuiVideoSettings extends GuiScreen {
|
|||
StringTranslate var1 = StringTranslate.getInstance();
|
||||
this.screenTitle = var1.translateKey("options.videoTitle");
|
||||
this.buttonList.clear();
|
||||
this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height / 6 + 168, var1.translateKey("gui.done")));
|
||||
this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height / 6 + 178, var1.translateKey("gui.done")));
|
||||
this.is64bit = true;
|
||||
/*
|
||||
String[] var2 = new String[] { "sun.arch.data.model", "com.ibm.vm.bitmode", "os.arch" };
|
||||
|
|
|
@ -145,6 +145,8 @@ public class RenderGlobal implements IWorldAccess {
|
|||
*/
|
||||
int frustumCheckOffset = 0;
|
||||
|
||||
private int occlusionForcedIndexShift = 0;
|
||||
|
||||
public RenderGlobal(Minecraft par1Minecraft, RenderEngine par2RenderEngine) {
|
||||
this.mc = par1Minecraft;
|
||||
this.renderEngine = par2RenderEngine;
|
||||
|
@ -415,7 +417,8 @@ public class RenderGlobal implements IWorldAccess {
|
|||
}
|
||||
|
||||
public String getDebugInfoShort() {
|
||||
return "" + Minecraft.debugFPS + "fps | C: " + this.renderersBeingRendered + "/" + this.renderersLoaded + ", E: " + this.countEntitiesRendered + "+" + tileEntities.size()+", U: "+Minecraft.debugChunkUpdates;
|
||||
return "" + Minecraft.debugFPS + "fps | C: " + this.renderersBeingRendered + "/" + this.renderersLoaded + ", E: " + this.countEntitiesRendered + "+" + tileEntities.size() +
|
||||
", U: " + Minecraft.debugChunkGeometryUpdates + "/" + Minecraft.debugChunkUpdates;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -566,9 +569,9 @@ public class RenderGlobal implements IWorldAccess {
|
|||
int var34;
|
||||
|
||||
long queryRate = 50l;
|
||||
long stallRateVisible = 50l;
|
||||
long stallRateVisible = 60l;
|
||||
long stallRate = 500l;
|
||||
int cooldownRate = 10;
|
||||
int cooldownRate = 13;
|
||||
|
||||
long ct = System.currentTimeMillis();
|
||||
if(par2 == 0) {
|
||||
|
@ -578,18 +581,29 @@ public class RenderGlobal implements IWorldAccess {
|
|||
int ccx = c.chunkX - fx;
|
||||
int ccy = c.chunkY - fy;
|
||||
int ccz = c.chunkZ - fz;
|
||||
if((ccx < 2 && ccx > -2 && ccy < 2 && ccy > -2 && ccz < 2 && ccz > -2) || glOcclusionQuery[c.chunkIndex] == -1) {
|
||||
boolean forced = ccx < 2 && ccx > -2 && ccy < 2 && ccy > -2 && ccz < 2 && ccz > -2;
|
||||
if(forced) {
|
||||
c.hasOcclusionData = 5;
|
||||
}
|
||||
if(forced || glOcclusionQuery[c.chunkIndex] == -1) {
|
||||
c.isNowVisible = true;
|
||||
c.isVisible = cooldownRate;
|
||||
}else if(!c.skipAllRenderPasses() && c.isInFrustum) {
|
||||
if(occlusionQueryAvailable[c.chunkIndex]) {
|
||||
}else if(occlusionQueryAvailable[c.chunkIndex]) {
|
||||
if(EaglerAdapter.glGetQueryResultAvailable(glOcclusionQuery[c.chunkIndex])) {
|
||||
if(EaglerAdapter.glGetQueryResult(glOcclusionQuery[c.chunkIndex])) {
|
||||
c.isNowVisible = true;
|
||||
++c.hasOcclusionData;
|
||||
if(c.hasOcclusionData > 5) {
|
||||
c.hasOcclusionData = 5;
|
||||
}
|
||||
c.isVisible = cooldownRate;
|
||||
}else {
|
||||
if(c.isVisible <= 0) {
|
||||
c.isNowVisible = false;
|
||||
--c.hasOcclusionData;
|
||||
if(c.hasOcclusionData < 0) {
|
||||
c.hasOcclusionData = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
occlusionQueryAvailable[c.chunkIndex] = false;
|
||||
|
@ -601,7 +615,6 @@ public class RenderGlobal implements IWorldAccess {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.theWorld.theProfiler.endStartSection("render");
|
||||
var34 = var17 + this.renderSortedRenderers(0, this.sortedWorldRenderers.length, par2, par3);
|
||||
|
@ -610,6 +623,27 @@ public class RenderGlobal implements IWorldAccess {
|
|||
|
||||
ct = System.currentTimeMillis();
|
||||
if(par2 == 0 && ct - lastOcclusionQuery > queryRate) {
|
||||
|
||||
int totalRenderers = this.sortedWorldRenderers.length;
|
||||
int inFrustumCount = 0;
|
||||
for (int i = 0; i < totalRenderers; ++i) {
|
||||
WorldRenderer c = this.sortedWorldRenderers[i];
|
||||
if(c.isInFrustum) {
|
||||
++inFrustumCount;
|
||||
}
|
||||
}
|
||||
|
||||
int occlusionForceCount = (int)(500l / queryRate);
|
||||
int occlusionForceStep = MathHelper.floor_float(inFrustumCount / (float)occlusionForceCount) + 1;
|
||||
int forceStartIndex = occlusionForcedIndexShift * occlusionForceStep;
|
||||
int forceEndIndex = forceStartIndex + occlusionForceStep;
|
||||
++occlusionForcedIndexShift;
|
||||
if(forceEndIndex + (occlusionForceStep >> 1) > inFrustumCount) {
|
||||
forceEndIndex = inFrustumCount;
|
||||
occlusionForcedIndexShift = 0;
|
||||
}
|
||||
|
||||
inFrustumCount = 0;
|
||||
lastOcclusionQuery = ct;
|
||||
this.theWorld.theProfiler.endStartSection("occl");
|
||||
EaglerAdapter.glEnable(EaglerAdapter.GL_CULL_FACE);
|
||||
|
@ -622,7 +656,14 @@ public class RenderGlobal implements IWorldAccess {
|
|||
int ccx = c.chunkX - fx;
|
||||
int ccy = c.chunkY - fy;
|
||||
int ccz = c.chunkZ - fz;
|
||||
if(!c.skipAllRenderPasses() && c.isInFrustum && !(ccx < 2 && ccx > -2 && ccy < 2 && ccy > -2 && ccz < 2 && ccz > -2)) {
|
||||
boolean shouldTry = c.isInFrustum;
|
||||
if(c.isInFrustum) {
|
||||
++inFrustumCount;
|
||||
if(!shouldTry && inFrustumCount >= forceStartIndex && inFrustumCount < forceEndIndex) {
|
||||
shouldTry = true;
|
||||
}
|
||||
}
|
||||
if(shouldTry && !(ccx < 2 && ccx > -2 && ccy < 2 && ccy > -2 && ccz < 2 && ccz > -2)) {
|
||||
boolean stalled = false;
|
||||
if(occlusionQueryAvailable[c.chunkIndex]) {
|
||||
if(occlusionQueryStalled[c.chunkIndex] == 0l) {
|
||||
|
@ -642,6 +683,11 @@ public class RenderGlobal implements IWorldAccess {
|
|||
EaglerAdapter.glDrawOcclusionBB((float)(c.posX - var33), (float)(c.posY - var7), (float)(c.posZ - var9), 16, 16, 16);
|
||||
EaglerAdapter.glEndQuery();
|
||||
}
|
||||
}else {
|
||||
--c.hasOcclusionData;
|
||||
if(c.hasOcclusionData < 0) {
|
||||
c.hasOcclusionData = 0;
|
||||
}
|
||||
}
|
||||
if(c.isVisible > 0) {
|
||||
--c.isVisible;
|
||||
|
@ -1227,54 +1273,31 @@ public class RenderGlobal implements IWorldAccess {
|
|||
WorldRenderer var10;
|
||||
int var11;
|
||||
int var12;
|
||||
label136:
|
||||
|
||||
List laterUpdateList = new ArrayList(var7);
|
||||
for (var9 = 0; var9 < var7; ++var9) {
|
||||
var10 = (WorldRenderer) this.worldRenderersToUpdate.get(var9);
|
||||
|
||||
if (var10 != null) {
|
||||
if (!par2) {
|
||||
if (var10.distanceToEntitySquared(par1EntityLiving) > 256.0F) {
|
||||
for (var11 = 0; var11 < var3 && (var5[var11] == null || var4.doCompare(var5[var11], var10) <= 0); ++var11) {
|
||||
;
|
||||
}
|
||||
|
||||
--var11;
|
||||
|
||||
if (var11 > 0) {
|
||||
var12 = var11;
|
||||
|
||||
while (true) {
|
||||
--var12;
|
||||
|
||||
if (var12 == 0) {
|
||||
var5[var11] = var10;
|
||||
continue label136;
|
||||
}
|
||||
|
||||
var5[var12 - 1] = var5[var12];
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
} else if (!var10.isInFrustum) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!var10.isInFrustum || !var10.isNowVisible || var10.hasOcclusionData < 3) { // config?
|
||||
laterUpdateList.add(var10);
|
||||
}else {
|
||||
if (var6 == null) {
|
||||
var6 = new ArrayList();
|
||||
}
|
||||
|
||||
++var8;
|
||||
var6.add(var10);
|
||||
this.worldRenderersToUpdate.set(var9, (Object) null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.worldRenderersToUpdate = laterUpdateList;
|
||||
|
||||
this.theWorld.theProfiler.endSection();
|
||||
this.theWorld.theProfiler.startSection("sort");
|
||||
this.theWorld.theProfiler.startSection("sortAndUpdate");
|
||||
|
||||
int updates = 0;
|
||||
int dropped = 0;
|
||||
if (var6 != null) {
|
||||
if (var6.size() > 1) {
|
||||
Collections.sort(var6, var4);
|
||||
|
@ -1282,71 +1305,24 @@ public class RenderGlobal implements IWorldAccess {
|
|||
|
||||
for (var9 = var6.size() - 1; var9 >= 0; --var9) {
|
||||
var10 = (WorldRenderer) var6.get(var9);
|
||||
if(updates >= mc.gameSettings.chunkUpdatePerFrame + 1) { // make configurable
|
||||
this.worldRenderersToUpdate.add(var10);
|
||||
++dropped;
|
||||
}else {
|
||||
++mc.chunkUpdates;
|
||||
var10.updateRenderer();
|
||||
var10.needsUpdate = false;
|
||||
if(!var10.skipAllRenderPasses()) {
|
||||
++updates;
|
||||
++mc.chunkGeometryUpdates;
|
||||
}
|
||||
}
|
||||
|
||||
this.theWorld.theProfiler.endSection();
|
||||
var9 = 0;
|
||||
int var16;
|
||||
|
||||
for (var16 = var3 - 1; var16 >= 0; --var16) {
|
||||
WorldRenderer var17 = var5[var16];
|
||||
|
||||
if (var17 != null) {
|
||||
if (!var17.isInFrustum && var16 != var3 - 1) {
|
||||
var5[var16] = null;
|
||||
var5[0] = null;
|
||||
break;
|
||||
}
|
||||
|
||||
var5[var16].updateRenderer();
|
||||
var5[var16].needsUpdate = false;
|
||||
++var9;
|
||||
}
|
||||
}
|
||||
|
||||
this.mc.chunkUpdates += var9;
|
||||
this.theWorld.theProfiler.startSection("cleanup");
|
||||
var16 = 0;
|
||||
var11 = 0;
|
||||
|
||||
for (var12 = this.worldRenderersToUpdate.size(); var16 != var12; ++var16) {
|
||||
WorldRenderer var13 = (WorldRenderer) this.worldRenderersToUpdate.get(var16);
|
||||
|
||||
if (var13 != null) {
|
||||
boolean var14 = false;
|
||||
|
||||
for (int var15 = 0; var15 < var3 && !var14; ++var15) {
|
||||
if (var13 == var5[var15]) {
|
||||
var14 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!var14) {
|
||||
if (var11 != var16) {
|
||||
this.worldRenderersToUpdate.set(var11, var13);
|
||||
}
|
||||
|
||||
++var11;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.theWorld.theProfiler.endSection();
|
||||
this.theWorld.theProfiler.startSection("trim");
|
||||
|
||||
while (true) {
|
||||
--var16;
|
||||
|
||||
if (var16 < var11) {
|
||||
this.theWorld.theProfiler.endSection();
|
||||
return var7 == var8 + var9;
|
||||
}
|
||||
|
||||
this.worldRenderersToUpdate.remove(var16);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final TextureLocation tex_terrain = new TextureLocation("/terrain.png");
|
||||
|
@ -1561,7 +1537,8 @@ public class RenderGlobal implements IWorldAccess {
|
|||
*/
|
||||
public void clipRenderersByFrustum(ICamera par1ICamera, float par2) {
|
||||
for (int var3 = 0; var3 < this.worldRenderers.length; ++var3) {
|
||||
if (!this.worldRenderers[var3].skipAllRenderPasses() && (!this.worldRenderers[var3].isInFrustum || (var3 + this.frustumCheckOffset & 15) == 0)) {
|
||||
WorldRenderer rd = this.worldRenderers[var3];
|
||||
if (!rd.isInFrustum || (var3 + this.frustumCheckOffset & 31) == 0) {
|
||||
this.worldRenderers[var3].updateInFrustum(par1ICamera);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ public class WorldRenderer {
|
|||
private int glRenderList = -1;
|
||||
private static Tessellator tessellator = Tessellator.instance;
|
||||
public static int chunksUpdated = 0;
|
||||
public static int chunksGeometryUpdated = 0;
|
||||
public int posX;
|
||||
public int posY;
|
||||
public int posZ;
|
||||
|
@ -72,6 +73,7 @@ public class WorldRenderer {
|
|||
/** Is the chunk lit */
|
||||
public boolean isChunkLit;
|
||||
private boolean isInitialized = false;
|
||||
public int hasOcclusionData = 0;
|
||||
|
||||
/** All the tile entities that have special rendering code for this chunk */
|
||||
public List tileEntityRenderers = new ArrayList();
|
||||
|
@ -96,6 +98,7 @@ public class WorldRenderer {
|
|||
public void setPosition(int par1, int par2, int par3) {
|
||||
if (par1 != this.posX || par2 != this.posY || par3 != this.posZ) {
|
||||
this.setDontDraw();
|
||||
this.hasOcclusionData = 0;
|
||||
this.posX = par1;
|
||||
this.posY = par2;
|
||||
this.posZ = par3;
|
||||
|
@ -224,6 +227,11 @@ public class WorldRenderer {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!(skipRenderPass[0] && skipRenderPass[1])) {
|
||||
++chunksGeometryUpdated;
|
||||
}
|
||||
|
||||
EaglerAdapter.hintAnisotropicFix(false);
|
||||
}
|
||||
|
||||
|
@ -284,6 +292,10 @@ public class WorldRenderer {
|
|||
EaglerAdapter.glCallList(this.glRenderList + 2);
|
||||
}
|
||||
|
||||
public boolean shouldTryOcclusionQuery() {
|
||||
return !this.isInitialized ? true : !this.skipRenderPass[0] || !this.skipRenderPass[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all render passes are to be skipped. Returns false if the renderer
|
||||
* is not initialized
|
||||
|
|
Loading…
Reference in a new issue