minecraft-src/com/mojang/blaze3d/pipeline/RenderTarget.java
2025-07-04 03:45:38 +03:00

136 lines
4.7 KiB
Java

package com.mojang.blaze3d.pipeline;
import com.mojang.blaze3d.buffers.GpuBuffer;
import com.mojang.blaze3d.systems.RenderPass;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.textures.AddressMode;
import com.mojang.blaze3d.textures.FilterMode;
import com.mojang.blaze3d.textures.GpuTexture;
import com.mojang.blaze3d.textures.TextureFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import java.util.OptionalInt;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.RenderPipelines;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public abstract class RenderTarget {
private static int UNNAMED_RENDER_TARGETS = 0;
public int width;
public int height;
public int viewWidth;
public int viewHeight;
protected final String label;
public final boolean useDepth;
@Nullable
protected GpuTexture colorTexture;
@Nullable
protected GpuTexture depthTexture;
public FilterMode filterMode;
public RenderTarget(@Nullable String name, boolean useDepth) {
this.label = name == null ? "FBO " + UNNAMED_RENDER_TARGETS++ : name;
this.useDepth = useDepth;
}
public void resize(int width, int height) {
RenderSystem.assertOnRenderThread();
this.destroyBuffers();
this.createBuffers(width, height);
}
public void destroyBuffers() {
RenderSystem.assertOnRenderThread();
if (this.depthTexture != null) {
this.depthTexture.close();
this.depthTexture = null;
}
if (this.colorTexture != null) {
this.colorTexture.close();
this.colorTexture = null;
}
}
public void copyDepthFrom(RenderTarget otherTarget) {
RenderSystem.assertOnRenderThread();
if (this.depthTexture == null) {
throw new IllegalStateException("Trying to copy depth texture to a RenderTarget without a depth texture");
} else if (otherTarget.depthTexture == null) {
throw new IllegalStateException("Trying to copy depth texture from a RenderTarget without a depth texture");
} else {
RenderSystem.getDevice().createCommandEncoder().copyTextureToTexture(otherTarget.depthTexture, this.depthTexture, 0, 0, 0, 0, 0, this.width, this.height);
}
}
public void createBuffers(int width, int height) {
RenderSystem.assertOnRenderThread();
int i = RenderSystem.getDevice().getMaxTextureSize();
if (width > 0 && width <= i && height > 0 && height <= i) {
this.viewWidth = width;
this.viewHeight = height;
this.width = width;
this.height = height;
if (this.useDepth) {
this.depthTexture = RenderSystem.getDevice().createTexture(() -> this.label + " / Depth", TextureFormat.DEPTH32, width, height, 1);
this.depthTexture.setTextureFilter(FilterMode.NEAREST, false);
this.depthTexture.setAddressMode(AddressMode.CLAMP_TO_EDGE);
}
this.colorTexture = RenderSystem.getDevice().createTexture(() -> this.label + " / Color", TextureFormat.RGBA8, width, height, 1);
this.colorTexture.setAddressMode(AddressMode.CLAMP_TO_EDGE);
this.setFilterMode(FilterMode.NEAREST, true);
} else {
throw new IllegalArgumentException("Window " + width + "x" + height + " size out of bounds (max. size: " + i + ")");
}
}
public void setFilterMode(FilterMode filterMode) {
this.setFilterMode(filterMode, false);
}
private void setFilterMode(FilterMode filterMode, boolean force) {
if (this.colorTexture == null) {
throw new IllegalStateException("Can't change filter mode, color texture doesn't exist yet");
} else {
if (force || filterMode != this.filterMode) {
this.filterMode = filterMode;
this.colorTexture.setTextureFilter(filterMode, false);
}
}
}
public void blitToScreen() {
if (this.colorTexture == null) {
throw new IllegalStateException("Can't blit to screen, color texture doesn't exist yet");
} else {
RenderSystem.getDevice().createCommandEncoder().presentTexture(this.colorTexture);
}
}
public void blitAndBlendToTexture(GpuTexture texture) {
RenderSystem.assertOnRenderThread();
RenderSystem.AutoStorageIndexBuffer autoStorageIndexBuffer = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS);
GpuBuffer gpuBuffer = autoStorageIndexBuffer.getBuffer(6);
GpuBuffer gpuBuffer2 = RenderSystem.getQuadVertexBuffer();
try (RenderPass renderPass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(texture, OptionalInt.empty())) {
renderPass.setPipeline(RenderPipelines.ENTITY_OUTLINE_BLIT);
renderPass.setVertexBuffer(0, gpuBuffer2);
renderPass.setIndexBuffer(gpuBuffer, autoStorageIndexBuffer.type());
renderPass.bindSampler("InSampler", this.colorTexture);
renderPass.drawIndexed(0, 6);
}
}
@Nullable
public GpuTexture getColorTexture() {
return this.colorTexture;
}
@Nullable
public GpuTexture getDepthTexture() {
return this.depthTexture;
}
}