I got a question regarding rendering a 2D text over the 3D scene in OpenGL 3.3. I followed this tutorial about how to render text in OpenGL. Although the tutorial is for C++ i ported it to Java (Kotlin), but I can't see any text rendered. Basically, what I am doing:

  1. Use program for 3D scene
  2. Render the 3D scene with proper view/projection matrix
  3. Use program for text rendering (basically vertex shader and fragment shader from the tutorial)
  4. Render text with ortho matrix

However, I do not see my text rendered. I went through some question here, which look similar, but they use the old OpenGL and their answers look like mine solution, I am using.

Does any of you have any advice on how to render 2D over 3D properly? Thanks

UPDATE with code:

// buffer setting up
glBindBuffer(GL_ARRAY_BUFFER, fontBuffer)
glBufferData(GL_ARRAY_BUFFER, BufferUtils.createFloatBuffer(24), GL_DYNAMIC_DRAW)

glBindBuffer(GL_ARRAY_BUFFER, fontBuffer)
glVertexAttribPointer(fontProgramCache[FontProgram.POSITION], 2, GL_FLOAT, false, 4 * java.lang.Float.BYTES, 0)
glVertexAttribPointer(fontProgramCache[FontProgram.TEXCOORD], 2, GL_FLOAT, false, 4 * java.lang.Float.BYTES, 2L * java.lang.Float.BYTES)

Now within the main loop:

// 3D models
// text
renderText("HELLO ", 0f, 0f, 2f, Vector3f(0f, 0f, 0f))

the renderText function:

fun renderText(text: String, x: Float, y: Float, scale: Float, color: Vector3f) {
    var mutableX = x
    glUniform3f(fontProgramCache[FontProgram.TEXT_COLOR], color.x, color.y, color.z)

    val projectionData = BufferUtils.createFloatBuffer(16)
    glUniformMatrix4fv(fontProgramCache[FontProgram.PROJECTION], false, projectionData)

    for (c in text) {
        val character = characterCache[c] ?: continue
        val xPos = mutableX + character.bearing.x * scale
        val yPos = y - (character.size.y - character.bearing.y) * scale
        val width = character.size.x * scale
        val height = character.size.y * scale

        val vertices: Array<Array<Float>> = arrayOf(
            arrayOf(xPos, yPos + height, 0f, 0f),
            arrayOf(xPos, yPos, 0f, 1f),
            arrayOf(xPos + width, yPos, 1f, 1f),
            arrayOf(xPos, yPos + height, 0f, 0f),
            arrayOf(xPos + width, yPos, 1f, 1f),
            arrayOf(xPos + width, yPos + height, 1f, 0f))
        glBindTexture(GL_TEXTURE_2D, character.textureId)
        glUniform1i(fontProgramCache[FontProgram.TEXT], 0)
        glBindBuffer(GL_ARRAY_BUFFER, fontBuffer)
        val verticesBuffer = BufferUtils.createFloatBuffer(24)
        vertices.forEach {
            it.forEach {
        glBufferSubData(GL_ARRAY_BUFFER, 0, verticesBuffer)
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glDrawArrays(GL_TRIANGLES, 0, 6)
        mutableX += (character.advance shr 6) * scale
    glBindTexture(GL_TEXTURE_2D, 0)

I think that the draw3dModel function is fine, as it does what it should.

  • \$\begingroup\$ You'll probably need to post your code, as we can't tell from what you've posted what might be wrong. \$\endgroup\$ – user1118321 May 26 '18 at 20:14
  • \$\begingroup\$ @user1118321 I edited the question with the relevant code! \$\endgroup\$ – Maroš Šeleng May 26 '18 at 20:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.