Update #0 - First Release

This commit is contained in:
LAX1DUDE
2022-12-25 01:12:28 -08:00
commit e7179fad45
2154 changed files with 256324 additions and 0 deletions

View File

@ -0,0 +1,81 @@
package net.lax1dude.eaglercraft.v1_8.minecraft;
import net.lax1dude.eaglercraft.v1_8.opengl.InstancedParticleRenderer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.entity.Entity;
import net.minecraft.util.MathHelper;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class AcceleratedEffectRenderer implements IAcceleratedParticleEngine {
private float partialTicks;
private float f1;
private float f2;
private float f3;
private float f4;
private float f5;
public void begin(float partialTicks) {
this.partialTicks = partialTicks;
InstancedParticleRenderer.begin();
Entity et = Minecraft.getMinecraft().getRenderViewEntity();
if(et != null) {
f1 = MathHelper.cos(et.rotationYaw * 0.017453292F);
f2 = MathHelper.sin(et.rotationYaw * 0.017453292F);
f3 = -f2 * MathHelper.sin(et.rotationPitch * 0.017453292F);
f4 = f1 * MathHelper.sin(et.rotationPitch * 0.017453292F);
f5 = MathHelper.cos(et.rotationPitch * 0.017453292F);
}
}
public void draw(float texCoordWidth, float texCoordHeight) {
InstancedParticleRenderer.render(texCoordWidth, texCoordHeight, 0.0625f, f1, f5, f2, f3, f4);
}
@Override
public void drawParticle(Entity entityIn, int particleIndexX, int particleIndexY, int lightMapData,
int texSize, float particleSize, float r, float g, float b, float a) {
float xx = (float) (entityIn.prevPosX + (entityIn.posX - entityIn.prevPosX) * (double) partialTicks - EntityFX.interpPosX);
float yy = (float) (entityIn.prevPosY + (entityIn.posY - entityIn.prevPosY) * (double) partialTicks - EntityFX.interpPosY);
float zz = (float) (entityIn.prevPosZ + (entityIn.posZ - entityIn.prevPosZ) * (double) partialTicks - EntityFX.interpPosZ);
drawParticle(xx, yy, zz, particleIndexX, particleIndexY, lightMapData, texSize, particleSize, r, g, b, a);
}
@Override
public void drawParticle(Entity entityIn, int particleIndexX, int particleIndexY, int lightMapData,
int texSize, float particleSize, int rgba) {
float xx = (float) (entityIn.prevPosX + (entityIn.posX - entityIn.prevPosX) * (double) partialTicks - EntityFX.interpPosX);
float yy = (float) (entityIn.prevPosY + (entityIn.posY - entityIn.prevPosY) * (double) partialTicks - EntityFX.interpPosY);
float zz = (float) (entityIn.prevPosZ + (entityIn.posZ - entityIn.prevPosZ) * (double) partialTicks - EntityFX.interpPosZ);
drawParticle(xx, yy, zz, particleIndexX, particleIndexY, lightMapData, texSize, particleSize, rgba);
}
@Override
public void drawParticle(float posX, float posY, float posZ, int particleIndexX, int particleIndexY,
int lightMapData, int texSize, float particleSize, float r, float g, float b, float a) {
InstancedParticleRenderer.appendParticle(posX, posY, posZ, particleIndexX, particleIndexY, lightMapData & 0xFF,
(lightMapData >> 16) & 0xFF, (int)(particleSize * 16.0f), texSize, r, g, b, a);
}
@Override
public void drawParticle(float posX, float posY, float posZ, int particleIndexX, int particleIndexY,
int lightMapData, int texSize, float particleSize, int rgba) {
InstancedParticleRenderer.appendParticle(posX, posY, posZ, particleIndexX, particleIndexY, lightMapData & 0xFF,
(lightMapData >> 16) & 0xFF, (int)(particleSize * 16.0f), texSize, rgba);
}
}

View File

