nanovg icon indicating copy to clipboard operation
nanovg copied to clipboard

NanoVG (GL2) and OpenGL cannot drawing together, but NanoVG(GL3) could

Open jiandingzhe opened this issue 5 years ago • 4 comments

For some reason, I tried to render using mixed NanoVG and raw OpenGL.

        glClearColor( 0.7f, 0.8f, 1, 1 );
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_ACCUM_BUFFER_BIT );

        // PART1: nanovg
        nvgBeginFrame( nvg, w, h, 1.0f );
        nvgCircle( nvg, 50, 50, 50 );
        nvgStrokeWidth( nvg, 3.0f );
        nvgStrokeColor( nvg, nvgRGB( 255, 127, 64 ) );
        nvgStroke( nvg );
        nvgEndFrame( nvg );
        
        // PART2: raw OpenGL
        glUseProgram( prog );
        glBindVertexArray( vao );
        glBindBuffer( GL_ARRAY_BUFFER, vbo );
        glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );

        glFinish();
        SDL_GL_SwapWindow( win );

If I compile nanovg_gl.h with NANOVG_GL2_IMPLEMENTATION, the OpenGL drawing part would always output nothing; and if compile with NANOVG_GL3_IMPLEMENTATION, it renders correctly.

The OpenGL drawing part as simple as drawing an rectangle with vertex color.

What make it so different between GL2 and GL3?

In addition:

  • I've turned on stencil buffer this time.
  • the result won't change even if I put PART2 before PART1.
  • The reason I'm using mixed drawing is that I'm making a screen-space image effect that needs drawing back hijacked framebuffer using OpenGL draws.
  • The reason I use NANOVG_GL2_IMPLEMENTATION is that my Linux laptop's Intel HD3000 graphic driver don't support #version 150 shader, which is required by NanoVG's GL3 implementation.

jiandingzhe avatar Mar 17 '20 14:03 jiandingzhe

I run both GL2 and GL3 programs with CodeXL and recorded all OpenGL calls in rendering loop.

Records from NanoVG compiled with NANOVG_GL2_IMPLEMENTATION:

glClearColor(0.69999999, 0.80000001, 1, 1)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
glUseProgram(1) [Context 3 - program 1: shader 2, shader 3]
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glFrontFace(GL_CCW)
glEnable(GL_BLEND)
glDisable(GL_DEPTH_TEST)
glDisable(GL_SCISSOR_TEST)
glColorMask(TRUE, TRUE, TRUE, TRUE)
glStencilMask(4294967295)
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP)
glStencilFunc(GL_ALWAYS, 0, 4294967295)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, 0)
glBindBuffer(GL_ARRAY_BUFFER, 1)
glBufferData(GL_ARRAY_BUFFER, 2080, 0x00000208FB7AB5E0, GL_STREAM_DRAW)
glEnableVertexAttribArray(0)
glEnableVertexAttribArray(1)
glVertexAttribPointer(0, 2, GL_FLOAT, FALSE, 16, 0x0000000000000000)
glVertexAttribPointer(1, 2, GL_FLOAT, FALSE, 16, 0x0000000000000008)
glUniform1i(12, 0) [Context 3 - program 1: shader 2, shader 3]
glUniform2fv(11, 1, {600, 400}) [Context 3 - program 1: shader 2, shader 3]
glBlendFuncSeparate(1, GL_ONE_MINUS_SRC_ALPHA, 1, GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_STENCIL_TEST)
glStencilMask(255)
glStencilFunc(GL_EQUAL, 0, 255)
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR)
glUniform4fv(0, 11, {0, 0, 0, 0}) [Context 3 - program 1: shader 2, shader 3]
glGetError()
glDrawArrays(GL_TRIANGLE_STRIP, 0, 130)
glUniform4fv(0, 11, {0, 0, 0, 0}) [Context 3 - program 1: shader 2, shader 3]
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 130)
glColorMask(FALSE, FALSE, FALSE, FALSE)
glStencilFunc(GL_ALWAYS, 0, 255)
glStencilOp(0, 0, 0)
glGetError()
glDrawArrays(GL_TRIANGLE_STRIP, 0, 130)
glColorMask(TRUE, TRUE, TRUE, TRUE)
glDisable(GL_STENCIL_TEST)
glDisableVertexAttribArray(0)
glDisableVertexAttribArray(1)
glDisable(GL_CULL_FACE)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glUseProgram(0) [Context 3 - program 0]
glUseProgram(4) [Context 3 - program 4: shader 5, shader 6]
glBindVertexArray(1)
glBindBuffer(GL_ARRAY_BUFFER, 2)
glDrawArrays(GL_TRIANGLE_FAN, 0, 4)
glFinish()
wglSwapBuffers(0x000000001A01224C)

