Compare commits

..

3 Commits

Author SHA1 Message Date
Kneelawk
7bb04daa82
Add level uniforms 2024-03-04 01:44:04 -08:00
Kneelawk
81d83e185b
Add more player uniforms 2024-03-03 23:30:27 -08:00
Kneelawk
0ea8a31103
Begin on player uniforms 2024-03-03 20:06:28 -08:00
10 changed files with 417 additions and 54 deletions

View File

@ -18,11 +18,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
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 FrameUniforms implements UniformProvider {
@ -123,7 +119,7 @@ public class FrameUniforms implements UniformProvider {
var window = Minecraft.getInstance()
.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
MemoryUtil.memPutFloat(ptr, Math.max(2.5F, (float) window.getWidth() / 1920.0F * 2.5F));
@ -180,18 +176,19 @@ public class FrameUniforms implements UniformProvider {
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()));
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 = writeVec3(ptr, camX, camY, camZ);
ptr = Uniforms.writeVec3(ptr, camX, camY, camZ);
ptr = writeVec3(ptr, lookVector.x, lookVector.y, lookVector.z);
ptr = Uniforms.writeVec3(ptr, lookVector.x, lookVector.y, lookVector.z);
ptr = writeVec2(ptr, xRot, yRot);
ptr = Uniforms.writeVec2(ptr, xRot, yRot);
return ptr;
}
@ -214,52 +211,12 @@ public class FrameUniforms implements UniformProvider {
if (!camera.isInitialized()) {
MemoryUtil.memPutInt(ptr, 0);
MemoryUtil.memPutInt(ptr + 4, 0);
return ptr + 8;
}
return ptr + 8;
}
Level level = camera.getEntity().level();
BlockPos blockPos = camera.getBlockPosition();
Vec3 cameraPos = camera.getPosition();
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 (cameraPos.y < blockPos.getY() + height) {
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 {
if (bState.is(Blocks.POWDER_SNOW)) {
MemoryUtil.memPutInt(ptr + 4, 0);
} else {
MemoryUtil.memPutInt(ptr + 4, -1);
}
}
return ptr + 8;
}
private 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;
}
private static long writeVec2(long ptr, float camX, float camY) {
MemoryUtil.memPutFloat(ptr, camX);
MemoryUtil.memPutFloat(ptr + 4, camY);
return ptr + 8;
return Uniforms.writeInFluidAndBlock(ptr, level, blockPos, cameraPos);
}
private static int getConstantAmbientLightFlag(RenderContext context) {

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -6,6 +6,15 @@ import com.jozufozu.flywheel.backend.gl.GlStateTracker;
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 static boolean frustumPaused = false;
@ -13,6 +22,8 @@ public class Uniforms {
private static @Nullable UniformBuffer<FrameUniforms> frame;
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() {
if (frame == null) {
@ -35,10 +46,26 @@ public class Uniforms {
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() {
bindFrame();
bindFog();
bindOptions();
bindPlayer();
bindLevel();
}
public static void bindFrame() {
@ -59,6 +86,18 @@ public class Uniforms {
}
}
public static void bindPlayer() {
if (player != null) {
player.bind();
}
}
public static void bindLevel() {
if (level != null) {
level.bind();
}
}
public static void onFogUpdate() {
try (var restoreState = GlStateTracker.getRestoreState()) {
fog().update();
@ -71,6 +110,14 @@ public class Uniforms {
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) {
@ -92,5 +139,69 @@ public class Uniforms {
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;
}
}

View File

@ -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();
}

View File

@ -49,9 +49,9 @@ layout(std140) uniform _FlwFrameUniforms {
float flw_renderTicks;
float flw_renderSeconds;
/** Contains 1 for water, 2 for lava, max-value for any other fluid, 0 for no fluid. */
/** 0 means no fluid. Use FLW_CAMERA_IN_FLUID_* defines to detect fluid type. */
uint flw_cameraInFluid;
/** Contains 1 for powder snow, max-value for any other block, 0 for no block. */
/** 0 means no block. Use FLW_CAMERA_IN_BLOCK_* defines to detect block type. */
uint flw_cameraInBlock;
uint _flw_debugMode;
@ -61,3 +61,10 @@ layout(std140) uniform _FlwFrameUniforms {
#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

View File

@ -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

View File

@ -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

View File

@ -3,3 +3,5 @@
#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"

View File

@ -5,6 +5,7 @@
"compatibilityLevel": "JAVA_17",
"refmap": "flywheel.refmap.json",
"client": [
"AbstractClientPlayerAccessor",
"GameRendererAccessor",
"GlStateManagerMixin",
"LightTextureAccessor",