minecraft-src/com/mojang/blaze3d/pipeline/RenderTarget.java
2025-07-04 02:49:36 +03:00

235 lines
8 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.renderer.CompiledShaderProgram;
import net.minecraft.client.renderer.CoreShaders;
@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) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._enableDepthTest();
if (this.frameBufferId >= 0) {
this.destroyBuffers();
}
this.createBuffers(width, height);
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) {
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();
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) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._glBindFramebuffer(36160, this.frameBufferId);
if (setViewport) {
GlStateManager._viewport(0, 0, this.viewWidth, this.viewHeight);
}
}
public void unbindWrite() {
RenderSystem.assertOnRenderThreadOrInit();
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) {
GlStateManager._glBindFramebuffer(36008, this.frameBufferId);
GlStateManager._glBlitFrameBuffer(0, 0, this.width, this.height, 0, 0, width, height, 16384, 9728);
GlStateManager._glBindFramebuffer(36008, 0);
}
public void blitAndBlendToScreen(int width, int height) {
RenderSystem.assertOnRenderThread();
GlStateManager._colorMask(true, true, true, false);
GlStateManager._disableDepthTest();
GlStateManager._depthMask(false);
GlStateManager._viewport(0, 0, width, height);
CompiledShaderProgram compiledShaderProgram = (CompiledShaderProgram)Objects.requireNonNull(
RenderSystem.setShader(CoreShaders.BLIT_SCREEN), "Blit shader not loaded"
);
compiledShaderProgram.bindSampler("InSampler", this.colorTextureId);
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.drawWithShader(bufferBuilder.buildOrThrow());
GlStateManager._depthMask(true);
GlStateManager._colorMask(true, true, true, true);
}
public void clear() {
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);
this.unbindWrite();
}
public int getColorTextureId() {
return this.colorTextureId;
}
public int getDepthTextureId() {
return this.depthBufferId;
}
}