136 lines
4.7 KiB
Java
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;
|
|
}
|
|
}
|