What is the best approach to render a list of commands that might change every frame?

Basically I’m currently writing a imgui jme3 adapter, it works so far as in, I already get the font working, and it is generating me a drawlist that I need to draw now.

I have a drawdata object, that I want to render somehow trough an appstate’s render method

The imgui port has a low level lwjgl3 renderer included, however that one sees to have issues with jme3’s rendering pipeline. How would I do something like the following code block, the correct way, ideally without using direct opengl calls (as that would allow to use the imgui with jogl as well)?

Here is the code they use to low level render, simply calling that in the render function does not produce any visible output. If anyone has any insight as to why, this would also be interesting.

fun renderDrawData(drawData: DrawData) {

    /** Avoid rendering when minimized, scale coordinates for retina displays
     *  (screen coordinates != framebuffer coordinates) */
    val fbSize = io.displaySize * io.displayFramebufferScale
    if (fbSize equal 0) return
    drawData.scaleClipRects(io.displayFramebufferScale)

    // Backup GL state
    val lastActiveTexture = glGetInteger(GL_ACTIVE_TEXTURE)
    val lastProgram = glGetInteger(GL_CURRENT_PROGRAM)
    val lastTexture = glGetInteger(GL_TEXTURE_BINDING_2D)
    val lastSampler = glGetInteger(GL_SAMPLER_BINDING)
    val lastArrayBuffer = glGetInteger(GL_ARRAY_BUFFER_BINDING)
    val lastElementArrayBuffer = glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING)
    val lastVertexArray = glGetInteger(GL_VERTEX_ARRAY_BINDING)
    val lastPolygonMode = glGetInteger(GL_POLYGON_MODE)
    val lastViewport = glGetVec4i(GL_VIEWPORT)
    val lastScissorBox = glGetVec4i(GL_SCISSOR_BOX)
    val lastBlendSrcRgb = glGetInteger(GL_BLEND_SRC_RGB)
    val lastBlendDstRgb = glGetInteger(GL_BLEND_DST_RGB)
    val lastBlendSrcAlpha = glGetInteger(GL_BLEND_SRC_ALPHA)
    val lastBlendDstAlpha = glGetInteger(GL_BLEND_DST_ALPHA)
    val lastBlendEquationRgb = glGetInteger(GL_BLEND_EQUATION_RGB)
    val lastBlendEquationAlpha = glGetInteger(GL_BLEND_EQUATION_ALPHA)
    val lastEnableBlend = glIsEnabled(GL_BLEND)
    val lastEnableCullFace = glIsEnabled(GL_CULL_FACE)
    val lastEnableDepthTest = glIsEnabled(GL_DEPTH_TEST)
    val lastEnableScissorTest = glIsEnabled(GL_SCISSOR_TEST)

    // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
    glEnable(GL_BLEND)
    glBlendEquation(GL_FUNC_ADD)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    glDisable(GL_CULL_FACE)
    glDisable(GL_DEPTH_TEST)
    glEnable(GL_SCISSOR_TEST)
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

    // Setup viewport, orthographic projection matrix
    glViewport(fbSize)
    val ortho = glm.ortho(mat, 0f, io.displaySize.x.f, io.displaySize.y.f, 0f)
    glUseProgram(program)
    glUniform(program.mat, ortho)

    checkSize(drawData.cmdLists)

    glBindVertexArray(vaoName)
    glBindSampler(semantic.sampler.DIFFUSE, 0) // Rely on combined texture/sampler state.

    for (cmdList in drawData.cmdLists) {

        cmdList.vtxBuffer.forEachIndexed { i, v ->
            val offset = i * DrawVert.size
            v.pos.to(vtxBuffer, offset)
            v.uv.to(vtxBuffer, offset + Vec2.size)
            vtxBuffer.putInt(offset + Vec2.size * 2, v.col)
        }
        glBindBuffer(GL_ARRAY_BUFFER, bufferName[Buffer.Vertex])
        glBufferSubData(GL_ARRAY_BUFFER, 0, cmdList._vtxWritePtr * DrawVert.size, vtxBuffer)
        cmdList.idxBuffer.forEachIndexed { i, idx -> idxBuffer[i] = idx }
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferName[Buffer.Element])
        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, cmdList._idxWritePtr * Int.BYTES, idxBuffer)

        var idxBufferOffset = 0L
        for (cmd in cmdList.cmdBuffer) {
            if (cmd.userCallback != null)
                cmd.userCallback!!(cmdList, cmd)
            else {
                glActiveTexture(GL_TEXTURE0 + semantic.sampler.DIFFUSE)
                glBindTexture(GL_TEXTURE_2D, cmd.textureId!!)
                glScissor(cmd.clipRect.x.i, fbSize.y - cmd.clipRect.w.i,
                        (cmd.clipRect.z - cmd.clipRect.x).i, (cmd.clipRect.w - cmd.clipRect.y).i)
                glDrawElements(GL_TRIANGLES, cmd.elemCount, GL_UNSIGNED_INT, idxBufferOffset)
            }
            idxBufferOffset += cmd.elemCount * Int.BYTES
        }
    }

    checkError("render")

    // Restore modified GL state
    glUseProgram(lastProgram)
    glBindTexture(GL_TEXTURE_2D, lastTexture)
    glBindSampler(0, lastSampler)
    glActiveTexture(lastActiveTexture)
    glBindVertexArray(lastVertexArray)
    glBindBuffer(GL_ARRAY_BUFFER, lastArrayBuffer)
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lastElementArrayBuffer)
    glBlendEquationSeparate(lastBlendEquationRgb, lastBlendEquationAlpha)
    glBlendFuncSeparate(lastBlendSrcRgb, lastBlendDstRgb, lastBlendSrcAlpha, lastBlendDstAlpha)
    if (lastEnableBlend) glEnable(GL_BLEND) else glDisable(GL_BLEND)
    if (lastEnableCullFace) glEnable(GL_CULL_FACE) else glDisable(GL_CULL_FACE)
    if (lastEnableDepthTest) glEnable(GL_DEPTH_TEST) else glDisable(GL_DEPTH_TEST)
    if (lastEnableScissorTest) glEnable(GL_SCISSOR_TEST) else glDisable(GL_SCISSOR_TEST)
    glPolygonMode(GL_FRONT_AND_BACK, lastPolygonMode)
    glViewport(lastViewport)
    glScissor(lastScissorBox)
}

Is it possible there is two lwjgl contexts running? One for JME and one for LWJGL IMGUI?

Have you looked at how Nifty was integrated? It essentially runs in more of an “immediate mode” where it draws to OpenGL directly through JME.

1 Like

Actually no, good idea I will take a look.