initial imgui addition
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2024-03-06 21:24:21 -05:00
parent 3e6d918f16
commit cb0ef5f59e
10 changed files with 431 additions and 6 deletions

View File

@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file
#Thu Feb 29 18:57:13 EST 2024
buildNumber=30
#Wed Mar 06 19:14:23 EST 2024
buildNumber=31

View File

@ -125,7 +125,8 @@ Implement proper Frustum Culling
- Regular Actors
- Instanced Actors
(03/06/2024)
Bake in imgui
@ -142,7 +143,6 @@ Implement proper Frustum Culling
Bake in imgui
Build a lod system
- Could potentially be held at actor level

20
imgui.ini Normal file
View File

@ -0,0 +1,20 @@
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][test window]
Pos=791,428
Size=328,189
Collapsed=1
[Window][FPS Graph]
Pos=1148,36
Size=775,335
Collapsed=0
[Window][Frametime Graph]
Pos=1345,20
Size=566,324
Collapsed=0

28
pom.xml
View File

@ -12,6 +12,7 @@
<lwjgl.version>3.2.3</lwjgl.version>
<joml.version>1.9.19</joml.version>
<recast.version>1.5.7</recast.version>
<imgui.version>1.86.11</imgui.version>
</properties>
<!-- Used for build number plugin because it LITERALLY WONT LET YOU NOT HAVE SCM-->
@ -215,6 +216,33 @@
</dependency>
<!--imgui-->
<!--License: MIT-->
<!---->
<dependency>
<groupId>io.github.spair</groupId>
<artifactId>imgui-java-binding</artifactId>
<version>${imgui.version}</version>
</dependency>
<dependency>
<groupId>io.github.spair</groupId>
<artifactId>imgui-java-lwjgl3</artifactId>
<version>${imgui.version}</version>
</dependency>
<dependency>
<groupId>io.github.spair</groupId>
<artifactId>imgui-java-natives-windows</artifactId>
<version>${imgui.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.github.spair</groupId>
<artifactId>imgui-java-natives-linux</artifactId>
<version>${imgui.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<profiles>

View File

@ -17,6 +17,10 @@ import electrosphere.game.config.UserSettings;
import electrosphere.game.server.world.MacroData;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.ui.imgui.ImGuiLinePlot;
import electrosphere.renderer.ui.imgui.ImGuiWindow;
import electrosphere.renderer.ui.imgui.ImGuiWindowMacros;
import electrosphere.renderer.ui.imgui.ImGuiLinePlot.ImGuiLinePlotDataset;
import electrosphere.server.simulation.MacroSimulation;
@ -174,6 +178,11 @@ public class Main {
Globals.initDefaultGraphicalResources();
Globals.initDefaultAudioResources();
}
//init imgui debug windows
if(Globals.RUN_CLIENT && !Globals.HEADLESS){
ImGuiWindowMacros.createFramerateGraph();
}
//fire off a loading thread for the title menus/screen
LoggerInterface.loggerStartup.INFO("Fire off loading thread");
@ -208,8 +217,13 @@ public class Main {
*/
public static void mainLoop(long maxFrames){
double functionTrackTimeStart = 0;
boolean captureFramerate = false;
//main loop
while (running) {
//sets whether to capture framerates of current frame
captureFramerate = frameCount % 10 == 0;
/*
Frame calculation
@ -223,6 +237,15 @@ public class Main {
deltaTime = currentTime - lastFrame;
deltaFrames = targetFrameRate * (float)deltaTime;
lastFrame = currentTime;
//
// track total frametiime in debug graph
//
if(captureFramerate){
ImGuiWindowMacros.addFramerateDatapoint("totalframerate",deltaTime);
}
///
@ -264,6 +287,9 @@ public class Main {
///
/// C L I E N T S I M U L A T I O N S T U F F
///
if(!Globals.HEADLESS && captureFramerate){
functionTrackTimeStart = glfwGetTime();
}
if(Globals.clientSimulation != null && Globals.clientSimulation.isReady() && framestep > 0){
ClientFunctions.runBeforeSimulationFunctions();
}
@ -276,10 +302,26 @@ public class Main {
if(Globals.clientSimulation != null && Globals.clientSimulation.isReady() && framestep > 0){
ClientFunctions.runClientFunctions();
}
if(!Globals.HEADLESS && captureFramerate){
ImGuiWindowMacros.addFramerateDatapoint("clientsim",glfwGetTime()-functionTrackTimeStart);
}
///
/// S E R V E R M I C R O S I M U L A T I O N
///
if(!!Globals.HEADLESS && captureFramerate){
functionTrackTimeStart = glfwGetTime();
}
if(Globals.realmManager != null){
Globals.realmManager.simulate();
}
@ -290,11 +332,38 @@ public class Main {
if(Globals.macroSimulation != null && Globals.macroSimulation.isReady() && framestep > 0){
Globals.macroSimulation.simulate();
}
if(!Globals.HEADLESS && captureFramerate){
ImGuiWindowMacros.addFramerateDatapoint("serversim",glfwGetTime()-functionTrackTimeStart);
}
///
/// M A I N R E N D E R F U N C T I O N
///
if(!Globals.HEADLESS && captureFramerate){
functionTrackTimeStart = glfwGetTime();
}
if(Globals.RUN_CLIENT && !Globals.HEADLESS){
Globals.renderingEngine.drawScreen();
}
if(!Globals.HEADLESS && captureFramerate){
ImGuiWindowMacros.addFramerateDatapoint("render",glfwGetTime()-functionTrackTimeStart);
}
///
/// S H U T D O W N C H E C K
///
if(Globals.HEADLESS){
if(Globals.ENGINE_SHUTDOWN_FLAG){
@ -306,6 +375,14 @@ public class Main {
}
}
//
// C L E A N U P T I M E V A R I A B L E S
//
if(deltaTime < targetFramePeriod){
sleep((int)(1000.0 * (targetFramePeriod - deltaTime)));
} else {

View File

@ -60,6 +60,8 @@ import static org.lwjgl.opengl.GL40.glBlendFunci;
import static org.lwjgl.system.MemoryUtil.NULL;
import java.nio.IntBuffer;
import java.util.LinkedList;
import java.util.List;
import org.joml.Matrix4d;
import org.joml.Matrix4f;
@ -99,9 +101,17 @@ import electrosphere.renderer.light.LightManager;
import electrosphere.renderer.texture.Texture;
import electrosphere.renderer.ui.DrawableElement;
import electrosphere.renderer.ui.Element;
import electrosphere.renderer.ui.imgui.ImGuiLinePlot;
import electrosphere.renderer.ui.imgui.ImGuiWindow;
import electrosphere.renderer.ui.imgui.ImGuiLinePlot.ImGuiLinePlotDataset;
import electrosphere.server.pathfinding.navmesh.NavCube;
import electrosphere.server.pathfinding.navmesh.NavMesh;
import electrosphere.server.pathfinding.navmesh.NavShape;
import imgui.ImGui;
import imgui.extension.implot.ImPlot;
import imgui.gl3.ImGuiImplGl3;
import imgui.glfw.ImGuiImplGlfw;
import imgui.internal.ImGuiContext;
public class RenderingEngine {
@ -115,8 +125,29 @@ public class RenderingEngine {
static Renderbuffer screenRenderbuffer;
static int screenTextureVAO;
static ShaderProgram screenTextureShaders;
static ShaderProgram drawChannel;
//
//imgui related
//
//imgui internal objects
private static final ImGuiImplGlfw imGuiGlfw = new ImGuiImplGlfw();
private static final ImGuiImplGl3 imGuiGl13 = new ImGuiImplGl3();
//the version of glsl to init imgui with
private static String glslVersion = null;
//the context pointer for the core imgui objects
private static ImGuiContext imGuiContext = null;
//if set to true, will render imgui windows
private static boolean imGuiShouldRender = true;
//All imgui windows that should be displayed
private static List<ImGuiWindow> imGuiWindows = new LinkedList<ImGuiWindow>();
//depth framebuffer/shader for shadow mapping
static ShaderProgram lightDepthShaderProgram;
@ -202,6 +233,7 @@ public class RenderingEngine {
//Gives hints to glfw to control how opengl will be used
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glslVersion = "#version 410";
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); Allows you to make the background transparent
// glfwWindowHint(GLFW_OPACITY, 23);
@ -260,6 +292,12 @@ public class RenderingEngine {
//Creates the OpenGL capabilities for the program.
GL.createCapabilities();
//init imgui (must happen after gl.createCapabilities)
imGuiContext = ImGui.createContext();
ImPlot.createContext();
imGuiGlfw.init(Globals.window,true);
imGuiGl13.init(glslVersion);
//This enables Z-buffering so that farther-back polygons are not drawn over nearer ones
glEnable(GL_DEPTH_TEST);
@ -505,6 +543,19 @@ public class RenderingEngine {
if(Globals.RENDER_FLAG_RENDER_UI_BOUNDS){
DebugRendering.drawUIBoundsWireframe();
}
/**
* Render imgui
*/
if(imGuiShouldRender){
imGuiGlfw.newFrame();
ImGui.newFrame();
for(ImGuiWindow window : imGuiWindows){
window.draw();
}
ImGui.render();
imGuiGl13.renderDrawData(ImGui.getDrawData());
}
//check for errors
@ -1545,6 +1596,22 @@ public class RenderingEngine {
Globals.projectionMatrix.setPerspective(radVerticalFOV, RenderingEngine.aspectRatio, nearClip, Globals.userSettings.getGraphicsViewDistance());
}
/**
* Adds a window to the rendering engine
* @param window The window
*/
public static void addImGuiWindow(ImGuiWindow window){
imGuiWindows.add(window);
}
/**
* Removes an imgui window from the rendering engine
* @param window The window
*/
public static void removeImGuiWindow(ImGuiWindow window){
imGuiWindows.remove(window);
}
/**
* Gets the current render pipeline state
* @return The current render pipeline state

View File

@ -0,0 +1,13 @@
package electrosphere.renderer.ui.imgui;
/**
* Generic interface for something inside an imgui window
*/
public interface ImGuiElement {
/**
* Draws the ui for this element
*/
public void draw();
}

View File

@ -0,0 +1,108 @@
package electrosphere.renderer.ui.imgui;
import java.util.LinkedList;
import java.util.List;
import imgui.ImVec2;
import imgui.extension.implot.ImPlot;
import imgui.extension.implot.flag.ImPlotAxisFlags;
/**
* A line plot of a given set of data
*/
public class ImGuiLinePlot implements ImGuiElement {
//the title of the plot
String plotTitle;
//the data sets to draw
List<ImGuiLinePlotDataset> dataSets = new LinkedList<ImGuiLinePlotDataset>();
/**
* Creates an im gui line plot
*/
public ImGuiLinePlot(String plotTitle){
this.plotTitle = plotTitle;
}
@Override
public void draw() {
if(ImPlot.beginPlot(plotTitle,"","",new ImVec2(-1,-1),0,ImPlotAxisFlags.AutoFit,ImPlotAxisFlags.AutoFit)){
for(ImGuiLinePlotDataset dataSet : dataSets){
double[] xs = dataSet.xData.stream().mapToDouble(Double::doubleValue).toArray();//(Double[])dataSet.xData.toArray(new Double[dataSet.xData.size()]);
double[] ys = dataSet.yData.stream().mapToDouble(Double::doubleValue).toArray();//(Double[])dataSet.yData.toArray(new Double[dataSet.yData.size()]);
ImPlot.plotLine(dataSet.label, xs, ys, xs.length, 0);
}
ImPlot.endPlot();
}
}
/**
* Adds a dataset to the line plot
* @param dataset The dataset
*/
public void addDataset(ImGuiLinePlotDataset dataset){
this.dataSets.add(dataset);
}
/**
* A single set of data to be plotted in this graph
*/
public static class ImGuiLinePlotDataset {
//x data
List<Double> xData = new LinkedList<Double>();
//y data
List<Double> yData = new LinkedList<Double>();
//the label of the line
String label;
//the max number of points
int limit;
/**
* Creates a dataset object
* @param x the x data
* @param y the y data
* @param label the label for the data
* @param limit the maximum number of objects to keep in the dataset
*/
public ImGuiLinePlotDataset(String label, int limit){
this.label = label;
this.limit = limit;
}
/**
* Adds data to the data set. If the amount of data is greater than the limit, it will remove the oldest datapoint
* @param x the x value
* @param y the y value
*/
public void addPoint(double x, double y){
xData.add(x);
yData.add(y);
while(xData.size() > limit){
xData.remove(0);
}
while(yData.size() > limit){
yData.remove(0);
}
}
/**
* Adds data to the data set. If the amount of data is greater than the limit, it will remove the oldest datapoint.
* Does not clear the x axis so can constantly receive data and update without axis freaking out.
* @param y the y value
*/
public void addPoint(double y){
yData.add(y);
while(yData.size() > limit){
yData.remove(0);
}
}
}
}

View File

@ -0,0 +1,54 @@
package electrosphere.renderer.ui.imgui;
import java.util.LinkedList;
import java.util.List;
import imgui.ImGui;
/**
* A window in ImGui. The window can contain any number of controls and information.
*/
public class ImGuiWindow {
//the name of the window
String windowName;
//The elements housed within this window
List<ImGuiElement> elements = new LinkedList<ImGuiElement>();
/**
* Creates the window
*/
public ImGuiWindow(String windowName){
this.windowName = windowName;
}
/**
* Adds an imgui element to the window
*/
public void addElement(ImGuiElement element){
elements.add(element);
}
/**
* Removes an element from this window
* @param element The element
*/
public void removeElement(ImGuiElement element){
this.elements.remove(element);
}
/**
* Draws this window
*/
public void draw(){
ImGui.begin(windowName);
for(ImGuiElement element : elements){
element.draw();
}
ImGui.end();
}
}

View File

@ -0,0 +1,58 @@
package electrosphere.renderer.ui.imgui;
import java.util.HashMap;
import java.util.Map;
import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.ui.imgui.ImGuiLinePlot.ImGuiLinePlotDataset;
/**
* Various methods for creating specific imgui windows in engine
*/
public class ImGuiWindowMacros {
//Framerate graph
private static ImGuiWindow imGuiWindow;
private static ImGuiLinePlot plot;
private static Map<String,ImGuiLinePlotDataset> dataSetMap;
/**
* Creates a framerate graph
*/
public static void createFramerateGraph(){
imGuiWindow = new ImGuiWindow("Frametime Graph");
plot = new ImGuiLinePlot("Frametime plot");
dataSetMap = new HashMap<String,ImGuiLinePlotDataset>();
initFramerateGraphSeries("totalframerate");
initFramerateGraphSeries("serversim");
initFramerateGraphSeries("clientsim");
initFramerateGraphSeries("render");
imGuiWindow.addElement(plot);
RenderingEngine.addImGuiWindow(imGuiWindow);
}
/**
* Inits a series for the framerate graph
* @param seriesName The name of the series
*/
public static void initFramerateGraphSeries(String seriesName){
ImGuiLinePlotDataset dataSet = new ImGuiLinePlotDataset(seriesName, 50);
dataSetMap.put(seriesName,dataSet);
for(int x = 0; x < 50; x++){
dataSet.addPoint(x, 0);
}
plot.addDataset(dataSet);
}
/**
* Adds a datapoint to the framerate graph
* @param seriesName The name of the series to add a datapoint for
* @param y the y coord
*/
public static void addFramerateDatapoint(String seriesName, double y){
if(dataSetMap != null && dataSetMap.containsKey(seriesName)){
dataSetMap.get(seriesName).addPoint(y);
}
}
}