@ -0,0 +1,231 @@
package net.lax1dude.eaglercraft.v1_8.minecraft;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import java.util.LinkedList;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
import net.lax1dude.eaglercraft.v1_8.opengl.WorldVertexBufferUploader;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RegionRenderCacheBuilder;
import net.minecraft.client.renderer.chunk.ChunkCompileTaskGenerator;
import net.minecraft.client.renderer.chunk.CompiledChunk;
import net.minecraft.client.renderer.chunk.ListedRenderChunk;
import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.entity.Entity;
import net.minecraft.util.EnumWorldBlockLayer;
public class ChunkUpdateManager {
private static final Logger LOGGER = LogManager.getLogger();
private final WorldVertexBufferUploader worldVertexUploader;
private final RegionRenderCacheBuilder renderCache;
private int chunkUpdatesTotal = 0;
private int chunkUpdatesTotalLast = 0;
private int chunkUpdatesTotalImmediate = 0;
private int chunkUpdatesTotalImmediateLast = 0;
private int chunkUpdatesQueued = 0;
private int chunkUpdatesQueuedLast = 0;
private long chunkUpdatesTotalLastUpdate = 0l;
private final List<ChunkCompileTaskGenerator> queue = new LinkedList();
public ChunkUpdateManager() {
worldVertexUploader = new WorldVertexBufferUploader();
renderCache = new RegionRenderCacheBuilder();
}
public static class EmptyBlockLayerException extends IllegalStateException {
}
private void runGenerator(ChunkCompileTaskGenerator generator, Entity entity) {
generator.setRegionRenderCacheBuilder(renderCache);
float f = (float) entity.posX;
float f1 = (float) entity.posY + entity.getEyeHeight();
float f2 = (float) entity.posZ;
ChunkCompileTaskGenerator.Type chunkcompiletaskgenerator$type = generator.getType();
generator.setStatus(ChunkCompileTaskGenerator.Status.COMPILING);
if (chunkcompiletaskgenerator$type == ChunkCompileTaskGenerator.Type.REBUILD_CHUNK) {
generator.getRenderChunk().rebuildChunk(f, f1, f2, generator);
} else if (chunkcompiletaskgenerator$type == ChunkCompileTaskGenerator.Type.RESORT_TRANSPARENCY) {
RenderChunk r = generator.getRenderChunk();
try {
r.resortTransparency(f, f1, f2, generator);
if(generator.getCompiledChunk().isLayerEmpty(EnumWorldBlockLayer.TRANSLUCENT)) {
throw new EmptyBlockLayerException();
}
}catch(EmptyBlockLayerException ex) {
LOGGER.error("RenderChunk {} tried to update it's TRANSLUCENT layer with no proper initialization", r.getPosition());
generator.setStatus(ChunkCompileTaskGenerator.Status.DONE);
return; // rip
}
}
generator.setStatus(ChunkCompileTaskGenerator.Status.UPLOADING);
final CompiledChunk compiledchunk = generator.getCompiledChunk();
if (chunkcompiletaskgenerator$type == ChunkCompileTaskGenerator.Type.REBUILD_CHUNK) {
for (EnumWorldBlockLayer enumworldblocklayer : EnumWorldBlockLayer.values()) {
if (!compiledchunk.isLayerEmpty(enumworldblocklayer)) {
this.uploadChunk(enumworldblocklayer,
generator.getRegionRenderCacheBuilder().getWorldRendererByLayer(enumworldblocklayer),
generator.getRenderChunk(), compiledchunk);
generator.setStatus(ChunkCompileTaskGenerator.Status.DONE);
}
}
generator.getRenderChunk().setCompiledChunk(compiledchunk);
} else if (chunkcompiletaskgenerator$type == ChunkCompileTaskGenerator.Type.RESORT_TRANSPARENCY) {
this.uploadChunk(EnumWorldBlockLayer.TRANSLUCENT, generator.getRegionRenderCacheBuilder()
.getWorldRendererByLayer(EnumWorldBlockLayer.TRANSLUCENT),
generator.getRenderChunk(), compiledchunk);
generator.getRenderChunk().setCompiledChunk(compiledchunk);
generator.setStatus(ChunkCompileTaskGenerator.Status.DONE);
}
}
public boolean updateChunks(long timeout) {
Entity entity = Minecraft.getMinecraft().getRenderViewEntity();
if (entity == null) {
queue.clear();
chunkUpdatesQueued = 0;
return false;
}else {
boolean flag = false;
long millis = System.currentTimeMillis();
List<ChunkCompileTaskGenerator> droppedUpdates = new LinkedList();
while(!queue.isEmpty()) {
ChunkCompileTaskGenerator generator = queue.remove(0);
if(!generator.canExecuteYet()) {
if(millis - generator.goddamnFuckingTimeout < 60000l) {
droppedUpdates.add(generator);
}
continue;
}
runGenerator(generator, entity);
flag = true;
++chunkUpdatesTotal;
if(timeout < System.nanoTime()) {
break;
}
}
queue.addAll(droppedUpdates);
return flag;
}
}
public boolean updateChunkLater(RenderChunk chunkRenderer) {
final ChunkCompileTaskGenerator chunkcompiletaskgenerator = chunkRenderer.makeCompileTaskChunk();
boolean flag = queue.size() < 100;
if (!flag) {
chunkcompiletaskgenerator.finish();
}else {
chunkcompiletaskgenerator.addFinishRunnable(new Runnable() {
@Override
public void run() {
if(queue.remove(chunkcompiletaskgenerator)) {
++chunkUpdatesTotal;
}
}
});
queue.add(chunkcompiletaskgenerator);
++chunkUpdatesQueued;
}
return flag;
}
public boolean updateChunkNow(RenderChunk chunkRenderer) {
Entity entity = Minecraft.getMinecraft().getRenderViewEntity();
if (entity != null) {
runGenerator(chunkRenderer.makeCompileTaskChunk(), entity);
++chunkUpdatesTotalImmediate;
}
return true;
}
public void stopChunkUpdates() {
queue.clear();
chunkUpdatesQueued = 0;
}
public boolean updateTransparencyLater(RenderChunk chunkRenderer) {
if(isAlreadyQueued(chunkRenderer)) {
return true;
}
final ChunkCompileTaskGenerator chunkcompiletaskgenerator = chunkRenderer.makeCompileTaskTransparency();
if (chunkcompiletaskgenerator == null) {
return true;
}
chunkcompiletaskgenerator.goddamnFuckingTimeout = System.currentTimeMillis();
if(queue.size() < 100) {
chunkcompiletaskgenerator.addFinishRunnable(new Runnable() {
@Override
public void run() {
if(queue.remove(chunkcompiletaskgenerator)) {
++chunkUpdatesTotal;
}
}
});
queue.add(chunkcompiletaskgenerator);
++chunkUpdatesQueued;
return true;
}else {
return false;
}
}
public void uploadChunk(final EnumWorldBlockLayer player, final WorldRenderer chunkRenderer,
final RenderChunk compiledChunkIn, final CompiledChunk parCompiledChunk) {
this.uploadDisplayList(chunkRenderer,
((ListedRenderChunk) compiledChunkIn).getDisplayList(player, parCompiledChunk), compiledChunkIn);
chunkRenderer.setTranslation(0.0D, 0.0D, 0.0D);
}
private void uploadDisplayList(WorldRenderer chunkRenderer, int parInt1, RenderChunk parRenderChunk) {
EaglercraftGPU.glNewList(parInt1, GL_COMPILE);
GlStateManager.pushMatrix();
this.worldVertexUploader.func_181679_a(chunkRenderer);
GlStateManager.popMatrix();
EaglercraftGPU.glEndList();
}
public boolean isAlreadyQueued(RenderChunk update) {
for(int i = 0, l = queue.size(); i < l; ++i) {
if(queue.get(i).getRenderChunk() == update) {
return true;
}
}
return false;
}
public String getDebugInfo() {
long millis = System.currentTimeMillis();
if(millis - chunkUpdatesTotalLastUpdate > 500l) {
chunkUpdatesTotalLastUpdate = millis;
chunkUpdatesTotalLast = chunkUpdatesTotal;
chunkUpdatesTotalImmediateLast = chunkUpdatesTotalImmediate;
chunkUpdatesTotalImmediate = 0;
chunkUpdatesTotal = 0;
chunkUpdatesQueuedLast = chunkUpdatesQueued;
chunkUpdatesQueued -= chunkUpdatesTotalLast;
if(chunkUpdatesQueued < 0) {
chunkUpdatesQueued = 0;
}
}
return "Uq: " + (chunkUpdatesTotalLast + chunkUpdatesTotalImmediateLast) + "/"
+ (chunkUpdatesQueuedLast + chunkUpdatesTotalImmediateLast);
}
}

