Merge remote-tracking branch 'upstream-core/main'
This commit is contained in:
@@ -37,6 +37,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
@@ -204,7 +205,7 @@ public class ServerApi
|
||||
{
|
||||
// generate the chunk's lighting, ignoring neighbors.
|
||||
// not a perfect solution, but should prevent chunks from having completely broken lighting
|
||||
List<IChunkWrapper> nearbyChunkList = new LinkedList<>();
|
||||
ArrayList<IChunkWrapper> nearbyChunkList = new ArrayList<>(1);
|
||||
nearbyChunkList.add(chunkWrapper);
|
||||
DhLightingEngine.INSTANCE.lightChunk(chunkWrapper, nearbyChunkList, level.hasSkyLight() ? 15 : 0);
|
||||
chunkWrapper.setUseDhLighting(true);
|
||||
|
||||
+3
-2
@@ -44,6 +44,7 @@ public class LodDataBuilder
|
||||
|
||||
|
||||
ChunkSizedFullDataAccessor chunkData = new ChunkSizedFullDataAccessor(chunkWrapper.getChunkPos());
|
||||
int minBuildHeight = chunkWrapper.getMinFilledHeight();
|
||||
|
||||
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
|
||||
{
|
||||
@@ -71,7 +72,7 @@ public class LodDataBuilder
|
||||
}
|
||||
|
||||
|
||||
for (; y >= chunkWrapper.getMinBuildHeight(); y--)
|
||||
for (; y >= minBuildHeight; y--)
|
||||
{
|
||||
IBiomeWrapper newBiome = chunkWrapper.getBiome(x, y, z);
|
||||
IBlockStateWrapper newBlockState = chunkWrapper.getBlockState(x, y, z);
|
||||
@@ -94,7 +95,7 @@ public class LodDataBuilder
|
||||
}
|
||||
longs.add(FullDataPointUtil.encode(mappedId, lastY - y, y + 1 - chunkWrapper.getMinBuildHeight(), light));
|
||||
|
||||
chunkData.setSingleColumn(longs.toArray(new long[0]), x, z);
|
||||
chunkData.setSingleColumn(longs.toLongArray(), x, z);
|
||||
}
|
||||
}
|
||||
if (!canGenerateLodFromChunk(chunkWrapper)) return null;
|
||||
|
||||
+110
-67
@@ -19,7 +19,6 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.generation;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||
@@ -27,11 +26,14 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
|
||||
/**
|
||||
* This logic was roughly based on
|
||||
* <a href="https://github.com/PaperMC/Starlight/blob/acc8ed9634bbe27ec68e8842e420948bfa9707e7/TECHNICAL_DETAILS.md">Starlight's technical documentation</a>
|
||||
@@ -42,6 +44,15 @@ public class DhLightingEngine
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
public static final DhLightingEngine INSTANCE = new DhLightingEngine();
|
||||
|
||||
/**
|
||||
* Minor garbage collection optimization. <br>
|
||||
* Since these objects are always mutated anyway, using a {@link ThreadLocal} will allow us to
|
||||
* only create as many of these {@link DhBlockPos} as necessary.
|
||||
*/
|
||||
private static final ThreadLocal<DhBlockPos> PRIMARY_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new DhBlockPos());
|
||||
private static final ThreadLocal<DhBlockPos> SECONDARY_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new DhBlockPos());
|
||||
|
||||
|
||||
|
||||
private DhLightingEngine() { }
|
||||
|
||||
@@ -56,7 +67,7 @@ public class DhLightingEngine
|
||||
* @param nearbyChunkList should also contain centerChunk
|
||||
* @param maxSkyLight should be a value between 0 and 15
|
||||
*/
|
||||
public void lightChunk(IChunkWrapper centerChunk, List<IChunkWrapper> nearbyChunkList, int maxSkyLight)
|
||||
public void lightChunk(IChunkWrapper centerChunk, ArrayList<IChunkWrapper> nearbyChunkList, int maxSkyLight)
|
||||
{
|
||||
DhChunkPos centerChunkPos = centerChunk.getChunkPos();
|
||||
AdjacentChunkHolder adjacentChunkHolder = new AdjacentChunkHolder(centerChunk);
|
||||
@@ -88,8 +99,10 @@ public class DhLightingEngine
|
||||
// find all adjacent chunks
|
||||
// and get any necessary info from them
|
||||
boolean warningLogged = false;
|
||||
for (IChunkWrapper chunk : nearbyChunkList)
|
||||
for (int chunkIndex = 0; chunkIndex < nearbyChunkList.size(); chunkIndex++) // using iterators in high traffic areas can cause GC issues due to allocating a bunch of iterators, use an indexed for-loop instead
|
||||
{
|
||||
IChunkWrapper chunk = nearbyChunkList.get(chunkIndex);
|
||||
|
||||
if (chunk != null && requestedAdjacentPositions.contains(chunk.getChunkPos()))
|
||||
{
|
||||
// remove the newly found position
|
||||
@@ -101,17 +114,22 @@ public class DhLightingEngine
|
||||
|
||||
|
||||
// get and set the adjacent chunk's initial block lights
|
||||
List<DhBlockPos> blockLightPosList = chunk.getBlockLightPosList();
|
||||
for (DhBlockPos blockLightPos : blockLightPosList)
|
||||
final DhBlockPos relLightBlockPos = PRIMARY_BLOCK_POS_REF.get();
|
||||
final DhBlockPos relBlockPos = SECONDARY_BLOCK_POS_REF.get();
|
||||
|
||||
ArrayList<DhBlockPos> blockLightPosList = chunk.getBlockLightPosList();
|
||||
for (int blockLightIndex = 0; blockLightIndex < blockLightPosList.size(); blockLightIndex++) // using iterators in high traffic areas can cause GC issues due to allocating a bunch of iterators, use an indexed for-loop instead
|
||||
{
|
||||
DhBlockPos blockLightPos = blockLightPosList.get(blockLightIndex);
|
||||
blockLightPos.mutateToChunkRelativePos(relLightBlockPos);
|
||||
|
||||
// get the light
|
||||
DhBlockPos relLightBlockPos = blockLightPos.convertToChunkRelativePos();
|
||||
IBlockStateWrapper blockState = chunk.getBlockState(relLightBlockPos);
|
||||
int lightValue = blockState.getLightEmission();
|
||||
blockLightPosQueue.push(blockLightPos.x, blockLightPos.y, blockLightPos.z, lightValue);
|
||||
|
||||
// set the light
|
||||
DhBlockPos relBlockPos = blockLightPos.convertToChunkRelativePos();
|
||||
blockLightPos.mutateToChunkRelativePos(relBlockPos);
|
||||
chunk.setDhBlockLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, lightValue);
|
||||
}
|
||||
|
||||
@@ -142,7 +160,7 @@ public class DhLightingEngine
|
||||
|
||||
|
||||
// set the light
|
||||
DhBlockPos relBlockPos = skyLightPos.convertToChunkRelativePos();
|
||||
skyLightPos.mutateToChunkRelativePos(relBlockPos);
|
||||
chunk.setDhSkyLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, maxSkyLight);
|
||||
}
|
||||
}
|
||||
@@ -156,16 +174,7 @@ public class DhLightingEngine
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// validate that at least 1 chunk was found
|
||||
if (adjacentChunkHolder.size() == 0)
|
||||
{
|
||||
LOGGER.warn("Attempted to generate lighting for position [" + centerChunkPos + "], but neither that chunk nor any adjacent chunks were found. No chunk lighting was performed.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// block light
|
||||
this.propagateLightPosList(blockLightPosQueue, adjacentChunkHolder,
|
||||
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhBlockLight(relBlockPos.x, relBlockPos.y, relBlockPos.z),
|
||||
@@ -199,8 +208,9 @@ public class DhLightingEngine
|
||||
{
|
||||
// these objects are saved so they can be mutated throughout the method,
|
||||
// this reduces the number of allocations necessary, reducing GC pressure
|
||||
final DhBlockPos neighbourBlockPos = new DhBlockPos();
|
||||
final DhBlockPos relNeighbourBlockPos = new DhBlockPos();
|
||||
final LightPos lightPos = new LightPos(0, 0, 0, 0);
|
||||
final DhBlockPos neighbourBlockPos = PRIMARY_BLOCK_POS_REF.get();
|
||||
final DhBlockPos relNeighbourBlockPos = SECONDARY_BLOCK_POS_REF.get();
|
||||
|
||||
|
||||
// update each light position
|
||||
@@ -208,18 +218,16 @@ public class DhLightingEngine
|
||||
{
|
||||
// since we don't care about the order the positions are processed,
|
||||
// we can grab the last position instead of the first for a slight performance increase (this way the array doesn't need to be shifted over every loop)
|
||||
LightPos lightPos = lightPosQueue.pop();
|
||||
lightPosQueue.popMutate(lightPos);
|
||||
|
||||
DhBlockPos pos = lightPos.pos;
|
||||
int lightValue = lightPos.lightValue;
|
||||
|
||||
|
||||
// propagate the lighting in each cardinal direction, IE: -x, +x, -y, +y, -z, +z
|
||||
for (EDhDirection direction : EDhDirection.CARDINAL_DIRECTIONS)
|
||||
for (EDhDirection direction : EDhDirection.CARDINAL_DIRECTIONS) // since this is an array instead of an ArrayList this advanced for-loop shouldn't cause any GC issues
|
||||
{
|
||||
pos.offset(direction, neighbourBlockPos); // mutates neighbourBlockPos
|
||||
// converting the block pos into a relative position is necessary for accessing the light values in the chunk
|
||||
neighbourBlockPos.convertToChunkRelativePos(relNeighbourBlockPos); // mutates relNeighbourBlockPos
|
||||
lightPos.mutateOffset(direction, neighbourBlockPos);
|
||||
neighbourBlockPos.mutateToChunkRelativePos(relNeighbourBlockPos);
|
||||
|
||||
|
||||
// only continue if the light position is inside one of our chunks
|
||||
@@ -230,7 +238,7 @@ public class DhLightingEngine
|
||||
continue;
|
||||
}
|
||||
|
||||
if (relNeighbourBlockPos.y < neighbourChunk.getMinBuildHeight() || relNeighbourBlockPos.y > neighbourChunk.getMaxBuildHeight())
|
||||
if (relNeighbourBlockPos.y < neighbourChunk.getMinFilledHeight() || relNeighbourBlockPos.y > neighbourChunk.getMaxBuildHeight())
|
||||
{
|
||||
// the light pos is outside the chunk's min/max height,
|
||||
// this can happen if given a chunk that hasn't finished generating
|
||||
@@ -277,14 +285,13 @@ public class DhLightingEngine
|
||||
@FunctionalInterface
|
||||
interface ISetLightFunc { void setLight(IChunkWrapper chunk, DhBlockPos pos, int lightValue); }
|
||||
|
||||
private static class LightPos
|
||||
private static class LightPos extends DhBlockPos
|
||||
{
|
||||
public final DhBlockPos pos;
|
||||
public int lightValue;
|
||||
|
||||
public LightPos(DhBlockPos pos, int lightValue)
|
||||
public LightPos(int x, int y, int z, int lightValue)
|
||||
{
|
||||
this.pos = pos;
|
||||
super(x, y, z);
|
||||
this.lightValue = lightValue;
|
||||
}
|
||||
|
||||
@@ -293,35 +300,58 @@ public class DhLightingEngine
|
||||
/** holds the adjacent chunks without having to create new Pos objects */
|
||||
private static class AdjacentChunkHolder
|
||||
{
|
||||
ArrayList<IChunkWrapper> chunkArray = new ArrayList<>(9);
|
||||
final IChunkWrapper[] chunkArray = new IChunkWrapper[9];
|
||||
|
||||
|
||||
public AdjacentChunkHolder(IChunkWrapper centerWrapper)
|
||||
public AdjacentChunkHolder(IChunkWrapper centerWrapper) { this.chunkArray[4] = centerWrapper; }
|
||||
|
||||
|
||||
public void add(IChunkWrapper centerWrapper)
|
||||
{
|
||||
this.chunkArray.add(centerWrapper);
|
||||
DhChunkPos centerPos = this.chunkArray[4].getChunkPos();
|
||||
DhChunkPos offsetPos = centerWrapper.getChunkPos();
|
||||
|
||||
int offsetX = offsetPos.x - centerPos.x;
|
||||
if (offsetX < -1 || offsetX > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int offsetZ = offsetPos.z - centerPos.z;
|
||||
if (offsetZ < -1 || offsetZ > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// equivalent to 4 + offsetX + (offsetZ * 3).
|
||||
this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)] = centerWrapper;
|
||||
}
|
||||
|
||||
|
||||
public int size() { return this.chunkArray.size(); }
|
||||
|
||||
public void add(IChunkWrapper centerWrapper) { this.chunkArray.add(centerWrapper); }
|
||||
|
||||
|
||||
public IChunkWrapper getByBlockPos(int blockX, int blockZ)
|
||||
{
|
||||
// >> 4 is equivalent to dividing by 16
|
||||
int chunkX = blockX >> 4;
|
||||
int chunkZ = blockZ >> 4;
|
||||
|
||||
// since there will only ever be 9 items in the array, this sequential search should be fast enough
|
||||
for (IChunkWrapper chunk : this.chunkArray)
|
||||
int chunkX = BitShiftUtil.divideByPowerOfTwo(blockX, 4);
|
||||
int chunkZ = BitShiftUtil.divideByPowerOfTwo(blockZ, 4);
|
||||
IChunkWrapper centerChunk = this.chunkArray[4];
|
||||
DhChunkPos centerPos = centerChunk.getChunkPos();
|
||||
if (centerPos.x == chunkX && centerPos.z == chunkZ)
|
||||
{
|
||||
if (chunk != null
|
||||
&& chunk.getChunkPos().x == chunkX && chunk.getChunkPos().z == chunkZ)
|
||||
{
|
||||
return chunk;
|
||||
}
|
||||
return centerChunk;
|
||||
}
|
||||
return null;
|
||||
|
||||
int offsetX = chunkX - centerPos.x;
|
||||
if (offsetX < -1 || offsetX > 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int offsetZ = chunkZ - centerPos.z;
|
||||
if (offsetZ < -1 || offsetZ > 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// equivalent to 4 + offsetX + (offsetZ * 3).
|
||||
return this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,10 +368,15 @@ public class DhLightingEngine
|
||||
|
||||
/** the index of the last item in the array, -1 if empty */
|
||||
private int index = -1;
|
||||
|
||||
/** x, y, z, and lightValue. */
|
||||
public static final int INTS_PER_LIGHT_POS = 4;
|
||||
|
||||
// when tested with a normal 1.20 world James saw a maximum of 36,709 block and 2,355 sky lights,
|
||||
// so this should give us a good base that should be able to contain most lighting tasks
|
||||
private final ArrayList<LightPos> arrayList = new ArrayList<>(40_000);
|
||||
/**
|
||||
* When tested with a normal 1.20 world James saw a maximum of 36,709 block and 2,355 sky lights,
|
||||
* so 40,000 should be a good starting point that can contain most lighting tasks.
|
||||
*/
|
||||
private final IntArrayList lightPositions = new IntArrayList(40_000 * INTS_PER_LIGHT_POS);
|
||||
|
||||
|
||||
|
||||
@@ -394,31 +429,39 @@ public class DhLightingEngine
|
||||
public void push(int blockX, int blockY, int blockZ, int lightValue)
|
||||
{
|
||||
this.index++;
|
||||
if (this.index < this.arrayList.size())
|
||||
int subIndex = this.index * INTS_PER_LIGHT_POS;
|
||||
if (subIndex < this.lightPositions.size())
|
||||
{
|
||||
// modify the existing pos in the array
|
||||
LightPos lightPos = this.arrayList.get(this.index);
|
||||
lightPos.pos.x = blockX;
|
||||
lightPos.pos.y = blockY;
|
||||
lightPos.pos.z = blockZ;
|
||||
lightPos.lightValue = lightValue;
|
||||
this.lightPositions.set(subIndex, blockX);
|
||||
this.lightPositions.set(subIndex + 1, blockY);
|
||||
this.lightPositions.set(subIndex + 2, blockZ);
|
||||
this.lightPositions.set(subIndex + 3, lightValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add a new pos
|
||||
this.arrayList.add(new LightPos(new DhBlockPos(blockX, blockY, blockZ), lightValue));
|
||||
this.lightPositions.add(blockX);
|
||||
this.lightPositions.add(blockY);
|
||||
this.lightPositions.add(blockZ);
|
||||
this.lightPositions.add(lightValue);
|
||||
}
|
||||
}
|
||||
|
||||
public LightPos pop()
|
||||
/** mutates the given {@link LightPos} to match the next {@link LightPos} in the queue. */
|
||||
public void popMutate(LightPos pos)
|
||||
{
|
||||
LightPos pos = this.arrayList.get(this.index);
|
||||
int subIndex = this.index * INTS_PER_LIGHT_POS;
|
||||
|
||||
pos.x = this.lightPositions.getInt(subIndex);
|
||||
pos.y = this.lightPositions.getInt(subIndex + 1);
|
||||
pos.z = this.lightPositions.getInt(subIndex + 2);
|
||||
pos.lightValue = this.lightPositions.getInt(subIndex + 3);
|
||||
|
||||
this.index--;
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() { return this.index + "/" + this.arrayList.size(); }
|
||||
public String toString() { return this.index + "/" + (this.lightPositions.size() / INTS_PER_LIGHT_POS); }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -130,12 +130,12 @@ public class DhBlockPos
|
||||
}
|
||||
|
||||
/** creates a new {@link DhBlockPos} with the given offset from the current pos. */
|
||||
public DhBlockPos offset(EDhDirection direction) { return this.offset(direction, null); }
|
||||
public DhBlockPos offset(EDhDirection direction) { return this.mutateOffset(direction, null); }
|
||||
/** if not null, mutates "mutablePos" so it matches the current pos after being offset. Otherwise creates a new {@link DhBlockPos}. */
|
||||
public DhBlockPos offset(EDhDirection direction, @Nullable DhBlockPos mutablePos) { return this.offset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z, mutablePos); }
|
||||
public DhBlockPos mutateOffset(EDhDirection direction, @Nullable DhBlockPos mutablePos) { return this.mutateOffset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z, mutablePos); }
|
||||
|
||||
public DhBlockPos offset(int x, int y, int z) { return this.offset(x,y,z, null); }
|
||||
public DhBlockPos offset(int x, int y, int z, @Nullable DhBlockPos mutablePos)
|
||||
public DhBlockPos offset(int x, int y, int z) { return this.mutateOffset(x,y,z, null); }
|
||||
public DhBlockPos mutateOffset(int x, int y, int z, @Nullable DhBlockPos mutablePos)
|
||||
{
|
||||
int newX = this.x + x;
|
||||
int newY = this.y + y;
|
||||
@@ -156,12 +156,12 @@ public class DhBlockPos
|
||||
}
|
||||
|
||||
/** Returns a new {@link DhBlockPos} limits to a value between 0 and 15 (inclusive) */
|
||||
public DhBlockPos convertToChunkRelativePos() { return this.convertToChunkRelativePos(null); }
|
||||
public DhBlockPos convertToChunkRelativePos() { return this.mutateToChunkRelativePos(null); }
|
||||
/**
|
||||
* Limits the block position to a value between 0 and 15 (inclusive)
|
||||
* If not null, mutates "mutableBlockPos"
|
||||
*/
|
||||
public DhBlockPos convertToChunkRelativePos(@Nullable DhBlockPos mutableBlockPos)
|
||||
public DhBlockPos mutateToChunkRelativePos(@Nullable DhBlockPos mutableBlockPos)
|
||||
{
|
||||
// move the position into the range -15 and +15
|
||||
int relX = (this.x % LodUtil.CHUNK_WIDTH);
|
||||
|
||||
@@ -19,34 +19,32 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.render.glObject;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.seibel.distanthorizons.api.enums.config.EGLErrorHandlingMode;
|
||||
import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.enums.EGLProxyContext;
|
||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.objects.GLMessage;
|
||||
import com.seibel.distanthorizons.core.util.objects.GLMessageOutputStream;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
import org.lwjgl.opengl.GLUtil;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EGLErrorHandlingMode;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GLCapabilities;
|
||||
import org.lwjgl.opengl.GLUtil;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.enums.EGLProxyContext;
|
||||
import com.seibel.distanthorizons.core.util.objects.GLMessage;
|
||||
import com.seibel.distanthorizons.core.util.objects.GLMessageOutputStream;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
|
||||
/**
|
||||
* A singleton that holds references to different openGL contexts
|
||||
* and GPU capabilities.
|
||||
@@ -108,7 +106,7 @@ public class GLProxy
|
||||
// this must be created on minecraft's render context to work correctly
|
||||
|
||||
GL_LOGGER.info("Creating " + GLProxy.class.getSimpleName() + "... If this is the last message you see there must have been an OpenGL error.");
|
||||
GL_LOGGER.info("Lod Render OpenGL version [" + GL11.glGetString(GL11.GL_VERSION) + "].");
|
||||
GL_LOGGER.info("Lod Render OpenGL version [" + GL32.glGetString(GL32.GL_VERSION) + "].");
|
||||
|
||||
// getting Minecraft's context has to be done on the render thread,
|
||||
// where the GL context is
|
||||
|
||||
+25
-2
@@ -20,6 +20,7 @@
|
||||
package com.seibel.distanthorizons.core.render.renderer;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
|
||||
@@ -40,6 +41,8 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDebugRendering;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EFogColorMode;
|
||||
import com.seibel.distanthorizons.core.render.fog.LodFogConfig;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
|
||||
@@ -62,6 +65,8 @@ public class LodRenderer
|
||||
public static ConfigBasedSpamLogger tickLogger = new ConfigBasedSpamLogger(LogManager.getLogger(LodRenderer.class),
|
||||
() -> Config.Client.Advanced.Logging.logRendererBufferEvent.get(), 1);
|
||||
|
||||
private static final IIrisAccessor IRIS_ACCESSOR = ModAccessorInjector.INSTANCE.get(IIrisAccessor.class);
|
||||
|
||||
public static final boolean ENABLE_DRAW_LAG_SPIKE_LOGGING = false;
|
||||
public static final boolean ENABLE_DUMP_GL_STATE = true;
|
||||
public static final long DRAW_LAG_SPIKE_THRESHOLD_NS = TimeUnit.NANOSECONDS.convert(20, TimeUnit.MILLISECONDS);
|
||||
@@ -182,6 +187,17 @@ public class LodRenderer
|
||||
return;
|
||||
}
|
||||
|
||||
if (IRIS_ACCESSOR != null && IRIS_ACCESSOR.isRenderingShadowPass())
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
// get MC's shader program and save MC's render state so we can restore it later
|
||||
@@ -243,16 +259,23 @@ public class LodRenderer
|
||||
{
|
||||
this.shaderProgram.free();
|
||||
this.shaderProgram = new LodRenderProgram(newFogConfig);
|
||||
|
||||
FogShader.INSTANCE.free();
|
||||
FogShader.INSTANCE = new FogShader(newFogConfig);
|
||||
}
|
||||
this.shaderProgram.bind();
|
||||
}
|
||||
|
||||
GL32.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
|
||||
/*---------Get required data--------*/
|
||||
int vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
|
||||
Mat4f modelViewProjectionMatrix = RenderUtil.createCombinedModelViewProjectionMatrix(baseProjectionMatrix, baseModelViewMatrix, partialTicks);
|
||||
//Mat4f modelViewProjectionMatrix = RenderUtil.createCombinedModelViewProjectionMatrix(baseProjectionMatrix, baseModelViewMatrix, partialTicks);
|
||||
|
||||
Mat4f projectionMatrix = RenderUtil.createLodProjectionMatrix(baseProjectionMatrix, partialTicks);
|
||||
|
||||
Mat4f modelViewProjectionMatrix = new Mat4f(projectionMatrix);
|
||||
modelViewProjectionMatrix.multiply(RenderUtil.createLodModelViewMatrix(baseModelViewMatrix));
|
||||
|
||||
/*---------Fill uniform data--------*/
|
||||
this.shaderProgram.fillUniformData(modelViewProjectionMatrix, /*Light map = GL_TEXTURE0*/ 0,
|
||||
@@ -283,12 +306,12 @@ public class LodRenderer
|
||||
if (Config.Client.Advanced.Graphics.Ssao.enabled.get())
|
||||
{
|
||||
profiler.popPush("LOD SSAO");
|
||||
SSAOShader.INSTANCE.setProjectionMatrix(projectionMatrix);
|
||||
SSAORenderer.INSTANCE.render(minecraftGlState, partialTicks);
|
||||
}
|
||||
|
||||
|
||||
profiler.popPush("LOD Fog");
|
||||
// TODO add the model view/projection matrices to the render() function
|
||||
FogShader.INSTANCE.setModelViewProjectionMatrix(modelViewProjectionMatrix);
|
||||
FogShader.INSTANCE.render(partialTicks);
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOApplyShader;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOShader;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class SSAORenderer
|
||||
{
|
||||
public static SSAORenderer INSTANCE = new SSAORenderer();
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
|
||||
private boolean init = false;
|
||||
|
||||
private int width = -1;
|
||||
private int height = -1;
|
||||
private int ssaoFramebuffer = -1;
|
||||
|
||||
private int ssaoTexture = -1;
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private SSAORenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init) return;
|
||||
this.init = true;
|
||||
|
||||
SSAOShader.INSTANCE.init();
|
||||
|
||||
SSAOApplyShader.INSTANCE.init();
|
||||
}
|
||||
|
||||
private void createFramebuffer(int width, int height)
|
||||
{
|
||||
if (this.ssaoFramebuffer != -1)
|
||||
{
|
||||
GL32.glDeleteFramebuffers(this.ssaoFramebuffer);
|
||||
this.ssaoFramebuffer = -1;
|
||||
}
|
||||
|
||||
if (this.ssaoTexture != -1)
|
||||
{
|
||||
GL32.glDeleteTextures(this.ssaoTexture);
|
||||
this.ssaoTexture = -1;
|
||||
}
|
||||
|
||||
this.ssaoFramebuffer = GL32.glGenFramebuffers();
|
||||
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.ssaoFramebuffer);
|
||||
|
||||
this.ssaoTexture = GL32.glGenTextures();
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.ssaoTexture);
|
||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_R16F, width, height, 0, GL32.GL_RED, GL32.GL_HALF_FLOAT, (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_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.ssaoTexture, 0);
|
||||
}
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
public void render(GLState primaryState, float partialTicks)
|
||||
{
|
||||
GLState state = new GLState();
|
||||
|
||||
this.init();
|
||||
|
||||
int width = MC_RENDER.getTargetFrameBufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFrameBufferViewportHeight();
|
||||
|
||||
if (this.width != width || this.height != height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.createFramebuffer(width, height);
|
||||
}
|
||||
|
||||
SSAOShader.INSTANCE.FrameBuffer = this.ssaoFramebuffer;
|
||||
SSAOShader.INSTANCE.render(partialTicks);
|
||||
|
||||
primaryState.RestoreFrameBuffer();
|
||||
|
||||
SSAOApplyShader.INSTANCE.BufferTexture = this.ssaoTexture;
|
||||
SSAOApplyShader.INSTANCE.render(partialTicks);
|
||||
|
||||
state.restore();
|
||||
}
|
||||
|
||||
public void free()
|
||||
{
|
||||
SSAOShader.INSTANCE.free();
|
||||
SSAOApplyShader.INSTANCE.free();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttribute;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class ScreenQuad
|
||||
{
|
||||
public static ScreenQuad INSTANCE = new ScreenQuad();
|
||||
|
||||
private static final float[] box_vertices = {
|
||||
-1, -1,
|
||||
1, -1,
|
||||
1, 1,
|
||||
-1, -1,
|
||||
1, 1,
|
||||
-1, 1,
|
||||
};
|
||||
|
||||
private GLVertexBuffer boxBuffer;
|
||||
private VertexAttribute va;
|
||||
private boolean init = false;
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private ScreenQuad() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init) return;
|
||||
this.init = true;
|
||||
|
||||
this.va = VertexAttribute.create();
|
||||
this.va.bind();
|
||||
|
||||
// Pos
|
||||
this.va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false));
|
||||
this.va.completeAndCheck(Float.BYTES * 2);
|
||||
|
||||
// Framebuffer
|
||||
this.createBuffer();
|
||||
}
|
||||
|
||||
public void render()
|
||||
{
|
||||
this.init();
|
||||
|
||||
this.va.bind();
|
||||
this.va.bindBufferToAllBindingPoint(this.boxBuffer.getId());
|
||||
|
||||
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
|
||||
}
|
||||
|
||||
private void createBuffer()
|
||||
{
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
buffer.asFloatBuffer().put(box_vertices);
|
||||
buffer.rewind();
|
||||
|
||||
this.boxBuffer = new GLVertexBuffer(false);
|
||||
this.boxBuffer.bind();
|
||||
this.boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES);
|
||||
}
|
||||
}
|
||||
+22
-86
@@ -19,120 +19,56 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttribute;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public abstract class AbstractShaderRenderer
|
||||
{
|
||||
protected static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
protected static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
private static final float[] box_vertices = {
|
||||
-1, -1,
|
||||
1, -1,
|
||||
1, 1,
|
||||
-1, -1,
|
||||
1, 1,
|
||||
-1, 1,
|
||||
};
|
||||
|
||||
protected final ShaderProgram shader;
|
||||
public GLVertexBuffer boxBuffer;
|
||||
protected VertexAttribute va;
|
||||
boolean init = false;
|
||||
protected ShaderProgram shader;
|
||||
|
||||
protected boolean init = false;
|
||||
|
||||
|
||||
protected AbstractShaderRenderer(ShaderProgram shader)
|
||||
protected AbstractShaderRenderer() {}
|
||||
|
||||
public void init()
|
||||
{
|
||||
this.shader = shader;
|
||||
if (this.init) return;
|
||||
this.init = true;
|
||||
|
||||
this.onInit();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
if (init) return;
|
||||
init = true;
|
||||
|
||||
va = VertexAttribute.create();
|
||||
va.bind();
|
||||
|
||||
// Pos
|
||||
setVertexAttributes();
|
||||
va.completeAndCheck(Float.BYTES * 2);
|
||||
|
||||
// Some shader stuff needs to be set a bit later than
|
||||
this.postInit();
|
||||
|
||||
// Framebuffer
|
||||
this.createBuffer();
|
||||
}
|
||||
|
||||
/** Sets all the vertex attributes */
|
||||
void setVertexAttributes()
|
||||
{
|
||||
va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false));
|
||||
}
|
||||
|
||||
/** Overwrite this to apply uniforms to the shader */
|
||||
void setShaderUniforms(float partialTicks) { }
|
||||
|
||||
/** Overwrite if you need to run something on runtime */
|
||||
void postInit() { }
|
||||
|
||||
|
||||
// TODO pass in the Model View and Projection Matrices along with the ticks
|
||||
public void render(float partialTicks)
|
||||
{
|
||||
GLState state = new GLState();
|
||||
this.init();
|
||||
|
||||
this.shader.bind();
|
||||
|
||||
this.onApplyUniforms(partialTicks);
|
||||
|
||||
int width = MC_RENDER.getTargetFrameBufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFrameBufferViewportHeight();
|
||||
|
||||
GL32.glViewport(0, 0, width, height);
|
||||
GL32.glDisable(GL32.GL_DEPTH_TEST);
|
||||
GL32.glDisable(GL32.GL_SCISSOR_TEST);
|
||||
|
||||
shader.bind();
|
||||
this.setShaderUniforms(partialTicks);
|
||||
this.onRender();
|
||||
|
||||
va.bind();
|
||||
va.bindBufferToAllBindingPoint(boxBuffer.getId());
|
||||
|
||||
GL32.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
|
||||
|
||||
GL32.glEnable(GL11.GL_BLEND);
|
||||
GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
|
||||
|
||||
state.restore();
|
||||
}
|
||||
|
||||
private void createBuffer()
|
||||
{
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
buffer.asFloatBuffer().put(box_vertices);
|
||||
buffer.rewind();
|
||||
|
||||
this.boxBuffer = new GLVertexBuffer(false);
|
||||
this.boxBuffer.bind();
|
||||
this.boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES);
|
||||
this.shader.unbind();
|
||||
}
|
||||
|
||||
public void free()
|
||||
{
|
||||
this.shader.free();
|
||||
}
|
||||
|
||||
protected void onInit() {}
|
||||
|
||||
protected void onApplyUniforms(float partialTicks) {}
|
||||
|
||||
protected void onRender() {}
|
||||
}
|
||||
|
||||
+32
-2
@@ -19,15 +19,45 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
public class DarkShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static DarkShader INSTANCE = new DarkShader();
|
||||
|
||||
|
||||
protected DarkShader()
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
super(new ShaderProgram("shaders/normal.vert", "shaders/test/dark.frag", "fragColor", new String[]{"vPosition", "color"}));
|
||||
this.shader = new ShaderProgram(
|
||||
"shaders/normal.vert",
|
||||
"shaders/test/dark.frag",
|
||||
"fragColor",
|
||||
new String[]{"vPosition", "color"});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onApplyUniforms(float partialTicks)
|
||||
{
|
||||
GL32.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
GLState state = new GLState();
|
||||
|
||||
GL32.glDisable(GL32.GL_DEPTH_TEST);
|
||||
GL32.glDisable(GL32.GL_SCISSOR_TEST);
|
||||
GL32.glEnable(GL32.GL_BLEND);
|
||||
GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
|
||||
state.restore();
|
||||
}
|
||||
}
|
||||
|
||||
+45
-20
@@ -23,11 +23,14 @@ import com.seibel.distanthorizons.api.enums.rendering.EFogColorMode;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.fog.LodFogConfig;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.Shader;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
@@ -36,31 +39,40 @@ import java.awt.*;
|
||||
public class FogShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static FogShader INSTANCE = new FogShader(LodFogConfig.generateFogConfig());
|
||||
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class);
|
||||
|
||||
|
||||
public final int gInvertedModelViewProjectionUniform;
|
||||
public final int gDepthMapUniform;
|
||||
private final LodFogConfig fogConfig;
|
||||
private Mat4f inverseMvmProjMatrix;
|
||||
public int gInvertedModelViewProjectionUniform;
|
||||
public int gDepthMapUniform;
|
||||
|
||||
// Fog Uniforms
|
||||
public final int fogColorUniform;
|
||||
public final int fogScaleUniform;
|
||||
public final int fogVerticalScaleUniform;
|
||||
public final int nearFogStartUniform;
|
||||
public final int nearFogLengthUniform;
|
||||
public final int fullFogModeUniform;
|
||||
|
||||
public int fogColorUniform;
|
||||
public int fogScaleUniform;
|
||||
public int fogVerticalScaleUniform;
|
||||
public int nearFogStartUniform;
|
||||
public int nearFogLengthUniform;
|
||||
public int fullFogModeUniform;
|
||||
|
||||
|
||||
public FogShader(LodFogConfig fogConfig)
|
||||
{
|
||||
super(new ShaderProgram(
|
||||
this.fogConfig = fogConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
this.shader = new ShaderProgram(
|
||||
// TODO rename normal.vert to something like "postProcess.vert"
|
||||
() -> Shader.loadFile("shaders/normal.vert", false, new StringBuilder()).toString(),
|
||||
() -> fogConfig.loadAndProcessFragShader("shaders/fog/fog.frag", false).toString(),
|
||||
() -> this.fogConfig.loadAndProcessFragShader("shaders/fog/fog.frag", false).toString(),
|
||||
"fragColor", new String[]{"vPosition"}
|
||||
));
|
||||
|
||||
);
|
||||
|
||||
// all uniforms should be tryGet...
|
||||
// because disabling fog can cause the GLSL to optimize out most (if not all) uniforms
|
||||
|
||||
@@ -79,9 +91,9 @@ public class FogShader extends AbstractShaderRenderer
|
||||
}
|
||||
|
||||
@Override
|
||||
void setShaderUniforms(float partialTicks)
|
||||
protected void onApplyUniforms(float partialTicks)
|
||||
{
|
||||
this.shader.bind();
|
||||
this.shader.setUniform(this.gInvertedModelViewProjectionUniform, this.inverseMvmProjMatrix);
|
||||
|
||||
int lodDrawDistance = RenderUtil.getFarClipPlaneDistanceInBlocks();
|
||||
int vanillaDrawDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
|
||||
@@ -127,12 +139,25 @@ public class FogShader extends AbstractShaderRenderer
|
||||
|
||||
public void setModelViewProjectionMatrix(Mat4f combinedModelViewProjectionMatrix)
|
||||
{
|
||||
this.shader.bind();
|
||||
this.inverseMvmProjMatrix = new Mat4f(combinedModelViewProjectionMatrix);
|
||||
this.inverseMvmProjMatrix.invert();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
GLState state = new GLState();
|
||||
|
||||
Mat4f inverseMvmProjMatrix = new Mat4f(combinedModelViewProjectionMatrix);
|
||||
inverseMvmProjMatrix.invert();
|
||||
this.shader.setUniform(this.gInvertedModelViewProjectionUniform, inverseMvmProjMatrix);
|
||||
GL32.glDisable(GL32.GL_DEPTH_TEST);
|
||||
GL32.glDisable(GL32.GL_SCISSOR_TEST);
|
||||
GL32.glEnable(GL32.GL_BLEND);
|
||||
GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
this.shader.unbind();
|
||||
GL32.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
|
||||
state.restore();
|
||||
}
|
||||
}
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
public class SSAOApplyShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static SSAOApplyShader INSTANCE = new SSAOApplyShader();
|
||||
|
||||
public int BufferTexture;
|
||||
|
||||
// uniforms
|
||||
public int gSSAOMapUniform;
|
||||
public int gDepthMapUniform;
|
||||
public int gViewSizeUniform;
|
||||
public int gBlurRadiusUniform;
|
||||
public int gNearUniform;
|
||||
public int gFarUniform;
|
||||
|
||||
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
this.shader = new ShaderProgram(
|
||||
"shaders/normal.vert",
|
||||
"shaders/ssao/apply.frag",
|
||||
"fragColor",
|
||||
new String[]{"vPosition"});
|
||||
|
||||
// uniform setup
|
||||
this.gSSAOMapUniform = this.shader.getUniformLocation("gSSAOMap");
|
||||
this.gDepthMapUniform = this.shader.getUniformLocation("gDepthMap");
|
||||
this.gViewSizeUniform = this.shader.tryGetUniformLocation("gViewSize");
|
||||
this.gBlurRadiusUniform = this.shader.tryGetUniformLocation("gBlurRadius");
|
||||
this.gNearUniform = this.shader.tryGetUniformLocation("gNear");
|
||||
this.gFarUniform = this.shader.tryGetUniformLocation("gFar");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onApplyUniforms(float partialTicks)
|
||||
{
|
||||
GL32.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
|
||||
GL32.glUniform1i(this.gDepthMapUniform, 0);
|
||||
|
||||
GL32.glActiveTexture(GL32.GL_TEXTURE1);
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.BufferTexture);
|
||||
GL32.glUniform1i(this.gSSAOMapUniform, 1);
|
||||
|
||||
GL32.glUniform1i(this.gBlurRadiusUniform,
|
||||
Config.Client.Advanced.Graphics.Ssao.blurRadius.get());
|
||||
|
||||
if (this.gViewSizeUniform >= 0)
|
||||
{
|
||||
GL32.glUniform2f(this.gViewSizeUniform,
|
||||
MC_RENDER.getTargetFrameBufferViewportWidth(),
|
||||
MC_RENDER.getTargetFrameBufferViewportHeight());
|
||||
}
|
||||
|
||||
if (this.gNearUniform >= 0)
|
||||
{
|
||||
GL32.glUniform1f(this.gNearUniform,
|
||||
RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks));
|
||||
}
|
||||
|
||||
if (this.gFarUniform >= 0)
|
||||
{
|
||||
float far = (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2));
|
||||
GL32.glUniform1f(this.gFarUniform, far);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
GL32.glEnable(GL32.GL_BLEND);
|
||||
GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||
GL32.glBlendFuncSeparate(GL32.GL_ZERO, GL32.GL_SRC_ALPHA, GL32.GL_ZERO, GL32.GL_ONE);
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
}
|
||||
}
|
||||
-277
@@ -1,277 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttribute;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class SSAORenderer
|
||||
{
|
||||
public static SSAORenderer INSTANCE = new SSAORenderer();
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
private static final float[] box_vertices = {
|
||||
-1, -1,
|
||||
1, -1,
|
||||
1, 1,
|
||||
-1, -1,
|
||||
1, 1,
|
||||
-1, 1,
|
||||
};
|
||||
|
||||
|
||||
private ShaderProgram ssaoShader;
|
||||
private ShaderProgram applyShader;
|
||||
|
||||
private GLVertexBuffer boxBuffer;
|
||||
private VertexAttribute va;
|
||||
private boolean init = false;
|
||||
|
||||
private int width = -1;
|
||||
private int height = -1;
|
||||
private int ssaoFramebuffer = -1;
|
||||
|
||||
private int ssaoTexture = -1;
|
||||
|
||||
// ssao uniforms
|
||||
private final SsaoShaderUniforms ssaoShaderUniforms = new SsaoShaderUniforms();
|
||||
private static class SsaoShaderUniforms
|
||||
{
|
||||
public int gProjUniform;
|
||||
public int gInvProjUniform;
|
||||
public int gSampleCountUniform;
|
||||
public int gRadiusUniform;
|
||||
public int gStrengthUniform;
|
||||
public int gMinLightUniform;
|
||||
public int gBiasUniform;
|
||||
public int gDepthMapUniform;
|
||||
}
|
||||
|
||||
// apply uniforms
|
||||
private final ApplyShaderUniforms applyShaderUniforms = new ApplyShaderUniforms();
|
||||
private static class ApplyShaderUniforms
|
||||
{
|
||||
public int gSSAOMapUniform;
|
||||
public int gDepthMapUniform;
|
||||
public int gViewSizeUniform;
|
||||
public int gBlurRadiusUniform;
|
||||
public int gNearUniform;
|
||||
public int gFarUniform;
|
||||
}
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private SSAORenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init) return;
|
||||
this.init = true;
|
||||
|
||||
this.va = VertexAttribute.create();
|
||||
this.va.bind();
|
||||
|
||||
// Pos
|
||||
this.va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false));
|
||||
this.va.completeAndCheck(Float.BYTES * 2);
|
||||
this.ssaoShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag",
|
||||
"fragColor", new String[]{"vPosition"});
|
||||
|
||||
this.applyShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/apply.frag",
|
||||
"fragColor", new String[]{"vPosition"});
|
||||
|
||||
// SSAO uniform setup
|
||||
this.ssaoShaderUniforms.gProjUniform = this.ssaoShader.getUniformLocation("gProj");
|
||||
this.ssaoShaderUniforms.gInvProjUniform = this.ssaoShader.getUniformLocation("gInvProj");
|
||||
this.ssaoShaderUniforms.gSampleCountUniform = this.ssaoShader.getUniformLocation("gSampleCount");
|
||||
this.ssaoShaderUniforms.gRadiusUniform = this.ssaoShader.getUniformLocation("gRadius");
|
||||
this.ssaoShaderUniforms.gStrengthUniform = this.ssaoShader.getUniformLocation("gStrength");
|
||||
this.ssaoShaderUniforms.gMinLightUniform = this.ssaoShader.getUniformLocation("gMinLight");
|
||||
this.ssaoShaderUniforms.gBiasUniform = this.ssaoShader.getUniformLocation("gBias");
|
||||
this.ssaoShaderUniforms.gDepthMapUniform = this.ssaoShader.getUniformLocation("gDepthMap");
|
||||
|
||||
// Apply uniform setup
|
||||
this.applyShaderUniforms.gSSAOMapUniform = this.applyShader.getUniformLocation("gSSAOMap");
|
||||
this.applyShaderUniforms.gDepthMapUniform = this.applyShader.getUniformLocation("gDepthMap");
|
||||
this.applyShaderUniforms.gViewSizeUniform = this.applyShader.tryGetUniformLocation("gViewSize");
|
||||
this.applyShaderUniforms.gBlurRadiusUniform = this.applyShader.tryGetUniformLocation("gBlurRadius");
|
||||
this.applyShaderUniforms.gNearUniform = this.applyShader.tryGetUniformLocation("gNear");
|
||||
this.applyShaderUniforms.gFarUniform = this.applyShader.tryGetUniformLocation("gFar");
|
||||
|
||||
// Framebuffer
|
||||
this.createBuffer();
|
||||
}
|
||||
|
||||
private void createFramebuffer(int width, int height)
|
||||
{
|
||||
if (this.ssaoFramebuffer != -1)
|
||||
{
|
||||
GL32.glDeleteFramebuffers(this.ssaoFramebuffer);
|
||||
this.ssaoFramebuffer = -1;
|
||||
}
|
||||
|
||||
if (this.ssaoTexture != -1)
|
||||
{
|
||||
GL32.glDeleteTextures(this.ssaoTexture);
|
||||
this.ssaoTexture = -1;
|
||||
}
|
||||
|
||||
this.ssaoFramebuffer = GL32.glGenFramebuffers();
|
||||
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.ssaoFramebuffer);
|
||||
|
||||
this.ssaoTexture = GL32.glGenTextures();
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.ssaoTexture);
|
||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_R16F, width, height, 0, GL32.GL_RED, GL32.GL_HALF_FLOAT, (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_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.ssaoTexture, 0);
|
||||
}
|
||||
|
||||
private void createBuffer()
|
||||
{
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
buffer.asFloatBuffer().put(box_vertices);
|
||||
buffer.rewind();
|
||||
|
||||
this.boxBuffer = new GLVertexBuffer(false);
|
||||
this.boxBuffer.bind();
|
||||
this.boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES);
|
||||
}
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
public void render(GLState primaryState, float partialTicks)
|
||||
{
|
||||
GLState state = new GLState();
|
||||
|
||||
this.init();
|
||||
|
||||
int width = MC_RENDER.getTargetFrameBufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFrameBufferViewportHeight();
|
||||
|
||||
if (this.width != width || this.height != height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.createFramebuffer(width, height);
|
||||
}
|
||||
|
||||
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.ssaoFramebuffer);
|
||||
GL32.glViewport(0, 0, width, height);
|
||||
GL32.glDisable(GL32.GL_SCISSOR_TEST);
|
||||
GL32.glDisable(GL32.GL_DEPTH_TEST);
|
||||
GL32.glDisable(GL11.GL_BLEND);
|
||||
|
||||
float near = RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks);
|
||||
float far = (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2));
|
||||
|
||||
Mat4f perspective = Mat4f.perspective(
|
||||
(float) MC_RENDER.getFov(partialTicks),
|
||||
width / (float) height,
|
||||
near, far);
|
||||
|
||||
Mat4f invertedPerspective = new Mat4f(perspective);
|
||||
invertedPerspective.invert();
|
||||
|
||||
int sampleCount = Config.Client.Advanced.Graphics.Ssao.sampleCount.get();
|
||||
int blurRadius = Config.Client.Advanced.Graphics.Ssao.blurRadius.get();
|
||||
float radius = Config.Client.Advanced.Graphics.Ssao.radius.get().floatValue();
|
||||
float strength = Config.Client.Advanced.Graphics.Ssao.strength.get().floatValue();
|
||||
float minLight = Config.Client.Advanced.Graphics.Ssao.minLight.get().floatValue();
|
||||
float bias = Config.Client.Advanced.Graphics.Ssao.bias.get().floatValue();
|
||||
|
||||
this.ssaoShader.bind();
|
||||
this.ssaoShader.setUniform(this.ssaoShaderUniforms.gProjUniform, perspective);
|
||||
this.ssaoShader.setUniform(this.ssaoShaderUniforms.gInvProjUniform, invertedPerspective);
|
||||
this.ssaoShader.setUniform(this.ssaoShaderUniforms.gSampleCountUniform, sampleCount);
|
||||
this.ssaoShader.setUniform(this.ssaoShaderUniforms.gRadiusUniform, radius);
|
||||
this.ssaoShader.setUniform(this.ssaoShaderUniforms.gStrengthUniform, strength);
|
||||
this.ssaoShader.setUniform(this.ssaoShaderUniforms.gMinLightUniform, minLight);
|
||||
this.ssaoShader.setUniform(this.ssaoShaderUniforms.gBiasUniform, bias);
|
||||
|
||||
this.va.bind();
|
||||
this.va.bindBufferToAllBindingPoint(this.boxBuffer.getId());
|
||||
|
||||
GL32.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
|
||||
|
||||
GL32.glUniform1i(this.ssaoShaderUniforms.gDepthMapUniform, 0);
|
||||
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
|
||||
|
||||
this.applyShader.bind();
|
||||
|
||||
primaryState.RestoreFrameBuffer();
|
||||
|
||||
GL32.glEnable(GL11.GL_BLEND);
|
||||
GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||
GL32.glBlendFuncSeparate(GL32.GL_ZERO, GL32.GL_SRC_ALPHA, GL32.GL_ZERO, GL32.GL_ONE);
|
||||
|
||||
GL32.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
|
||||
GL32.glUniform1i(this.applyShaderUniforms.gDepthMapUniform, 0);
|
||||
|
||||
GL32.glActiveTexture(GL32.GL_TEXTURE1);
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.ssaoTexture);
|
||||
GL32.glUniform1i(this.applyShaderUniforms.gSSAOMapUniform, 1);
|
||||
|
||||
GL32.glUniform1i(this.applyShaderUniforms.gBlurRadiusUniform, blurRadius);
|
||||
|
||||
if (this.applyShaderUniforms.gViewSizeUniform >= 0)
|
||||
GL32.glUniform2f(this.applyShaderUniforms.gViewSizeUniform, width, height);
|
||||
|
||||
if (this.applyShaderUniforms.gNearUniform >= 0)
|
||||
GL32.glUniform1f(this.applyShaderUniforms.gNearUniform, near);
|
||||
|
||||
if (this.applyShaderUniforms.gFarUniform >= 0)
|
||||
GL32.glUniform1f(this.applyShaderUniforms.gFarUniform, far);
|
||||
|
||||
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
|
||||
|
||||
state.restore();
|
||||
}
|
||||
|
||||
public void free()
|
||||
{
|
||||
this.ssaoShader.free();
|
||||
this.applyShader.free();
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
public class SSAOShader extends AbstractShaderRenderer
|
||||
{
|
||||
public static SSAOShader INSTANCE = new SSAOShader();
|
||||
|
||||
public int FrameBuffer;
|
||||
|
||||
private Mat4f perspective;
|
||||
private Mat4f invertedPerspective;
|
||||
|
||||
// uniforms
|
||||
public int gProjUniform;
|
||||
public int gInvProjUniform;
|
||||
public int gSampleCountUniform;
|
||||
public int gRadiusUniform;
|
||||
public int gStrengthUniform;
|
||||
public int gMinLightUniform;
|
||||
public int gBiasUniform;
|
||||
public int gDepthMapUniform;
|
||||
|
||||
|
||||
@Override
|
||||
public void onInit()
|
||||
{
|
||||
this.shader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag",
|
||||
"fragColor", new String[]{"vPosition"});
|
||||
|
||||
// uniform setup
|
||||
this.gProjUniform = this.shader.getUniformLocation("gProj");
|
||||
this.gInvProjUniform = this.shader.getUniformLocation("gInvProj");
|
||||
this.gSampleCountUniform = this.shader.getUniformLocation("gSampleCount");
|
||||
this.gRadiusUniform = this.shader.getUniformLocation("gRadius");
|
||||
this.gStrengthUniform = this.shader.getUniformLocation("gStrength");
|
||||
this.gMinLightUniform = this.shader.getUniformLocation("gMinLight");
|
||||
this.gBiasUniform = this.shader.getUniformLocation("gBias");
|
||||
this.gDepthMapUniform = this.shader.getUniformLocation("gDepthMap");
|
||||
}
|
||||
|
||||
public void setProjectionMatrix(Mat4f perspective)
|
||||
{
|
||||
this.perspective = perspective;
|
||||
|
||||
this.invertedPerspective = new Mat4f(perspective);
|
||||
this.invertedPerspective.invert();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onApplyUniforms(float partialTicks)
|
||||
{
|
||||
this.shader.setUniform(this.gProjUniform, this.perspective);
|
||||
|
||||
this.shader.setUniform(this.gInvProjUniform, this.invertedPerspective);
|
||||
|
||||
this.shader.setUniform(this.gSampleCountUniform,
|
||||
Config.Client.Advanced.Graphics.Ssao.sampleCount.get());
|
||||
|
||||
this.shader.setUniform(this.gRadiusUniform,
|
||||
Config.Client.Advanced.Graphics.Ssao.radius.get().floatValue());
|
||||
|
||||
this.shader.setUniform(this.gStrengthUniform,
|
||||
Config.Client.Advanced.Graphics.Ssao.strength.get().floatValue());
|
||||
|
||||
this.shader.setUniform(this.gMinLightUniform,
|
||||
Config.Client.Advanced.Graphics.Ssao.minLight.get().floatValue());
|
||||
|
||||
this.shader.setUniform(this.gBiasUniform,
|
||||
Config.Client.Advanced.Graphics.Ssao.bias.get().floatValue());
|
||||
|
||||
GL32.glActiveTexture(GL32.GL_TEXTURE0);
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
|
||||
|
||||
GL32.glUniform1i(this.gDepthMapUniform, 0);
|
||||
}
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
@Override
|
||||
protected void onRender()
|
||||
{
|
||||
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.FrameBuffer);
|
||||
GL32.glDisable(GL32.GL_SCISSOR_TEST);
|
||||
GL32.glDisable(GL32.GL_DEPTH_TEST);
|
||||
GL32.glDisable(GL32.GL_BLEND);
|
||||
|
||||
ScreenQuad.INSTANCE.render();
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -19,7 +19,7 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.render.vertexFormat;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/**
|
||||
* This object is used to build LodVertexFormats.
|
||||
@@ -80,13 +80,13 @@ public class LodVertexFormatElement
|
||||
|
||||
public enum DataType
|
||||
{
|
||||
FLOAT(4, "Float", GL11.GL_FLOAT),
|
||||
UBYTE(1, "Unsigned Byte", GL11.GL_UNSIGNED_BYTE),
|
||||
BYTE(1, "Byte", GL11.GL_BYTE),
|
||||
USHORT(2, "Unsigned Short", GL11.GL_UNSIGNED_SHORT),
|
||||
SHORT(2, "Short", GL11.GL_SHORT),
|
||||
UINT(4, "Unsigned Int", GL11.GL_UNSIGNED_INT),
|
||||
INT(4, "Int", GL11.GL_INT);
|
||||
FLOAT(4, "Float", GL32.GL_FLOAT),
|
||||
UBYTE(1, "Unsigned Byte", GL32.GL_UNSIGNED_BYTE),
|
||||
BYTE(1, "Byte", GL32.GL_BYTE),
|
||||
USHORT(2, "Unsigned Short", GL32.GL_UNSIGNED_SHORT),
|
||||
SHORT(2, "Short", GL32.GL_SHORT),
|
||||
UINT(4, "Unsigned Int", GL32.GL_UNSIGNED_INT),
|
||||
INT(4, "Int", GL32.GL_INT);
|
||||
|
||||
private final int size;
|
||||
private final String name;
|
||||
|
||||
+8
-1
@@ -28,6 +28,7 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindab
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public interface IChunkWrapper extends IBindable
|
||||
@@ -38,6 +39,12 @@ public interface IChunkWrapper extends IBindable
|
||||
int getMinBuildHeight();
|
||||
int getMaxBuildHeight();
|
||||
|
||||
/**
|
||||
* returns the Y level for the first non-empty section in this chunk,
|
||||
* or {@link Integer#MAX_VALUE} if this chunk is completely empty.
|
||||
*/
|
||||
int getMinFilledHeight();
|
||||
|
||||
/** @return The highest y position of a solid block at the given relative chunk position. */
|
||||
int getSolidHeightMapValue(int xRel, int zRel);
|
||||
/**
|
||||
@@ -98,7 +105,7 @@ public interface IChunkWrapper extends IBindable
|
||||
|
||||
|
||||
|
||||
List<DhBlockPos> getBlockLightPosList();
|
||||
ArrayList<DhBlockPos> getBlockLightPosList();
|
||||
|
||||
|
||||
default boolean blockPosInsideChunk(DhBlockPos blockPos) { return this.blockPosInsideChunk(blockPos.x, blockPos.y, blockPos.z); }
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor;
|
||||
|
||||
public interface IIrisAccessor extends IModAccessor
|
||||
{
|
||||
boolean isShaderPackInUse();
|
||||
|
||||
boolean isRenderingShadowPass();
|
||||
}
|
||||
Reference in New Issue
Block a user