mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-11-14 22:43:56 +01:00
Compare commits
11 Commits
965190328b
...
a3c66f2b08
Author | SHA1 | Date | |
---|---|---|---|
|
a3c66f2b08 | ||
|
7bb04daa82 | ||
|
81d83e185b | ||
|
3a0ec10a30 | ||
|
0ea8a31103 | ||
|
56d03601cd | ||
|
ef2f2268cc | ||
|
87c914100e | ||
|
9f1c722474 | ||
|
7eb7c4cca0 | ||
|
116b2df6a9 |
@ -56,9 +56,9 @@ public class EmbeddedEnvironment extends AtomicReferenceCounted implements Envir
|
|||||||
|
|
||||||
lightTexture.bind();
|
lightTexture.bind();
|
||||||
|
|
||||||
lightTexture.ensureCapacity(lightVolume.sizeX, lightVolume.sizeY, lightVolume.sizeZ);
|
lightTexture.ensureCapacity(lightVolume.sizeX(), lightVolume.sizeY(), lightVolume.sizeZ());
|
||||||
|
|
||||||
lightTexture.upload(lightVolume.ptr(), lightVolume.sizeX, lightVolume.sizeY, lightVolume.sizeZ);
|
lightTexture.upload(lightVolume.ptr(), lightVolume.sizeX(), lightVolume.sizeY(), lightVolume.sizeZ());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -94,7 +94,7 @@ public class EmbeddedEnvironment extends AtomicReferenceCounted implements Envir
|
|||||||
float oneOverSizeZ = 1f / (float) lightTexture.sizeZ;
|
float oneOverSizeZ = 1f / (float) lightTexture.sizeZ;
|
||||||
|
|
||||||
drawProgram.setVec3("_flw_oneOverLightBoxSize", oneOverSizeX, oneOverSizeY, oneOverSizeZ);
|
drawProgram.setVec3("_flw_oneOverLightBoxSize", oneOverSizeX, oneOverSizeY, oneOverSizeZ);
|
||||||
drawProgram.setVec3("_flw_lightVolumeMin", lightVolume.minX, lightVolume.minY, lightVolume.minZ);
|
drawProgram.setVec3("_flw_lightVolumeMin", lightVolume.x(), lightVolume.y(), lightVolume.z());
|
||||||
}
|
}
|
||||||
drawProgram.setMat4("_flw_model", pose);
|
drawProgram.setMat4("_flw_model", pose);
|
||||||
drawProgram.setMat3("_flw_normal", normal);
|
drawProgram.setMat3("_flw_normal", normal);
|
||||||
|
@ -3,6 +3,7 @@ package com.jozufozu.flywheel.backend.engine.embed;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.util.BoxSet;
|
||||||
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
import com.jozufozu.flywheel.lib.memory.MemoryBlock;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
@ -11,20 +12,16 @@ import net.minecraft.world.level.LightLayer;
|
|||||||
|
|
||||||
public class EmbeddedLightVolume {
|
public class EmbeddedLightVolume {
|
||||||
public static final long STRIDE = Short.BYTES;
|
public static final long STRIDE = Short.BYTES;
|
||||||
public int minX;
|
|
||||||
public int minY;
|
private final BoxSet wantedCoords = new BoxSet();
|
||||||
public int minZ;
|
|
||||||
public int sizeX;
|
|
||||||
public int sizeY;
|
|
||||||
public int sizeZ;
|
|
||||||
private final BlockPos.MutableBlockPos scratchPos = new BlockPos.MutableBlockPos();
|
private final BlockPos.MutableBlockPos scratchPos = new BlockPos.MutableBlockPos();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected MemoryBlock block;
|
protected MemoryBlock memoryBlock;
|
||||||
protected boolean dirty;
|
|
||||||
|
|
||||||
public boolean empty() {
|
public boolean empty() {
|
||||||
return block == null;
|
return memoryBlock == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collect(BlockAndTintGetter level, int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ) {
|
public void collect(BlockAndTintGetter level, int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ) {
|
||||||
@ -37,12 +34,37 @@ public class EmbeddedLightVolume {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
markDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invalidate(int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ) {
|
public void invalidate(int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ) {
|
||||||
// TODO: shrink the volume
|
if (memoryBlock == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oldMinX = wantedCoords.minX();
|
||||||
|
int oldMinY = wantedCoords.minY();
|
||||||
|
int oldMinZ = wantedCoords.minZ();
|
||||||
|
int oldSizeX = wantedCoords.sizeX();
|
||||||
|
int oldSizeY = wantedCoords.sizeY();
|
||||||
|
|
||||||
|
var shrank = wantedCoords.clear(minX, minY, minZ, sizeX, sizeY, sizeZ);
|
||||||
|
|
||||||
|
if (!shrank) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newVolume = wantedCoords.volume();
|
||||||
|
|
||||||
|
MemoryBlock newBlock = MemoryBlock.malloc(newVolume * STRIDE);
|
||||||
|
|
||||||
|
int xOff = wantedCoords.minX() - oldMinX;
|
||||||
|
int yOff = wantedCoords.minY() - oldMinY;
|
||||||
|
int zOff = wantedCoords.minZ() - oldMinZ;
|
||||||
|
|
||||||
|
blit(memoryBlock, xOff, yOff, zOff, oldSizeX, oldSizeY, newBlock, 0, 0, 0, wantedCoords.sizeX(), wantedCoords.sizeY(), wantedCoords.sizeX(), wantedCoords.sizeY(), wantedCoords.sizeZ());
|
||||||
|
|
||||||
|
memoryBlock.free();
|
||||||
|
memoryBlock = newBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void paintLight(BlockAndTintGetter level, int x, int y, int z) {
|
private void paintLight(BlockAndTintGetter level, int x, int y, int z) {
|
||||||
@ -51,97 +73,94 @@ public class EmbeddedLightVolume {
|
|||||||
int block = level.getBrightness(LightLayer.BLOCK, scratchPos);
|
int block = level.getBrightness(LightLayer.BLOCK, scratchPos);
|
||||||
int sky = level.getBrightness(LightLayer.SKY, scratchPos);
|
int sky = level.getBrightness(LightLayer.SKY, scratchPos);
|
||||||
|
|
||||||
long ptr = worldPosToPtr(x, y, z);
|
long ptr = this.memoryBlock.ptr() + offset(x - x(), y - y(), z - z(), sizeX(), sizeY());
|
||||||
MemoryUtil.memPutShort(ptr, (short) ((block << 4) | sky << 12));
|
MemoryUtil.memPutShort(ptr, (short) ((block << 4) | sky << 12));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void maybeExpandForBox(int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ) {
|
private void maybeExpandForBox(int minX, int minY, int minZ, int sizeX, int sizeY, int sizeZ) {
|
||||||
if (block == null) {
|
int oldMinX = wantedCoords.minX();
|
||||||
this.minX = minX;
|
int oldMinY = wantedCoords.minY();
|
||||||
this.minY = minY;
|
int oldMinZ = wantedCoords.minZ();
|
||||||
this.minZ = minZ;
|
int oldSizeX = wantedCoords.sizeX();
|
||||||
this.sizeX = sizeX;
|
int oldSizeY = wantedCoords.sizeY();
|
||||||
this.sizeY = sizeY;
|
int oldSizeZ = wantedCoords.sizeZ();
|
||||||
this.sizeZ = sizeZ;
|
|
||||||
|
|
||||||
|
var grew = wantedCoords.add(minX, minY, minZ, sizeX, sizeY, sizeZ);
|
||||||
|
|
||||||
|
if (memoryBlock == null) {
|
||||||
int volume = sizeX * sizeY * sizeZ;
|
int volume = sizeX * sizeY * sizeZ;
|
||||||
|
|
||||||
block = MemoryBlock.malloc(volume * STRIDE);
|
memoryBlock = MemoryBlock.malloc(volume * STRIDE);
|
||||||
block.clear();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int newMinX = Math.min(this.minX, minX);
|
if (!grew) {
|
||||||
int newMinY = Math.min(this.minY, minY);
|
|
||||||
int newMinZ = Math.min(this.minZ, minZ);
|
|
||||||
|
|
||||||
int newSizeX = Math.max(this.minX + this.sizeX, minX + sizeX) - newMinX;
|
|
||||||
int newSizeY = Math.max(this.minY + this.sizeY, minY + sizeY) - newMinY;
|
|
||||||
int newSizeZ = Math.max(this.minZ + this.sizeZ, minZ + sizeZ) - newMinZ;
|
|
||||||
|
|
||||||
if (newMinX == this.minX && newMinY == this.minY && newMinZ == this.minZ && newSizeX == this.sizeX && newSizeY == this.sizeY && newSizeZ == this.sizeZ) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int newVolume = newSizeX * newSizeY * newSizeZ;
|
int newVolume = wantedCoords.volume();
|
||||||
|
|
||||||
MemoryBlock newBlock = MemoryBlock.malloc(newVolume * STRIDE);
|
MemoryBlock newBlock = MemoryBlock.malloc(newVolume * STRIDE);
|
||||||
newBlock.clear();
|
|
||||||
|
|
||||||
int xOff = newMinX - this.minX;
|
int xOff = oldMinX - wantedCoords.minX();
|
||||||
int yOff = newMinY - this.minY;
|
int yOff = oldMinY - wantedCoords.minY();
|
||||||
int zOff = newMinZ - this.minZ;
|
int zOff = oldMinZ - wantedCoords.minZ();
|
||||||
|
|
||||||
for (int z = 0; z < this.sizeZ; z++) {
|
blit(memoryBlock, 0, 0, 0, oldSizeX, oldSizeY, newBlock, xOff, yOff, zOff, wantedCoords.sizeX(), wantedCoords.sizeY(), oldSizeX, oldSizeY, oldSizeZ);
|
||||||
for (int y = 0; y < this.sizeY; y++) {
|
|
||||||
for (int x = 0; x < this.sizeX; x++) {
|
|
||||||
long oldPtr = boxPosToPtr(x, y, z);
|
|
||||||
long newPtr = newBlock.ptr() + x + xOff + (newSizeX * (y + yOff + (z + zOff) * newSizeY)) * STRIDE;
|
|
||||||
|
|
||||||
MemoryUtil.memPutShort(newPtr, MemoryUtil.memGetShort(oldPtr));
|
memoryBlock.free();
|
||||||
|
memoryBlock = newBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void blit(MemoryBlock src, int srcX, int srcY, int srcZ, int srcSizeX, int srcSizeY, MemoryBlock dst, int dstX, int dstY, int dstZ, int dstSizeX, int dstSizeY, int sizeX, int sizeY, int sizeZ) {
|
||||||
|
for (int z = 0; z < sizeZ; z++) {
|
||||||
|
for (int y = 0; y < sizeY; y++) {
|
||||||
|
for (int x = 0; x < sizeX; x++) {
|
||||||
|
long srcPtr = src.ptr() + offset(x + srcX, y + srcY, z + srcZ, srcSizeX, srcSizeY);
|
||||||
|
long dstPtr = dst.ptr() + offset(x + dstX, y + dstY, z + dstZ, dstSizeX, dstSizeY);
|
||||||
|
|
||||||
|
MemoryUtil.memPutShort(dstPtr, MemoryUtil.memGetShort(srcPtr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.minX = newMinX;
|
|
||||||
this.minY = newMinY;
|
|
||||||
this.minZ = newMinZ;
|
|
||||||
this.sizeX = newSizeX;
|
|
||||||
this.sizeY = newSizeY;
|
|
||||||
this.sizeZ = newSizeZ;
|
|
||||||
|
|
||||||
block.free();
|
|
||||||
block = newBlock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long worldPosToPtr(int x, int y, int z) {
|
public static long offset(int x, int y, int z, int sizeX, int sizeY) {
|
||||||
return block.ptr() + worldPosToPtrOffset(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected long boxPosToPtr(int x, int y, int z) {
|
|
||||||
return block.ptr() + boxPosToPtrOffset(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected long worldPosToPtrOffset(int x, int y, int z) {
|
|
||||||
return boxPosToPtrOffset(x - minX, y - minY, z - minZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected long boxPosToPtrOffset(int x, int y, int z) {
|
|
||||||
return (x + sizeX * (y + z * sizeY)) * STRIDE;
|
return (x + sizeX * (y + z * sizeY)) * STRIDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
if (block != null) {
|
if (memoryBlock != null) {
|
||||||
block.free();
|
memoryBlock.free();
|
||||||
block = null;
|
memoryBlock = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void markDirty() {
|
public long ptr() {
|
||||||
this.dirty = true;
|
return memoryBlock.ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long ptr() {
|
public int x() {
|
||||||
return block.ptr();
|
return wantedCoords.minX();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int y() {
|
||||||
|
return wantedCoords.minY();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int z() {
|
||||||
|
return wantedCoords.minZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int sizeX() {
|
||||||
|
return wantedCoords.sizeX();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int sizeY() {
|
||||||
|
return wantedCoords.sizeY();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int sizeZ() {
|
||||||
|
return wantedCoords.sizeZ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,54 @@ package com.jozufozu.flywheel.backend.engine.uniform;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.Matrix4f;
|
||||||
|
import org.joml.Vector2f;
|
||||||
|
import org.joml.Vector3f;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.api.event.RenderContext;
|
import com.jozufozu.flywheel.api.event.RenderContext;
|
||||||
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
|
import com.jozufozu.flywheel.api.visualization.VisualizationManager;
|
||||||
|
import com.jozufozu.flywheel.backend.mixin.GameRendererAccessor;
|
||||||
import com.jozufozu.flywheel.lib.math.MatrixMath;
|
import com.jozufozu.flywheel.lib.math.MatrixMath;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
|
||||||
import net.minecraft.client.Camera;
|
import net.minecraft.client.Camera;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Vec3i;
|
import net.minecraft.core.Vec3i;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
public class FrameUniforms implements UniformProvider {
|
public class FrameUniforms implements UniformProvider {
|
||||||
public static final int SIZE = 304;
|
public static final int SIZE = 1188;
|
||||||
public int debugMode;
|
public int debugMode;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private RenderContext context;
|
private RenderContext context;
|
||||||
|
|
||||||
|
private final Matrix4f view = new Matrix4f();
|
||||||
|
private final Matrix4f viewInverse = new Matrix4f();
|
||||||
|
private final Matrix4f viewPrev = new Matrix4f();
|
||||||
|
private final Matrix4f projection = new Matrix4f();
|
||||||
|
private final Matrix4f projectionInverse = new Matrix4f();
|
||||||
|
private final Matrix4f projectionPrev = new Matrix4f();
|
||||||
private final Matrix4f viewProjection = new Matrix4f();
|
private final Matrix4f viewProjection = new Matrix4f();
|
||||||
private final Matrix4f viewProjectionInverse = new Matrix4f();
|
private final Matrix4f viewProjectionInverse = new Matrix4f();
|
||||||
|
private final Matrix4f viewProjectionPrev = new Matrix4f();
|
||||||
|
|
||||||
|
private final Matrix4f cleanProjection = new Matrix4f();
|
||||||
|
private final Matrix4f cleanProjectionInverse = new Matrix4f();
|
||||||
|
private final Matrix4f cleanProjectionPrev = new Matrix4f();
|
||||||
|
private final Matrix4f cleanViewProjection = new Matrix4f();
|
||||||
|
private final Matrix4f cleanViewProjectionInverse = new Matrix4f();
|
||||||
|
private final Matrix4f cleanViewProjectionPrev = new Matrix4f();
|
||||||
|
|
||||||
|
private final Vector3f cameraPositionPrev = new Vector3f();
|
||||||
|
private final Vector3f cameraLookPrev = new Vector3f();
|
||||||
|
private final Vector2f cameraRotPrev = new Vector2f();
|
||||||
|
|
||||||
|
private boolean lastInit = false;
|
||||||
|
|
||||||
public int byteSize() {
|
public int byteSize() {
|
||||||
return SIZE;
|
return SIZE;
|
||||||
@ -46,8 +74,12 @@ public class FrameUniforms implements UniformProvider {
|
|||||||
var camY = (float) (cameraPos.y - renderOrigin.getY());
|
var camY = (float) (cameraPos.y - renderOrigin.getY());
|
||||||
var camZ = (float) (cameraPos.z - renderOrigin.getZ());
|
var camZ = (float) (cameraPos.z - renderOrigin.getZ());
|
||||||
|
|
||||||
|
view.set(context.stack().last().pose());
|
||||||
|
view.translate(-camX, -camY, -camZ);
|
||||||
|
projection.set(context.projection());
|
||||||
viewProjection.set(context.viewProjection());
|
viewProjection.set(context.viewProjection());
|
||||||
viewProjection.translate(-camX, -camY, -camZ);
|
viewProjection.translate(-camX, -camY, -camZ);
|
||||||
|
setupCleanMatrices(context.stack(), camera, context.partialTick());
|
||||||
|
|
||||||
if (!Uniforms.frustumPaused || Uniforms.frustumCapture) {
|
if (!Uniforms.frustumPaused || Uniforms.frustumCapture) {
|
||||||
MatrixMath.writePackedFrustumPlanes(ptr, viewProjection);
|
MatrixMath.writePackedFrustumPlanes(ptr, viewProjection);
|
||||||
@ -56,39 +88,107 @@ public class FrameUniforms implements UniformProvider {
|
|||||||
|
|
||||||
ptr += 96;
|
ptr += 96;
|
||||||
|
|
||||||
|
// manage last values of matrices
|
||||||
|
if (!lastInit) {
|
||||||
|
viewPrev.set(view);
|
||||||
|
projectionPrev.set(projection);
|
||||||
|
viewProjectionPrev.set(viewProjectionPrev);
|
||||||
|
cleanProjectionPrev.set(cleanProjection);
|
||||||
|
cleanViewProjectionPrev.set(cleanViewProjection);
|
||||||
|
}
|
||||||
ptr = writeMatrices(ptr);
|
ptr = writeMatrices(ptr);
|
||||||
|
viewPrev.set(view);
|
||||||
|
projectionPrev.set(projection);
|
||||||
|
viewProjectionPrev.set(viewProjection);
|
||||||
|
cleanProjectionPrev.set(cleanProjection);
|
||||||
|
cleanViewProjectionPrev.set(cleanViewProjection);
|
||||||
|
|
||||||
ptr = writeCamera(ptr, camX, camY, camZ, camera);
|
ptr = writeCamera(ptr, camX, camY, camZ, camera.getLookVector(), camera.getXRot(), camera.getYRot());
|
||||||
|
|
||||||
|
// last values for camera
|
||||||
|
if (!lastInit) {
|
||||||
|
cameraPositionPrev.set(camX, camY, camZ);
|
||||||
|
cameraLookPrev.set(camera.getLookVector());
|
||||||
|
cameraRotPrev.set(camera.getXRot(), camera.getYRot());
|
||||||
|
}
|
||||||
|
ptr = writeCamera(ptr, cameraPositionPrev.x, cameraPositionPrev.y, cameraPositionPrev.z, cameraLookPrev,
|
||||||
|
cameraRotPrev.x, cameraRotPrev.y);
|
||||||
|
cameraPositionPrev.set(camX, camY, camZ);
|
||||||
|
cameraLookPrev.set(camera.getLookVector());
|
||||||
|
cameraRotPrev.set(camera.getXRot(), camera.getYRot());
|
||||||
|
|
||||||
var window = Minecraft.getInstance()
|
var window = Minecraft.getInstance()
|
||||||
.getWindow();
|
.getWindow();
|
||||||
ptr = writeVec2(ptr, window.getWidth(), window.getHeight());
|
ptr = Uniforms.writeVec2(ptr, window.getWidth(), window.getHeight());
|
||||||
|
|
||||||
// default line width: net.minecraft.client.renderer.RenderStateShard.LineStateShard
|
// default line width: net.minecraft.client.renderer.RenderStateShard.LineStateShard
|
||||||
MemoryUtil.memPutFloat(ptr, Math.max(2.5F, (float) window.getWidth() / 1920.0F * 2.5F));
|
MemoryUtil.memPutFloat(ptr, Math.max(2.5F, (float) window.getWidth() / 1920.0F * 2.5F));
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, (float) window.getWidth() / (float) window.getHeight());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, Minecraft.getInstance().gameRenderer.getDepthFar());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
MemoryUtil.memPutInt(ptr, getConstantAmbientLightFlag(context));
|
MemoryUtil.memPutInt(ptr, getConstantAmbientLightFlag(context));
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
|
|
||||||
ptr = writeTime(ptr);
|
ptr = writeTime(ptr);
|
||||||
|
|
||||||
|
ptr = writeCameraIn(ptr);
|
||||||
|
|
||||||
MemoryUtil.memPutInt(ptr, debugMode);
|
MemoryUtil.memPutInt(ptr, debugMode);
|
||||||
|
|
||||||
|
lastInit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long writeMatrices(long ptr) {
|
private long writeMatrices(long ptr) {
|
||||||
MatrixMath.writeUnsafe(viewProjection, ptr);
|
MatrixMath.writeUnsafe(view, ptr);
|
||||||
MatrixMath.writeUnsafe(viewProjection.invert(viewProjectionInverse), ptr + 64);
|
MatrixMath.writeUnsafe(view.invert(viewInverse), ptr + 64);
|
||||||
return ptr + 128;
|
MatrixMath.writeUnsafe(viewPrev, ptr + 64 * 2);
|
||||||
|
MatrixMath.writeUnsafe(projection, ptr + 64 * 3);
|
||||||
|
MatrixMath.writeUnsafe(projection.invert(projectionInverse), ptr + 64 * 4);
|
||||||
|
MatrixMath.writeUnsafe(projectionPrev, ptr + 64 * 5);
|
||||||
|
MatrixMath.writeUnsafe(viewProjection, ptr + 64 * 6);
|
||||||
|
MatrixMath.writeUnsafe(viewProjection.invert(viewProjectionInverse), ptr + 64 * 7);
|
||||||
|
MatrixMath.writeUnsafe(viewProjectionPrev, ptr + 64 * 8);
|
||||||
|
MatrixMath.writeUnsafe(cleanProjection, ptr + 64 * 9);
|
||||||
|
MatrixMath.writeUnsafe(cleanProjection.invert(cleanProjectionInverse), ptr + 64 * 10);
|
||||||
|
MatrixMath.writeUnsafe(cleanProjectionPrev, ptr + 64 * 11);
|
||||||
|
MatrixMath.writeUnsafe(cleanViewProjection, ptr + 64 * 12);
|
||||||
|
MatrixMath.writeUnsafe(cleanViewProjection.invert(cleanViewProjectionInverse), ptr + 64 * 13);
|
||||||
|
MatrixMath.writeUnsafe(cleanViewProjectionPrev, ptr + 64 * 14);
|
||||||
|
return ptr + 64 * 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long writeCamera(long ptr, float camX, float camY, float camZ, Camera camera) {
|
private void setupCleanMatrices(PoseStack stack, Camera camera, float partialTicks) {
|
||||||
ptr = writeVec3(ptr, camX, camY, camZ);
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
GameRenderer gr = mc.gameRenderer;
|
||||||
|
GameRendererAccessor gra = (GameRendererAccessor) gr;
|
||||||
|
|
||||||
var lookVector = camera.getLookVector();
|
float fov = (float) gra.flywheel$getFov(camera, partialTicks, true);
|
||||||
ptr = writeVec3(ptr, lookVector.x, lookVector.y, lookVector.z);
|
|
||||||
|
|
||||||
ptr = writeVec2(ptr, camera.getXRot(), camera.getYRot());
|
cleanProjection.identity();
|
||||||
|
|
||||||
|
if (gra.flywheel$getZoom() != 1.0F) {
|
||||||
|
cleanProjection.translate(gra.flywheel$getZoomX(), -gra.flywheel$getZoomY(), 0.0F);
|
||||||
|
cleanProjection.scale(gra.flywheel$getZoom(), gra.flywheel$getZoom(), 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanProjection.mul(new Matrix4f().setPerspective(fov * ((float) Math.PI / 180F),
|
||||||
|
(float) mc.getWindow().getWidth() / (float) mc.getWindow().getHeight(), 0.05F, gr.getDepthFar()));
|
||||||
|
|
||||||
|
cleanViewProjection.set(cleanProjection).mul(stack.last().pose());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long writeCamera(long ptr, float camX, float camY, float camZ, Vector3f lookVector, float xRot,
|
||||||
|
float yRot) {
|
||||||
|
ptr = Uniforms.writeVec3(ptr, camX, camY, camZ);
|
||||||
|
|
||||||
|
ptr = Uniforms.writeVec3(ptr, lookVector.x, lookVector.y, lookVector.z);
|
||||||
|
|
||||||
|
ptr = Uniforms.writeVec2(ptr, xRot, yRot);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,18 +206,17 @@ public class FrameUniforms implements UniformProvider {
|
|||||||
return ptr + 16;
|
return ptr + 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long writeVec3(long ptr, float camX, float camY, float camZ) {
|
private long writeCameraIn(long ptr) {
|
||||||
MemoryUtil.memPutFloat(ptr, camX);
|
Camera camera = context.camera();
|
||||||
MemoryUtil.memPutFloat(ptr + 4, camY);
|
if (!camera.isInitialized()) {
|
||||||
MemoryUtil.memPutFloat(ptr + 8, camZ);
|
MemoryUtil.memPutInt(ptr, 0);
|
||||||
MemoryUtil.memPutFloat(ptr + 12, 0f); // empty component of vec4 because we don't trust std140
|
MemoryUtil.memPutInt(ptr + 4, 0);
|
||||||
return ptr + 16;
|
return ptr + 8;
|
||||||
}
|
}
|
||||||
|
Level level = camera.getEntity().level();
|
||||||
private static long writeVec2(long ptr, float camX, float camY) {
|
BlockPos blockPos = camera.getBlockPosition();
|
||||||
MemoryUtil.memPutFloat(ptr, camX);
|
Vec3 cameraPos = camera.getPosition();
|
||||||
MemoryUtil.memPutFloat(ptr + 4, camY);
|
return Uniforms.writeInFluidAndBlock(ptr, level, blockPos, cameraPos);
|
||||||
return ptr + 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getConstantAmbientLightFlag(RenderContext context) {
|
private static int getConstantAmbientLightFlag(RenderContext context) {
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
package com.jozufozu.flywheel.backend.engine.uniform;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.event.RenderContext;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
|
public class LevelUniforms implements UniformProvider {
|
||||||
|
public static final int SIZE = 12 * 4 + 2 * 16;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private RenderContext context;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteSize() {
|
||||||
|
return SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContext(RenderContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(long ptr) {
|
||||||
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
ClientLevel level = mc.level;
|
||||||
|
if (level == null || context == null) {
|
||||||
|
MemoryUtil.memSet(ptr, 0, SIZE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ptick = context.partialTick();
|
||||||
|
|
||||||
|
long dayTime = level.getDayTime();
|
||||||
|
long levelDay = dayTime / 24000L;
|
||||||
|
long timeOfDay = dayTime - levelDay * 24000L;
|
||||||
|
MemoryUtil.memPutInt(ptr, (int) (levelDay % 0x7FFFFFFFL));
|
||||||
|
ptr += 4;
|
||||||
|
MemoryUtil.memPutFloat(ptr, (float) timeOfDay / 24000f);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, level.dimensionType().hasSkyLight() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
float sunAngle = level.getSunAngle(ptick);
|
||||||
|
MemoryUtil.memPutFloat(ptr, sunAngle);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, level.getMoonBrightness());
|
||||||
|
ptr += 4;
|
||||||
|
MemoryUtil.memPutInt(ptr, level.getMoonPhase());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, level.isRaining() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
MemoryUtil.memPutFloat(ptr, level.getRainLevel(ptick));
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, level.isThundering() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
MemoryUtil.memPutFloat(ptr, level.getThunderLevel(ptick));
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, level.getSkyDarken(ptick));
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
Vec3 skyColor = level.getSkyColor(mc.gameRenderer.getMainCamera().getPosition(), ptick);
|
||||||
|
ptr = Uniforms.writeVec4(ptr, (float) skyColor.x, (float) skyColor.y, (float) skyColor.z, 1f);
|
||||||
|
|
||||||
|
Vec3 cloudColor = level.getCloudColor(ptick);
|
||||||
|
ptr = Uniforms.writeVec4(ptr, (float) cloudColor.x, (float) cloudColor.y, (float) cloudColor.z, 1f);
|
||||||
|
|
||||||
|
// TODO: use defines for custom dimension ids
|
||||||
|
int dimensionId;
|
||||||
|
ResourceKey<Level> dimension = level.dimension();
|
||||||
|
if (Level.OVERWORLD.equals(dimension)) {
|
||||||
|
dimensionId = 0;
|
||||||
|
} else if (Level.NETHER.equals(dimension)) {
|
||||||
|
dimensionId = 1;
|
||||||
|
} else if (Level.END.equals(dimension)) {
|
||||||
|
dimensionId = 2;
|
||||||
|
} else {
|
||||||
|
dimensionId = -1;
|
||||||
|
}
|
||||||
|
MemoryUtil.memPutInt(ptr, dimensionId);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.jozufozu.flywheel.backend.engine.uniform;
|
||||||
|
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.Options;
|
||||||
|
|
||||||
|
public class OptionsUniforms implements UniformProvider {
|
||||||
|
public static final int SIZE = 4 * 14;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteSize() {
|
||||||
|
return SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(long ptr) {
|
||||||
|
Options options = Minecraft.getInstance().options;
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, options.gamma().get().floatValue());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, options.fov().get());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, options.screenEffectScale().get().floatValue());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, options.glintSpeed().get().floatValue());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, options.glintStrength().get().floatValue());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, options.biomeBlendRadius().get());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, options.ambientOcclusion().get() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, options.bobView().get() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, options.highContrast().get() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, options.textBackgroundOpacity().get().floatValue());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, options.backgroundForChatOnly().get() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, options.darknessEffectScale().get().floatValue());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, options.damageTiltStrength().get().floatValue());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, options.hideLightningFlash().get() ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
package com.jozufozu.flywheel.backend.engine.uniform;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.api.event.RenderContext;
|
||||||
|
import com.jozufozu.flywheel.backend.mixin.AbstractClientPlayerAccessor;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
import net.minecraft.client.multiplayer.PlayerInfo;
|
||||||
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.util.FastColor;
|
||||||
|
import net.minecraft.world.InteractionHand;
|
||||||
|
import net.minecraft.world.item.BlockItem;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraft.world.scores.PlayerTeam;
|
||||||
|
|
||||||
|
public class PlayerUniforms implements UniformProvider {
|
||||||
|
public static final int SIZE = 9 * 4 + 8 + 2 * 16;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private RenderContext context;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteSize() {
|
||||||
|
return SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContext(RenderContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(long ptr) {
|
||||||
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
LocalPlayer player = mc.player;
|
||||||
|
if (context == null || player == null) {
|
||||||
|
MemoryUtil.memSet(ptr, 0, SIZE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int luminance = 0;
|
||||||
|
for (InteractionHand hand : InteractionHand.values()) {
|
||||||
|
Item handItem = player.getItemInHand(hand).getItem();
|
||||||
|
if (handItem instanceof BlockItem bitem) {
|
||||||
|
Block block = bitem.getBlock();
|
||||||
|
int blockLight = block.defaultBlockState().getLightEmission(player.clientLevel, BlockPos.ZERO);
|
||||||
|
if (luminance < blockLight) {
|
||||||
|
luminance = blockLight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryUtil.memPutFloat(ptr, (float) luminance / 15);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
Vec3 eyePos = player.getEyePosition(context.partialTick());
|
||||||
|
ptr = Uniforms.writeVec3(ptr, (float) eyePos.x, (float) eyePos.y, (float) eyePos.z);
|
||||||
|
|
||||||
|
int blockBrightness = player.clientLevel.getBrightness(LightLayer.BLOCK, player.blockPosition());
|
||||||
|
int skyBrightness = player.clientLevel.getBrightness(LightLayer.SKY, player.blockPosition());
|
||||||
|
int maxBrightness = player.clientLevel.getMaxLightLevel();
|
||||||
|
|
||||||
|
ptr = Uniforms.writeVec2(ptr, (float) blockBrightness / (float) maxBrightness,
|
||||||
|
(float) skyBrightness / (float) maxBrightness);
|
||||||
|
|
||||||
|
ptr = writeEyeIn(ptr, player);
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, player.isCrouching() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
MemoryUtil.memPutInt(ptr, player.isSleeping() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
MemoryUtil.memPutInt(ptr, player.isSwimming() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
MemoryUtil.memPutInt(ptr, player.isFallFlying() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
MemoryUtil.memPutInt(ptr, player.isShiftKeyDown() ? 1 : 0);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
PlayerInfo info = ((AbstractClientPlayerAccessor) player).flywheel$getPlayerInfo();
|
||||||
|
MemoryUtil.memPutInt(ptr, info.getGameMode().getId());
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
int red = 0, green = 0, blue = 0, alpha = 0;
|
||||||
|
PlayerTeam team = info.getTeam();
|
||||||
|
if (team != null) {
|
||||||
|
Integer color = team.getColor().getColor();
|
||||||
|
if (color != null) {
|
||||||
|
int icolor = color;
|
||||||
|
red = FastColor.ARGB32.red(icolor);
|
||||||
|
green = FastColor.ARGB32.green(icolor);
|
||||||
|
blue = FastColor.ARGB32.blue(icolor);
|
||||||
|
alpha = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = Uniforms.writeVec4(ptr, (float) red / 255f, (float) blue / 255f, (float) green / 255f,
|
||||||
|
(float) alpha / 255f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long writeEyeIn(long ptr, LocalPlayer player) {
|
||||||
|
ClientLevel level = player.clientLevel;
|
||||||
|
Vec3 eyePos = player.getEyePosition();
|
||||||
|
BlockPos blockPos = BlockPos.containing(eyePos);
|
||||||
|
return Uniforms.writeInFluidAndBlock(ptr, level, blockPos, eyePos);
|
||||||
|
}
|
||||||
|
}
|
@ -5,11 +5,25 @@ import com.jozufozu.flywheel.api.event.RenderContext;
|
|||||||
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
import com.jozufozu.flywheel.backend.gl.GlStateTracker;
|
||||||
import com.jozufozu.flywheel.config.DebugMode;
|
import com.jozufozu.flywheel.config.DebugMode;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.tags.FluidTags;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
public class Uniforms {
|
public class Uniforms {
|
||||||
public static boolean frustumPaused = false;
|
public static boolean frustumPaused = false;
|
||||||
public static boolean frustumCapture = false;
|
public static boolean frustumCapture = false;
|
||||||
private static UniformBuffer<FrameUniforms> frame;
|
private static @Nullable UniformBuffer<FrameUniforms> frame;
|
||||||
private static UniformBuffer<FogUniforms> fog;
|
private static @Nullable UniformBuffer<FogUniforms> fog;
|
||||||
|
private static @Nullable UniformBuffer<OptionsUniforms> options;
|
||||||
|
private static @Nullable UniformBuffer<PlayerUniforms> player;
|
||||||
|
private static @Nullable UniformBuffer<LevelUniforms> level;
|
||||||
|
|
||||||
public static UniformBuffer<FrameUniforms> frame() {
|
public static UniformBuffer<FrameUniforms> frame() {
|
||||||
if (frame == null) {
|
if (frame == null) {
|
||||||
@ -25,9 +39,33 @@ public class Uniforms {
|
|||||||
return fog;
|
return fog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static UniformBuffer<OptionsUniforms> options() {
|
||||||
|
if (options == null) {
|
||||||
|
options = new UniformBuffer<>(2, new OptionsUniforms());
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniformBuffer<PlayerUniforms> player() {
|
||||||
|
if (player == null) {
|
||||||
|
player = new UniformBuffer<>(3, new PlayerUniforms());
|
||||||
|
}
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniformBuffer<LevelUniforms> level() {
|
||||||
|
if (level == null) {
|
||||||
|
level = new UniformBuffer<>(4, new LevelUniforms());
|
||||||
|
}
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
public static void bindForDraw() {
|
public static void bindForDraw() {
|
||||||
bindFrame();
|
bindFrame();
|
||||||
bindFog();
|
bindFog();
|
||||||
|
bindOptions();
|
||||||
|
bindPlayer();
|
||||||
|
bindLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bindFrame() {
|
public static void bindFrame() {
|
||||||
@ -42,6 +80,24 @@ public class Uniforms {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void bindOptions() {
|
||||||
|
if (options != null) {
|
||||||
|
options.bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void bindPlayer() {
|
||||||
|
if (player != null) {
|
||||||
|
player.bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void bindLevel() {
|
||||||
|
if (level != null) {
|
||||||
|
level.bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void onFogUpdate() {
|
public static void onFogUpdate() {
|
||||||
try (var restoreState = GlStateTracker.getRestoreState()) {
|
try (var restoreState = GlStateTracker.getRestoreState()) {
|
||||||
fog().update();
|
fog().update();
|
||||||
@ -52,6 +108,16 @@ public class Uniforms {
|
|||||||
var ubo = frame();
|
var ubo = frame();
|
||||||
ubo.provider.setContext(ctx);
|
ubo.provider.setContext(ctx);
|
||||||
ubo.update();
|
ubo.update();
|
||||||
|
|
||||||
|
options();
|
||||||
|
|
||||||
|
var player = player();
|
||||||
|
player.provider.setContext(ctx);
|
||||||
|
player.update();
|
||||||
|
|
||||||
|
var level = level();
|
||||||
|
level.provider.setContext(ctx);
|
||||||
|
level.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setDebugMode(DebugMode mode) {
|
public static void setDebugMode(DebugMode mode) {
|
||||||
@ -68,5 +134,74 @@ public class Uniforms {
|
|||||||
fog.delete();
|
fog.delete();
|
||||||
fog = null;
|
fog = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options != null) {
|
||||||
|
options.delete();
|
||||||
|
options = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player != null) {
|
||||||
|
player.delete();
|
||||||
|
player = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level != null) {
|
||||||
|
level.delete();
|
||||||
|
level = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static long writeVec4(long ptr, float x, float y, float z, float w) {
|
||||||
|
MemoryUtil.memPutFloat(ptr, x);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 4, y);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 8, z);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 12, w);
|
||||||
|
return ptr + 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long writeVec3(long ptr, float camX, float camY, float camZ) {
|
||||||
|
MemoryUtil.memPutFloat(ptr, camX);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 4, camY);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 8, camZ);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 12, 0f); // empty component of vec4 because we don't trust std140
|
||||||
|
return ptr + 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long writeVec2(long ptr, float camX, float camY) {
|
||||||
|
MemoryUtil.memPutFloat(ptr, camX);
|
||||||
|
MemoryUtil.memPutFloat(ptr + 4, camY);
|
||||||
|
return ptr + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long writeInFluidAndBlock(long ptr, Level level, BlockPos blockPos, Vec3 pos) {
|
||||||
|
FluidState fState = level.getFluidState(blockPos);
|
||||||
|
BlockState bState = level.getBlockState(blockPos);
|
||||||
|
float height = fState.getHeight(level, blockPos);
|
||||||
|
|
||||||
|
if (fState.isEmpty()) {
|
||||||
|
MemoryUtil.memPutInt(ptr, 0);
|
||||||
|
} else if (pos.y < blockPos.getY() + height) {
|
||||||
|
// TODO: handle custom fluids via defines
|
||||||
|
if (fState.is(FluidTags.WATER)) {
|
||||||
|
MemoryUtil.memPutInt(ptr, 1);
|
||||||
|
} else if (fState.is(FluidTags.LAVA)) {
|
||||||
|
MemoryUtil.memPutInt(ptr, 2);
|
||||||
|
} else {
|
||||||
|
MemoryUtil.memPutInt(ptr, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bState.isAir()) {
|
||||||
|
MemoryUtil.memPutInt(ptr + 4, 0);
|
||||||
|
} else {
|
||||||
|
// TODO: handle custom blocks via defines
|
||||||
|
if (bState.is(Blocks.POWDER_SNOW)) {
|
||||||
|
MemoryUtil.memPutInt(ptr + 4, 0);
|
||||||
|
} else {
|
||||||
|
MemoryUtil.memPutInt(ptr + 4, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr + 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.jozufozu.flywheel.backend.mixin;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
import net.minecraft.client.multiplayer.PlayerInfo;
|
||||||
|
import net.minecraft.client.player.AbstractClientPlayer;
|
||||||
|
|
||||||
|
@Mixin(AbstractClientPlayer.class)
|
||||||
|
public interface AbstractClientPlayerAccessor {
|
||||||
|
@Invoker("getPlayerInfo")
|
||||||
|
PlayerInfo flywheel$getPlayerInfo();
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.jozufozu.flywheel.backend.mixin;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
import net.minecraft.client.Camera;
|
||||||
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
|
|
||||||
|
@Mixin(GameRenderer.class)
|
||||||
|
public interface GameRendererAccessor {
|
||||||
|
@Invoker("getFov")
|
||||||
|
double flywheel$getFov(Camera pActiveRenderInfo, float pPartialTicks, boolean pUseFOVSetting);
|
||||||
|
|
||||||
|
@Accessor("zoom")
|
||||||
|
float flywheel$getZoom();
|
||||||
|
|
||||||
|
@Accessor("zoomX")
|
||||||
|
float flywheel$getZoomX();
|
||||||
|
|
||||||
|
@Accessor("zoomY")
|
||||||
|
float flywheel$getZoomY();
|
||||||
|
}
|
174
src/main/java/com/jozufozu/flywheel/backend/util/BoxSet.java
Normal file
174
src/main/java/com/jozufozu/flywheel/backend/util/BoxSet.java
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
package com.jozufozu.flywheel.backend.util;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
|
||||||
|
public class BoxSet {
|
||||||
|
private final LongSet occupied = new LongOpenHashSet();
|
||||||
|
|
||||||
|
private int minX;
|
||||||
|
private int minY;
|
||||||
|
private int minZ;
|
||||||
|
private int maxX;
|
||||||
|
private int maxY;
|
||||||
|
private int maxZ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a box to the set.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the position or size of the set changed.
|
||||||
|
*/
|
||||||
|
public boolean add(int x, int y, int z, int sizeX, int sizeY, int sizeZ) {
|
||||||
|
boolean wasEmpty = occupied.isEmpty();
|
||||||
|
for (int i = x; i < x + sizeX; i++) {
|
||||||
|
for (int j = y; j < y + sizeY; j++) {
|
||||||
|
for (int k = z; k < z + sizeZ; k++) {
|
||||||
|
occupied.add(BlockPos.asLong(i, j, k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wasEmpty) {
|
||||||
|
this.minX = x;
|
||||||
|
this.minY = y;
|
||||||
|
this.minZ = z;
|
||||||
|
this.maxX = x + sizeX;
|
||||||
|
this.maxY = y + sizeY;
|
||||||
|
this.maxZ = z + sizeZ;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
boolean changed = false;
|
||||||
|
if (x < minX) {
|
||||||
|
minX = x;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (y < minY) {
|
||||||
|
minY = y;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (z < minZ) {
|
||||||
|
minZ = z;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (x + sizeX > maxX) {
|
||||||
|
maxX = x + sizeX;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (y + sizeY > maxY) {
|
||||||
|
maxY = y + sizeY;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
if (z + sizeZ > maxZ) {
|
||||||
|
maxZ = z + sizeZ;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a box from the set.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the position or size of the set changed.
|
||||||
|
*/
|
||||||
|
public boolean clear(int x, int y, int z, int sizeX, int sizeY, int sizeZ) {
|
||||||
|
for (int i = x; i < x + sizeX; i++) {
|
||||||
|
for (int j = y; j < y + sizeY; j++) {
|
||||||
|
for (int k = z; k < z + sizeZ; k++) {
|
||||||
|
occupied.remove(BlockPos.asLong(i, j, k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (occupied.isEmpty()) {
|
||||||
|
minX = 0;
|
||||||
|
minY = 0;
|
||||||
|
minZ = 0;
|
||||||
|
maxX = 0;
|
||||||
|
maxY = 0;
|
||||||
|
maxZ = 0;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
ExtremaFinder finder = new ExtremaFinder();
|
||||||
|
occupied.forEach(finder::accept);
|
||||||
|
|
||||||
|
if (finder.volume() != volume()) {
|
||||||
|
minX = finder.minX;
|
||||||
|
minY = finder.minY;
|
||||||
|
minZ = finder.minZ;
|
||||||
|
maxX = finder.maxX;
|
||||||
|
maxY = finder.maxY;
|
||||||
|
maxZ = finder.maxZ;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int minX() {
|
||||||
|
return minX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int minY() {
|
||||||
|
return minY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int minZ() {
|
||||||
|
return minZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int sizeX() {
|
||||||
|
return maxX - minX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int sizeY() {
|
||||||
|
return maxY - minY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int sizeZ() {
|
||||||
|
return maxZ - minZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int volume() {
|
||||||
|
return sizeX() * sizeY() * sizeZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ExtremaFinder {
|
||||||
|
int minX = Integer.MAX_VALUE;
|
||||||
|
int minY = Integer.MAX_VALUE;
|
||||||
|
int minZ = Integer.MAX_VALUE;
|
||||||
|
int maxX = Integer.MIN_VALUE;
|
||||||
|
int maxY = Integer.MIN_VALUE;
|
||||||
|
int maxZ = Integer.MIN_VALUE;
|
||||||
|
|
||||||
|
public void accept(long l) {
|
||||||
|
int x = BlockPos.getX(l);
|
||||||
|
int y = BlockPos.getY(l);
|
||||||
|
int z = BlockPos.getZ(l);
|
||||||
|
if (x < minX) {
|
||||||
|
minX = x;
|
||||||
|
}
|
||||||
|
if (y < minY) {
|
||||||
|
minY = y;
|
||||||
|
}
|
||||||
|
if (z < minZ) {
|
||||||
|
minZ = z;
|
||||||
|
}
|
||||||
|
if (x > maxX) {
|
||||||
|
maxX = x;
|
||||||
|
}
|
||||||
|
if (y > maxY) {
|
||||||
|
maxY = y;
|
||||||
|
}
|
||||||
|
if (z > maxZ) {
|
||||||
|
maxZ = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int volume() {
|
||||||
|
return (maxX - minX) * (maxY - minY) * (maxZ - minZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
#include "flywheel:internal/material.glsl"
|
#include "flywheel:internal/material.glsl"
|
||||||
#include "flywheel:internal/uniforms/frame.glsl"
|
#include "flywheel:internal/uniforms/uniforms.glsl"
|
||||||
#include "flywheel:internal/uniforms/fog.glsl"
|
|
||||||
|
|
||||||
in vec4 flw_vertexPos;
|
in vec4 flw_vertexPos;
|
||||||
in vec4 flw_vertexColor;
|
in vec4 flw_vertexColor;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "flywheel:internal/material.glsl"
|
#include "flywheel:internal/material.glsl"
|
||||||
#include "flywheel:internal/uniforms/frame.glsl"
|
#include "flywheel:internal/uniforms/uniforms.glsl"
|
||||||
#include "flywheel:internal/uniforms/fog.glsl"
|
|
||||||
|
|
||||||
// TODO: can we combine some of these internally to use fewer in/out slots?
|
// TODO: can we combine some of these internally to use fewer in/out slots?
|
||||||
out vec4 flw_vertexPos;
|
out vec4 flw_vertexPos;
|
||||||
|
@ -12,15 +12,34 @@ struct FrustumPlanes {
|
|||||||
layout(std140) uniform _FlwFrameUniforms {
|
layout(std140) uniform _FlwFrameUniforms {
|
||||||
FrustumPlanes flw_frustumPlanes;
|
FrustumPlanes flw_frustumPlanes;
|
||||||
|
|
||||||
|
mat4 flw_view;
|
||||||
|
mat4 flw_viewInverse;
|
||||||
|
mat4 flw_viewPrev;
|
||||||
|
mat4 flw_projection;
|
||||||
|
mat4 flw_projectionInverse;
|
||||||
|
mat4 flw_projectionPrev;
|
||||||
mat4 flw_viewProjection;
|
mat4 flw_viewProjection;
|
||||||
mat4 flw_viewProjectionInverse;
|
mat4 flw_viewProjectionInverse;
|
||||||
|
mat4 flw_viewProjectionPrev;
|
||||||
|
|
||||||
|
mat4 flw_cleanProjection;
|
||||||
|
mat4 flw_cleanProjectionInverse;
|
||||||
|
mat4 flw_cleanProjectionPrev;
|
||||||
|
mat4 flw_cleanViewProjection;
|
||||||
|
mat4 flw_cleanViewProjectionInverse;
|
||||||
|
mat4 flw_cleanViewProjectionPrev;
|
||||||
|
|
||||||
vec4 _flw_cameraPos;
|
vec4 _flw_cameraPos;
|
||||||
vec4 _flw_cameraLook;
|
vec4 _flw_cameraLook;
|
||||||
vec2 flw_cameraRot;
|
vec2 flw_cameraRot;
|
||||||
|
vec4 _flw_cameraPosPrev;
|
||||||
|
vec4 _flw_cameraLookPrev;
|
||||||
|
vec2 flw_cameraRotPrev;
|
||||||
|
|
||||||
vec2 flw_viewportSize;
|
vec2 flw_viewportSize;
|
||||||
float flw_defaultLineWidth;
|
float flw_defaultLineWidth;
|
||||||
|
float flw_aspectRatio;
|
||||||
|
float flw_viewDistance;
|
||||||
|
|
||||||
uint flw_constantAmbientLight;
|
uint flw_constantAmbientLight;
|
||||||
|
|
||||||
@ -30,8 +49,22 @@ layout(std140) uniform _FlwFrameUniforms {
|
|||||||
float flw_renderTicks;
|
float flw_renderTicks;
|
||||||
float flw_renderSeconds;
|
float flw_renderSeconds;
|
||||||
|
|
||||||
|
/** 0 means no fluid. Use FLW_CAMERA_IN_FLUID_* defines to detect fluid type. */
|
||||||
|
uint flw_cameraInFluid;
|
||||||
|
/** 0 means no block. Use FLW_CAMERA_IN_BLOCK_* defines to detect block type. */
|
||||||
|
uint flw_cameraInBlock;
|
||||||
|
|
||||||
uint _flw_debugMode;
|
uint _flw_debugMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define flw_cameraPos _flw_cameraPos.xyz
|
#define flw_cameraPos _flw_cameraPos.xyz
|
||||||
#define flw_cameraLook _flw_cameraLook.xyz
|
#define flw_cameraLook _flw_cameraLook.xyz
|
||||||
|
#define flw_cameraPosPrev _flw_cameraPosPrev.xyz
|
||||||
|
#define flw_cameraLookPrev _flw_cameraLookPrev.xyz
|
||||||
|
|
||||||
|
#define FLW_CAMERA_IN_FLUID_WATER 1
|
||||||
|
#define FLW_CAMERA_IN_FLUID_LAVA 2
|
||||||
|
#define FLW_CAMERA_IN_FLUID_UNKNOWN 0xFFFFFFFFu
|
||||||
|
|
||||||
|
#define FLW_CAMERA_IN_BLOCK_POWDER_SNOW 1
|
||||||
|
#define FLW_CAMERA_IN_BLOCK_UNKNOWN 0xFFFFFFFFu
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
layout(std140) uniform _FlwLevelUniforms {
|
||||||
|
/** The current day number of the level. */
|
||||||
|
uint flw_levelDay;
|
||||||
|
/** The current fraction of the current day that has elapsed. */
|
||||||
|
float flw_timeOfDay;
|
||||||
|
|
||||||
|
uint flw_levelHasSkyLight;
|
||||||
|
|
||||||
|
float flw_sunAngle;
|
||||||
|
|
||||||
|
float flw_moonBrightness;
|
||||||
|
/** There are normally only 8 moon phases. */
|
||||||
|
uint flw_moonPhase;
|
||||||
|
|
||||||
|
uint flw_isRaining;
|
||||||
|
float flw_rainLevel;
|
||||||
|
uint flw_isThundering;
|
||||||
|
float flw_thunderLevel;
|
||||||
|
|
||||||
|
float flw_skyDarken;
|
||||||
|
vec4 flw_skyColor;
|
||||||
|
vec4 flw_cloudColor;
|
||||||
|
|
||||||
|
/** Use FLW_DIMENSION_* ids to determine the dimension. May eventually be implemented for custom dimensions. */
|
||||||
|
uint flw_dimension;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FLW_DIMENSION_OVERWORLD 0
|
||||||
|
#define FLW_DIMENSION_NETHER 1
|
||||||
|
#define FLW_DIMENSION_END 2
|
||||||
|
#define FLW_DIMENSION_UNKNOWN 0xFFFFFFFFu
|
@ -0,0 +1,19 @@
|
|||||||
|
// options.glsl - Houses uniforms for many of the game's settings, focusing on video and accessibility settings.
|
||||||
|
|
||||||
|
layout(std140) uniform _FlwOptionsUniforms {
|
||||||
|
float flw_brightnessOption;
|
||||||
|
uint flw_fovOption;
|
||||||
|
float flw_distortionOption;
|
||||||
|
float flw_glintSpeedOption;
|
||||||
|
float flw_glintStrengthOption;
|
||||||
|
uint flw_biomeBlendOption;
|
||||||
|
uint flw_smoothLightingOption;
|
||||||
|
uint flw_viewBobbingOption;
|
||||||
|
|
||||||
|
uint flw_highContrastOption;
|
||||||
|
float flw_textBackgroundOpacityOption;
|
||||||
|
uint flw_textBackgroundForChatOnlyOption;
|
||||||
|
float flw_darknessPulsingOption;
|
||||||
|
float flw_damageTiltOption;
|
||||||
|
uint hideLightningFlashesOption;
|
||||||
|
};
|
@ -0,0 +1,35 @@
|
|||||||
|
// player.glsl - Holds uniforms for player state.
|
||||||
|
|
||||||
|
layout (std140) uniform _FlwPlayerUniforms {
|
||||||
|
/** Brightness of the brightest light that the player is holding, 0-1. */
|
||||||
|
float flw_heldLight;
|
||||||
|
vec4 _flw_eyePos;
|
||||||
|
/** The brightness at the player's eye position. */
|
||||||
|
vec2 flw_eyeBrightness;
|
||||||
|
/** 0 means no fluid. Use FLW_PLAYER_EYE_IN_FLUID_* defines to detect fluid type. */
|
||||||
|
uint flw_playerEyeInFluid;
|
||||||
|
/** 0 means no block. Use FLW_PLAYER_EYE_IN_BLOCK_* defines to detect block type. */
|
||||||
|
uint flw_playerEyeInBlock;
|
||||||
|
|
||||||
|
uint flw_playerCrouching;
|
||||||
|
uint flw_playerSleeping;
|
||||||
|
uint flw_playerSwimming;
|
||||||
|
uint flw_playerFallFlying;
|
||||||
|
|
||||||
|
uint flw_shiftKeyDown;
|
||||||
|
|
||||||
|
/** 0 = survival, 1 = creative, 2 = adventure, 3 = spectator. */
|
||||||
|
uint flw_gameMode;
|
||||||
|
|
||||||
|
/** Alpha is 1 if any team color is present, 0 otherwise. */
|
||||||
|
vec4 flw_teamColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define flw_eyePos _flw_eyePos.xyz
|
||||||
|
|
||||||
|
#define FLW_PLAYER_EYE_IN_FLUID_WATER 1
|
||||||
|
#define FLW_PLAYER_EYE_IN_FLUID_LAVA 2
|
||||||
|
#define FLW_PLAYER_EYE_IN_FLUID_UNKNOWN 0xFFFFFFFFu
|
||||||
|
|
||||||
|
#define FLW_PLAYER_EYE_IN_BLOCK_POWDER_SNOW 1
|
||||||
|
#define FLW_PLAYER_EYE_IN_BLOCK_UNKNOWN 0xFFFFFFFFu
|
@ -0,0 +1,7 @@
|
|||||||
|
// uniforms.glsl - Includes common uniforms.
|
||||||
|
|
||||||
|
#include "flywheel:internal/uniforms/frame.glsl"
|
||||||
|
#include "flywheel:internal/uniforms/fog.glsl"
|
||||||
|
#include "flywheel:internal/uniforms/options.glsl"
|
||||||
|
#include "flywheel:internal/uniforms/player.glsl"
|
||||||
|
#include "flywheel:internal/uniforms/level.glsl"
|
@ -5,6 +5,8 @@
|
|||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"refmap": "flywheel.refmap.json",
|
"refmap": "flywheel.refmap.json",
|
||||||
"client": [
|
"client": [
|
||||||
|
"AbstractClientPlayerAccessor",
|
||||||
|
"GameRendererAccessor",
|
||||||
"GlStateManagerMixin",
|
"GlStateManagerMixin",
|
||||||
"LightTextureAccessor",
|
"LightTextureAccessor",
|
||||||
"OverlayTextureAccessor",
|
"OverlayTextureAccessor",
|
||||||
|
Loading…
Reference in New Issue
Block a user