[SOLVED] Trying to draw images in viewport using BGL


(Dimitris Chloupis) #1

So basically I am trying to draw inside the viewport using a modal operator and adding a draw handler callback function to the space. Basically that the Modal Draw template from inside Blender.

My problem is that this example uses blender image functionality to load the image itself and then load it to opengl / bgl.

I would prefer however not to do this way because I dont want to add new images inside a blend file. So i tried to draw a red rectangle using this code.


buf = Buffer(GL_INT,[768,256])

TextureID = Buffer(GL_INT,[1])
<b>for </b>x <b>in </b>range(0,768):
    <b>for </b>y <b>in </b>range(256):
        buf[x][y]= 150
    x = x + 3
error = []
error.append(glGetError())

glGenTextures(1, TextureID)
error.append(glGetError())
glBindTexture(GL_TEXTURE_2D, TextureID.to_list()[0])
error.append(glGetError())
# GetObject(Bitmap.Handle, SizeOf(Buffer), @ Buffer)
glTexImage2D(GL_TEXTURE_2D, 0, 3, 256,256, 0, GL_RGB, GL_INT, buf)
error.append(glGetError())
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
error.append(glGetError())
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
error.append(glGetError())
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
error.append(glGetError())
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
error.append(glGetError())

glEnable(GL_BLEND)
glEnable(GL_TEXTURE_2D)
error.append(glGetError())
glBegin(GL_QUADS)
glTexCoord2f(0, 0)
glVertex2f(0, 0)
glTexCoord2f(1, 0)
glVertex2f(300,0)
glTexCoord2f(1, 1)
glVertex2f(300, 300)
glTexCoord2f(0, 1)
glVertex2f(0, 300)



glEnd()
error.append(glGetError())

but all I am getting is a black rectangle. Any idea how exactly this could work , what I am doing wrong and how to improve it ?


(Dimitris Chloupis) #2

And after much digging around and a ton of testing the code that works is this




    def load_texture(self,name,scale=0.5):
        currentPath = __file__[0:-11]
        bpy.path.basename(currentPath)
        full_path = currentPath + 'dev/media/graphics/'+name+'.png'
        f = cyclops.png.Reader(full_path)
        f.read()
        f=f.asFloat()
        content = list(f[2])
        buf = Buffer(GL_FLOAT, [len(content), len(content[0])],content)


        self.textures[name]={'dimensions':[f[3]['size'][0],f[3]['size'][1]],
                             'full_path': full_path, 'data': buf,
                             'is_gl_initialised': False, 'scale':scale, 'texture_id':0}
        self.width=self.textures[name]['dimensions'][0]
        self.height=self.textures[name]['dimensions'][1]
        self.activate_texture(name)




        return self.textures[name]


    def activate_texture(self,name):
        self.active_texture = name
        self.width = round(self.textures[name]['dimensions'][0]* self.textures[name]['scale'])
        self.height = round(self.textures[name]['dimensions'][1]* self.textures[name]['scale'])




    def draw(self):
        if (not self.is_hidden):
            self.draw_count = self.draw_count + 1
            # pdb.set_trace()
            at = self.textures[self.active_texture]
            if not at['is_gl_initialised']:


                at['texture_id'] = Buffer(GL_INT, [1])


                glGenTextures(1, at['texture_id'])


                glBindTexture(GL_TEXTURE_2D,at['texture_id'].to_list()[0])




                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, at['dimensions'][0], at['dimensions'][1], 0, GL_RGBA,GL_FLOAT, at['data'])
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
                at['is_gl_initialised']= True
            else:
                glBindTexture(GL_TEXTURE_2D, at['texture_id'].to_list()[0])


            glColor4f(*self.color)
            # pdb.set_trace()


            glEnable(GL_BLEND)
            glEnable(GL_TEXTURE_2D)
            glBegin(GL_QUADS)
            glTexCoord2f(1, 1)
            glVertex2f(self.position[0],self.position[1])
            glTexCoord2f(0, 1)
            glVertex2f((self.position[0]+self.width),self.position[1])
            glTexCoord2f(0, 0)
            glVertex2f((self.position[0]+self.width), (self.position[1]+self.height))
            glTexCoord2f(1, 0)
            glVertex2f(self.position[0], (self.position[1]+self.height))






            glEnd()
            glDisable(GL_TEXTURE_2D)
            glDisable(GL_BLEND)

The main issue is that it does not like it when buffer array is anything but GL_FLOAT , the dimensions of the array are basically [x*4][y], x and y being the pixels and 4 being for floats for RGBA (base colors + transparency)

With this code you no longer need to load the textures inside Blender and then convert them to opengl textures , instead I load them directly to OpengGL (BGL) via PyPNG that can convert a png file to 2 dimensional array of floats in the RGBA format.