mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-14 01:14:08 +00:00
Composite terrain behind block entities under Fancy translucency
This commit is contained in:
7 files changed
+208
-37
No files matched your search
@@ -103,8 +103,12 @@ public class PanoramaRenderer {
|
||||
}
|
||||
|
||||
public static <T> GlProgram<T> loadProgram(String name, String vertBase, String fragBase, Function<ShaderBindingContext, T> factory) {
|
||||
return loadProgram(name, vertBase, fragBase, ShaderConstants.EMPTY, factory);
|
||||
}
|
||||
|
||||
public static <T> GlProgram<T> loadProgram(String name, String vertBase, String fragBase, ShaderConstants fragConstants, Function<ShaderBindingContext, T> factory) {
|
||||
final GlShader vert = ShaderLoader.loadShader(ShaderType.VERTEX, vertBase + ".vert", ShaderConstants.EMPTY);
|
||||
final GlShader frag = ShaderLoader.loadShader(ShaderType.FRAGMENT, fragBase + ".frag", ShaderConstants.EMPTY);
|
||||
final GlShader frag = ShaderLoader.loadShader(ShaderType.FRAGMENT, fragBase + ".frag", fragConstants);
|
||||
try {
|
||||
final GlProgram<T> program = GlProgram.builder(name).attachShader(vert).attachShader(frag).link(factory);
|
||||
program.bind();
|
||||
|
||||
+3
@@ -13,6 +13,7 @@ import com.gtnewhorizons.angelica.rendering.TextureSamplers;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.api.IrisShaderProvider;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.api.IrisShaderProviderHolder;
|
||||
import com.gtnewhorizons.angelica.rendering.culling.GpuCulling;
|
||||
import com.gtnewhorizons.angelica.rendering.translucency.TranslucencyLayers;
|
||||
import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions;
|
||||
import me.jellysquid.mods.sodium.client.gui.options.named.MultiDrawMode;
|
||||
import com.gtnewhorizons.angelica.rendering.voxelization.SdlShadowVoxelizationSink;
|
||||
@@ -196,6 +197,7 @@ class AngelicaChunkRenderer extends DefaultChunkRenderer {
|
||||
if (program != null) {
|
||||
program.bind();
|
||||
program.getInterface().setupState(pass);
|
||||
if (pass == AngelicaRenderPassConfiguration.TRANSLUCENT_PASS) TranslucencyLayers.INSTANCE.beginTerrainSplit(program.handle());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +206,7 @@ class AngelicaChunkRenderer extends DefaultChunkRenderer {
|
||||
if (irisProgram != null) {
|
||||
endIrisPass(pass);
|
||||
} else {
|
||||
if (pass == AngelicaRenderPassConfiguration.TRANSLUCENT_PASS) TranslucencyLayers.INSTANCE.endTerrainSplit();
|
||||
super.end(pass);
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -81,6 +81,7 @@ public class AngelicaRenderPassConfiguration {
|
||||
.name("translucent")
|
||||
.useReverseOrder(true)
|
||||
.useTranslucencySorting(ClientProxy.options().performance.translucencyMode.sorts())
|
||||
.extraDefine("TRANSLUCENCY_SPLIT", "")
|
||||
.build();
|
||||
|
||||
TRANSLUCENT_MATERIAL = new Material(TRANSLUCENT_PASS, translucentCutoff, true);
|
||||
|
||||
+87
-17
@@ -25,6 +25,7 @@ import net.coderbot.iris.rendertarget.IRenderTargetExt;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.shader.Framebuffer;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.GlProgram;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.ShaderConstants;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
@@ -35,10 +36,18 @@ import java.nio.ByteBuffer;
|
||||
/// Draws each [TranslucentLayer] into its own target, seeded with the main depth, and composites the drawn layers over
|
||||
/// the main framebuffer per pixel, farthest first. Layers hold premultiplied color with coverage alpha (GLSM layer
|
||||
/// blending), and the composite writes the nearest layer depth.
|
||||
///
|
||||
/// The terrain layer has a second sheet for fragments behind the block-entity layer, so a tile entity inside a
|
||||
/// block's own translucent model is covered only by the faces in front of it.
|
||||
public final class TranslucencyLayers {
|
||||
|
||||
private static final int LAYERS = TranslucentLayer.values().length;
|
||||
private static final int FIRST_LAYER_UNIT = 1;
|
||||
private static final int TERRAIN_BEHIND_UNIT = FIRST_LAYER_UNIT + 2 * LAYERS;
|
||||
private static final int SPLIT_DEPTH_UNIT = TERRAIN_BEHIND_UNIT + 1;
|
||||
private static final int[] SINGLE_BUFFER = { 0 };
|
||||
private static final int[] SPLIT_BUFFERS = { 0, 1 };
|
||||
private static final int[] BEHIND_BUFFER = { 1 };
|
||||
|
||||
public static final TranslucencyLayers INSTANCE = new TranslucencyLayers(new MinecraftTarget());
|
||||
|
||||
@@ -66,8 +75,11 @@ public final class TranslucencyLayers {
|
||||
private int savedRead;
|
||||
private boolean alphaMasked;
|
||||
|
||||
private GlProgram<Object> program;
|
||||
private int maskUniform;
|
||||
private boolean splitting;
|
||||
private boolean behindDrawn;
|
||||
|
||||
private CompositeProgram program;
|
||||
private CompositeProgram behindProgram;
|
||||
private int vao;
|
||||
private StateSet prepareState;
|
||||
private StateSet compositeState;
|
||||
@@ -80,12 +92,14 @@ public final class TranslucencyLayers {
|
||||
public void beginFrame() {
|
||||
decided = false;
|
||||
drawnMask = 0;
|
||||
behindDrawn = false;
|
||||
}
|
||||
|
||||
void beginFrame(boolean active) {
|
||||
this.active = active;
|
||||
decided = true;
|
||||
drawnMask = 0;
|
||||
behindDrawn = false;
|
||||
}
|
||||
|
||||
public boolean active() {
|
||||
@@ -143,6 +157,33 @@ public final class TranslucencyLayers {
|
||||
layers[open.ordinal()].framebuffer.bind();
|
||||
}
|
||||
|
||||
public void beginTerrainSplit(int program) {
|
||||
splitting = open == TranslucentLayer.TERRAIN && (drawnMask & (1 << TranslucentLayer.BLOCK_ENTITIES.ordinal())) != 0;
|
||||
GLSMPrograms.glUniform1i(GLSMPrograms.glGetUniformLocation(program, "u_SplitEnabled"), splitting ? 1 : 0);
|
||||
if (!splitting) return;
|
||||
GLSMPrograms.glUniform1i(GLSMPrograms.glGetUniformLocation(program, "u_SplitDepth"), SPLIT_DEPTH_UNIT);
|
||||
final Target terrain = layers[TranslucentLayer.TERRAIN.ordinal()];
|
||||
if (!behindDrawn) {
|
||||
behindDrawn = true;
|
||||
terrain.attachBehind(width, height);
|
||||
terrain.framebuffer.drawBuffers(BEHIND_BUFFER);
|
||||
clear(terrain);
|
||||
}
|
||||
final int unit = GLSMTextures.getActiveTextureUnit();
|
||||
bindTexture(SPLIT_DEPTH_UNIT, layers[TranslucentLayer.BLOCK_ENTITIES.ordinal()].depth);
|
||||
GLSMTextures.glActiveTexture(GL13.GL_TEXTURE0 + unit);
|
||||
terrain.framebuffer.drawBuffers(SPLIT_BUFFERS);
|
||||
}
|
||||
|
||||
public void endTerrainSplit() {
|
||||
if (!splitting) return;
|
||||
splitting = false;
|
||||
layers[TranslucentLayer.TERRAIN.ordinal()].framebuffer.drawBuffers(SINGLE_BUFFER);
|
||||
final int unit = GLSMTextures.getActiveTextureUnit();
|
||||
bindTexture(SPLIT_DEPTH_UNIT, 0);
|
||||
GLSMTextures.glActiveTexture(GL13.GL_TEXTURE0 + unit);
|
||||
}
|
||||
|
||||
public void composite() {
|
||||
if (drawnMask == 0) return;
|
||||
BatchStateGuard.beforeChange();
|
||||
@@ -172,8 +213,10 @@ public final class TranslucencyLayers {
|
||||
bindTexture(FIRST_LAYER_UNIT + i, layers[i].color);
|
||||
bindTexture(FIRST_LAYER_UNIT + LAYERS + i, layers[i].depth);
|
||||
}
|
||||
GLSMPrograms.glUseProgram(program.handle());
|
||||
GLSMPrograms.glUniform1i(maskUniform, drawnMask);
|
||||
if (behindDrawn) bindTexture(TERRAIN_BEHIND_UNIT, layers[TranslucentLayer.TERRAIN.ordinal()].behind);
|
||||
final CompositeProgram composite = behindDrawn ? behindProgram : program;
|
||||
GLSMPrograms.glUseProgram(composite.program.handle());
|
||||
GLSMPrograms.glUniform1i(composite.maskUniform, drawnMask);
|
||||
GLSMVertexInput.glBindVertexArray(vao);
|
||||
GLSMDraws.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
|
||||
} finally {
|
||||
@@ -183,34 +226,34 @@ public final class TranslucencyLayers {
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, read);
|
||||
GLSMAttribStack.popStateTo(depth);
|
||||
drawnMask = 0;
|
||||
behindDrawn = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
destroyTargets();
|
||||
if (program != null) {
|
||||
program.delete();
|
||||
program.program.delete();
|
||||
behindProgram.program.delete();
|
||||
GLSMVertexInput.glDeleteVertexArrays(vao);
|
||||
program = null;
|
||||
behindProgram = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void initProgram() {
|
||||
program = PanoramaRenderer.loadProgram("angelica:translucency_composite", "angelica:panorama_blur", "angelica:translucency_composite", ctx -> ctx);
|
||||
final int handle = program.handle();
|
||||
GLSMPrograms.glUseProgram(handle);
|
||||
GLSMPrograms.glUniform1i(GLSMPrograms.glGetUniformLocation(handle, "u_Depth"), 0);
|
||||
for (int i = 0; i < LAYERS; i++) {
|
||||
GLSMPrograms.glUniform1i(GLSMPrograms.glGetUniformLocation(handle, "u_Layer" + i), FIRST_LAYER_UNIT + i);
|
||||
GLSMPrograms.glUniform1i(GLSMPrograms.glGetUniformLocation(handle, "u_LayerDepth" + i), FIRST_LAYER_UNIT + LAYERS + i);
|
||||
}
|
||||
maskUniform = GLSMPrograms.glGetUniformLocation(handle, "u_LayerMask");
|
||||
GLSMPrograms.glUseProgram(0);
|
||||
program = new CompositeProgram("angelica:translucency_composite", ShaderConstants.EMPTY);
|
||||
behindProgram = new CompositeProgram("angelica:translucency_composite_behind", ShaderConstants.builder().add("TERRAIN_BEHIND").build());
|
||||
vao = GLSMVertexInput.glGenVertexArrays();
|
||||
compositeState = StateSet.forMask(GL11.GL_ALL_ATTRIB_BITS);
|
||||
}
|
||||
|
||||
private void prepare(Target target) {
|
||||
clear(target);
|
||||
blit(main.framebuffer(), target.framebuffer.getId(), depthFormat.isCombinedStencil() ? GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT : GL11.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
private void clear(Target target) {
|
||||
if (prepareState == null) prepareState = StateSet.forMask(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_SCISSOR_BIT);
|
||||
final int depth = GLSMAttribStack.pushState(prepareState);
|
||||
try {
|
||||
@@ -219,7 +262,6 @@ public final class TranslucencyLayers {
|
||||
target.framebuffer.bind();
|
||||
GLSMBlend.glClearColor(0f, 0f, 0f, 0f);
|
||||
GLSMFramebuffer.glClear(GL11.GL_COLOR_BUFFER_BIT);
|
||||
blit(main.framebuffer(), target.framebuffer.getId(), depthFormat.isCombinedStencil() ? GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT : GL11.GL_DEPTH_BUFFER_BIT);
|
||||
} finally {
|
||||
GLSMAttribStack.popStateTo(depth);
|
||||
}
|
||||
@@ -264,12 +306,33 @@ public final class TranslucencyLayers {
|
||||
if (depthSnapshot != null) depthSnapshot.destroy();
|
||||
depthSnapshot = null;
|
||||
drawnMask = 0;
|
||||
behindDrawn = false;
|
||||
}
|
||||
|
||||
private static final class CompositeProgram {
|
||||
final GlProgram<Object> program;
|
||||
final int maskUniform;
|
||||
|
||||
CompositeProgram(String name, ShaderConstants constants) {
|
||||
program = PanoramaRenderer.loadProgram(name, "angelica:panorama_blur", "angelica:translucency_composite", constants, ctx -> ctx);
|
||||
final int handle = program.handle();
|
||||
GLSMPrograms.glUseProgram(handle);
|
||||
GLSMPrograms.glUniform1i(GLSMPrograms.glGetUniformLocation(handle, "u_Depth"), 0);
|
||||
for (int i = 0; i < LAYERS; i++) {
|
||||
GLSMPrograms.glUniform1i(GLSMPrograms.glGetUniformLocation(handle, "u_Layer" + i), FIRST_LAYER_UNIT + i);
|
||||
GLSMPrograms.glUniform1i(GLSMPrograms.glGetUniformLocation(handle, "u_LayerDepth" + i), FIRST_LAYER_UNIT + LAYERS + i);
|
||||
}
|
||||
GLSMPrograms.glUniform1i(GLSMPrograms.glGetUniformLocation(handle, "u_TerrainBehind"), TERRAIN_BEHIND_UNIT);
|
||||
maskUniform = GLSMPrograms.glGetUniformLocation(handle, "u_LayerMask");
|
||||
GLSMPrograms.glUseProgram(0);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Target {
|
||||
final int color;
|
||||
final int depth;
|
||||
final GlFramebuffer framebuffer;
|
||||
int behind;
|
||||
|
||||
Target(int width, int height, DepthBufferFormat depthFormat, boolean withColor) {
|
||||
depth = texture(width, height, depthFormat.getGlInternalFormat(), depthFormat.getGlType(), depthFormat.getGlFormat());
|
||||
@@ -278,7 +341,7 @@ public final class TranslucencyLayers {
|
||||
if (withColor) {
|
||||
color = texture(width, height, GL11.GL_RGBA8, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE);
|
||||
framebuffer.addColorAttachment(0, color);
|
||||
framebuffer.drawBuffers(new int[] { 0 });
|
||||
framebuffer.drawBuffers(SINGLE_BUFFER);
|
||||
framebuffer.readBuffer(0);
|
||||
} else {
|
||||
color = 0;
|
||||
@@ -287,6 +350,12 @@ public final class TranslucencyLayers {
|
||||
}
|
||||
}
|
||||
|
||||
void attachBehind(int width, int height) {
|
||||
if (behind != 0) return;
|
||||
behind = texture(width, height, GL11.GL_RGBA8, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE);
|
||||
framebuffer.addColorAttachment(1, behind);
|
||||
}
|
||||
|
||||
private static int texture(int width, int height, int internalFormat, int format, int type) {
|
||||
final int previous = GLSMQueries.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||
final int texture = GLSMTextures.glGenTextures();
|
||||
@@ -303,6 +372,7 @@ public final class TranslucencyLayers {
|
||||
void destroy() {
|
||||
framebuffer.destroy();
|
||||
if (color != 0) GLSMTextures.glDeleteTextures(color);
|
||||
if (behind != 0) GLSMTextures.glDeleteTextures(behind);
|
||||
GLSMTextures.glDeleteTextures(depth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,13 @@ out vec4 fragColor; // The output fragment for the color framebuffer
|
||||
#define fragColor gl_FragColor
|
||||
#endif
|
||||
|
||||
#if !defined(LEGACY) && defined(TRANSLUCENCY_SPLIT)
|
||||
// Fragments behind the block-entity layer's depth go to a second sheet (TranslucencyLayers).
|
||||
uniform bool u_SplitEnabled;
|
||||
uniform sampler2D u_SplitDepth;
|
||||
layout(location = 1) out vec4 fragBehind;
|
||||
#endif
|
||||
|
||||
vec2 snapToTexelCentre(vec2 uv, vec2 texelSize, vec2 texelsPerPixel) {
|
||||
vec2 centreCoords = uv / texelSize - 0.5;
|
||||
vec2 lowerCentre = floor(centreCoords);
|
||||
@@ -237,4 +244,12 @@ void main() {
|
||||
#else // No fog
|
||||
fragColor = diffuseColor;
|
||||
#endif
|
||||
|
||||
#if !defined(LEGACY) && defined(TRANSLUCENCY_SPLIT)
|
||||
fragBehind = vec4(0.0);
|
||||
if (u_SplitEnabled && gl_FragCoord.z > texelFetch(u_SplitDepth, ivec2(gl_FragCoord.xy), 0).r) {
|
||||
fragBehind = fragColor;
|
||||
fragColor = vec4(0.0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#version 330 core
|
||||
|
||||
// A sample is skipped only when all zero, so additive light with no coverage still counts.
|
||||
// A sample is skipped only when all zero, so additive light with no coverage still counts. The TERRAIN_BEHIND sheet
|
||||
// sorts at the block-entity depth where the front sheet has terrain, inserted first so a tie keeps it behind.
|
||||
|
||||
in vec2 v_TexCoord;
|
||||
|
||||
@@ -16,19 +17,21 @@ uniform sampler2D u_LayerDepth2;
|
||||
uniform sampler2D u_LayerDepth3;
|
||||
uniform sampler2D u_LayerDepth4;
|
||||
uniform int u_LayerMask;
|
||||
#ifdef TERRAIN_BEHIND
|
||||
uniform sampler2D u_TerrainBehind;
|
||||
#define SHEETS 6
|
||||
#else
|
||||
#define SHEETS 5
|
||||
#endif
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
vec4 colors[5];
|
||||
float depths[5];
|
||||
vec4 colors[SHEETS];
|
||||
float depths[SHEETS];
|
||||
int count = 0;
|
||||
float mainDepth;
|
||||
|
||||
void insert(int bit, sampler2D colorTexture, sampler2D depthTexture) {
|
||||
if ((u_LayerMask & bit) == 0) return;
|
||||
vec4 color = texture(colorTexture, v_TexCoord);
|
||||
if (color == vec4(0.0)) return;
|
||||
float depth = texture(depthTexture, v_TexCoord).r;
|
||||
void insertSheet(vec4 color, float depth) {
|
||||
if (depth > mainDepth) return;
|
||||
int j = count++;
|
||||
colors[j] = color;
|
||||
@@ -44,9 +47,31 @@ void insert(int bit, sampler2D colorTexture, sampler2D depthTexture) {
|
||||
}
|
||||
}
|
||||
|
||||
void insert(int bit, sampler2D colorTexture, sampler2D depthTexture) {
|
||||
if ((u_LayerMask & bit) == 0) return;
|
||||
vec4 color = texture(colorTexture, v_TexCoord);
|
||||
if (color == vec4(0.0)) return;
|
||||
insertSheet(color, texture(depthTexture, v_TexCoord).r);
|
||||
}
|
||||
|
||||
#ifdef TERRAIN_BEHIND
|
||||
void insertTerrain() {
|
||||
vec4 behind = texture(u_TerrainBehind, v_TexCoord);
|
||||
vec4 front = texture(u_Layer0, v_TexCoord);
|
||||
if (behind != vec4(0.0)) {
|
||||
insertSheet(behind, front == vec4(0.0) ? texture(u_LayerDepth0, v_TexCoord).r : texture(u_LayerDepth1, v_TexCoord).r);
|
||||
}
|
||||
if (front != vec4(0.0)) insertSheet(front, texture(u_LayerDepth0, v_TexCoord).r);
|
||||
}
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
mainDepth = texture(u_Depth, v_TexCoord).r;
|
||||
#ifdef TERRAIN_BEHIND
|
||||
insertTerrain();
|
||||
#else
|
||||
insert(1, u_Layer0, u_LayerDepth0);
|
||||
#endif
|
||||
insert(2, u_Layer1, u_LayerDepth1);
|
||||
insert(4, u_Layer2, u_LayerDepth2);
|
||||
insert(8, u_Layer3, u_LayerDepth3);
|
||||
|
||||
+64
-11
@@ -42,11 +42,25 @@ class TranslucencyCompositeGLTest {
|
||||
out vec4 color;
|
||||
void main() { color = u_Color; }
|
||||
""";
|
||||
private static final String SPLIT_FS = """
|
||||
#version 330 core
|
||||
uniform vec4 u_Color;
|
||||
uniform bool u_SplitEnabled;
|
||||
uniform sampler2D u_SplitDepth;
|
||||
layout(location = 0) out vec4 front;
|
||||
layout(location = 1) out vec4 behind;
|
||||
void main() {
|
||||
bool back = u_SplitEnabled && gl_FragCoord.z > texelFetch(u_SplitDepth, ivec2(gl_FragCoord.xy), 0).r;
|
||||
front = back ? vec4(0.0) : u_Color;
|
||||
behind = back ? u_Color : vec4(0.0);
|
||||
}
|
||||
""";
|
||||
|
||||
private int colorTex;
|
||||
private int depthTex;
|
||||
private GlFramebuffer main;
|
||||
private int quadProgram;
|
||||
private int splitProgram;
|
||||
private int vao;
|
||||
private TranslucencyLayers layers;
|
||||
|
||||
@@ -62,6 +76,7 @@ class TranslucencyCompositeGLTest {
|
||||
main.bind();
|
||||
GLSMRasterizer.glViewport(0, 0, WIDTH, 1);
|
||||
quadProgram = GlTestSupport.program(QUAD_VS, QUAD_FS);
|
||||
splitProgram = GlTestSupport.program(QUAD_VS, SPLIT_FS);
|
||||
vao = GLSMVertexInput.glGenVertexArrays();
|
||||
layers = new TranslucencyLayers(new TranslucencyLayers.MainTarget() {
|
||||
@Override public int framebuffer() { return main.getId(); }
|
||||
@@ -87,6 +102,7 @@ class TranslucencyCompositeGLTest {
|
||||
GLSMTextures.glDeleteTextures(depthTex);
|
||||
GLSMPrograms.glUseProgram(0);
|
||||
GLSMPrograms.glDeleteProgram(quadProgram);
|
||||
GLSMPrograms.glDeleteProgram(splitProgram);
|
||||
GLSMVertexInput.glDeleteVertexArrays(vao);
|
||||
GLSMBlend.disableBlend();
|
||||
GLSMDepthStencilAlpha.disableDepthTest();
|
||||
@@ -105,20 +121,36 @@ class TranslucencyCompositeGLTest {
|
||||
return tex;
|
||||
}
|
||||
|
||||
private void drawInto(TranslucentLayer layer, int column, float depth, float r, float g, float b, float a) {
|
||||
drawInto(layer, column, depth, r, g, b, a, GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
private void drawInto(TranslucentLayer layer, int column, float depth, float r, float g, float b, float a, int srcRgb, int dstRgb) {
|
||||
layers.begin(layer);
|
||||
GLSMBlend.enableBlend();
|
||||
GLSMBlend.glBlendFunc(srcRgb, dstRgb);
|
||||
draw(column, depth, r, g, b, a);
|
||||
GLSMBlend.disableBlend();
|
||||
drawBlended(quadProgram, column, depth, r, g, b, a, srcRgb, dstRgb);
|
||||
layers.end();
|
||||
}
|
||||
|
||||
private void drawBlended(int program, int column, float depth, float r, float g, float b, float a, int srcRgb, int dstRgb) {
|
||||
GLSMBlend.enableBlend();
|
||||
GLSMBlend.glBlendFunc(srcRgb, dstRgb);
|
||||
draw(program, column, depth, r, g, b, a);
|
||||
GLSMBlend.disableBlend();
|
||||
}
|
||||
|
||||
private void drawTerrain(int column, float depth, float r, float g, float b, float a) {
|
||||
drawBlended(splitProgram, column, depth, r, g, b, a, GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
private void draw(int column, float depth, float r, float g, float b, float a) {
|
||||
draw(quadProgram, column, depth, r, g, b, a);
|
||||
}
|
||||
|
||||
private void draw(int program, int column, float depth, float r, float g, float b, float a) {
|
||||
GLSMRasterizer.glViewport(column, 0, 1, 1);
|
||||
GLSMPrograms.glUseProgram(quadProgram);
|
||||
GLSMPrograms.glUniform1f(GLSMPrograms.glGetUniformLocation(quadProgram, "u_Depth"), depth);
|
||||
GLSMPrograms.glUniform4f(GLSMPrograms.glGetUniformLocation(quadProgram, "u_Color"), r, g, b, a);
|
||||
GLSMPrograms.glUseProgram(program);
|
||||
GLSMPrograms.glUniform1f(GLSMPrograms.glGetUniformLocation(program, "u_Depth"), depth);
|
||||
GLSMPrograms.glUniform4f(GLSMPrograms.glGetUniformLocation(program, "u_Color"), r, g, b, a);
|
||||
GLSMVertexInput.glBindVertexArray(vao);
|
||||
GLSMDraws.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
|
||||
GLSMVertexInput.glBindVertexArray(0);
|
||||
@@ -153,11 +185,11 @@ class TranslucencyCompositeGLTest {
|
||||
@Test
|
||||
void compositesLayersByDepthAndWritesNearestDepth() {
|
||||
layers.beginFrame(true);
|
||||
drawInto(TranslucentLayer.TERRAIN, 0, 0.3f, 0f, 1f, 0f, 0.5f, GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
drawInto(TranslucentLayer.PARTICLES, 0, 0.5f, 0f, 0f, 1f, 0.5f, GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
drawInto(TranslucentLayer.TERRAIN, 1, 0.95f, 0f, 0f, 1f, 0.5f, GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
drawInto(TranslucentLayer.TERRAIN, 0, 0.3f, 0f, 1f, 0f, 0.5f);
|
||||
drawInto(TranslucentLayer.PARTICLES, 0, 0.5f, 0f, 0f, 1f, 0.5f);
|
||||
drawInto(TranslucentLayer.TERRAIN, 1, 0.95f, 0f, 0f, 1f, 0.5f);
|
||||
drawInto(TranslucentLayer.CLOUDS, 2, 0.5f, 0f, 0.4f, 0f, 0f, GL11.GL_ONE, GL11.GL_ONE);
|
||||
drawInto(TranslucentLayer.TERRAIN, 3, 0.5f, 0f, 1f, 0f, 0.5f, GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
drawInto(TranslucentLayer.TERRAIN, 3, 0.5f, 0f, 1f, 0f, 0.5f);
|
||||
draw(3, 0.2f, 0f, 0f, 1f, 1f);
|
||||
layers.composite();
|
||||
|
||||
@@ -174,4 +206,25 @@ class TranslucencyCompositeGLTest {
|
||||
final ByteBuffer again = readColor();
|
||||
for (int i = 0; i < WIDTH * 4; i++) assertEquals(color.get(i), again.get(i), "a composite with no new layer draws changes nothing");
|
||||
}
|
||||
|
||||
@Test
|
||||
void terrainBehindTheBlockEntityLayerCompositesBehindIt() {
|
||||
layers.beginFrame(true);
|
||||
drawInto(TranslucentLayer.BLOCK_ENTITIES, 0, 0.5f, 0f, 0f, 1f, 0.5f);
|
||||
drawInto(TranslucentLayer.BLOCK_ENTITIES, 1, 0.5f, 0f, 0f, 1f, 0.5f);
|
||||
drawInto(TranslucentLayer.PARTICLES, 1, 0.55f, 0f, 1f, 0f, 0.5f);
|
||||
layers.begin(TranslucentLayer.TERRAIN);
|
||||
GLSMPrograms.glUseProgram(splitProgram);
|
||||
layers.beginTerrainSplit(splitProgram);
|
||||
drawTerrain(0, 0.6f, 0f, 1f, 0f, 0.5f);
|
||||
drawTerrain(0, 0.3f, 1f, 1f, 1f, 0.5f);
|
||||
drawTerrain(1, 0.6f, 1f, 1f, 1f, 0.5f);
|
||||
layers.endTerrainSplit();
|
||||
layers.end();
|
||||
layers.composite();
|
||||
|
||||
final ByteBuffer color = readColor();
|
||||
assertColumn(color, 0, 159, 159, 191);
|
||||
assertColumn(color, 1, 64, 96, 159);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user