1
$\begingroup$

I'm loading a texture into a simple GL_QUAD drawn with OpenGL with the help of bgl and bge.texture modules in Blender. The texture loads but the colour of the texture changes, most of the parts are black, blues are rendered red and so on.

Following is the code for loading the texture:

import bge
import bgl
from bge import logic, texture

def loadTex():
    if objbuf is not None:
        bgl.glEnable(bgl.GL_TEXTURE_2D)
        texBuf = bgl.Buffer(bgl.GL_INT, 1)
        bgl.glGenTextures(1, texBuf)
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, texBuf.to_list()[0])
        bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, 48, 48, 0,\
            bgl.GL_RGBA, bgl.GL_BYTE, objbuf)
        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.glBegin(bgl.GL_QUADS);
        bgl.glNormal3f(0, 0, 2)
        bgl.glTexCoord2d(1, 0); bgl.glVertex3f(1, -1, 1.2)
        bgl.glTexCoord2d(0, 0); bgl.glVertex3f(1, 1, 1.2)
        bgl.glTexCoord2d(0, 1); bgl.glVertex3f(-1, 1, 1.2)
        bgl.glTexCoord2d(1, 1); bgl.glVertex3f(-1, -1, 1.2)
        bgl.glEnd()
        bgl.glDeleteTextures(1, texBuf)
        bgl.glDisable(bgl.GL_TEXTURE_2D)

obj = logic.getCurrentController().owner
if not obj.scene.post_draw:
        # face.png is a 48x48 PNG image
        obj["buf"] = texture.imageToArray(texture.ImageFFmpeg(\
            logic.expandPath("//face.png")), "RGBA")
        objbuf = obj["buf"]
        obj.scene.post_draw = [loadTex]

Here is the original image: original image

and here is the loaded texture: loaded texture

Excuse the mirroring of texture, I used mirrored textured coordinates. Can anyone help me figure this out? Thanks.

$\endgroup$
  • $\begingroup$ Looks like a filter too me. Aren't "bgl.GL_TEXTURE_MIN_FILTER" and Co. doing this for you? Btw. you do not need \ when using ( ) in Python. $\endgroup$ – Monster Apr 27 '16 at 11:44
  • $\begingroup$ @Monster, I don't know much python, thanks for the tip. GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER are supposed to handle the level of detail extracted from the texture when the texture is enlarged or reduced, without them the texture isn't properly mapping over the surface because the surface can be of arbitrary size. For example I see white quads without them. $\endgroup$ – Samik Apr 27 '16 at 14:01
  • $\begingroup$ I can't really tell as I never used BGL or any OpenGL operations at that detail. $\endgroup$ – Monster Apr 28 '16 at 7:32
0
$\begingroup$

I have solved the problem. In the glTexImage2D call the type parameter(8th) needs to be bgl.GL_UNSIGNED_BYTE instead of bgl.GL_BYTE. It's really strange because when I printed the buffer in console with print(obj["buf"]) the output was

Buffer(GL_BYTE, [...])

Here is the rectified code

import bge
import bgl
from bge import logic, texture

def loadTex():
    if objbuf is not None:
        bgl.glEnable(bgl.GL_TEXTURE_2D)
        bgl.glEnable(bgl.GL_BLEND)
        # enable light because blender disables it if no object is in the vicinity
        bgl.glEnable(bgl.GL_LIGHTING)
        bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ONE_MINUS_SRC_ALPHA)
        texBuf = bgl.Buffer(bgl.GL_INT, 1)
        bgl.glGenTextures(1, texBuf)
        bgl.glActiveTexture(bgl.GL_TEXTURE0)
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, texBuf.to_list()[0])
        bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, 48, 48, 0,\
            bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, objbuf)
        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.glBegin(bgl.GL_QUADS);
        bgl.glNormal3f(0, 0, 1)
        bgl.glTexCoord2d(1, 0); bgl.glVertex3f(1, -1, 1)
        bgl.glTexCoord2d(1, 1); bgl.glVertex3f(1, 1, 1)
        bgl.glTexCoord2d(0, 1); bgl.glVertex3f(-1, 1, 1)
        bgl.glTexCoord2d(0, 0); bgl.glVertex3f(-1, -1, 1)
        bgl.glEnd()
        bgl.glDeleteTextures(1, texBuf)
        bgl.glDisable(bgl.GL_LIGHTING)
        bgl.glDisable(bgl.GL_BLEND)
        bgl.glDisable(bgl.GL_TEXTURE_2D)

obj = logic.getCurrentController().owner
if not obj.scene.post_draw:
        # face.png is a 48x48 PNG image
        obj["buf"] = texture.imageToArray(texture.ImageFFmpeg(\
            logic.expandPath("//face.png")), "RGBA")
        objbuf = obj["buf"]
        obj.scene.post_draw = [loadTex]

Here is the result

render

$\endgroup$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.