261 lines
8.7 KiB
Java
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;
|
|
}
|
|
}
|