Rewrite framebuffers to look more decent

This commit is contained in:
IMS212
2023-10-21 15:55:03 -07:00
parent b57d7c13df
commit cbd404913f
9 changed files with 681 additions and 60 deletions
@@ -0,0 +1,154 @@
package com.seibel.distanthorizons.core.render.glObject.texture;
import org.joml.Vector2i;
import org.lwjgl.opengl.GL11C;
import org.lwjgl.opengl.GL13C;
import org.lwjgl.opengl.GL43C;
import java.nio.ByteBuffer;
public class DHColorTexture
{
private final DHInternalTextureFormat internalFormat;
private final DHPixelFormat format;
private final DHPixelType type;
private int width;
private int height;
private boolean isValid;
private final int texture;
private static final ByteBuffer NULL_BUFFER = null;
public DHColorTexture(Builder builder) {
this.isValid = true;
this.internalFormat = builder.internalFormat;
this.format = builder.format;
this.type = builder.type;
this.width = builder.width;
this.height = builder.height;
this.texture = GL43C.glGenTextures();
boolean isPixelFormatInteger = builder.internalFormat.getPixelFormat().isInteger();
setupTexture(texture, builder.width, builder.height, !isPixelFormatInteger);
// Clean up after ourselves
// This is strictly defensive to ensure that other buggy code doesn't tamper with our textures
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, 0);
}
private void setupTexture(int texture, int width, int height, boolean allowsLinear) {
resizeTexture(texture, width, height);
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MIN_FILTER, allowsLinear ? GL11C.GL_LINEAR : GL11C.GL_NEAREST);
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MAG_FILTER, allowsLinear ? GL11C.GL_LINEAR : GL11C.GL_NEAREST);
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE);
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE);
}
private void resizeTexture(int texture, int width, int height) {
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, texture);
GL43C.glTexImage2D(GL11C.GL_TEXTURE_2D, 0, internalFormat.getGlFormat(), width, height, 0, format.getGlFormat(), type.getGlFormat(), NULL_BUFFER);
}
void resize(Vector2i textureScaleOverride) {
this.resize(textureScaleOverride.x, textureScaleOverride.y);
}
// Package private, call CompositeRenderTargets#resizeIfNeeded instead.
public void resize(int width, int height) {
requireValid();
this.width = width;
this.height = height;
resizeTexture(texture, width, height);
}
public DHInternalTextureFormat getInternalFormat() {
return internalFormat;
}
public int getTexture() {
requireValid();
return texture;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void destroy() {
requireValid();
isValid = false;
GL43C.glDeleteTextures(texture);
}
private void requireValid() {
if (!isValid) {
throw new IllegalStateException("Attempted to use a deleted composite render target");
}
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private DHInternalTextureFormat internalFormat = DHInternalTextureFormat.RGBA8;
private int width = 0;
private int height = 0;
private DHPixelFormat format = DHPixelFormat.RGBA;
private DHPixelType type = DHPixelType.UNSIGNED_BYTE;
private Builder() {
// No-op
}
public Builder setInternalFormat(DHInternalTextureFormat format) {
this.internalFormat = format;
return this;
}
public Builder setDimensions(int width, int height) {
if (width <= 0) {
throw new IllegalArgumentException("Width must be greater than zero");
}
if (height <= 0) {
throw new IllegalArgumentException("Height must be greater than zero");
}
this.width = width;
this.height = height;
return this;
}
public Builder setPixelFormat(DHPixelFormat pixelFormat) {
this.format = pixelFormat;
return this;
}
public Builder setPixelType(DHPixelType pixelType) {
this.type = pixelType;
return this;
}
public DHColorTexture build() {
return new DHColorTexture(this);
}
}
}
@@ -0,0 +1,97 @@
package com.seibel.distanthorizons.core.render.glObject.texture;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.opengl.GL30C;
import org.lwjgl.opengl.GL43C;
public enum DHDepthBufferFormat {
DEPTH(false),
DEPTH16(false),
DEPTH24(false),
DEPTH32(false),
DEPTH32F(false),
DEPTH_STENCIL(true),
DEPTH24_STENCIL8(true),
DEPTH32F_STENCIL8(true);
private final boolean combinedStencil;
DHDepthBufferFormat(boolean combinedStencil) {
this.combinedStencil = combinedStencil;
}
@Nullable
public static DHDepthBufferFormat fromGlEnum(int glenum) {
switch (glenum) {
case GL30C.GL_DEPTH_COMPONENT: return DHDepthBufferFormat.DEPTH;
case GL30C.GL_DEPTH_COMPONENT16: return DHDepthBufferFormat.DEPTH16;
case GL30C.GL_DEPTH_COMPONENT24: return DHDepthBufferFormat.DEPTH24;
case GL30C.GL_DEPTH_COMPONENT32: return DHDepthBufferFormat.DEPTH32;
case GL30C.GL_DEPTH_COMPONENT32F: return DHDepthBufferFormat.DEPTH32F;
case GL30C.GL_DEPTH_STENCIL: return DHDepthBufferFormat.DEPTH_STENCIL;
case GL30C.GL_DEPTH24_STENCIL8: return DHDepthBufferFormat.DEPTH24_STENCIL8;
case GL30C.GL_DEPTH32F_STENCIL8: return DHDepthBufferFormat.DEPTH32F_STENCIL8;
default: return null;
}
}
public static DHDepthBufferFormat fromGlEnumOrDefault(int glenum) {
DHDepthBufferFormat format = fromGlEnum(glenum);
if (format == null) {
// yolo, just assume it's GL_DEPTH_COMPONENT
return DHDepthBufferFormat.DEPTH;
}
return format;
}
public int getGlInternalFormat() {
switch (this) {
case DEPTH:
return GL30C.GL_DEPTH_COMPONENT;
case DEPTH16:
return GL30C.GL_DEPTH_COMPONENT16;
case DEPTH24:
return GL30C.GL_DEPTH_COMPONENT24;
case DEPTH32:
return GL30C.GL_DEPTH_COMPONENT32;
case DEPTH32F:
return GL30C.GL_DEPTH_COMPONENT32F;
case DEPTH_STENCIL:
return GL30C.GL_DEPTH_STENCIL;
case DEPTH24_STENCIL8:
return GL30C.GL_DEPTH24_STENCIL8;
case DEPTH32F_STENCIL8:
return GL30C.GL_DEPTH32F_STENCIL8;
}
throw new AssertionError("unreachable");
}
public int getGlType() {
return isCombinedStencil() ? GL30C.GL_DEPTH_STENCIL : GL30C.GL_DEPTH_COMPONENT;
}
public int getGlFormat() {
switch (this) {
case DEPTH:
case DEPTH16:
return GL43C.GL_UNSIGNED_SHORT;
case DEPTH24:
case DEPTH32:
return GL43C.GL_UNSIGNED_INT;
case DEPTH32F:
return GL30C.GL_FLOAT;
case DEPTH_STENCIL:
case DEPTH24_STENCIL8:
return GL30C.GL_UNSIGNED_INT_24_8;
case DEPTH32F_STENCIL8:
return GL30C.GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
}
throw new AssertionError("unreachable");
}
public boolean isCombinedStencil() {
return combinedStencil;
}
}
@@ -0,0 +1,50 @@
package com.seibel.distanthorizons.core.render.glObject.texture;
import org.lwjgl.opengl.GL11C;
import org.lwjgl.opengl.GL13C;
import org.lwjgl.opengl.GL43C;
import java.nio.ByteBuffer;
public class DHDepthTexture
{
private int id;
public DHDepthTexture(int width, int height, DHDepthBufferFormat format)
{
this.id = GL43C.glGenTextures();
resize(width, height, format);
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MIN_FILTER, GL11C.GL_NEAREST);
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MAG_FILTER, GL11C.GL_NEAREST);
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE);
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE);
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, 0);
}
// For internal use by Iris for copying data. Do not use this in DH.
public DHDepthTexture(int id) {
this.id = id;
}
public void resize(int width, int height, DHDepthBufferFormat format)
{
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, getTextureId());
GL43C.glTexImage2D(GL11C.GL_TEXTURE_2D, 0, format.getGlInternalFormat(), width, height, 0,
format.getGlType(), format.getGlFormat(), (ByteBuffer) null);
}
public int getTextureId()
{
if (id == -1) throw new IllegalStateException("Depth texture does not exist!");
return id;
}
public void destroy()
{
GL43C.glDeleteTextures(getTextureId());
this.id = -1;
}
}
@@ -0,0 +1,110 @@
package com.seibel.distanthorizons.core.render.glObject.texture;
import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import org.lwjgl.opengl.GL30C;
import org.lwjgl.opengl.GL43C;
public class DHFramebuffer {
private final Int2IntMap attachments;
private final int maxDrawBuffers;
private final int maxColorAttachments;
private boolean hasDepthAttachment;
private int id;
public DHFramebuffer() {
id = GL43C.glGenFramebuffers();
this.attachments = new Int2IntArrayMap();
this.maxDrawBuffers = GL43C.glGetInteger(GL30C.GL_MAX_DRAW_BUFFERS);
this.maxColorAttachments = GL43C.glGetInteger(GL30C.GL_MAX_COLOR_ATTACHMENTS);
this.hasDepthAttachment = false;
}
public void addDepthAttachment(int texture, DHDepthBufferFormat depthBufferFormat) {
bind();
if (depthBufferFormat.isCombinedStencil()) {
GL43C.glFramebufferTexture2D(GL30C.GL_FRAMEBUFFER, GL30C.GL_DEPTH_STENCIL_ATTACHMENT, GL30C.GL_TEXTURE_2D, texture, 0);
} else {
GL43C.glFramebufferTexture2D(GL30C.GL_FRAMEBUFFER, GL30C.GL_DEPTH_ATTACHMENT, GL30C.GL_TEXTURE_2D, texture, 0);
}
this.hasDepthAttachment = true;
}
public void addColorAttachment(int index, int texture) {
int fb = id;
bind();
GL43C.glFramebufferTexture2D(GL30C.GL_FRAMEBUFFER, GL30C.GL_COLOR_ATTACHMENT0 + index, GL30C.GL_TEXTURE_2D, texture, 0);
attachments.put(index, texture);
}
public void noDrawBuffers() {
bind();
GL43C.glDrawBuffers(new int[] { GL30C.GL_NONE });
}
public void drawBuffers(int[] buffers) {
int[] glBuffers = new int[buffers.length];
int index = 0;
if (buffers.length > maxDrawBuffers) {
throw new IllegalArgumentException("Cannot write to more than " + maxDrawBuffers + " draw buffers on this GPU");
}
for (int buffer : buffers) {
if (buffer >= maxColorAttachments) {
throw new IllegalArgumentException("Only " + maxColorAttachments + " color attachments are supported on this GPU, but an attempt was made to write to a color attachment with index " + buffer);
}
glBuffers[index++] = GL30C.GL_COLOR_ATTACHMENT0 + buffer;
}
bind();
GL43C.glDrawBuffers(new int[] { GL30C.GL_NONE });
}
public void readBuffer(int buffer) {
bind();
GL43C.glReadBuffer(GL30C.GL_COLOR_ATTACHMENT0 + buffer);
}
public int getColorAttachment(int index) {
return attachments.get(index);
}
public boolean hasDepthAttachment() {
return hasDepthAttachment;
}
public void bind() {
if (id == -1) throw new IllegalStateException("Framebuffer does not exist!");
GL43C.glBindFramebuffer(GL30C.GL_FRAMEBUFFER, id);
}
public void bindAsReadBuffer() {
GL43C.glBindFramebuffer(GL30C.GL_READ_FRAMEBUFFER, id);
}
public void bindAsDrawBuffer() {
GL43C.glBindFramebuffer(GL30C.GL_DRAW_FRAMEBUFFER, id);
}
public void destroyInternal() {
GL43C.glDeleteFramebuffers(id);
this.id = -1;
}
public int getStatus() {
bind();
int status = GL43C.glCheckFramebufferStatus(GL30C.GL_FRAMEBUFFER);
return status;
}
public int getId() {
return id;
}
}
@@ -0,0 +1,108 @@
package com.seibel.distanthorizons.core.render.glObject.texture;
import org.lwjgl.opengl.GL11C;
import org.lwjgl.opengl.GL30C;
import org.lwjgl.opengl.GL31C;
import java.util.Locale;
import java.util.Optional;
public enum DHInternalTextureFormat {
// Default
// TODO: This technically shouldn't be exposed to shaders since it's not in the specification, it's the default anyways
RGBA(GL11C.GL_RGBA, GlVersion.GL_11, DHPixelFormat.RGBA),
// 8-bit normalized
R8(GL30C.GL_R8, GlVersion.GL_30, DHPixelFormat.RED),
RG8(GL30C.GL_RG8, GlVersion.GL_30, DHPixelFormat.RG),
RGB8(GL11C.GL_RGB8, GlVersion.GL_11, DHPixelFormat.RGB),
RGBA8(GL11C.GL_RGBA8, GlVersion.GL_11, DHPixelFormat.RGBA),
// 8-bit signed normalized
R8_SNORM(GL31C.GL_R8_SNORM, GlVersion.GL_31, DHPixelFormat.RED),
RG8_SNORM(GL31C.GL_RG8_SNORM, GlVersion.GL_31, DHPixelFormat.RG),
RGB8_SNORM(GL31C.GL_RGB8_SNORM, GlVersion.GL_31, DHPixelFormat.RGB),
RGBA8_SNORM(GL31C.GL_RGBA8_SNORM, GlVersion.GL_31, DHPixelFormat.RGBA),
// 16-bit normalized
R16(GL30C.GL_R16, GlVersion.GL_30, DHPixelFormat.RED),
RG16(GL30C.GL_RG16, GlVersion.GL_30, DHPixelFormat.RG),
RGB16(GL11C.GL_RGB16, GlVersion.GL_11, DHPixelFormat.RGB),
RGBA16(GL11C.GL_RGBA16, GlVersion.GL_11, DHPixelFormat.RGBA),
// 16-bit signed normalized
R16_SNORM(GL31C.GL_R16_SNORM, GlVersion.GL_31, DHPixelFormat.RED),
RG16_SNORM(GL31C.GL_RG16_SNORM, GlVersion.GL_31, DHPixelFormat.RG),
RGB16_SNORM(GL31C.GL_RGB16_SNORM, GlVersion.GL_31, DHPixelFormat.RGB),
RGBA16_SNORM(GL31C.GL_RGBA16_SNORM, GlVersion.GL_31, DHPixelFormat.RGBA),
// 16-bit float
R16F(GL30C.GL_R16F, GlVersion.GL_30, DHPixelFormat.RED),
RG16F(GL30C.GL_RG16F, GlVersion.GL_30, DHPixelFormat.RG),
RGB16F(GL30C.GL_RGB16F, GlVersion.GL_30, DHPixelFormat.RGB),
RGBA16F(GL30C.GL_RGBA16F, GlVersion.GL_30, DHPixelFormat.RGBA),
// 32-bit float
R32F(GL30C.GL_R32F, GlVersion.GL_30, DHPixelFormat.RED),
RG32F(GL30C.GL_RG32F, GlVersion.GL_30, DHPixelFormat.RG),
RGB32F(GL30C.GL_RGB32F, GlVersion.GL_30, DHPixelFormat.RGB),
RGBA32F(GL30C.GL_RGBA32F, GlVersion.GL_30, DHPixelFormat.RGBA),
// 8-bit integer
R8I(GL30C.GL_R8I, GlVersion.GL_30, DHPixelFormat.RED_INTEGER),
RG8I(GL30C.GL_RG8I, GlVersion.GL_30, DHPixelFormat.RG_INTEGER),
RGB8I(GL30C.GL_RGB8I, GlVersion.GL_30, DHPixelFormat.RGB_INTEGER),
RGBA8I(GL30C.GL_RGBA8I, GlVersion.GL_30, DHPixelFormat.RGBA_INTEGER),
// 8-bit unsigned integer
R8UI(GL30C.GL_R8UI, GlVersion.GL_30, DHPixelFormat.RED_INTEGER),
RG8UI(GL30C.GL_RG8UI, GlVersion.GL_30, DHPixelFormat.RG_INTEGER),
RGB8UI(GL30C.GL_RGB8UI, GlVersion.GL_30, DHPixelFormat.RGB_INTEGER),
RGBA8UI(GL30C.GL_RGBA8UI, GlVersion.GL_30, DHPixelFormat.RGBA_INTEGER),
// 16-bit integer
R16I(GL30C.GL_R16I, GlVersion.GL_30, DHPixelFormat.RED_INTEGER),
RG16I(GL30C.GL_RG16I, GlVersion.GL_30, DHPixelFormat.RG_INTEGER),
RGB16I(GL30C.GL_RGB16I, GlVersion.GL_30, DHPixelFormat.RGB_INTEGER),
RGBA16I(GL30C.GL_RGBA16I, GlVersion.GL_30, DHPixelFormat.RGBA_INTEGER),
// 16-bit unsigned integer
R16UI(GL30C.GL_R16UI, GlVersion.GL_30, DHPixelFormat.RED_INTEGER),
RG16UI(GL30C.GL_RG16UI, GlVersion.GL_30, DHPixelFormat.RG_INTEGER),
RGB16UI(GL30C.GL_RGB16UI, GlVersion.GL_30, DHPixelFormat.RGB_INTEGER),
RGBA16UI(GL30C.GL_RGBA16UI, GlVersion.GL_30, DHPixelFormat.RGBA_INTEGER),
// 32-bit integer
R32I(GL30C.GL_R32I, GlVersion.GL_30, DHPixelFormat.RED_INTEGER),
RG32I(GL30C.GL_RG32I, GlVersion.GL_30, DHPixelFormat.RG_INTEGER),
RGB32I(GL30C.GL_RGB32I, GlVersion.GL_30, DHPixelFormat.RGB_INTEGER),
RGBA32I(GL30C.GL_RGBA32I, GlVersion.GL_30, DHPixelFormat.RGBA_INTEGER),
// 32-bit unsigned integer
R32UI(GL30C.GL_R32UI, GlVersion.GL_30, DHPixelFormat.RED_INTEGER),
RG32UI(GL30C.GL_RG32UI, GlVersion.GL_30, DHPixelFormat.RG_INTEGER),
RGB32UI(GL30C.GL_RGB32UI, GlVersion.GL_30, DHPixelFormat.RGB_INTEGER),
RGBA32UI(GL30C.GL_RGBA32UI, GlVersion.GL_30, DHPixelFormat.RGBA_INTEGER),
// Mixed
R3_G3_B2(GL11C.GL_R3_G3_B2, GlVersion.GL_11, DHPixelFormat.RGB),
RGB5_A1(GL11C.GL_RGB5_A1, GlVersion.GL_11, DHPixelFormat.RGBA),
RGB10_A2(GL11C.GL_RGB10_A2, GlVersion.GL_11, DHPixelFormat.RGBA),
R11F_G11F_B10F(GL30C.GL_R11F_G11F_B10F, GlVersion.GL_30, DHPixelFormat.RGB),
RGB9_E5(GL30C.GL_RGB9_E5, GlVersion.GL_30, DHPixelFormat.RGB);
private final int glFormat;
private final GlVersion minimumGlVersion;
private final DHPixelFormat expectedPixelFormat;
DHInternalTextureFormat(int glFormat, GlVersion minimumGlVersion, DHPixelFormat expectedPixelFormat) {
this.glFormat = glFormat;
this.minimumGlVersion = minimumGlVersion;
this.expectedPixelFormat = expectedPixelFormat;
}
public static Optional<DHInternalTextureFormat> fromString(String name) {
try {
return Optional.of(DHInternalTextureFormat.valueOf(name.toUpperCase(Locale.US)));
} catch (IllegalArgumentException e) {
return Optional.empty();
}
}
public int getGlFormat() {
return glFormat;
}
public DHPixelFormat getPixelFormat() { return expectedPixelFormat; }
public GlVersion getMinimumGlVersion() {
return minimumGlVersion;
}
}
@@ -0,0 +1,53 @@
package com.seibel.distanthorizons.core.render.glObject.texture;
import org.lwjgl.opengl.GL11C;
import org.lwjgl.opengl.GL12C;
import org.lwjgl.opengl.GL30C;
import java.util.Locale;
import java.util.Optional;
public enum DHPixelFormat {
RED(GL11C.GL_RED, GlVersion.GL_11, false),
RG(GL30C.GL_RG, GlVersion.GL_30, false),
RGB(GL11C.GL_RGB, GlVersion.GL_11, false),
BGR(GL12C.GL_BGR, GlVersion.GL_12, false),
RGBA(GL11C.GL_RGBA, GlVersion.GL_11, false),
BGRA(GL12C.GL_BGRA, GlVersion.GL_12, false),
RED_INTEGER(GL30C.GL_RED_INTEGER, GlVersion.GL_30, true),
RG_INTEGER(GL30C.GL_RG_INTEGER, GlVersion.GL_30, true),
RGB_INTEGER(GL30C.GL_RGB_INTEGER, GlVersion.GL_30, true),
BGR_INTEGER(GL30C.GL_BGR_INTEGER, GlVersion.GL_30, true),
RGBA_INTEGER(GL30C.GL_RGBA_INTEGER, GlVersion.GL_30, true),
BGRA_INTEGER(GL30C.GL_BGRA_INTEGER, GlVersion.GL_30, true);
private final int glFormat;
private final GlVersion minimumGlVersion;
private final boolean isInteger;
DHPixelFormat(int glFormat, GlVersion minimumGlVersion, boolean isInteger) {
this.glFormat = glFormat;
this.minimumGlVersion = minimumGlVersion;
this.isInteger = isInteger;
}
public static Optional<DHPixelFormat> fromString(String name) {
try {
return Optional.of(DHPixelFormat.valueOf(name.toUpperCase(Locale.US)));
} catch (IllegalArgumentException e) {
return Optional.empty();
}
}
public int getGlFormat() {
return glFormat;
}
public GlVersion getMinimumGlVersion() {
return minimumGlVersion;
}
public boolean isInteger() {
return isInteger;
}
}
@@ -0,0 +1,55 @@
package com.seibel.distanthorizons.core.render.glObject.texture;
import org.lwjgl.opengl.GL11C;
import org.lwjgl.opengl.GL12C;
import org.lwjgl.opengl.GL30C;
import java.util.Locale;
import java.util.Optional;
public enum DHPixelType {
BYTE(GL11C.GL_BYTE, GlVersion.GL_11),
SHORT(GL11C.GL_SHORT, GlVersion.GL_11),
INT(GL11C.GL_INT, GlVersion.GL_11),
HALF_FLOAT(GL30C.GL_HALF_FLOAT, GlVersion.GL_30),
FLOAT(GL11C.GL_FLOAT, GlVersion.GL_11),
UNSIGNED_BYTE(GL11C.GL_UNSIGNED_BYTE, GlVersion.GL_11),
UNSIGNED_BYTE_3_3_2(GL12C.GL_UNSIGNED_BYTE_3_3_2, GlVersion.GL_12),
UNSIGNED_BYTE_2_3_3_REV(GL12C.GL_UNSIGNED_BYTE_2_3_3_REV, GlVersion.GL_12),
UNSIGNED_SHORT(GL11C.GL_UNSIGNED_SHORT, GlVersion.GL_11),
UNSIGNED_SHORT_5_6_5(GL12C.GL_UNSIGNED_SHORT_5_6_5, GlVersion.GL_12),
UNSIGNED_SHORT_5_6_5_REV(GL12C.GL_UNSIGNED_SHORT_5_6_5_REV, GlVersion.GL_12),
UNSIGNED_SHORT_4_4_4_4(GL12C.GL_UNSIGNED_SHORT_4_4_4_4, GlVersion.GL_12),
UNSIGNED_SHORT_4_4_4_4_REV(GL12C.GL_UNSIGNED_SHORT_4_4_4_4_REV, GlVersion.GL_12),
UNSIGNED_SHORT_5_5_5_1(GL12C.GL_UNSIGNED_SHORT_5_5_5_1, GlVersion.GL_12),
UNSIGNED_SHORT_1_5_5_5_REV(GL12C.GL_UNSIGNED_SHORT_1_5_5_5_REV, GlVersion.GL_12),
UNSIGNED_INT(GL11C.GL_UNSIGNED_INT, GlVersion.GL_11),
UNSIGNED_INT_8_8_8_8(GL12C.GL_UNSIGNED_INT_8_8_8_8, GlVersion.GL_12),
UNSIGNED_INT_8_8_8_8_REV(GL12C.GL_UNSIGNED_INT_8_8_8_8_REV, GlVersion.GL_12),
UNSIGNED_INT_10_10_10_2(GL12C.GL_UNSIGNED_INT_10_10_10_2, GlVersion.GL_12),
UNSIGNED_INT_2_10_10_10_REV(GL12C.GL_UNSIGNED_INT_2_10_10_10_REV, GlVersion.GL_12);
private final int glFormat;
private final GlVersion minimumGlVersion;
DHPixelType(int glFormat, GlVersion minimumGlVersion) {
this.glFormat = glFormat;
this.minimumGlVersion = minimumGlVersion;
}
public static Optional<DHPixelType> fromString(String name) {
try {
return Optional.of(DHPixelType.valueOf(name.toUpperCase(Locale.US)));
} catch (IllegalArgumentException e) {
return Optional.empty();
}
}
public int getGlFormat() {
return glFormat;
}
public GlVersion getMinimumGlVersion() {
return minimumGlVersion;
}
}
@@ -0,0 +1,8 @@
package com.seibel.distanthorizons.core.render.glObject.texture;
public enum GlVersion {
GL_11,
GL_12,
GL_30,
GL_31
}
@@ -31,6 +31,7 @@ import com.seibel.distanthorizons.core.render.glObject.GLProxy;
import com.seibel.distanthorizons.core.render.glObject.GLState;
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.core.render.glObject.buffer.QuadElementBuffer;
import com.seibel.distanthorizons.core.render.glObject.texture.*;
import com.seibel.distanthorizons.core.render.renderer.shaders.*;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.RenderUtil;
@@ -50,7 +51,6 @@ import org.apache.logging.log4j.Logger;
import org.lwjgl.opengl.GL32;
import java.awt.*;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
@@ -85,6 +85,8 @@ public class LodRenderer
private static int activeFramebufferId = -1;
private static int activeColorTextureId = -1;
private static int activeDepthTextureId = -1;
private int cachedWidth;
private int cachedHeight;
@@ -150,9 +152,9 @@ public class LodRenderer
public boolean isSetupComplete = false;
// frameBuffer and texture ID's for this renderer
private int framebufferId = -1;
private int colorTextureId = -1;
private int depthTextureId = -1;
private DHFramebuffer framebuffer;
private DHColorTexture colorTexture;
private DHDepthTexture depthTexture;
@@ -194,6 +196,11 @@ public class LodRenderer
}
}
public void resize(int width, int height) {
colorTexture.resize(width, height);
depthTexture.resize(width, height, DHDepthBufferFormat.DEPTH32F);
}
//===============//
@@ -218,11 +225,13 @@ public class LodRenderer
{
if (IRIS_ACCESSOR != null && IRIS_ACCESSOR.isRenderingShadowPass())
{
// Do not do this while Iris compat is being worked on.
// We do not have a wy to properly render shader shadow pass, since they can
// and often do change the projection entirely, as well as the output usage.
//EVENT_LOGGER.debug("Skipping shadow pass render.");
return;
//return;
}
// Note: Since lightmapTexture is changing every frame, it's faster to recreate it than to reuse the old one.
@@ -261,46 +270,17 @@ public class LodRenderer
}
}
if (MC_RENDER.getTargetFrameBufferViewportWidth() != cachedWidth || MC_RENDER.getTargetFrameBufferViewportHeight() != cachedHeight) {
this.cachedWidth = MC_RENDER.getTargetFrameBufferViewportWidth();
this.cachedHeight = MC_RENDER.getTargetFrameBufferViewportHeight();
resize(cachedWidth, cachedHeight);
}
this.setActiveFramebufferId(framebuffer.getId());
this.setActiveDepthTextureId(depthTexture.getTextureId());
this.setActiveColorTextureId(colorTexture.getTexture());
// Bind LOD frame buffer
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.framebufferId);
this.setActiveFramebufferId(this.framebufferId);
// Bind LOD color texture
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.colorTextureId);
GL32.glTexImage2D(GL32.GL_TEXTURE_2D,
0,
GL32.GL_RGBA8,
MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight(),
0,
GL32.GL_RGBA,
GL32.GL_UNSIGNED_BYTE,
(ByteBuffer) null);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
GL32.glFramebufferTexture2D(GL32.GL_DRAW_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.colorTextureId, 0);
this.setActiveColorTextureId(this.colorTextureId);
// bind LOD depth texture
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.depthTextureId);
GL32.glTexImage2D(GL32.GL_TEXTURE_2D,
0,
GL32.GL_DEPTH_COMPONENT32,
MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight(),
0,
GL32.GL_DEPTH_COMPONENT,
GL32.GL_UNSIGNED_BYTE,
(ByteBuffer) null);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
GL32.glFramebufferTexture2D(GL32.GL_DRAW_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_TEXTURE_2D, this.depthTextureId, 0);
this.setActiveDepthTextureId(this.depthTextureId);
this.framebuffer.bind();
// Clear LOD framebuffer and depth buffers
GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT);
@@ -308,14 +288,6 @@ public class LodRenderer
GL32.glEnable(GL32.GL_DEPTH_TEST);
GL32.glDepthFunc(GL32.GL_LESS);
if(GL32.glCheckFramebufferStatus(GL32.GL_FRAMEBUFFER) != GL32.GL_FRAMEBUFFER_COMPLETE)
{
// This generally means something wasn't bound, IE missing either the color or depth texture
tickLogger.warn("FrameBuffer ["+this.framebufferId+"] isn't complete.");
}
// Set OpenGL polygon mode
boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get();
if (renderWireframe)
@@ -514,9 +486,26 @@ public class LodRenderer
}
// Generate framebuffer, color texture, and depth render buffer
this.framebufferId = GL32.glGenFramebuffers();
this.colorTextureId = GL32.glGenTextures();
this.depthTextureId = GL32.glGenTextures();
this.framebuffer = new DHFramebuffer();
this.colorTexture = DHColorTexture.builder().setDimensions(MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight())
.setInternalFormat(DHInternalTextureFormat.RGBA8)
.setPixelType(DHPixelType.UNSIGNED_BYTE)
.setPixelFormat(DHPixelFormat.RGBA)
.build();
this.depthTexture = new DHDepthTexture(MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight(), DHDepthBufferFormat.DEPTH32F);
this.framebuffer.addDepthAttachment(depthTexture.getTextureId(), DHDepthBufferFormat.DEPTH32F);
this.framebuffer.addColorAttachment(0, colorTexture.getTexture());
this.cachedWidth = MC_RENDER.getTargetFrameBufferViewportWidth();
this.cachedHeight = MC_RENDER.getTargetFrameBufferViewportHeight();
if(framebuffer.getStatus() != GL32.GL_FRAMEBUFFER_COMPLETE)
{
// This generally means something wasn't bound, IE missing either the color or depth texture
tickLogger.warn("FrameBuffer ["+this.framebuffer.getId()+"] isn't complete.");
}
EVENT_LOGGER.info("Renderer setup complete");
}
@@ -600,12 +589,9 @@ public class LodRenderer
}
// Delete framebuffer, color texture, and depth texture
if (this.framebufferId != -1)
GL32.glDeleteFramebuffers(this.framebufferId);
if (this.colorTextureId != -1)
GL32.glDeleteTextures(this.colorTextureId);
if (this.depthTextureId != -1)
GL32.glDeleteTextures(this.depthTextureId);
this.framebuffer.destroyInternal();
this.colorTexture.destroy();
this.depthTexture.destroy();
EVENT_LOGGER.info("Renderer Cleanup Complete");
});