UI fonts smearing when viewport rendering

Hi,

This one is a bit hard to explain, so let me know if you need me to elaborate more.

For some reason, when our RenderEngine addon is requested to do viewport rendering, the fonts in Blender’s UI eventually will look like they are “smeared” making it almost impossible to see what you’re clicking on (see image)

Our addon’s view_draw method looks something like this:

    bgl.glEnable(bgl.GL_BLEND)
    bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ONE_MINUS_SRC_ALPHA)
    self.bind_display_space_shader(scene)

    self.rman_render.draw_pixels() 

    self.unbind_display_space_shader()
    bgl.glDisable(bgl.GL_BLEND)

The draw_pixels call eventually calls into a DLL to make C++ GL calls to draw a buffer. The GL calls are based on the CustomRenderEngine example in the docs. To get updates, we start a python thread that goes into a loop of calling RenderEngine.tag_redraw() and time.sleep(0.01), until the viewport render is aborted.

I’ve seen this happen on all platforms (macOS, Windows, and linux). Is there something we’re missing?

In general add-ons should restore the OpenGL state to exactly what it was before.

Regarding the blending and displace space shader, Cycles does the same thing. So the question is what is happening exactly in self.rman_render.draw_pixels() ?

You should be able to find which OpenGL state change is the problem by elimination.

Thanks for the reply brecht. draw_pixels() eventually calls into a function in a DLL, that looks something like the code below. I’m not exactly sure how am I supposed to restore the OpenGL state.

if (s_blenderImage == nullptr)
    return;
GLenum err = glewInit();
if (GLEW_OK != err)
    return;

std::array<GLfloat, 8> position = {0.0, 0.0, 
                                   (float) s_blenderImage->width, 
                                   0.0, 
                                   (float) s_blenderImage->width, 
                                   (float) s_blenderImage->height, 
                                   0.0, 
                                   (float) s_blenderImage->height};
std::array<GLfloat, 8> texture_coords = {0.0, 1.0, 1.0, 1.0,  
                                        1.0, 0.0,  0.0, 0.0};
GLuint vertex_array;
std::array<GLint, 2> vertex_buffer;
GLuint texture_id;

GLuint   texcoord_location;
GLuint   position_location;

GLint shader_program_id;
GLuint texture_vbo_id;
GLuint vertex_vbo_id;

glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(
    GL_TEXTURE_2D,
    0,
    GL_RGBA32F,
    static_cast<GLsizei>(s_blenderImage->width),
    static_cast<GLsizei>(s_blenderImage->height),
    0,
    GL_RGBA,
    GL_FLOAT,
    (float*) s_blenderImage->framebuffer);
glBindTexture(GL_TEXTURE_2D, 0);

// Get shader program set by Blender.
glGetIntegerv(GL_CURRENT_PROGRAM, &shader_program_id);

// Generate vertex array
glGenVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);

texcoord_location = glGetAttribLocation(shader_program_id, "texCoord");
position_location = glGetAttribLocation(shader_program_id, "pos");
  
glEnableVertexAttribArray(texcoord_location);
glEnableVertexAttribArray(position_location);

glGenBuffers(1, &texture_vbo_id);
glBindBuffer(GL_ARRAY_BUFFER, texture_vbo_id);
glBufferData(GL_ARRAY_BUFFER, texture_coords.size() * sizeof(float), 
             &texture_coords[0], GL_STATIC_DRAW);
glVertexAttribPointer(texcoord_location, 2, GL_FLOAT, GL_FALSE, 
                      2 * sizeof(float), reinterpret_cast<void*>(0));        

glGenBuffers(1, &vertex_vbo_id);
glBindBuffer(GL_ARRAY_BUFFER, vertex_vbo_id);
glBufferData(GL_ARRAY_BUFFER, position.size() * sizeof(float), 
             &position[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(position_location);
glVertexAttribPointer(position_location, 2, GL_FLOAT, GL_FALSE, 
                      2 * sizeof(float), reinterpret_cast<void*>(0));

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id);
glBindVertexArray(vertex_array);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);

Just to follow up, in case someone else runs into this. From reading the drawing code in Cycles, it looks like you have to delete the vertex array and the texture. i.e.:

glDeleteVertexArrays(1, &vertex_array);
glDeleteTextures(1, &texture_id);
1 Like

Hmm…spoke too soon. Looks like it’s still smearing after doing further tests. Be grateful if you give me other hints to look at @brecht.

I just can’t tell from this code, there is nothing here that jumps out to me as wrong. I suggest to find the cause by elimination. Comment out more and more of the drawing code until it’s clear which exact part is the problem.

Vertex arrays and textures definitely have to be freed at some point, otherwise it will leak memory.

Thanks. Looks like I was also missing a call to glGenTextures (oops).