diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
index 97e9d1d..3f4e356 100644
--- a/config/checkstyle/checkstyle.xml
+++ b/config/checkstyle/checkstyle.xml
@@ -121,7 +121,7 @@
-
+
diff --git a/imgui-binding/src/main/java/imgui/ImDrawData.java b/imgui-binding/src/main/java/imgui/ImDrawData.java
index 3b3055b..6011af4 100644
--- a/imgui-binding/src/main/java/imgui/ImDrawData.java
+++ b/imgui-binding/src/main/java/imgui/ImDrawData.java
@@ -1,173 +1,234 @@
package imgui;
-import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
- * All draw data to render a Dear ImGui frame.
+ * All draw data to render Dear ImGui frame
+ * (NB: the style and the naming convention here is a little inconsistent, we currently preserve them for backward compatibility purpose,
+ * as this is one of the oldest structure exposed by the library! Basically, ImDrawList == CmdList)
*
- * BINDING NOTICE: DO NOT TRY TO MODIFY FIELDS OF THIS CLASS MANUALLY! You should only access their values after {@link ImGui#render()} call.
+ * BINDING NOTICE: Since it's impossible to do a 1:1 mapping with JNI, current class provides "getCmdList*()" methods.
+ * Those are used to get the data needed to do a rendering.
*/
-public final class ImDrawData {
- public static final int V_BUFFER_SIZE = (4 + 1) * 4;
- public static final int I_BUFFER_SIZE = 2;
- public static final int CMD_BUFFER_SIZE = (1 + 4 + 1) * 4;
+public final class ImDrawData implements ImDestroyable {
+ public static final int SIZEOF_IM_DRAW_IDX = 2;
+ public static final int SIZEOF_IM_DRAW_VERT = (4 + 1) * 4;
- public ByteBuffer vByteBuffer;
- public ByteBuffer iByteBuffer;
- public ByteBuffer cmdByteBuffer;
+ private static final int COUNT_FACTOR = 5_000;
- public int totalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size
- public int totalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size
- public int cmdListsCount; // Number of ImDrawList* to render
+ final long ptr;
- // Upper-left position of the viewport to render (== upper-left of the orthogonal projection matrix to use)
- //
- public float displayPosX;
- public float displayPosY;
+ private ByteBuffer idxBuffer = ByteBuffer.allocateDirect(SIZEOF_IM_DRAW_IDX * COUNT_FACTOR).order(ByteOrder.nativeOrder());
+ private ByteBuffer vtxBuffer = ByteBuffer.allocateDirect(SIZEOF_IM_DRAW_VERT * COUNT_FACTOR).order(ByteOrder.nativeOrder());
- // Size of the viewport to render (== io.DisplaySize for the main viewport)
- // (DisplayPos+DisplaySize == lower-right of the orthogonal projection matrix to use)
- //
- public float displaySizeX;
- public float displaySizeY;
+ /**
+ * This class will create a native structure.
+ * Call {@link #destroy()} method to manually free used memory.
+ */
+ public ImDrawData() {
+ ImGui.touch();
+ ptr = nCreate();
+ }
- // Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display.
- //
- public float framebufferScaleX;
- public float framebufferScaleY;
+ ImDrawData(final long ptr) {
+ this.ptr = ptr;
+ }
- ImDrawData(final int maxVertices, final int maxIndices, final int maxCmd) {
- vByteBuffer = ByteBuffer.allocateDirect(maxVertices * V_BUFFER_SIZE).order(ByteOrder.nativeOrder());
- iByteBuffer = ByteBuffer.allocateDirect(maxIndices * I_BUFFER_SIZE).order(ByteOrder.nativeOrder());
- cmdByteBuffer = ByteBuffer.allocateDirect(maxCmd * CMD_BUFFER_SIZE).order(ByteOrder.nativeOrder());
+ @Override
+ public void destroy() {
+ nDestroy(ptr);
}
/*JNI
#include
#include
+ #include "jni_common.h"
- jfieldID totalVtxCountID;
- jfieldID totalIdxCountID;
- jfieldID CmdListsCountID;
- jfieldID displayPosXID;
- jfieldID displayPosYID;
- jfieldID displaySizeXID;
- jfieldID displaySizeYID;
- jfieldID framebufferScaleXID;
- jfieldID framebufferScaleYID;
+ jfieldID imDrawDataPtrID;
+
+ #define IM_DRAW_DATA ((ImDrawData*)env->GetLongField(object, imDrawDataPtrID))
*/
static native void nInit(); /*
- jclass jDrawDataClass = env->FindClass("imgui/ImDrawData");
-
- totalVtxCountID = env->GetFieldID(jDrawDataClass, "totalVtxCount", "I");
- totalIdxCountID = env->GetFieldID(jDrawDataClass, "totalIdxCount", "I");
- CmdListsCountID = env->GetFieldID(jDrawDataClass, "cmdListsCount", "I");
- displayPosXID = env->GetFieldID(jDrawDataClass, "displayPosX", "F");
- displayPosYID = env->GetFieldID(jDrawDataClass, "displayPosY", "F");
- displaySizeXID = env->GetFieldID(jDrawDataClass, "displaySizeX", "F");
- displaySizeYID = env->GetFieldID(jDrawDataClass, "displaySizeY", "F");
- framebufferScaleXID = env->GetFieldID(jDrawDataClass, "framebufferScaleX", "F");
- framebufferScaleYID = env->GetFieldID(jDrawDataClass, "framebufferScaleY", "F");
+ jclass jImDrawDataClass = env->FindClass("imgui/ImDrawData");
+ imDrawDataPtrID = env->GetFieldID(jImDrawDataClass, "ptr", "J");
*/
- native void nFillDrawData(Buffer indexBuffer, Buffer vertexBuffer, Buffer cmdBuffer); /*
- ImDrawData* drawData = ImGui::GetDrawData();
+ private native long nCreate(); /*
+ ImDrawData* imDrawData = new ImDrawData();
+ return (intptr_t)imDrawData;
+ */
- if (drawData == NULL) {
- return;
+ private native void nDestroy(long ptr); /*
+ delete (ImDrawData*)ptr;
+ */
+
+ ///////// Start of Render Methods | Binding
+
+ /**
+ * Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback.
+ */
+ public native int getCmdListCmdBufferSize(int cmdListIdx); /*
+ return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer.Size;
+ */
+
+ /**
+ * Number of indices (multiple of 3) to be rendered as triangles.
+ * Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[].
+ */
+ public native int getCmdListCmdBufferElemCount(int cmdListIdx, int cmdBufferIdx); /*
+ return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].ElemCount;
+ */
+
+ /**
+ * Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates
+ */
+ public native void getCmdListCmdBufferClipRect(int cmdListIdx, int cmdBufferIdx, ImVec4 dstImVec4); /*
+ Jni::ImVec4Cpy(env, &IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].ClipRect, dstImVec4);
+ */
+
+ /**
+ * User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions.
+ * Ignore if never using images or multiple fonts atlas.
+ */
+ public native int getCmdListCmdBufferTextureId(int cmdListIdx, int cmdBufferIdx); /*
+ return (intptr_t)IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].TextureId;
+ */
+
+ /**
+ * Start offset in vertex buffer. Pre-1.71 or without ImGuiBackendFlags_RendererHasVtxOffset: always 0.
+ * With ImGuiBackendFlags_RendererHasVtxOffset: may be >0 to support meshes larger than 64K vertices with 16-bit indices.
+ */
+ public native int getCmdListCmdBufferVtxOffset(int cmdListIdx, int cmdBufferIdx); /*
+ return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].VtxOffset;
+ */
+
+ /**
+ * Start offset in index buffer. Always equal to sum of ElemCount drawn so far.
+ */
+ public native int getCmdListCmdBufferIdxOffset(int cmdListIdx, int cmdBufferIdx); /*
+ return IM_DRAW_DATA->CmdLists[cmdListIdx]->CmdBuffer[cmdBufferIdx].IdxOffset;
+ */
+
+ /**
+ * Index buffer. Each command consume ImDrawCmd::ElemCount of those
+ */
+ public native int getCmdListIdxBufferSize(int cmdListIdx); /*
+ return IM_DRAW_DATA->CmdLists[cmdListIdx]->IdxBuffer.Size;
+ */
+
+ public ByteBuffer getCmdListIdxBufferData(final int cmdListIdx) {
+ final int idxBufferCapacity = getCmdListIdxBufferSize(cmdListIdx) * SIZEOF_IM_DRAW_IDX;
+ if (idxBuffer.capacity() < idxBufferCapacity) {
+ idxBuffer = ByteBuffer.allocateDirect(idxBufferCapacity + COUNT_FACTOR).order(ByteOrder.nativeOrder());
}
- int cmdListsCount = drawData->CmdListsCount;
+ nGetCmdListIdxBufferData(cmdListIdx, idxBuffer, idxBufferCapacity);
- // Set values
- env->SetIntField(object, totalVtxCountID, drawData->TotalVtxCount);
- env->SetIntField(object, totalIdxCountID, drawData->TotalIdxCount);
- env->SetIntField(object, CmdListsCountID, cmdListsCount);
+ idxBuffer.position(0);
+ idxBuffer.limit(idxBufferCapacity);
- env->SetFloatField(object, displayPosXID, drawData->DisplayPos.x);
- env->SetFloatField(object, displayPosYID, drawData->DisplayPos.y);
+ return idxBuffer;
+ }
- env->SetFloatField(object, displaySizeXID, drawData->DisplaySize.x);
- env->SetFloatField(object, displaySizeYID, drawData->DisplaySize.y);
+ private native void nGetCmdListIdxBufferData(int cmdListIdx, ByteBuffer idxBuffer, int idxBufferCapacity); /*
+ memcpy(idxBuffer, IM_DRAW_DATA->CmdLists[cmdListIdx]->IdxBuffer.Data, idxBufferCapacity);
+ */
- env->SetFloatField(object, framebufferScaleXID, drawData->FramebufferScale.x);
- env->SetFloatField(object, framebufferScaleYID, drawData->FramebufferScale.y);
+ /**
+ * Vertex buffer.
+ */
+ public native int getCmdListVtxBufferSize(int cmdListIdx); /*
+ return IM_DRAW_DATA->CmdLists[cmdListIdx]->VtxBuffer.Size;
+ */
- ImDrawList** drawLists = drawData->CmdLists;
-
- int verticesOffset = 0;
- int indicesOffset = 0;
- int cmdOffset = 0;
-
- for(int i = 0; i < cmdListsCount; i++) {
- ImDrawList& drawList = *drawLists[i];
- ImVector& imDrawCmdList = drawList.CmdBuffer;
- ImVector& idxBuffer = drawList.IdxBuffer;
- ImVector& vtxBuffer = drawList.VtxBuffer;
-
- float* vertexArrayDest = (float*)vertexBuffer;
- short* indexArrayDest = (short*)indexBuffer;
-
- int colorSize = 1;
- int verticesItemSize = (4 + colorSize);
-
- vertexArrayDest[verticesOffset++] = vtxBuffer.Size;
-
- // copy vertices to Destination buffer
- for(int j = 0; j < vtxBuffer.Size; j++) {
- ImDrawVert v = vtxBuffer[j];
- float posX = v.pos.x;
- float posY = v.pos.y;
- float uvX = v.uv.x;
- float uvY = v.uv.y;
-
- int byteIndex = (j * verticesItemSize) + verticesOffset;
-
- float color = 0;
- memcpy(&color, &v.col, 4); // move unsigned int color to float
-
- vertexArrayDest[byteIndex + 0] = posX;
- vertexArrayDest[byteIndex + 1] = posY;
- vertexArrayDest[byteIndex + 2] = uvX;
- vertexArrayDest[byteIndex + 3] = uvY;
- vertexArrayDest[byteIndex + 4] = color;
- }
- verticesOffset += vtxBuffer.Size * verticesItemSize;
-
- // copy index to destination buffer
- indexArrayDest[indicesOffset++] = idxBuffer.Size;
-
- for(int j = 0; j < idxBuffer.Size; j++) {
- indexArrayDest[j + indicesOffset] = idxBuffer[j];
- }
-
- indicesOffset += idxBuffer.Size;
-
- float* cmdArrayDest = (float*)cmdBuffer;
-
- cmdArrayDest[cmdOffset++] = imDrawCmdList.Size;
- int bytesOffset = 0;
- int imDrawCmdSize = 1 + 4 + 1;
-
- for (int cmd_i = 0; cmd_i < imDrawCmdList.Size; cmd_i++) {
- const ImDrawCmd* pcmd = &imDrawCmdList[cmd_i];
-
- float textureID = (float)(intptr_t)pcmd->TextureId;
- float tempArray [6] = {
- (float)pcmd->ElemCount,
- pcmd->ClipRect.x, pcmd->ClipRect.y,
- pcmd->ClipRect.z, pcmd->ClipRect.w,
- textureID
- };
-
- memcpy((cmdArrayDest + (cmd_i * imDrawCmdSize) + cmdOffset), tempArray, imDrawCmdSize * 4);
- bytesOffset = bytesOffset + imDrawCmdSize;
- }
-
- cmdOffset += imDrawCmdList.Size * imDrawCmdSize;
+ public ByteBuffer getCmdListVtxBufferData(final int cmdListIdx) {
+ final int vtxBufferCapacity = getCmdListVtxBufferSize(cmdListIdx) * SIZEOF_IM_DRAW_VERT;
+ if (vtxBuffer.capacity() < vtxBufferCapacity) {
+ vtxBuffer = ByteBuffer.allocateDirect(vtxBufferCapacity + COUNT_FACTOR).order(ByteOrder.nativeOrder());
}
+
+ nGetCmdListVtxBufferData(cmdListIdx, vtxBuffer, vtxBufferCapacity);
+
+ vtxBuffer.position(0);
+ vtxBuffer.limit(vtxBufferCapacity);
+
+ return vtxBuffer;
+ }
+
+ private native void nGetCmdListVtxBufferData(int cmdListIdx, ByteBuffer vtxBuffer, int vtxBufferCapacity); /*
+ memcpy(vtxBuffer, IM_DRAW_DATA->CmdLists[cmdListIdx]->VtxBuffer.Data, vtxBufferCapacity);
+ */
+
+ ///////// End of Render Methods
+
+ /**
+ * Only valid after Render() is called and before the next NewFrame() is called.
+ */
+ public native boolean getValid(); /*
+ return IM_DRAW_DATA->Valid;
+ */
+
+ /**
+ * Number of ImDrawList* to render
+ */
+ public native int getCmdListsCount(); /*
+ return IM_DRAW_DATA->CmdListsCount;
+ */
+
+ /**
+ * For convenience, sum of all ImDrawList's IdxBuffer.Size
+ */
+ public native int getTotalIdxCount(); /*
+ return IM_DRAW_DATA->TotalIdxCount;
+ */
+
+ /**
+ * For convenience, sum of all ImDrawList's VtxBuffer.Size
+ */
+ public native int getTotalVtxCount(); /*
+ return IM_DRAW_DATA->TotalVtxCount;
+ */
+
+ /**
+ * Upper-left position of the viewport to render (== upper-left of the orthogonal projection matrix to use)
+ */
+ public native void getDisplayPos(ImVec2 dstImVec2); /*
+ Jni::ImVec2Cpy(env, &IM_DRAW_DATA->DisplayPos, dstImVec2);
+ */
+
+ /**
+ * Size of the viewport to render (== io.DisplaySize for the main viewport)
+ * (DisplayPos + DisplaySize == lower-right of the orthogonal projection matrix to use)
+ */
+ public native void getDisplaySize(ImVec2 dstImVec2); /*
+ Jni::ImVec2Cpy(env, &IM_DRAW_DATA->DisplaySize, dstImVec2);
+ */
+
+ /**
+ * Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display.
+ */
+ public native void getFramebufferScale(ImVec2 dstImVec2); /*
+ Jni::ImVec2Cpy(env, &IM_DRAW_DATA->FramebufferScale, dstImVec2);
+ */
+
+ // Functions
+
+ /**
+ * Helper to convert all buffers from indexed to non-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources.
+ * Always prefer indexed rendering!
+ */
+ public native void deIndexAllBuffers(); /*
+ IM_DRAW_DATA->DeIndexAllBuffers();
+ */
+
+ /**
+ * Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than Dear ImGui expects,
+ * or if there is a difference between your window resolution and framebuffer resolution.
+ */
+ public native void scaleClipRects(float fbScaleX, float fbScaleY); /*
+ const ImVec2 fbScale = ImVec2(fbScaleX, fbScaleY);
+ IM_DRAW_DATA->ScaleClipRects(fbScale);
*/
}
diff --git a/imgui-binding/src/main/java/imgui/ImDrawList.java b/imgui-binding/src/main/java/imgui/ImDrawList.java
index ee4ce0d..7879596 100644
--- a/imgui-binding/src/main/java/imgui/ImDrawList.java
+++ b/imgui-binding/src/main/java/imgui/ImDrawList.java
@@ -55,11 +55,16 @@ public final class ImDrawList {
drawListTypeID = env->GetFieldID(jImDrawListClass, "drawListType", "I");
*/
- // Flags, you may poke into these to adjust anti-aliasing settings per-primitive.
+ /**
+ * Flags, you may poke into these to adjust anti-aliasing settings per-primitive.
+ */
public native int getImDrawListFlags(); /*
return IM_DRAW_LIST->Flags;
*/
+ /**
+ * Flags, you may poke into these to adjust anti-aliasing settings per-primitive.
+ */
public native void setImDrawListFlags(int imDrawListFlags); /*
IM_DRAW_LIST->Flags = imDrawListFlags;
*/
diff --git a/imgui-binding/src/main/java/imgui/ImGui.java b/imgui-binding/src/main/java/imgui/ImGui.java
index eb94d1b..f198a06 100644
--- a/imgui-binding/src/main/java/imgui/ImGui.java
+++ b/imgui-binding/src/main/java/imgui/ImGui.java
@@ -5,7 +5,6 @@ import imgui.enums.ImGuiInputTextFlags;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
-import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -17,13 +16,13 @@ public final class ImGui {
private static final String LIB_NAME_DEFAULT = System.getProperty("os.arch").contains("64") ? "imgui-java64" : "imgui-java";
private static final String LIB_TMP_DIR_PREFIX = "imgui-java-bin_" + System.getProperty("user.name", "user");
- private static final ImDrawData DRAW_DATA;
private static final ImGuiIO IMGUI_IO;
private static final ImDrawList IM_DRAW_LIST_WINDOW = new ImDrawList(ImDrawList.TYPE_WINDOW);
private static final ImDrawList IM_DRAW_LIST_BACKGROUND = new ImDrawList(ImDrawList.TYPE_BACKGROUND);
private static final ImDrawList IM_DRAW_LIST_FOREGROUND = new ImDrawList(ImDrawList.TYPE_FOREGROUND);
+ private static ImDrawData drawData;
private static ImFont font;
private static ImGuiStyle style;
@@ -42,7 +41,6 @@ public final class ImGui {
System.loadLibrary(libName);
}
- DRAW_DATA = new ImDrawData(100_000, 100_000, 1000);
IMGUI_IO = new ImGuiIO();
nInitJni();
@@ -188,16 +186,16 @@ public final class ImGui {
* Valid after Render() and until the next call to NewFrame(). this is what you have to render.
*/
public static ImDrawData getDrawData() {
- final ByteBuffer cmdByteBuffer = DRAW_DATA.cmdByteBuffer;
- final ByteBuffer vByteBuffer = DRAW_DATA.vByteBuffer;
- final ByteBuffer iByteBuffer = DRAW_DATA.iByteBuffer;
- vByteBuffer.position(0);
- iByteBuffer.position(0);
- cmdByteBuffer.position(0);
- DRAW_DATA.nFillDrawData(iByteBuffer, vByteBuffer, cmdByteBuffer);
- return DRAW_DATA;
+ if (drawData == null) {
+ drawData = new ImDrawData(nGetDrawData());
+ }
+ return drawData;
}
+ private static native long nGetDrawData(); /*
+ return (intptr_t)ImGui::GetDrawData();
+ */
+
// Demo, Debug, Information
/**
diff --git a/imgui-lwjgl3/src/main/java/imgui/gl3/ImGuiImplGl3.java b/imgui-lwjgl3/src/main/java/imgui/gl3/ImGuiImplGl3.java
index eeed6f1..78b8b5a 100644
--- a/imgui-lwjgl3/src/main/java/imgui/gl3/ImGuiImplGl3.java
+++ b/imgui-lwjgl3/src/main/java/imgui/gl3/ImGuiImplGl3.java
@@ -4,6 +4,8 @@ import imgui.ImDrawData;
import imgui.ImFontAtlas;
import imgui.ImGui;
import imgui.ImInt;
+import imgui.ImVec2;
+import imgui.ImVec4;
import java.io.BufferedReader;
import java.io.IOException;
@@ -13,7 +15,7 @@ import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import java.util.Objects;
-import static org.lwjgl.opengl.GL30.*;
+import static org.lwjgl.opengl.GL32.*;
/**
* This class mostly a straightforward port of the
@@ -27,10 +29,14 @@ import static org.lwjgl.opengl.GL30.*;
*/
@SuppressWarnings("MagicNumber")
public final class ImGuiImplGl3 {
- private int vBufferHandle = 0;
- private int iBufferHandle = 0;
+ private int vboHandle = 0;
+ private int elementsHandle = 0;
- private boolean isFontInitialized = false;
+ // Used to store tmp renderer data
+ private final ImVec2 displaySize = new ImVec2();
+ private final ImVec2 framebufferScale = new ImVec2();
+ private final ImVec2 displayPos = new ImVec2();
+ private final ImVec4 clipRect = new ImVec4();
// Shader stuff
private int programId = 0;
@@ -67,6 +73,8 @@ public final class ImGuiImplGl3 {
public void init() {
prepareShader();
prepareFont();
+ vboHandle = glGenBuffers();
+ elementsHandle = glGenBuffers();
}
/**
@@ -75,86 +83,52 @@ public final class ImGuiImplGl3 {
* @param drawData data used to draw ImGui interface to your current OpenGL context
*/
public void render(final ImDrawData drawData) {
- if (drawData.cmdListsCount <= 0) {
+ if (drawData.getCmdListsCount() <= 0) {
return;
}
+ drawData.getDisplaySize(displaySize);
+ drawData.getFramebufferScale(framebufferScale);
+
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
- final int fbWidth = (int) (drawData.displaySizeX * drawData.framebufferScaleX);
- final int fbHeight = (int) (drawData.displaySizeY * drawData.framebufferScaleY);
+ final int fbWidth = (int) (displaySize.x * framebufferScale.x);
+ final int fbHeight = (int) (displaySize.y * framebufferScale.y);
if (fbWidth <= 0 || fbHeight <= 0) {
return;
}
- if (!isFontInitialized) {
- isFontInitialized = true;
- vBufferHandle = glGenBuffers();
- iBufferHandle = glGenBuffers();
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iBufferHandle);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, drawData.iByteBuffer.capacity(), GL_STATIC_DRAW);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
+ drawData.getDisplayPos(displayPos);
backupGlState();
- bind(drawData);
+ bind();
- int verticesOffset = 0;
- int indexOffset = 0;
+ // Render command lists
+ for (int cmdListIdx = 0; cmdListIdx < drawData.getCmdListsCount(); cmdListIdx++) {
+ // Upload vertex/index buffers
+ glBufferData(GL_ARRAY_BUFFER, drawData.getCmdListVtxBufferData(cmdListIdx), GL_STREAM_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, drawData.getCmdListIdxBufferData(cmdListIdx), GL_STREAM_DRAW);
- for (int i = 0; i < drawData.cmdListsCount; i++) {
- drawData.vByteBuffer.limit(verticesOffset + 4);
- final int verticesSize = (int) drawData.vByteBuffer.getFloat(verticesOffset);
+ for (int cmdBufferIdx = 0; cmdBufferIdx < drawData.getCmdListCmdBufferSize(cmdListIdx); cmdBufferIdx++) {
+ drawData.getCmdListCmdBufferClipRect(cmdListIdx, cmdBufferIdx, clipRect);
- drawData.iByteBuffer.limit(indexOffset + 2);
- final short indexSize = drawData.iByteBuffer.getShort(indexOffset);
- final int cmdSize = (int) drawData.cmdByteBuffer.getFloat();
-
- final int verticesStartOffset = verticesOffset + 4;
- final int indexStartOffset = indexOffset + 2;
-
- drawData.vByteBuffer.position(verticesStartOffset);
- drawData.iByteBuffer.position(indexStartOffset);
-
- final int newVlimit = verticesStartOffset + verticesSize * ImDrawData.V_BUFFER_SIZE;
- final int newIlimit = indexStartOffset + indexSize * ImDrawData.I_BUFFER_SIZE;
-
- drawData.vByteBuffer.limit(newVlimit);
- drawData.iByteBuffer.limit(newIlimit);
-
- glBufferData(GL_ARRAY_BUFFER, drawData.vByteBuffer, GL_STATIC_DRAW);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, drawData.iByteBuffer, GL_STATIC_DRAW);
-
- verticesOffset += ((verticesSize) * ImDrawData.V_BUFFER_SIZE) + 4;
- indexOffset += ((indexSize) * ImDrawData.I_BUFFER_SIZE) + 2;
-
- final float clipOffX = drawData.displayPosX; // (0,0) unless using multi-viewports
- final float clipOffY = drawData.displayPosY;
- final float clipScaleX = drawData.framebufferScaleX; // (1,1) unless using retina display which are often (2,2)
- final float clipScaleY = drawData.framebufferScaleY;
-
- int idxBufferOffset = 0;
-
- for (int j = 0; j < cmdSize; j++) {
- final int elemCount = (int) drawData.cmdByteBuffer.getFloat();
- float clipRectX = drawData.cmdByteBuffer.getFloat();
- float clipRectY = drawData.cmdByteBuffer.getFloat();
- float clipRectZ = drawData.cmdByteBuffer.getFloat();
- float clipRectW = drawData.cmdByteBuffer.getFloat();
- final int textureID = (int) drawData.cmdByteBuffer.getFloat();
-
- clipRectX = (clipRectX - clipOffX) * clipScaleX;
- clipRectY = (clipRectY - clipOffY) * clipScaleY;
- clipRectZ = (clipRectZ - clipOffX) * clipScaleX;
- clipRectW = (clipRectW - clipOffY) * clipScaleY;
+ final float clipRectX = (clipRect.x - displayPos.x) * framebufferScale.x;
+ final float clipRectY = (clipRect.y - displayPos.y) * framebufferScale.y;
+ final float clipRectZ = (clipRect.z - displayPos.x) * framebufferScale.x;
+ final float clipRectW = (clipRect.w - displayPos.y) * framebufferScale.y;
if (clipRectX < fbWidth && clipRectY < fbHeight && clipRectZ >= 0.0f && clipRectW >= 0.0f) {
+ // Apply scissor/clipping rectangle
glScissor((int) clipRectX, (int) (fbHeight - clipRectW), (int) (clipRectZ - clipRectX), (int) (clipRectW - clipRectY));
- glBindTexture(GL_TEXTURE_2D, textureID);
- glDrawElements(GL_TRIANGLES, elemCount, GL_UNSIGNED_SHORT, idxBufferOffset);
- }
- idxBufferOffset += elemCount * 2;
+ // Bind texture, Draw
+ final int textureId = drawData.getCmdListCmdBufferTextureId(cmdListIdx, cmdBufferIdx);
+ final int elemCount = drawData.getCmdListCmdBufferElemCount(cmdListIdx, cmdBufferIdx);
+ final int idxBufferOffset = drawData.getCmdListCmdBufferIdxOffset(cmdListIdx, cmdBufferIdx);
+
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ glDrawElements(GL_TRIANGLES, elemCount, GL_UNSIGNED_SHORT, idxBufferOffset * ImDrawData.SIZEOF_IM_DRAW_IDX);
+ }
}
}
@@ -168,8 +142,8 @@ public final class ImGuiImplGl3 {
public void dispose() {
glDeleteTextures(gFontTexture);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glDeleteBuffers(iBufferHandle);
- glDeleteBuffers(vBufferHandle);
+ glDeleteBuffers(elementsHandle);
+ glDeleteBuffers(vboHandle);
glDetachShader(programId, vertexShaderId);
glDetachShader(programId, fragmentShaderId);
glDeleteProgram(programId);
@@ -214,10 +188,7 @@ public final class ImGuiImplGl3 {
glGetIntegerv(GL_ACTIVE_TEXTURE, lastActiveTexture);
glGetIntegerv(GL_CURRENT_PROGRAM, lastProgram);
glGetIntegerv(GL_TEXTURE_BINDING_2D, lastTexture);
- // int[] last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler); // do it by yourself if needed
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, lastArrayBuffer);
- // int[] last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array_object); // do it by yourself if needed
- // int[] last_polygon_mode; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); // do it by yourself if needed
glGetIntegerv(GL_VIEWPORT, lastViewport);
glGetIntegerv(GL_SCISSOR_BOX, lastScissorBox);
glGetIntegerv(GL_BLEND_SRC_RGB, lastBlendSrcRgb);
@@ -249,8 +220,8 @@ public final class ImGuiImplGl3 {
glScissor(lastScissorBox[0], lastScissorBox[1], lastScissorBox[2], lastScissorBox[3]);
}
- private void bind(final ImDrawData drawData) {
- glViewport(0, 0, (int) drawData.displaySizeX, (int) drawData.displaySizeY);
+ private void bind() {
+ glViewport(0, 0, (int) displaySize.x, (int) displaySize.y);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
@@ -259,10 +230,10 @@ public final class ImGuiImplGl3 {
glDisable(GL_DEPTH_TEST);
glEnable(GL_SCISSOR_TEST);
- final float left = drawData.displayPosX;
- final float right = drawData.displayPosX + drawData.displaySizeX;
- final float top = drawData.displayPosY;
- final float bottom = drawData.displayPosY + drawData.displaySizeY;
+ final float left = displayPos.x;
+ final float right = displayPos.x + displaySize.x;
+ final float top = displayPos.y;
+ final float bottom = displayPos.y + displaySize.y;
// Orthographic matrix projection
projMatrix[0] = 2.0f / (right - left);
@@ -272,28 +243,26 @@ public final class ImGuiImplGl3 {
projMatrix[13] = (top + bottom) / (bottom - top);
projMatrix[15] = 1.0f;
- // Bind vertices
- glBindBuffer(GL_ARRAY_BUFFER, vBufferHandle);
+ // Bind shader
+ glUseProgram(programId);
+ glUniform1i(glGetUniformLocation(programId, "Texture"), 0);
+ glUniformMatrix4fv(glGetUniformLocation(programId, "ProjMtx"), false, projMatrix);
+
+ // Bind vertex/index buffers and setup attributes for ImDrawVert
+ glBindBuffer(GL_ARRAY_BUFFER, vboHandle);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementsHandle);
int location = glGetAttribLocation(programId, "Position");
glEnableVertexAttribArray(location);
- glVertexAttribPointer(location, 2, GL_FLOAT, false, 20, 0);
+ glVertexAttribPointer(location, 2, GL_FLOAT, false, ImDrawData.SIZEOF_IM_DRAW_VERT, 0);
location = glGetAttribLocation(programId, "UV");
glEnableVertexAttribArray(location);
- glVertexAttribPointer(location, 2, GL_FLOAT, false, 20, 8);
+ glVertexAttribPointer(location, 2, GL_FLOAT, false, ImDrawData.SIZEOF_IM_DRAW_VERT, 8);
location = glGetAttribLocation(programId, "Color");
glEnableVertexAttribArray(location);
- glVertexAttribPointer(location, 4, GL_UNSIGNED_BYTE, true, 20, 16);
-
- //Bind index
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iBufferHandle);
-
- // Bind shader
- glUseProgram(programId);
- glUniformMatrix4fv(glGetUniformLocation(programId, "ProjMtx"), false, projMatrix);
- glUniform1i(glGetUniformLocation(programId, "Texture"), 0);
+ glVertexAttribPointer(location, 4, GL_UNSIGNED_BYTE, true, ImDrawData.SIZEOF_IM_DRAW_VERT, 16);
}
private void unbind() {
diff --git a/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java b/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java
index d28536f..7452a55 100644
--- a/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java
+++ b/imgui-lwjgl3/src/test/java/ImGuiGlfwExample.java
@@ -34,7 +34,7 @@ import java.util.Objects;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
-import static org.lwjgl.opengl.GL30.*;
+import static org.lwjgl.opengl.GL32.*;
import static org.lwjgl.system.MemoryStack.stackPush;
import static org.lwjgl.system.MemoryUtil.NULL;