From c80805fc668794dca5eb6cff0776d2b9c53781cf Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Sat, 17 May 2025 12:38:29 +0200 Subject: [PATCH] refactor: fbo --- .../java/chess/view/DDDrender/Renderer.java | 41 ++----- .../java/chess/view/DDDrender/Window.java | 64 ++++++----- .../view/DDDrender/opengl/FrameBuffer.java | 106 ++++++++++++++++++ 3 files changed, 153 insertions(+), 58 deletions(-) create mode 100644 app/src/main/java/chess/view/DDDrender/opengl/FrameBuffer.java diff --git a/app/src/main/java/chess/view/DDDrender/Renderer.java b/app/src/main/java/chess/view/DDDrender/Renderer.java index eb66ad0..a7ee8ac 100644 --- a/app/src/main/java/chess/view/DDDrender/Renderer.java +++ b/app/src/main/java/chess/view/DDDrender/Renderer.java @@ -1,21 +1,15 @@ package chess.view.DDDrender; -import static org.lwjgl.opengl.GL11.GL_DEPTH_COMPONENT; -import static org.lwjgl.opengl.GL11.GL_RGB; -import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; -import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; import static org.lwjgl.opengl.GL11.GL_UNSIGNED_INT; -import static org.lwjgl.opengl.GL11.glBindTexture; -import static org.lwjgl.opengl.GL11.glTexImage2D; import java.io.Closeable; import java.io.IOException; -import java.nio.IntBuffer; import org.joml.Matrix4f; import org.joml.Vector3f; import org.lwjgl.opengl.GL30; +import chess.view.DDDrender.opengl.FrameBuffer; import chess.view.DDDrender.opengl.VertexArray; import chess.view.DDDrender.shader.BoardShader; import chess.view.DDDrender.shader.PieceShader; @@ -24,41 +18,18 @@ import chess.view.DDDrender.shader.ShaderProgram; public class Renderer implements Closeable { private BoardShader boardShader; private PieceShader pieceShader; + private FrameBuffer frameBuffer; public Renderer() { this.boardShader = new BoardShader(); this.pieceShader = new PieceShader(); } - public void Init() { + public void Init(float windowWidth, float widowHeight) { boardShader.LoadShader(); pieceShader.LoadShader(); - // The frame buffer - int fbo = GL30.glGenFramebuffers(); - GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, fbo); - - // The texture - int renderTexture = GL30.glGenTextures(); - glBindTexture(GL_TEXTURE_2D, renderTexture); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 800, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - - GL30.glTexParameteri(GL_TEXTURE_2D, GL30.GL_TEXTURE_MAG_FILTER, GL30.GL_NEAREST); - GL30.glTexParameteri(GL_TEXTURE_2D, GL30.GL_TEXTURE_MIN_FILTER, GL30.GL_NEAREST); - - // The depth buffer - int depthBuffer = GL30.glGenRenderbuffers(); - GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBuffer); - GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 800, 800); - GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER, - depthBuffer); - - // Set "renderedTexture" as our colour attachement #0 - GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0); - // Set the list of draw buffers. - int[] drawBuffers = { GL30.GL_COLOR_ATTACHMENT0 }; - GL30.glDrawBuffers(drawBuffers); + this.frameBuffer = new FrameBuffer((int) windowWidth, (int) (widowHeight * 8.0f / 10.0f)); } public void Update(Camera cam) { @@ -89,6 +60,10 @@ public class Renderer implements Closeable { vertexArray.Unbind(); } + public FrameBuffer getFrameBuffer() { + return frameBuffer; + } + public BoardShader getBoardShader() { return boardShader; } diff --git a/app/src/main/java/chess/view/DDDrender/Window.java b/app/src/main/java/chess/view/DDDrender/Window.java index 4e92982..2cac876 100644 --- a/app/src/main/java/chess/view/DDDrender/Window.java +++ b/app/src/main/java/chess/view/DDDrender/Window.java @@ -9,14 +9,18 @@ import org.lwjgl.system.*; import chess.model.Coordinate; import chess.view.AssetManager; +import chess.view.DDDrender.opengl.FrameBuffer; import chess.view.DDDrender.world.Entity; import chess.view.DDDrender.world.World; import common.Signal1; import imgui.ImFontConfig; import imgui.ImGui; import imgui.ImVec2; +import imgui.flag.ImGuiWindowFlags; import imgui.gl3.ImGuiImplGl3; import imgui.glfw.ImGuiImplGlfw; +import imgui.type.ImBoolean; +import imgui.type.ImInt; import java.io.Closeable; import java.io.IOException; @@ -57,6 +61,9 @@ public class Window implements Closeable { public final Signal0 OnImGuiTopRender = new Signal0(); public final Signal0 OnImGuiBottomRender = new Signal0(); + private ImInt detailLevel = new ImInt(10); + private ImBoolean pixelatedFrame = new ImBoolean(true); + public Window(Renderer renderer, World world, Camera camera) { this.renderer = new Renderer(); this.cam = camera; @@ -153,17 +160,17 @@ public class Window implements Closeable { (vidmode.height() - pHeight.get(0)) / 2); glfwSetWindowSize(window, vidmode.width(), vidmode.height()); + + // Make the OpenGL context current + glfwMakeContextCurrent(window); + + GL.createCapabilities(); + + initImGui(); + + renderer.Init(vidmode.width(), vidmode.height()); } // the stack frame is popped automatically - // Make the OpenGL context current - glfwMakeContextCurrent(window); - - GL.createCapabilities(); - - initImGui(); - - renderer.Init(); - // Enable v-sync glfwSwapInterval(1); @@ -172,13 +179,14 @@ public class Window implements Closeable { } private void render(float delta, float aspectRatio) { - cam.setAspectRatio(1.0f); - GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 1); - glViewport(0, 0, 800, 800); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer + final FrameBuffer frameBuffer = this.renderer.getFrameBuffer(); + + cam.setAspectRatio(frameBuffer.getAspectRatio()); + frameBuffer.Bind(); + frameBuffer.Clear(); renderer.Update(cam); renderWorld(); - GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0); + frameBuffer.Unbind(); } private void renderWorld() { @@ -231,13 +239,25 @@ public class Window implements Closeable { private void renderWindow() { ImGui.showDemoWindow(); - ImGui.begin("Main Window"); + final FrameBuffer frameBuffer = this.renderer.getFrameBuffer(); + final int frameWidth = (int) ImGui.getIO().getDisplaySizeX(); + final int frameHeight = (int) (ImGui.getIO().getDisplaySizeY() * 8.0f / 10.0f); + + ImGui.setNextWindowSize(ImGui.getIO().getDisplaySize()); + ImGui.setNextWindowPos(new ImVec2()); + ImGui.begin("Main Window", ImGuiWindowFlags.NoDecoration); this.OnImGuiTopRender.emit(); ImVec2 mousePos = ImGui.getIO().getMousePos(); ImVec2 framePos = ImGui.getCursorScreenPos(); - checkCursor(mousePos.x - framePos.x, 800 - (mousePos.y - framePos.y), 800, 800); - ImGui.image(1, new ImVec2(800, 800)); + checkCursor(mousePos.x - framePos.x, frameHeight - (mousePos.y - framePos.y), frameWidth, frameHeight); + ImGui.image(frameBuffer.getRenderTexture(), new ImVec2(frameWidth, frameHeight)); this.OnImGuiBottomRender.emit(); + if(ImGui.sliderInt("Niveau de détail", detailLevel.getData(), 1, 10)){ + frameBuffer.Resize((int) ((float) frameWidth * detailLevel.get() / 10.0f), (int) ((float) frameHeight * detailLevel.get() / 10.0f)); + } + if (ImGui.checkbox("Minecraft", pixelatedFrame)) { + frameBuffer.SetPixelScaling(pixelatedFrame.get()); + } ImGui.end(); } @@ -254,8 +274,6 @@ public class Window implements Closeable { glColor4f(1.0f, 0.0f, 0.0f, 1.0f); - double lastTime = glfwGetTime(); - int width[] = new int[1]; int height[] = new int[1]; glfwGetWindowSize(window, width, height); @@ -266,23 +284,19 @@ public class Window implements Closeable { newFrame(); - double currentTime = glfwGetTime(); - float deltaTime = (float) (currentTime - lastTime); - render(deltaTime, (float) width[0] / (float) height[0]); + render(ImGui.getIO().getDeltaTime(), (float) width[0] / (float) height[0]); renderWindow(); ImGui.render(); implGl3.renderDrawData(ImGui.getDrawData()); - lastTime = glfwGetTime(); - glfwSwapBuffers(window); // swap the color buffers // Poll for window events. The key callback above will only be // invoked during this call. glfwPollEvents(); - executeTasks(deltaTime); + executeTasks(ImGui.getIO().getDeltaTime()); glfwGetWindowSize(window, width, height); glViewport(0, 0, width[0], height[0]); diff --git a/app/src/main/java/chess/view/DDDrender/opengl/FrameBuffer.java b/app/src/main/java/chess/view/DDDrender/opengl/FrameBuffer.java new file mode 100644 index 0000000..d145f3f --- /dev/null +++ b/app/src/main/java/chess/view/DDDrender/opengl/FrameBuffer.java @@ -0,0 +1,106 @@ +package chess.view.DDDrender.opengl; + +import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; +import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; +import static org.lwjgl.opengl.GL11.GL_DEPTH_COMPONENT; +import static org.lwjgl.opengl.GL11.GL_RGB; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; +import static org.lwjgl.opengl.GL11.glBindTexture; +import static org.lwjgl.opengl.GL11.glClear; +import static org.lwjgl.opengl.GL11.glTexImage2D; +import static org.lwjgl.opengl.GL11.glViewport; + +import org.lwjgl.opengl.GL30; + +public class FrameBuffer { + + private int fbo; + private int renderTexture; + private int depthBuffer; + + private int width; + private int height; + + public FrameBuffer(int width, int height) { + this.width = width; + this.height = height; + + // The frame buffer + this.fbo = GL30.glGenFramebuffers(); + GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, fbo); + + // The texture + this.renderTexture = GL30.glGenTextures(); + glBindTexture(GL_TEXTURE_2D, renderTexture); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + + GL30.glTexParameteri(GL_TEXTURE_2D, GL30.GL_TEXTURE_MAG_FILTER, GL30.GL_NEAREST); + GL30.glTexParameteri(GL_TEXTURE_2D, GL30.GL_TEXTURE_MIN_FILTER, GL30.GL_NEAREST); + + // The depth buffer + this.depthBuffer = GL30.glGenRenderbuffers(); + GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBuffer); + GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); + GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER, + depthBuffer); + + // Set "renderedTexture" as our colour attachement #0 + GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0); + // Set the list of draw buffers. + int[] drawBuffers = { GL30.GL_COLOR_ATTACHMENT0 }; + GL30.glDrawBuffers(drawBuffers); + } + + public void Bind() { + GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, this.fbo); + glViewport(0, 0, this.width, this.height); + } + + public void Unbind() { + GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0); + } + + public void Clear() { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer + } + + public void Resize(int width, int height) { + this.width = width; + this.height = height; + + GL30.glBindTexture(GL_TEXTURE_2D, this.renderTexture); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, this.width, this.height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + + GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, this.depthBuffer); + GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL_DEPTH_COMPONENT, this.width, this.height); + } + + public void SetPixelScaling(boolean pixelated) { + glBindTexture(GL_TEXTURE_2D, renderTexture); + + int method = pixelated ? GL30.GL_NEAREST : GL30.GL_LINEAR; + + GL30.glTexParameteri(GL_TEXTURE_2D, GL30.GL_TEXTURE_MAG_FILTER, method); + GL30.glTexParameteri(GL_TEXTURE_2D, GL30.GL_TEXTURE_MIN_FILTER, method); + } + + public float getAspectRatio() { + return (float) width / (float) height; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public int getRenderTexture() { + return renderTexture; + } + +}