minecraft-src/com/mojang/blaze3d/pipeline/RenderTarget.java
2025-07-04 01:41:11 +03:00

261 lines
8.7 KiB
Java

package com.mojang.blaze3d.pipeline;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.platform.TextureUtil;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.BufferUploader;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import java.util.Objects;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ShaderInstance;
@Environment(EnvType.CLIENT)
public abstract class RenderTarget {
private static final int RED_CHANNEL = 0;
private static final int GREEN_CHANNEL = 1;
private static final int BLUE_CHANNEL = 2;
private static final int ALPHA_CHANNEL = 3;
public int width;
public int height;
public int viewWidth;
public int viewHeight;
public final boolean useDepth;
public int frameBufferId;
protected int colorTextureId;
protected int depthBufferId;
private final float[] clearChannels = Util.make(() -> new float[]{1.0F, 1.0F, 1.0F, 0.0F});
public int filterMode;
public RenderTarget(boolean useDepth) {
this.useDepth = useDepth;
this.frameBufferId = -1;
this.colorTextureId = -1;
this.depthBufferId = -1;
}
public void resize(int width, int height, boolean clearError) {
if (!RenderSystem.isOnRenderThread()) {
RenderSystem.recordRenderCall(() -> this._resize(width, height, clearError));
} else {
this._resize(width, height, clearError);
}
}
private void _resize(int width, int height, boolean clearError) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._enableDepthTest();
if (this.frameBufferId >= 0) {
this.destroyBuffers();
}
this.createBuffers(width, height, clearError);
GlStateManager._glBindFramebuffer(36160, 0);
}
public void destroyBuffers() {
RenderSystem.assertOnRenderThreadOrInit();
this.unbindRead();
this.unbindWrite();
if (this.depthBufferId > -1) {
TextureUtil.releaseTextureId(this.depthBufferId);
this.depthBufferId = -1;
}
if (this.colorTextureId > -1) {
TextureUtil.releaseTextureId(this.colorTextureId);
this.colorTextureId = -1;
}
if (this.frameBufferId > -1) {
GlStateManager._glBindFramebuffer(36160, 0);
GlStateManager._glDeleteFramebuffers(this.frameBufferId);
this.frameBufferId = -1;
}
}
public void copyDepthFrom(RenderTarget otherTarget) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._glBindFramebuffer(36008, otherTarget.frameBufferId);
GlStateManager._glBindFramebuffer(36009, this.frameBufferId);
GlStateManager._glBlitFrameBuffer(0, 0, otherTarget.width, otherTarget.height, 0, 0, this.width, this.height, 256, 9728);
GlStateManager._glBindFramebuffer(36160, 0);
}
public void createBuffers(int width, int height, boolean clearError) {
RenderSystem.assertOnRenderThreadOrInit();
int i = RenderSystem.maxSupportedTextureSize();
if (width > 0 && width <= i && height > 0 && height <= i) {
this.viewWidth = width;
this.viewHeight = height;
this.width = width;
this.height = height;
this.frameBufferId = GlStateManager.glGenFramebuffers();
this.colorTextureId = TextureUtil.generateTextureId();
if (this.useDepth) {
this.depthBufferId = TextureUtil.generateTextureId();
GlStateManager._bindTexture(this.depthBufferId);
GlStateManager._texParameter(3553, 10241, 9728);
GlStateManager._texParameter(3553, 10240, 9728);
GlStateManager._texParameter(3553, 34892, 0);
GlStateManager._texParameter(3553, 10242, 33071);
GlStateManager._texParameter(3553, 10243, 33071);
GlStateManager._texImage2D(3553, 0, 6402, this.width, this.height, 0, 6402, 5126, null);
}
this.setFilterMode(9728, true);
GlStateManager._bindTexture(this.colorTextureId);
GlStateManager._texParameter(3553, 10242, 33071);
GlStateManager._texParameter(3553, 10243, 33071);
GlStateManager._texImage2D(3553, 0, 32856, this.width, this.height, 0, 6408, 5121, null);
GlStateManager._glBindFramebuffer(36160, this.frameBufferId);
GlStateManager._glFramebufferTexture2D(36160, 36064, 3553, this.colorTextureId, 0);
if (this.useDepth) {
GlStateManager._glFramebufferTexture2D(36160, 36096, 3553, this.depthBufferId, 0);
}
this.checkStatus();
this.clear(clearError);
this.unbindRead();
} else {
throw new IllegalArgumentException("Window " + width + "x" + height + " size out of bounds (max. size: " + i + ")");
}
}
public void setFilterMode(int filterMode) {
this.setFilterMode(filterMode, false);
}
private void setFilterMode(int filterMode, boolean force) {
RenderSystem.assertOnRenderThreadOrInit();
if (force || filterMode != this.filterMode) {
this.filterMode = filterMode;
GlStateManager._bindTexture(this.colorTextureId);
GlStateManager._texParameter(3553, 10241, filterMode);
GlStateManager._texParameter(3553, 10240, filterMode);
GlStateManager._bindTexture(0);
}
}
public void checkStatus() {
RenderSystem.assertOnRenderThreadOrInit();
int i = GlStateManager.glCheckFramebufferStatus(36160);
if (i != 36053) {
if (i == 36054) {
throw new RuntimeException("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
} else if (i == 36055) {
throw new RuntimeException("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
} else if (i == 36059) {
throw new RuntimeException("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER");
} else if (i == 36060) {
throw new RuntimeException("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER");
} else if (i == 36061) {
throw new RuntimeException("GL_FRAMEBUFFER_UNSUPPORTED");
} else if (i == 1285) {
throw new RuntimeException("GL_OUT_OF_MEMORY");
} else {
throw new RuntimeException("glCheckFramebufferStatus returned unknown status:" + i);
}
}
}
public void bindRead() {
RenderSystem.assertOnRenderThread();
GlStateManager._bindTexture(this.colorTextureId);
}
public void unbindRead() {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._bindTexture(0);
}
public void bindWrite(boolean setViewport) {
if (!RenderSystem.isOnRenderThread()) {
RenderSystem.recordRenderCall(() -> this._bindWrite(setViewport));
} else {
this._bindWrite(setViewport);
}
}
private void _bindWrite(boolean setViewport) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._glBindFramebuffer(36160, this.frameBufferId);
if (setViewport) {
GlStateManager._viewport(0, 0, this.viewWidth, this.viewHeight);
}
}
public void unbindWrite() {
if (!RenderSystem.isOnRenderThread()) {
RenderSystem.recordRenderCall(() -> GlStateManager._glBindFramebuffer(36160, 0));
} else {
GlStateManager._glBindFramebuffer(36160, 0);
}
}
public void setClearColor(float red, float green, float blue, float alpha) {
this.clearChannels[0] = red;
this.clearChannels[1] = green;
this.clearChannels[2] = blue;
this.clearChannels[3] = alpha;
}
public void blitToScreen(int width, int height) {
this.blitToScreen(width, height, true);
}
public void blitToScreen(int width, int height, boolean disableBlend) {
this._blitToScreen(width, height, disableBlend);
}
private void _blitToScreen(int width, int height, boolean disableBlend) {
RenderSystem.assertOnRenderThread();
GlStateManager._colorMask(true, true, true, false);
GlStateManager._disableDepthTest();
GlStateManager._depthMask(false);
GlStateManager._viewport(0, 0, width, height);
if (disableBlend) {
GlStateManager._disableBlend();
}
Minecraft minecraft = Minecraft.getInstance();
ShaderInstance shaderInstance = (ShaderInstance)Objects.requireNonNull(minecraft.gameRenderer.blitShader, "Blit shader not loaded");
shaderInstance.setSampler("DiffuseSampler", this.colorTextureId);
shaderInstance.apply();
BufferBuilder bufferBuilder = RenderSystem.renderThreadTesselator().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLIT_SCREEN);
bufferBuilder.addVertex(0.0F, 0.0F, 0.0F);
bufferBuilder.addVertex(1.0F, 0.0F, 0.0F);
bufferBuilder.addVertex(1.0F, 1.0F, 0.0F);
bufferBuilder.addVertex(0.0F, 1.0F, 0.0F);
BufferUploader.draw(bufferBuilder.buildOrThrow());
shaderInstance.clear();
GlStateManager._depthMask(true);
GlStateManager._colorMask(true, true, true, true);
}
public void clear(boolean clearError) {
RenderSystem.assertOnRenderThreadOrInit();
this.bindWrite(true);
GlStateManager._clearColor(this.clearChannels[0], this.clearChannels[1], this.clearChannels[2], this.clearChannels[3]);
int i = 16384;
if (this.useDepth) {
GlStateManager._clearDepth(1.0);
i |= 256;
}
GlStateManager._clear(i, clearError);
this.unbindWrite();
}
public int getColorTextureId() {
return this.colorTextureId;
}
public int getDepthTextureId() {
return this.depthBufferId;
}
}