I’ve already posted on BA about this but I have a feeling it’s a better-suited question for here.
I’m adding viewport rendering to my custom renderer add-on, and I’m running into a problem where the color rendered in my viewport isn’t changing when my pixel buffer is updated. Here’s what I know so far:
- I’m basing my implementation on Blender’s example
CustomDrawData
class (RenderEngine(bpy_struct) — Blender Python API) - I’m initiating the class with a
self.buffer
variable that holds a list of pixel color values, just like the example (although the example calls itself.pixels
). I start with a solid red color ([1.0, 0.0, 0.0, 1.0]
), and it displays in the viewport perfectly fine. - After the red box appears I flood the buffer with 1’s to turn it white (
[1.0, 1.0, 1.0, 1.0]
). I can see that myself.buffer
attribute is updated correctly, but the function I call to update theglTexImage2d
object doesn’t seem to do anything, because the color stays red and never turns white. - I am calling
FrameBuffer.build_gl_texture()
(see below) andengine.tag_redraw()
after updating my buffer values to refresh the texture in OpenGL.
Here is the code to my custom class so far. I’m not super familiar with OpenGL in general - is there something obvious that I’m missing that I need to do to get the glTexImage2d
object to properly register the new pixel values? I’m not getting any errors in the console, so I have very little info to go on outside of the docs and the code I have.
class FrameBuffer:
def __init__(self):
# This is hard-coded for now, will change later
self.width, self.height = 512, 512
# For debugging purposes, I'm starting with a solid red color
# so I KNOW when the color changes
pixels = [1.0, 0.0, 0.0, 1.0] * self.width * self.height
self.buffer = bgl.Buffer(bgl.GL_FLOAT, self.width * self.height * 4, pixels)
self.init_opengl()
def init_opengl(self):
self.texture = bgl.Buffer(bgl.GL_INT, 1)
bgl.glGenTextures(1, self.texture)
self.build_gl_texture()
shader_program = bgl.Buffer(bgl.GL_INT, 1)
bgl.glGetIntegerv(bgl.GL_CURRENT_PROGRAM, shader_program)
self.vertex_array = bgl.Buffer(bgl.GL_INT, 1)
bgl.glGenVertexArrays(1, self.vertex_array)
bgl.glBindVertexArray(self.vertex_array[0])
texturecoord_location = bgl.glGetAttribLocation(shader_program[0], "texCoord")
position_location = bgl.glGetAttribLocation(shader_program[0], "pos")
bgl.glEnableVertexAttribArray(texturecoord_location)
bgl.glEnableVertexAttribArray(position_location)
position = [0.0, 0.0, self.width, 0.0, self.width, self.height, 0.0, self.height]
position = bgl.Buffer(bgl.GL_FLOAT, len(position), position)
texcoord = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]
texcoord = bgl.Buffer(bgl.GL_FLOAT, len(texcoord), texcoord)
self.vertex_buffer = bgl.Buffer(bgl.GL_INT, 2)
bgl.glGenBuffers(2, self.vertex_buffer)
bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vertex_buffer[0])
bgl.glBufferData(bgl.GL_ARRAY_BUFFER, 32, position, bgl.GL_STATIC_DRAW)
bgl.glVertexAttribPointer(position_location, 2, bgl.GL_FLOAT, bgl.GL_FALSE, 0, None)
bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vertex_buffer[1])
bgl.glBufferData(bgl.GL_ARRAY_BUFFER, 32, texcoord, bgl.GL_STATIC_DRAW)
bgl.glVertexAttribPointer(texturecoord_location, 2, bgl.GL_FLOAT, bgl.GL_FALSE, 0, None)
bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, 0)
bgl.glBindVertexArray(0)
# This gets called every time I update self.buffer to refresh the OpenGL texture with the new values
def build_gl_texture(self):
bgl.glActiveTexture(bgl.GL_TEXTURE0)
bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture[0])
bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA16F, self.width, self.height, 0, bgl.GL_RGBA, bgl.GL_FLOAT, self.buffer)
bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR)
bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR)
bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
def __del__(self):
bgl.glDeleteBuffers(2, self.vertex_buffer)
bgl.glDeleteVertexArrays(1, self.vertex_array)
bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
bgl.glDeleteTextures(1, self.texture)
def draw(self):
bgl.glActiveTexture(bgl.GL_TEXTURE0)
bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture[0])
bgl.glBindVertexArray(self.vertex_array[0])
bgl.glDrawArrays(bgl.GL_TRIANGLE_FAN, 0, 4)
bgl.glBindVertexArray(0)
bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)