Update #37 - Touch support without userscript, many other feats

This commit is contained in:
lax1dude
2024-09-21 20:17:42 -07:00
parent 173727c8c4
commit ec1ab8ece3
683 changed files with 62074 additions and 8996 deletions

View File

@ -3,15 +3,16 @@ package net.lax1dude.eaglercraft.v1_8.opengl;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL;
import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants;
/**
* Copyright (c) 2022-2023 lax1dude. All Rights Reserved.
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -28,17 +29,19 @@ import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionCon
public class DrawUtils {
public static final String vertexShaderPath = "/assets/eagler/glsl/local.vsh";
public static final String vertexShaderPrecision = "precision highp float;\n";
public static IBufferArrayGL standardQuad2DVAO = null;
public static IBufferArrayGL standardQuad3DVAO = null;
public static IBufferGL standardQuadVBO = null;
public static IShaderGL vshLocal = null;
public static List<VSHInputLayoutParser.ShaderInput> vshLocalLayout = null;
static void init() {
if(standardQuad2DVAO == null) {
standardQuad2DVAO = _wglGenVertexArrays();
standardQuad3DVAO = _wglGenVertexArrays();
standardQuad2DVAO = EaglercraftGPU.createGLBufferArray();
standardQuad3DVAO = EaglercraftGPU.createGLBufferArray();
standardQuadVBO = _wglGenBuffers();
FloatBuffer verts = EagRuntime.allocateFloatBuffer(18);
@ -48,30 +51,29 @@ public class DrawUtils {
});
verts.flip();
EaglercraftGPU.bindGLArrayBuffer(standardQuadVBO);
EaglercraftGPU.bindVAOGLArrayBufferNow(standardQuadVBO);
_wglBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW);
EagRuntime.freeFloatBuffer(verts);
EaglercraftGPU.bindGLBufferArray(standardQuad2DVAO);
_wglEnableVertexAttribArray(0);
_wglVertexAttribPointer(0, 2, GL_FLOAT, false, 12, 0);
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, 2, GL_FLOAT, false, 12, 0);
EaglercraftGPU.bindGLBufferArray(standardQuad3DVAO);
_wglEnableVertexAttribArray(0);
_wglVertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
}
if(vshLocal == null) {
String vertexSource = EagRuntime.getResourceString(vertexShaderPath);
if(vertexSource == null) {
throw new RuntimeException("vertex shader \"" + vertexShaderPath + "\" is missing!");
}
String vertexSource = EagRuntime.getRequiredResourceString(vertexShaderPath);
vshLocalLayout = VSHInputLayoutParser.getShaderInputs(vertexSource);
vshLocal = _wglCreateShader(GL_VERTEX_SHADER);
_wglShaderSource(vshLocal, FixedFunctionConstants.VERSION + "\n" + vertexSource);
_wglShaderSource(vshLocal, GLSLHeader.getVertexHeaderCompat(vertexSource, vertexShaderPrecision));
_wglCompileShader(vshLocal);
if(_wglGetShaderi(vshLocal, GL_COMPILE_STATUS) != GL_TRUE) {
@ -90,12 +92,32 @@ public class DrawUtils {
public static void drawStandardQuad2D() {
EaglercraftGPU.bindGLBufferArray(standardQuad2DVAO);
_wglDrawArrays(GL_TRIANGLES, 0, 6);
EaglercraftGPU.doDrawArrays(GL_TRIANGLES, 0, 6);
}
public static void drawStandardQuad3D() {
EaglercraftGPU.bindGLBufferArray(standardQuad3DVAO);
_wglDrawArrays(GL_TRIANGLES, 0, 6);
EaglercraftGPU.doDrawArrays(GL_TRIANGLES, 0, 6);
}
public static void destroy() {
if(standardQuad2DVAO != null) {
EaglercraftGPU.destroyGLBufferArray(standardQuad2DVAO);
standardQuad2DVAO = null;
}
if(standardQuad3DVAO != null) {
EaglercraftGPU.destroyGLBufferArray(standardQuad3DVAO);
standardQuad3DVAO = null;
}
if(standardQuadVBO != null) {
_wglDeleteBuffers(standardQuadVBO);
standardQuadVBO = null;
}
if(vshLocal != null) {
vshLocal.free();
vshLocal = null;
vshLocalLayout = null;
}
}
}

View File

@ -39,7 +39,7 @@ public class EaglerMeshLoader implements IResourceManagerReloadListener {
private static final Logger logger = LogManager.getLogger("EaglerMeshLoader");
private static final Map<ResourceLocation, HighPolyMesh> meshCache = new HashMap();
private static final Map<ResourceLocation, HighPolyMesh> meshCache = new HashMap<>();
public static HighPolyMesh getEaglerMesh(ResourceLocation meshLoc) {
if(meshLoc.cachedPointerType == ResourceLocation.CACHED_POINTER_EAGLER_MESH) {
@ -104,7 +104,7 @@ public class EaglerMeshLoader implements IResourceManagerReloadListener {
}
if(meshStruct.vertexArray == null) {
meshStruct.vertexArray = _wglGenVertexArrays();
meshStruct.vertexArray = EaglercraftGPU.createGLBufferArray();
}
if(meshStruct.vertexBuffer == null) {
meshStruct.vertexBuffer = _wglGenBuffers();
@ -115,29 +115,29 @@ public class EaglerMeshLoader implements IResourceManagerReloadListener {
up1.position(0).limit(intsOfVertex);
EaglercraftGPU.bindGLArrayBuffer(meshStruct.vertexBuffer);
EaglercraftGPU.bindVAOGLArrayBufferNow(meshStruct.vertexBuffer);
_wglBufferData(GL_ARRAY_BUFFER, up1, GL_STATIC_DRAW);
EaglercraftGPU.bindGLBufferArray(meshStruct.vertexArray);
up1.position(intsOfVertex).limit(intsTotal);
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshStruct.indexBuffer);
EaglercraftGPU.bindVAOGLElementArrayBufferNow(meshStruct.indexBuffer);
_wglBufferData(GL_ELEMENT_ARRAY_BUFFER, up1, GL_STATIC_DRAW);
_wglEnableVertexAttribArray(0);
_wglVertexAttribPointer(0, 3, GL_FLOAT, false, stride, 0);
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, 3, GL_FLOAT, false, stride, 0);
if(meshStruct.hasTexture) {
_wglEnableVertexAttribArray(1);
_wglVertexAttribPointer(1, 2, GL_FLOAT, false, stride, 16);
EaglercraftGPU.enableVertexAttribArray(1);
EaglercraftGPU.vertexAttribPointer(1, 2, GL_FLOAT, false, stride, 16);
}
_wglEnableVertexAttribArray(meshStruct.hasTexture ? 2 : 1);
_wglVertexAttribPointer(meshStruct.hasTexture ? 2 : 1, 4, GL_BYTE, true, stride, 12);
EaglercraftGPU.enableVertexAttribArray(meshStruct.hasTexture ? 2 : 1);
EaglercraftGPU.vertexAttribPointer(meshStruct.hasTexture ? 2 : 1, 4, GL_BYTE, true, stride, 12);
}catch(Throwable ex) {
if(meshStruct.vertexArray != null) {
_wglDeleteVertexArrays(meshStruct.vertexArray);
EaglercraftGPU.destroyGLBufferArray(meshStruct.vertexArray);
meshStruct.vertexArray = null;
}
if(meshStruct.vertexBuffer != null) {

View File

@ -5,6 +5,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.minecraft.util.MathHelper;
import java.util.HashMap;
import java.util.Map;
@ -16,7 +17,6 @@ import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
import net.lax1dude.eaglercraft.v1_8.internal.IQueryGL;
import net.lax1dude.eaglercraft.v1_8.internal.ITextureGL;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformBufferFunctions;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
@ -39,12 +39,15 @@ import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
*/
public class EaglercraftGPU {
static final GLObjectMap<ITextureGL> mapTexturesGL = new GLObjectMap(32767);
static final GLObjectMap<IQueryGL> mapQueriesGL = new GLObjectMap(32767);
static final GLObjectMap<DisplayList> mapDisplayListsGL = new GLObjectMap(32767);
static final GLObjectMap<ITextureGL> mapTexturesGL = new GLObjectMap<>(8192);
static final GLObjectMap<IQueryGL> mapQueriesGL = new GLObjectMap<>(8192);
static final GLObjectMap<DisplayList> mapDisplayListsGL = new GLObjectMap<>(8192);
static final Logger logger = LogManager.getLogger("EaglercraftGPU");
static boolean emulatedVAOs = false;
static SoftGLBufferState emulatedVAOState = new SoftGLBufferState();
public static final String gluErrorString(int i) {
switch(i) {
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
@ -87,16 +90,16 @@ public class EaglercraftGPU {
EaglercraftGPU.bindGLBufferArray(dp.vertexArray);
int c = 0;
if((dp.attribs & ATTRIB_TEXTURE) == ATTRIB_TEXTURE) {
_wglDisableVertexAttribArray(++c);
EaglercraftGPU.disableVertexAttribArray(++c);
}
if((dp.attribs & ATTRIB_COLOR) == ATTRIB_COLOR) {
_wglDisableVertexAttribArray(++c);
EaglercraftGPU.disableVertexAttribArray(++c);
}
if((dp.attribs & ATTRIB_NORMAL) == ATTRIB_NORMAL) {
_wglDisableVertexAttribArray(++c);
EaglercraftGPU.disableVertexAttribArray(++c);
}
if((dp.attribs & ATTRIB_LIGHTMAP) == ATTRIB_LIGHTMAP) {
_wglDisableVertexAttribArray(++c);
EaglercraftGPU.disableVertexAttribArray(++c);
}
}
dp.attribs = -1;
@ -109,7 +112,7 @@ public class EaglercraftGPU {
if(displayListBuffer.capacity() < wantSize) {
int newSize = (wantSize & 0xFFFE0000) + 0x40000;
ByteBuffer newBuffer = EagRuntime.allocateByteBuffer(newSize);
PlatformBufferFunctions.put(newBuffer, (ByteBuffer)displayListBuffer.flip());
newBuffer.put((ByteBuffer)displayListBuffer.flip());
EagRuntime.freeByteBuffer(displayListBuffer);
displayListBuffer = newBuffer;
}
@ -123,7 +126,7 @@ public class EaglercraftGPU {
if(dp.attribs == -1) {
if(dp.vertexArray != null) {
_wglDeleteVertexArrays(dp.vertexArray);
EaglercraftGPU.destroyGLBufferArray(dp.vertexArray);
dp.vertexArray = null;
}
if(dp.vertexBuffer != null) {
@ -135,7 +138,7 @@ public class EaglercraftGPU {
}
if(dp.vertexArray == null) {
dp.vertexArray = _wglGenVertexArrays();
dp.vertexArray = createGLBufferArray();
dp.bindQuad16 = false;
dp.bindQuad32 = false;
}
@ -143,7 +146,7 @@ public class EaglercraftGPU {
dp.vertexBuffer = _wglGenBuffers();
}
bindGLArrayBuffer(dp.vertexBuffer);
bindVAOGLArrayBufferNow(dp.vertexBuffer);
displayListBuffer.flip();
_wglBufferData(GL_ARRAY_BUFFER, displayListBuffer, GL_STATIC_DRAW);
displayListBuffer.clear();
@ -194,7 +197,7 @@ public class EaglercraftGPU {
}
dp.attribs = -1;
if(dp.vertexArray != null) {
_wglDeleteVertexArrays(dp.vertexArray);
EaglercraftGPU.destroyGLBufferArray(dp.vertexArray);
dp.vertexArray = null;
}
if(dp.vertexBuffer != null) {
@ -210,7 +213,7 @@ public class EaglercraftGPU {
++GlStateManager.stateNormalSerial;
}
private static final Map<Integer,String> stringCache = new HashMap();
private static final Map<Integer,String> stringCache = new HashMap<>();
public static final String glGetString(int param) {
String str = stringCache.get(param);
@ -238,9 +241,24 @@ public class EaglercraftGPU {
return _wglGetInteger(param);
}
public static final void glTexImage2D(int target, int level, int internalFormat, int w, int h, int unused,
int format, int type, ByteBuffer pixels) {
if(glesVers >= 300) {
_wglTexImage2D(target, level, internalFormat, w, h, unused, format, type, pixels);
}else {
int tv = TextureFormatHelper.trivializeInternalFormatToGLES20(internalFormat);
_wglTexImage2D(target, level, tv, w, h, unused, tv, type, pixels);
}
}
public static final void glTexImage2D(int target, int level, int internalFormat, int w, int h, int unused,
int format, int type, IntBuffer pixels) {
_wglTexImage2D(target, level, internalFormat, w, h, unused, format, type, pixels);
if(glesVers >= 300) {
_wglTexImage2D(target, level, internalFormat, w, h, unused, format, type, pixels);
}else {
int tv = TextureFormatHelper.trivializeInternalFormatToGLES20(internalFormat);
_wglTexImage2D(target, level, tv, w, h, unused, tv, type, pixels);
}
}
public static final void glTexSubImage2D(int target, int level, int x, int y, int w, int h, int format,
@ -249,9 +267,32 @@ public class EaglercraftGPU {
}
public static final void glTexStorage2D(int target, int levels, int internalFormat, int w, int h) {
_wglTexStorage2D(target, levels, internalFormat, w, h);
if(texStorageCapable && (glesVers >= 300 || levels == 1 || (MathHelper.calculateLogBaseTwo(Math.max(w, h)) + 1) == levels)) {
_wglTexStorage2D(target, levels, internalFormat, w, h);
}else {
int tv = TextureFormatHelper.trivializeInternalFormatToGLES20(internalFormat);
int type = TextureFormatHelper.getTypeFromInternal(internalFormat);
for(int i = 0; i < levels; ++i) {
_wglTexImage2D(target, i, tv, Math.max(w >> i, 1), Math.max(h >> i, 1), 0, tv, type, (ByteBuffer)null);
}
}
}
public static final void glReadPixels(int x, int y, int width, int height, int format, int type, ByteBuffer buffer) {
switch(type) {
case GL_FLOAT:
_wglReadPixels(x, y, width, height, format, GL_FLOAT, buffer.asFloatBuffer());
break;
case 0x140B: // GL_HALF_FLOAT
_wglReadPixels_u16(x, y, width, height, format, glesVers == 200 ? 0x8D61 : 0x140B, buffer);
break;
case GL_UNSIGNED_BYTE:
default:
_wglReadPixels(x, y, width, height, format, type, buffer);
break;
}
}
public static final void glLineWidth(float f) {
_wglLineWidth(f);
}
@ -284,7 +325,7 @@ public class EaglercraftGPU {
DisplayList d = mapDisplayListsGL.free(id);
if(d != null) {
if(d.vertexArray != null) {
_wglDeleteVertexArrays(d.vertexArray);
EaglercraftGPU.destroyGLBufferArray(d.vertexArray);
}
if(d.vertexBuffer != null) {
_wglDeleteBuffers(d.vertexBuffer);
@ -302,18 +343,197 @@ public class EaglercraftGPU {
GlStateManager.stateBlendEquation = equation;
}
}
private static IBufferArrayGL currentBufferArray = null;
public static final void bindGLBufferArray(IBufferArrayGL buffer) {
if(currentBufferArray != buffer) {
_wglBindVertexArray(buffer);
currentBufferArray = buffer;
public static final boolean areVAOsEmulated() {
return emulatedVAOs;
}
public static final IBufferArrayGL createGLBufferArray() {
if(emulatedVAOs) {
return new SoftGLBufferArray();
}else {
return _wglGenVertexArrays();
}
}
public static final void destroyGLBufferArray(IBufferArrayGL buffer) {
if(!emulatedVAOs) {
_wglDeleteVertexArrays(buffer);
}
}
public static final void enableVertexAttribArray(int index) {
if(emulatedVAOs) {
if(currentBufferArray == null) {
logger.warn("Skipping enable attrib with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLBufferArray)currentBufferArray).enableAttrib(index, true);
}else {
_wglEnableVertexAttribArray(index);
}
}
public static final void disableVertexAttribArray(int index) {
if(emulatedVAOs) {
if(currentBufferArray == null) {
logger.warn("Skipping disable attrib with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLBufferArray)currentBufferArray).enableAttrib(index, false);
}else {
_wglDisableVertexAttribArray(index);
}
}
public static final void vertexAttribPointer(int index, int size, int format, boolean normalized, int stride, int offset) {
if(emulatedVAOs) {
if(currentBufferArray == null) {
logger.warn("Skipping vertexAttribPointer with emulated VAO because no known VAO is bound!");
return;
}
if(currentVAOArrayBuffer == null) {
logger.warn("Skipping vertexAttribPointer with emulated VAO because no VAO array buffer is bound!");
return;
}
((SoftGLBufferArray)currentBufferArray).setAttrib(currentVAOArrayBuffer, index, size, format, normalized, stride, offset);
}else {
_wglVertexAttribPointer(index, size, format, normalized, stride, offset);
}
}
public static final void vertexAttribDivisor(int index, int divisor) {
if(emulatedVAOs) {
if(currentBufferArray == null) {
logger.warn("Skipping vertexAttribPointer with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLBufferArray)currentBufferArray).setAttribDivisor(index, divisor);
}else {
_wglVertexAttribDivisor(index, divisor);
}
}
public static final void doDrawArrays(int mode, int first, int count) {
if(emulatedVAOs) {
if(currentBufferArray == null) {
logger.warn("Skipping draw call with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLBufferArray)currentBufferArray).transitionToState(emulatedVAOState, false);
}
_wglDrawArrays(mode, first, count);
}
public static final void doDrawElements(int mode, int count, int type, int offset) {
if(emulatedVAOs) {
if(currentBufferArray == null) {
logger.warn("Skipping draw call with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLBufferArray)currentBufferArray).transitionToState(emulatedVAOState, true);
}
_wglDrawElements(mode, count, type, offset);
}
public static final void doDrawArraysInstanced(int mode, int first, int count, int instances) {
if(emulatedVAOs) {
if(currentBufferArray == null) {
logger.warn("Skipping instanced draw call with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLBufferArray)currentBufferArray).transitionToState(emulatedVAOState, false);
}
_wglDrawArraysInstanced(mode, first, count, instances);
}
public static final void doDrawElementsInstanced(int mode, int count, int type, int offset, int instances) {
if(emulatedVAOs) {
if(currentBufferArray == null) {
logger.warn("Skipping instanced draw call with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLBufferArray)currentBufferArray).transitionToState(emulatedVAOState, true);
}
_wglDrawElementsInstanced(mode, count, type, offset, instances);
}
static IBufferArrayGL currentBufferArray = null;
private static IBufferGL currentArrayBuffer = null;
public static final void bindGLBufferArray(IBufferArrayGL buffer) {
if(emulatedVAOs) {
currentBufferArray = buffer;
}else {
if(currentBufferArray != buffer) {
_wglBindVertexArray(buffer);
currentBufferArray = buffer;
}
}
}
static IBufferGL currentArrayBuffer = null;
// only used when VAOs are emulated
static IBufferGL currentVAOArrayBuffer = null;
public static final void bindVAOGLArrayBuffer(IBufferGL buffer) {
if(emulatedVAOs) {
currentVAOArrayBuffer = buffer;
}else {
if(currentArrayBuffer != buffer) {
_wglBindBuffer(GL_ARRAY_BUFFER, buffer);
currentArrayBuffer = buffer;
}
}
}
public static final void bindVAOGLArrayBufferNow(IBufferGL buffer) {
if(emulatedVAOs) {
currentVAOArrayBuffer = buffer;
}
if(currentArrayBuffer != buffer) {
_wglBindBuffer(GL_ARRAY_BUFFER, buffer);
currentArrayBuffer = buffer;
}
}
public static final void bindVAOGLElementArrayBuffer(IBufferGL buffer) {
if(emulatedVAOs) {
if(currentBufferArray == null) {
logger.warn("Skipping set element array buffer with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLBufferArray)currentBufferArray).setIndexBuffer(buffer);
}else {
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
}
}
static final void bindVAOGLElementArrayBufferNow(IBufferGL buffer) {
if(emulatedVAOs) {
if(currentBufferArray == null) {
logger.warn("Skipping set element array buffer with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLBufferArray)currentBufferArray).setIndexBuffer(buffer);
if(currentEmulatedVAOIndexBuffer != buffer) {
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
currentEmulatedVAOIndexBuffer = buffer;
}
}else {
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
}
}
static IBufferGL currentEmulatedVAOIndexBuffer = null;
static final void bindEmulatedVAOIndexBuffer(IBufferGL buffer) {
if(currentEmulatedVAOIndexBuffer != buffer) {
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
currentEmulatedVAOIndexBuffer = buffer;
}
}
public static final void bindGLArrayBuffer(IBufferGL buffer) {
if(currentArrayBuffer != buffer) {
_wglBindBuffer(GL_ARRAY_BUFFER, buffer);
@ -321,7 +541,7 @@ public class EaglercraftGPU {
}
}
private static IBufferGL currentUniformBuffer = null;
static IBufferGL currentUniformBuffer = null;
public static final void bindGLUniformBuffer(IBufferGL buffer) {
if(currentUniformBuffer != buffer) {
@ -330,7 +550,7 @@ public class EaglercraftGPU {
}
}
private static IProgramGL currentShaderProgram = null;
static IProgramGL currentShaderProgram = null;
public static final void bindGLShaderProgram(IProgramGL prog) {
if(currentShaderProgram != prog) {
@ -352,6 +572,38 @@ public class EaglercraftGPU {
currentUniformBlockBindingSize[index] = size;
}
}
public static final int CLEAR_BINDING_TEXTURE = 1;
public static final int CLEAR_BINDING_TEXTURE0 = 2;
public static final int CLEAR_BINDING_ACTIVE_TEXTURE = 4;
public static final int CLEAR_BINDING_BUFFER_ARRAY = 8;
public static final int CLEAR_BINDING_ARRAY_BUFFER = 16;
public static final int CLEAR_BINDING_SHADER_PROGRAM = 32;
public static final void clearCurrentBinding(int mask) {
if((mask & CLEAR_BINDING_TEXTURE) != 0) {
int[] i = GlStateManager.boundTexture;
for(int j = 0; j < i.length; ++j) {
i[j] = -1;
}
}
if((mask & CLEAR_BINDING_TEXTURE0) != 0) {
GlStateManager.boundTexture[0] = -1;
}
if((mask & CLEAR_BINDING_ACTIVE_TEXTURE) != 0) {
GlStateManager.activeTexture = 0;
_wglActiveTexture(GL_TEXTURE0);
}
if((mask & CLEAR_BINDING_BUFFER_ARRAY) != 0) {
currentBufferArray = null;
}
if((mask & CLEAR_BINDING_ARRAY_BUFFER) != 0) {
currentArrayBuffer = currentVAOArrayBuffer = null;
}
if((mask & CLEAR_BINDING_SHADER_PROGRAM) != 0) {
currentShaderProgram = null;
}
}
public static final int ATTRIB_TEXTURE = 1;
public static final int ATTRIB_COLOR = 2;
@ -414,7 +666,7 @@ public class EaglercraftGPU {
if(newSize > 0xFFFF) {
newSize = 0xFFFF;
}
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
resizeQuad16EmulationBuffer(newSize >> 2);
}else {
int cnt = quad16EmulationBufferSize;
@ -423,10 +675,10 @@ public class EaglercraftGPU {
if(newSize > 0xFFFF) {
newSize = 0xFFFF;
}
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
resizeQuad16EmulationBuffer(newSize >> 2);
}else if(bind) {
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
EaglercraftGPU.bindVAOGLElementArrayBuffer(buf);
}
}
}
@ -436,16 +688,16 @@ public class EaglercraftGPU {
if(buf == null) {
quad32EmulationBuffer = buf = _wglGenBuffers();
int newSize = quad32EmulationBufferSize = (vertexCount & 0xFFFFC000) + 0x8000;
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
resizeQuad32EmulationBuffer(newSize >> 2);
}else {
int cnt = quad32EmulationBufferSize;
if(cnt < vertexCount) {
int newSize = quad32EmulationBufferSize = (vertexCount & 0xFFFFC000) + 0x8000;
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
resizeQuad32EmulationBuffer(newSize >> 2);
}else if(bind) {
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf);
EaglercraftGPU.bindVAOGLElementArrayBuffer(buf);
}
}
}
@ -508,9 +760,19 @@ public class EaglercraftGPU {
p.drawElements(GL_TRIANGLES, mesh.indexCount, GL_UNSIGNED_SHORT, 0);
}
static int glesVers = -1;
static boolean hasFramebufferHDR16FSupport = false;
static boolean hasFramebufferHDR32FSupport = false;
static boolean hasLinearHDR16FSupport = false;
static boolean hasLinearHDR32FSupport = false;
static boolean fboRenderMipmapCapable = false;
static boolean vertexArrayCapable = false;
static boolean instancingCapable = false;
static boolean texStorageCapable = false;
static boolean textureLODCapable = false;
static boolean shader5Capable = false;
static boolean npotCapable = false;
static int uniformBufferOffsetAlignment = -1;
public static final void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, boolean allow32bitFallback) {
createFramebufferHDR16FTexture(target, level, w, h, format, allow32bitFallback, null);
@ -525,19 +787,24 @@ public class EaglercraftGPU {
int internalFormat;
switch(format) {
case GL_RED:
internalFormat = 0x822D; // GL_R16F
if(glesVers == 200) {
format = GL_LUMINANCE;
internalFormat = GL_LUMINANCE;
}else {
internalFormat = glesVers == 200 ? GL_LUMINANCE : 0x822D; // GL_R16F
}
break;
case 0x8227: // GL_RG
internalFormat = 0x822F; // GL_RG16F
internalFormat = glesVers == 200 ? 0x8227 : 0x822F; // GL_RG16F
case GL_RGB:
throw new UnsupportedOperationException("GL_RGB16F isn't supported specifically in WebGL 2.0 for some goddamn reason");
case GL_RGBA:
internalFormat = 0x881A; // GL_RGBA16F
internalFormat = glesVers == 200 ? GL_RGBA : 0x881A; // GL_RGBA16F
break;
default:
throw new UnsupportedOperationException("Unknown format: " + format);
}
_wglTexImage2Du16(target, level, internalFormat, w, h, 0, format, 0x140B, pixelData);
_wglTexImage2Du16(target, level, internalFormat, w, h, 0, format, glesVers == 200 ? 0x8D61 : 0x140B, pixelData);
}else {
if(allow32bitFallback) {
if(hasFramebufferHDR32FSupport) {
@ -567,7 +834,7 @@ public class EaglercraftGPU {
internalFormat = 0x822E; // GL_R32F
break;
case 0x8227: // GL_RG
internalFormat = 0x822F; // GL_RG32F
internalFormat = 0x8230; // GL_RG32F
case GL_RGB:
throw new UnsupportedOperationException("GL_RGB32F isn't supported specifically in WebGL 2.0 for some goddamn reason");
case GL_RGBA:
@ -594,19 +861,38 @@ public class EaglercraftGPU {
EaglercraftGPU.glGetString(7936);
EaglercraftGPU.glGetString(7937);
EaglercraftGPU.glGetString(7938);
glesVers = PlatformOpenGL.checkOpenGLESVersion();
vertexArrayCapable = PlatformOpenGL.checkVAOCapable();
emulatedVAOs = !vertexArrayCapable;
fboRenderMipmapCapable = PlatformOpenGL.checkFBORenderMipmapCapable();
instancingCapable = PlatformOpenGL.checkInstancingCapable();
texStorageCapable = PlatformOpenGL.checkTexStorageCapable();
textureLODCapable = PlatformOpenGL.checkTextureLODCapable();
shader5Capable = PlatformOpenGL.checkOESGPUShader5Capable() || PlatformOpenGL.checkEXTGPUShader5Capable();
npotCapable = PlatformOpenGL.checkNPOTCapable();
uniformBufferOffsetAlignment = glesVers >= 300 ? _wglGetInteger(0x8A34) : -1;
if(!npotCapable) {
logger.warn("NPOT texture support detected as false, texture wrapping must be set to GL_CLAMP_TO_EDGE if the texture's width or height is not a power of 2");
}
hasFramebufferHDR16FSupport = PlatformOpenGL.checkHDRFramebufferSupport(16);
if(hasFramebufferHDR16FSupport) {
logger.info("16-bit HDR render target support: true");
}else {
logger.error("16-bit HDR render target support: false");
}
hasLinearHDR16FSupport = PlatformOpenGL.checkLinearHDRFilteringSupport(16);
if(hasLinearHDR16FSupport) {
logger.info("16-bit HDR linear filter support: true");
}else {
logger.error("16-bit HDR linear filter support: false");
}
hasFramebufferHDR32FSupport = PlatformOpenGL.checkHDRFramebufferSupport(32);
if(hasFramebufferHDR32FSupport) {
logger.info("32-bit HDR render target support: true");
}else {
logger.error("32-bit HDR render target support: false");
}
hasLinearHDR32FSupport = PlatformOpenGL.checkLinearHDR32FSupport();
hasLinearHDR32FSupport = PlatformOpenGL.checkLinearHDRFilteringSupport(32);
if(hasLinearHDR32FSupport) {
logger.info("32-bit HDR linear filter support: true");
}else {
@ -615,16 +901,86 @@ public class EaglercraftGPU {
if(!checkHasHDRFramebufferSupportWithFilter()) {
logger.error("No HDR render target support was detected! Shaders will be disabled.");
}
if(emulatedVAOs) {
logger.info("Note: Could not unlock VAOs via OpenGL extensions, emulating them instead");
}
if(!instancingCapable) {
logger.info("Note: Could not unlock instancing via OpenGL extensions, using slow vanilla font and particle rendering");
}
emulatedVAOState = emulatedVAOs ? new SoftGLBufferState() : null;
PlatformOpenGL.enterVAOEmulationHook();
GLSLHeader.init();
DrawUtils.init();
SpriteLevelMixer.initialize();
InstancedFontRenderer.initialize();
InstancedParticleRenderer.initialize();
if(instancingCapable) {
InstancedFontRenderer.initialize();
InstancedParticleRenderer.initialize();
}
EffectPipelineFXAA.initialize();
TextureCopyUtil.initialize();
DrawUtils.vshLocal.free();
DrawUtils.vshLocal = null;
}
public static final void destroyCache() {
stringCache.clear();
mapTexturesGL.clear();
mapQueriesGL.clear();
mapDisplayListsGL.clear();
emulatedVAOs = false;
emulatedVAOState = null;
glesVers = -1;
fboRenderMipmapCapable = false;
vertexArrayCapable = false;
instancingCapable = false;
hasFramebufferHDR16FSupport = false;
hasFramebufferHDR32FSupport = false;
hasLinearHDR32FSupport = false;
GLSLHeader.destroy();
DrawUtils.destroy();
SpriteLevelMixer.destroy();
InstancedFontRenderer.destroy();
InstancedParticleRenderer.destroy();
EffectPipelineFXAA.destroy();
TextureCopyUtil.destroy();
}
public static final int checkOpenGLESVersion() {
return glesVers;
}
public static final boolean checkFBORenderMipmapCapable() {
return fboRenderMipmapCapable;
}
public static final boolean checkVAOCapable() {
return vertexArrayCapable;
}
public static final boolean checkInstancingCapable() {
return instancingCapable;
}
public static final boolean checkTexStorageCapable() {
return texStorageCapable;
}
public static final boolean checkTextureLODCapable() {
return textureLODCapable;
}
public static final boolean checkShader5Capable() {
return shader5Capable;
}
public static final boolean checkNPOTCapable() {
return npotCapable;
}
public static final int getUniformBufferOffsetAlignment() {
return uniformBufferOffsetAlignment;
}
public static final boolean checkHDRFramebufferSupport(int bits) {
switch(bits) {
case 16:
@ -636,15 +992,28 @@ public class EaglercraftGPU {
}
}
public static final boolean checkLinearHDRFilteringSupport(int bits) {
switch(bits) {
case 16:
return hasLinearHDR16FSupport;
case 32:
return hasLinearHDR32FSupport;
default:
return false;
}
}
public static final boolean checkHasHDRFramebufferSupport() {
return hasFramebufferHDR16FSupport || hasFramebufferHDR32FSupport;
}
public static final boolean checkHasHDRFramebufferSupportWithFilter() {
return hasFramebufferHDR16FSupport || (hasFramebufferHDR32FSupport && hasLinearHDR32FSupport);
return (hasFramebufferHDR16FSupport && hasLinearHDR16FSupport) || (hasFramebufferHDR32FSupport && hasLinearHDR32FSupport);
}
//legacy
public static final boolean checkLinearHDR32FSupport() {
return hasLinearHDR32FSupport;
}
}

View File

@ -8,7 +8,6 @@ import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
@ -35,11 +34,13 @@ public class EffectPipelineFXAA {
private static final Logger logger = LogManager.getLogger("EffectPipelineFXAA");
public static final String fragmentShaderPath = "/assets/eagler/glsl/post_fxaa.fsh";
public static final String fragmentShaderPrecision = "precision lowp int;\nprecision mediump float;\nprecision mediump sampler2D;\n";
private static final int _GL_FRAMEBUFFER = 0x8D40;
private static final int _GL_RENDERBUFFER = 0x8D41;
private static final int _GL_COLOR_ATTACHMENT0 = 0x8CE0;
private static final int _GL_DEPTH_ATTACHMENT = 0x8D00;
private static final int _GL_DEPTH_COMPONENT16 = 0x81A5;
private static final int _GL_DEPTH_COMPONENT32F = 0x8CAC;
private static IProgramGL shaderProgram = null;
@ -53,14 +54,11 @@ public class EffectPipelineFXAA {
private static int currentHeight = -1;
static void initialize() {
String fragmentSource = EagRuntime.getResourceString(fragmentShaderPath);
if(fragmentSource == null) {
throw new RuntimeException("EffectPipelineFXAA shader \"" + fragmentShaderPath + "\" is missing!");
}
String fragmentSource = EagRuntime.getRequiredResourceString(fragmentShaderPath);
IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER);
_wglShaderSource(frag, FixedFunctionConstants.VERSION + "\n" + fragmentSource);
_wglShaderSource(frag, GLSLHeader.getFragmentHeaderCompat(fragmentSource, fragmentShaderPrecision));
_wglCompileShader(frag);
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
@ -80,6 +78,10 @@ public class EffectPipelineFXAA {
_wglAttachShader(shaderProgram, DrawUtils.vshLocal);
_wglAttachShader(shaderProgram, frag);
if(EaglercraftGPU.checkOpenGLESVersion() == 200) {
VSHInputLayoutParser.applyLayout(shaderProgram, DrawUtils.vshLocalLayout);
}
_wglLinkProgram(shaderProgram);
_wglDetachShader(shaderProgram, DrawUtils.vshLocal);
@ -130,10 +132,10 @@ public class EffectPipelineFXAA {
currentHeight = height;
GlStateManager.bindTexture(framebufferColor);
_wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
EaglercraftGPU.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
_wglBindRenderbuffer(_GL_RENDERBUFFER, framebufferDepth);
_wglRenderbufferStorage(_GL_RENDERBUFFER, _GL_DEPTH_COMPONENT32F, width, height);
_wglRenderbufferStorage(_GL_RENDERBUFFER, EaglercraftGPU.checkOpenGLESVersion() == 200 ? _GL_DEPTH_COMPONENT16 : _GL_DEPTH_COMPONENT32F, width, height);
}
_wglBindFramebuffer(_GL_FRAMEBUFFER, framebuffer);
@ -155,4 +157,24 @@ public class EffectPipelineFXAA {
DrawUtils.drawStandardQuad2D();
}
public static void destroy() {
if(shaderProgram != null) {
_wglDeleteProgram(shaderProgram);
shaderProgram = null;
}
u_screenSize2f = null;
if(framebuffer != null) {
_wglDeleteFramebuffer(framebuffer);
framebuffer = null;
}
if(framebufferColor != -1) {
GlStateManager.deleteTexture(framebufferColor);
framebufferColor = -2;
}
if(framebufferDepth != null) {
_wglDeleteRenderbuffer(framebufferDepth);
framebufferDepth = null;
}
}
}

View File

@ -98,33 +98,33 @@ public class FixedFunctionPipeline {
}
EaglercraftGPU.bindGLBufferArray(list.vertexArray);
EaglercraftGPU.bindGLArrayBuffer(list.vertexBuffer);
EaglercraftGPU.bindVAOGLArrayBuffer(list.vertexBuffer);
_wglEnableVertexAttribArray(0);
_wglVertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
VertexFormat.COMPONENT_POSITION_FORMAT, false, self.attribStride, 0);
if(self.attribTextureIndex != -1) {
_wglEnableVertexAttribArray(self.attribTextureIndex);
_wglVertexAttribPointer(self.attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
EaglercraftGPU.enableVertexAttribArray(self.attribTextureIndex);
EaglercraftGPU.vertexAttribPointer(self.attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
VertexFormat.COMPONENT_TEX_FORMAT, false, self.attribStride, self.attribTextureOffset);
}
if(self.attribColorIndex != -1) {
_wglEnableVertexAttribArray(self.attribColorIndex);
_wglVertexAttribPointer(self.attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
EaglercraftGPU.enableVertexAttribArray(self.attribColorIndex);
EaglercraftGPU.vertexAttribPointer(self.attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
VertexFormat.COMPONENT_COLOR_FORMAT, true, self.attribStride, self.attribColorOffset);
}
if(self.attribNormalIndex != -1) {
_wglEnableVertexAttribArray(self.attribNormalIndex);
_wglVertexAttribPointer(self.attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
EaglercraftGPU.enableVertexAttribArray(self.attribNormalIndex);
EaglercraftGPU.vertexAttribPointer(self.attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
VertexFormat.COMPONENT_NORMAL_FORMAT, true, self.attribStride, self.attribNormalOffset);
}
if(self.attribLightmapIndex != -1) {
_wglEnableVertexAttribArray(self.attribLightmapIndex);
_wglVertexAttribPointer(self.attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
EaglercraftGPU.enableVertexAttribArray(self.attribLightmapIndex);
EaglercraftGPU.vertexAttribPointer(self.attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
VertexFormat.COMPONENT_LIGHTMAP_FORMAT, false, self.attribStride, self.attribLightmapOffset);
}
@ -145,7 +145,7 @@ public class FixedFunctionPipeline {
void drawArrays(int mode, int offset, int count) {
EaglercraftGPU.bindGLShaderProgram(shaderProgram);
PlatformOpenGL._wglDrawArrays(mode, offset, count);
EaglercraftGPU.doDrawArrays(mode, offset, count);
}
void drawDirectArrays(int mode, int offset, int count) {
@ -160,7 +160,7 @@ public class FixedFunctionPipeline {
}else {
EaglercraftGPU.attachQuad32EmulationBuffer(count, false);
}
PlatformOpenGL._wglDrawElements(GL_TRIANGLES, count + (count >> 1),
EaglercraftGPU.doDrawElements(GL_TRIANGLES, count + (count >> 1),
GL_UNSIGNED_INT, 0);
}else {
if(!sb.bindQuad16) {
@ -170,17 +170,17 @@ public class FixedFunctionPipeline {
}else {
EaglercraftGPU.attachQuad16EmulationBuffer(count, false);
}
PlatformOpenGL._wglDrawElements(GL_TRIANGLES, count + (count >> 1),
EaglercraftGPU.doDrawElements(GL_TRIANGLES, count + (count >> 1),
GL_UNSIGNED_SHORT, 0);
}
}else {
PlatformOpenGL._wglDrawArrays(mode, offset, count);
EaglercraftGPU.doDrawArrays(mode, offset, count);
}
}
void drawElements(int mode, int count, int type, int offset) {
EaglercraftGPU.bindGLShaderProgram(shaderProgram);
PlatformOpenGL._wglDrawElements(mode, count, type, offset);
EaglercraftGPU.doDrawElements(mode, count, type, offset);
}
private static IExtPipelineCompiler extensionProvider;
@ -192,7 +192,7 @@ public class FixedFunctionPipeline {
private static final FixedFunctionPipeline[] pipelineStateCache = new FixedFunctionPipeline[fixedFunctionStatesBits + 1];
private static final FixedFunctionPipeline[][] pipelineExtStateCache = new FixedFunctionPipeline[fixedFunctionStatesBits + 1][];
private static final List<FixedFunctionPipeline> pipelineListTracker = new ArrayList(1024);
private static final List<FixedFunctionPipeline> pipelineListTracker = new ArrayList<>(1024);
private static String shaderSourceCacheVSH = null;
private static String shaderSourceCacheFSH = null;
@ -232,22 +232,16 @@ public class FixedFunctionPipeline {
fshSource = extSource[1];
}else {
if(shaderSourceCacheVSH == null) {
shaderSourceCacheVSH = EagRuntime.getResourceString(FILENAME_VSH);
if(shaderSourceCacheVSH == null) {
throw new RuntimeException("Could not load: " + FILENAME_VSH);
}
shaderSourceCacheVSH = EagRuntime.getRequiredResourceString(FILENAME_VSH);
}
vshSource = shaderSourceCacheVSH;
if(shaderSourceCacheFSH == null) {
shaderSourceCacheFSH = EagRuntime.getResourceString(FILENAME_FSH);
if(shaderSourceCacheFSH == null) {
throw new RuntimeException("Could not load: " + FILENAME_FSH);
}
shaderSourceCacheFSH = EagRuntime.getRequiredResourceString(FILENAME_FSH);
}
fshSource = shaderSourceCacheFSH;
}
StringBuilder macros = new StringBuilder(VERSION + "\n");
StringBuilder macros = new StringBuilder();
if((coreBits & STATE_HAS_ATTRIB_TEXTURE) != 0) {
macros.append("#define " + MACRO_ATTRIB_TEXTURE + "\n");
}
@ -291,7 +285,8 @@ public class FixedFunctionPipeline {
IShaderGL vsh = _wglCreateShader(GL_VERTEX_SHADER);
_wglShaderSource(vsh, macros.toString() + vshSource);
String macrosStr = macros.toString();
_wglShaderSource(vsh, GLSLHeader.getVertexHeaderCompat(vshSource, macrosStr));
_wglCompileShader(vsh);
if(_wglGetShaderi(vsh, GL_COMPILE_STATUS) != GL_TRUE) {
@ -309,7 +304,7 @@ public class FixedFunctionPipeline {
IShaderGL fsh = _wglCreateShader(GL_FRAGMENT_SHADER);
_wglShaderSource(fsh, macros.toString() + fshSource);
_wglShaderSource(fsh, GLSLHeader.getFragmentHeaderCompat(fshSource, macrosStr));
_wglCompileShader(fsh);
if(_wglGetShaderi(fsh, GL_COMPILE_STATUS) != GL_TRUE) {
@ -581,45 +576,45 @@ public class FixedFunctionPipeline {
streamBuffer = new StreamBuffer(FixedFunctionShader.initialSize, FixedFunctionShader.initialCount,
FixedFunctionShader.maxCount, (vertexArray, vertexBuffer) -> {
EaglercraftGPU.bindGLBufferArray(vertexArray);
EaglercraftGPU.bindGLArrayBuffer(vertexBuffer);
EaglercraftGPU.bindVAOGLArrayBuffer(vertexBuffer);
_wglEnableVertexAttribArray(0);
_wglVertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
VertexFormat.COMPONENT_POSITION_FORMAT, false, attribStride, 0);
if(attribTextureIndex != -1) {
_wglEnableVertexAttribArray(attribTextureIndex);
_wglVertexAttribPointer(attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
EaglercraftGPU.enableVertexAttribArray(attribTextureIndex);
EaglercraftGPU.vertexAttribPointer(attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
VertexFormat.COMPONENT_TEX_FORMAT, false, attribStride, attribTextureOffset);
}
if(attribColorIndex != -1) {
_wglEnableVertexAttribArray(attribColorIndex);
_wglVertexAttribPointer(attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
EaglercraftGPU.enableVertexAttribArray(attribColorIndex);
EaglercraftGPU.vertexAttribPointer(attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
VertexFormat.COMPONENT_COLOR_FORMAT, true, attribStride, attribColorOffset);
}
if(attribNormalIndex != -1) {
_wglEnableVertexAttribArray(attribNormalIndex);
_wglVertexAttribPointer(attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
EaglercraftGPU.enableVertexAttribArray(attribNormalIndex);
EaglercraftGPU.vertexAttribPointer(attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
VertexFormat.COMPONENT_NORMAL_FORMAT, true, attribStride, attribNormalOffset);
}
if(attribLightmapIndex != -1) {
_wglEnableVertexAttribArray(attribLightmapIndex);
_wglVertexAttribPointer(attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
EaglercraftGPU.enableVertexAttribArray(attribLightmapIndex);
EaglercraftGPU.vertexAttribPointer(attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
VertexFormat.COMPONENT_LIGHTMAP_FORMAT, false, attribStride, attribLightmapOffset);
}
});
stateEnableTexture2D = (bits & STATE_ENABLE_TEXTURE2D) == STATE_ENABLE_TEXTURE2D;
stateEnableLightmap = (bits & STATE_ENABLE_LIGHTMAP) == STATE_ENABLE_LIGHTMAP;
stateEnableAlphaTest = (bits & STATE_ENABLE_ALPHA_TEST) == STATE_ENABLE_ALPHA_TEST;
stateEnableMCLighting = (bits & STATE_ENABLE_MC_LIGHTING) == STATE_ENABLE_MC_LIGHTING;
stateEnableEndPortal = (bits & STATE_ENABLE_END_PORTAL) == STATE_ENABLE_END_PORTAL;
stateEnableAnisotropicFix = (bits & STATE_ENABLE_ANISOTROPIC_FIX) == STATE_ENABLE_ANISOTROPIC_FIX;
stateEnableFog = (bits & STATE_ENABLE_FOG) == STATE_ENABLE_FOG;
stateEnableBlendAdd = (bits & STATE_ENABLE_BLEND_ADD) == STATE_ENABLE_BLEND_ADD;
stateEnableTexture2D = (bits & STATE_ENABLE_TEXTURE2D) != 0;
stateEnableLightmap = (bits & STATE_ENABLE_LIGHTMAP) != 0;
stateEnableAlphaTest = (bits & STATE_ENABLE_ALPHA_TEST) != 0;
stateEnableMCLighting = (bits & STATE_ENABLE_MC_LIGHTING) != 0;
stateEnableEndPortal = (bits & STATE_ENABLE_END_PORTAL) != 0;
stateEnableAnisotropicFix = (bits & STATE_ENABLE_ANISOTROPIC_FIX) != 0;
stateEnableFog = (bits & STATE_ENABLE_FOG) != 0;
stateEnableBlendAdd = (bits & STATE_ENABLE_BLEND_ADD) != 0;
for(int i = 0; i < stateLightsVectors.length; ++i) {
stateLightsVectors[i] = new Vector4f(-999.0f, -999.0f, -999.0f, 0.0f);
@ -1068,7 +1063,6 @@ public class FixedFunctionPipeline {
}
static void optimize() {
FixedFunctionPipeline pp;
for(int i = 0, l = pipelineListTracker.size(); i < l; ++i) {
pipelineListTracker.get(i).streamBuffer.optimize();
}

View File

@ -44,7 +44,6 @@ public class FixedFunctionShader {
public class FixedFunctionConstants {
public static final String VERSION = "#version 300 es";
public static final String FILENAME_VSH = "/assets/eagler/glsl/core.vsh";
public static final String FILENAME_FSH = "/assets/eagler/glsl/core.fsh";

View File

@ -0,0 +1,99 @@
package net.lax1dude.eaglercraft.v1_8.opengl;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL;
/**
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public class GLSLHeader {
public static final String GLES2_COMPAT_FILE_NAME = "/assets/eagler/glsl/gles2_compat.glsl";
private static String header = null;
private static String gles2CompatFile = null;
static void init() {
gles2CompatFile = EagRuntime.getRequiredResourceString(GLES2_COMPAT_FILE_NAME);
int glesVersion = EaglercraftGPU.checkOpenGLESVersion();
StringBuilder headerBuilder;
if(glesVersion >= 310) {
headerBuilder = new StringBuilder("#version 310 es");
boolean oes5 = PlatformOpenGL.checkOESGPUShader5Capable();
boolean ext5 = !oes5 && PlatformOpenGL.checkEXTGPUShader5Capable();
if(oes5) {
headerBuilder.append("\n#extension GL_OES_gpu_shader5 : enable");
}else if(ext5) {
headerBuilder.append("\n#extension GL_EXT_gpu_shader5 : enable");
}
headerBuilder.append("\n#define EAGLER_IS_GLES_310");
headerBuilder.append("\n#define EAGLER_HAS_GLES_310");
headerBuilder.append("\n#define EAGLER_HAS_GLES_300");
headerBuilder.append("\n#define EAGLER_HAS_GLES_200");
if(oes5 || ext5) {
headerBuilder.append("\n#define EAGLER_HAS_GLES_310_SHADER_5");
}
}else if(glesVersion == 300) {
headerBuilder = new StringBuilder("#version 300 es");
headerBuilder.append("\n#define EAGLER_IS_GLES_300");
headerBuilder.append("\n#define EAGLER_HAS_GLES_300");
headerBuilder.append("\n#define EAGLER_HAS_GLES_200");
}else if(glesVersion == 200) {
boolean texLOD = PlatformOpenGL.checkTextureLODCapable();
headerBuilder = new StringBuilder("#version 100");
if(texLOD) {
headerBuilder.append("\n#extension GL_EXT_shader_texture_lod : enable");
}
headerBuilder.append("\n#define EAGLER_HAS_GLES_200");
headerBuilder.append("\n#define EAGLER_IS_GLES_200");
if(texLOD) {
headerBuilder.append("\n#define EAGLER_HAS_GLES_200_SHADER_TEXTURE_LOD");
}
}else {
throw new IllegalStateException("Unsupported OpenGL ES version: " + glesVersion);
}
header = headerBuilder.append('\n').toString();
}
static void destroy() {
header = null;
}
public static String getHeader() {
if(header == null) throw new IllegalStateException();
return header;
}
public static String getVertexHeader(String shaderSrc) {
if(header == null) throw new IllegalStateException();
return header + "#define EAGLER_IS_VERTEX_SHADER\n" + shaderSrc;
}
public static String getFragmentHeader(String shaderSrc) {
if(header == null) throw new IllegalStateException();
return header + "#define EAGLER_IS_FRAGMENT_SHADER\n" + shaderSrc;
}
public static String getVertexHeaderCompat(String shaderSrc, String precisions) {
if(header == null || gles2CompatFile == null) throw new IllegalStateException();
return header + "#define EAGLER_IS_VERTEX_SHADER\n" + (precisions == null ? "" : precisions + "\n") + gles2CompatFile + "\n" + shaderSrc;
}
public static String getFragmentHeaderCompat(String shaderSrc, String precisions) {
if(header == null || gles2CompatFile == null) throw new IllegalStateException();
return header + "#define EAGLER_IS_FRAGMENT_SHADER\n"+ (precisions == null ? "" : precisions + "\n") + gles2CompatFile + "\n" + shaderSrc;
}
}

View File

@ -5,10 +5,13 @@ import net.lax1dude.eaglercraft.v1_8.internal.IRenderbufferGL;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
/**
* Copyright (c) 2022-2023 lax1dude. All Rights Reserved.
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -40,10 +43,20 @@ public class GameOverlayFramebuffer {
private int framebufferColor = -1;
public void beginRender(int width, int height) {
private final boolean enableDepth;
public GameOverlayFramebuffer() {
this(true);
}
public GameOverlayFramebuffer(boolean enableDepth) {
this.enableDepth = enableDepth;
}
public boolean beginRender(int width, int height) {
if(framebuffer == null) {
framebuffer = _wglCreateFramebuffer();
depthBuffer = _wglCreateRenderbuffer();
depthBuffer = enableDepth ? _wglCreateRenderbuffer() : null;
framebufferColor = GlStateManager.generateTexture();
_wglBindFramebuffer(_GL_FRAMEBUFFER, framebuffer);
GlStateManager.bindTexture(framebufferColor);
@ -52,29 +65,35 @@ public class GameOverlayFramebuffer {
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
_wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(framebufferColor), 0);
_wglBindRenderbuffer(_GL_RENDERBUFFER, depthBuffer);
_wglFramebufferRenderbuffer(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, _GL_RENDERBUFFER, depthBuffer);
if(enableDepth) {
_wglBindRenderbuffer(_GL_RENDERBUFFER, depthBuffer);
_wglFramebufferRenderbuffer(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, _GL_RENDERBUFFER, depthBuffer);
}
}
if(currentWidth != width || currentHeight != height) {
boolean resized = currentWidth != width || currentHeight != height;
if(resized) {
currentWidth = width;
currentHeight = height;
GlStateManager.bindTexture(framebufferColor);
_wglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
_wglBindRenderbuffer(_GL_RENDERBUFFER, depthBuffer);
_wglRenderbufferStorage(_GL_RENDERBUFFER, _GL_DEPTH_COMPONENT16, width, height);
EaglercraftGPU.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer)null);
if(enableDepth) {
_wglBindRenderbuffer(_GL_RENDERBUFFER, depthBuffer);
_wglRenderbufferStorage(_GL_RENDERBUFFER, _GL_DEPTH_COMPONENT16, width, height);
}
}
_wglBindFramebuffer(_GL_FRAMEBUFFER, framebuffer);
return resized;
}
public void endRender() {
_wglBindFramebuffer(_GL_FRAMEBUFFER, null);
age = System.currentTimeMillis();
age = EagRuntime.steadyTimeMillis();
}
public long getAge() {
return age == -1l ? -1l : (System.currentTimeMillis() - age);
return age == -1l ? -1l : (EagRuntime.steadyTimeMillis() - age);
}
public int getTexture() {
@ -84,7 +103,9 @@ public class GameOverlayFramebuffer {
public void destroy() {
if(framebuffer != null) {
_wglDeleteFramebuffer(framebuffer);
_wglDeleteRenderbuffer(depthBuffer);
if(enableDepth) {
_wglDeleteRenderbuffer(depthBuffer);
}
GlStateManager.deleteTexture(framebufferColor);
framebuffer = null;
depthBuffer = null;

View File

@ -30,10 +30,12 @@ public class GlStateManager {
static final Logger logger = LogManager.getLogger("GlStateManager");
static boolean stateDepthTest = false;
static boolean stateDepthTestStash = false;
static int stateDepthFunc = -1;
static boolean stateDepthMask = true;
static boolean stateCull = false;
static boolean stateCullStash = false;
static int stateCullFace = GL_BACK;
static boolean statePolygonOffset = false;
@ -58,6 +60,7 @@ public class GlStateManager {
static boolean stateEnableShaderBlendColor = false;
static boolean stateBlend = false;
static boolean stateBlendStash = false;
static boolean stateGlobalBlend = true;
static int stateBlendEquation = -1;
static int stateBlendSRC = -1;
@ -312,6 +315,30 @@ public class GlStateManager {
}
}
public static final void eagPushStateForGLES2BlitHack() {
stateDepthTestStash = stateDepthTest;
stateCullStash = stateCull;
stateBlendStash = stateBlend;
}
public static final void eagPopStateForGLES2BlitHack() {
if(stateDepthTestStash) {
enableDepth();
}else {
disableDepth();
}
if(stateCullStash) {
enableCull();
}else {
disableCull();
}
if(stateBlendStash) {
enableBlend();
}else {
disableBlend();
}
}
public static final void depthFunc(int depthFunc) {
int rev = depthFunc;
switch(depthFunc) {
@ -603,7 +630,9 @@ public class GlStateManager {
f2 = f1;
}
_wglBindTexture(GL_TEXTURE_2D, null);
_wglBindTexture(GL_TEXTURE_3D, null);
if(EaglercraftGPU.checkOpenGLESVersion() >= 300) {
_wglBindTexture(GL_TEXTURE_3D, null);
}
boundTexture[i] = -1;
}
}

View File

@ -56,6 +56,22 @@ public class ImageData {
return new ImageData(pw, ph, img, alpha);
}
public static String getMimeFromType(String nameOrPath) {
if(nameOrPath == null) return "image/png";
nameOrPath = nameOrPath.toLowerCase();
if(nameOrPath.endsWith(".png")) {
return "image/png";
}else if(nameOrPath.endsWith(".jpg") || nameOrPath.endsWith(".jpeg")) {
return "image/jpeg";
}else if(nameOrPath.endsWith(".gif")) {
return "image/gif";
}else if(nameOrPath.endsWith(".bmp")) {
return "image/bmp";
}else {
return "image/png"; // rip
}
}
public static final ImageData loadImageFile(String path) {
byte[] fileData = EagRuntime.getResourceBytes(path);
if(fileData != null) {
@ -73,6 +89,23 @@ public class ImageData {
return PlatformAssets.loadImageFile(data);
}
public static final ImageData loadImageFile(String path, String mime) {
byte[] fileData = EagRuntime.getResourceBytes(path);
if(fileData != null) {
return loadImageFile(fileData, mime);
}else {
return null;
}
}
public static final ImageData loadImageFile(InputStream data, String mime) {
return PlatformAssets.loadImageFile(data, mime);
}
public static final ImageData loadImageFile(byte[] data, String mime) {
return PlatformAssets.loadImageFile(data, mime);
}
public void getRGB(int startX, int startY, int w, int h,
int[] rgbArray, int offset, int scansize) {
for(int y = 0; y < h; ++y) {
@ -147,5 +180,22 @@ public class ImageData {
public static int swapRB(int c) {
return (c & 0xFF00FF00) | ((c & 0x00FF0000) >>> 16) | ((c & 0x000000FF) << 16);
}
public static int[] swapRB(int[] arr) {
for(int i = 0; i < arr.length; ++i) {
int j = arr[i];
arr[i] = (j & 0xFF00FF00) | ((j & 0x00FF0000) >>> 16) |
((j & 0x000000FF) << 16);
}
return arr;
}
public boolean isNPOT() {
return (width & (width - 1)) != 0 || (height & (height - 1)) != 0;
}
public static boolean isNPOTStatic(int w, int h) {
return (w & (w - 1)) != 0 || (h & (h - 1)) != 0;
}
}

View File

@ -13,13 +13,12 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager;
import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f;
import net.lax1dude.eaglercraft.v1_8.vector.Vector4f;
/**
* Copyright (c) 2022 lax1dude. All Rights Reserved.
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -38,7 +37,10 @@ public class InstancedFontRenderer {
private static final Logger logger = LogManager.getLogger("InstancedFontRenderer");
public static final String vertexShaderPath = "/assets/eagler/glsl/accel_font.vsh";
public static final String vertexShaderPrecision = "precision lowp int;\nprecision highp float;\nprecision mediump sampler2D;\n";
public static final String fragmentShaderPath = "/assets/eagler/glsl/accel_font.fsh";
public static final String fragmentShaderPrecision = "precision lowp int;\nprecision highp float;\nprecision mediump sampler2D;\n";
private static final int BYTES_PER_CHARACTER = 10;
private static final int CHARACTER_LIMIT = 6553;
@ -78,21 +80,13 @@ public class InstancedFontRenderer {
private static float charCoordHeightValue = -1.0f;
static void initialize() {
String vertexSource = EagRuntime.getResourceString(vertexShaderPath);
if(vertexSource == null) {
throw new RuntimeException("InstancedFontRenderer shader \"" + vertexShaderPath + "\" is missing!");
}
String fragmentSource = EagRuntime.getResourceString(fragmentShaderPath);
if(fragmentSource == null) {
throw new RuntimeException("InstancedFontRenderer shader \"" + fragmentShaderPath + "\" is missing!");
}
String vertexSource = EagRuntime.getRequiredResourceString(vertexShaderPath);
String fragmentSource = EagRuntime.getRequiredResourceString(fragmentShaderPath);
IShaderGL vert = _wglCreateShader(GL_VERTEX_SHADER);
IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER);
_wglShaderSource(vert, FixedFunctionConstants.VERSION + "\n" + vertexSource);
_wglShaderSource(vert, GLSLHeader.getVertexHeaderCompat(vertexSource, vertexShaderPrecision));
_wglCompileShader(vert);
if(_wglGetShaderi(vert, GL_COMPILE_STATUS) != GL_TRUE) {
@ -107,7 +101,7 @@ public class InstancedFontRenderer {
throw new IllegalStateException("Vertex shader \"" + vertexShaderPath + "\" could not be compiled!");
}
_wglShaderSource(frag, FixedFunctionConstants.VERSION + "\n" + fragmentSource);
_wglShaderSource(frag, GLSLHeader.getFragmentHeaderCompat(fragmentSource, fragmentShaderPrecision));
_wglCompileShader(frag);
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
@ -127,6 +121,10 @@ public class InstancedFontRenderer {
_wglAttachShader(shaderProgram, vert);
_wglAttachShader(shaderProgram, frag);
if(EaglercraftGPU.checkOpenGLESVersion() == 200) {
VSHInputLayoutParser.applyLayout(shaderProgram, VSHInputLayoutParser.getShaderInputs(vertexSource));
}
_wglLinkProgram(shaderProgram);
_wglDetachShader(shaderProgram, vert);
@ -161,60 +159,62 @@ public class InstancedFontRenderer {
_wglUniform1i(_wglGetUniformLocation(shaderProgram, "u_inputTexture"), 0);
vertexArray = _wglGenVertexArrays();
vertexArray = EaglercraftGPU.createGLBufferArray();
vertexBuffer = _wglGenBuffers();
instancesBuffer = _wglGenBuffers();
FloatBuffer verts = EagRuntime.allocateFloatBuffer(108);
float paddingA = 0.005f;
float paddingB = 1.0f - paddingA;
verts.put(new float[] {
// (0 - 6 - 12) regular:
0.0f, 0.0f, 0.25f, 0.0f, 1.0f, 0.25f, 1.0f, 0.0f, 0.25f,
1.0f, 0.0f, 0.25f, 0.0f, 1.0f, 0.25f, 1.0f, 1.0f, 0.25f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
paddingA, paddingA, 0.25f, paddingA, paddingB, 0.25f, paddingB, paddingA, 0.25f,
paddingB, paddingA, 0.25f, paddingA, paddingB, 0.25f, paddingB, paddingB, 0.25f,
paddingA, paddingA, 0.0f, paddingA, paddingB, 0.0f, paddingB, paddingA, 0.0f,
paddingB, paddingA, 0.0f, paddingA, paddingB, 0.0f, paddingB, paddingB, 0.0f,
// (12 - 24 - 36) bold shadow:
0.0f, 0.0f, 0.25f, 0.0f, 1.0f, 0.25f, 1.0f, 0.0f, 0.25f,
1.0f, 0.0f, 0.25f, 0.0f, 1.0f, 0.25f, 1.0f, 1.0f, 0.25f,
0.0f, 0.0f, 0.75f, 0.0f, 1.0f, 0.75f, 1.0f, 0.0f, 0.75f,
1.0f, 0.0f, 0.75f, 0.0f, 1.0f, 0.75f, 1.0f, 1.0f, 0.75f,
paddingA, paddingA, 0.25f, paddingA, paddingB, 0.25f, paddingB, paddingA, 0.25f,
paddingB, paddingA, 0.25f, paddingA, paddingB, 0.25f, paddingB, paddingB, 0.25f,
paddingA, paddingA, 0.75f, paddingA, paddingB, 0.75f, paddingB, paddingA, 0.75f,
paddingB, paddingA, 0.75f, paddingA, paddingB, 0.75f, paddingB, paddingB, 0.75f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 0.0f, 0.5f,
1.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.5f, 1.0f, 1.0f, 0.5f
paddingA, paddingA, 0.0f, paddingA, paddingB, 0.0f, paddingB, paddingA, 0.0f,
paddingB, paddingA, 0.0f, paddingA, paddingB, 0.0f, paddingB, paddingB, 0.0f,
paddingA, paddingA, 0.5f, paddingA, paddingB, 0.5f, paddingB, paddingA, 0.5f,
paddingB, paddingA, 0.5f, paddingA, paddingB, 0.5f, paddingB, paddingB, 0.5f
});
verts.flip();
EaglercraftGPU.bindGLBufferArray(vertexArray);
EaglercraftGPU.bindGLArrayBuffer(vertexBuffer);
EaglercraftGPU.bindVAOGLArrayBufferNow(vertexBuffer);
_wglBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW);
EagRuntime.freeFloatBuffer(verts);
_wglEnableVertexAttribArray(0);
_wglVertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
_wglVertexAttribDivisor(0, 0);
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
EaglercraftGPU.vertexAttribDivisor(0, 0);
EaglercraftGPU.bindGLArrayBuffer(instancesBuffer);
EaglercraftGPU.bindVAOGLArrayBufferNow(instancesBuffer);
_wglBufferData(GL_ARRAY_BUFFER, fontDataBuffer.remaining(), GL_STREAM_DRAW);
_wglEnableVertexAttribArray(1);
_wglVertexAttribPointer(1, 2, GL_SHORT, false, 10, 0);
_wglVertexAttribDivisor(1, 1);
EaglercraftGPU.enableVertexAttribArray(1);
EaglercraftGPU.vertexAttribPointer(1, 2, GL_SHORT, false, 10, 0);
EaglercraftGPU.vertexAttribDivisor(1, 1);
_wglEnableVertexAttribArray(2);
_wglVertexAttribPointer(2, 2, GL_UNSIGNED_BYTE, false, 10, 4);
_wglVertexAttribDivisor(2, 1);
EaglercraftGPU.enableVertexAttribArray(2);
EaglercraftGPU.vertexAttribPointer(2, 2, GL_UNSIGNED_BYTE, false, 10, 4);
EaglercraftGPU.vertexAttribDivisor(2, 1);
_wglEnableVertexAttribArray(3);
_wglVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, true, 10, 6);
_wglVertexAttribDivisor(3, 1);
EaglercraftGPU.enableVertexAttribArray(3);
EaglercraftGPU.vertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, true, 10, 6);
EaglercraftGPU.vertexAttribDivisor(3, 1);
}
@ -381,7 +381,7 @@ public class InstancedFontRenderer {
fontDataBuffer.position(p);
fontDataBuffer.limit(l);
_wglDrawArraysInstanced(GL_TRIANGLES, shadow ? 0 : 6, shadow ? 12 : 6, charactersDrawn);
EaglercraftGPU.doDrawArraysInstanced(GL_TRIANGLES, shadow ? 0 : 6, shadow ? 12 : 6, charactersDrawn);
}
if(boldCharactersDrawn > 0) {
@ -394,7 +394,7 @@ public class InstancedFontRenderer {
fontBoldDataBuffer.position(p);
fontBoldDataBuffer.limit(l);
_wglDrawArraysInstanced(GL_TRIANGLES, shadow ? 12 : 24, shadow ? 24 : 12, boldCharactersDrawn);
EaglercraftGPU.doDrawArraysInstanced(GL_TRIANGLES, shadow ? 12 : 24, shadow ? 24 : 12, boldCharactersDrawn);
}
}
@ -455,4 +455,40 @@ public class InstancedFontRenderer {
if(y > heightCalcMost || heightCalcMost == Integer.MAX_VALUE) heightCalcMost = y;
}
public static void destroy() {
if(fontDataBuffer != null) {
EagRuntime.freeByteBuffer(fontDataBuffer);
fontDataBuffer = null;
}
if(fontBoldDataBuffer != null) {
EagRuntime.freeByteBuffer(fontBoldDataBuffer);
fontBoldDataBuffer = null;
}
if(shaderProgram != null) {
_wglDeleteProgram(shaderProgram);
shaderProgram = null;
}
if(matrixCopyBuffer != null) {
EagRuntime.freeFloatBuffer(matrixCopyBuffer);
matrixCopyBuffer = null;
}
u_matrixTransform = null;
u_charSize2f = null;
u_charCoordSize2f = null;
u_color4f = null;
u_colorBias4f = null;
if(vertexArray != null) {
EaglercraftGPU.destroyGLBufferArray(vertexArray);
vertexArray = null;
}
if(vertexBuffer != null) {
_wglDeleteBuffers(vertexBuffer);
vertexBuffer = null;
}
if(instancesBuffer != null) {
_wglDeleteBuffers(instancesBuffer);
instancesBuffer = null;
}
}
}

View File

@ -13,11 +13,10 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants;
import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f;
/**
* Copyright (c) 2022 lax1dude. All Rights Reserved.
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -36,7 +35,10 @@ public class InstancedParticleRenderer {
private static final Logger logger = LogManager.getLogger("InstancedParticleRenderer");
public static final String vertexShaderPath = "/assets/eagler/glsl/accel_particle.vsh";
public static final String vertexShaderPrecision = "precision lowp int;\nprecision highp float;\nprecision mediump sampler2D;\n";
public static final String fragmentShaderPath = "/assets/eagler/glsl/accel_particle.fsh";
public static final String fragmentShaderPrecision = "precision lowp int;\nprecision mediump float;\nprecision mediump sampler2D;\n";
private static ByteBuffer particleBuffer = null;
private static int particleCount = 0;
@ -79,20 +81,13 @@ public class InstancedParticleRenderer {
private static float stateTransformParam5 = -999.0f;
static void initialize() {
String vertexSource = EagRuntime.getResourceString(vertexShaderPath);
if(vertexSource == null) {
throw new RuntimeException("InstancedParticleRenderer shader \"" + vertexShaderPath + "\" is missing!");
}
String fragmentSource = EagRuntime.getResourceString(fragmentShaderPath);
if(fragmentSource == null) {
throw new RuntimeException("InstancedParticleRenderer shader \"" + fragmentShaderPath + "\" is missing!");
}
String vertexSource = EagRuntime.getRequiredResourceString(vertexShaderPath);
String fragmentSource = EagRuntime.getRequiredResourceString(fragmentShaderPath);
IShaderGL vert = _wglCreateShader(GL_VERTEX_SHADER);
IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER);
_wglShaderSource(vert, FixedFunctionConstants.VERSION + "\n" + vertexSource);
_wglShaderSource(vert, GLSLHeader.getVertexHeaderCompat(vertexSource, vertexShaderPrecision));
_wglCompileShader(vert);
if(_wglGetShaderi(vert, GL_COMPILE_STATUS) != GL_TRUE) {
@ -107,7 +102,7 @@ public class InstancedParticleRenderer {
throw new IllegalStateException("Vertex shader \"" + vertexShaderPath + "\" could not be compiled!");
}
_wglShaderSource(frag, FixedFunctionConstants.VERSION + "\n" + fragmentSource);
_wglShaderSource(frag, GLSLHeader.getFragmentHeaderCompat(fragmentSource, fragmentShaderPrecision));
_wglCompileShader(frag);
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
@ -127,6 +122,10 @@ public class InstancedParticleRenderer {
_wglAttachShader(shaderProgram, vert);
_wglAttachShader(shaderProgram, frag);
if(EaglercraftGPU.checkOpenGLESVersion() == 200) {
VSHInputLayoutParser.applyLayout(shaderProgram, VSHInputLayoutParser.getShaderInputs(vertexSource));
}
_wglLinkProgram(shaderProgram);
_wglDetachShader(shaderProgram, vert);
@ -161,7 +160,7 @@ public class InstancedParticleRenderer {
_wglUniform1i(_wglGetUniformLocation(shaderProgram, "u_inputTexture"), 0);
_wglUniform1i(_wglGetUniformLocation(shaderProgram, "u_lightmapTexture"), 1);
vertexArray = _wglGenVertexArrays();
vertexArray = EaglercraftGPU.createGLBufferArray();
vertexBuffer = _wglGenBuffers();
instancesBuffer = _wglGenBuffers();
@ -174,37 +173,37 @@ public class InstancedParticleRenderer {
EaglercraftGPU.bindGLBufferArray(vertexArray);
EaglercraftGPU.bindGLArrayBuffer(vertexBuffer);
EaglercraftGPU.bindVAOGLArrayBufferNow(vertexBuffer);
_wglBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW);
EagRuntime.freeFloatBuffer(verts);
_wglEnableVertexAttribArray(0);
_wglVertexAttribPointer(0, 2, GL_FLOAT, false, 8, 0);
_wglVertexAttribDivisor(0, 0);
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, 2, GL_FLOAT, false, 8, 0);
EaglercraftGPU.vertexAttribDivisor(0, 0);
EaglercraftGPU.bindGLArrayBuffer(instancesBuffer);
EaglercraftGPU.bindVAOGLArrayBufferNow(instancesBuffer);
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.remaining(), GL_STREAM_DRAW);
_wglEnableVertexAttribArray(1);
_wglVertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0);
_wglVertexAttribDivisor(1, 1);
EaglercraftGPU.enableVertexAttribArray(1);
EaglercraftGPU.vertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0);
EaglercraftGPU.vertexAttribDivisor(1, 1);
_wglEnableVertexAttribArray(2);
_wglVertexAttribPointer(2, 2, GL_UNSIGNED_SHORT, false, 24, 12);
_wglVertexAttribDivisor(2, 1);
EaglercraftGPU.enableVertexAttribArray(2);
EaglercraftGPU.vertexAttribPointer(2, 2, GL_UNSIGNED_SHORT, false, 24, 12);
EaglercraftGPU.vertexAttribDivisor(2, 1);
_wglEnableVertexAttribArray(3);
_wglVertexAttribPointer(3, 2, GL_UNSIGNED_BYTE, true, 24, 16);
_wglVertexAttribDivisor(3, 1);
EaglercraftGPU.enableVertexAttribArray(3);
EaglercraftGPU.vertexAttribPointer(3, 2, GL_UNSIGNED_BYTE, true, 24, 16);
EaglercraftGPU.vertexAttribDivisor(3, 1);
_wglEnableVertexAttribArray(4);
_wglVertexAttribPointer(4, 2, GL_UNSIGNED_BYTE, false, 24, 18);
_wglVertexAttribDivisor(4, 1);
EaglercraftGPU.enableVertexAttribArray(4);
EaglercraftGPU.vertexAttribPointer(4, 2, GL_UNSIGNED_BYTE, false, 24, 18);
EaglercraftGPU.vertexAttribDivisor(4, 1);
_wglEnableVertexAttribArray(5);
_wglVertexAttribPointer(5, 4, GL_UNSIGNED_BYTE, true, 24, 20);
_wglVertexAttribDivisor(5, 1);
EaglercraftGPU.enableVertexAttribArray(5);
EaglercraftGPU.vertexAttribPointer(5, 4, GL_UNSIGNED_BYTE, true, 24, 20);
EaglercraftGPU.vertexAttribDivisor(5, 1);
}
@ -316,11 +315,43 @@ public class InstancedParticleRenderer {
particleBuffer.position(p);
particleBuffer.limit(l);
_wglDrawArraysInstanced(GL_TRIANGLES, 0, 6, particleCount);
EaglercraftGPU.doDrawArraysInstanced(GL_TRIANGLES, 0, 6, particleCount);
}
public static void stupidColorSetHack(IUniformGL color4f) {
_wglUniform4f(color4f, GlStateManager.stateColorR, GlStateManager.stateColorG, GlStateManager.stateColorB, GlStateManager.stateColorA);
}
public static void destroy() {
if(particleBuffer != null) {
EagRuntime.freeByteBuffer(particleBuffer);
particleBuffer = null;
}
if(shaderProgram != null) {
_wglDeleteProgram(shaderProgram);
shaderProgram = null;
}
if(matrixCopyBuffer != null) {
EagRuntime.freeFloatBuffer(matrixCopyBuffer);
matrixCopyBuffer = null;
}
u_matrixTransform = null;
u_texCoordSize2f_particleSize1f = null;
u_transformParam_1_2_5_f = null;
u_transformParam_3_4_f = null;
u_color4f = null;
if(vertexArray != null) {
EaglercraftGPU.destroyGLBufferArray(vertexArray);
vertexArray = null;
}
if(vertexBuffer != null) {
_wglDeleteBuffers(vertexBuffer);
vertexBuffer = null;
}
if(instancesBuffer != null) {
_wglDeleteBuffers(instancesBuffer);
instancesBuffer = null;
}
}
}

View File

@ -1,7 +1,7 @@
package net.lax1dude.eaglercraft.v1_8.opengl;
/**
* Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved.
* Copyright (c) 2022-2023 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

View File

@ -0,0 +1,225 @@
package net.lax1dude.eaglercraft.v1_8.opengl;
import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL;
import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
/**
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
class SoftGLBufferArray implements IBufferArrayGL {
Attrib[] attribs = new Attrib[4];
int[] attribDivisors = null;
int hasAttribDivisorMask = 0;
int enabled = 0;
int enabledCnt = -1;
IBufferGL indexBuffer = null;
SoftGLBufferArray() {
}
void setAttrib(IBufferGL buffer, int index, int size, int format, boolean normalized, int stride, int offset) {
if(index >= attribs.length) {
int newLen = attribs.length << 1;
while(newLen <= index) {
newLen <<= 1;
}
Attrib[] newAttrib = new Attrib[newLen];
System.arraycopy(attribs, 0, newAttrib, 0, attribs.length);
attribs = newAttrib;
}
attribs[index] = new Attrib(buffer, size, format, normalized, stride, offset);
}
void setAttribDivisor(int index, int divisor) {
if(attribDivisors == null) {
if(divisor != 0) {
int newLen = 8;
while(newLen <= index) {
newLen <<= 1;
}
attribDivisors = new int[newLen];
}
}else if(index >= attribDivisors.length) {
int newLen = attribDivisors.length << 1;
while(newLen <= index) {
newLen <<= 1;
}
int[] newDivisor = new int[newLen];
System.arraycopy(attribDivisors, 0, newDivisor, 0, attribDivisors.length);
attribDivisors = newDivisor;
}
if(attribDivisors != null) {
attribDivisors[index] = divisor;
if(divisor != 0) {
hasAttribDivisorMask |= (1 << index);
}else {
hasAttribDivisorMask &= ~(1 << index);
}
}
}
void enableAttrib(int index, boolean en) {
if(en) {
enabled |= (1 << index);
}else {
enabled &= ~(1 << index);
}
enabledCnt = 32 - Integer.numberOfLeadingZeros(enabled);
}
void setIndexBuffer(IBufferGL buffer) {
indexBuffer = buffer;
}
void transitionToState(SoftGLBufferState previousState, boolean elements) {
int oldEnabled = previousState.oldEnabled;
int oldEnabledCnt = previousState.oldEnabledCnt;
int[] oldAttribDivisors = previousState.attribDivisors;
int oldHasAttribDivisorMask = previousState.hasAttribDivisorMask;
Attrib[] oldAttrs = previousState.attribs;
boolean instancingCapable = EaglercraftGPU.checkInstancingCapable();
int enCnt = enabledCnt;
int en = enabled;
Attrib[] attrs = attribs;
int[] divs = attribDivisors;
int hasDivs = hasAttribDivisorMask;
if(oldEnabledCnt >= 0) {
int enMax = Math.max(enCnt, oldEnabledCnt);
for(int i = 0, ii; i < enMax; ++i) {
ii = (1 << i);
boolean old = i < oldEnabledCnt && (oldEnabled & ii) != 0;
boolean _new = i < enCnt && (en & ii) != 0;
if(_new) {
if(!old) {
_wglEnableVertexAttribArray(i);
}
Attrib attr = i < attrs.length ? attrs[i] : null;
if(attr != null) {
Attrib oldAttr = oldAttrs[i];
if(oldAttr == null || !oldAttr.equalsExplicit(attr)) {
EaglercraftGPU.bindGLArrayBuffer(attr.buffer);
_wglVertexAttribPointer(i, attr.size, attr.format, attr.normalized, attr.stride, attr.offset);
oldAttrs[i] = attr;
}
}else {
oldAttrs[i] = null;
}
if(instancingCapable) {
// instancing is uncommon
if((hasDivs & ii) != 0) {
int newDivisor = divs[i];
if((oldHasAttribDivisorMask & ii) == 0 || newDivisor != oldAttribDivisors[i]) {
_wglVertexAttribDivisor(i, newDivisor);
oldAttribDivisors[i] = newDivisor;
previousState.hasAttribDivisorMask |= ii;
}
}else {
if((oldHasAttribDivisorMask & ii) != 0) {
_wglVertexAttribDivisor(i, 0);
oldAttribDivisors[i] = 0;
previousState.hasAttribDivisorMask &= ~ii;
}
}
}
}else if(old) {
_wglDisableVertexAttribArray(i);
}
}
}else {
// Bootstrap code for the emulator's first draw
for(int i = 0; i < enCnt; ++i) {
int ii = (1 << i);
if((en & ii) != 0) {
_wglEnableVertexAttribArray(i);
Attrib attr = attrs[i];
if(attr != null) {
EaglercraftGPU.bindGLArrayBuffer(attr.buffer);
_wglVertexAttribPointer(i, attr.size, attr.format, attr.normalized, attr.stride, attr.offset);
oldAttrs[i] = attr;
}else {
oldAttrs[i] = null;
}
if(instancingCapable) {
if((hasDivs & ii) != 0) {
int newDivisor = divs[i];
_wglVertexAttribDivisor(i, newDivisor);
oldAttribDivisors[i] = newDivisor;
previousState.hasAttribDivisorMask |= ii;
}else {
_wglVertexAttribDivisor(i, 0);
oldAttribDivisors[i] = 0;
}
}
}
}
}
if(elements) {
IBufferGL indexBufferL = indexBuffer;
if(indexBufferL != null) {
EaglercraftGPU.bindEmulatedVAOIndexBuffer(indexBufferL);
}
}
previousState.oldEnabled = en & ((1 << enCnt) - 1);
previousState.oldEnabledCnt = enCnt;
}
@Override
public void free() {
}
static class Attrib {
final IBufferGL buffer;
final int size;
final int format;
final boolean normalized;
final int stride;
final int offset;
final int hash;
final int checkVal;
Attrib(IBufferGL buffer, int size, int format, boolean normalized, int stride, int offset) {
this.buffer = buffer;
this.size = size;
this.format = format;
this.normalized = normalized;
this.stride = stride;
this.offset = offset;
this.checkVal = ((size - 1) & 3) | (normalized ? 4 : 0) | (format << 4);
this.hash = (((((31 + buffer.hashCode()) * 31 + size) * 31 + format) * 31 + (normalized ? 1 : 0)) * 31
+ stride) * 31 + offset;
}
public int hashCode() {
return hash;
}
public boolean equals(Object obj) {
if(obj == this) return true;
if(!(obj instanceof Attrib)) return false;
Attrib o2 = (Attrib)obj;
return o2.hash == hash && o2.buffer == buffer && o2.checkVal == checkVal && o2.stride == stride && o2.offset == offset;
}
public boolean equalsExplicit(Attrib o2) {
return o2 == this || (o2.hash == hash && o2.buffer == buffer && o2.checkVal == checkVal && o2.stride == stride && o2.offset == offset);
}
}
}

View File

@ -0,0 +1,31 @@
package net.lax1dude.eaglercraft.v1_8.opengl;
import net.lax1dude.eaglercraft.v1_8.opengl.SoftGLBufferArray.Attrib;
/**
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
class SoftGLBufferState {
final Attrib[] attribs = new Attrib[24];
int[] attribDivisors = new int[24];
int hasAttribDivisorMask = 0;
int oldEnabled = 0;
int oldEnabledCnt = -1;
SoftGLBufferState() {
}
}

View File

@ -10,7 +10,6 @@ import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants;
import net.lax1dude.eaglercraft.v1_8.vector.Matrix3f;
/**
@ -33,6 +32,7 @@ public class SpriteLevelMixer {
private static final Logger LOGGER = LogManager.getLogger("SpriteLevelMixer");
public static final String fragmentShaderPath = "/assets/eagler/glsl/texture_mix.fsh";
public static final String fragmentShaderPrecision = "precision lowp int;\nprecision highp float;\nprecision highp sampler2D;\n";
private static IProgramGL shaderProgram = null;
@ -61,15 +61,11 @@ public class SpriteLevelMixer {
private static final Matrix3f identityMatrix = new Matrix3f();
static void initialize() {
String fragmentSource = EagRuntime.getResourceString(fragmentShaderPath);
if(fragmentSource == null) {
throw new RuntimeException("SpriteLevelMixer shader \"" + fragmentShaderPath + "\" is missing!");
}
String fragmentSource = EagRuntime.getRequiredResourceString(fragmentShaderPath);
IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER);
_wglShaderSource(frag, FixedFunctionConstants.VERSION + "\n" + fragmentSource);
_wglShaderSource(frag, GLSLHeader.getFragmentHeaderCompat(fragmentSource, fragmentShaderPrecision));
_wglCompileShader(frag);
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
@ -89,6 +85,10 @@ public class SpriteLevelMixer {
_wglAttachShader(shaderProgram, DrawUtils.vshLocal);
_wglAttachShader(shaderProgram, frag);
if(EaglercraftGPU.checkOpenGLESVersion() == 200) {
VSHInputLayoutParser.applyLayout(shaderProgram, DrawUtils.vshLocalLayout);
}
_wglLinkProgram(shaderProgram);
_wglDetachShader(shaderProgram, DrawUtils.vshLocal);
@ -155,7 +155,14 @@ public class SpriteLevelMixer {
public static void drawSprite(float level) {
EaglercraftGPU.bindGLShaderProgram(shaderProgram);
_wglUniform1f(u_textureLod1f, level);
if(EaglercraftGPU.checkTextureLODCapable()) {
_wglUniform1f(u_textureLod1f, level);
}else {
if(level != 0.0f) {
LOGGER.error("Tried to copy from mipmap level {}, but this GPU does not support textureLod!", level);
}
_wglUniform1f(u_textureLod1f, 0.0f);
}
if(blendColorChanged) {
_wglUniform4f(u_blendFactor4f, blendColorR, blendColorG, blendColorB, blendColorA);
@ -178,4 +185,19 @@ public class SpriteLevelMixer {
DrawUtils.drawStandardQuad2D();
}
public static void destroy() {
if(matrixCopyBuffer != null) {
EagRuntime.freeFloatBuffer(matrixCopyBuffer);
matrixCopyBuffer = null;
}
if(shaderProgram != null) {
_wglDeleteProgram(shaderProgram);
shaderProgram = null;
}
u_textureLod1f = null;
u_blendFactor4f = null;
u_blendBias4f = null;
u_matrixTransform = null;
}
}

View File

@ -74,7 +74,7 @@ public class StreamBuffer {
next.vertexBuffer = _wglGenBuffers();
}
if(next.vertexArray == null) {
next.vertexArray = _wglGenVertexArrays();
next.vertexArray = EaglercraftGPU.createGLBufferArray();
initializer.initialize(next.vertexArray, next.vertexBuffer);
}
if(next.vertexBufferSize < requiredMemory) {
@ -100,7 +100,7 @@ public class StreamBuffer {
newArray[i] = buffers[i];
}else {
if(buffers[i].vertexArray != null) {
_wglDeleteVertexArrays(buffers[i].vertexArray);
EaglercraftGPU.destroyGLBufferArray(buffers[i].vertexArray);
}
if(buffers[i].vertexBuffer != null) {
_wglDeleteBuffers(buffers[i].vertexBuffer);
@ -135,7 +135,7 @@ public class StreamBuffer {
for(int i = 0; i < buffers.length; ++i) {
StreamBufferInstance next = buffers[i];
if(next.vertexArray != null) {
_wglDeleteVertexArrays(next.vertexArray);
EaglercraftGPU.destroyGLBufferArray(next.vertexArray);
}
if(next.vertexBuffer != null) {
_wglDeleteBuffers(next.vertexBuffer);

View File

@ -3,16 +3,17 @@ package net.lax1dude.eaglercraft.v1_8.opengl;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionConstants;
/**
* Copyright (c) 2023 lax1dude. All Rights Reserved.
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -31,9 +32,13 @@ public class TextureCopyUtil {
private static final Logger LOGGER = LogManager.getLogger("TextureCopyUtil");
public static final String vertexShaderPath = "/assets/eagler/glsl/texture_blit.vsh";
public static final String vertexShaderPrecision = "precision lowp int;\nprecision highp float;\nprecision highp sampler2D;\n";
public static final String fragmentShaderPath = "/assets/eagler/glsl/texture_blit.fsh";
public static final String fragmentShaderPrecision = "precision lowp int;\nprecision highp float;\nprecision highp sampler2D;\n";
private static String vshSource = null;
private static List<VSHInputLayoutParser.ShaderInput> vshSourceLayout = null;
private static String fshSource = null;
private static IShaderGL vshShader = null;
@ -54,6 +59,17 @@ public class TextureCopyUtil {
this.u_pixelAlignmentSizes4f = _wglGetUniformLocation(shaderProgram, "u_pixelAlignmentSizes4f");
this.u_pixelAlignmentOffset2f = _wglGetUniformLocation(shaderProgram, "u_pixelAlignmentOffset2f");
}
private void destroy() {
if(shaderProgram != null) {
_wglDeleteProgram(shaderProgram);
shaderProgram = null;
}
u_srcCoords4f = null;
u_dstCoords4f = null;
u_textureLod1f = null;
u_pixelAlignmentSizes4f = null;
u_pixelAlignmentOffset2f = null;
}
}
private static TextureCopyShader textureBlit = null;
@ -74,19 +90,12 @@ public class TextureCopyUtil {
private static float alignOffsetY = 0.0f;
static void initialize() {
vshSource = EagRuntime.getResourceString(vertexShaderPath);
if(vshSource == null) {
throw new RuntimeException("TextureCopyUtil shader \"" + vertexShaderPath + "\" is missing!");
}
fshSource = EagRuntime.getResourceString(fragmentShaderPath);
if(fshSource == null) {
throw new RuntimeException("TextureCopyUtil shader \"" + fragmentShaderPath + "\" is missing!");
}
vshSource = EagRuntime.getRequiredResourceString(vertexShaderPath);
fshSource = EagRuntime.getRequiredResourceString(fragmentShaderPath);
vshShader = _wglCreateShader(GL_VERTEX_SHADER);
_wglShaderSource(vshShader, FixedFunctionConstants.VERSION + "\n" + vshSource);
_wglShaderSource(vshShader, GLSLHeader.getVertexHeaderCompat(vshSource, vertexShaderPrecision));
_wglCompileShader(vshShader);
if(_wglGetShaderi(vshShader, GL_COMPILE_STATUS) != GL_TRUE) {
@ -100,14 +109,17 @@ public class TextureCopyUtil {
}
throw new IllegalStateException("Vertex shader \"" + vertexShaderPath + "\" could not be compiled!");
}
if(EaglercraftGPU.checkOpenGLESVersion() == 200) {
vshSourceLayout = VSHInputLayoutParser.getShaderInputs(vshSource);
}
}
private static TextureCopyShader compileShader(boolean align, boolean depth) {
IShaderGL frag = _wglCreateShader(GL_FRAGMENT_SHADER);
_wglShaderSource(frag,
FixedFunctionConstants.VERSION + "\n" + (align ? "#define COMPILE_PIXEL_ALIGNMENT\n" : "")
+ (depth ? "#define COMPILE_BLIT_DEPTH\n" : "") + fshSource);
_wglShaderSource(frag, GLSLHeader.getFragmentHeaderCompat(fshSource, fragmentShaderPrecision
+ (align ? "#define COMPILE_PIXEL_ALIGNMENT\n" : "") + (depth ? "#define COMPILE_BLIT_DEPTH\n" : "")));
_wglCompileShader(frag);
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
@ -127,6 +139,10 @@ public class TextureCopyUtil {
_wglAttachShader(shaderProgram, vshShader);
_wglAttachShader(shaderProgram, frag);
if(EaglercraftGPU.checkOpenGLESVersion() == 200) {
VSHInputLayoutParser.applyLayout(shaderProgram, vshSourceLayout);
}
_wglLinkProgram(shaderProgram);
_wglDetachShader(shaderProgram, vshShader);
@ -226,7 +242,14 @@ public class TextureCopyUtil {
_wglUniform4f(shaderObj.u_srcCoords4f, (float)srcX / srcViewW, (float)srcY / srcViewH, (float)srcW / srcViewW, (float)srcH / srcViewH);
_wglUniform4f(shaderObj.u_dstCoords4f, (float) dstX / dstViewW - 1.0f, (float) dstY / dstViewH - 1.0f,
(float) dstW / dstViewW, (float) dstH / dstViewH);
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
if(EaglercraftGPU.checkTextureLODCapable()) {
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
}else {
if(lvl != 0.0f) {
LOGGER.error("Tried to copy from mipmap level {}, but this GPU does not support textureLod!", lvl);
}
_wglUniform1f(shaderObj.u_textureLod1f, 0.0f);
}
if(isAligned) {
_wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH);
_wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY);
@ -244,7 +267,14 @@ public class TextureCopyUtil {
EaglercraftGPU.bindGLShaderProgram(shaderObj.shaderProgram);
_wglUniform4f(shaderObj.u_srcCoords4f, 0.0f, 0.0f, 1.0f, 1.0f);
_wglUniform4f(shaderObj.u_dstCoords4f, -1.0f, -1.0f, 2.0f, 2.0f);
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
if(EaglercraftGPU.checkTextureLODCapable()) {
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
}else {
if(lvl != 0.0f) {
LOGGER.error("Tried to copy from mipmap level {}, but this GPU does not support textureLod!", lvl);
}
_wglUniform1f(shaderObj.u_textureLod1f, 0.0f);
}
if(isAligned) {
_wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH);
_wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY);
@ -271,7 +301,14 @@ public class TextureCopyUtil {
GlStateManager.viewport(dstX, dstY, dstW, dstH);
_wglUniform4f(shaderObj.u_srcCoords4f, (float)srcX / srcViewW, (float)srcY / srcViewH, (float)srcW / srcViewW, (float)srcH / srcViewH);
_wglUniform4f(shaderObj.u_dstCoords4f, -1.0f, -1.0f, 2.0f, 2.0f);
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
if(EaglercraftGPU.checkTextureLODCapable()) {
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
}else {
if(lvl != 0.0f) {
LOGGER.error("Tried to copy from mipmap level {}, but this GPU does not support textureLod!", lvl);
}
_wglUniform1f(shaderObj.u_textureLod1f, 0.0f);
}
if(isAligned) {
_wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH);
_wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY);
@ -298,7 +335,14 @@ public class TextureCopyUtil {
_wglUniform4f(shaderObj.u_srcCoords4f, (float)srcX / srcViewW, (float)srcY / srcViewH, (float)srcW / srcViewW, (float)srcH / srcViewH);
_wglUniform4f(shaderObj.u_dstCoords4f, (float) dstX / dstViewW - 1.0f, (float) dstY / dstViewH - 1.0f,
(float) dstW / dstViewW, (float) dstH / dstViewH);
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
if(EaglercraftGPU.checkTextureLODCapable()) {
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
}else {
if(lvl != 0.0f) {
LOGGER.error("Tried to copy from mipmap level {}, but this GPU does not support textureLod!", lvl);
}
_wglUniform1f(shaderObj.u_textureLod1f, 0.0f);
}
if(isAligned) {
_wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH);
_wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY);
@ -316,7 +360,14 @@ public class TextureCopyUtil {
EaglercraftGPU.bindGLShaderProgram(shaderObj.shaderProgram);
_wglUniform4f(shaderObj.u_srcCoords4f, 0.0f, 0.0f, 1.0f, 1.0f);
_wglUniform4f(shaderObj.u_dstCoords4f, -1.0f, -1.0f, 2.0f, 2.0f);
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
if(EaglercraftGPU.checkTextureLODCapable()) {
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
}else {
if(lvl != 0.0f) {
LOGGER.error("Tried to copy from mipmap level {}, but this GPU does not support textureLod!", lvl);
}
_wglUniform1f(shaderObj.u_textureLod1f, 0.0f);
}
if(isAligned) {
_wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH);
_wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY);
@ -343,7 +394,14 @@ public class TextureCopyUtil {
GlStateManager.viewport(dstX, dstY, dstW, dstH);
_wglUniform4f(shaderObj.u_srcCoords4f, (float)srcX / srcViewW, (float)srcY / srcViewH, (float)srcW / srcViewW, (float)srcH / srcViewH);
_wglUniform4f(shaderObj.u_dstCoords4f, -1.0f, -1.0f, 2.0f, 2.0f);
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
if(EaglercraftGPU.checkTextureLODCapable()) {
_wglUniform1f(shaderObj.u_textureLod1f, lvl);
}else {
if(lvl != 0.0f) {
LOGGER.error("Tried to copy from mipmap level {}, but this GPU does not support textureLod!", lvl);
}
_wglUniform1f(shaderObj.u_textureLod1f, 0.0f);
}
if(isAligned) {
_wglUniform4f(shaderObj.u_pixelAlignmentSizes4f, alignW, alignH, 1.0f / alignW, 1.0f / alignH);
_wglUniform2f(shaderObj.u_pixelAlignmentOffset2f, alignOffsetX, alignOffsetY);
@ -351,4 +409,27 @@ public class TextureCopyUtil {
}
DrawUtils.drawStandardQuad2D();
}
public static void destroy() {
if(vshShader != null) {
_wglDeleteShader(vshShader);
vshShader = null;
}
if(textureBlit != null) {
textureBlit.destroy();
textureBlit = null;
}
if(textureBlitAligned != null) {
textureBlitAligned.destroy();
textureBlitAligned = null;
}
if(textureBlitDepth != null) {
textureBlitDepth.destroy();
textureBlitDepth = null;
}
if(textureBlitDepthAligned != null) {
textureBlitDepthAligned.destroy();
textureBlitDepthAligned = null;
}
}
}

View File

@ -0,0 +1,81 @@
package net.lax1dude.eaglercraft.v1_8.opengl;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import static net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ExtGLEnums.*;
/**
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public class TextureFormatHelper {
public static int getFormatFromInternal(int internalFormat) {
switch(internalFormat) {
case _GL_R8:
case 0x822D: // GL_R16F
case 0x822E: // GL_R32F
return GL_RED;
case _GL_RG8:
case 0x822F: // GL_RG16F
case 0x8230: // GL_RG32F
return _GL_RG;
case GL_RGB8:
case _GL_RGB16F:
case 0x8815: // GL_RGB32F
return GL_RGB;
case GL_RGBA8:
case 0x881A: // GL_RGBA16F
case 0x8814: // GL_RGBA32F
return GL_RGBA;
default:
throw new UnsupportedOperationException();
}
}
public static int getTypeFromInternal(int internalFormat) {
switch(internalFormat) {
case _GL_R8:
case _GL_RG8:
case GL_RGB8:
case GL_RGBA8:
return GL_UNSIGNED_BYTE;
case 0x822D: // GL_R16F
case 0x822F: // GL_RG16F
case _GL_RGB16F:
case 0x881A: // GL_RGBA16F
return _GL_HALF_FLOAT;
case 0x822E: // GL_R32F
case 0x8230: // GL_RG32F
case 0x8815: // GL_RGB32F
case 0x8814: // GL_RGBA32F
return GL_FLOAT;
default:
throw new UnsupportedOperationException();
}
}
public static int trivializeInternalFormatToGLES20(int internalFormat) {
switch(internalFormat) {
case _GL_R8:
return GL_LUMINANCE;
case GL_RGB8:
return GL_RGB;
case GL_RGBA8:
return GL_RGBA;
default:
throw new UnsupportedOperationException();
}
}
}

View File

@ -0,0 +1,91 @@
package net.lax1dude.eaglercraft.v1_8.opengl;
import java.util.ArrayList;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.EagUtils;
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
/**
* Copyright (c) 2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
public class VSHInputLayoutParser {
public static class ShaderInput {
public final int index;
public final String type;
public final String name;
public ShaderInput(int index, String type, String name) {
this.index = index;
this.type = type;
this.name = name;
}
}
public static class ShaderLayoutParseException extends RuntimeException {
public ShaderLayoutParseException(String message, Throwable cause) {
super(message, cause);
}
public ShaderLayoutParseException(String message) {
super(message);
}
}
public static List<ShaderInput> getShaderInputs(String vshSource) {
int idx1 = vshSource.indexOf("EAGLER_VSH_LAYOUT_BEGIN()");
if(idx1 == -1) {
throw new ShaderLayoutParseException("Could not find \"EAGLER_VSH_LAYOUT_BEGIN()\" delimiter!");
}
int idx2 = vshSource.indexOf("EAGLER_VSH_LAYOUT_END()", idx1 + 25);
if(idx2 == -1) {
throw new ShaderLayoutParseException("Could not find \"EAGLER_VSH_LAYOUT_END()\" delimiter!");
}
List<String> lines = EagUtils.linesList(vshSource.substring(idx1 + 25, idx2));
List<ShaderInput> ret = new ArrayList<>();
for(int i = 0, l = lines.size(); i < l; ++i) {
String ln = lines.get(i);
ln = ln.trim();
if(ln.startsWith("EAGLER_IN(") && ln.endsWith(")")) {
String[] tokens = ln.substring(10, ln.length() - 1).split(",", 3);
if(tokens.length == 3) {
int idx;
try {
idx = Integer.parseInt(tokens[0].trim());
}catch(NumberFormatException ex) {
continue;
}
ret.add(new ShaderInput(idx, tokens[1].trim(), tokens[2].trim()));
}
}
}
return ret;
}
public static void applyLayout(IProgramGL program, List<ShaderInput> layout) {
for(int i = 0, l = layout.size(); i < l; ++i) {
ShaderInput itm = layout.get(i);
_wglBindAttribLocation(program, itm.index, itm.name);
}
}
}

View File

@ -8,7 +8,6 @@ import java.util.BitSet;
import java.util.Comparator;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformBufferFunctions;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.vector.Vector3f;
import net.minecraft.client.renderer.GLAllocation;
@ -121,7 +120,7 @@ public class WorldRenderer {
for (int k1 = ainteger[i1].intValue(); j1 != l1; k1 = ainteger[k1].intValue()) {
this.intBuffer.limit(k1 * l + l);
this.intBuffer.position(k1 * l);
IntBuffer intbuffer = this.intBuffer.slice();
IntBuffer intbuffer = this.intBuffer.duplicate();
this.intBuffer.limit(j1 * l + l);
this.intBuffer.position(j1 * l);
this.intBuffer.put(intbuffer);
@ -178,7 +177,10 @@ public class WorldRenderer {
*/
public void setVertexState(WorldRenderer.State state) {
this.grow(state.getRawBuffer().length);
PlatformBufferFunctions.put(this.intBuffer, 0, state.getRawBuffer());
int p = intBuffer.position();
this.intBuffer.position(0);
this.intBuffer.put(state.getRawBuffer());
this.intBuffer.position(p);
this.vertexCount = state.getVertexCount();
this.vertexFormat = state.getVertexFormat();
}
@ -339,7 +341,10 @@ public class WorldRenderer {
*/
public void addVertexData(int[] vertexData) {
this.grow(vertexData.length);
PlatformBufferFunctions.put(this.intBuffer, (this.vertexCount * this.vertexFormat.attribStride) >> 2, vertexData);
int p = this.intBuffer.position();
this.intBuffer.position((this.vertexCount * this.vertexFormat.attribStride) >> 2);
this.intBuffer.put(vertexData);
this.intBuffer.position(p);
this.vertexCount += vertexData.length / (this.vertexFormat.attribStride >> 2);
}

View File

@ -32,7 +32,7 @@ public class BlockVertexIDs implements IResourceManagerReloadListener {
private static final Logger logger = LogManager.getLogger("BlockVertexIDsCSV");
public static final Map<String,Integer> modelToID = new HashMap();
public static final Map<String,Integer> modelToID = new HashMap<>();
public static int builtin_water_still_vertex_id = 0;
public static int builtin_water_flow_vertex_id = 0;

View File

@ -103,7 +103,7 @@ public class CloudRenderWorker {
static void initialize() {
destroy();
cloudStartTimer = System.currentTimeMillis();
cloudStartTimer = EagRuntime.steadyTimeMillis();
cloudRenderProgress = 0;
cloudRenderPeriod = 500;
cloudRenderPhase = 0;
@ -168,7 +168,7 @@ public class CloudRenderWorker {
_wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
_wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
_wglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
byte[] cloudShapeTexture = EagRuntime.getResourceBytes("/assets/eagler/glsl/deferred/clouds_shapes.bmp");
byte[] cloudShapeTexture = EagRuntime.getRequiredResourceBytes("/assets/eagler/glsl/deferred/clouds_shapes.bmp");
cloudNoiseDatBuffer = EagRuntime.allocateByteBuffer(cloudShapeTexture.length);
cloudNoiseDatBuffer.put(cloudShapeTexture);
cloudNoiseDatBuffer.flip();
@ -207,7 +207,7 @@ public class CloudRenderWorker {
}
static void update() {
long millis = System.currentTimeMillis();
long millis = EagRuntime.steadyTimeMillis();
int cloudProgress = (int)(millis - cloudStartTimer);
int totalCloudSteps = 32 + 32 - 1;
int currentCloudStep = cloudProgress * totalCloudSteps / cloudRenderPeriod;
@ -268,7 +268,7 @@ public class CloudRenderWorker {
cloudColorB += (currentSunAngle.z - cloudColorB) * 0.1f;
_wglUniform3f(shader_clouds_sample.uniforms.u_sunColor3f, cloudColorR, cloudColorG, cloudColorB);
float cloudDensityTimer = (float)((System.currentTimeMillis() % 10000000l) * 0.001);
float cloudDensityTimer = (float)((EagRuntime.steadyTimeMillis() % 10000000l) * 0.001);
cloudDensityTimer += MathHelper.sin(cloudDensityTimer * 1.5f) * 1.5f;
float x = cloudDensityTimer * 0.004f;
float f1 = MathHelper.sin(x + 0.322f) * 0.544f + MathHelper.sin(x * 4.5f + 1.843f) * 0.69f + MathHelper.sin(x * 3.4f + 0.8f) * 0.6f + MathHelper.sin(x * 6.1f + 1.72f) * 0.7f;
@ -404,7 +404,7 @@ public class CloudRenderWorker {
if(b) {
cloudRenderProgress = 0;
cloudStartTimer = System.currentTimeMillis();
cloudStartTimer = EagRuntime.steadyTimeMillis();
cloudProgress = 0;
cloudRenderPhase = (cloudRenderPhase + 1) % 3;
}else {
@ -539,7 +539,7 @@ public class CloudRenderWorker {
}
private static void updateShape() {
long millis = System.currentTimeMillis();
long millis = EagRuntime.steadyTimeMillis();
float dt = (float)((millis - shapeUpdateTimer) * 0.001);
shapeUpdateTimer = millis;
if(millis > nextShapeAppearance) {

View File

@ -4,12 +4,12 @@ import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.opengl.DrawUtils;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.PipelineShaderGBufferDebugView;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.ScaledResolution;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
@ -249,7 +249,7 @@ public class DebugFramebufferView {
PipelineShaderGBufferDebugView dbg = pipeline.useDebugViewShader(18);
GlStateManager.setActiveTexture(GL_TEXTURE0);
GlStateManager.bindTexture3D(CloudRenderWorker.cloud3DSamplesTexture);
_wglUniform1f(_wglGetUniformLocation(dbg.program, "u_fuckU1f"), (float)((System.currentTimeMillis() % 5000l) / 5000.0));
_wglUniform1f(_wglGetUniformLocation(dbg.program, "u_fuckU1f"), (float)((EagRuntime.steadyTimeMillis() % 5000l) / 5000.0));
DrawUtils.drawStandardQuad2D();
})),
(new DebugFramebufferView("Clouds Back Buffer", (pipeline) -> {
@ -449,19 +449,18 @@ public class DebugFramebufferView {
GlStateManager.clear(GL_COLOR_BUFFER_BIT);
noData = true;
}
long millis = System.currentTimeMillis();
long millis = EagRuntime.steadyTimeMillis();
long elapsed = millis - debugViewNameTimer;
if(elapsed < 2000l || noData) {
GlStateManager.matrixMode(GL_PROJECTION);
GlStateManager.pushMatrix();
GlStateManager.matrixMode(GL_MODELVIEW);
GlStateManager.pushMatrix();
ScaledResolution scaledresolution = new ScaledResolution(mc);
int w = scaledresolution.getScaledWidth();
int w = mc.scaledResolution.getScaledWidth();
mc.entityRenderer.setupOverlayRendering();
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
int h = scaledresolution.getScaledHeight() / 2;
int h = mc.scaledResolution.getScaledHeight() / 2;
if(noData) {
String noDataTxt = "No Data";
@ -507,13 +506,13 @@ public class DebugFramebufferView {
public static void toggleDebugView() {
debugViewShown = !debugViewShown;
if(debugViewShown) {
debugViewNameTimer = System.currentTimeMillis();
debugViewNameTimer = EagRuntime.steadyTimeMillis();
}
}
public static void switchView(int dir) {
if(!debugViewShown) return;
debugViewNameTimer = System.currentTimeMillis();
debugViewNameTimer = EagRuntime.steadyTimeMillis();
currentDebugView += dir;
if(currentDebugView < 0) currentDebugView = views.size() - 1;
if(currentDebugView >= views.size()) currentDebugView = 0;

View File

@ -148,7 +148,7 @@ public class DeferredStateManager {
if(!cfg.is_rendering_dynamicLights || !cfg.shaderPackInfo.DYNAMIC_LIGHTS) {
return;
}
instance.loadLightSourceBucket(centerX, centerY, centerZ);
instance.bindLightSourceBucket(centerX, centerY, centerZ, 1);
}
}
@ -162,7 +162,7 @@ public class DeferredStateManager {
float posX = (float)((x + TileEntityRendererDispatcher.staticPlayerX) - (MathHelper.floor_double(TileEntityRendererDispatcher.staticPlayerX / 16.0) << 4));
float posY = (float)((y + TileEntityRendererDispatcher.staticPlayerY) - (MathHelper.floor_double(TileEntityRendererDispatcher.staticPlayerY / 16.0) << 4));
float posZ = (float)((z + TileEntityRendererDispatcher.staticPlayerZ) - (MathHelper.floor_double(TileEntityRendererDispatcher.staticPlayerZ / 16.0) << 4));
instance.loadLightSourceBucket((int)posX, (int)posY, (int)posZ);
instance.bindLightSourceBucket((int)posX, (int)posY, (int)posZ, 1);
}
}

View File

@ -1,5 +1,7 @@
package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
/**
* Copyright (c) 2023 lax1dude. All Rights Reserved.
*
@ -35,7 +37,7 @@ class DynamicLightInstance {
}
public void updateLight(double posX, double posY, double posZ, float red, float green, float blue) {
this.lastCacheHit = System.currentTimeMillis();
this.lastCacheHit = EagRuntime.steadyTimeMillis();
this.posX = posX;
this.posY = posY;
this.posZ = posZ;

View File

@ -6,6 +6,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
/**
* Copyright (c) 2023 lax1dude. All Rights Reserved.
*
@ -23,8 +25,8 @@ import java.util.Map;
*/
public class DynamicLightManager {
static final Map<String, DynamicLightInstance> lightRenderers = new HashMap();
static final List<DynamicLightInstance> lightRenderList = new LinkedList();
static final Map<String, DynamicLightInstance> lightRenderers = new HashMap<>();
static final List<DynamicLightInstance> lightRenderList = new LinkedList<>();
static long renderTimeout = 5000l;
static boolean isRenderLightsPass = false;
@ -51,7 +53,7 @@ public class DynamicLightManager {
}
static void updateTimers() {
long millis = System.currentTimeMillis();
long millis = EagRuntime.steadyTimeMillis();
if(millis - lastTick > 1000l) {
lastTick = millis;
Iterator<DynamicLightInstance> itr = lightRenderers.values().iterator();

View File

@ -71,7 +71,7 @@ import java.util.Iterator;
import java.util.List;
/**
* Copyright (c) 2023 lax1dude. All Rights Reserved.
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@ -112,6 +112,7 @@ public class EaglerDeferredPipeline {
public double currentRenderX = 0.0;
public double currentRenderY = 0.0;
public double currentRenderZ = 0.0;
public int currentRenderPosSerial = 0;
public IFramebufferGL gBufferFramebuffer = null;
@ -307,6 +308,7 @@ public class EaglerDeferredPipeline {
private ByteBuffer worldLightingDataCopyBuffer;
public IBufferGL buffer_chunkLightingData;
public IBufferGL buffer_chunkLightingDataZero;
private ByteBuffer chunkLightingDataCopyBuffer;
private boolean isChunkLightingEnabled = false;
public ListSerial<DynamicLightInstance> currentBoundLightSourceBucket;
@ -336,9 +338,20 @@ public class EaglerDeferredPipeline {
public static final Vector3f tmpVector4 = new Vector3f();
public final ListSerial<DynamicLightInstance>[] lightSourceBuckets;
private final int[] lightSourceBucketSerials;
private final int[] lightSourceRenderPosSerials;
public ListSerial<DynamicLightInstance> currentLightSourceBucket;
private int currentLightSourceBucketId = -1;
private int lightingBufferSliceLength = -1;
public static final int MAX_LIGHTS_PER_CHUNK = 12;
public static final int LIGHTING_BUFFER_LENGTH = 32 * MAX_LIGHTS_PER_CHUNK + 16;
private int uniformBufferOffsetAlignment = -1;
private int uboAlign(int offset) {
return MathHelper.ceiling_float_int((float)offset / (float)uniformBufferOffsetAlignment) * uniformBufferOffsetAlignment;
}
private final int lightSourceBucketsWidth;
private final int lightSourceBucketsHeight;
@ -372,13 +385,18 @@ public class EaglerDeferredPipeline {
this.lightSourceBucketsHeight = 3;
int cnt = 5 * 3 * 5;
this.lightSourceBuckets = new ListSerial[cnt];
this.lightSourceBucketSerials = new int[cnt];
this.lightSourceRenderPosSerials = new int[cnt];
for(int i = 0; i < cnt; ++i) {
this.lightSourceBuckets[i] = new ArrayListSerial(16);
this.lightSourceBuckets[i] = new ArrayListSerial<>(16);
this.lightSourceBucketSerials[i] = -1;
this.lightSourceRenderPosSerials[i] = -1;
}
}
public void rebuild(EaglerDeferredConfig config) {
destroy();
uniformBufferOffsetAlignment = EaglercraftGPU.getUniformBufferOffsetAlignment();
DeferredStateManager.doCheckErrors = EagRuntime.getConfiguration().isCheckShaderGLErrors();
DeferredStateManager.checkGLError("Pre: rebuild pipeline");
this.config = config;
@ -544,7 +562,7 @@ public class EaglerDeferredPipeline {
GlStateManager.bindTexture(ssaoNoiseTexture);
setNearest();
int noiseTexSize = 64, noiseTexLen = 16384;
byte[] noiseTexDat = EagRuntime.getResourceBytes("assets/eagler/glsl/deferred/ssao_noise.bmp");
byte[] noiseTexDat = EagRuntime.getRequiredResourceBytes("assets/eagler/glsl/deferred/ssao_noise.bmp");
if(noiseTexDat == null || noiseTexDat.length != noiseTexLen) {
noiseTexDat = new byte[noiseTexLen];
for(int i = 0; i < 4096; ++i) {
@ -592,7 +610,7 @@ public class EaglerDeferredPipeline {
GlStateManager.bindTexture(brdfTexture);
setLinear();
int brdfLutW = 64, brdfLutH = 64, brdfLutLen = 8192;
byte[] brdfLutDat = EagRuntime.getResourceBytes("assets/eagler/glsl/deferred/brdf_lut.bmp");
byte[] brdfLutDat = EagRuntime.getRequiredResourceBytes("assets/eagler/glsl/deferred/brdf_lut.bmp");
if(brdfLutDat == null || brdfLutDat.length != brdfLutLen) {
brdfLutDat = new byte[brdfLutLen];
for(int i = 0; i < 4096; ++i) {
@ -748,7 +766,9 @@ public class EaglerDeferredPipeline {
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
ByteBuffer copyBuffer = EagRuntime.allocateByteBuffer(262144);
int mip = 0;
try(DataInputStream dis = new DataInputStream(EagRuntime.getResourceStream("/assets/eagler/glsl/deferred/eagler_moon.bmp"))) {
try (DataInputStream dis = new DataInputStream(mc.getResourceManager()
.getResource(new ResourceLocation("eagler:glsl/deferred/eagler_moon.bmp")).getInputStream())) {
while(dis.read() == 'E') {
int w = dis.readShort();
int h = dis.readShort();
@ -873,7 +893,7 @@ public class EaglerDeferredPipeline {
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
_wglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
String realistic_water_noise_filename = "assets/eagler/glsl/deferred/realistic_water_noise.bmp";
byte[] bitmapBytes = EagRuntime.getResourceBytes(realistic_water_noise_filename);
byte[] bitmapBytes = EagRuntime.getRequiredResourceBytes(realistic_water_noise_filename);
try {
if(bitmapBytes.length != 32768) {
throw new IOException("File is length " + bitmapBytes.length + ", expected " + 32768);
@ -1008,15 +1028,22 @@ public class EaglerDeferredPipeline {
shader_lighting_point = PipelineShaderLightingPoint.compile(false);
shader_lighting_point.loadUniforms();
buffer_chunkLightingData = _wglGenBuffers();
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
int lightingDataLength = 8 * MAX_LIGHTS_PER_CHUNK + 4;
chunkLightingDataCopyBuffer = EagRuntime.allocateByteBuffer(lightingDataLength << 2);
for(int i = 0; i < lightingDataLength; ++i) {
lightingBufferSliceLength = uboAlign(LIGHTING_BUFFER_LENGTH);
chunkLightingDataCopyBuffer = EagRuntime.allocateByteBuffer(LIGHTING_BUFFER_LENGTH);
for(int i = 0; i < LIGHTING_BUFFER_LENGTH; i += 4) {
chunkLightingDataCopyBuffer.putInt(0);
}
chunkLightingDataCopyBuffer.flip();
_wglBufferData(_GL_UNIFORM_BUFFER, chunkLightingDataCopyBuffer, GL_DYNAMIC_DRAW);
buffer_chunkLightingData = _wglGenBuffers();
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
int cnt = lightSourceBucketsWidth * lightSourceBucketsHeight * lightSourceBucketsWidth;
_wglBufferData(_GL_UNIFORM_BUFFER, cnt * lightingBufferSliceLength, GL_DYNAMIC_DRAW);
buffer_chunkLightingDataZero = _wglGenBuffers();
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingDataZero);
_wglBufferData(_GL_UNIFORM_BUFFER, chunkLightingDataCopyBuffer, GL_STATIC_DRAW);
DeferredStateManager.checkGLError("Post: rebuild pipeline: dynamic lights");
}
@ -1042,6 +1069,16 @@ public class EaglerDeferredPipeline {
DeferredStateManager.checkGLError("Post: rebuild pipeline");
}
public void setRenderPosGlobal(double renderPosX, double renderPosY, double renderPosZ) {
if (renderPosX != currentRenderX || renderPosY != currentRenderY || renderPosZ != currentRenderZ
|| currentRenderPosSerial == 0) {
currentRenderX = renderPosX;
currentRenderY = renderPosY;
currentRenderZ = renderPosZ;
++currentRenderPosSerial;
}
}
public void updateReprojectionCoordinates(double worldX, double worldY, double worldZ) {
double distX = worldX - reprojectionOriginCoordinateX;
double distY = worldY - reprojectionOriginCoordinateY;
@ -1467,7 +1504,7 @@ public class EaglerDeferredPipeline {
float sunKelvin = 1500.0f + (2500.0f * Math.max(-currentSunAngle.y, 0.0f));
float fff = mc.theWorld.getRainStrength(partialTicks);
float ff2 = mc.theWorld.getThunderStrength(partialTicks);
long millis = System.currentTimeMillis();
long millis = EagRuntime.steadyTimeMillis();
int dim = Minecraft.getMinecraft().theWorld.provider.getDimensionId();
// ==================== UPDATE CLOUD RENDERER ===================== //
@ -2172,7 +2209,7 @@ public class EaglerDeferredPipeline {
GlStateManager.disableBlend();
}
public void loadLightSourceBucket(int relativeBlockX, int relativeBlockY, int relativeBlockZ) {
public void bindLightSourceBucket(int relativeBlockX, int relativeBlockY, int relativeBlockZ, int uboIndex) {
int hw = lightSourceBucketsWidth / 2;
int hh = lightSourceBucketsHeight / 2;
int bucketX = (relativeBlockX >> 4) + hw;
@ -2180,12 +2217,51 @@ public class EaglerDeferredPipeline {
int bucketZ = (relativeBlockZ >> 4) + hw;
if(bucketX >= 0 && bucketY >= 0 && bucketZ >= 0 && bucketX < lightSourceBucketsWidth
&& bucketY < lightSourceBucketsHeight && bucketZ < lightSourceBucketsWidth) {
currentLightSourceBucket = lightSourceBuckets[bucketY * lightSourceBucketsWidth * lightSourceBucketsWidth
+ bucketZ * lightSourceBucketsWidth + bucketX];
currentLightSourceBucketId = bucketY * lightSourceBucketsWidth * lightSourceBucketsWidth
+ bucketZ * lightSourceBucketsWidth + bucketX;
currentLightSourceBucket = lightSourceBuckets[currentLightSourceBucketId];
int ser = currentLightSourceBucket.getEaglerSerial();
int max = currentLightSourceBucket.size();
if(max > 0) {
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
int offset = currentLightSourceBucketId * lightingBufferSliceLength;
if (lightSourceBucketSerials[currentLightSourceBucketId] != ser
|| lightSourceRenderPosSerials[currentLightSourceBucketId] != currentRenderPosSerial) {
lightSourceBucketSerials[currentLightSourceBucketId] = ser;
lightSourceRenderPosSerials[currentLightSourceBucketId] = currentRenderPosSerial;
if(max > MAX_LIGHTS_PER_CHUNK) {
max = MAX_LIGHTS_PER_CHUNK;
}
chunkLightingDataCopyBuffer.clear();
chunkLightingDataCopyBuffer.putInt(max);
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
for(int i = 0; i < max; ++i) {
DynamicLightInstance dl = currentLightSourceBucket.get(i);
chunkLightingDataCopyBuffer.putFloat((float)(dl.posX - currentRenderX));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posY - currentRenderY));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posZ - currentRenderZ));
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putFloat(dl.red);
chunkLightingDataCopyBuffer.putFloat(dl.green);
chunkLightingDataCopyBuffer.putFloat(dl.blue);
chunkLightingDataCopyBuffer.putInt(0); //padding
}
chunkLightingDataCopyBuffer.flip();
_wglBufferSubData(_GL_UNIFORM_BUFFER, offset, chunkLightingDataCopyBuffer);
}
EaglercraftGPU.bindUniformBufferRange(uboIndex, buffer_chunkLightingData, offset, LIGHTING_BUFFER_LENGTH);
}else {
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingDataZero);
EaglercraftGPU.bindUniformBufferRange(uboIndex, buffer_chunkLightingDataZero, 0, LIGHTING_BUFFER_LENGTH);
}
}else {
currentLightSourceBucketId = -1;
currentLightSourceBucket = null;
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingDataZero);
EaglercraftGPU.bindUniformBufferRange(uboIndex, buffer_chunkLightingDataZero, 0, LIGHTING_BUFFER_LENGTH);
}
updateLightSourceUBO();
}
public ListSerial<DynamicLightInstance> getLightSourceBucketRelativeChunkCoords(int cx, int cy, int cz) {
@ -2319,65 +2395,10 @@ public class EaglerDeferredPipeline {
}
}
public void updateLightSourceUBO() {
if(currentLightSourceBucket == null) {
currentBoundLightSourceBucket = null;
if(isChunkLightingEnabled) {
isChunkLightingEnabled = false;
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
chunkLightingDataCopyBuffer.clear();
chunkLightingDataCopyBuffer.putInt(0);
chunkLightingDataCopyBuffer.flip();
_wglBufferSubData(_GL_UNIFORM_BUFFER, 0, chunkLightingDataCopyBuffer);
}
}else {
boolean isNew;
if(!isChunkLightingEnabled) {
isChunkLightingEnabled = true;
isNew = true;
}else {
isNew = currentLightSourceBucket != currentBoundLightSourceBucket;
}
currentBoundLightSourceBucket = currentLightSourceBucket;
if(isNew || currentBoundLightSourceBucket.eaglerCheck()) {
populateLightSourceUBOFromBucket(currentBoundLightSourceBucket);
currentBoundLightSourceBucket.eaglerResetCheck();
}
}
}
private static final Comparator<DynamicLightInstance> comparatorLightRadius = (l1, l2) -> {
return l1.radius < l2.radius ? 1 : -1;
};
private void populateLightSourceUBOFromBucket(List<DynamicLightInstance> lights) {
int max = lights.size();
if(max > MAX_LIGHTS_PER_CHUNK) {
max = MAX_LIGHTS_PER_CHUNK;
}
chunkLightingDataCopyBuffer.clear();
chunkLightingDataCopyBuffer.putInt(max);
if(max > 0) {
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
for(int i = 0; i < max; ++i) {
DynamicLightInstance dl = lights.get(i);
chunkLightingDataCopyBuffer.putFloat((float)(dl.posX - currentRenderX));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posY - currentRenderY));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posZ - currentRenderZ));
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putFloat(dl.red);
chunkLightingDataCopyBuffer.putFloat(dl.green);
chunkLightingDataCopyBuffer.putFloat(dl.blue);
chunkLightingDataCopyBuffer.putInt(0); //padding
}
}
chunkLightingDataCopyBuffer.flip();
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
_wglBufferSubData(_GL_UNIFORM_BUFFER, 0, chunkLightingDataCopyBuffer);
}
public void beginDrawEnvMap() {
DeferredStateManager.checkGLError("Pre: beginDrawEnvMap()");
GlStateManager.enableDepth();
@ -2797,7 +2818,7 @@ public class EaglerDeferredPipeline {
GlStateManager.bindTexture(realisticWaterNoiseMap);
shader_realistic_water_noise.useProgram();
float waveTimer = (float)((System.currentTimeMillis() % 600000l) * 0.001);
float waveTimer = (float)((EagRuntime.steadyTimeMillis() % 600000l) * 0.001);
_wglUniform4f(shader_realistic_water_noise.uniforms.u_waveTimer4f, waveTimer, 0.0f, 0.0f, 0.0f);
DrawUtils.drawStandardQuad2D();
@ -3147,7 +3168,7 @@ public class EaglerDeferredPipeline {
// ================ DOWNSCALE AND AVERAGE LUMA =============== //
long millis = System.currentTimeMillis();
long millis = EagRuntime.steadyTimeMillis();
if(millis - lastExposureUpdate > 33l) {
if(lumaAvgDownscaleFramebuffers.length == 0) {
_wglBindFramebuffer(_GL_FRAMEBUFFER, exposureBlendFramebuffer);
@ -3925,6 +3946,10 @@ public class EaglerDeferredPipeline {
_wglDeleteBuffers(buffer_chunkLightingData);
buffer_chunkLightingData = null;
}
if(buffer_chunkLightingDataZero != null) {
_wglDeleteBuffers(buffer_chunkLightingDataZero);
buffer_chunkLightingDataZero = null;
}
if(buffer_worldLightingData != null) {
_wglDeleteBuffers(buffer_worldLightingData);
buffer_worldLightingData = null;
@ -3939,8 +3964,11 @@ public class EaglerDeferredPipeline {
}
for(int i = 0; i < lightSourceBuckets.length; ++i) {
lightSourceBuckets[i].clear();
lightSourceBucketSerials[i] = -1;
lightSourceRenderPosSerials[i] = -1;
}
currentLightSourceBucket = null;
currentLightSourceBucketId = -1;
currentBoundLightSourceBucket = null;
isChunkLightingEnabled = false;
for(int i = 0; i < shader_gbuffer_debug_view.length; ++i) {
@ -3993,11 +4021,13 @@ public class EaglerDeferredPipeline {
}
public static final boolean isSupported() {
return EaglercraftGPU.checkHasHDRFramebufferSupportWithFilter();
return EaglercraftGPU.checkOpenGLESVersion() >= 300 && EaglercraftGPU.checkHasHDRFramebufferSupportWithFilter();
}
public static final String getReasonUnsupported() {
if(!EaglercraftGPU.checkHasHDRFramebufferSupportWithFilter()) {
if(EaglercraftGPU.checkOpenGLESVersion() < 300) {
return I18n.format("shaders.gui.unsupported.reason.oldOpenGLVersion");
}else if(!EaglercraftGPU.checkHasHDRFramebufferSupportWithFilter()) {
return I18n.format("shaders.gui.unsupported.reason.hdrFramebuffer");
}else {
return null;
@ -4015,7 +4045,7 @@ public class EaglerDeferredPipeline {
GlStateManager.pushMatrix();
GlStateManager.matrixMode(GL_MODELVIEW);
GlStateManager.pushMatrix();
ScaledResolution scaledresolution = new ScaledResolution(mc);
ScaledResolution scaledresolution = mc.scaledResolution;
int w = scaledresolution.getScaledWidth();
mc.entityRenderer.setupOverlayRendering();
GlStateManager.enableAlpha();

View File

@ -22,7 +22,7 @@ import java.util.List;
*/
public class ForwardRenderCallbackHandler {
public final List<ShadersRenderPassFuture> renderPassList = new ArrayList(1024);
public final List<ShadersRenderPassFuture> renderPassList = new ArrayList<>(1024);
public void push(ShadersRenderPassFuture f) {
renderPassList.add(f);

View File

@ -8,7 +8,6 @@ import java.io.DataInputStream;
import java.io.IOException;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.EaglerInputStream;
import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL;
import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
@ -20,6 +19,7 @@ import net.lax1dude.eaglercraft.v1_8.vector.Matrix3f;
import net.lax1dude.eaglercraft.v1_8.vector.Vector3f;
import net.minecraft.client.Minecraft;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
/**
* Copyright (c) 2023 lax1dude. All Rights Reserved.
@ -38,8 +38,8 @@ import net.minecraft.util.MathHelper;
*/
public class LensFlareMeshRenderer {
public static final String streaksTextureLocation ="assets/eagler/glsl/deferred/lens_streaks.bmp";
public static final String ghostsTextureLocation = "assets/eagler/glsl/deferred/lens_ghosts.bmp";
public static final ResourceLocation streaksTextureLocation = new ResourceLocation("eagler:glsl/deferred/lens_streaks.bmp");
public static final ResourceLocation ghostsTextureLocation = new ResourceLocation("eagler:glsl/deferred/lens_ghosts.bmp");
public static final int ghostsSpriteCount = 4;
static IBufferArrayGL streaksVertexArray = null;
@ -157,11 +157,8 @@ public class LensFlareMeshRenderer {
streaksTexture = GlStateManager.generateTexture();
GlStateManager.bindTexture(streaksTexture);
byte[] flareTex = EagRuntime.getResourceBytes(streaksTextureLocation);
if(flareTex == null) {
throw new RuntimeException("Could not locate: " + streaksTextureLocation);
}
try(DataInputStream dis = new DataInputStream(new EaglerInputStream(flareTex))) {
try (DataInputStream dis = new DataInputStream(
Minecraft.getMinecraft().getResourceManager().getResource(streaksTextureLocation).getInputStream())) {
loadFlareTexture(copyBuffer, dis);
}catch(IOException ex) {
EagRuntime.freeByteBuffer(copyBuffer);
@ -170,11 +167,8 @@ public class LensFlareMeshRenderer {
ghostsTexture = GlStateManager.generateTexture();
GlStateManager.bindTexture(ghostsTexture);
flareTex = EagRuntime.getResourceBytes(ghostsTextureLocation);
if(flareTex == null) {
throw new RuntimeException("Could not locate: " + ghostsTextureLocation);
}
try(DataInputStream dis = new DataInputStream(new EaglerInputStream(flareTex))) {
try (DataInputStream dis = new DataInputStream(
Minecraft.getMinecraft().getResourceManager().getResource(ghostsTextureLocation).getInputStream())) {
loadFlareTexture(copyBuffer, dis);
}catch(IOException ex) {
EagRuntime.freeByteBuffer(copyBuffer);

View File

@ -52,7 +52,7 @@ public class ShaderPackInfo {
vers = json.optString("vers", "Unknown");
author = json.optString("author", "Unknown");
apiVers = json.optInt("api_vers", -1);
supportedFeatures = new HashSet();
supportedFeatures = new HashSet<>();
JSONArray features = json.getJSONArray("features");
if(features.length() == 0) {
throw new JSONException("No supported features list has been defined for this shader pack!");

View File

@ -103,6 +103,11 @@ public class GuiShaderConfig extends GuiScreen {
listView.handleMouseInput();
}
public void handleTouchInput() throws IOException {
super.handleTouchInput();
listView.handleTouchInput();
}
protected void mouseClicked(int parInt1, int parInt2, int parInt3) {
super.mouseClicked(parInt1, parInt2, parInt3);
listView.mouseClicked(parInt1, parInt2, parInt3);

View File

@ -35,7 +35,7 @@ public class GuiShaderConfigList extends GuiListExtended {
private final GuiShaderConfig screen;
private final List<IGuiListEntry> list = new ArrayList();
private final List<IGuiListEntry> list = new ArrayList<>();
private static abstract class ShaderOption {
@ -56,7 +56,7 @@ public class GuiShaderConfigList extends GuiListExtended {
}
private static List<String> loadDescription(String key) {
List<String> ret = new ArrayList();
List<String> ret = new ArrayList<>();
String msg;
int i = 0;
while(true) {
@ -112,7 +112,7 @@ public class GuiShaderConfigList extends GuiListExtended {
this.list.add(new ListEntrySpacing());
this.list.add(new ListEntrySpacing());
this.list.add(new ListEntryHeader(I18n.format("shaders.gui.headerTier1")));
List<ShaderOption> opts = new ArrayList();
List<ShaderOption> opts = new ArrayList<>();
EaglerDeferredConfig conf = mcIn.gameSettings.deferredShaderConf;
if(conf.shaderPackInfo.WAVING_BLOCKS) {
opts.add(new ShaderOption(loadShaderLbl("WAVING_BLOCKS"), loadShaderDesc("WAVING_BLOCKS")) {
@ -550,6 +550,7 @@ public class GuiShaderConfigList extends GuiListExtended {
@Override
public boolean mousePressed(int var1, int var2, int var3, int var4, int var5, int var6) {
if(var4 != 0) return false;
if(this.button1 != null) {
if(this.button1.yPosition + 15 < bottom && this.button1.yPosition + 5 > top) {
if(this.button1.mousePressed(mc, var2, var3)) {
@ -610,7 +611,7 @@ public class GuiShaderConfigList extends GuiListExtended {
}
private void renderTooltip(int x, int y, int width, List<String> msg) {
ArrayList tooltipList = new ArrayList(msg.size() * 2);
List<String> tooltipList = new ArrayList<>(msg.size() * 2);
for(int i = 0, l = msg.size(); i < l; ++i) {
String s = msg.get(i);
if(s.length() > 0) {

View File

@ -32,7 +32,7 @@ public class PipelineShaderAccelParticleForward extends ShaderProgram<PipelineSh
ShaderSource.accel_particle_vsh, "COMPILE_FORWARD_VSH");
IShaderGL accelParticleFSH = null;
try {
List<String> lst = new ArrayList(2);
List<String> lst = new ArrayList<>(2);
if(dynamicLights) {
lst.add("COMPILE_DYNAMIC_LIGHTS");
}

View File

@ -30,7 +30,7 @@ public class PipelineShaderGBufferCombine extends ShaderProgram<PipelineShaderGB
public static PipelineShaderGBufferCombine compile(boolean ssao, boolean env, boolean ssr) throws ShaderException {
IShaderGL coreGBuffer = null;
List<String> compileFlags = new ArrayList(2);
List<String> compileFlags = new ArrayList<>(2);
if(ssao) {
compileFlags.add("COMPILE_GLOBAL_AMBIENT_OCCLUSION");
}

View File

@ -28,7 +28,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL;
public class PipelineShaderGBufferFog extends ShaderProgram<PipelineShaderGBufferFog.Uniforms> {
public static PipelineShaderGBufferFog compile(boolean linear, boolean atmosphere, boolean lightShafts) {
List<String> macros = new ArrayList(3);
List<String> macros = new ArrayList<>(3);
if(linear) {
macros.add("COMPILE_FOG_LINEAR");
}

View File

@ -29,7 +29,7 @@ public class PipelineShaderLightingPoint extends ShaderProgram<PipelineShaderLig
public static PipelineShaderLightingPoint compile(boolean shadows)
throws ShaderException {
List<String> compileFlags = new ArrayList(2);
List<String> compileFlags = new ArrayList<>(2);
if(shadows) {
compileFlags.add("COMPILE_PARABOLOID_SHADOW");
}

View File

@ -29,7 +29,7 @@ public class PipelineShaderLightingSun extends ShaderProgram<PipelineShaderLight
public static PipelineShaderLightingSun compile(int shadowsSun, boolean coloredShadows) throws ShaderException {
IShaderGL sunShader = null;
List<String> compileFlags = new ArrayList(1);
List<String> compileFlags = new ArrayList<>(1);
if(shadowsSun > 0) {
compileFlags.add("COMPILE_SUN_SHADOW");
}

View File

@ -28,7 +28,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL;
public class PipelineShaderPostExposureAvg extends ShaderProgram<PipelineShaderPostExposureAvg.Uniforms> {
public static PipelineShaderPostExposureAvg compile(boolean luma) throws ShaderException {
List<String> compileFlags = new ArrayList(1);
List<String> compileFlags = new ArrayList<>(1);
if(luma) {
compileFlags.add("CALCULATE_LUMINANCE");
}

View File

@ -28,7 +28,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL;
public class PipelineShaderReprojControl extends ShaderProgram<PipelineShaderReprojControl.Uniforms> {
public static PipelineShaderReprojControl compile(boolean ssao, boolean ssr) throws ShaderException {
List<String> compileFlags = new ArrayList(2);
List<String> compileFlags = new ArrayList<>(2);
if(ssao) {
compileFlags.add("COMPILE_REPROJECT_SSAO");
}

View File

@ -30,7 +30,7 @@ public class PipelineShaderShadowsSun extends ShaderProgram<PipelineShaderShadow
public static PipelineShaderShadowsSun compile(int shadowsSun, boolean shadowsSunSmooth, boolean coloredShadows)
throws ShaderException {
IShaderGL shadowShader = null;
List<String> compileFlags = new ArrayList(2);
List<String> compileFlags = new ArrayList<>(2);
if(shadowsSun == 0) {
throw new IllegalStateException("Enable shadows to compile this shader");
}

View File

@ -28,7 +28,7 @@ import java.util.List;
public class PipelineShaderSkyboxRender extends ShaderProgram<PipelineShaderSkyboxRender.Uniforms> {
public static PipelineShaderSkyboxRender compile(boolean paraboloid, boolean clouds) throws ShaderException {
List<String> compileFlags = new ArrayList();
List<String> compileFlags = new ArrayList<>();
if(paraboloid) {
compileFlags.add("COMPILE_PARABOLOID_SKY");
}

View File

@ -10,7 +10,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader;
import net.lax1dude.eaglercraft.v1_8.opengl.GLSLHeader;
import net.minecraft.util.ResourceLocation;
/**
@ -47,7 +47,7 @@ public class ShaderCompiler {
public static IShaderGL compileShader(String name, int stage, String filename, String source, List<String> compileFlags) throws ShaderCompileException {
logger.info("Compiling Shader: " + filename);
StringBuilder srcCat = new StringBuilder();
srcCat.append(FixedFunctionShader.FixedFunctionConstants.VERSION).append('\n');
srcCat.append(GLSLHeader.getHeader()).append('\n');
if(compileFlags != null && compileFlags.size() > 0) {
for(int i = 0, l = compileFlags.size(); i < l; ++i) {

View File

@ -97,7 +97,7 @@ public class ShaderSource {
public static final ResourceLocation accel_particle_dynamiclights_vsh = new ResourceLocation("eagler:glsl/dynamiclights/accel_particle_dynamiclights.vsh");
public static final ResourceLocation accel_particle_dynamiclights_fsh = new ResourceLocation("eagler:glsl/dynamiclights/accel_particle_dynamiclights.fsh");
private static final Map<ResourceLocation, String> sourceCache = new HashMap();
private static final Map<ResourceLocation, String> sourceCache = new HashMap<>();
private static boolean isHighP = false;

View File

@ -1,7 +1,6 @@
package net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
@ -121,7 +120,7 @@ public class EaglerTextureAtlasSpritePBR extends EaglerTextureAtlasSprite {
this.animationMetadata = meta;
} else {
ArrayList arraylist = Lists.newArrayList();
List<AnimationFrame> arraylist = Lists.newArrayList();
for (int l1 = 0; l1 < j1; ++l1) {
this.frameTextureDataPBR[0].add(getFrameTextureData(aint[0], k1, l, l1));

View File

@ -34,7 +34,7 @@ public class EmissiveItems implements IResourceManagerReloadListener {
private static final Logger logger = LogManager.getLogger("EmissiveItemsCSV");
private static final Map<String,float[]> entries = new HashMap();
private static final Map<String,float[]> entries = new HashMap<>();
public static float[] getItemEmission(ItemStack itemStack) {
return getItemEmission(itemStack.getItem(), itemStack.getItemDamage());

View File

@ -34,7 +34,7 @@ public class PBRMaterialConstants implements IResourceManagerReloadListener {
public static final Logger logger = LogManager.getLogger("PBRMaterialConstants");
public final ResourceLocation resourceLocation;
public final Map<String,Integer> spriteNameToMaterialConstants = new HashMap();
public final Map<String,Integer> spriteNameToMaterialConstants = new HashMap<>();
public int defaultMaterial = 0x00000A77;

View File

@ -34,14 +34,19 @@ import net.minecraft.util.MathHelper;
public class DynamicLightBucketLoader {
public IBufferGL buffer_chunkLightingData;
public IBufferGL buffer_chunkLightingDataZero;
private ByteBuffer chunkLightingDataCopyBuffer;
private boolean isChunkLightingEnabled = false;
public ListSerial<DynamicLightInstance> currentBoundLightSourceBucket;
public final ListSerial<DynamicLightInstance>[] lightSourceBuckets;
private final int[] lightSourceBucketsSerials;
private final int[] lightSourceRenderPosSerials;
public ListSerial<DynamicLightInstance> currentLightSourceBucket;
private int currentLightSourceBucketId = -1;
private int lightingBufferSliceLength = -1;
public static final int MAX_LIGHTS_PER_CHUNK = 12;
public static final int LIGHTING_BUFFER_LENGTH = 16 * MAX_LIGHTS_PER_CHUNK + 16;
private final int lightSourceBucketsWidth;
private final int lightSourceBucketsHeight;
@ -49,29 +54,42 @@ public class DynamicLightBucketLoader {
private double currentRenderX = 0.0;
private double currentRenderY = 0.0;
private double currentRenderZ = 0.0;
private int currentRenderPosSerial = 0;
public DynamicLightBucketLoader() {
this.lightSourceBucketsWidth = 5;
this.lightSourceBucketsHeight = 3;
int cnt = 5 * 3 * 5;
this.lightSourceBuckets = new ListSerial[cnt];
this.lightSourceBucketsSerials = new int[cnt];
this.lightSourceRenderPosSerials = new int[cnt];
}
public void initialize() {
destroy();
buffer_chunkLightingData = _wglGenBuffers();
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
int lightingDataLength = 4 * MAX_LIGHTS_PER_CHUNK + 4;
chunkLightingDataCopyBuffer = EagRuntime.allocateByteBuffer(lightingDataLength << 2);
for(int i = 0; i < lightingDataLength; ++i) {
int alignment = EaglercraftGPU.getUniformBufferOffsetAlignment();
lightingBufferSliceLength = MathHelper.ceiling_float_int((float)LIGHTING_BUFFER_LENGTH / (float)alignment) * alignment;
chunkLightingDataCopyBuffer = EagRuntime.allocateByteBuffer(LIGHTING_BUFFER_LENGTH);
for(int i = 0; i < LIGHTING_BUFFER_LENGTH; i += 4) {
chunkLightingDataCopyBuffer.putInt(0);
}
chunkLightingDataCopyBuffer.flip();
_wglBufferData(_GL_UNIFORM_BUFFER, chunkLightingDataCopyBuffer, GL_DYNAMIC_DRAW);
buffer_chunkLightingData = _wglGenBuffers();
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
int cnt = lightSourceBucketsWidth * lightSourceBucketsHeight * lightSourceBucketsWidth;
_wglBufferData(_GL_UNIFORM_BUFFER, cnt * lightingBufferSliceLength, GL_DYNAMIC_DRAW);
buffer_chunkLightingDataZero = _wglGenBuffers();
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingDataZero);
_wglBufferData(_GL_UNIFORM_BUFFER, chunkLightingDataCopyBuffer, GL_STATIC_DRAW);
for(int i = 0; i < this.lightSourceBuckets.length; ++i) {
this.lightSourceBuckets[i] = new ArrayListSerial(16);
this.lightSourceBuckets[i] = new ArrayListSerial<>(16);
this.lightSourceBucketsSerials[i] = -1;
this.lightSourceRenderPosSerials[i] = -1;
}
}
@ -81,7 +99,7 @@ public class DynamicLightBucketLoader {
}
}
public void loadLightSourceBucket(int relativeBlockX, int relativeBlockY, int relativeBlockZ) {
public void bindLightSourceBucket(int relativeBlockX, int relativeBlockY, int relativeBlockZ, int uboIndex) {
int hw = lightSourceBucketsWidth / 2;
int hh = lightSourceBucketsHeight / 2;
int bucketX = (relativeBlockX >> 4) + hw;
@ -89,12 +107,47 @@ public class DynamicLightBucketLoader {
int bucketZ = (relativeBlockZ >> 4) + hw;
if(bucketX >= 0 && bucketY >= 0 && bucketZ >= 0 && bucketX < lightSourceBucketsWidth
&& bucketY < lightSourceBucketsHeight && bucketZ < lightSourceBucketsWidth) {
currentLightSourceBucket = lightSourceBuckets[bucketY * lightSourceBucketsWidth * lightSourceBucketsWidth
+ bucketZ * lightSourceBucketsWidth + bucketX];
currentLightSourceBucketId = bucketY * lightSourceBucketsWidth * lightSourceBucketsWidth
+ bucketZ * lightSourceBucketsWidth + bucketX;
currentLightSourceBucket = lightSourceBuckets[currentLightSourceBucketId];
int ser = currentLightSourceBucket.getEaglerSerial();
int max = currentLightSourceBucket.size();
if(max > 0) {
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
int offset = currentLightSourceBucketId * lightingBufferSliceLength;
if (lightSourceBucketsSerials[currentLightSourceBucketId] != ser
|| lightSourceRenderPosSerials[currentLightSourceBucketId] != currentRenderPosSerial) {
lightSourceBucketsSerials[currentLightSourceBucketId] = ser;
lightSourceRenderPosSerials[currentLightSourceBucketId] = currentRenderPosSerial;
if(max > MAX_LIGHTS_PER_CHUNK) {
max = MAX_LIGHTS_PER_CHUNK;
}
chunkLightingDataCopyBuffer.clear();
chunkLightingDataCopyBuffer.putInt(max);
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
for(int i = 0; i < max; ++i) {
DynamicLightInstance dl = currentLightSourceBucket.get(i);
chunkLightingDataCopyBuffer.putFloat((float)(dl.posX - currentRenderX));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posY - currentRenderY));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posZ - currentRenderZ));
chunkLightingDataCopyBuffer.putFloat(dl.radius);
}
chunkLightingDataCopyBuffer.flip();
_wglBufferSubData(_GL_UNIFORM_BUFFER, offset, chunkLightingDataCopyBuffer);
}
EaglercraftGPU.bindUniformBufferRange(uboIndex, buffer_chunkLightingData, offset, LIGHTING_BUFFER_LENGTH);
}else {
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingDataZero);
EaglercraftGPU.bindUniformBufferRange(uboIndex, buffer_chunkLightingDataZero, 0, LIGHTING_BUFFER_LENGTH);
}
}else {
currentLightSourceBucketId = -1;
currentLightSourceBucket = null;
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingDataZero);
EaglercraftGPU.bindUniformBufferRange(uboIndex, buffer_chunkLightingDataZero, 0, LIGHTING_BUFFER_LENGTH);
}
updateLightSourceUBO();
}
public ListSerial<DynamicLightInstance> getLightSourceBucketRelativeChunkCoords(int cx, int cy, int cz) {
@ -188,8 +241,8 @@ public class DynamicLightBucketLoader {
}
public void truncateOverflowingBuffers() {
for(int i = 0; i < this.lightSourceBuckets.length; ++i) {
List<DynamicLightInstance> lst = this.lightSourceBuckets[i];
for(int i = 0; i < lightSourceBuckets.length; ++i) {
List<DynamicLightInstance> lst = lightSourceBuckets[i];
int k = lst.size();
if(k > MAX_LIGHTS_PER_CHUNK) {
lst.sort(comparatorLightRadius);
@ -200,74 +253,18 @@ public class DynamicLightBucketLoader {
}
}
public void updateLightSourceUBO() {
if(currentLightSourceBucket == null) {
currentBoundLightSourceBucket = null;
if(isChunkLightingEnabled) {
isChunkLightingEnabled = false;
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
chunkLightingDataCopyBuffer.clear();
chunkLightingDataCopyBuffer.putInt(0);
chunkLightingDataCopyBuffer.flip();
_wglBufferSubData(_GL_UNIFORM_BUFFER, 0, chunkLightingDataCopyBuffer);
}
}else {
boolean isNew;
if(!isChunkLightingEnabled) {
isChunkLightingEnabled = true;
isNew = true;
}else {
isNew = currentLightSourceBucket != currentBoundLightSourceBucket;
}
currentBoundLightSourceBucket = currentLightSourceBucket;
if(isNew || currentBoundLightSourceBucket.eaglerCheck()) {
populateLightSourceUBOFromBucket(currentBoundLightSourceBucket);
currentBoundLightSourceBucket.eaglerResetCheck();
}
}
}
private static final Comparator<DynamicLightInstance> comparatorLightRadius = (l1, l2) -> {
return l1.radius < l2.radius ? 1 : -1;
};
private void populateLightSourceUBOFromBucket(List<DynamicLightInstance> lights) {
int max = lights.size();
if(max > MAX_LIGHTS_PER_CHUNK) {
//tmpListLights.clear();
//tmpListLights.addAll(lights);
//lights = tmpListLights;
//lights.sort(comparatorLightRadius);
max = MAX_LIGHTS_PER_CHUNK;
}
chunkLightingDataCopyBuffer.clear();
chunkLightingDataCopyBuffer.putInt(max);
if(max > 0) {
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
for(int i = 0; i < max; ++i) {
DynamicLightInstance dl = lights.get(i);
chunkLightingDataCopyBuffer.putFloat((float)(dl.posX - currentRenderX));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posY - currentRenderY));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posZ - currentRenderZ));
chunkLightingDataCopyBuffer.putFloat(dl.radius);
}
}
chunkLightingDataCopyBuffer.flip();
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
_wglBufferSubData(_GL_UNIFORM_BUFFER, 0, chunkLightingDataCopyBuffer);
}
public void setRenderPos(double currentRenderX, double currentRenderY, double currentRenderZ) {
this.currentRenderX = currentRenderX;
this.currentRenderY = currentRenderY;
this.currentRenderZ = currentRenderZ;
}
public void bindUniformBuffer(int index) {
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
EaglercraftGPU.bindUniformBufferRange(index, buffer_chunkLightingData, 0, chunkLightingDataCopyBuffer.capacity());
if (this.currentRenderX != currentRenderX || this.currentRenderY != currentRenderY
|| this.currentRenderZ != currentRenderZ || this.currentRenderPosSerial == 0) {
this.currentRenderX = currentRenderX;
this.currentRenderY = currentRenderY;
this.currentRenderZ = currentRenderZ;
++this.currentRenderPosSerial;
}
}
public void destroy() {
@ -279,8 +276,16 @@ public class DynamicLightBucketLoader {
_wglDeleteBuffers(buffer_chunkLightingData);
buffer_chunkLightingData = null;
}
for(int i = 0; i < this.lightSourceBuckets.length; ++i) {
this.lightSourceBuckets[i] = null;
if(buffer_chunkLightingDataZero != null) {
_wglDeleteBuffers(buffer_chunkLightingDataZero);
buffer_chunkLightingDataZero = null;
}
for(int i = 0; i < lightSourceBuckets.length; ++i) {
lightSourceBuckets[i] = null;
lightSourceBucketsSerials[i] = -1;
lightSourceRenderPosSerials[i] = -1;
}
currentLightSourceBucket = null;
currentLightSourceBucketId = -1;
}
}

View File

@ -5,6 +5,8 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU;
import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionPipeline;
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f;
@ -30,10 +32,10 @@ import net.minecraft.util.MathHelper;
public class DynamicLightsStateManager {
static final DynamicLightsPipelineCompiler deferredExtPipeline = new DynamicLightsPipelineCompiler();
private static List<DynamicLightInstance> lightInstancePool = new ArrayList();
private static List<DynamicLightInstance> lightInstancePool = new ArrayList<>();
private static int instancePoolIndex = 0;
private static int maxListLengthTracker = 0;
static final List<DynamicLightInstance> lightRenderList = new LinkedList();
static final List<DynamicLightInstance> lightRenderList = new LinkedList<>();
static final Matrix4f inverseViewMatrix = new Matrix4f();
static int inverseViewMatrixSerial = 0;
static DynamicLightBucketLoader bucketLoader = null;
@ -45,7 +47,7 @@ public class DynamicLightsStateManager {
if(bucketLoader == null) {
bucketLoader = new DynamicLightBucketLoader();
bucketLoader.initialize();
bucketLoader.bindUniformBuffer(0);
bucketLoader.bindLightSourceBucket(-999, -999, -999, 0);
FixedFunctionPipeline.loadExtensionPipeline(deferredExtPipeline);
}
if(accelParticleRenderer == null) {
@ -89,7 +91,7 @@ public class DynamicLightsStateManager {
public static final void reportForwardRenderObjectPosition(int centerX, int centerY, int centerZ) {
if(bucketLoader != null) {
bucketLoader.loadLightSourceBucket(centerX, centerY, centerZ);
bucketLoader.bindLightSourceBucket(centerX, centerY, centerZ, 0);
}
}
@ -98,7 +100,7 @@ public class DynamicLightsStateManager {
float posX = (float)((x + TileEntityRendererDispatcher.staticPlayerX) - (MathHelper.floor_double(TileEntityRendererDispatcher.staticPlayerX / 16.0) << 4));
float posY = (float)((y + TileEntityRendererDispatcher.staticPlayerY) - (MathHelper.floor_double(TileEntityRendererDispatcher.staticPlayerY / 16.0) << 4));
float posZ = (float)((z + TileEntityRendererDispatcher.staticPlayerZ) - (MathHelper.floor_double(TileEntityRendererDispatcher.staticPlayerZ / 16.0) << 4));
bucketLoader.loadLightSourceBucket((int)posX, (int)posY, (int)posZ);
bucketLoader.bindLightSourceBucket((int)posX, (int)posY, (int)posZ, 0);
}
}
@ -152,11 +154,11 @@ public class DynamicLightsStateManager {
}
private static final void updateTimers() {
long millis = System.currentTimeMillis();
long millis = EagRuntime.steadyTimeMillis();
if(millis - lastTick > 5000l) {
lastTick = millis;
if(maxListLengthTracker < (lightInstancePool.size() >> 1)) {
List<DynamicLightInstance> newPool = new ArrayList(Math.max(maxListLengthTracker, 16));
List<DynamicLightInstance> newPool = new ArrayList<>(Math.max(maxListLengthTracker, 16));
for(int i = 0; i < maxListLengthTracker; ++i) {
newPool.add(lightInstancePool.get(i));
}
@ -167,11 +169,15 @@ public class DynamicLightsStateManager {
}
public static final void destroyAll() {
lightInstancePool = new ArrayList();
lightInstancePool = new ArrayList<>();
}
public static String getF3String() {
return "DynamicLightsTotal: " + lastTotal;
}
public static boolean isSupported() {
return EaglercraftGPU.checkOpenGLESVersion() >= 300;
}
}