View File

@ -0,0 +1,231 @@
package net.lax1dude.eaglercraft.v1_8.minecraft;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.InstancedFontRenderer;
import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class EaglerFontRenderer extends FontRenderer {
private final int[] temporaryCodepointArray = new int[6553];
public EaglerFontRenderer(GameSettings gameSettingsIn, ResourceLocation location, TextureManager textureManagerIn,
boolean unicode) {
super(gameSettingsIn, location, textureManagerIn, unicode);
}
public int drawString(String text, float x, float y, int color, boolean dropShadow) {
if (text == null || text.length() == 0) {
this.posX = x + (dropShadow ? 1 : 0);
this.posY = y;
} else {
if(this.unicodeFlag || !decodeASCIICodepointsAndValidate(text)) {
return super.drawString(text, x, y, color, dropShadow);
}
this.resetStyles();
if ((color & 0xFC000000) == 0) {
color |= 0xFF000000;
}
this.red = (float) (color >> 16 & 255) / 255.0F;
this.blue = (float) (color >> 8 & 255) / 255.0F;
this.green = (float) (color & 255) / 255.0F;
this.alpha = (float) (color >> 24 & 255) / 255.0F;
this.posX = x;
this.posY = y;
this.textColor = color;
this.renderStringAtPos0(text, dropShadow);
}
return (int) this.posX;
}
protected void renderStringAtPos(String parString1, boolean parFlag) {
if(parString1 == null) return;
if(this.unicodeFlag || !decodeASCIICodepointsAndValidate(parString1)) {
super.renderStringAtPos(parString1, parFlag);
}else {
renderStringAtPos0(parString1, false);
}
}
private void renderStringAtPos0(String parString1, boolean parFlag) {
renderEngine.bindTexture(locationFontTexture);
InstancedFontRenderer.begin();
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer worldrenderer = tessellator.getWorldRenderer();
worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR);
boolean hasStrike = false;
for (int i = 0; i < parString1.length(); ++i) {
char c0 = parString1.charAt(i);
if (c0 == 167 && i + 1 < parString1.length()) {
int i1 = "0123456789abcdefklmnor".indexOf(Character.toLowerCase(parString1.charAt(i + 1)));
if (i1 < 16) {
this.randomStyle = false;
this.boldStyle = false;
this.strikethroughStyle = false;
this.underlineStyle = false;
this.italicStyle = false;
if (i1 < 0 || i1 > 15) {
i1 = 15;
}
int j1 = this.colorCode[i1];
this.textColor = j1 | (this.textColor & 0xFF000000);
} else if (i1 == 16) {
this.randomStyle = true;
} else if (i1 == 17) {
this.boldStyle = true;
} else if (i1 == 18) {
this.strikethroughStyle = true;
} else if (i1 == 19) {
this.underlineStyle = true;
} else if (i1 == 20) {
this.italicStyle = true;
} else if (i1 == 21) {
this.randomStyle = false;
this.boldStyle = false;
this.strikethroughStyle = false;
this.underlineStyle = false;
this.italicStyle = false;
this.textColor = ((int) (this.alpha * 255.0f) << 24) | ((int) (this.red * 255.0f) << 16)
| ((int) (this.green * 255.0f) << 8) | (int) (this.blue * 255.0f);
}
++i;
} else {
int j = temporaryCodepointArray[i];
if (this.randomStyle && j != -1) {
int k = this.getCharWidth(c0);
String chars = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000";
char c1;
while (true) {
j = this.fontRandom.nextInt(chars.length());
c1 = chars.charAt(j);
if (k == this.getCharWidth(c1)) {
break;
}
}
c0 = c1;
}
float f = this.appendCharToBuffer(j, this.textColor, this.boldStyle, this.italicStyle);
if (this.strikethroughStyle) {
hasStrike = true;
worldrenderer.pos((double) this.posX, (double) (this.posY + (float) (this.FONT_HEIGHT / 2)), 0.0D)
.endVertex();
worldrenderer
.pos((double) (this.posX + f), (double) (this.posY + (float) (this.FONT_HEIGHT / 2)), 0.0D)
.endVertex();
worldrenderer.pos((double) (this.posX + f),
(double) (this.posY + (float) (this.FONT_HEIGHT / 2) - 1.0F), 0.0D).endVertex();
worldrenderer
.pos((double) this.posX, (double) (this.posY + (float) (this.FONT_HEIGHT / 2) - 1.0F), 0.0D)
.endVertex();
worldrenderer.putColor4(this.textColor);
}
if (this.underlineStyle) {
hasStrike = true;
int l = this.underlineStyle ? -1 : 0;
worldrenderer.pos((double) (this.posX + (float) l),
(double) (this.posY + (float) this.FONT_HEIGHT), 0.0D).endVertex();
worldrenderer.pos((double) (this.posX + f), (double) (this.posY + (float) this.FONT_HEIGHT), 0.0D)
.endVertex();
worldrenderer
.pos((double) (this.posX + f), (double) (this.posY + (float) this.FONT_HEIGHT - 1.0F), 0.0D)
.endVertex();
worldrenderer.pos((double) (this.posX + (float) l),
(double) (this.posY + (float) this.FONT_HEIGHT - 1.0F), 0.0D).endVertex();
worldrenderer.putColor4(this.textColor);
}
this.posX += (float) ((int) f);
}
}
float texScale = 0.0625f;
if(!hasStrike) {
worldrenderer.finishDrawing();
}
if(parFlag) {
if(hasStrike) {
GlStateManager.color(0.25f, 0.25f, 0.25f, 1.0f);
GlStateManager.translate(1.0f, 1.0f, 0.0f);
tessellator.draw();
GlStateManager.translate(-1.0f, -1.0f, 0.0f);
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
InstancedFontRenderer.render(8, 8, texScale, texScale, true);
EaglercraftGPU.renderAgain();
}else {
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
InstancedFontRenderer.render(8, 8, texScale, texScale, true);
}
}else {
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
if(hasStrike) {
tessellator.draw();
}
InstancedFontRenderer.render(8, 8, texScale, texScale, false);
}
if(parFlag) {
this.posX += 1.0f;
}
}
private float appendCharToBuffer(int parInt1, int color, boolean boldStyle, boolean italicStyle) {
if (parInt1 == 32) {
return 4.0f;
}else {
int i = parInt1 % 16;
int j = parInt1 / 16;
float w = this.charWidth[parInt1];
if(boldStyle) {
InstancedFontRenderer.appendBoldQuad((int)this.posX, (int)this.posY, i, j, color, italicStyle);
++w;
}else {
InstancedFontRenderer.appendQuad((int)this.posX, (int)this.posY, i, j, color, italicStyle);
}
return w;
}
}
private boolean decodeASCIICodepointsAndValidate(String str) {
for(int i = 0, l = str.length(); i < l; ++i) {
int j = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000\u00a7"
.indexOf(str.charAt(i));
if(j != -1) {
temporaryCodepointArray[i] = j;
}else {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,355 @@
package net.lax1dude.eaglercraft.v1_8.minecraft;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import com.google.common.collect.Lists;
import net.lax1dude.eaglercraft.v1_8.HString;
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
import net.minecraft.client.renderer.texture.TextureClock;
import net.minecraft.client.renderer.texture.TextureCompass;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.resources.data.AnimationFrame;
import net.minecraft.client.resources.data.AnimationMetadataSection;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.util.ReportedException;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class EaglerTextureAtlasSprite {
private final String iconName;
protected List<int[][]> framesTextureData = Lists.newArrayList();
protected int[][] interpolatedFrameData;
private AnimationMetadataSection animationMetadata;
private int cacheInterpolateSteps;
protected boolean rotated;
protected int originX;
protected int originY;
protected int width;
protected int height;
private float minU;
private float maxU;
private float minV;
private float maxV;
protected int frameCounter;
protected int tickCounter;
private static String locationNameClock = "builtin/clock";
private static String locationNameCompass = "builtin/compass";
protected TextureAnimationCache animationCache = null;
public EaglerTextureAtlasSprite(String spriteName) {
this.iconName = spriteName;
}
public static EaglerTextureAtlasSprite makeAtlasSprite(ResourceLocation spriteResourceLocation) {
String s = spriteResourceLocation.toString();
return (EaglerTextureAtlasSprite) (locationNameClock.equals(s) ? new TextureClock(s)
: (locationNameCompass.equals(s) ? new TextureCompass(s) : new EaglerTextureAtlasSprite(s)));
}
public static void setLocationNameClock(String clockName) {
locationNameClock = clockName;
}
public static void setLocationNameCompass(String compassName) {
locationNameCompass = compassName;
}
public void initSprite(int inX, int inY, int originInX, int originInY, boolean rotatedIn) {
this.originX = originInX;
this.originY = originInY;
this.rotated = rotatedIn;
float f = (float) (0.009999999776482582D / (double) inX);
float f1 = (float) (0.009999999776482582D / (double) inY);
this.minU = (float) originInX / (float) ((double) inX) + f;
this.maxU = (float) (originInX + this.width) / (float) ((double) inX) - f;
this.minV = (float) originInY / (float) inY + f1;
this.maxV = (float) (originInY + this.height) / (float) inY - f1;
}
public void copyFrom(EaglerTextureAtlasSprite atlasSpirit) {
this.originX = atlasSpirit.originX;
this.originY = atlasSpirit.originY;
this.width = atlasSpirit.width;
this.height = atlasSpirit.height;
this.rotated = atlasSpirit.rotated;
this.minU = atlasSpirit.minU;
this.maxU = atlasSpirit.maxU;
this.minV = atlasSpirit.minV;
this.maxV = atlasSpirit.maxV;
}
public int getOriginX() {
return this.originX;
}
public int getOriginY() {
return this.originY;
}
public int getIconWidth() {
return this.width;
}
public int getIconHeight() {
return this.height;
}
public float getMinU() {
return this.minU;
}
public float getMaxU() {
return this.maxU;
}
public float getInterpolatedU(double u) {
float f = this.maxU - this.minU;
return this.minU + f * (float) u / 16.0F;
}
public float getMinV() {
return this.minV;
}
public float getMaxV() {
return this.maxV;
}
public float getInterpolatedV(double v) {
float f = this.maxV - this.minV;
return this.minV + f * ((float) v / 16.0F);
}
public String getIconName() {
return this.iconName;
}
public void updateAnimation() {
if(animationCache == null) {
throw new IllegalStateException("Animation cache for '" + this.iconName + "' was never baked!");
}
++this.tickCounter;
if (this.tickCounter >= this.animationMetadata.getFrameTimeSingle(this.frameCounter)) {
int i = this.animationMetadata.getFrameIndex(this.frameCounter);
int j = this.animationMetadata.getFrameCount() == 0 ? this.framesTextureData.size()
: this.animationMetadata.getFrameCount();
this.frameCounter = (this.frameCounter + 1) % j;
this.tickCounter = 0;
int k = this.animationMetadata.getFrameIndex(this.frameCounter);
if (i != k && k >= 0 && k < this.framesTextureData.size()) {
animationCache.copyFrameLevelsToTex2D(k, this.originX, this.originY, this.width, this.height);
}
} else if (this.animationMetadata.isInterpolate()) {
float f = 1.0f - (float) this.tickCounter / (float) this.animationMetadata.getFrameTimeSingle(this.frameCounter);
int i = this.animationMetadata.getFrameIndex(this.frameCounter);
int j = this.animationMetadata.getFrameCount() == 0 ? this.framesTextureData.size()
: this.animationMetadata.getFrameCount();
int k = this.animationMetadata.getFrameIndex((this.frameCounter + 1) % j);
if (i != k && k >= 0 && k < this.framesTextureData.size()) {
animationCache.copyInterpolatedFrameLevelsToTex2D(i, k, f, this.originX, this.originY, this.width, this.height);
}
}
}
public int[][] getFrameTextureData(int index) {
return (int[][]) this.framesTextureData.get(index);
}
public int getFrameCount() {
return this.framesTextureData.size();
}
public void setIconWidth(int newWidth) {
this.width = newWidth;
}
public void setIconHeight(int newHeight) {
this.height = newHeight;
}
public void loadSprite(ImageData[] images, AnimationMetadataSection meta) throws IOException {
this.resetSprite();
int i = images[0].width;
int j = images[0].height;
this.width = i;
this.height = j;
int[][] aint = new int[images.length][];
for (int k = 0; k < images.length; ++k) {
ImageData bufferedimage = images[k];
if (bufferedimage != null) {
if (k > 0 && (bufferedimage.width) != i >> k || bufferedimage.height != j >> k) {
throw new RuntimeException(
HString.format("Unable to load miplevel: %d, image is size: %dx%d, expected %dx%d",
new Object[] { Integer.valueOf(k), Integer.valueOf(bufferedimage.width),
Integer.valueOf(bufferedimage.height), Integer.valueOf(i >> k),
Integer.valueOf(j >> k) }));
}
aint[k] = new int[bufferedimage.width * bufferedimage.height];
bufferedimage.getRGB(0, 0, bufferedimage.width, bufferedimage.height, aint[k], 0, bufferedimage.width);
}
}
if (meta == null) {
if (j != i) {
throw new RuntimeException("broken aspect ratio and not an animation");
}
this.framesTextureData.add(aint);
} else {
int j1 = j / i;
int k1 = i;
int l = i;
this.height = this.width;
if (meta.getFrameCount() > 0) {
Iterator iterator = meta.getFrameIndexSet().iterator();
while (iterator.hasNext()) {
int i1 = ((Integer) iterator.next()).intValue();
if (i1 >= j1) {
throw new RuntimeException("invalid frameindex " + i1);
}
this.allocateFrameTextureData(i1);
this.framesTextureData.set(i1, getFrameTextureData(aint, k1, l, i1));
}
this.animationMetadata = meta;
} else {
ArrayList arraylist = Lists.newArrayList();
for (int l1 = 0; l1 < j1; ++l1) {
this.framesTextureData.add(getFrameTextureData(aint, k1, l, l1));
arraylist.add(new AnimationFrame(l1, -1));
}
this.animationMetadata = new AnimationMetadataSection(arraylist, this.width, this.height,
meta.getFrameTime(), meta.isInterpolate());
}
}
}
public void generateMipmaps(int level) {
ArrayList arraylist = Lists.newArrayList();
for (int i = 0; i < this.framesTextureData.size(); ++i) {
final int[][] aint = (int[][]) this.framesTextureData.get(i);
if (aint != null) {
try {
arraylist.add(TextureUtil.generateMipmapData(level, this.width, aint));
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Generating mipmaps for frame");
CrashReportCategory crashreportcategory = crashreport.makeCategory("Frame being iterated");
crashreportcategory.addCrashSection("Frame index", Integer.valueOf(i));
crashreportcategory.addCrashSectionCallable("Frame sizes", new Callable<String>() {
public String call() throws Exception {
StringBuilder stringbuilder = new StringBuilder();
for (int[] aint1 : aint) {
if (stringbuilder.length() > 0) {
stringbuilder.append(", ");
}
stringbuilder.append(aint1 == null ? "null" : Integer.valueOf(aint1.length));
}
return stringbuilder.toString();
}
});
throw new ReportedException(crashreport);
}
}
}
this.setFramesTextureData(arraylist);
this.bakeAnimationCache();
}
public void bakeAnimationCache() {
if(animationMetadata != null) {
int mipLevels = framesTextureData.get(0).length;
if(animationCache == null) {
animationCache = new TextureAnimationCache(width, height, mipLevels);
}
animationCache.initialize(framesTextureData, animationMetadata.isInterpolate());
}
}
private void allocateFrameTextureData(int index) {
if (this.framesTextureData.size() <= index) {
for (int i = this.framesTextureData.size(); i <= index; ++i) {
this.framesTextureData.add((int[][]) null);
}
}
}
private static int[][] getFrameTextureData(int[][] data, int rows, int columns, int parInt3) {
int[][] aint = new int[data.length][];
for (int i = 0; i < data.length; ++i) {
int[] aint1 = data[i];
if (aint1 != null) {
aint[i] = new int[(rows >> i) * (columns >> i)];
System.arraycopy(aint1, parInt3 * aint[i].length, aint[i], 0, aint[i].length);
}
}
return aint;
}
public void clearFramesTextureData() {
this.framesTextureData.clear();
if(this.animationCache != null) {
this.animationCache.free();
this.animationCache = null;
}
}
public boolean hasAnimationMetadata() {
return this.animationMetadata != null;
}
public void setFramesTextureData(List<int[][]> newFramesTextureData) {
this.framesTextureData = newFramesTextureData;
}
private void resetSprite() {
this.animationMetadata = null;
this.setFramesTextureData(Lists.newArrayList());
this.frameCounter = 0;
this.tickCounter = 0;
if(this.animationCache != null) {
this.animationCache.free();
this.animationCache = null;
}
}
public String toString() {
return "TextureAtlasSprite{name=\'" + this.iconName + '\'' + ", frameCount=" + this.framesTextureData.size()
+ ", rotated=" + this.rotated + ", x=" + this.originX + ", y=" + this.originY + ", height="
+ this.height + ", width=" + this.width + ", u0=" + this.minU + ", u1=" + this.maxU + ", v0="
+ this.minV + ", v1=" + this.maxV + '}';
}
}

View File

@ -0,0 +1,32 @@
package net.lax1dude.eaglercraft.v1_8.minecraft;
import net.minecraft.entity.Entity;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public interface IAcceleratedParticleEngine {
void drawParticle(Entity entityIn, int particleIndexX, int particleIndexY,
int lightMapData, int texSize, float particleSize, float r, float g, float b, float a);
void drawParticle(Entity entityIn, int particleIndexX, int particleIndexY,
int lightMapData, int texSize, float particleSize, int rgba);
void drawParticle(float posX, float posY, float posZ, int particleIndexX, int particleIndexY,
int lightMapData, int texSize, float particleSize, float r, float g, float b, float a);
void drawParticle(float posX, float posY, float posZ, int particleIndexX, int particleIndexY,
int lightMapData, int texSize, float particleSize, int rgba);
}

View File

@ -0,0 +1,237 @@
package net.lax1dude.eaglercraft.v1_8.minecraft;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.IFramebufferGL;
import net.lax1dude.eaglercraft.v1_8.internal.IRenderbufferGL;
import net.lax1dude.eaglercraft.v1_8.internal.ITextureGL;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.SpriteLevelMixer;
import net.lax1dude.eaglercraft.v1_8.vector.Matrix3f;
import net.minecraft.client.renderer.GLAllocation;
/**
* Copyright (c) 2022 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
public class TextureAnimationCache {
public static final int _GL_FRAMEBUFFER = 0x8D40; // enum not defined in RealOpenGLEnums
public static final int _GL_RENDERBUFFER = 0x8D41;
public static final int _GL_COLOR_ATTACHMENT0 = 0x8CE0;
public final int width;
public final int height;
public final int mipLevels;
private int frameCount = 1;
private int[] cacheTextures = null;
private IFramebufferGL[] cacheFramebuffers = null;
private IFramebufferGL interpolateFramebuffer = null;
private IRenderbufferGL interpolateRenderbuffer = null;
public TextureAnimationCache(int width, int height, int mipLevels) {
this.width = width;
this.height = height;
this.mipLevels = mipLevels;
}
public void initialize(List<int[][]> frames, boolean enableInterpolation) {
boolean init = cacheTextures == null;
if(init) {
cacheTextures = new int[mipLevels];
for(int i = 0; i < cacheTextures.length; ++i) {
cacheTextures[i] = GlStateManager.generateTexture();
GlStateManager.bindTexture(cacheTextures[i]);
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
EaglercraftGPU.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
if(enableInterpolation) {
interpolateFramebuffer = _wglCreateFramebuffer();
_wglBindFramebuffer(_GL_FRAMEBUFFER, interpolateFramebuffer);
interpolateRenderbuffer = _wglCreateRenderbuffer();
_wglBindRenderbuffer(_GL_RENDERBUFFER, interpolateRenderbuffer);
_wglRenderbufferStorage(_GL_RENDERBUFFER, GL_RGBA8, width, height);
_wglFramebufferRenderbuffer(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0,
_GL_RENDERBUFFER, interpolateRenderbuffer);
_wglBindFramebuffer(_GL_FRAMEBUFFER, null);
}
}
frameCount = frames.size();
IntBuffer pixels = GLAllocation.createDirectIntBuffer(width * height * frameCount);
try {
for(int i = 0; i < mipLevels; ++i) {
pixels.clear();
int lw = width >> i;
int lh = height >> i;
int tileLength = lw * lh;
for(int j = 0; j < frameCount; ++j) {
int[][] frame = frames.get(j);
if(frame.length <= i) {
throw new IllegalArgumentException("Frame #" + j + " only has " + frame.length + " mipmap levels! (" + mipLevels + " were expected)");
}
int[] frameLevel = frame[i];
if(frameLevel.length != tileLength) {
throw new IllegalArgumentException("Frame #" + j + " level " + i + " is " + frameLevel.length + " pixels large! (" + tileLength + " expected)");
}
pixels.put(frameLevel);
}
pixels.flip();
GlStateManager.bindTexture(cacheTextures[i]);
EaglercraftGPU.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, lw, lh * frameCount, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
}
}finally {
EagRuntime.freeIntBuffer(pixels);
}
if(init) {
cacheFramebuffers = new IFramebufferGL[mipLevels];
for(int i = 0; i < mipLevels; ++i) {
GlStateManager.bindTexture(cacheTextures[i]);
IFramebufferGL fbo = _wglCreateFramebuffer();
_wglBindFramebuffer(_GL_FRAMEBUFFER, fbo);
_wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
EaglercraftGPU.getNativeTexture(cacheTextures[i]), 0);
cacheFramebuffers[i] = fbo;
}
_wglBindFramebuffer(_GL_FRAMEBUFFER, null);
}
}
public void free() {
if(cacheTextures != null) {
if(interpolateFramebuffer != null) {
_wglDeleteFramebuffer(interpolateFramebuffer);
interpolateFramebuffer = null;
}
if(interpolateRenderbuffer != null) {
_wglDeleteRenderbuffer(interpolateRenderbuffer);
interpolateRenderbuffer = null;
}
if(cacheFramebuffers != null) {
for(int i = 0; i < mipLevels; ++i) {
_wglDeleteFramebuffer(cacheFramebuffers[i]);
}
cacheFramebuffers = null;
}
for(int i = 0; i < cacheTextures.length; ++i) {
GlStateManager.deleteTexture(cacheTextures[i]);
}
cacheTextures = null;
}
}
public void copyFrameLevelsToTex2D(int animationFrame, int dx, int dy, int w, int h) {
copyFrameLevelsToTex2D(animationFrame, mipLevels, dx, dy, w, h);
}
public void copyFrameLevelsToTex2D(int animationFrame, int levels, int dx, int dy, int w, int h) {
for(int i = 0; i < levels; ++i) {
copyFrameToTex2D(animationFrame, i, dx >> i, dy >> i, w >> i, h >> i);
}
}
public void copyFrameToTex2D(int animationFrame, int level, int dx, int dy, int w, int h) {
if(cacheTextures == null) {
throw new IllegalStateException("Cannot copy from uninitialized TextureAnimationCache");
}
_wglBindFramebuffer(_GL_FRAMEBUFFER, cacheFramebuffers[level]);
_wglReadBuffer(_GL_COLOR_ATTACHMENT0);
_wglCopyTexSubImage2D(GL_TEXTURE_2D, level, dx, dy, 0, h * animationFrame, w, h);
_wglBindFramebuffer(_GL_FRAMEBUFFER, null);
}
public void copyInterpolatedFrameLevelsToTex2D(int animationFrameFrom, int animationFrameTo, float factor, int dx,
int dy, int w, int h) {
copyInterpolatedFrameLevelsToTex2D(animationFrameFrom, animationFrameTo, factor, mipLevels, dx, dy, w, h);
}
public void copyInterpolatedFrameLevelsToTex2D(int animationFrameFrom, int animationFrameTo, float factor,
int levels, int dx, int dy, int w, int h) {
for(int i = 0; i < levels; ++i) {
copyInterpolatedFrameToTex2D(animationFrameFrom, animationFrameTo, factor, i, dx >> i, dy >> i, w >> i, h >> i);
}
}
public void copyInterpolatedFrameToTex2D(int animationFrameFrom, int animationFrameTo, float factor, int level,
int dx, int dy, int w, int h) {
if(cacheTextures == null) {
throw new IllegalStateException("Cannot copy from uninitialized TextureAnimationCache");
}
int storeTexture = GlStateManager.getTextureBound();
_wglBindFramebuffer(_GL_FRAMEBUFFER, interpolateFramebuffer);
GlStateManager.bindTexture(cacheTextures[level]);
int[] storeViewport = new int[4];
EaglercraftGPU.glGetInteger(GL_VIEWPORT, storeViewport);
GlStateManager.viewport(0, 0, w, h);
GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
GlStateManager.clear(GL_COLOR_BUFFER_BIT);
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL_ONE, GL_ONE);
Matrix3f matrix = new Matrix3f();
matrix.m11 = 1.0f / frameCount;
matrix.m21 = matrix.m11 * animationFrameFrom;
SpriteLevelMixer.setMatrix3f(matrix);
SpriteLevelMixer.setBlendColor(factor, factor, factor, factor);
SpriteLevelMixer.setBiasColor(0.0f, 0.0f, 0.0f, 0.0f);
SpriteLevelMixer.drawSprite(0);
matrix.m21 = matrix.m11 * animationFrameTo;
SpriteLevelMixer.setMatrix3f(matrix);
float fac1 = 1.0f - factor;
SpriteLevelMixer.setBlendColor(fac1, fac1, fac1, fac1);
SpriteLevelMixer.drawSprite(0);
GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GlStateManager.disableBlend();
GlStateManager.bindTexture(storeTexture);
GlStateManager.viewport(storeViewport[0], storeViewport[1], storeViewport[2], storeViewport[3]);
GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
_wglReadBuffer(_GL_COLOR_ATTACHMENT0);
_wglCopyTexSubImage2D(GL_TEXTURE_2D, level, dx, dy, 0, 0, w, h);
_wglBindFramebuffer(_GL_FRAMEBUFFER, null);
}
public int getFrameCount() {
return frameCount;
}
}