Reactor ImGuiImplGl3
- Almost a 1:1 port of original C++ code - Fix for the OpenGL profiles >= 3.2
This commit is contained in:
1 parent
283e78070c
commit
41d7f4e04a
4 files changed
+309
-149
No files matched your search
@@ -15,12 +15,12 @@ public final class ImDrawData implements ImDestroyable {
|
|||||||
public static final int SIZEOF_IM_DRAW_IDX = 2;
|
public static final int SIZEOF_IM_DRAW_IDX = 2;
|
||||||
public static final int SIZEOF_IM_DRAW_VERT = (4 + 1) * 4;
|
public static final int SIZEOF_IM_DRAW_VERT = (4 + 1) * 4;
|
||||||
|
|
||||||
private static final int COUNT_FACTOR = 5_000;
|
private static final int FACTOR = 5_000;
|
||||||
|
|
||||||
final long ptr;
|
final long ptr;
|
||||||
|
|
||||||
private ByteBuffer idxBuffer = ByteBuffer.allocateDirect(SIZEOF_IM_DRAW_IDX * COUNT_FACTOR).order(ByteOrder.nativeOrder());
|
private ByteBuffer idxBuffer = ByteBuffer.allocateDirect(SIZEOF_IM_DRAW_IDX * FACTOR).order(ByteOrder.nativeOrder());
|
||||||
private ByteBuffer vtxBuffer = ByteBuffer.allocateDirect(SIZEOF_IM_DRAW_VERT * COUNT_FACTOR).order(ByteOrder.nativeOrder());
|
private ByteBuffer vtxBuffer = ByteBuffer.allocateDirect(SIZEOF_IM_DRAW_VERT * FACTOR).order(ByteOrder.nativeOrder());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class will create a native structure.
|
* This class will create a native structure.
|
||||||
@@ -121,7 +121,7 @@ public final class ImDrawData implements ImDestroyable {
|
|||||||
public ByteBuffer getCmdListIdxBufferData(final int cmdListIdx) {
|
public ByteBuffer getCmdListIdxBufferData(final int cmdListIdx) {
|
||||||
final int idxBufferCapacity = getCmdListIdxBufferSize(cmdListIdx) * SIZEOF_IM_DRAW_IDX;
|
final int idxBufferCapacity = getCmdListIdxBufferSize(cmdListIdx) * SIZEOF_IM_DRAW_IDX;
|
||||||
if (idxBuffer.capacity() < idxBufferCapacity) {
|
if (idxBuffer.capacity() < idxBufferCapacity) {
|
||||||
idxBuffer = ByteBuffer.allocateDirect(idxBufferCapacity + COUNT_FACTOR).order(ByteOrder.nativeOrder());
|
idxBuffer = ByteBuffer.allocateDirect(idxBufferCapacity + FACTOR).order(ByteOrder.nativeOrder());
|
||||||
}
|
}
|
||||||
|
|
||||||
nGetCmdListIdxBufferData(cmdListIdx, idxBuffer, idxBufferCapacity);
|
nGetCmdListIdxBufferData(cmdListIdx, idxBuffer, idxBufferCapacity);
|
||||||
@@ -146,7 +146,7 @@ public final class ImDrawData implements ImDestroyable {
|
|||||||
public ByteBuffer getCmdListVtxBufferData(final int cmdListIdx) {
|
public ByteBuffer getCmdListVtxBufferData(final int cmdListIdx) {
|
||||||
final int vtxBufferCapacity = getCmdListVtxBufferSize(cmdListIdx) * SIZEOF_IM_DRAW_VERT;
|
final int vtxBufferCapacity = getCmdListVtxBufferSize(cmdListIdx) * SIZEOF_IM_DRAW_VERT;
|
||||||
if (vtxBuffer.capacity() < vtxBufferCapacity) {
|
if (vtxBuffer.capacity() < vtxBufferCapacity) {
|
||||||
vtxBuffer = ByteBuffer.allocateDirect(vtxBufferCapacity + COUNT_FACTOR).order(ByteOrder.nativeOrder());
|
vtxBuffer = ByteBuffer.allocateDirect(vtxBufferCapacity + FACTOR).order(ByteOrder.nativeOrder());
|
||||||
}
|
}
|
||||||
|
|
||||||
nGetCmdListVtxBufferData(cmdListIdx, vtxBuffer, vtxBufferCapacity);
|
nGetCmdListVtxBufferData(cmdListIdx, vtxBuffer, vtxBufferCapacity);
|
||||||
|
|||||||
@@ -3,57 +3,60 @@ package imgui.gl3;
|
|||||||
import imgui.ImDrawData;
|
import imgui.ImDrawData;
|
||||||
import imgui.ImFontAtlas;
|
import imgui.ImFontAtlas;
|
||||||
import imgui.ImGui;
|
import imgui.ImGui;
|
||||||
|
import imgui.ImGuiIO;
|
||||||
import imgui.ImInt;
|
import imgui.ImInt;
|
||||||
import imgui.ImVec2;
|
import imgui.ImVec2;
|
||||||
import imgui.ImVec4;
|
import imgui.ImVec4;
|
||||||
|
import imgui.enums.ImGuiBackendFlags;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.UncheckedIOException;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Objects;
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static org.lwjgl.opengl.GL32.*;
|
import static org.lwjgl.opengl.GL32.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class mostly a straightforward port of the
|
* This class is a straightforward port of the
|
||||||
* <a href="https://raw.githubusercontent.com/ocornut/imgui/v1.74/examples/imgui_impl_opengl3.cpp">imgui_impl_opengl3.cpp</a>
|
* <a href="https://raw.githubusercontent.com/ocornut/imgui/v1.76/examples/imgui_impl_opengl3.cpp">imgui_impl_opengl3.cpp</a>.
|
||||||
* adapted for Java and LWJGL realms.
|
|
||||||
* <p>
|
* <p>
|
||||||
* It do support a backup of the current GL state before rendering and restoring of its initial state after.
|
* It do support a backup and restoring of the GL state in the same way the original Dear ImGui code does.
|
||||||
* But some specific state variables may be missed (all which are hidden under '#ifdef' macros in the original 'imgui_impl_opengl3.cpp' file).
|
* Some of the very specific OpenGL variables may be ignored here,
|
||||||
|
* yet you can copy-paste this class in your codebase and modify the rendering routine in the way you'd like.
|
||||||
* <p>
|
* <p>
|
||||||
* This implementation uses shaders with 130 version of GLSL (OpenGL 3.0).
|
* This implementation has an ability to use a GLSL version provided during the initialization.
|
||||||
|
* Please read the documentation for the {@link #init(String)}.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("MagicNumber")
|
@SuppressWarnings("MagicNumber")
|
||||||
public final class ImGuiImplGl3 {
|
public final class ImGuiImplGl3 {
|
||||||
private int vboHandle = 0;
|
// OpenGL Data
|
||||||
private int elementsHandle = 0;
|
private int glVersion = 0;
|
||||||
|
private String glslVersion = "";
|
||||||
|
private int gVboHandle = 0;
|
||||||
|
private int gElementsHandle = 0;
|
||||||
|
private int gShaderHandle = 0;
|
||||||
|
private int gFragHandle = 0;
|
||||||
|
private int gVertHandle = 0;
|
||||||
|
private int gAttribLocationTex = 0;
|
||||||
|
private int gAttribLocationProjMtx = 0;
|
||||||
|
private int gAttribLocationVtxPos = 0;
|
||||||
|
private int gAttribLocationVtxUV = 0;
|
||||||
|
private int gAttribLocationVtxColor = 0;
|
||||||
|
private int gFontTexture = 0;
|
||||||
|
private int gVertexArrayObjectHandle = 0;
|
||||||
|
|
||||||
// Used to store tmp renderer data
|
// Used to store tmp renderer data
|
||||||
private final ImVec2 displaySize = new ImVec2();
|
private final ImVec2 displaySize = new ImVec2();
|
||||||
private final ImVec2 framebufferScale = new ImVec2();
|
private final ImVec2 framebufferScale = new ImVec2();
|
||||||
private final ImVec2 displayPos = new ImVec2();
|
private final ImVec2 displayPos = new ImVec2();
|
||||||
private final ImVec4 clipRect = new ImVec4();
|
private final ImVec4 clipRect = new ImVec4();
|
||||||
|
private final float[] orthoProjMatrix = new float[4 * 4];
|
||||||
|
|
||||||
// Shader stuff
|
// Variables used to backup GL state before and after the rendering of Dear ImGui
|
||||||
private int programId = 0;
|
|
||||||
private int fragmentShaderId = 0;
|
|
||||||
private int vertexShaderId = 0;
|
|
||||||
|
|
||||||
// Texture used by fonts
|
|
||||||
private int gFontTexture = 0;
|
|
||||||
|
|
||||||
// Projection matrix for ImGui
|
|
||||||
private final float[] projMatrix = new float[4 * 4];
|
|
||||||
|
|
||||||
// Variables used to backup GL state before and after rendering of ImGui
|
|
||||||
private final int[] lastActiveTexture = new int[1];
|
private final int[] lastActiveTexture = new int[1];
|
||||||
private final int[] lastProgram = new int[1];
|
private final int[] lastProgram = new int[1];
|
||||||
private final int[] lastTexture = new int[1];
|
private final int[] lastTexture = new int[1];
|
||||||
private final int[] lastArrayBuffer = new int[1];
|
private final int[] lastArrayBuffer = new int[1];
|
||||||
|
private final int[] lastVertexArrayObject = new int[1];
|
||||||
private final int[] lastViewport = new int[4];
|
private final int[] lastViewport = new int[4];
|
||||||
private final int[] lastScissorBox = new int[4];
|
private final int[] lastScissorBox = new int[4];
|
||||||
private final int[] lastBlendSrcRgb = new int[1];
|
private final int[] lastBlendSrcRgb = new int[1];
|
||||||
@@ -68,27 +71,65 @@ public final class ImGuiImplGl3 {
|
|||||||
private boolean lastEnableScissorTest = false;
|
private boolean lastEnableScissorTest = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method SHOULD be called before calling of {@link ImGuiImplGl3#render(ImDrawData)} method.
|
* Method to do an initialization of the {@link ImGuiImplGl3} state.
|
||||||
|
* It SHOULD be called before calling of the {@link ImGuiImplGl3#render(ImDrawData)} method.
|
||||||
|
* <p>
|
||||||
|
* Unlike in the {@link #init(String)} method, here the glslVersion argument is omitted.
|
||||||
|
* Thus a "#version 130" string will be used instead.
|
||||||
*/
|
*/
|
||||||
public void init() {
|
public void init() {
|
||||||
prepareShader();
|
init(null);
|
||||||
prepareFont();
|
|
||||||
vboHandle = glGenBuffers();
|
|
||||||
elementsHandle = glGenBuffers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method which renders {@link ImDrawData} from ImGui.
|
* Method to do an initialization of the {@link ImGuiImplGl3} state.
|
||||||
*
|
* It SHOULD be called before calling of the {@link ImGuiImplGl3#render(ImDrawData)} method.
|
||||||
* @param drawData data used to draw ImGui interface to your current OpenGL context
|
* <p>
|
||||||
|
* Method takes an argument, which should be a valid GLSL string with the version to use.
|
||||||
|
* <pre>
|
||||||
|
* ----------------------------------------
|
||||||
|
* OpenGL GLSL GLSL
|
||||||
|
* version version string
|
||||||
|
* ---------------------------------------
|
||||||
|
* 2.0 110 "#version 110"
|
||||||
|
* 2.1 120 "#version 120"
|
||||||
|
* 3.0 130 "#version 130"
|
||||||
|
* 3.1 140 "#version 140"
|
||||||
|
* 3.2 150 "#version 150"
|
||||||
|
* 3.3 330 "#version 330 core"
|
||||||
|
* 4.0 400 "#version 400 core"
|
||||||
|
* 4.1 410 "#version 410 core"
|
||||||
|
* 4.2 420 "#version 410 core"
|
||||||
|
* 4.3 430 "#version 430 core"
|
||||||
|
* ---------------------------------------
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* If the argument is null, then a "#version 130" string will be used by default.
|
||||||
|
*/
|
||||||
|
public void init(final String glslVersion) {
|
||||||
|
readGlVersion();
|
||||||
|
setupBackendCapabilitiesFlags();
|
||||||
|
|
||||||
|
if (glslVersion == null) {
|
||||||
|
this.glslVersion = "#version 130";
|
||||||
|
} else {
|
||||||
|
this.glslVersion = glslVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
createDeviceObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to render {@link ImDrawData} into current OpenGL context.
|
||||||
*/
|
*/
|
||||||
public void render(final ImDrawData drawData) {
|
public void render(final ImDrawData drawData) {
|
||||||
if (drawData.getCmdListsCount() <= 0) {
|
if (drawData.getCmdListsCount() <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
drawData.getDisplaySize(displaySize);
|
// Will project scissor/clipping rectangles into framebuffer space
|
||||||
drawData.getFramebufferScale(framebufferScale);
|
drawData.getDisplaySize(displaySize); // (0,0) unless using multi-viewports
|
||||||
|
drawData.getFramebufferScale(framebufferScale); // (1,1) unless using retina display which are often (2,2)
|
||||||
|
|
||||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||||
final int fbWidth = (int) (displaySize.x * framebufferScale.x);
|
final int fbWidth = (int) (displaySize.x * framebufferScale.x);
|
||||||
@@ -125,9 +166,16 @@ public final class ImGuiImplGl3 {
|
|||||||
final int textureId = drawData.getCmdListCmdBufferTextureId(cmdListIdx, cmdBufferIdx);
|
final int textureId = drawData.getCmdListCmdBufferTextureId(cmdListIdx, cmdBufferIdx);
|
||||||
final int elemCount = drawData.getCmdListCmdBufferElemCount(cmdListIdx, cmdBufferIdx);
|
final int elemCount = drawData.getCmdListCmdBufferElemCount(cmdListIdx, cmdBufferIdx);
|
||||||
final int idxBufferOffset = drawData.getCmdListCmdBufferIdxOffset(cmdListIdx, cmdBufferIdx);
|
final int idxBufferOffset = drawData.getCmdListCmdBufferIdxOffset(cmdListIdx, cmdBufferIdx);
|
||||||
|
final int vtxBufferOffset = drawData.getCmdListCmdBufferVtxOffset(cmdListIdx, cmdBufferIdx);
|
||||||
|
final int indices = idxBufferOffset * ImDrawData.SIZEOF_IM_DRAW_IDX;
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||||
glDrawElements(GL_TRIANGLES, elemCount, GL_UNSIGNED_SHORT, idxBufferOffset * ImDrawData.SIZEOF_IM_DRAW_IDX);
|
|
||||||
|
if (glVersion >= 320) {
|
||||||
|
glDrawElementsBaseVertex(GL_TRIANGLES, elemCount, GL_UNSIGNED_SHORT, indices, vtxBufferOffset);
|
||||||
|
} else {
|
||||||
|
glDrawElements(GL_TRIANGLES, elemCount, GL_UNSIGNED_SHORT, indices);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,36 +185,22 @@ public final class ImGuiImplGl3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this method in the end of your app working state to dispose resources.
|
* Call this method in the end of your application cycle to dispose resources used by {@link ImGuiImplGl3}.
|
||||||
*/
|
*/
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
glDeleteBuffers(gVboHandle);
|
||||||
|
glDeleteBuffers(gElementsHandle);
|
||||||
|
glDetachShader(gShaderHandle, gVertHandle);
|
||||||
|
glDetachShader(gShaderHandle, gFragHandle);
|
||||||
|
glDeleteProgram(gShaderHandle);
|
||||||
glDeleteTextures(gFontTexture);
|
glDeleteTextures(gFontTexture);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
||||||
glDeleteBuffers(elementsHandle);
|
|
||||||
glDeleteBuffers(vboHandle);
|
|
||||||
glDetachShader(programId, vertexShaderId);
|
|
||||||
glDetachShader(programId, fragmentShaderId);
|
|
||||||
glDeleteProgram(programId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareShader() {
|
/**
|
||||||
final CharSequence fragShaderSource = readFromResources("default.frag");
|
* Method rebuilds the font atlas for Dear ImGui. Could be used to update application fonts in runtime.
|
||||||
final CharSequence vertShaderSource = readFromResources("default.vert");
|
*/
|
||||||
|
public void updateFontsTexture() {
|
||||||
fragmentShaderId = loadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderSource);
|
glDeleteTextures(gFontTexture);
|
||||||
vertexShaderId = loadAndCompileShader(GL_VERTEX_SHADER, vertShaderSource);
|
|
||||||
|
|
||||||
programId = glCreateProgram();
|
|
||||||
glAttachShader(programId, fragmentShaderId);
|
|
||||||
glAttachShader(programId, vertexShaderId);
|
|
||||||
glLinkProgram(programId);
|
|
||||||
|
|
||||||
if (glGetProgrami(programId, GL_LINK_STATUS) != GL_TRUE) {
|
|
||||||
throw new IllegalStateException(glGetProgramInfoLog(programId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prepareFont() {
|
|
||||||
gFontTexture = glGenTextures();
|
gFontTexture = glGenTextures();
|
||||||
|
|
||||||
final ImFontAtlas fontAtlas = ImGui.getIO().getFonts();
|
final ImFontAtlas fontAtlas = ImGui.getIO().getFonts();
|
||||||
@@ -184,11 +218,102 @@ public final class ImGuiImplGl3 {
|
|||||||
fontAtlas.setTexID(gFontTexture);
|
fontAtlas.setTexID(gFontTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readGlVersion() {
|
||||||
|
final int[] major = new int[1];
|
||||||
|
final int[] minor = new int[1];
|
||||||
|
glGetIntegerv(GL_MAJOR_VERSION, major);
|
||||||
|
glGetIntegerv(GL_MINOR_VERSION, minor);
|
||||||
|
glVersion = major[0] * 100 + minor[0] * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupBackendCapabilitiesFlags() {
|
||||||
|
final ImGuiIO io = ImGui.getIO();
|
||||||
|
io.setBackendRendererName("imgui_java_impl_opnegl3");
|
||||||
|
|
||||||
|
// We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||||
|
if (glVersion >= 320) {
|
||||||
|
io.setBackendFlags(io.getBackendFlags() | ImGuiBackendFlags.RendererHasVtxOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createDeviceObjects() {
|
||||||
|
// Backup GL state
|
||||||
|
final int[] lastTexture = new int[1];
|
||||||
|
final int[] lastArrayBuffer = new int[1];
|
||||||
|
final int[] lastVertexArray = new int[1];
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, lastTexture);
|
||||||
|
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, lastArrayBuffer);
|
||||||
|
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, lastVertexArray);
|
||||||
|
|
||||||
|
createShaders();
|
||||||
|
|
||||||
|
gAttribLocationTex = glGetUniformLocation(gShaderHandle, "Texture");
|
||||||
|
gAttribLocationProjMtx = glGetUniformLocation(gShaderHandle, "ProjMtx");
|
||||||
|
gAttribLocationVtxPos = glGetAttribLocation(gShaderHandle, "Position");
|
||||||
|
gAttribLocationVtxUV = glGetAttribLocation(gShaderHandle, "UV");
|
||||||
|
gAttribLocationVtxColor = glGetAttribLocation(gShaderHandle, "Color");
|
||||||
|
|
||||||
|
// Create buffers
|
||||||
|
gVboHandle = glGenBuffers();
|
||||||
|
gElementsHandle = glGenBuffers();
|
||||||
|
|
||||||
|
updateFontsTexture();
|
||||||
|
|
||||||
|
// Restore modified GL state
|
||||||
|
glBindTexture(GL_TEXTURE_2D, lastTexture[0]);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, lastArrayBuffer[0]);
|
||||||
|
glBindVertexArray(lastVertexArray[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createShaders() {
|
||||||
|
final int glslVersionValue = parseGlslVersionString();
|
||||||
|
|
||||||
|
// Select shaders matching our GLSL versions
|
||||||
|
final CharSequence vertShaderSource;
|
||||||
|
final CharSequence fragShaderSource;
|
||||||
|
|
||||||
|
if (glslVersionValue < 130) {
|
||||||
|
vertShaderSource = getVertexShaderGlsl120();
|
||||||
|
fragShaderSource = getFragmentShaderGlsl120();
|
||||||
|
} else if (glslVersionValue >= 410) {
|
||||||
|
vertShaderSource = getVertexShaderGlsl410Core();
|
||||||
|
fragShaderSource = getFragmentShaderGlsl410Core();
|
||||||
|
} else {
|
||||||
|
vertShaderSource = getVertexShaderGlsl130();
|
||||||
|
fragShaderSource = getFragmentShaderGlsl130();
|
||||||
|
}
|
||||||
|
|
||||||
|
gVertHandle = createAndCompileShader(GL_VERTEX_SHADER, vertShaderSource);
|
||||||
|
gFragHandle = createAndCompileShader(GL_FRAGMENT_SHADER, fragShaderSource);
|
||||||
|
|
||||||
|
gShaderHandle = glCreateProgram();
|
||||||
|
glAttachShader(gShaderHandle, gVertHandle);
|
||||||
|
glAttachShader(gShaderHandle, gFragHandle);
|
||||||
|
glLinkProgram(gShaderHandle);
|
||||||
|
|
||||||
|
if (glGetProgrami(gShaderHandle, GL_LINK_STATUS) == GL_FALSE) {
|
||||||
|
throw new IllegalStateException("Failed to link shader program:\n" + glGetProgramInfoLog(gShaderHandle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int parseGlslVersionString() {
|
||||||
|
final Pattern p = Pattern.compile("\\d+");
|
||||||
|
final Matcher m = p.matcher(glslVersion);
|
||||||
|
|
||||||
|
if (m.find()) {
|
||||||
|
return Integer.parseInt(m.group());
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Invalid GLSL version string: " + glslVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void backupGlState() {
|
private void backupGlState() {
|
||||||
glGetIntegerv(GL_ACTIVE_TEXTURE, lastActiveTexture);
|
glGetIntegerv(GL_ACTIVE_TEXTURE, lastActiveTexture);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glGetIntegerv(GL_CURRENT_PROGRAM, lastProgram);
|
glGetIntegerv(GL_CURRENT_PROGRAM, lastProgram);
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, lastTexture);
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, lastTexture);
|
||||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, lastArrayBuffer);
|
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, lastArrayBuffer);
|
||||||
|
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, lastVertexArrayObject);
|
||||||
glGetIntegerv(GL_VIEWPORT, lastViewport);
|
glGetIntegerv(GL_VIEWPORT, lastViewport);
|
||||||
glGetIntegerv(GL_SCISSOR_BOX, lastScissorBox);
|
glGetIntegerv(GL_SCISSOR_BOX, lastScissorBox);
|
||||||
glGetIntegerv(GL_BLEND_SRC_RGB, lastBlendSrcRgb);
|
glGetIntegerv(GL_BLEND_SRC_RGB, lastBlendSrcRgb);
|
||||||
@@ -207,6 +332,7 @@ public final class ImGuiImplGl3 {
|
|||||||
glUseProgram(lastProgram[0]);
|
glUseProgram(lastProgram[0]);
|
||||||
glBindTexture(GL_TEXTURE_2D, lastTexture[0]);
|
glBindTexture(GL_TEXTURE_2D, lastTexture[0]);
|
||||||
glActiveTexture(lastActiveTexture[0]);
|
glActiveTexture(lastActiveTexture[0]);
|
||||||
|
glBindVertexArray(lastVertexArrayObject[0]);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, lastArrayBuffer[0]);
|
glBindBuffer(GL_ARRAY_BUFFER, lastArrayBuffer[0]);
|
||||||
glBlendEquationSeparate(lastBlendEquationRgb[0], lastBlendEquationAlpha[0]);
|
glBlendEquationSeparate(lastBlendEquationRgb[0], lastBlendEquationAlpha[0]);
|
||||||
glBlendFuncSeparate(lastBlendSrcRgb[0], lastBlendDstRgb[0], lastBlendSrcAlpha[0], lastBlendDstAlpha[0]);
|
glBlendFuncSeparate(lastBlendSrcRgb[0], lastBlendDstRgb[0], lastBlendSrcAlpha[0], lastBlendDstAlpha[0]);
|
||||||
@@ -220,9 +346,13 @@ public final class ImGuiImplGl3 {
|
|||||||
glScissor(lastScissorBox[0], lastScissorBox[1], lastScissorBox[2], lastScissorBox[3]);
|
glScissor(lastScissorBox[0], lastScissorBox[1], lastScissorBox[2], lastScissorBox[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup desired GL state
|
||||||
private void bind() {
|
private void bind() {
|
||||||
glViewport(0, 0, (int) displaySize.x, (int) displaySize.y);
|
// Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
|
||||||
glActiveTexture(GL_TEXTURE0);
|
// The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound.
|
||||||
|
gVertexArrayObjectHandle = glGenVertexArrays();
|
||||||
|
|
||||||
|
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
@@ -230,83 +360,142 @@ public final class ImGuiImplGl3 {
|
|||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
// Setup viewport, orthographic projection matrix
|
||||||
|
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
|
||||||
|
// DisplayPos is (0,0) for single viewport apps.
|
||||||
|
glViewport(0, 0, (int) displaySize.x, (int) displaySize.y);
|
||||||
final float left = displayPos.x;
|
final float left = displayPos.x;
|
||||||
final float right = displayPos.x + displaySize.x;
|
final float right = displayPos.x + displaySize.x;
|
||||||
final float top = displayPos.y;
|
final float top = displayPos.y;
|
||||||
final float bottom = displayPos.y + displaySize.y;
|
final float bottom = displayPos.y + displaySize.y;
|
||||||
|
|
||||||
// Orthographic matrix projection
|
// Orthographic matrix projection
|
||||||
projMatrix[0] = 2.0f / (right - left);
|
orthoProjMatrix[0] = 2.0f / (right - left);
|
||||||
projMatrix[5] = 2.0f / (top - bottom);
|
orthoProjMatrix[5] = 2.0f / (top - bottom);
|
||||||
projMatrix[10] = -1.0f;
|
orthoProjMatrix[10] = -1.0f;
|
||||||
projMatrix[12] = (right + left) / (left - right);
|
orthoProjMatrix[12] = (right + left) / (left - right);
|
||||||
projMatrix[13] = (top + bottom) / (bottom - top);
|
orthoProjMatrix[13] = (top + bottom) / (bottom - top);
|
||||||
projMatrix[15] = 1.0f;
|
orthoProjMatrix[15] = 1.0f;
|
||||||
|
|
||||||
// Bind shader
|
// Bind shader
|
||||||
glUseProgram(programId);
|
glUseProgram(gShaderHandle);
|
||||||
glUniform1i(glGetUniformLocation(programId, "Texture"), 0);
|
glUniform1i(gAttribLocationTex, 0);
|
||||||
glUniformMatrix4fv(glGetUniformLocation(programId, "ProjMtx"), false, projMatrix);
|
glUniformMatrix4fv(gAttribLocationProjMtx, false, orthoProjMatrix);
|
||||||
|
|
||||||
|
glBindVertexArray(gVertexArrayObjectHandle);
|
||||||
|
|
||||||
// Bind vertex/index buffers and setup attributes for ImDrawVert
|
// Bind vertex/index buffers and setup attributes for ImDrawVert
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vboHandle);
|
glBindBuffer(GL_ARRAY_BUFFER, gVboHandle);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementsHandle);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gElementsHandle);
|
||||||
|
glEnableVertexAttribArray(gAttribLocationVtxPos);
|
||||||
int location = glGetAttribLocation(programId, "Position");
|
glEnableVertexAttribArray(gAttribLocationVtxUV);
|
||||||
glEnableVertexAttribArray(location);
|
glEnableVertexAttribArray(gAttribLocationVtxColor);
|
||||||
glVertexAttribPointer(location, 2, GL_FLOAT, false, ImDrawData.SIZEOF_IM_DRAW_VERT, 0);
|
glVertexAttribPointer(gAttribLocationVtxPos, 2, GL_FLOAT, false, ImDrawData.SIZEOF_IM_DRAW_VERT, 0);
|
||||||
|
glVertexAttribPointer(gAttribLocationVtxUV, 2, GL_FLOAT, false, ImDrawData.SIZEOF_IM_DRAW_VERT, 8);
|
||||||
location = glGetAttribLocation(programId, "UV");
|
glVertexAttribPointer(gAttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, true, ImDrawData.SIZEOF_IM_DRAW_VERT, 16);
|
||||||
glEnableVertexAttribArray(location);
|
|
||||||
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, ImDrawData.SIZEOF_IM_DRAW_VERT, 16);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unbind() {
|
private void unbind() {
|
||||||
// Unbind vertices
|
// Destroy the temporary VAO
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glDeleteVertexArrays(gVertexArrayObjectHandle);
|
||||||
|
|
||||||
glDisableVertexAttribArray(glGetAttribLocation(programId, "Position"));
|
|
||||||
glDisableVertexAttribArray(glGetAttribLocation(programId, "UV"));
|
|
||||||
glDisableVertexAttribArray(glGetAttribLocation(programId, "Color"));
|
|
||||||
|
|
||||||
// Unbind index
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
||||||
glFlush();
|
|
||||||
|
|
||||||
// Unbind shader
|
|
||||||
glUseProgram(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int loadAndCompileShader(final int type, final CharSequence source) {
|
private int createAndCompileShader(final int type, final CharSequence source) {
|
||||||
final int id = glCreateShader(type);
|
final int id = glCreateShader(type);
|
||||||
|
|
||||||
glShaderSource(id, source);
|
glShaderSource(id, source);
|
||||||
glCompileShader(id);
|
glCompileShader(id);
|
||||||
|
|
||||||
if (glGetShaderi(id, GL_COMPILE_STATUS) != GL_TRUE) {
|
if (glGetShaderi(id, GL_COMPILE_STATUS) == GL_FALSE) {
|
||||||
throw new IllegalStateException(glGetShaderInfoLog(id));
|
throw new IllegalStateException("Failed to compile shader:\n" + glGetShaderInfoLog(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CharSequence readFromResources(final String path) {
|
private String getVertexShaderGlsl120() {
|
||||||
final StringBuilder builder = new StringBuilder();
|
return glslVersion + "\n"
|
||||||
|
+ "uniform mat4 ProjMtx;\n"
|
||||||
try (InputStream in = getClass().getClassLoader().getResourceAsStream(path);
|
+ "attribute vec2 Position;\n"
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull(in)))) {
|
+ "attribute vec2 UV;\n"
|
||||||
String line;
|
+ "attribute vec4 Color;\n"
|
||||||
while ((line = reader.readLine()) != null) {
|
+ "varying vec2 Frag_UV;\n"
|
||||||
builder.append(line).append('\n');
|
+ "varying vec4 Frag_Color;\n"
|
||||||
}
|
+ "void main()\n"
|
||||||
} catch (IOException ex) {
|
+ "{\n"
|
||||||
throw new UncheckedIOException("Failed to read from resources!", ex);
|
+ " Frag_UV = UV;\n"
|
||||||
|
+ " Frag_Color = Color;\n"
|
||||||
|
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||||
|
+ "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.toString();
|
private String getVertexShaderGlsl130() {
|
||||||
|
return glslVersion + "\n"
|
||||||
|
+ "uniform mat4 ProjMtx;\n"
|
||||||
|
+ "in vec2 Position;\n"
|
||||||
|
+ "in vec2 UV;\n"
|
||||||
|
+ "in vec4 Color;\n"
|
||||||
|
+ "out vec2 Frag_UV;\n"
|
||||||
|
+ "out vec4 Frag_Color;\n"
|
||||||
|
+ "void main()\n"
|
||||||
|
+ "{\n"
|
||||||
|
+ " Frag_UV = UV;\n"
|
||||||
|
+ " Frag_Color = Color;\n"
|
||||||
|
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||||
|
+ "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getVertexShaderGlsl410Core() {
|
||||||
|
return glslVersion + "\n"
|
||||||
|
+ "layout (location = 0) in vec2 Position;\n"
|
||||||
|
+ "layout (location = 1) in vec2 UV;\n"
|
||||||
|
+ "layout (location = 2) in vec4 Color;\n"
|
||||||
|
+ "uniform mat4 ProjMtx;\n"
|
||||||
|
+ "out vec2 Frag_UV;\n"
|
||||||
|
+ "out vec4 Frag_Color;\n"
|
||||||
|
+ "void main()\n"
|
||||||
|
+ "{\n"
|
||||||
|
+ " Frag_UV = UV;\n"
|
||||||
|
+ " Frag_Color = Color;\n"
|
||||||
|
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||||
|
+ "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFragmentShaderGlsl120() {
|
||||||
|
return glslVersion + "\n"
|
||||||
|
+ "#ifdef GL_ES\n"
|
||||||
|
+ " precision mediump float;\n"
|
||||||
|
+ "#endif\n"
|
||||||
|
+ "uniform sampler2D Texture;\n"
|
||||||
|
+ "varying vec2 Frag_UV;\n"
|
||||||
|
+ "varying vec4 Frag_Color;\n"
|
||||||
|
+ "void main()\n"
|
||||||
|
+ "{\n"
|
||||||
|
+ " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n"
|
||||||
|
+ "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFragmentShaderGlsl130() {
|
||||||
|
return glslVersion + "\n"
|
||||||
|
+ "uniform sampler2D Texture;\n"
|
||||||
|
+ "in vec2 Frag_UV;\n"
|
||||||
|
+ "in vec4 Frag_Color;\n"
|
||||||
|
+ "out vec4 Out_Color;\n"
|
||||||
|
+ "void main()\n"
|
||||||
|
+ "{\n"
|
||||||
|
+ " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
|
||||||
|
+ "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFragmentShaderGlsl410Core() {
|
||||||
|
return glslVersion + "\n"
|
||||||
|
+ "in vec2 Frag_UV;\n"
|
||||||
|
+ "in vec4 Frag_Color;\n"
|
||||||
|
+ "uniform sampler2D Texture;\n"
|
||||||
|
+ "layout (location = 0) out vec4 Out_Color;\n"
|
||||||
|
+ "void main()\n"
|
||||||
|
+ "{\n"
|
||||||
|
+ " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
|
||||||
|
+ "}\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#version 130
|
|
||||||
|
|
||||||
#ifdef GL_ES
|
|
||||||
precision mediump float;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uniform sampler2D Texture;
|
|
||||||
in vec2 Frag_UV;
|
|
||||||
in vec4 Frag_Color;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#version 130
|
|
||||||
|
|
||||||
uniform mat4 ProjMtx;
|
|
||||||
in vec2 Position;
|
|
||||||
in vec2 UV;
|
|
||||||
in vec4 Color;
|
|
||||||
out vec2 Frag_UV;
|
|
||||||
out vec4 Frag_Color;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
Frag_UV = UV;
|
|
||||||
Frag_Color = Color;
|
|
||||||
gl_Position = ProjMtx * vec4(Position.xy, 0, 1);
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user