Skip to content
154 changes: 80 additions & 74 deletions src/main/java/rs117/hd/HdPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import java.awt.image.DataBufferInt;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
Expand Down Expand Up @@ -76,13 +75,19 @@
import org.lwjgl.opengl.*;
import org.lwjgl.system.Callback;
import org.lwjgl.system.Configuration;
import org.lwjgl.system.MemoryStack;
import rs117.hd.config.ColorFilter;
import rs117.hd.config.DynamicLights;
import rs117.hd.config.SeasonalHemisphere;
import rs117.hd.config.SeasonalTheme;
import rs117.hd.config.ShadingMode;
import rs117.hd.config.ShadowMode;
import rs117.hd.config.VanillaShadowMode;
import rs117.hd.opengl.GLVao;
import rs117.hd.opengl.GLVertexLayout;
import rs117.hd.opengl.GLVertexLayout.ArrayField;
import rs117.hd.opengl.GLVertexLayout.ComponentType;
import rs117.hd.opengl.GLVertexLayout.FormatType;
import rs117.hd.opengl.shader.ShaderException;
import rs117.hd.opengl.shader.ShaderIncludes;
import rs117.hd.opengl.shader.TiledLightingShaderProgram;
Expand Down Expand Up @@ -160,6 +165,7 @@ public class HdPlugin extends Plugin {

public static int MAX_TEXTURE_UNITS;
public static int TEXTURE_UNIT_COUNT = 0;
public static final int TEXTURE_UNIT_UNUSED = GL_TEXTURE0 + TEXTURE_UNIT_COUNT++;
public static final int TEXTURE_UNIT_UI = GL_TEXTURE0 + TEXTURE_UNIT_COUNT++;
public static final int TEXTURE_UNIT_GAME = GL_TEXTURE0 + TEXTURE_UNIT_COUNT++;
public static final int TEXTURE_UNIT_SHADOW_MAP = GL_TEXTURE0 + TEXTURE_UNIT_COUNT++;
Expand Down Expand Up @@ -344,11 +350,13 @@ public class HdPlugin extends Plugin {
private static final ResourcePath SHADER_PATH = Props
.getFolder("rlhd.shader-path", () -> path(HdPlugin.class));

public int vaoQuad;
private int vboQuad;
private static final GLVertexLayout FULLSCREEN_VERTEX_LAYOUT = new GLVertexLayout("FULLSCREEN_VERTEX_LAYOUT")
.edit(ArrayField.VERTEX_FIELD_0).enabled().component(ComponentType.RG).format(FormatType.FLOAT).stride(16).offset(0)
.edit(ArrayField.VERTEX_FIELD_1).enabled().component(ComponentType.RG).format(FormatType.FLOAT).stride(16).offset(8)
.finish();

public int vaoTri;
private int vboTri;
public GLVao quadVao;
public GLVao triVao;

@Getter
@Nullable
Expand Down Expand Up @@ -564,7 +572,7 @@ protected void startUp() {
INTEL_GPU = glRenderer.contains("Intel");
NVIDIA_GPU = glRenderer.toLowerCase().contains("nvidia");

SUPPORTS_INDIRECT_DRAW = NVIDIA_GPU && !APPLE || config.forceIndirectDraw();
SUPPORTS_INDIRECT_DRAW = false; //NVIDIA_GPU && !APPLE || config.forceIndirectDraw(); TODO: This isn't working at the moment, not sure why just yet

renderer = config.legacyRenderer() ?
injector.getInstance(LegacyRenderer.class) :
Expand Down Expand Up @@ -927,7 +935,7 @@ private void initializeShaders() throws ShaderException, IOException {
var includes = getShaderIncludes();

// Bind a valid VAO, otherwise validation may fail on older Intel-based Macs
glBindVertexArray(vaoTri);
triVao.bind();

renderer.initializeShaders(includes);
uiProgram.compile(includes);
Expand Down Expand Up @@ -1018,76 +1026,56 @@ public void recompilePrograms() {
}

private void initializeVaos() {
{
// Create quad VAO
vaoQuad = glGenVertexArrays();
vboQuad = glGenBuffers();
glBindVertexArray(vaoQuad);

FloatBuffer vboQuadData = BufferUtils.createFloatBuffer(16)
.put(new float[] {
// x, y, u, v
1, 1, 1, 1, // top right
-1, 1, 0, 1, // top left
-1, -1, 0, 0, // bottom left
1, -1, 1, 0 // bottom right
})
.flip();
glBindBuffer(GL_ARRAY_BUFFER, vboQuad);
glBufferData(GL_ARRAY_BUFFER, vboQuadData, GL_STATIC_DRAW);

// position attribute
glVertexAttribPointer(0, 2, GL_FLOAT, false, 4 * Float.BYTES, 0);
glEnableVertexAttribArray(0);

// texture coord attribute
glVertexAttribPointer(1, 2, GL_FLOAT, false, 4 * Float.BYTES, 2 * Float.BYTES);
glEnableVertexAttribArray(1);
}
try (MemoryStack stack = MemoryStack.stackPush()) {
quadVao = new GLVao("FullscreenQuad::VAO", FULLSCREEN_VERTEX_LAYOUT);
quadVao.setBufferRange(
new GLBuffer("FullscreenQuad::VBO", GL_ARRAY_BUFFER, GL_STATIC_DRAW)
.initialize()
.upload(stack
.mallocFloat(16)
.put(new float[] {
// x, y, u, v
1, 1, 1, 1, // top right
-1, 1, 0, 1, // top left
-1, -1, 0, 0, // bottom left
1, -1, 1, 0 // bottom right
})
.flip()
),
true,
ArrayField.VERTEX_FIELD_0,
ArrayField.VERTEX_FIELD_1
);

{
// Create tri VAO
vaoTri = glGenVertexArrays();
vboTri = glGenBuffers();
glBindVertexArray(vaoTri);

FloatBuffer vboTriData = BufferUtils.createFloatBuffer(12)
.put(new float[] {
// x, y, u, v
-1, -1, 0, 0, // bottom left
3, -1, 2, 0, // bottom right (off-screen)
-1, 3, 0, 2 // top left (off-screen)
})
.flip();
glBindBuffer(GL_ARRAY_BUFFER, vboTri);
glBufferData(GL_ARRAY_BUFFER, vboTriData, GL_STATIC_DRAW);

// position attribute
glVertexAttribPointer(0, 2, GL_FLOAT, false, 4 * Float.BYTES, 0);
glEnableVertexAttribArray(0);

// texture coord attribute
glVertexAttribPointer(1, 2, GL_FLOAT, false, 4 * Float.BYTES, 2 * Float.BYTES);
glEnableVertexAttribArray(1);
triVao = new GLVao("FullscreenQuad::VAO", FULLSCREEN_VERTEX_LAYOUT);
triVao.setBufferRange(
new GLBuffer("FullscreenQuad::VBO", GL_ARRAY_BUFFER, GL_STATIC_DRAW)
.initialize()
.upload(stack
.mallocFloat(16)
.put(new float[] {
// x, y, u, v
-1, -1, 0, 0, // bottom left
3, -1, 2, 0, // bottom right (off-screen)
-1, 3, 0, 2 // top left (off-screen)
})
.flip()
),
true,
ArrayField.VERTEX_FIELD_0,
ArrayField.VERTEX_FIELD_1
);
}
}

private void destroyVaos() {
if (vboQuad != 0)
glDeleteBuffers(vboQuad);
vboQuad = 0;
if (quadVao != null)
quadVao.destroy();
quadVao = null;

if (vaoQuad != 0)
glDeleteVertexArrays(vaoQuad);
vaoQuad = 0;

if (vboTri != 0)
glDeleteBuffers(vboTri);
vboTri = 0;

if (vaoTri != 0)
glDeleteVertexArrays(vaoTri);
vaoTri = 0;
if (triVao != null)
triVao.destroy();
triVao = null;
}

private void initializeUbos() {
Expand Down Expand Up @@ -1141,6 +1129,9 @@ private void initializeUiTexture() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glActiveTexture(TEXTURE_UNIT_UNUSED);
glBindTexture(GL_TEXTURE_2D, 0);

checkGLErrors();
}

Expand Down Expand Up @@ -1202,6 +1193,9 @@ public void updateTiledLightingFbo() {

glBindFramebuffer(GL_FRAMEBUFFER, awtContext.getFramebuffer(false));

glActiveTexture(TEXTURE_UNIT_UNUSED);
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);

checkGLErrors();

uboGlobal.tiledLightingResolution.set(tiledLightingResolution);
Expand Down Expand Up @@ -1401,8 +1395,17 @@ private void initializeShadowMapFbo() {
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);

// Check framebuffer completeness
int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
log.error("Shadow map framebuffer is not complete: 0x{}", Integer.toHexString(status));
throw new RuntimeException("Failed to create shadow map framebuffer: status 0x" + Integer.toHexString(status));
}

// Reset FBO
glBindFramebuffer(GL_FRAMEBUFFER, awtContext.getFramebuffer(false));
glActiveTexture(TEXTURE_UNIT_UNUSED);
glBindTexture(GL_TEXTURE_2D, 0);
}

private void initializeDummyShadowMap() {
Expand All @@ -1415,6 +1418,9 @@ private void initializeDummyShadowMap() {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

glActiveTexture(TEXTURE_UNIT_UNUSED);
glBindTexture(GL_TEXTURE_2D, 0);
}

private void destroyShadowMapFbo() {
Expand Down Expand Up @@ -1447,7 +1453,6 @@ public void prepareInterfaceTexture() {
if (resize) {
uiResolution = resolution;

glActiveTexture(TEXTURE_UNIT_UI);
glBindTexture(GL_TEXTURE_2D, texUi);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, uiResolution[0], uiResolution[1], 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
}
Expand Down Expand Up @@ -1520,7 +1525,6 @@ public void drawUi(int overlayColor) {
// See https://www.khronos.org/opengl/wiki/Sampler_Object for details.
// GL_NEAREST makes sampling for bicubic/xBR simpler, so it should be used whenever linear/pixel isn't
final int function = config.uiScalingMode().glSamplingFunction;
glActiveTexture(TEXTURE_UNIT_UI);
glBindTexture(GL_TEXTURE_2D, texUi);

if (uiCopyJob != null) {
Expand All @@ -1544,8 +1548,10 @@ public void drawUi(int overlayColor) {

glEnable(GL_BLEND);
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
glBindVertexArray(vaoTri);

triVao.bind();
glDrawArrays(GL_TRIANGLES, 0, 3);
triVao.unbind();

shadowMapOverlay.render();
gammaCalibrationOverlay.render();
Expand Down
71 changes: 44 additions & 27 deletions src/main/java/rs117/hd/opengl/GLState.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package rs117.hd.opengl;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import lombok.Getter;

public abstract class GLState {
protected boolean hasValue;
Expand All @@ -22,6 +21,11 @@ public void apply() {
}

abstract void internalApply();
public abstract void setDefault();

public void printState(StringBuffer sb) {
sb.append(getClass().getSimpleName()).append(": ").append(hasApplied ? "applied " : " ");
}

public abstract static class Bool extends GLState {
private boolean value;
Expand All @@ -41,6 +45,12 @@ void internalApply() {
}

protected abstract void applyValue(boolean value);

@Override
public void printState(StringBuffer sb) {
super.printState(sb);
sb.append("(").append(appliedValue).append(") \n");
}
}

public abstract static class Int extends GLState {
Expand All @@ -61,10 +71,17 @@ void internalApply() {
}

protected abstract void applyValue(int value);

@Override
public void printState(StringBuffer sb) {
super.printState(sb);
sb.append("(").append(appliedValue).append(") \n");
}
}

public abstract static class Object<T> extends GLState {
private T value;
@Getter
private T appliedValue;

public final void set(T v) {
Expand All @@ -81,6 +98,12 @@ void internalApply() {
}

protected abstract void applyValue(T value);

@Override
public void printState(StringBuffer sb) {
super.printState(sb);
sb.append("(").append(appliedValue).append(") \n");
}
}

public abstract static class IntArray extends GLState {
Expand All @@ -106,6 +129,17 @@ void internalApply() {
}

protected abstract void applyValues(int[] values);

@Override
public void printState(StringBuffer sb) {
super.printState(sb);
sb.append("(");
for(int i = 0; i < value.length; i++) {
if(i > 0) sb.append(", ");
sb.append(value[i]);
}
sb.append(") \n");
}
}

public abstract static class BoolArray extends GLState {
Expand All @@ -131,33 +165,16 @@ void internalApply() {
}

protected abstract void applyValues(boolean[] values);
}

public abstract static class IntSet extends GLState {
private final Set<Integer> targets = new HashSet<>();

public void add(int target) {
hasValue = true;
targets.add(target);
}

public void remove(int target) {
targets.remove(target);
hasApplied = !targets.isEmpty();
}

@Override
void internalApply() {
for (int t : targets) applyTarget(t);
targets.clear();
}

@Override
public void reset() {
super.reset();
targets.clear();
public void printState(StringBuffer sb) {
super.printState(sb);
sb.append("(");
for(int i = 0; i < value.length; i++) {
if(i > 0) sb.append(", ");
sb.append(value[i]);
}
sb.append(") \n");
}

protected abstract void applyTarget(int target);
}
}
Loading