im trying to get multi texturing working and have so far got miltiple textures to load using this function
def loadTexture(name):
img = PIL.Image.open(name) # .jpg, .bmp, etc. also work
img_data = numpy.array(list(img.getdata()), numpy.int8)
id = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glBindTexture(GL_TEXTURE_2D, id)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
return id
And I can set the texture to use with this code
glBindTexture(GL_TEXTURE_2D, 1)
glEnable(GL_TEXTURE_2D)
My first attempt has been this:
glBindTexture(GL_TEXTURE_2D, 1)
glEnable(GL_TEXTURE_2D)
glBegin(GL_TRIANGLES)
....
glEnd()
glBindTexture(GL_TEXTURE_2D, 3)
glEnable(GL_TEXTURE_2D)
glBegin(GL_TRIANGLES)
....
glEnd()
So i render the polys twice and select a different texture each time, this seems to work in as much as calling glBindTexture(GL_TEXTURE_2D, n) will select the relivant texture and it will render but there is no blending going on per se, i just see the last selected texture in the render. I've tried adding glEnable(GL_BLEND), but that doesn't seem to do anything.
What I would like to do is to add pixels of the two passes together
How would I go about this?
Are you sure that you need multiple passes? Here is an example of plain old OpenGL multitexturing:
import pygame
from pygame.locals import *
import numpy
import numpy.linalg
from OpenGL.GL import *
from OpenGL.GL.shaders import *
RESOLUTION = (800,600)
POSITIONS = numpy.array([[-1.0, -1.0], [+1.0, -1.0], [-1.0, +1.0], [+1.0, +1.0]], dtype=numpy.float32)
TEXCOORDS = numpy.array([[0.0, 1.0], [1.0, 1.0], [0.0, 0.0], [1.0, 0.0]], dtype=numpy.float32)
from PIL import Image
tex0 = 0
tex1 = 0
def loadTexture(path):
img = Image.open(path)
img = img.convert("RGBA")
img_data = numpy.array(list(img.getdata()), numpy.int8)
texture = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glBindTexture(GL_TEXTURE_2D, texture)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.size[0], img.size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data)
return texture
def init():
global tex0
global tex1
tex0 = loadTexture("texture0.png")
tex1 = loadTexture("texture1.png")
glViewport(0, 0, *RESOLUTION)
aspect = RESOLUTION[0]/float(RESOLUTION[1])
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-aspect, +aspect, -1.0, +1.0, -1.0, +1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0.0, 0.0, 0.0, 1.0);
glVertexPointer(2, GL_FLOAT, 0, POSITIONS);
glEnableClientState(GL_VERTEX_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glTexCoordPointer(2, GL_FLOAT, 0, TEXCOORDS);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, 0, TEXCOORDS);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
def draw():
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
def main():
pygame.init()
screen = pygame.display.set_mode(RESOLUTION, OPENGL | DOUBLEBUF)
init()
while True:
for event in pygame.event.get():
if event.type == QUIT: return
draw()
pygame.display.flip()
if __name__ == "__main__":
main()
Have a look at Texture Combiners, they may enable the type of effect you are looking for. Of course, the state of the art for this kind of thing nowadays are shaders.
Related
I have a scene with a sphere spinning, just like Earth and the Sun. I can activate the lighting over the object but i notice that the light is moving with the object when spin, illuminating the same face ever. I want to set the light on a fixed point so, the illumination will be fixed while the "Earth" spin, giving the effect of day and night.
I know that if an object is rotated, all the "coordinate system" moves, not the object, so, i think that the ligth is fixed to the system. I tried to find the point where initialy the light is placed using trigonometry but without positive results. How can i place the light in a fixed spot to reach the day/night effect?
This is my code:
import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
#<some other libraries imports>
def sup_texture(surf):
rgbsurf = pygame.image.tostring(surf, 'RGB')
textID = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texID)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
surfrc = surf.get_rect()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, surfrc[2], surfrc[3], 0, GL_RGB, GL_UNSIGNED_BYTE, rgbsurf)
return textID
def texture(arch,arch2):
textID = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, textID)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,arch2[0], arch2[1], 0, GL_RGB, GL_UNSIGNED_BYTE, arch)
glGenerateMipmap(GL_TEXTURE_2D)
return textID
def oglprint(sup):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glDisable(GL_LIGHTING)
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, sup)
glBegin(GL_QUADS)
glTexCoord2f(0, 0); glVertex2f(-1, 1)
glTexCoord2f(0, 1); glVertex2f(-1, -1)
glTexCoord2f(1, 1); glVertex2f(1, -1)
glTexCoord2f(1, 0); glVertex2f(1, 1)
glEnd()
glDisable(GL_TEXTURE_2D)
def esfep(vesf,resol,texture,rotpt,punt,tama):
light_ambient = [0.0, 0.0, 0.0, 1.0]
light_diffuse = [1.0, 1.0, 1.0, 1.0]
light_position = [1, 1, 0, 0.0]
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient)
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
glLightfv(GL_LIGHT0, GL_POSITION, light_position)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
rotpt = rotpt + vesf
glOrtho(0,resol[0],resol[1],0,-resol[0],resol[1])
glTranslatef(float(punt[0]),float(punt[1]),-resol[1])
glRotatef(270, 1, 0, 0)
glRotatef(rotpt, 0, 0, 1)
glScalef(1*tama/resol[1],1*tama/resol[1],1*tama/resol[1])
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE )
esf = gluNewQuadric()
gluQuadricTexture(esf, GL_TRUE)
glDisable(GL_DEPTH_TEST)
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, texture)
gluSphere(esf,round(resol[1]/2), 50, 50)
gluDeleteQuadric(esf)
glDisable(GL_TEXTURE_2D)
glDisable(GL_DEPTH_TEST)
return rotpt
pygame.init()
resol = (1366,768)
opcp = pygame.HWSURFACE | pygame.DOUBLEBUF | pygame.OPENGL | pygame.FULLSCREEN
displayG = pygame.display.set_mode(resol,opcp)
display = pygame.Surface(resol)
imgpl = pygame.image.load('texture.jpg')
imgplt = imgpl.get_size()
imgpl = pygame.transform.smoothscale(imgpl,(1000,500))
imgpltd = pygame.image.tostring(imgpl,'RGB',False)
planpres = texture(imgpltd,imgplt)
rotpt = randint(270,360)
timer = pygame.time.Clock()
RE = tab(display)
while True:
#<some pygame stuff and display blitting>
opsurf = pygame.Surface.copy(display)
pantsp = sup_texture(opsurf)
botact = 1
while botact == 1:
timer.tick(20)
oglprint(pantsp)
rotpt = esfep(0.05,resol,planpres,rotpt,(0,resol[1] + resol[1]/4.5),1000) #this is the printing of the sphere.
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
x_mouse, y_mouse = pygame.mouse.get_pos()
dot = (x_mouse,y_mouse)
for x in range(len(RE)):
if RE[x].collidepoint(dot):
#<some stuff>
botact = 0
glDeleteTextures(pantsp)
The light position (GL_POSITION) an direction (GL_SPOT_DIRECTION) is transformed by the current modelview matrix when glLighv is called. Make sure that the model view matrix is the Identity matrix, before calling glLight, but set the transformations to the model view matrix:
def esfep(vesf,resol,texture,rotpt,punt,tama):
light_ambient = [0.0, 0.0, 0.0, 1.0]
light_diffuse = [1.0, 1.0, 1.0, 1.0]
light_position = [1, 1, 0, 0.0]
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient)
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
# set projection matrix
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0,resol[0],resol[1],0,-resol[0],resol[1])
# set model view identity matrix
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
# set light position (multiplied by identity matrix)
glLightfv(GL_LIGHT0, GL_POSITION, light_position)
# set model view transformations
rotpt = rotpt + vesf
glTranslatef(float(punt[0]),float(punt[1]),-resol[1])
glRotatef(270, 1, 0, 0)
glRotatef(rotpt, 0, 0, 1)
glScalef(1*tama/resol[1],1*tama/resol[1],1*tama/resol[1])
# [...]
I tried everything but still I don't get my error. I am trying to put a texture on my sphere object.
"""
Minimal texture on sphere demo
This is demo for showing how to put image
on sphere as texture in PyOpenGL.
"""
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
from PIL import Image
import numpy
def run_scene():
glutInit()
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
glutCreateWindow("Minimal sphere OpenGL")
lightning()
glutDisplayFunc(draw_sphere)
glMatrixMode(GL_PROJECTION)
gluPerspective(40, 1, 1, 40)
glMatrixMode(GL_MODELVIEW)
gluLookAt(0, 0, 10,
0, 0, 0,
0, 1, 0)
glPushMatrix()
glutMainLoop()
return
def lightning():
glEnable(GL_DEPTH_TEST)
glEnable(GL_LIGHTING)
glEnable(GL_BLEND)
glLightfv(GL_LIGHT0, GL_POSITION, [10, 4, 10, 1])
glLightfv(GL_LIGHT0, GL_DIFFUSE, [0.8, 1, 0.8, 1])
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1)
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05)
glEnable(GL_LIGHT0)
return
def draw_sphere():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glPushMatrix()
texture_id = read_texture('mars.png')
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, texture_id)
glEnable(GL_TEXTURE_GEN_S)
glEnable(GL_TEXTURE_GEN_T)
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP)
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP)
glutSolidSphere(1, 50, 50)
glDisable(GL_TEXTURE_2D)
glPopMatrix()
glutSwapBuffers()
return
def read_texture(filename):
img = Image.open(filename)
img_data = numpy.array(list(img.getdata()), numpy.int8)
texture_id = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0,
GL_RGB, GL_UNSIGNED_BYTE, img_data)
return texture_id
if __name__ == '__main__':
run_scene()
This is result of this code, simple green sphere as this:
But this is not my expected result. I want to simply show this texture mars.png on sphere surface:
Help me with this I cannot solve this on my own it seems.
In read_texture() after you generate a texture name you don't bind it. So the subsequent texture related calls are going to the default texture and not your newly created texture.
texture_id = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture_id) # This is what's missing
Also since your image is a PNG image. Then list(img.getdata()) will be a list of tuples containing (R, G, B, A). So when calling glTexImage2D you need to tell that your data is GL_RGBA and not GL_RGB.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0,
GL_RGBA, GL_UNSIGNED_BYTE, img_data)
You can also automate it.
format = GL_RGB if img.mode == "RGB" else GL_RGBA
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0,
format, GL_UNSIGNED_BYTE, img_data)
You can also convert it to not have an alpha channel.
img = img.convert("RGB")
Which of course needs to be done before calling img.getdata().
Now you should see the following:
Also an important note. You're calling read_texture() in draw_sphere(). This means that every time draw_sphere() is called, the image is loaded and a new texture is created. You really don't want to do that. Instead before calling glutMainLoop() call read_texture() and store the result as a global name.
I want to overlay 3d objects on OpenCV feed. I found an example here That uses webcam video as texture in OpenGL. I changed some part so that it works with cv2. Now the output is something strange
CODE
import cv2
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import numpy as np
import sys
#window dimensions
width = 1280
height = 720
nRange = 1.0
global capture
capture = None
def cv2array(im):
h,w,c=im.shape
a = np.fromstring(
im.tostring(),
dtype=im.dtype,
count=w*h*c)
a.shape = (h,w,c)
return a
def init():
#glclearcolor (r, g, b, alpha)
glClearColor(0.0, 0.0, 0.0, 1.0)
glutDisplayFunc(display)
glutReshapeFunc(reshape)
glutKeyboardFunc(keyboard)
glutIdleFunc(idle)
def idle():
#capture next frame
global capture
_,image = capture.read()
cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
#you must convert the image to array for glTexImage2D to work
#maybe there is a faster way that I don't know about yet...
#print image_arr
# Create Texture
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
720,1280,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
image)
cv2.imshow('frame',image)
glutPostRedisplay()
def display():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glEnable(GL_TEXTURE_2D)
#glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
#glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
#glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
#this one is necessary with texture2d for some reason
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
# Set Projection Matrix
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0, width, 0, height)
# Switch to Model View Matrix
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
# Draw textured Quads
glBegin(GL_QUADS)
glTexCoord2f(0.0, 0.0)
glVertex2f(0.0, 0.0)
glTexCoord2f(1.0, 0.0)
glVertex2f(width, 0.0)
glTexCoord2f(1.0, 1.0)
glVertex2f(width, height)
glTexCoord2f(0.0, 1.0)
glVertex2f(0.0, height)
glEnd()
glFlush()
glutSwapBuffers()
def reshape(w, h):
if h == 0:
h = 1
glViewport(0, 0, w, h)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
# allows for reshaping the window without distoring shape
if w <= h:
glOrtho(-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange)
else:
glOrtho(-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def keyboard(key, x, y):
global anim
if key == chr(27):
sys.exit()
def main():
global capture
#start openCV capturefromCAM
capture = cv2.VideoCapture(0)
print capture
capture.set(3,1280)
capture.set(4,720)
glutInit(sys.argv)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
glutInitWindowSize(width, height)
glutInitWindowPosition(100, 100)
glutCreateWindow("OpenGL + OpenCV")
init()
glutMainLoop()
main()
I find it very unlikely that your camera is providing a 720 pixel wide and 1280 pixel high image as you tell to OpenGL here:
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
720,1280, // <---- HERE
0,
GL_RGB,
GL_UNSIGNED_BYTE,
image)
It seems you just mixed up those two parametes, so the data is reinterpreted as such, resulting in the output you got.
I'm trying to get multipass texturing work for me but right now i can get simple texturing to work, can anybody spor whats going wring with the following code. This examples just shows the poly as white, rather than textured.
def loadTexture(name):
img = PIL.Image.open(name) # .jpg, .bmp, etc. also work
img_data = numpy.array(list(img.getdata()), numpy.int8)
id = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
return id
....
tex = loadTexture(/foobar.png)
....
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslate(0.0, 0.0, -600)
glScale(50.0, 50.0, 50.0)
glRotate(90, 0.0, 0.0, 0.0)
glEnable(GL_TEXTURE_2D)
glBindTexture(GL_TEXTURE_2D, tex)
glBegin(GL_TRIANGLES)
....
glEnd()
You must call glBindTexture(GL_TEXTURE_2D, id) when you are setting texture parameters or uploading data:
id = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glBindTexture(GL_TEXTURE_2D, id)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
I'm working on a project using PyOpenGL, and I'm currently attempting to get OpenGL to render a kind of splash screen. My decided solution to this is to draw a textured 2D rectangle. Unfortunately, it appears that no matter what I do, nothing is ever drawn, I just get a black screen (So I guess something is drawn, otherwise it would be a transparent window, but it's definitely not what I want). Here is the pertinent code for my class:
class ClassThing:
def __init__(self):
self.Splash = True
glutInit(sys.argv)
def TexFromPNG(self, filename):
img = Image.open(filename)
img_data = numpy.array(list(img.getdata()), numpy.uint8)
texture = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glBindTexture(GL_TEXTURE_2D, texture)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
return texture
def run(self):
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(256,224)
self.window = glutCreateWindow("GL")
glutDisplayFunc(self.draw)
glClearColor(0,0,0,0)
glEnable(GL_TEXTURE_2D)
glEnable(GL_VERTEX_ARRAY)
self.MainTex = glGenTextures(1)
self.SplashTex = self.TexFromPNG("Resources/Splash.png")
glutMainLoop()
def draw(self):
glClear(GL_COLOR_BUFFER_BIT)
glLoadIdentity()
if self.Splash:
glBindTexture(GL_TEXTURE_2D, self.SplashTex)
else:
glBindTexture(GL_TEXTURE_2D, self.MainTex)
glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
Varray = numpy.array([[0,0],[0,256],[224,256],[224,0]],numpy.uint16)
glVertexPointer(2,GL_SHORT,0,Varray)
indices = [0,1,2,3]
glDrawElements(GL_QUADS,1,GL_UNSIGNED_SHORT,indices)
glFlush()
thing = ClassThing()
thing.run()
As I said, just that nets me with a totally black screen. It feels like I may be missing some kind of initialization or enabling, but I don't know what else I would need to enable.
As an aside, apparently glVertexPointer is deprecated, how would I run glDrawElements without it? Is there some kind of vertex generation you can do similar to texture generation or what?
Could it be because you called glGenTextures(1) twice? You assigned it to texture in TexFromPNG and assigned it to self.MainTex in run.
You need to supply texture coordinates as well, otherwise OpenGL doesn't know how to map the texture to your quad — you also could use automatic texture coordinate generation, but in your case just specifying coordinates is simpler. In addition you also need to specify viewport and projection
class ClassThing:
def __init__(self):
self.Splash = True
def TexFromPNG(self, filename):
img = Image.open(filename)
img_data = numpy.array(list(img.getdata()), numpy.uint8)
texture = glGenTextures(1)
glPixelStorei(GL_UNPACK_ALIGNMENT,1)
glBindTexture(GL_TEXTURE_2D, texture)
# Texture parameters are part of the texture object, so you need to
# specify them only once for a given texture object.
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
return texture
def run(self):
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(256,224)
self.window = glutCreateWindow("GL")
glutReshapeFunc(self.reshape)
glutDisplayFunc(self.draw)
self.MainTex = glGenTextures(1)
self.SplashTex = self.TexFromPNG("Resources/Splash.png")
glutMainLoop()
def reshape(self, width, height):
self.width = width
self.height = height
glutPostRedisplay();
def draw(self):
glViewport(0, 0, self.width, self.height)
glClearDepth(1) # just for completeness
glClearColor(0,0,0,0)
glClear(GL_COLOR_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, 1, 0, 1, -1, 1)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity()
if self.Splash:
glBindTexture(GL_TEXTURE_2D, self.SplashTex)
else:
glBindTexture(GL_TEXTURE_2D, self.MainTex)
# it's a good idea to enable state right before you need it
# there's no such thing like global state intialization in
# OpenGL
glEnable(GL_TEXTURE_2D)
# vertex arrays must be enabled using glEnableClientState
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
Varray = numpy.array([[0,0],[0,1],[1,1],[1,0]],numpy.float)
glVertexPointer(2,GL_FLOAT,0,Varray)
glTexCoordPointer(2,GL_FLOAT,0,Varray)
indices = [0,1,2,3]
glDrawElements(GL_QUADS,1,GL_UNSIGNED_SHORT,indices)
# This implies a glFinish, which includes a glFlush
glutSwapBuffers()
# GLUT initialization in program global, so initialize it on
# the process level. It might be
glutInit(sys.argv)
thing = ClassThing()
thing.run()