142 lines
4.9 KiB
Java
142 lines
4.9 KiB
Java
package net.minecraft.client.gui.render.pip;
|
|
|
|
import com.mojang.blaze3d.ProjectionType;
|
|
import com.mojang.blaze3d.systems.GpuDevice;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import com.mojang.blaze3d.textures.FilterMode;
|
|
import com.mojang.blaze3d.textures.GpuTexture;
|
|
import com.mojang.blaze3d.textures.GpuTextureView;
|
|
import com.mojang.blaze3d.textures.TextureFormat;
|
|
import com.mojang.blaze3d.vertex.PoseStack;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.client.gui.render.TextureSetup;
|
|
import net.minecraft.client.gui.render.state.BlitRenderState;
|
|
import net.minecraft.client.gui.render.state.GuiRenderState;
|
|
import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState;
|
|
import net.minecraft.client.renderer.CachedOrthoProjectionMatrixBuffer;
|
|
import net.minecraft.client.renderer.MultiBufferSource;
|
|
import net.minecraft.client.renderer.RenderPipelines;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public abstract class PictureInPictureRenderer<T extends PictureInPictureRenderState> implements AutoCloseable {
|
|
protected final MultiBufferSource.BufferSource bufferSource;
|
|
@Nullable
|
|
private GpuTexture texture;
|
|
@Nullable
|
|
private GpuTextureView textureView;
|
|
@Nullable
|
|
private GpuTexture depthTexture;
|
|
@Nullable
|
|
private GpuTextureView depthTextureView;
|
|
private final CachedOrthoProjectionMatrixBuffer projectionMatrixBuffer = new CachedOrthoProjectionMatrixBuffer(
|
|
"PIP - " + this.getClass().getSimpleName(), -1000.0F, 1000.0F, true
|
|
);
|
|
|
|
protected PictureInPictureRenderer(MultiBufferSource.BufferSource bufferSource) {
|
|
this.bufferSource = bufferSource;
|
|
}
|
|
|
|
public void prepare(T renderState, GuiRenderState guiRenderState, int guiScale) {
|
|
int i = (renderState.x1() - renderState.x0()) * guiScale;
|
|
int j = (renderState.y1() - renderState.y0()) * guiScale;
|
|
boolean bl = this.texture == null || this.texture.getWidth(0) != i || this.texture.getHeight(0) != j;
|
|
if (!bl && this.textureIsReadyToBlit(renderState)) {
|
|
this.blitTexture(renderState, guiRenderState);
|
|
} else {
|
|
this.prepareTexturesAndProjection(bl, i, j);
|
|
RenderSystem.outputColorTextureOverride = this.textureView;
|
|
RenderSystem.outputDepthTextureOverride = this.depthTextureView;
|
|
PoseStack poseStack = new PoseStack();
|
|
poseStack.translate(i / 2.0F, this.getTranslateY(j, guiScale), 0.0F);
|
|
float f = guiScale * renderState.scale();
|
|
poseStack.scale(f, f, -f);
|
|
this.renderToTexture(renderState, poseStack);
|
|
this.bufferSource.endBatch();
|
|
RenderSystem.outputColorTextureOverride = null;
|
|
RenderSystem.outputDepthTextureOverride = null;
|
|
this.blitTexture(renderState, guiRenderState);
|
|
}
|
|
}
|
|
|
|
protected void blitTexture(T renderState, GuiRenderState guiRenderState) {
|
|
guiRenderState.submitBlitToCurrentLayer(
|
|
new BlitRenderState(
|
|
RenderPipelines.GUI_TEXTURED_PREMULTIPLIED_ALPHA,
|
|
TextureSetup.singleTexture(this.textureView),
|
|
renderState.pose(),
|
|
renderState.x0(),
|
|
renderState.y0(),
|
|
renderState.x1(),
|
|
renderState.y1(),
|
|
0.0F,
|
|
1.0F,
|
|
1.0F,
|
|
0.0F,
|
|
-1,
|
|
renderState.scissorArea(),
|
|
null
|
|
)
|
|
);
|
|
}
|
|
|
|
private void prepareTexturesAndProjection(boolean resetTexture, int width, int height) {
|
|
if (this.texture != null && resetTexture) {
|
|
this.texture.close();
|
|
this.texture = null;
|
|
this.textureView.close();
|
|
this.textureView = null;
|
|
this.depthTexture.close();
|
|
this.depthTexture = null;
|
|
this.depthTextureView.close();
|
|
this.depthTextureView = null;
|
|
}
|
|
|
|
GpuDevice gpuDevice = RenderSystem.getDevice();
|
|
if (this.texture == null) {
|
|
this.texture = gpuDevice.createTexture(() -> "UI " + this.getTextureLabel() + " texture", 12, TextureFormat.RGBA8, width, height, 1, 1);
|
|
this.texture.setTextureFilter(FilterMode.NEAREST, false);
|
|
this.textureView = gpuDevice.createTextureView(this.texture);
|
|
this.depthTexture = gpuDevice.createTexture(() -> "UI " + this.getTextureLabel() + " depth texture", 8, TextureFormat.DEPTH32, width, height, 1, 1);
|
|
this.depthTextureView = gpuDevice.createTextureView(this.depthTexture);
|
|
}
|
|
|
|
gpuDevice.createCommandEncoder().clearColorAndDepthTextures(this.texture, 0, this.depthTexture, 1.0);
|
|
RenderSystem.setProjectionMatrix(this.projectionMatrixBuffer.getBuffer(width, height), ProjectionType.ORTHOGRAPHIC);
|
|
}
|
|
|
|
protected boolean textureIsReadyToBlit(T renderState) {
|
|
return false;
|
|
}
|
|
|
|
protected float getTranslateY(int height, int guiScale) {
|
|
return height;
|
|
}
|
|
|
|
public void close() {
|
|
if (this.texture != null) {
|
|
this.texture.close();
|
|
}
|
|
|
|
if (this.textureView != null) {
|
|
this.textureView.close();
|
|
}
|
|
|
|
if (this.depthTexture != null) {
|
|
this.depthTexture.close();
|
|
}
|
|
|
|
if (this.depthTextureView != null) {
|
|
this.depthTextureView.close();
|
|
}
|
|
|
|
this.projectionMatrixBuffer.close();
|
|
}
|
|
|
|
public abstract Class<T> getRenderStateClass();
|
|
|
|
protected abstract void renderToTexture(T renderState, PoseStack poseStack);
|
|
|
|
protected abstract String getTextureLabel();
|
|
}
|