mirror of
https://github.com/Eaglercraft-Archive/Eaglercraftx-1.8.8-src.git
synced 2025-06-28 02:48:14 -05:00
Update #51 - Protocol and FPS improvements, better workspace
This commit is contained in:
@ -21,6 +21,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Display;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IVertexArrayGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
|
||||
@ -78,6 +79,7 @@ public class DrawUtils {
|
||||
_wglCompileShader(vshLocal);
|
||||
|
||||
if(_wglGetShaderi(vshLocal, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
EaglercraftGPU.logger.error("Failed to compile GL_VERTEX_SHADER \"" + vertexShaderPath + "\"!");
|
||||
String log = _wglGetShaderInfoLog(vshLocal);
|
||||
if(log != null) {
|
||||
|
@ -47,6 +47,11 @@ public class EaglercraftGPU {
|
||||
return _wglGenBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invalidate(IBufferGL object) {
|
||||
// Don't bother
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void destroy(IBufferGL object) {
|
||||
_wglDeleteBuffers(object);
|
||||
@ -61,6 +66,11 @@ public class EaglercraftGPU {
|
||||
return _wglGenBuffers();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invalidate(IBufferGL object) {
|
||||
// Don't bother
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void destroy(IBufferGL object) {
|
||||
_wglDeleteBuffers(object);
|
||||
@ -68,13 +78,32 @@ public class EaglercraftGPU {
|
||||
|
||||
};
|
||||
|
||||
static final GLObjectRecycler<IVertexArrayGL> VAORecycler = new GLObjectRecycler<IVertexArrayGL>(128) {
|
||||
static final GLObjectRecycler<IVertexArrayGL> VAORecycler = new GLObjectRecycler<IVertexArrayGL>(256) {
|
||||
|
||||
@Override
|
||||
protected IVertexArrayGL create() {
|
||||
return _wglGenVertexArrays();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invalidate(IVertexArrayGL object) {
|
||||
int i;
|
||||
int bits = object.getBits();
|
||||
if(bits != 0) {
|
||||
IVertexArrayGL old = currentVertexArray;
|
||||
if (old != object) {
|
||||
_wglBindVertexArray(object);
|
||||
}
|
||||
do {
|
||||
i = Integer.numberOfTrailingZeros(bits);
|
||||
_wglDisableVertexAttribArray(i);
|
||||
} while((bits &= ~((i << 1) - 1)) != 0);
|
||||
if (old != object) {
|
||||
_wglBindVertexArray(old);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void destroy(IVertexArrayGL object) {
|
||||
_wglDeleteVertexArrays(object);
|
||||
@ -186,7 +215,7 @@ public class EaglercraftGPU {
|
||||
dp.bindQuad32 = false;
|
||||
}
|
||||
if(dp.vertexBuffer == null) {
|
||||
dp.vertexBuffer = _wglGenBuffers();
|
||||
dp.vertexBuffer = createGLArrayBuffer();
|
||||
}
|
||||
|
||||
bindVAOGLArrayBufferNow(dp.vertexBuffer);
|
||||
@ -250,7 +279,7 @@ public class EaglercraftGPU {
|
||||
bindGLVertexArray(dp.vertexArray);
|
||||
if(dp.mode == GL_QUADS) {
|
||||
int cnt = dp.count;
|
||||
if(cnt > 0xFFFF) {
|
||||
if(cnt > quad16MaxVertices) {
|
||||
if(!dp.bindQuad32) {
|
||||
dp.bindQuad16 = false;
|
||||
dp.bindQuad32 = true;
|
||||
@ -258,16 +287,14 @@ public class EaglercraftGPU {
|
||||
}else {
|
||||
attachQuad32EmulationBuffer(cnt, false);
|
||||
}
|
||||
p.drawElements(GL_TRIANGLES, cnt + (cnt >> 1), GL_UNSIGNED_INT, 0);
|
||||
p.drawElements(GL_TRIANGLES, (cnt >> 2) * 6, GL_UNSIGNED_INT, 0);
|
||||
}else {
|
||||
if(!dp.bindQuad16) {
|
||||
dp.bindQuad16 = true;
|
||||
dp.bindQuad32 = false;
|
||||
attachQuad16EmulationBuffer(cnt, true);
|
||||
}else {
|
||||
attachQuad16EmulationBuffer(cnt, false);
|
||||
attachQuad16EmulationBuffer(true);
|
||||
}
|
||||
p.drawElements(GL_TRIANGLES, cnt + (cnt >> 1), GL_UNSIGNED_SHORT, 0);
|
||||
p.drawElements(GL_TRIANGLES, (cnt >> 2) * 6, GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
}else {
|
||||
p.drawArrays(dp.mode, 0, dp.count);
|
||||
@ -436,7 +463,7 @@ public class EaglercraftGPU {
|
||||
}
|
||||
|
||||
public static void destroyGLArrayBuffer(IBufferGL buffer) {
|
||||
arrayBufferRecycler.destroy(buffer);
|
||||
arrayBufferRecycler.destroyObject(buffer);
|
||||
}
|
||||
|
||||
public static IBufferGL createGLElementArrayBuffer() {
|
||||
@ -444,7 +471,7 @@ public class EaglercraftGPU {
|
||||
}
|
||||
|
||||
public static void destroyGLElementArrayBuffer(IBufferGL buffer) {
|
||||
elementArrayBufferRecycler.destroy(buffer);
|
||||
elementArrayBufferRecycler.destroyObject(buffer);
|
||||
}
|
||||
|
||||
public static boolean areVAOsEmulated() {
|
||||
@ -461,7 +488,7 @@ public class EaglercraftGPU {
|
||||
|
||||
public static void destroyGLVertexArray(IVertexArrayGL buffer) {
|
||||
if(!emulatedVAOs) {
|
||||
VAORecycler.destroy(buffer);
|
||||
VAORecycler.destroyObject(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -694,7 +721,7 @@ public class EaglercraftGPU {
|
||||
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_VERTEX_ARRAY = 8;
|
||||
public static final int CLEAR_BINDING_ARRAY_BUFFER = 16;
|
||||
public static final int CLEAR_BINDING_SHADER_PROGRAM = 32;
|
||||
|
||||
@ -712,7 +739,7 @@ public class EaglercraftGPU {
|
||||
GlStateManager.activeTexture = 0;
|
||||
_wglActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
if((mask & CLEAR_BINDING_BUFFER_ARRAY) != 0) {
|
||||
if((mask & CLEAR_BINDING_VERTEX_ARRAY) != 0) {
|
||||
currentVertexArray = null;
|
||||
}
|
||||
if((mask & CLEAR_BINDING_ARRAY_BUFFER) != 0) {
|
||||
@ -757,11 +784,11 @@ public class EaglercraftGPU {
|
||||
private static long lastRecyclerFlush = 0l;
|
||||
|
||||
public static void optimize() {
|
||||
FixedFunctionPipeline.optimize();
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
if(millis - lastRecyclerFlush > 120000l) {
|
||||
lastRecyclerFlush = millis;
|
||||
arrayBufferRecycler.compact();
|
||||
elementArrayBufferRecycler.compact();
|
||||
VAORecycler.compact();
|
||||
}
|
||||
}
|
||||
@ -778,34 +805,21 @@ public class EaglercraftGPU {
|
||||
lastRender.update().drawDirectArrays(lastMode, 0, lastCount);
|
||||
}
|
||||
|
||||
public static final int quad16MaxVertices = 65536;
|
||||
|
||||
private static IBufferGL quad16EmulationBuffer = null;
|
||||
private static int quad16EmulationBufferSize = 0;
|
||||
|
||||
private static IBufferGL quad32EmulationBuffer = null;
|
||||
private static int quad32EmulationBufferSize = 0;
|
||||
|
||||
public static void attachQuad16EmulationBuffer(int vertexCount, boolean bind) {
|
||||
public static void attachQuad16EmulationBuffer(boolean bind) {
|
||||
IBufferGL buf = quad16EmulationBuffer;
|
||||
if(buf == null) {
|
||||
quad16EmulationBuffer = buf = _wglGenBuffers();
|
||||
int newSize = quad16EmulationBufferSize = (vertexCount & 0xFFFFF000) + 0x2000;
|
||||
if(newSize > 0xFFFF) {
|
||||
newSize = 0xFFFF;
|
||||
}
|
||||
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
|
||||
resizeQuad16EmulationBuffer(newSize >> 2);
|
||||
}else {
|
||||
int cnt = quad16EmulationBufferSize;
|
||||
if(cnt < vertexCount) {
|
||||
int newSize = quad16EmulationBufferSize = (vertexCount & 0xFFFFF000) + 0x2000;
|
||||
if(newSize > 0xFFFF) {
|
||||
newSize = 0xFFFF;
|
||||
}
|
||||
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
|
||||
resizeQuad16EmulationBuffer(newSize >> 2);
|
||||
}else if(bind) {
|
||||
EaglercraftGPU.bindVAOGLElementArrayBuffer(buf);
|
||||
}
|
||||
resizeQuad16EmulationBuffer(quad16MaxVertices >> 2);
|
||||
}else if(bind) {
|
||||
EaglercraftGPU.bindVAOGLElementArrayBuffer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -813,13 +827,13 @@ public class EaglercraftGPU {
|
||||
IBufferGL buf = quad32EmulationBuffer;
|
||||
if(buf == null) {
|
||||
quad32EmulationBuffer = buf = _wglGenBuffers();
|
||||
int newSize = quad32EmulationBufferSize = (vertexCount & 0xFFFFC000) + 0x8000;
|
||||
int newSize = quad32EmulationBufferSize = (vertexCount + 0xFFFF) & 0xFFFF0000;
|
||||
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
|
||||
resizeQuad32EmulationBuffer(newSize >> 2);
|
||||
}else {
|
||||
int cnt = quad32EmulationBufferSize;
|
||||
if(cnt < vertexCount) {
|
||||
int newSize = quad32EmulationBufferSize = (vertexCount & 0xFFFFC000) + 0x8000;
|
||||
int newSize = quad32EmulationBufferSize = (vertexCount + 0xFFFF) & 0xFFFF0000;
|
||||
EaglercraftGPU.bindVAOGLElementArrayBufferNow(buf);
|
||||
resizeQuad32EmulationBuffer(newSize >> 2);
|
||||
}else if(bind) {
|
||||
|
@ -26,6 +26,9 @@ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
|
||||
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Display;
|
||||
|
||||
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
@ -41,8 +44,9 @@ public class EffectPipelineFXAA {
|
||||
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 final int _GL_DEPTH_STENCIL_ATTACHMENT = 0x821A;
|
||||
private static final int _GL_DEPTH_STENCIL = 0x84F9;
|
||||
|
||||
private static IProgramGL shaderProgram = null;
|
||||
private static IUniformGL u_screenSize2f = null;
|
||||
@ -63,6 +67,7 @@ public class EffectPipelineFXAA {
|
||||
_wglCompileShader(frag);
|
||||
|
||||
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
logger.error("Failed to compile GL_FRAGMENT_SHADER \"" + fragmentShaderPath + "\" for EffectPipelineFXAA!");
|
||||
String log = _wglGetShaderInfoLog(frag);
|
||||
if(log != null) {
|
||||
@ -91,6 +96,7 @@ public class EffectPipelineFXAA {
|
||||
_wglDeleteShader(frag);
|
||||
|
||||
if(_wglGetProgrami(shaderProgram, GL_LINK_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
logger.error("Failed to link shader program for EffectPipelineFXAA!");
|
||||
String log = _wglGetProgramInfoLog(shaderProgram);
|
||||
if(log != null) {
|
||||
@ -121,8 +127,11 @@ public class EffectPipelineFXAA {
|
||||
_wglBindRenderbuffer(_GL_RENDERBUFFER, framebufferDepth);
|
||||
|
||||
_wglBindFramebuffer(_GL_FRAMEBUFFER, framebuffer);
|
||||
_wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, EaglercraftGPU.getNativeTexture(framebufferColor), 0);
|
||||
_wglFramebufferRenderbuffer(_GL_FRAMEBUFFER, _GL_DEPTH_ATTACHMENT, _GL_RENDERBUFFER, framebufferDepth);
|
||||
_wglFramebufferTexture2D(_GL_FRAMEBUFFER, _GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
EaglercraftGPU.getNativeTexture(framebufferColor), 0);
|
||||
_wglFramebufferRenderbuffer(_GL_FRAMEBUFFER,
|
||||
EaglercraftGPU.checkOpenGLESVersion() == 200 ? _GL_DEPTH_STENCIL_ATTACHMENT : _GL_DEPTH_ATTACHMENT,
|
||||
_GL_RENDERBUFFER, framebufferDepth);
|
||||
|
||||
_wglBindFramebuffer(_GL_FRAMEBUFFER, null);
|
||||
}
|
||||
@ -136,7 +145,8 @@ public class EffectPipelineFXAA {
|
||||
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, EaglercraftGPU.checkOpenGLESVersion() == 200 ? _GL_DEPTH_COMPONENT16 : _GL_DEPTH_COMPONENT32F, width, height);
|
||||
_wglRenderbufferStorage(_GL_RENDERBUFFER, EaglercraftGPU.checkOpenGLESVersion() == 200 ? _GL_DEPTH_STENCIL
|
||||
: _GL_DEPTH_COMPONENT32F, width, height);
|
||||
}
|
||||
|
||||
_wglBindFramebuffer(_GL_FRAMEBUFFER, framebuffer);
|
||||
|
@ -24,7 +24,7 @@ import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Display;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IVertexArrayGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
|
||||
@ -153,7 +153,7 @@ public class FixedFunctionPipeline {
|
||||
EaglercraftGPU.bindGLShaderProgram(shaderProgram);
|
||||
if(mode == GL_QUADS) {
|
||||
StreamBufferInstance sb = currentVertexArray;
|
||||
if(count > 0xFFFF) {
|
||||
if(count > EaglercraftGPU.quad16MaxVertices) {
|
||||
if(!sb.bindQuad32) {
|
||||
sb.bindQuad16 = false;
|
||||
sb.bindQuad32 = true;
|
||||
@ -161,18 +161,14 @@ public class FixedFunctionPipeline {
|
||||
}else {
|
||||
EaglercraftGPU.attachQuad32EmulationBuffer(count, false);
|
||||
}
|
||||
EaglercraftGPU.drawElements(GL_TRIANGLES, count + (count >> 1),
|
||||
GL_UNSIGNED_INT, 0);
|
||||
EaglercraftGPU.drawElements(GL_TRIANGLES, (count >> 2) * 6, GL_UNSIGNED_INT, 0);
|
||||
}else {
|
||||
if(!sb.bindQuad16) {
|
||||
sb.bindQuad16 = true;
|
||||
sb.bindQuad32 = false;
|
||||
EaglercraftGPU.attachQuad16EmulationBuffer(count, true);
|
||||
}else {
|
||||
EaglercraftGPU.attachQuad16EmulationBuffer(count, false);
|
||||
EaglercraftGPU.attachQuad16EmulationBuffer(true);
|
||||
}
|
||||
EaglercraftGPU.drawElements(GL_TRIANGLES, count + (count >> 1),
|
||||
GL_UNSIGNED_SHORT, 0);
|
||||
EaglercraftGPU.drawElements(GL_TRIANGLES, (count >> 2) * 6, GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
}else {
|
||||
EaglercraftGPU.drawArrays(mode, offset, count);
|
||||
@ -291,6 +287,7 @@ public class FixedFunctionPipeline {
|
||||
_wglCompileShader(vsh);
|
||||
|
||||
if(_wglGetShaderi(vsh, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
LOGGER.error("Failed to compile GL_VERTEX_SHADER for state {} !", (visualizeBits(coreBits) + (enableExt && extBits != 0 ? " ext " + visualizeBits(extBits) : "")));
|
||||
String log = _wglGetShaderInfoLog(vsh);
|
||||
if(log != null) {
|
||||
@ -309,6 +306,7 @@ public class FixedFunctionPipeline {
|
||||
_wglCompileShader(fsh);
|
||||
|
||||
if(_wglGetShaderi(fsh, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
LOGGER.error("Failed to compile GL_FRAGMENT_SHADER for state {} !", (visualizeBits(coreBits) + (enableExt && extBits != 0 ? " ext " + visualizeBits(extBits) : "")));
|
||||
String log = _wglGetShaderInfoLog(fsh);
|
||||
if(log != null) {
|
||||
@ -563,6 +561,7 @@ public class FixedFunctionPipeline {
|
||||
_wglLinkProgram(compiledProg);
|
||||
|
||||
if(_wglGetProgrami(compiledProg, GL_LINK_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
LOGGER.error("Program could not be linked for state {} !", (visualizeBits(bits) + (extensionProvider != null && extBits != 0 ? " ext " + visualizeBits(extBits) : "")));
|
||||
String log = _wglGetProgramInfoLog(compiledProg);
|
||||
if(log != null) {
|
||||
@ -574,8 +573,7 @@ public class FixedFunctionPipeline {
|
||||
throw new IllegalStateException("Program could not be linked!");
|
||||
}
|
||||
|
||||
streamBuffer = new StreamBuffer(FixedFunctionShader.initialSize, FixedFunctionShader.initialCount,
|
||||
FixedFunctionShader.maxCount, (vertexArray, vertexBuffer) -> {
|
||||
streamBuffer = new StreamBuffer((vertexArray, vertexBuffer) -> {
|
||||
EaglercraftGPU.bindGLVertexArray(vertexArray);
|
||||
EaglercraftGPU.bindVAOGLArrayBuffer(vertexBuffer);
|
||||
|
||||
@ -1063,12 +1061,6 @@ public class FixedFunctionPipeline {
|
||||
return this;
|
||||
}
|
||||
|
||||
static void optimize() {
|
||||
for(int i = 0, l = pipelineListTracker.size(); i < l; ++i) {
|
||||
pipelineListTracker.get(i).streamBuffer.optimize();
|
||||
}
|
||||
}
|
||||
|
||||
public static void flushCache() {
|
||||
shaderSourceCacheVSH = null;
|
||||
shaderSourceCacheFSH = null;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
@ -18,10 +18,6 @@ package net.lax1dude.eaglercraft.v1_8.opengl;
|
||||
|
||||
public class FixedFunctionShader {
|
||||
|
||||
public static final int initialSize = 0x8000;
|
||||
public static final int initialCount = 3;
|
||||
public static final int maxCount = 8;
|
||||
|
||||
public class FixedFunctionState {
|
||||
|
||||
public static final int fixedFunctionStatesCount = 12;
|
||||
|
@ -40,6 +40,7 @@ public abstract class GLObjectRecycler<T> {
|
||||
}
|
||||
|
||||
public void destroyObject(T obj) {
|
||||
invalidate(obj);
|
||||
deletedObjects.addLast(obj);
|
||||
}
|
||||
|
||||
@ -51,6 +52,8 @@ public abstract class GLObjectRecycler<T> {
|
||||
|
||||
protected abstract T create();
|
||||
|
||||
protected abstract void invalidate(T object);
|
||||
|
||||
protected abstract void destroy(T object);
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ 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 net.lax1dude.eaglercraft.v1_8.Display;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IVertexArrayGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
|
||||
@ -91,6 +92,7 @@ public class InstancedFontRenderer {
|
||||
_wglCompileShader(vert);
|
||||
|
||||
if(_wglGetShaderi(vert, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
logger.error("Failed to compile GL_VERTEX_SHADER \"" + vertexShaderPath + "\" for InstancedFontRenderer!");
|
||||
String log = _wglGetShaderInfoLog(vert);
|
||||
if(log != null) {
|
||||
@ -106,6 +108,7 @@ public class InstancedFontRenderer {
|
||||
_wglCompileShader(frag);
|
||||
|
||||
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
logger.error("Failed to compile GL_FRAGMENT_SHADER \"" + fragmentShaderPath + "\" for InstancedFontRenderer!");
|
||||
String log = _wglGetShaderInfoLog(frag);
|
||||
if(log != null) {
|
||||
@ -135,6 +138,7 @@ public class InstancedFontRenderer {
|
||||
_wglDeleteShader(frag);
|
||||
|
||||
if(_wglGetProgrami(shaderProgram, GL_LINK_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
logger.error("Failed to link shader program for InstancedFontRenderer!");
|
||||
String log = _wglGetProgramInfoLog(shaderProgram);
|
||||
if(log != null) {
|
||||
@ -203,7 +207,7 @@ public class InstancedFontRenderer {
|
||||
EaglercraftGPU.vertexAttribDivisor(0, 0);
|
||||
|
||||
EaglercraftGPU.bindVAOGLArrayBufferNow(instancesBuffer);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, fontDataBuffer.remaining(), GL_STREAM_DRAW);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, fontDataBuffer.capacity(), GL_STREAM_DRAW);
|
||||
|
||||
EaglercraftGPU.enableVertexAttribArray(1);
|
||||
EaglercraftGPU.vertexAttribPointer(1, 2, GL_SHORT, false, 10, 0);
|
||||
@ -377,6 +381,7 @@ public class InstancedFontRenderer {
|
||||
int l = fontDataBuffer.limit();
|
||||
|
||||
fontDataBuffer.flip();
|
||||
_wglBufferData(GL_ARRAY_BUFFER, fontDataBuffer.capacity(), GL_STREAM_DRAW);
|
||||
_wglBufferSubData(GL_ARRAY_BUFFER, 0, fontDataBuffer);
|
||||
|
||||
fontDataBuffer.position(p);
|
||||
@ -390,6 +395,7 @@ public class InstancedFontRenderer {
|
||||
int l = fontBoldDataBuffer.limit();
|
||||
|
||||
fontBoldDataBuffer.flip();
|
||||
_wglBufferData(GL_ARRAY_BUFFER, fontBoldDataBuffer.capacity(), GL_STREAM_DRAW);
|
||||
_wglBufferSubData(GL_ARRAY_BUFFER, 0, fontBoldDataBuffer);
|
||||
|
||||
fontBoldDataBuffer.position(p);
|
||||
|
@ -19,6 +19,7 @@ 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 net.lax1dude.eaglercraft.v1_8.Display;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IVertexArrayGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
|
||||
@ -92,6 +93,7 @@ public class InstancedParticleRenderer {
|
||||
_wglCompileShader(vert);
|
||||
|
||||
if(_wglGetShaderi(vert, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
logger.error("Failed to compile GL_VERTEX_SHADER \"" + vertexShaderPath + "\" for InstancedParticleRenderer!");
|
||||
String log = _wglGetShaderInfoLog(vert);
|
||||
if(log != null) {
|
||||
@ -107,6 +109,7 @@ public class InstancedParticleRenderer {
|
||||
_wglCompileShader(frag);
|
||||
|
||||
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
logger.error("Failed to compile GL_FRAGMENT_SHADER \"" + fragmentShaderPath + "\" for InstancedParticleRenderer!");
|
||||
String log = _wglGetShaderInfoLog(frag);
|
||||
if(log != null) {
|
||||
@ -136,6 +139,7 @@ public class InstancedParticleRenderer {
|
||||
_wglDeleteShader(frag);
|
||||
|
||||
if(_wglGetProgrami(shaderProgram, GL_LINK_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
logger.error("Failed to link shader program for InstancedParticleRenderer!");
|
||||
String log = _wglGetProgramInfoLog(shaderProgram);
|
||||
if(log != null) {
|
||||
@ -184,7 +188,7 @@ public class InstancedParticleRenderer {
|
||||
EaglercraftGPU.vertexAttribDivisor(0, 0);
|
||||
|
||||
EaglercraftGPU.bindVAOGLArrayBufferNow(instancesBuffer);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.remaining(), GL_STREAM_DRAW);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
|
||||
|
||||
EaglercraftGPU.enableVertexAttribArray(1);
|
||||
EaglercraftGPU.vertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0);
|
||||
@ -311,6 +315,7 @@ public class InstancedParticleRenderer {
|
||||
int l = particleBuffer.limit();
|
||||
|
||||
particleBuffer.flip();
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
|
||||
_wglBufferSubData(GL_ARRAY_BUFFER, 0, particleBuffer);
|
||||
|
||||
particleBuffer.position(p);
|
||||
|
@ -223,4 +223,17 @@ class SoftGLVertexArray implements IVertexArrayGL {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBits() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBit(int bit) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetBit(int bit) {
|
||||
}
|
||||
|
||||
}
|
@ -22,6 +22,7 @@ import java.util.List;
|
||||
|
||||
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Display;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
|
||||
@ -78,6 +79,7 @@ public class SpriteLevelMixer {
|
||||
_wglCompileShader(frag);
|
||||
|
||||
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
LOGGER.error("Failed to compile GL_FRAGMENT_SHADER \"" + fragmentShaderPath + "\" for SpriteLevelMixer!");
|
||||
String log = _wglGetShaderInfoLog(frag);
|
||||
if(log != null) {
|
||||
@ -106,6 +108,7 @@ public class SpriteLevelMixer {
|
||||
_wglDeleteShader(frag);
|
||||
|
||||
if(_wglGetProgrami(shaderProgram, GL_LINK_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
LOGGER.error("Failed to link shader program for SpriteLevelMixer!");
|
||||
String log = _wglGetProgramInfoLog(shaderProgram);
|
||||
if(log != null) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
* Copyright (c) 2023-2025 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
|
||||
@ -24,11 +24,7 @@ import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
|
||||
|
||||
public class StreamBuffer {
|
||||
|
||||
public static final int poolSize = 16;
|
||||
|
||||
public final int initialSize;
|
||||
public final int initialCount;
|
||||
public final int maxCount;
|
||||
public static final int poolSize = 4;
|
||||
|
||||
protected static final PoolInstance[] pool = new PoolInstance[poolSize];
|
||||
protected static int poolBufferID = 0;
|
||||
@ -55,21 +51,23 @@ public class StreamBuffer {
|
||||
}
|
||||
|
||||
private static void resizeInstance(PoolInstance instance, int requiredMemory) {
|
||||
if(instance.vertexBuffer == null) {
|
||||
instance.vertexBuffer = _wglGenBuffers();
|
||||
IBufferGL buffer = instance.vertexBuffer;
|
||||
if (buffer == null) {
|
||||
buffer = _wglGenBuffers();
|
||||
instance.vertexBuffer = buffer;
|
||||
}
|
||||
if(instance.vertexBufferSize < requiredMemory) {
|
||||
int newSize = (requiredMemory & 0xFFFFF000) + 0x2000;
|
||||
EaglercraftGPU.bindGLArrayBuffer(instance.vertexBuffer);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, newSize, GL_STREAM_DRAW);
|
||||
int newSize = instance.vertexBufferSize;
|
||||
if (newSize < requiredMemory) {
|
||||
newSize = (requiredMemory + 0xFFFF) & 0xFFFF0000;
|
||||
instance.vertexBufferSize = newSize;
|
||||
}
|
||||
EaglercraftGPU.bindGLArrayBuffer(buffer);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, newSize, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
protected StreamBufferInstance[] buffers;
|
||||
|
||||
protected int currentBufferId = 0;
|
||||
protected int overflowCounter = 0;
|
||||
|
||||
protected final IStreamBufferInitializer initializer;
|
||||
|
||||
@ -95,19 +93,20 @@ public class StreamBuffer {
|
||||
void initialize(IVertexArrayGL vertexArray, IBufferGL vertexBuffer);
|
||||
}
|
||||
|
||||
public StreamBuffer(int initialSize, int initialCount, int maxCount, IStreamBufferInitializer initializer) {
|
||||
if(maxCount > poolSize) {
|
||||
maxCount = poolSize;
|
||||
public StreamBuffer(IStreamBufferInitializer initializer) {
|
||||
this(poolSize, initializer);
|
||||
}
|
||||
|
||||
public StreamBuffer(int count, IStreamBufferInitializer initializer) {
|
||||
if(count > poolSize) {
|
||||
count = poolSize;
|
||||
}
|
||||
this.buffers = new StreamBufferInstance[initialCount];
|
||||
this.buffers = new StreamBufferInstance[count];
|
||||
for(int i = 0; i < this.buffers.length; ++i) {
|
||||
StreamBufferInstance j = new StreamBufferInstance();
|
||||
j.poolInstance = fillPoolInstance();
|
||||
this.buffers[i] = j;
|
||||
}
|
||||
this.initialSize = initialSize;
|
||||
this.initialCount = initialCount;
|
||||
this.maxCount = maxCount;
|
||||
this.initializer = initializer;
|
||||
}
|
||||
|
||||
@ -121,67 +120,6 @@ public class StreamBuffer {
|
||||
return next;
|
||||
}
|
||||
|
||||
public void optimize() {
|
||||
overflowCounter += currentBufferId - buffers.length;
|
||||
if(overflowCounter < -25) {
|
||||
int newCount = buffers.length - 1 + ((overflowCounter + 25) / 5);
|
||||
if(newCount < initialCount) {
|
||||
newCount = initialCount;
|
||||
}
|
||||
if(newCount < buffers.length) {
|
||||
StreamBufferInstance[] newArray = new StreamBufferInstance[newCount];
|
||||
for(int i = 0; i < buffers.length; ++i) {
|
||||
if(i < newArray.length) {
|
||||
newArray[i] = buffers[i];
|
||||
}else {
|
||||
if(buffers[i].vertexArray != null) {
|
||||
EaglercraftGPU.destroyGLVertexArray(buffers[i].vertexArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
buffers = newArray;
|
||||
refill();
|
||||
}
|
||||
overflowCounter = 0;
|
||||
}else if(overflowCounter > 15) {
|
||||
int newCount = buffers.length + 1 + ((overflowCounter - 15) / 5);
|
||||
if(newCount > maxCount) {
|
||||
newCount = maxCount;
|
||||
}
|
||||
if(newCount > buffers.length) {
|
||||
StreamBufferInstance[] newArray = new StreamBufferInstance[newCount];
|
||||
for(int i = 0; i < newArray.length; ++i) {
|
||||
if(i < buffers.length) {
|
||||
newArray[i] = buffers[i];
|
||||
}else {
|
||||
newArray[i] = new StreamBufferInstance();
|
||||
}
|
||||
}
|
||||
buffers = newArray;
|
||||
refill();
|
||||
}
|
||||
overflowCounter = 0;
|
||||
}
|
||||
currentBufferId = 0;
|
||||
}
|
||||
|
||||
private void refill() {
|
||||
for(int i = 0; i < buffers.length; ++i) {
|
||||
PoolInstance j = fillPoolInstance();
|
||||
StreamBufferInstance k = buffers[i];
|
||||
if(j != k.poolInstance) {
|
||||
PoolInstance l = k.poolInstance;
|
||||
k.poolInstance = j;
|
||||
if(k.vertexArray != null) {
|
||||
if(j.vertexBuffer == null) {
|
||||
resizeInstance(j, l.vertexBufferSize);
|
||||
}
|
||||
initializer.initialize(k.vertexArray, j.vertexBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
for(int i = 0; i < buffers.length; ++i) {
|
||||
StreamBufferInstance next = buffers[i];
|
||||
@ -189,12 +127,6 @@ public class StreamBuffer {
|
||||
EaglercraftGPU.destroyGLVertexArray(next.vertexArray);
|
||||
}
|
||||
}
|
||||
buffers = new StreamBufferInstance[initialCount];
|
||||
for(int i = 0; i < initialCount; ++i) {
|
||||
StreamBufferInstance j = new StreamBufferInstance();
|
||||
j.poolInstance = fillPoolInstance();
|
||||
buffers[i] = j;
|
||||
}
|
||||
}
|
||||
|
||||
public static void destroyPool() {
|
||||
|
@ -21,6 +21,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Display;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
|
||||
@ -100,6 +101,7 @@ public class TextureCopyUtil {
|
||||
_wglCompileShader(vshShader);
|
||||
|
||||
if(_wglGetShaderi(vshShader, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
LOGGER.error("Failed to compile GL_VERTEX_SHADER \"" + vertexShaderPath + "\" for TextureCopyUtil!");
|
||||
String log = _wglGetShaderInfoLog(vshShader);
|
||||
if(log != null) {
|
||||
@ -126,6 +128,7 @@ public class TextureCopyUtil {
|
||||
_wglCompileShader(frag);
|
||||
|
||||
if(_wglGetShaderi(frag, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
LOGGER.error("Failed to compile GL_FRAGMENT_SHADER \"" + fragmentShaderPath + "\" for TextureCopyUtil!");
|
||||
String log = _wglGetShaderInfoLog(frag);
|
||||
if(log != null) {
|
||||
@ -154,6 +157,7 @@ public class TextureCopyUtil {
|
||||
_wglDeleteShader(frag);
|
||||
|
||||
if(_wglGetProgrami(shaderProgram, GL_LINK_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
LOGGER.error("Failed to link shader program for TextureCopyUtil!");
|
||||
String log = _wglGetProgramInfoLog(shaderProgram);
|
||||
if(log != null) {
|
||||
|
@ -1483,6 +1483,7 @@ public class EaglerDeferredPipeline {
|
||||
GlStateManager.globalEnableBlend();
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.depthMask(false);
|
||||
GlStateManager.cullFace(GL_FRONT);
|
||||
GlStateManager.tryBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ZERO);
|
||||
GlStateManager.enablePolygonOffset();
|
||||
GlStateManager.doPolygonOffset(0.25f, 1.0f);
|
||||
@ -1497,6 +1498,7 @@ public class EaglerDeferredPipeline {
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.globalDisableBlend();
|
||||
GlStateManager.depthMask(true);
|
||||
GlStateManager.cullFace(GL_BACK);
|
||||
GlStateManager.disablePolygonOffset();
|
||||
GlStateManager.colorMask(false, false, false, false);
|
||||
DeferredStateManager.checkGLError("Post: endDrawColoredShadows()");
|
||||
|
@ -92,7 +92,7 @@ public class ForwardAcceleratedEffectRenderer extends AbstractAcceleratedEffectR
|
||||
_wglVertexAttribDivisor(0, 0);
|
||||
|
||||
EaglercraftGPU.bindGLArrayBuffer(instancesBuffer);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.remaining(), GL_STREAM_DRAW);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
|
||||
|
||||
_wglEnableVertexAttribArray(1);
|
||||
_wglVertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0);
|
||||
@ -149,6 +149,7 @@ public class ForwardAcceleratedEffectRenderer extends AbstractAcceleratedEffectR
|
||||
int l = particleBuffer.limit();
|
||||
|
||||
particleBuffer.flip();
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
|
||||
_wglBufferSubData(GL_ARRAY_BUFFER, 0, particleBuffer);
|
||||
|
||||
particleBuffer.position(p);
|
||||
|
@ -92,7 +92,7 @@ public class GBufferAcceleratedEffectRenderer extends AbstractAcceleratedEffectR
|
||||
_wglVertexAttribDivisor(0, 0);
|
||||
|
||||
EaglercraftGPU.bindGLArrayBuffer(instancesBuffer);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.remaining(), GL_STREAM_DRAW);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
|
||||
|
||||
_wglEnableVertexAttribArray(1);
|
||||
_wglVertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0);
|
||||
@ -148,6 +148,7 @@ public class GBufferAcceleratedEffectRenderer extends AbstractAcceleratedEffectR
|
||||
int l = particleBuffer.limit();
|
||||
|
||||
particleBuffer.flip();
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
|
||||
_wglBufferSubData(GL_ARRAY_BUFFER, 0, particleBuffer);
|
||||
|
||||
particleBuffer.position(p);
|
||||
|
@ -89,7 +89,7 @@ public class LensFlareMeshRenderer {
|
||||
|
||||
streaksVertexArray = _wglGenVertexArrays();
|
||||
EaglercraftGPU.bindGLVertexArray(streaksVertexArray);
|
||||
EaglercraftGPU.attachQuad16EmulationBuffer(16, true);
|
||||
EaglercraftGPU.attachQuad16EmulationBuffer(true);
|
||||
|
||||
_wglEnableVertexAttribArray(0);
|
||||
_wglVertexAttribPointer(0, 2, GL_FLOAT, false, 16, 0);
|
||||
|
@ -22,6 +22,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Display;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
@ -69,6 +70,7 @@ public class ShaderCompiler {
|
||||
_wglCompileShader(ret);
|
||||
|
||||
if(_wglGetShaderi(ret, GL_COMPILE_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
logger.error("Failed to compile {} \"{}\" of program \"{}\"!", getStageName(stage), filename, name);
|
||||
String log = _wglGetShaderInfoLog(ret);
|
||||
if(log != null) {
|
||||
@ -95,6 +97,7 @@ public class ShaderCompiler {
|
||||
_wglDetachShader(ret, frag);
|
||||
|
||||
if(_wglGetProgrami(ret, GL_LINK_STATUS) != GL_TRUE) {
|
||||
Display.checkContextLost();
|
||||
logger.error("Failed to link program \"{}\"!", name);
|
||||
String log = _wglGetProgramInfoLog(ret);
|
||||
if(log != null) {
|
||||
|
@ -97,7 +97,7 @@ public class DynamicLightsAcceleratedEffectRenderer extends AbstractAcceleratedE
|
||||
_wglVertexAttribDivisor(0, 0);
|
||||
|
||||
EaglercraftGPU.bindGLArrayBuffer(instancesBuffer);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.remaining(), GL_STREAM_DRAW);
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
|
||||
|
||||
_wglEnableVertexAttribArray(1);
|
||||
_wglVertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0);
|
||||
@ -155,6 +155,7 @@ public class DynamicLightsAcceleratedEffectRenderer extends AbstractAcceleratedE
|
||||
int l = particleBuffer.limit();
|
||||
|
||||
particleBuffer.flip();
|
||||
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
|
||||
_wglBufferSubData(GL_ARRAY_BUFFER, 0, particleBuffer);
|
||||
|
||||
particleBuffer.position(p);
|
||||
|
Reference in New Issue
Block a user