916 lines
44 KiB
Java
916 lines
44 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.mojang.jtracy.TracyClient
|
|
* com.mojang.logging.LogUtils
|
|
* org.apache.commons.io.IOUtils
|
|
* org.joml.Matrix4f
|
|
* org.joml.Matrix4fStack
|
|
* org.joml.Matrix4fc
|
|
* org.joml.Quaternionf
|
|
* org.joml.Quaternionfc
|
|
* org.joml.Vector3f
|
|
* org.joml.Vector3fc
|
|
* org.joml.Vector4f
|
|
* org.jspecify.annotations.Nullable
|
|
* org.slf4j.Logger
|
|
*/
|
|
package net.minecraft.client.renderer;
|
|
|
|
import com.mojang.blaze3d.ProjectionType;
|
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
|
import com.mojang.blaze3d.pipeline.RenderTarget;
|
|
import com.mojang.blaze3d.platform.Lighting;
|
|
import com.mojang.blaze3d.platform.NativeImage;
|
|
import com.mojang.blaze3d.resource.CrossFrameResourcePool;
|
|
import com.mojang.blaze3d.shaders.ShaderSource;
|
|
import com.mojang.blaze3d.systems.GpuDevice;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import com.mojang.blaze3d.vertex.PoseStack;
|
|
import com.mojang.jtracy.TracyClient;
|
|
import com.mojang.logging.LogUtils;
|
|
import com.mojang.math.Axis;
|
|
import java.io.BufferedReader;
|
|
import java.io.IOException;
|
|
import java.io.Reader;
|
|
import java.lang.runtime.SwitchBootstraps;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.LinkOption;
|
|
import java.nio.file.Path;
|
|
import java.util.List;
|
|
import net.minecraft.CrashReport;
|
|
import net.minecraft.CrashReportCategory;
|
|
import net.minecraft.ReportedException;
|
|
import net.minecraft.SharedConstants;
|
|
import net.minecraft.client.Camera;
|
|
import net.minecraft.client.DeltaTracker;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.Options;
|
|
import net.minecraft.client.Screenshot;
|
|
import net.minecraft.client.entity.ClientAvatarState;
|
|
import net.minecraft.client.gui.Font;
|
|
import net.minecraft.client.gui.GuiGraphics;
|
|
import net.minecraft.client.gui.components.debug.DebugScreenEntries;
|
|
import net.minecraft.client.gui.font.ActiveArea;
|
|
import net.minecraft.client.gui.font.EmptyArea;
|
|
import net.minecraft.client.gui.font.TextRenderable;
|
|
import net.minecraft.client.gui.render.GuiRenderer;
|
|
import net.minecraft.client.gui.render.TextureSetup;
|
|
import net.minecraft.client.gui.render.pip.GuiBannerResultRenderer;
|
|
import net.minecraft.client.gui.render.pip.GuiBookModelRenderer;
|
|
import net.minecraft.client.gui.render.pip.GuiEntityRenderer;
|
|
import net.minecraft.client.gui.render.pip.GuiProfilerChartRenderer;
|
|
import net.minecraft.client.gui.render.pip.GuiSignRenderer;
|
|
import net.minecraft.client.gui.render.pip.GuiSkinRenderer;
|
|
import net.minecraft.client.gui.render.state.ColoredRectangleRenderState;
|
|
import net.minecraft.client.gui.render.state.GuiRenderState;
|
|
import net.minecraft.client.gui.render.state.GuiTextRenderState;
|
|
import net.minecraft.client.gui.screens.debug.DebugOptionsScreen;
|
|
import net.minecraft.client.multiplayer.ClientLevel;
|
|
import net.minecraft.client.player.AbstractClientPlayer;
|
|
import net.minecraft.client.player.LocalPlayer;
|
|
import net.minecraft.client.renderer.CachedPerspectiveProjectionMatrixBuffer;
|
|
import net.minecraft.client.renderer.CubeMap;
|
|
import net.minecraft.client.renderer.GlobalSettingsUniform;
|
|
import net.minecraft.client.renderer.ItemInHandRenderer;
|
|
import net.minecraft.client.renderer.LevelTargetBundle;
|
|
import net.minecraft.client.renderer.LightTexture;
|
|
import net.minecraft.client.renderer.MultiBufferSource;
|
|
import net.minecraft.client.renderer.PanoramaRenderer;
|
|
import net.minecraft.client.renderer.PanoramicScreenshotParameters;
|
|
import net.minecraft.client.renderer.PerspectiveProjectionMatrixBuffer;
|
|
import net.minecraft.client.renderer.PostChain;
|
|
import net.minecraft.client.renderer.RenderBuffers;
|
|
import net.minecraft.client.renderer.RenderPipelines;
|
|
import net.minecraft.client.renderer.ScreenEffectRenderer;
|
|
import net.minecraft.client.renderer.SubmitNodeStorage;
|
|
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
|
import net.minecraft.client.renderer.feature.FeatureRenderDispatcher;
|
|
import net.minecraft.client.renderer.fog.FogRenderer;
|
|
import net.minecraft.client.renderer.state.CameraRenderState;
|
|
import net.minecraft.client.renderer.state.LevelRenderState;
|
|
import net.minecraft.client.renderer.texture.OverlayTexture;
|
|
import net.minecraft.client.resources.model.AtlasManager;
|
|
import net.minecraft.client.server.IntegratedServer;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.HolderLookup;
|
|
import net.minecraft.core.registries.Registries;
|
|
import net.minecraft.network.chat.Style;
|
|
import net.minecraft.resources.Identifier;
|
|
import net.minecraft.server.packs.resources.ResourceProvider;
|
|
import net.minecraft.util.ARGB;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.util.Util;
|
|
import net.minecraft.util.profiling.Profiler;
|
|
import net.minecraft.util.profiling.ProfilerFiller;
|
|
import net.minecraft.util.profiling.Zone;
|
|
import net.minecraft.world.effect.MobEffectInstance;
|
|
import net.minecraft.world.effect.MobEffects;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntitySelector;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.monster.Creeper;
|
|
import net.minecraft.world.entity.monster.EnderMan;
|
|
import net.minecraft.world.entity.monster.Spider;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.entity.projectile.ProjectileUtil;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.level.GameType;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
|
|
import net.minecraft.world.level.material.FogType;
|
|
import net.minecraft.world.phys.AABB;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.EntityHitResult;
|
|
import net.minecraft.world.phys.HitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import net.minecraft.world.waypoints.TrackedWaypoint;
|
|
import org.apache.commons.io.IOUtils;
|
|
import org.joml.Matrix4f;
|
|
import org.joml.Matrix4fStack;
|
|
import org.joml.Matrix4fc;
|
|
import org.joml.Quaternionf;
|
|
import org.joml.Quaternionfc;
|
|
import org.joml.Vector3f;
|
|
import org.joml.Vector3fc;
|
|
import org.joml.Vector4f;
|
|
import org.jspecify.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
public class GameRenderer
|
|
implements AutoCloseable,
|
|
TrackedWaypoint.Projector {
|
|
private static final Identifier BLUR_POST_CHAIN_ID = Identifier.withDefaultNamespace("blur");
|
|
public static final int MAX_BLUR_RADIUS = 10;
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
public static final float PROJECTION_Z_NEAR = 0.05f;
|
|
public static final float PROJECTION_3D_HUD_Z_FAR = 100.0f;
|
|
private static final float PORTAL_SPINNING_SPEED = 20.0f;
|
|
private static final float NAUSEA_SPINNING_SPEED = 7.0f;
|
|
private final Minecraft minecraft;
|
|
private final RandomSource random = RandomSource.create();
|
|
private float renderDistance;
|
|
public final ItemInHandRenderer itemInHandRenderer;
|
|
private final ScreenEffectRenderer screenEffectRenderer;
|
|
private final RenderBuffers renderBuffers;
|
|
private float spinningEffectTime;
|
|
private float spinningEffectSpeed;
|
|
private float fovModifier;
|
|
private float oldFovModifier;
|
|
private float darkenWorldAmount;
|
|
private float darkenWorldAmountO;
|
|
private boolean renderBlockOutline = true;
|
|
private long lastScreenshotAttempt;
|
|
private boolean hasWorldScreenshot;
|
|
private long lastActiveTime = Util.getMillis();
|
|
private final LightTexture lightTexture;
|
|
private final OverlayTexture overlayTexture = new OverlayTexture();
|
|
private @Nullable PanoramicScreenshotParameters panoramicScreenshotParameters;
|
|
protected final CubeMap cubeMap = new CubeMap(Identifier.withDefaultNamespace("textures/gui/title/background/panorama"));
|
|
protected final PanoramaRenderer panorama = new PanoramaRenderer(this.cubeMap);
|
|
private final CrossFrameResourcePool resourcePool = new CrossFrameResourcePool(3);
|
|
private final FogRenderer fogRenderer = new FogRenderer();
|
|
private final GuiRenderer guiRenderer;
|
|
private final GuiRenderState guiRenderState;
|
|
private final LevelRenderState levelRenderState = new LevelRenderState();
|
|
private final SubmitNodeStorage submitNodeStorage;
|
|
private final FeatureRenderDispatcher featureRenderDispatcher;
|
|
private @Nullable Identifier postEffectId;
|
|
private boolean effectActive;
|
|
private final Camera mainCamera = new Camera();
|
|
private final Lighting lighting = new Lighting();
|
|
private final GlobalSettingsUniform globalSettingsUniform = new GlobalSettingsUniform();
|
|
private final PerspectiveProjectionMatrixBuffer levelProjectionMatrixBuffer = new PerspectiveProjectionMatrixBuffer("level");
|
|
private final CachedPerspectiveProjectionMatrixBuffer hud3dProjectionMatrixBuffer = new CachedPerspectiveProjectionMatrixBuffer("3d hud", 0.05f, 100.0f);
|
|
|
|
public GameRenderer(Minecraft minecraft, ItemInHandRenderer itemInHandRenderer, RenderBuffers renderBuffers, BlockRenderDispatcher blockRenderer) {
|
|
this.minecraft = minecraft;
|
|
this.itemInHandRenderer = itemInHandRenderer;
|
|
this.lightTexture = new LightTexture(this, minecraft);
|
|
this.renderBuffers = renderBuffers;
|
|
this.guiRenderState = new GuiRenderState();
|
|
MultiBufferSource.BufferSource bufferSource = renderBuffers.bufferSource();
|
|
AtlasManager atlasManager = minecraft.getAtlasManager();
|
|
this.submitNodeStorage = new SubmitNodeStorage();
|
|
this.featureRenderDispatcher = new FeatureRenderDispatcher(this.submitNodeStorage, blockRenderer, bufferSource, atlasManager, renderBuffers.outlineBufferSource(), renderBuffers.crumblingBufferSource(), minecraft.font);
|
|
this.guiRenderer = new GuiRenderer(this.guiRenderState, bufferSource, this.submitNodeStorage, this.featureRenderDispatcher, List.of(new GuiEntityRenderer(bufferSource, minecraft.getEntityRenderDispatcher()), new GuiSkinRenderer(bufferSource), new GuiBookModelRenderer(bufferSource), new GuiBannerResultRenderer(bufferSource, atlasManager), new GuiSignRenderer(bufferSource, atlasManager), new GuiProfilerChartRenderer(bufferSource)));
|
|
this.screenEffectRenderer = new ScreenEffectRenderer(minecraft, atlasManager, bufferSource);
|
|
}
|
|
|
|
@Override
|
|
public void close() {
|
|
this.globalSettingsUniform.close();
|
|
this.lightTexture.close();
|
|
this.overlayTexture.close();
|
|
this.resourcePool.close();
|
|
this.guiRenderer.close();
|
|
this.levelProjectionMatrixBuffer.close();
|
|
this.hud3dProjectionMatrixBuffer.close();
|
|
this.lighting.close();
|
|
this.cubeMap.close();
|
|
this.fogRenderer.close();
|
|
this.featureRenderDispatcher.close();
|
|
}
|
|
|
|
public SubmitNodeStorage getSubmitNodeStorage() {
|
|
return this.submitNodeStorage;
|
|
}
|
|
|
|
public FeatureRenderDispatcher getFeatureRenderDispatcher() {
|
|
return this.featureRenderDispatcher;
|
|
}
|
|
|
|
public LevelRenderState getLevelRenderState() {
|
|
return this.levelRenderState;
|
|
}
|
|
|
|
public void setRenderBlockOutline(boolean renderBlockOutline) {
|
|
this.renderBlockOutline = renderBlockOutline;
|
|
}
|
|
|
|
public void setPanoramicScreenshotParameters(@Nullable PanoramicScreenshotParameters panoramicScreenshotParameters) {
|
|
this.panoramicScreenshotParameters = panoramicScreenshotParameters;
|
|
}
|
|
|
|
public @Nullable PanoramicScreenshotParameters getPanoramicScreenshotParameters() {
|
|
return this.panoramicScreenshotParameters;
|
|
}
|
|
|
|
public boolean isPanoramicMode() {
|
|
return this.panoramicScreenshotParameters != null;
|
|
}
|
|
|
|
public void clearPostEffect() {
|
|
this.postEffectId = null;
|
|
this.effectActive = false;
|
|
}
|
|
|
|
public void togglePostEffect() {
|
|
this.effectActive = !this.effectActive;
|
|
}
|
|
|
|
public void checkEntityPostEffect(@Nullable Entity cameraEntity) {
|
|
Entity entity = cameraEntity;
|
|
int n = 0;
|
|
switch (SwitchBootstraps.typeSwitch("typeSwitch", new Object[]{Creeper.class, Spider.class, EnderMan.class}, (Object)entity, n)) {
|
|
case 0: {
|
|
Creeper ignored = (Creeper)entity;
|
|
this.setPostEffect(Identifier.withDefaultNamespace("creeper"));
|
|
break;
|
|
}
|
|
case 1: {
|
|
Spider ignored = (Spider)entity;
|
|
this.setPostEffect(Identifier.withDefaultNamespace("spider"));
|
|
break;
|
|
}
|
|
case 2: {
|
|
EnderMan ignored = (EnderMan)entity;
|
|
this.setPostEffect(Identifier.withDefaultNamespace("invert"));
|
|
break;
|
|
}
|
|
default: {
|
|
this.clearPostEffect();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void setPostEffect(Identifier id) {
|
|
this.postEffectId = id;
|
|
this.effectActive = true;
|
|
}
|
|
|
|
public void processBlurEffect() {
|
|
PostChain postChain = this.minecraft.getShaderManager().getPostChain(BLUR_POST_CHAIN_ID, LevelTargetBundle.MAIN_TARGETS);
|
|
if (postChain != null) {
|
|
postChain.process(this.minecraft.getMainRenderTarget(), this.resourcePool);
|
|
}
|
|
}
|
|
|
|
public void preloadUiShader(ResourceProvider resourceProvider) {
|
|
GpuDevice device = RenderSystem.getDevice();
|
|
ShaderSource shaderSource = (id, type) -> {
|
|
String string;
|
|
block8: {
|
|
Identifier location = type.idConverter().idToFile(id);
|
|
BufferedReader reader = resourceProvider.getResourceOrThrow(location).openAsReader();
|
|
try {
|
|
string = IOUtils.toString((Reader)reader);
|
|
if (reader == null) break block8;
|
|
}
|
|
catch (Throwable throwable) {
|
|
try {
|
|
if (reader != null) {
|
|
try {
|
|
((Reader)reader).close();
|
|
}
|
|
catch (Throwable throwable2) {
|
|
throwable.addSuppressed(throwable2);
|
|
}
|
|
}
|
|
throw throwable;
|
|
}
|
|
catch (IOException exception) {
|
|
LOGGER.error("Coudln't preload {} shader {}: {}", new Object[]{type, id, exception});
|
|
return null;
|
|
}
|
|
}
|
|
((Reader)reader).close();
|
|
}
|
|
return string;
|
|
};
|
|
device.precompilePipeline(RenderPipelines.GUI, shaderSource);
|
|
device.precompilePipeline(RenderPipelines.GUI_TEXTURED, shaderSource);
|
|
if (TracyClient.isAvailable()) {
|
|
device.precompilePipeline(RenderPipelines.TRACY_BLIT, shaderSource);
|
|
}
|
|
}
|
|
|
|
public void tick() {
|
|
this.tickFov();
|
|
this.lightTexture.tick();
|
|
LocalPlayer player = this.minecraft.player;
|
|
if (this.minecraft.getCameraEntity() == null) {
|
|
this.minecraft.setCameraEntity(player);
|
|
}
|
|
this.mainCamera.tick();
|
|
this.itemInHandRenderer.tick();
|
|
float portalIntensity = player.portalEffectIntensity;
|
|
float nauseaIntensity = player.getEffectBlendFactor(MobEffects.NAUSEA, 1.0f);
|
|
if (portalIntensity > 0.0f || nauseaIntensity > 0.0f) {
|
|
this.spinningEffectSpeed = (portalIntensity * 20.0f + nauseaIntensity * 7.0f) / (portalIntensity + nauseaIntensity);
|
|
this.spinningEffectTime += this.spinningEffectSpeed;
|
|
} else {
|
|
this.spinningEffectSpeed = 0.0f;
|
|
}
|
|
if (!this.minecraft.level.tickRateManager().runsNormally()) {
|
|
return;
|
|
}
|
|
this.darkenWorldAmountO = this.darkenWorldAmount;
|
|
if (this.minecraft.gui.getBossOverlay().shouldDarkenScreen()) {
|
|
this.darkenWorldAmount += 0.05f;
|
|
if (this.darkenWorldAmount > 1.0f) {
|
|
this.darkenWorldAmount = 1.0f;
|
|
}
|
|
} else if (this.darkenWorldAmount > 0.0f) {
|
|
this.darkenWorldAmount -= 0.0125f;
|
|
}
|
|
this.screenEffectRenderer.tick();
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("levelRenderer");
|
|
this.minecraft.levelRenderer.tick(this.mainCamera);
|
|
profiler.pop();
|
|
}
|
|
|
|
public @Nullable Identifier currentPostEffect() {
|
|
return this.postEffectId;
|
|
}
|
|
|
|
public void resize(int width, int height) {
|
|
this.resourcePool.clear();
|
|
this.minecraft.levelRenderer.resize(width, height);
|
|
}
|
|
|
|
public void pick(float a) {
|
|
Entity entity;
|
|
HitResult hitResult;
|
|
Entity cameraEntity = this.minecraft.getCameraEntity();
|
|
if (cameraEntity == null) {
|
|
return;
|
|
}
|
|
if (this.minecraft.level == null || this.minecraft.player == null) {
|
|
return;
|
|
}
|
|
Profiler.get().push("pick");
|
|
double blockInteractionRange = this.minecraft.player.blockInteractionRange();
|
|
double entityInteractionRange = this.minecraft.player.entityInteractionRange();
|
|
this.minecraft.hitResult = hitResult = this.pick(cameraEntity, blockInteractionRange, entityInteractionRange, a);
|
|
if (hitResult instanceof EntityHitResult) {
|
|
EntityHitResult entityHitResult = (EntityHitResult)hitResult;
|
|
entity = entityHitResult.getEntity();
|
|
} else {
|
|
entity = null;
|
|
}
|
|
this.minecraft.crosshairPickEntity = entity;
|
|
Profiler.get().pop();
|
|
}
|
|
|
|
private HitResult pick(Entity cameraEntity, double blockInteractionRange, double entityInteractionRange, float partialTicks) {
|
|
double maxDistance = Math.max(blockInteractionRange, entityInteractionRange);
|
|
double maxDistanceSq = Mth.square(maxDistance);
|
|
Vec3 from = cameraEntity.getEyePosition(partialTicks);
|
|
HitResult blockHitResult = cameraEntity.pick(maxDistance, partialTicks, false);
|
|
double blockDistanceSq = blockHitResult.getLocation().distanceToSqr(from);
|
|
if (blockHitResult.getType() != HitResult.Type.MISS) {
|
|
maxDistanceSq = blockDistanceSq;
|
|
maxDistance = Math.sqrt(maxDistanceSq);
|
|
}
|
|
Vec3 direction = cameraEntity.getViewVector(partialTicks);
|
|
Vec3 to = from.add(direction.x * maxDistance, direction.y * maxDistance, direction.z * maxDistance);
|
|
float overlap = 1.0f;
|
|
AABB box = cameraEntity.getBoundingBox().expandTowards(direction.scale(maxDistance)).inflate(1.0, 1.0, 1.0);
|
|
EntityHitResult entityHitResult = ProjectileUtil.getEntityHitResult(cameraEntity, from, to, box, EntitySelector.CAN_BE_PICKED, maxDistanceSq);
|
|
if (entityHitResult != null && entityHitResult.getLocation().distanceToSqr(from) < blockDistanceSq) {
|
|
return GameRenderer.filterHitResult(entityHitResult, from, entityInteractionRange);
|
|
}
|
|
return GameRenderer.filterHitResult(blockHitResult, from, blockInteractionRange);
|
|
}
|
|
|
|
private static HitResult filterHitResult(HitResult hitResult, Vec3 from, double maxRange) {
|
|
Vec3 hitLocation = hitResult.getLocation();
|
|
if (!hitLocation.closerThan(from, maxRange)) {
|
|
Vec3 location = hitResult.getLocation();
|
|
Direction direction = Direction.getApproximateNearest(location.x - from.x, location.y - from.y, location.z - from.z);
|
|
return BlockHitResult.miss(location, direction, BlockPos.containing(location));
|
|
}
|
|
return hitResult;
|
|
}
|
|
|
|
private void tickFov() {
|
|
float targetFovModifier;
|
|
Entity entity = this.minecraft.getCameraEntity();
|
|
if (entity instanceof AbstractClientPlayer) {
|
|
AbstractClientPlayer player = (AbstractClientPlayer)entity;
|
|
Options options = this.minecraft.options;
|
|
boolean firstPerson = options.getCameraType().isFirstPerson();
|
|
float effectScale = options.fovEffectScale().get().floatValue();
|
|
targetFovModifier = player.getFieldOfViewModifier(firstPerson, effectScale);
|
|
} else {
|
|
targetFovModifier = 1.0f;
|
|
}
|
|
this.oldFovModifier = this.fovModifier;
|
|
this.fovModifier += (targetFovModifier - this.fovModifier) * 0.5f;
|
|
this.fovModifier = Mth.clamp(this.fovModifier, 0.1f, 1.5f);
|
|
}
|
|
|
|
private float getFov(Camera camera, float partialTicks, boolean applyEffects) {
|
|
FogType state;
|
|
LivingEntity cameraEntity;
|
|
Entity entity;
|
|
if (this.isPanoramicMode()) {
|
|
return 90.0f;
|
|
}
|
|
float fov = 70.0f;
|
|
if (applyEffects) {
|
|
fov = this.minecraft.options.fov().get().intValue();
|
|
fov *= Mth.lerp(partialTicks, this.oldFovModifier, this.fovModifier);
|
|
}
|
|
if ((entity = camera.entity()) instanceof LivingEntity && (cameraEntity = (LivingEntity)entity).isDeadOrDying()) {
|
|
float duration = Math.min((float)cameraEntity.deathTime + partialTicks, 20.0f);
|
|
fov /= (1.0f - 500.0f / (duration + 500.0f)) * 2.0f + 1.0f;
|
|
}
|
|
if ((state = camera.getFluidInCamera()) == FogType.LAVA || state == FogType.WATER) {
|
|
float effectScale = this.minecraft.options.fovEffectScale().get().floatValue();
|
|
fov *= Mth.lerp(effectScale, 1.0f, 0.85714287f);
|
|
}
|
|
return fov;
|
|
}
|
|
|
|
private void bobHurt(PoseStack poseStack, float a) {
|
|
Entity entity = this.minecraft.getCameraEntity();
|
|
if (entity instanceof LivingEntity) {
|
|
LivingEntity camera = (LivingEntity)entity;
|
|
float hurt = (float)camera.hurtTime - a;
|
|
if (camera.isDeadOrDying()) {
|
|
float duration = Math.min((float)camera.deathTime + a, 20.0f);
|
|
poseStack.mulPose((Quaternionfc)Axis.ZP.rotationDegrees(40.0f - 8000.0f / (duration + 200.0f)));
|
|
}
|
|
if (hurt < 0.0f) {
|
|
return;
|
|
}
|
|
hurt /= (float)camera.hurtDuration;
|
|
hurt = Mth.sin(hurt * hurt * hurt * hurt * (float)Math.PI);
|
|
float rr = camera.getHurtDir();
|
|
poseStack.mulPose((Quaternionfc)Axis.YP.rotationDegrees(-rr));
|
|
float tiltAmount = (float)((double)(-hurt) * 14.0 * this.minecraft.options.damageTiltStrength().get());
|
|
poseStack.mulPose((Quaternionfc)Axis.ZP.rotationDegrees(tiltAmount));
|
|
poseStack.mulPose((Quaternionfc)Axis.YP.rotationDegrees(rr));
|
|
}
|
|
}
|
|
|
|
private void bobView(PoseStack poseStack, float a) {
|
|
Entity entity = this.minecraft.getCameraEntity();
|
|
if (!(entity instanceof AbstractClientPlayer)) {
|
|
return;
|
|
}
|
|
AbstractClientPlayer player = (AbstractClientPlayer)entity;
|
|
ClientAvatarState avatarState = player.avatarState();
|
|
float b = avatarState.getBackwardsInterpolatedWalkDistance(a);
|
|
float bob = avatarState.getInterpolatedBob(a);
|
|
poseStack.translate(Mth.sin(b * (float)Math.PI) * bob * 0.5f, -Math.abs(Mth.cos(b * (float)Math.PI) * bob), 0.0f);
|
|
poseStack.mulPose((Quaternionfc)Axis.ZP.rotationDegrees(Mth.sin(b * (float)Math.PI) * bob * 3.0f));
|
|
poseStack.mulPose((Quaternionfc)Axis.XP.rotationDegrees(Math.abs(Mth.cos(b * (float)Math.PI - 0.2f) * bob) * 5.0f));
|
|
}
|
|
|
|
private void renderItemInHand(float deltaPartialTick, boolean isSleeping, Matrix4f modelViewMatrix) {
|
|
if (this.isPanoramicMode()) {
|
|
return;
|
|
}
|
|
this.featureRenderDispatcher.renderAllFeatures();
|
|
this.renderBuffers.bufferSource().endBatch();
|
|
PoseStack poseStack = new PoseStack();
|
|
poseStack.pushPose();
|
|
poseStack.mulPose((Matrix4fc)modelViewMatrix.invert(new Matrix4f()));
|
|
Matrix4fStack modelViewStack = RenderSystem.getModelViewStack();
|
|
modelViewStack.pushMatrix().mul((Matrix4fc)modelViewMatrix);
|
|
this.bobHurt(poseStack, deltaPartialTick);
|
|
if (this.minecraft.options.bobView().get().booleanValue()) {
|
|
this.bobView(poseStack, deltaPartialTick);
|
|
}
|
|
if (this.minecraft.options.getCameraType().isFirstPerson() && !isSleeping && !this.minecraft.options.hideGui && this.minecraft.gameMode.getPlayerMode() != GameType.SPECTATOR) {
|
|
this.itemInHandRenderer.renderHandsWithItems(deltaPartialTick, poseStack, this.minecraft.gameRenderer.getSubmitNodeStorage(), this.minecraft.player, this.minecraft.getEntityRenderDispatcher().getPackedLightCoords(this.minecraft.player, deltaPartialTick));
|
|
}
|
|
modelViewStack.popMatrix();
|
|
poseStack.popPose();
|
|
}
|
|
|
|
public Matrix4f getProjectionMatrix(float fov) {
|
|
Matrix4f projection = new Matrix4f();
|
|
return projection.perspective(fov * ((float)Math.PI / 180), (float)this.minecraft.getWindow().getWidth() / (float)this.minecraft.getWindow().getHeight(), 0.05f, this.getDepthFar());
|
|
}
|
|
|
|
public float getDepthFar() {
|
|
return Math.max(this.renderDistance * 4.0f, (float)(this.minecraft.options.cloudRange().get() * 16));
|
|
}
|
|
|
|
public static float getNightVisionScale(LivingEntity camera, float a) {
|
|
MobEffectInstance nightVision = camera.getEffect(MobEffects.NIGHT_VISION);
|
|
if (!nightVision.endsWithin(200)) {
|
|
return 1.0f;
|
|
}
|
|
return 0.7f + Mth.sin(((float)nightVision.getDuration() - a) * (float)Math.PI * 0.2f) * 0.3f;
|
|
}
|
|
|
|
public void render(DeltaTracker deltaTracker, boolean renderLevel) {
|
|
if (this.minecraft.isWindowActive() || !this.minecraft.options.pauseOnLostFocus || this.minecraft.options.touchscreen().get().booleanValue() && this.minecraft.mouseHandler.isRightPressed()) {
|
|
this.lastActiveTime = Util.getMillis();
|
|
} else if (Util.getMillis() - this.lastActiveTime > 500L) {
|
|
this.minecraft.pauseGame(false);
|
|
}
|
|
if (this.minecraft.noRender) {
|
|
return;
|
|
}
|
|
ProfilerFiller profiler = Profiler.get();
|
|
profiler.push("camera");
|
|
this.updateCamera(deltaTracker);
|
|
profiler.pop();
|
|
this.globalSettingsUniform.update(this.minecraft.getWindow().getWidth(), this.minecraft.getWindow().getHeight(), this.minecraft.options.glintStrength().get(), this.minecraft.level == null ? 0L : this.minecraft.level.getGameTime(), deltaTracker, this.minecraft.options.getMenuBackgroundBlurriness(), this.mainCamera);
|
|
boolean resourcesLoaded = this.minecraft.isGameLoadFinished();
|
|
int xMouse = (int)this.minecraft.mouseHandler.getScaledXPos(this.minecraft.getWindow());
|
|
int yMouse = (int)this.minecraft.mouseHandler.getScaledYPos(this.minecraft.getWindow());
|
|
if (resourcesLoaded && renderLevel && this.minecraft.level != null) {
|
|
PostChain postChain;
|
|
profiler.push("world");
|
|
this.renderLevel(deltaTracker);
|
|
this.tryTakeScreenshotIfNeeded();
|
|
this.minecraft.levelRenderer.doEntityOutline();
|
|
if (this.postEffectId != null && this.effectActive && (postChain = this.minecraft.getShaderManager().getPostChain(this.postEffectId, LevelTargetBundle.MAIN_TARGETS)) != null) {
|
|
postChain.process(this.minecraft.getMainRenderTarget(), this.resourcePool);
|
|
}
|
|
profiler.pop();
|
|
}
|
|
this.fogRenderer.endFrame();
|
|
RenderTarget mainRenderTarget = this.minecraft.getMainRenderTarget();
|
|
RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(mainRenderTarget.getDepthTexture(), 1.0);
|
|
this.minecraft.gameRenderer.getLighting().setupFor(Lighting.Entry.ITEMS_3D);
|
|
this.guiRenderState.reset();
|
|
profiler.push("guiExtraction");
|
|
GuiGraphics graphics = new GuiGraphics(this.minecraft, this.guiRenderState, xMouse, yMouse);
|
|
if (resourcesLoaded && renderLevel && this.minecraft.level != null) {
|
|
this.minecraft.gui.render(graphics, deltaTracker);
|
|
}
|
|
if (this.minecraft.getOverlay() != null) {
|
|
try {
|
|
this.minecraft.getOverlay().render(graphics, xMouse, yMouse, deltaTracker.getGameTimeDeltaTicks());
|
|
}
|
|
catch (Throwable t) {
|
|
CrashReport report = CrashReport.forThrowable(t, "Rendering overlay");
|
|
CrashReportCategory category = report.addCategory("Overlay render details");
|
|
category.setDetail("Overlay name", () -> this.minecraft.getOverlay().getClass().getCanonicalName());
|
|
throw new ReportedException(report);
|
|
}
|
|
}
|
|
if (resourcesLoaded && this.minecraft.screen != null) {
|
|
try {
|
|
this.minecraft.screen.renderWithTooltipAndSubtitles(graphics, xMouse, yMouse, deltaTracker.getGameTimeDeltaTicks());
|
|
}
|
|
catch (Throwable t) {
|
|
CrashReport report = CrashReport.forThrowable(t, "Rendering screen");
|
|
CrashReportCategory category = report.addCategory("Screen render details");
|
|
category.setDetail("Screen name", () -> this.minecraft.screen.getClass().getCanonicalName());
|
|
this.minecraft.mouseHandler.fillMousePositionDetails(category, this.minecraft.getWindow());
|
|
throw new ReportedException(report);
|
|
}
|
|
if (SharedConstants.DEBUG_CURSOR_POS) {
|
|
this.minecraft.mouseHandler.drawDebugMouseInfo(this.minecraft.font, graphics);
|
|
}
|
|
try {
|
|
if (this.minecraft.screen != null) {
|
|
this.minecraft.screen.handleDelayedNarration();
|
|
}
|
|
}
|
|
catch (Throwable t) {
|
|
CrashReport report = CrashReport.forThrowable(t, "Narrating screen");
|
|
CrashReportCategory category = report.addCategory("Screen details");
|
|
category.setDetail("Screen name", () -> this.minecraft.screen.getClass().getCanonicalName());
|
|
throw new ReportedException(report);
|
|
}
|
|
}
|
|
if (resourcesLoaded && renderLevel && this.minecraft.level != null) {
|
|
this.minecraft.gui.renderSavingIndicator(graphics, deltaTracker);
|
|
}
|
|
if (resourcesLoaded) {
|
|
try (Zone ignored = profiler.zone("toasts");){
|
|
this.minecraft.getToastManager().render(graphics);
|
|
}
|
|
}
|
|
if (!(this.minecraft.screen instanceof DebugOptionsScreen)) {
|
|
this.minecraft.gui.renderDebugOverlay(graphics);
|
|
}
|
|
this.minecraft.gui.renderDeferredSubtitles();
|
|
if (SharedConstants.DEBUG_ACTIVE_TEXT_AREAS) {
|
|
this.renderActiveTextDebug();
|
|
}
|
|
profiler.popPush("guiRendering");
|
|
this.guiRenderer.render(this.fogRenderer.getBuffer(FogRenderer.FogMode.NONE));
|
|
this.guiRenderer.incrementFrameNumber();
|
|
profiler.pop();
|
|
graphics.applyCursor(this.minecraft.getWindow());
|
|
this.submitNodeStorage.endFrame();
|
|
this.featureRenderDispatcher.endFrame();
|
|
this.resourcePool.endFrame();
|
|
}
|
|
|
|
private void renderActiveTextDebug() {
|
|
this.guiRenderState.nextStratum();
|
|
this.guiRenderState.forEachText(text -> text.ensurePrepared().visit(new Font.GlyphVisitor(){
|
|
private int index;
|
|
final /* synthetic */ GuiTextRenderState val$text;
|
|
{
|
|
this.val$text = guiTextRenderState;
|
|
}
|
|
|
|
@Override
|
|
public void acceptGlyph(TextRenderable.Styled glyph) {
|
|
this.renderDebugMarkers(glyph, false);
|
|
}
|
|
|
|
@Override
|
|
public void acceptEmptyArea(EmptyArea empty) {
|
|
this.renderDebugMarkers(empty, true);
|
|
}
|
|
|
|
private void renderDebugMarkers(ActiveArea glyph, boolean isEmpty) {
|
|
int intensity = (isEmpty ? 128 : 255) - (this.index++ & 1) * 64;
|
|
Style style = glyph.style();
|
|
int red = style.getClickEvent() != null ? intensity : 0;
|
|
int green = style.getHoverEvent() != null ? intensity : 0;
|
|
int blue = red == 0 || green == 0 ? intensity : 0;
|
|
int color = ARGB.color(128, red, green, blue);
|
|
GameRenderer.this.guiRenderState.submitGuiElement(new ColoredRectangleRenderState(RenderPipelines.GUI, TextureSetup.noTexture(), this.val$text.pose, (int)glyph.activeLeft(), (int)glyph.activeTop(), (int)glyph.activeRight(), (int)glyph.activeBottom(), color, color, this.val$text.scissor));
|
|
}
|
|
}));
|
|
}
|
|
|
|
private void tryTakeScreenshotIfNeeded() {
|
|
if (this.hasWorldScreenshot || !this.minecraft.isLocalServer()) {
|
|
return;
|
|
}
|
|
long time = Util.getMillis();
|
|
if (time - this.lastScreenshotAttempt < 1000L) {
|
|
return;
|
|
}
|
|
this.lastScreenshotAttempt = time;
|
|
IntegratedServer server = this.minecraft.getSingleplayerServer();
|
|
if (server == null || server.isStopped()) {
|
|
return;
|
|
}
|
|
server.getWorldScreenshotFile().ifPresent(path -> {
|
|
if (Files.isRegularFile(path, new LinkOption[0])) {
|
|
this.hasWorldScreenshot = true;
|
|
} else {
|
|
this.takeAutoScreenshot((Path)path);
|
|
}
|
|
});
|
|
}
|
|
|
|
private void takeAutoScreenshot(Path screenshotFile) {
|
|
if (this.minecraft.levelRenderer.countRenderedSections() > 10 && this.minecraft.levelRenderer.hasRenderedAllSections()) {
|
|
Screenshot.takeScreenshot(this.minecraft.getMainRenderTarget(), screenshot -> Util.ioPool().execute(() -> {
|
|
int width = screenshot.getWidth();
|
|
int height = screenshot.getHeight();
|
|
int x = 0;
|
|
int y = 0;
|
|
if (width > height) {
|
|
x = (width - height) / 2;
|
|
width = height;
|
|
} else {
|
|
y = (height - width) / 2;
|
|
height = width;
|
|
}
|
|
try (NativeImage scaled = new NativeImage(64, 64, false);){
|
|
screenshot.resizeSubRectTo(x, y, width, height, scaled);
|
|
scaled.writeToFile(screenshotFile);
|
|
}
|
|
catch (IOException e) {
|
|
LOGGER.warn("Couldn't save auto screenshot", (Throwable)e);
|
|
}
|
|
finally {
|
|
screenshot.close();
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
private boolean shouldRenderBlockOutline() {
|
|
boolean renderOutline;
|
|
if (!this.renderBlockOutline) {
|
|
return false;
|
|
}
|
|
Entity cameraEntity = this.minecraft.getCameraEntity();
|
|
boolean bl = renderOutline = cameraEntity instanceof Player && !this.minecraft.options.hideGui;
|
|
if (renderOutline && !((Player)cameraEntity).getAbilities().mayBuild) {
|
|
ItemStack itemStack = ((LivingEntity)cameraEntity).getMainHandItem();
|
|
HitResult hitResult = this.minecraft.hitResult;
|
|
if (hitResult != null && hitResult.getType() == HitResult.Type.BLOCK) {
|
|
BlockPos pos = ((BlockHitResult)hitResult).getBlockPos();
|
|
BlockState blockState = this.minecraft.level.getBlockState(pos);
|
|
if (this.minecraft.gameMode.getPlayerMode() == GameType.SPECTATOR) {
|
|
renderOutline = blockState.getMenuProvider(this.minecraft.level, pos) != null;
|
|
} else {
|
|
BlockInWorld blockInWorld = new BlockInWorld(this.minecraft.level, pos, false);
|
|
HolderLookup.RegistryLookup blockRegistry = this.minecraft.level.registryAccess().lookupOrThrow(Registries.BLOCK);
|
|
renderOutline = !itemStack.isEmpty() && (itemStack.canBreakBlockInAdventureMode(blockInWorld) || itemStack.canPlaceOnBlockInAdventureMode(blockInWorld));
|
|
}
|
|
}
|
|
}
|
|
return renderOutline;
|
|
}
|
|
|
|
public void updateCamera(DeltaTracker deltaTracker) {
|
|
float deltaPartialTick = deltaTracker.getGameTimeDeltaPartialTick(true);
|
|
LocalPlayer player = this.minecraft.player;
|
|
if (player == null || this.minecraft.level == null) {
|
|
return;
|
|
}
|
|
if (this.minecraft.getCameraEntity() == null) {
|
|
this.minecraft.setCameraEntity(player);
|
|
}
|
|
LocalPlayer cameraEntity = this.minecraft.getCameraEntity() == null ? player : this.minecraft.getCameraEntity();
|
|
float cameraDeltaPartialTicks = this.minecraft.level.tickRateManager().isEntityFrozen(cameraEntity) ? 1.0f : deltaPartialTick;
|
|
this.mainCamera.setup(this.minecraft.level, cameraEntity, !this.minecraft.options.getCameraType().isFirstPerson(), this.minecraft.options.getCameraType().isMirrored(), cameraDeltaPartialTicks);
|
|
}
|
|
|
|
public void renderLevel(DeltaTracker deltaTracker) {
|
|
float deltaPartialTick = deltaTracker.getGameTimeDeltaPartialTick(true);
|
|
LocalPlayer player = this.minecraft.player;
|
|
this.lightTexture.updateLightTexture(1.0f);
|
|
this.pick(deltaPartialTick);
|
|
ProfilerFiller profiler = Profiler.get();
|
|
boolean renderOutline = this.shouldRenderBlockOutline();
|
|
this.extractCamera(deltaPartialTick);
|
|
this.renderDistance = this.minecraft.options.getEffectiveRenderDistance() * 16;
|
|
profiler.push("matrices");
|
|
float fovWithEffects = this.getFov(this.mainCamera, deltaPartialTick, true);
|
|
Matrix4f projectionMatrix = this.getProjectionMatrix(fovWithEffects);
|
|
PoseStack bobStack = new PoseStack();
|
|
this.bobHurt(bobStack, this.mainCamera.getPartialTickTime());
|
|
if (this.minecraft.options.bobView().get().booleanValue()) {
|
|
this.bobView(bobStack, this.mainCamera.getPartialTickTime());
|
|
}
|
|
projectionMatrix.mul((Matrix4fc)bobStack.last().pose());
|
|
float screenEffectScale = this.minecraft.options.screenEffectScale().get().floatValue();
|
|
float portalIntensity = Mth.lerp(deltaPartialTick, player.oPortalEffectIntensity, player.portalEffectIntensity);
|
|
float nauseaIntensity = player.getEffectBlendFactor(MobEffects.NAUSEA, deltaPartialTick);
|
|
float spinningEffectIntensity = Math.max(portalIntensity, nauseaIntensity) * (screenEffectScale * screenEffectScale);
|
|
if (spinningEffectIntensity > 0.0f) {
|
|
float skew = 5.0f / (spinningEffectIntensity * spinningEffectIntensity + 5.0f) - spinningEffectIntensity * 0.04f;
|
|
skew *= skew;
|
|
Vector3f axis = new Vector3f(0.0f, Mth.SQRT_OF_TWO / 2.0f, Mth.SQRT_OF_TWO / 2.0f);
|
|
float angle = (this.spinningEffectTime + deltaPartialTick * this.spinningEffectSpeed) * ((float)Math.PI / 180);
|
|
projectionMatrix.rotate(angle, (Vector3fc)axis);
|
|
projectionMatrix.scale(1.0f / skew, 1.0f, 1.0f);
|
|
projectionMatrix.rotate(-angle, (Vector3fc)axis);
|
|
}
|
|
RenderSystem.setProjectionMatrix(this.levelProjectionMatrixBuffer.getBuffer(projectionMatrix), ProjectionType.PERSPECTIVE);
|
|
Quaternionf inverseRotation = this.mainCamera.rotation().conjugate(new Quaternionf());
|
|
Matrix4f modelViewMatrix = new Matrix4f().rotation((Quaternionfc)inverseRotation);
|
|
profiler.popPush("fog");
|
|
Vector4f fogColor = this.fogRenderer.setupFog(this.mainCamera, this.minecraft.options.getEffectiveRenderDistance(), deltaTracker, this.getDarkenWorldAmount(deltaPartialTick), this.minecraft.level);
|
|
GpuBufferSlice terrainFog = this.fogRenderer.getBuffer(FogRenderer.FogMode.WORLD);
|
|
profiler.popPush("level");
|
|
boolean shouldCreateBossFog = this.minecraft.gui.getBossOverlay().shouldCreateWorldFog();
|
|
this.minecraft.levelRenderer.renderLevel(this.resourcePool, deltaTracker, renderOutline, this.mainCamera, modelViewMatrix, projectionMatrix, this.getProjectionMatrixForCulling(fovWithEffects), terrainFog, fogColor, !shouldCreateBossFog);
|
|
profiler.popPush("hand");
|
|
boolean isSleeping = this.minecraft.getCameraEntity() instanceof LivingEntity && ((LivingEntity)this.minecraft.getCameraEntity()).isSleeping();
|
|
RenderSystem.setProjectionMatrix(this.hud3dProjectionMatrixBuffer.getBuffer(this.minecraft.getWindow().getWidth(), this.minecraft.getWindow().getHeight(), this.getFov(this.mainCamera, deltaPartialTick, false)), ProjectionType.PERSPECTIVE);
|
|
RenderSystem.getDevice().createCommandEncoder().clearDepthTexture(this.minecraft.getMainRenderTarget().getDepthTexture(), 1.0);
|
|
this.renderItemInHand(deltaPartialTick, isSleeping, modelViewMatrix);
|
|
profiler.popPush("screenEffects");
|
|
MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource();
|
|
this.screenEffectRenderer.renderScreenEffect(isSleeping, deltaPartialTick, this.submitNodeStorage);
|
|
this.featureRenderDispatcher.renderAllFeatures();
|
|
bufferSource.endBatch();
|
|
profiler.pop();
|
|
RenderSystem.setShaderFog(this.fogRenderer.getBuffer(FogRenderer.FogMode.NONE));
|
|
if (this.minecraft.debugEntries.isCurrentlyEnabled(DebugScreenEntries.THREE_DIMENSIONAL_CROSSHAIR) && this.minecraft.options.getCameraType().isFirstPerson() && !this.minecraft.options.hideGui) {
|
|
this.minecraft.getDebugOverlay().render3dCrosshair(this.mainCamera);
|
|
}
|
|
}
|
|
|
|
private void extractCamera(float partialTicks) {
|
|
CameraRenderState cameraState = this.levelRenderState.cameraRenderState;
|
|
cameraState.initialized = this.mainCamera.isInitialized();
|
|
cameraState.pos = this.mainCamera.position();
|
|
cameraState.blockPos = this.mainCamera.blockPosition();
|
|
cameraState.entityPos = this.mainCamera.entity().getPosition(partialTicks);
|
|
cameraState.orientation = new Quaternionf((Quaternionfc)this.mainCamera.rotation());
|
|
}
|
|
|
|
private Matrix4f getProjectionMatrixForCulling(float fovWithEffects) {
|
|
float fovForCulling = Math.max(fovWithEffects, (float)this.minecraft.options.fov().get().intValue());
|
|
return this.getProjectionMatrix(fovForCulling);
|
|
}
|
|
|
|
public void resetData() {
|
|
this.screenEffectRenderer.resetItemActivation();
|
|
this.minecraft.getMapTextureManager().resetData();
|
|
this.mainCamera.reset();
|
|
this.hasWorldScreenshot = false;
|
|
}
|
|
|
|
public void displayItemActivation(ItemStack itemStack) {
|
|
this.screenEffectRenderer.displayItemActivation(itemStack, this.random);
|
|
}
|
|
|
|
public Minecraft getMinecraft() {
|
|
return this.minecraft;
|
|
}
|
|
|
|
public float getDarkenWorldAmount(float a) {
|
|
return Mth.lerp(a, this.darkenWorldAmountO, this.darkenWorldAmount);
|
|
}
|
|
|
|
public float getRenderDistance() {
|
|
return this.renderDistance;
|
|
}
|
|
|
|
public Camera getMainCamera() {
|
|
return this.mainCamera;
|
|
}
|
|
|
|
public LightTexture lightTexture() {
|
|
return this.lightTexture;
|
|
}
|
|
|
|
public OverlayTexture overlayTexture() {
|
|
return this.overlayTexture;
|
|
}
|
|
|
|
@Override
|
|
public Vec3 projectPointToScreen(Vec3 point) {
|
|
Matrix4f projectionMatrix = this.getProjectionMatrix(this.getFov(this.mainCamera, 0.0f, true));
|
|
Quaternionf inverseRotation = this.mainCamera.rotation().conjugate(new Quaternionf());
|
|
Matrix4f modelViewMatrix = new Matrix4f().rotation((Quaternionfc)inverseRotation);
|
|
Matrix4f mvp = projectionMatrix.mul((Matrix4fc)modelViewMatrix);
|
|
Vec3 camPos = this.mainCamera.position();
|
|
Vec3 offset = point.subtract(camPos);
|
|
Vector3f vector3f = mvp.transformProject(offset.toVector3f());
|
|
return new Vec3((Vector3fc)vector3f);
|
|
}
|
|
|
|
@Override
|
|
public double projectHorizonToScreen() {
|
|
float xRot = this.mainCamera.xRot();
|
|
if (xRot <= -90.0f) {
|
|
return Double.NEGATIVE_INFINITY;
|
|
}
|
|
if (xRot >= 90.0f) {
|
|
return Double.POSITIVE_INFINITY;
|
|
}
|
|
float fov = this.getFov(this.mainCamera, 0.0f, true);
|
|
return Math.tan(xRot * ((float)Math.PI / 180)) / Math.tan(fov / 2.0f * ((float)Math.PI / 180));
|
|
}
|
|
|
|
public GlobalSettingsUniform getGlobalSettingsUniform() {
|
|
return this.globalSettingsUniform;
|
|
}
|
|
|
|
public Lighting getLighting() {
|
|
return this.lighting;
|
|
}
|
|
|
|
public void setLevel(@Nullable ClientLevel level) {
|
|
if (level != null) {
|
|
this.lighting.updateLevel(level.dimensionType().cardinalLightType());
|
|
}
|
|
}
|
|
|
|
public PanoramaRenderer getPanorama() {
|
|
return this.panorama;
|
|
}
|
|
}
|
|
|