And from NANOVG_GL3_IMPLEMENTATION:

glClearColor(0.69999999, 0.80000001, 1, 1)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
glUseProgram(1) [Context 3 - program 1: shader 2, shader 3]
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glFrontFace(GL_CCW)
glEnable(GL_BLEND)
glDisable(GL_DEPTH_TEST)
glDisable(GL_SCISSOR_TEST)
glColorMask(TRUE, TRUE, TRUE, TRUE)
glStencilMask(4294967295)
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP)
glStencilFunc(GL_ALWAYS, 0, 4294967295)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, 0)
glBindBuffer(GL_UNIFORM_BUFFER, 2)
glBufferData(GL_UNIFORM_BUFFER, 512, 0x000001D670FF28B0, GL_STREAM_DRAW)
glBindVertexArray(1)
glBindBuffer(GL_ARRAY_BUFFER, 1)
glBufferData(GL_ARRAY_BUFFER, 2080, 0x000001D670FE2870, GL_STREAM_DRAW)
glEnableVertexAttribArray(0)
glEnableVertexAttribArray(1)
glVertexAttribPointer(0, 2, GL_FLOAT, FALSE, 16, 0x0000000000000000)
glVertexAttribPointer(1, 2, GL_FLOAT, FALSE, 16, 0x0000000000000008)
glUniform1i(14, 0) [Context 3 - program 1: shader 2, shader 3]
glUniform2fv(13, 1, {600, 400}) [Context 3 - program 1: shader 2, shader 3]
glBindBuffer(GL_UNIFORM_BUFFER, 2)
glBlendFuncSeparate(1, GL_ONE_MINUS_SRC_ALPHA, 1, GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_STENCIL_TEST)
glStencilMask(255)
glStencilFunc(GL_EQUAL, 0, 255)
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR)
glBindBufferRange(GL_UNIFORM_BUFFER, 0, 2, 256, 176)
glGetError()
glDrawArrays(GL_TRIANGLE_STRIP, 0, 130)
glBindBufferRange(GL_UNIFORM_BUFFER, 0, 2, 0, 176)
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP)
glDrawArrays(GL_TRIANGLE_STRIP, 0, 130)
glColorMask(FALSE, FALSE, FALSE, FALSE)
glStencilFunc(GL_ALWAYS, 0, 255)
glStencilOp(0, 0, 0)
glGetError()
glDrawArrays(GL_TRIANGLE_STRIP, 0, 130)
glColorMask(TRUE, TRUE, TRUE, TRUE)
glDisable(GL_STENCIL_TEST)
glDisableVertexAttribArray(0)
glDisableVertexAttribArray(1)
glBindVertexArray(0)
glDisable(GL_CULL_FACE)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glUseProgram(0) [Context 3 - program 0]
glUseProgram(4) [Context 3 - program 4: shader 5, shader 6]
glBindVertexArray(2)
glBindBuffer(GL_ARRAY_BUFFER, 3)
glDrawArrays(GL_TRIANGLE_FAN, 0, 4)
glFinish()
wglSwapBuffers(0x000000004B0123A6)

The last six lines start from glUseProgram(4) is my custom raw GL drawing.

I compared the two records. It seems in GL3 version, nanovg is using its own VAO (an extra pair of glBindVertexArray(1) and glBindVertexArray(0)), while GL2 version not. So would GL2 version disturb some currently binding VAO? As VAO feature is not GL3-only, why nanovg don't have this pair of call in GL2 version?

jiandingzhe avatar Mar 18 '20 02:03 jiandingzhe

Did you find a solution to this ? I want to try mixing OpenGL calls with nanovg also, so I guess this will concern me too soon.

mulle-nat avatar May 29 '21 23:05 mulle-nat

NanoVG will change some OpenGL state, which you will need to manually reset. See https://github.com/memononen/nanovg#opengl-state-touched-by-the-backend

memononen avatar May 30 '21 05:05 memononen

I was trying to leach off some working demo code here. :) I know that page. (But thanks anyway)

mulle-nat avatar May 30 '21 15:05 mulle-nat