From 5e99efe093befa6c455ee305b58c07cee00f13e0 Mon Sep 17 00:00:00 2001 From: morippi Date: Thu, 21 Jul 2022 16:32:47 +0200 Subject: [PATCH] block that touch trasparent surfaces are added in the building phase and added to the rendering phase. Transparenc is not working for some reason --- .../core/enums/config/VerticalQuality.java | 2 +- .../lod/core/objects/opengl/LodBox.java | 24 ++-- .../lod/core/objects/opengl/RenderRegion.java | 134 +++++++++--------- .../seibel/lod/core/render/LodRenderer.java | 5 +- .../seibel/lod/core/util/DataPointUtil.java | 6 +- 5 files changed, 94 insertions(+), 77 deletions(-) diff --git a/src/main/java/com/seibel/lod/core/enums/config/VerticalQuality.java b/src/main/java/com/seibel/lod/core/enums/config/VerticalQuality.java index 833d6a772..b62c0c69e 100644 --- a/src/main/java/com/seibel/lod/core/enums/config/VerticalQuality.java +++ b/src/main/java/com/seibel/lod/core/enums/config/VerticalQuality.java @@ -44,7 +44,7 @@ public enum VerticalQuality ), ULTRA( - new int[] { 16, 8, 4, 2, 2, 2, 2, 1, 1, 1, 1 }, + new int[] { 16, 16, 8, 8, 4, 4, 4, 1, 1, 1, 1 }, 12 ); diff --git a/src/main/java/com/seibel/lod/core/objects/opengl/LodBox.java b/src/main/java/com/seibel/lod/core/objects/opengl/LodBox.java index bdde5c9e3..a00e032a5 100644 --- a/src/main/java/com/seibel/lod/core/objects/opengl/LodBox.java +++ b/src/main/java/com/seibel/lod/core/objects/opengl/LodBox.java @@ -38,13 +38,20 @@ public class LodBox short maxY = (short) (y + ySize); short maxZ = (short) (z + zSize); byte skyLightTop = skyLight; + boolean isTransparent = ColorUtil.getAlpha(color)<255; + boolean isTopTransparent = DataPointUtil.isTransparent(topData); + boolean isBotTransparent = DataPointUtil.isTransparent(botData); byte skyLightBot = DataPointUtil.doesItExist(botData) ? DataPointUtil.getLightSky(botData) : 0; - // Up direction case - boolean skipTop = DataPointUtil.doesItExist(topData) && DataPointUtil.getDepth(topData) == maxY;// && + boolean skipTop = DataPointUtil.doesItExist(topData) && ( + (isTransparent && (DataPointUtil.getDepth(topData) == maxY)) || + (!isTransparent && (DataPointUtil.getDepth(topData) == maxY) && !isTopTransparent)); + boolean skipBot = DataPointUtil.doesItExist(botData) && ( + (isTransparent && (DataPointUtil.getDepth(botData) == maxY)) || + (!isTransparent && (DataPointUtil.getDepth(botData) == maxY) && !isBotTransparent)); // DataPointUtil.getAlpha(singleAdjDataPoint) // == 255; - boolean skipBot = DataPointUtil.doesItExist(botData) && DataPointUtil.getHeight(botData) == y;// && + //boolean skipBot = DataPointUtil.doesItExist(botData) && DataPointUtil.getHeight(botData) == y;// && // DataPointUtil.getAlpha(singleAdjDataPoint) // == 255; @@ -148,6 +155,8 @@ public class LodBox private static void makeAdjQuads(LodQuadBuilder builder, long[] adjData, LodDirection direction, short x, short y, short z, short w0, short wy, int color, int overlapColor, byte upSkyLight, byte blockLight) { + + boolean isTransparent = ColorUtil.getAlpha(color)<255; color = ColorUtil.applyShade(color, MC.getShade(direction)); long[] dataPoint = adjData; if (dataPoint == null || DataPointUtil.isVoid(dataPoint[0])) @@ -164,14 +173,13 @@ public class LodBox // TODO transparency ocean floor fix // boolean isOpaque = ((colorMap[0] >> 24) & 0xFF) == 255; - for (i = 0; i < dataPoint.length && DataPointUtil.doesItExist(adjData[i]) - && !DataPointUtil.isVoid(adjData[i]); i++) + for (i = 0; i < dataPoint.length && DataPointUtil.doesItExist(adjData[i]) && !DataPointUtil.isVoid(adjData[i]); i++) { long adjPoint = adjData[i]; - + boolean isAdjTransparent = DataPointUtil.isTransparent(adjPoint); // TODO transparency ocean floor fix - // if (isOpaque && DataPointUtil.getAlpha(singleAdjDataPoint) != 255) - // continue; + if (!isTransparent && isAdjTransparent) + continue; short height = DataPointUtil.getHeight(adjPoint); short depth = DataPointUtil.getDepth(adjPoint); diff --git a/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java b/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java index d045e2811..c3a13ae70 100644 --- a/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java +++ b/src/main/java/com/seibel/lod/core/objects/opengl/RenderRegion.java @@ -277,7 +277,7 @@ public class RenderRegion implements AutoCloseable private static void makeLodRenderData(LodQuadBuilder quadBuilder, LodRegion region, LodRegion[] adjRegions, int playerX, int playerZ) { byte minDetail = region.getMinDetailLevel(); - + // Variable initialization DebugMode debugMode = CONFIG.client().advanced().debugging().getDebugMode(); @@ -292,7 +292,7 @@ public class RenderRegion implements AutoCloseable byte detailLevel = posToRender.getNthDetailLevel(index); int posX = posToRender.getNthPosX(index); int posZ = posToRender.getNthPosZ(index); - + // TODO: In the future, We don't need to ignore rendered chunks! Just build it // and leave it for the renderer to decide! // We don't want to render this fake block if @@ -311,7 +311,7 @@ public class RenderRegion implements AutoCloseable if (posData == null || posData.length == 0 || !DataPointUtil.doesItExist(posData[0]) || DataPointUtil.isVoid(posData[0])) continue; - + long[][][] adjData = new long[4][][]; boolean[] adjUseBlack = new boolean[4]; @@ -321,79 +321,83 @@ public class RenderRegion implements AutoCloseable // border when we have transparent block like water or glass // to avoid having a "darker border" underground // Arrays.fill(adjShadeDisabled, false); - + // We check every adj block in each direction - + // If the adj block is rendered in the same region and with same detail // and is positioned in a place that is not going to be rendered by vanilla game // then we can set this position as adj // We avoid cases where the adjPosition is in player chunk while the position is // not // to always have a wall underwater - for (LodDirection lodDirection : LodDirection.ADJ_DIRECTIONS) { - try { - int xAdj = posX + lodDirection.getNormal().x; - int zAdj = posZ + lodDirection.getNormal().z; - int chunkXAdj = LevelPosUtil.getChunkPos(detailLevel, xAdj); - int chunkZAdj = LevelPosUtil.getChunkPos(detailLevel, zAdj); - if (chunkGrid != null && chunkGrid.get(chunkXAdj, chunkZAdj)!=null) { - adjUseBlack[lodDirection.ordinal()-2] = true; + for (int transparency = 0; transparency < 2; transparency++) + { + for (LodDirection lodDirection : LodDirection.ADJ_DIRECTIONS) { + try { + int xAdj = posX + lodDirection.getNormal().x; + int zAdj = posZ + lodDirection.getNormal().z; + int chunkXAdj = LevelPosUtil.getChunkPos(detailLevel, xAdj); + int chunkZAdj = LevelPosUtil.getChunkPos(detailLevel, zAdj); + if (chunkGrid != null && chunkGrid.get(chunkXAdj, chunkZAdj) != null) { + adjUseBlack[lodDirection.ordinal() - 2] = true; + } + + boolean isCrossRegionBoundary = LevelPosUtil.getRegion(detailLevel, xAdj) != region.regionPosX || + LevelPosUtil.getRegion(detailLevel, zAdj) != region.regionPosZ; + + LodRegion adjRegion; + byte adjDetail; + int childXAdj = xAdj * 2 + (lodDirection.getNormal().x < 0 ? 1 : 0); + int childZAdj = zAdj * 2 + (lodDirection.getNormal().z < 0 ? 1 : 0); + + //we check if the detail of the adjPos is equal to the correct one (region border fix) + //or if the detail is wrong by 1 value (region+circle border fix) + if (isCrossRegionBoundary) { + //we compute at which detail that position should be rendered + adjRegion = adjRegions[lodDirection.ordinal() - 2]; + if (adjRegion == null) continue; + adjDetail = adjRegion.getRenderDetailLevelAt(playerX, playerZ, detailLevel, xAdj, zAdj); + } else { + adjRegion = region; + if (posToRender.contains(detailLevel, xAdj, zAdj)) adjDetail = detailLevel; + else if (detailLevel > 0 && + posToRender.contains((byte) (detailLevel - 1), childXAdj, childZAdj)) + adjDetail = (byte) (detailLevel - 1); + else if (detailLevel < LodUtil.REGION_DETAIL_LEVEL && + posToRender.contains((byte) (detailLevel + 1), xAdj / 2, zAdj / 2)) + adjDetail = (byte) (detailLevel + 1); + else continue; + } + + if (adjDetail < detailLevel - 1 || adjDetail > detailLevel + 1) { + continue; + } + + if (adjDetail == detailLevel || adjDetail > detailLevel) { + adjData[lodDirection.ordinal() - 2] = new long[1][]; + adjData[lodDirection.ordinal() - 2][0] = adjRegion.getAllData(adjDetail, + LevelPosUtil.convert(detailLevel, xAdj, adjDetail), + LevelPosUtil.convert(detailLevel, zAdj, adjDetail)); + } else { + adjData[lodDirection.ordinal() - 2] = new long[2][]; + adjData[lodDirection.ordinal() - 2][0] = adjRegion.getAllData(adjDetail, + childXAdj, childZAdj); + adjData[lodDirection.ordinal() - 2][1] = adjRegion.getAllData(adjDetail, + childXAdj + (lodDirection.getAxis() == LodDirection.Axis.X ? 0 : 1), + childZAdj + (lodDirection.getAxis() == LodDirection.Axis.Z ? 0 : 1)); + } + } catch (RuntimeException e) { + EVENT_LOGGER.warn("Failed to get adj data for [{}:{},{}] at [{}]", detailLevel, posX, posZ, lodDirection); + EVENT_LOGGER.warn("Detail exception: ", e); } - - boolean isCrossRegionBoundary = LevelPosUtil.getRegion(detailLevel, xAdj) != region.regionPosX || - LevelPosUtil.getRegion(detailLevel, zAdj) != region.regionPosZ; - - LodRegion adjRegion; - byte adjDetail; - int childXAdj = xAdj*2 + (lodDirection.getNormal().x<0 ? 1 : 0); - int childZAdj = zAdj*2 + (lodDirection.getNormal().z<0 ? 1 : 0); - - //we check if the detail of the adjPos is equal to the correct one (region border fix) - //or if the detail is wrong by 1 value (region+circle border fix) - if (isCrossRegionBoundary) { - //we compute at which detail that position should be rendered - adjRegion = adjRegions[lodDirection.ordinal()-2]; - if(adjRegion == null) continue; - adjDetail = adjRegion.getRenderDetailLevelAt(playerX, playerZ, detailLevel, xAdj, zAdj); - } else { - adjRegion = region; - if (posToRender.contains(detailLevel, xAdj, zAdj)) adjDetail = detailLevel; - else if (detailLevel>0 && - posToRender.contains((byte) (detailLevel-1), childXAdj, childZAdj)) - adjDetail = (byte) (detailLevel-1); - else if (detailLevel detailLevel+1) { - continue; - } - - if (adjDetail == detailLevel || adjDetail > detailLevel) { - adjData[lodDirection.ordinal() - 2] = new long[1][]; - adjData[lodDirection.ordinal() - 2][0] = adjRegion.getAllData(adjDetail, - LevelPosUtil.convert(detailLevel, xAdj, adjDetail), - LevelPosUtil.convert(detailLevel, zAdj, adjDetail)); - } else { - adjData[lodDirection.ordinal() - 2] = new long[2][]; - adjData[lodDirection.ordinal() - 2][0] = adjRegion.getAllData(adjDetail, - childXAdj, childZAdj); - adjData[lodDirection.ordinal() - 2][1] = adjRegion.getAllData(adjDetail, - childXAdj + (lodDirection.getAxis()==LodDirection.Axis.X ? 0 : 1), - childZAdj + (lodDirection.getAxis()==LodDirection.Axis.Z ? 0 : 1)); - } - } catch (RuntimeException e) { - EVENT_LOGGER.warn("Failed to get adj data for [{}:{},{}] at [{}]", detailLevel, posX, posZ, lodDirection); - EVENT_LOGGER.warn("Detail exception: ", e); } - } - + // We render every vertical lod present in this position // We only stop when we find a block that is void or non-existing block for (int i = 0; i < posData.length; i++) { long data = posData[i]; + if (DataPointUtil.isTransparent(data) == (transparency == 1)) + continue; // If the data is not renderable (Void or non-existing) we stop since there is // no data left in this position if (DataPointUtil.isVoid(data) || !DataPointUtil.doesItExist(data)) @@ -407,8 +411,8 @@ public class RenderRegion implements AutoCloseable LevelPosUtil.getRegionModule(detailLevel, posX), LevelPosUtil.getRegionModule(detailLevel, posZ), quadBuilder, debugMode); } - - } // for pos to in list to render + } + }// for pos to in list to render // the thread executed successfully // Merge all quads quadBuilder.mergeQuads(); diff --git a/src/main/java/com/seibel/lod/core/render/LodRenderer.java b/src/main/java/com/seibel/lod/core/render/LodRenderer.java index 14e51eddc..a8f8a0697 100644 --- a/src/main/java/com/seibel/lod/core/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/core/render/LodRenderer.java @@ -267,8 +267,9 @@ public class LodRenderer drawEnableDepth.end("drawEnableDepth"); drawGLSetup.end("drawGLSetup"); // enable transparent rendering - // GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA); - // GL32.glEnable(GL32.GL_BLEND); + GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA); + GL32.glEnable(GL32.GL_BLEND); + GL32.glDisable(GL32.GL_BLEND); GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT); diff --git a/src/main/java/com/seibel/lod/core/util/DataPointUtil.java b/src/main/java/com/seibel/lod/core/util/DataPointUtil.java index e1dade03f..a421891a5 100644 --- a/src/main/java/com/seibel/lod/core/util/DataPointUtil.java +++ b/src/main/java/com/seibel/lod/core/util/DataPointUtil.java @@ -245,7 +245,11 @@ public class DataPointUtil long alpha = getAlpha(dataPoint); return (int) (((dataPoint >>> COLOR_SHIFT) & COLOR_MASK) | (alpha << (ALPHA_SHIFT-COLOR_SHIFT))); } - + + public static boolean isTransparent(long dataPoint){ + return getAlpha(dataPoint) < 255; + } + /** This is used to convert a dataPoint to string (useful for the print function) */ @SuppressWarnings("unused") public static String toString(long dataPoint)