Adding different textures to differents objects using PyOpenGL - python

I feel kind of stupid for asking this, but I've tried almost every example and proved every solution.
I'm trying to create a endless runner game using pyOpenGL and pygames, and facing many troubles, one of them is the following: I'm trying to render 2 textures for differents objects using pyOpenGL glBindTexture(GL_TEXTURE_2D, id). I have a main object, that is a cube, called cube and I also have an array of cube. I want to render a texture in cube and a different one all the cubes in the array, but everytime I try to do this the last texture "rendered" overlaps the previus one. What could I do?
Here is my code:
# Execute with Python 3
import os
import pygame
import random
import math
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
camera_x = 0
camera_z = 0
camera_y = 0
x = 0
Vertices = [
[1, -1, 1],
[-1, -1, 1],
[-1, -1, -1],
[1, -1, -1],
[1, 1, -1],
[-1, 1, -1],
[-1, 1, 1],
[1, 1, 1]
]
textureSurface = pygame.image.load('./textures/ursa.png'), pygame.image.load('./textures/caja.png')
textureData = pygame.image.tostring(textureSurface[0], "RGBA"), pygame.image.tostring(textureSurface[1], "RGBA")
width = textureSurface[0].get_width(), textureSurface[1].get_width()
height = textureSurface[0].get_height(), textureSurface[1].get_height()
class Ground:
global camera_z
def __init__(self):
self.ground_vertices = (
(-11, -2.01, 20),
(11, -2.01, 20),
(11, -2.01, -300),
(-11, -2.01, -300)
)
def draw(self):
glPushMatrix()
glTranslatef(0, 0, camera_z)
glBegin(GL_QUADS)
for vertex in self.ground_vertices:
glColor3fv((0, 0.5, 0.5))
glVertex3fv(vertex)
glEnd()
glPopMatrix()
class Cube:
def __init__(self, texture=False):
self.vertices = [
[1, -1, 1],
[-1, -1, 1],
[-1, -1, -1],
[1, -1, -1],
[1, 1, -1],
[-1, 1, -1],
[-1, 1, 1],
[1, 1, 1]
]
self.surfaces = (
(0, 1, 6, 7),
(0, 1, 2, 3),
(0, 3, 4, 7),
(1, 2, 6, 5),
(2, 3, 4, 5),
(4, 5, 6, 7)
)
self.colors = (
(105 / 255, 210 / 255, 231 / 255),
(167 / 255, 219 / 255, 216 / 255),
(224 / 255, 228 / 255, 204 / 255),
(243 / 255, 134 / 255, 48 / 255)
)
self.vertices_texture = (
(0.0, 0.0),
(1.0, 0.0),
(1.0, 1.0),
(0.0, 1.0),
)
self.texture = texture
self.center = [0, 0, 0]
def draw(self):
if self.texture:
glEnable(GL_TEXTURE_2D)
glColor3f(1, 1, 1)
glBegin(GL_QUADS)
if self.texture:
for surface in self.surfaces:
for x, vertex in enumerate(surface):
glTexCoord2fv(self.vertices_texture[x])
glVertex3fv(self.vertices[vertex])
else:
for surface in self.surfaces:
for x, vertex in enumerate(surface):
glColor3fv(self.colors[x])
glVertex3fv(self.vertices[vertex])
self.center = [
(self.vertices[2][0]+self.vertices[7][0])/2,
(self.vertices[2][1]+self.vertices[7][1])/2,
(self.vertices[2][2]+self.vertices[7][2])/2
]
glEnd()
if self.texture:
glDisable(GL_TEXTURE_2D)
def set_vertices(self, max_distance, min_distance=-40):
x_value_change = random.randrange(-10, 10)
y_value_change = -1
z_value_change = random.randrange(-1 * max_distance, min_distance)
new_vertices = []
for vertex in Vertices:
new_vertex = []
new_x = vertex[0] + x_value_change
new_y = vertex[1] + y_value_change
new_z = vertex[2] + z_value_change
new_vertex.append(new_x)
new_vertex.append(new_y)
new_vertex.append(new_z)
new_vertices.append(new_vertex)
self.vertices = new_vertices
def rotate(self):
glPushMatrix()
glRotatef(25, 1, 0, 0)
glPopMatrix()
def loadTexture(self, file):
glEnable(GL_TEXTURE_2D)
id = [0]*2
glGenTextures(2, id)
if file == 0:
glBindTexture(GL_TEXTURE_2D, id[0])
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width[0], height[0], 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData[0])
if file == 1:
glBindTexture(GL_TEXTURE_2D, id[1])
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width[1], height[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData[1])
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glDisable(GL_TEXTURE_2D)
#return texid
def leave(event):
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
quit()
def main():
global camera_x, camera_y, camera_z, x
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL | OPENGLBLIT)
max_distance = 300
gluPerspective(45, (display[0] / display[1]), 0.1, max_distance)
glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glTranslatef(0, -10 / 2.4, -50)
ground = Ground()
cube = Cube(True)
cube.loadTexture(0)
my_cubes = []
for i in range(20):
tmp_cube = Cube(True)
tmp_cube.loadTexture(1)
tmp_cube.set_vertices(max_distance)
my_cubes.append(tmp_cube)
while True:
for event in pygame.event.get():
leave(event)
# movInverse(event)
M = glGetDoublev(GL_MODELVIEW_MATRIX)
# print(M)
camera_x = M[3][0]
camera_y = M[3][1]
camera_z = M[3][2]
glTranslatef(0, 0, 1.5)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
ground.draw()
glPushMatrix()
if(math.fabs(x) < 11):
glTranslatef(x, -1.5, camera_z-20)
glScalef(1 / 2, 1 / 2, 0)
cube.draw()
glPopMatrix()
for tmp_cube in my_cubes:
tmp_cube.draw()
print(tmp_cube.center)
for tmp_cube in my_cubes:
if camera_z <= tmp_cube.vertices[0][2]:
new_max = int(-1 * (camera_z - max_distance * 2))
tmp_cube.set_vertices(new_max, int(camera_z - max_distance))
pygame.display.flip()
if __name__ == '__main__':
main()
The method loadTexture is supposed to choose what texture is going to apply, but it doesn't, I don't know why. I hope someone could help me. Thanks!

When each cube has its own texture, then add an attribute self.id , which holds the texture for the cube.
Create this texture object and load the texture in the method loadTexture():
class Cube:
# [...]
def loadTexture(self, file):
self.id = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, self.id)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width[file], height[file], 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData[file])
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
Bind the texture before the cube is draw (glBindTexture):
class Cube:
# [...]
def draw(self):
if self.texture:
glEnable(GL_TEXTURE_2D)
glColor3f(1, 1, 1)
glBindTexture(GL_TEXTURE_2D, self.id) # <-----
glBegin(GL_QUADS)
# [...]

Related

Pyopengl: Texture color not the same while being rendered

The color of the texture changes when it is being rendered by OpenGL, and I have no other color predefined in the code, except during the glClear and once during the cube() function. Note: changing the glTexImage2D format parameter from GL_RGB to GL_BGR only swaps colors.
Original texture:
Rendered Texture:
Full code:
import time
import numpy
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from PIL import Image
width = 500
height = 500
vertices = [(-1, -1, -1), (1, -1, -1), (1, 1, -1), (-1, 1, -1), (-1, -1, 1), (1, -1, 1), (1, 1, 1), (-1, 1, 1)]
faces = [(4, 0, 3, 7), (1, 0, 4, 5), (0, 1, 2, 3), (1, 5, 6, 2), (3, 2, 6, 7), (5, 4, 7, 6)]
colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (1, 0, 1), (0, 1, 1)]
def cube():
glRotatef(1, 3, 1, 1)
glColor3fv((1, 1, 1))
glBegin(GL_QUADS)
for i, face in enumerate(faces):
for surftex, vertex in enumerate(face):
if surftex == 0:
glTexCoord2f(0.0, 0.0)
elif surftex == 1:
glTexCoord2f(0.0, 1.0)
elif surftex == 2:
glTexCoord2f(1.0, 1.0)
elif surftex == 3:
glTexCoord2f(1.0, 0.0)
glVertex3fv(vertices[vertex])
glEnd()
def textureBind():
img = Image.open('Image.png')
img_data = numpy.array(list(img.getdata()), numpy.int8)
glEnable(GL_TEXTURE_2D)
texture_id = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture_id)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
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_RGB, GL_FLOAT, img_data)
return texture_id
def showScreen():
global width, height
glClearColor(0, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
cube()
glEnable(GL_DEPTH_TEST)
glutSwapBuffers()
def mouseTracker(mousex, mousey):
print(f"Mouse pos: {mousex}, {mousey}")
def reshapeWindow(x, y):
global width, height
width = x
height = y
print(x, y)
glutReshapeWindow(width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, (width / height), 0.0001, 1000)
glViewport(0, 0, width, height)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(0, 0, -5)
glutInit()
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(500, 500)
wind = glutCreateWindow("OpenGL")
glutDisplayFunc(showScreen)
glutIdleFunc(showScreen)
glutMotionFunc(mouseTracker)
glutPassiveMotionFunc(mouseTracker)
glutReshapeFunc(reshapeWindow)
gluPerspective(45, (width / height), 0.0001, 1000)
textureBind()
while True:
glutMainLoopEvent()
glutPostRedisplay()
time.sleep(0.001)
The format of this texture is BGR, but not RGB. Use GL_BGR instead of GL_RGB:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.size[0], img.size[1],0, GL_RGB, GL_FLOAT, img_data)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.size[0], img.size[1],
0, GL_BGR, GL_FLOAT, img_data)
The format of the image is stored in the mode attribute of the PIL.Image.Image object. See Mode.

How to set a ligth fixed when a sphere is spinning?

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])
# [...]

How do I add an image as texture of my 3D cube in pyopengl

How do I add an image as texture in my cube:
I want to add my self-provided image as the surfaces of my cube while still having some lighting
I am using Visual Studio Code as my compiler
here is the code I copied:
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
verticies = (
( 1, -1, -1), # 0
( 1, 1, -1), # 1
(-1, 1, -1), # 2
(-1, -1, -1), # 3
( 1, -1, 1), # 4
( 1, 1, 1), # 5
(-1, -1, 1), # 6
(-1, 1, 1), # 7
)
surfaces = (
(0,1,2,3),
(3,2,7,6),
(6,7,5,4),
(4,5,1,0),
(1,5,7,2),
(4,0,3,6),
)
normals = [
( 0, 0, -1), # surface 0
(-1, 0, 0), # surface 1
( 0, 0, 1), # surface 2
( 1, 0, 0), # surface 3
( 0, 1, 0), # surface 4
( 0, -1, 0) # surface 5
]
colors = (
(1,1,1),
(0,1,0),
(0,0,1),
(0,1,0),
(0,0,1),
(1,0,1),
(0,1,0),
(1,0,1),
(0,1,0),
(0,0,1),
)
edges = (
(0,1),
(0,3),
(0,4),
(2,1),
(2,3),
(2,7),
(6,3),
(6,4),
(6,7),
(5,1),
(5,4),
(5,7),
)
def Cube():
glBegin(GL_QUADS)
for i_surface, surface in enumerate(surfaces):
x = 0
glNormal3fv(normals[i_surface])
for vertex in surface:
x+=1
glColor3fv(colors[x])
glVertex3fv(verticies[vertex])
glEnd()
glColor3fv(colors[0])
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(verticies[vertex])
glEnd()
def main():
global surfaces
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
clock = pygame.time.Clock()
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glTranslatef(0, 0, -5)
#glLight(GL_LIGHT0, GL_POSITION, (0, 0, 1, 0)) # directional light from the front
glLight(GL_LIGHT0, GL_POSITION, (5, 5, 5, 1)) # point light from the left, top, front
glLightfv(GL_LIGHT0, GL_AMBIENT, (0, 0, 0, 1))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (1, 1, 1, 1))
glEnable(GL_DEPTH_TEST)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE )
glRotatef(1, 3, 1, 1)
Cube()
glDisable(GL_LIGHT0)
glDisable(GL_LIGHTING)
glDisable(GL_COLOR_MATERIAL)
pygame.display.flip()
clock.tick(60)
main()
The program displays a rotating cube with just colors as its surface
how can I change the surface?
Define the array of texture coordinates:
textureCoordinates = ((0, 0), (0, 1), (1, 1), (1, 0))
Set a white color, but specify the texture coordinates when you draw the cube:
def Cube():
glColor3f(1, 1, 1)
glBegin(GL_QUADS)
for i_surface, surface in enumerate(surfaces):
x = 0
glNormal3fv(normals[i_surface])
for i_vertex, vertex in enumerate(surface):
x+=1
#
glTexCoord2fv(textureCoordinates[i_vertex])
glVertex3fv(verticies[vertex])
glEnd()
Load an image with pygame.image.load(), create the texture object and enable 2 dimensional texturing before the application loop:
def main():
# [...]
image = pygame.image.load('image.png')
datas = pygame.image.tostring(image, 'RGBA')
texID = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texID)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.get_width(), image.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, datas)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glEnable(GL_TEXTURE_2D)
while True:
# [...]
Complete example:
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
verticies = (
( 1, -1, -1), # 0
( 1, 1, -1), # 1
(-1, 1, -1), # 2
(-1, -1, -1), # 3
( 1, -1, 1), # 4
( 1, 1, 1), # 5
(-1, -1, 1), # 6
(-1, 1, 1), # 7
)
textureCoordinates = ((0, 0), (0, 1), (1, 1), (1, 0))
surfaces = (
(0,1,2,3),
(3,2,7,6),
(6,7,5,4),
(4,5,1,0),
(1,5,7,2),
(4,0,3,6),
)
normals = [
( 0, 0, -1), # surface 0
(-1, 0, 0), # surface 1
( 0, 0, 1), # surface 2
( 1, 0, 0), # surface 3
( 0, 1, 0), # surface 4
( 0, -1, 0) # surface 5
]
colors = (
(1,1,1),
(0,1,0),
(0,0,1),
(0,1,0),
(0,0,1),
(1,0,1),
(0,1,0),
(1,0,1),
(0,1,0),
(0,0,1),
)
edges = (
(0,1),
(0,3),
(0,4),
(2,1),
(2,3),
(2,7),
(6,3),
(6,4),
(6,7),
(5,1),
(5,4),
(5,7),
)
def Cube():
glColor3f(1, 1, 1)
glBegin(GL_QUADS)
for i_surface, surface in enumerate(surfaces):
x = 0
glNormal3fv(normals[i_surface])
for i_vertex, vertex in enumerate(surface):
x+=1
#
glTexCoord2fv(textureCoordinates[i_vertex])
glVertex3fv(verticies[vertex])
glEnd()
glColor3fv(colors[0])
glBegin(GL_LINES)
for edge in edges:
for vertex in edge:
glVertex3fv(verticies[vertex])
glEnd()
def main():
global surfaces
pygame.init()
display = (400, 300)
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
clock = pygame.time.Clock()
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
glTranslatef(0, 0, -5)
#glLight(GL_LIGHT0, GL_POSITION, (0, 0, 1, 0)) # directional light from the front
glLight(GL_LIGHT0, GL_POSITION, (5, 5, 5, 1)) # point light from the left, top, front
glLightfv(GL_LIGHT0, GL_AMBIENT, (0, 0, 0, 1))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (1, 1, 1, 1))
glEnable(GL_DEPTH_TEST)
image = pygame.image.load('image.png')
datas = pygame.image.tostring(image, 'RGBA')
texID = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texID)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.get_width(), image.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, datas)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glEnable(GL_TEXTURE_2D)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE )
glRotatef(1, 3, 1, 1)
Cube()
glDisable(GL_LIGHT0)
glDisable(GL_LIGHTING)
glDisable(GL_COLOR_MATERIAL)
pygame.display.flip()
clock.tick(60)
main()

Texture arrays in OpenGL

I am working on a project and I need to use texture arrays to apply textures. I have asked many questions about this, none of which I got an answer I was completely satisfied with (Get access to later versions of GLSL , OpenGL: Access Array Texture in GLSL , and OpenGL: How would I implement texture arrays?) so I'm asking a more broad question to hopefully get a response. Anyways, How would I texture an object in OpenGL (PyOpenGL more specifically, but it's fine if you put your answer in C++). I already have a way to load the texture arrays, just not a way to apply it. This is the desired result:
Image from opengl-tutorial
and this is what I currently have for loading array textures:
def load_texture_array(path,width,height):
teximg = pygame.image.load(path)
texels = teximg.get_buffer().raw
texture = GLuint(0)
layerCount = 6
mipLevelCount = 1
glGenTextures(1, texture)
glBindTexture(GL_TEXTURE_2D_ARRAY, texture)
glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipLevelCount, GL_RGBA8, width, height, layerCount)
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, layerCount, GL_RGBA, GL_UNSIGNED_BYTE, texels)
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
TLDR: How would I apply textures to objects in OpenGL using texture arrays?
I will happily provide any other information if necessary.
If you want to use a 2D Array Texture for a cube, each of the 6 textures for the 6 side must be the same size.
You can lookup the texture by 3 dimensional texture coordinates. The 3rd component of the texture coordinate is the index of the 2d texture in the 2d texture array.
Hence the texture coordinates for the 6 sides are
0: [(0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0)]
1: [(0, 0, 1), (1, 0, 1), (1, 1, 1), (0, 1, 1)]
2: [(0, 0, 2), (1, 0, 2), (1, 1, 2), (0, 1, 2)]
3: [(0, 0, 3), (1, 0, 3), (1, 1, 3), (0, 1, 3)]
4: [(0, 0, 4), (1, 0, 4), (1, 1, 4), (0, 1, 4)]
5: [(0, 0, 5), (1, 0, 5), (1, 1, 5), (0, 1, 5)]
Get the 3 dimensional texture coordinate attribute in the vertex shader and pass it to the fragment shader:
in a_uv;
out v_uv;
// [...]
void main()
{
v_uv = a_uv;
// [...]
}
Use the 3 dimensional texture coordinate to look up the sampler2DArray in the fragment shader:
out v_uv;
uniform sampler2DArray u_texture;
// [...]
void main()
{
vec4 texture(u_texture, v_uv.xyz);
// [...]
}
Create a GL_TEXTURE_2D_ARRAY and use glTexSubImage3D to load 6 2-dimensional images to the 6 planes of the 2D Array Texture. In the following image_planes is a list with the 6 2-dimensional image planes:
tex_obj = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D_ARRAY, self.tex_obj)
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, sizeX, sizeY, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, None)
for i in range(6):
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, sizeX, sizeY, 1, GL_RGBA, GL_UNSIGNED_BYTE, image_planes[i])
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
See also PyGame and OpenGL 4.
Minimal example:
import os, math, ctypes
import glm
from OpenGL.GL import *
from OpenGL.GL.shaders import *
from OpenGL.arrays import *
import pygame
pygame.init()
image_path = r"images"
image_names = ["banana64.png", "apple64.png", "fish64.png", "rocket64.png", "ice64.png", "boomerang64.png"]
image_planes = [
(GLubyte * 4)(255, 0, 0, 255), (GLubyte * 4)(0, 255, 0, 255), (GLubyte * 4)(0, 0, 255, 255),
(GLubyte * 4)(255, 255, 0, 255), (GLubyte * 4)(0, 255, 255, 255), (GLubyte * 4)(255, 0, 255, 255)]
image_size = (1, 1)
for i, filename in enumerate(image_names):
try:
image = pygame.image.load(os.path.join(image_path, filename))
image_size = image.get_size()
image_planes[i] = pygame.image.tostring(image, 'RGBA')
except:
pass
class MyWindow:
__glsl_vert = """
#version 130
in vec3 a_pos;
in vec3 a_nv;
in vec3 a_uv;
out vec3 v_pos;
out vec3 v_nv;
out vec3 v_uv;
uniform mat4 u_proj;
uniform mat4 u_view;
uniform mat4 u_model;
void main()
{
mat4 model_view = u_view * u_model;
mat3 normal = mat3(model_view);
vec4 view_pos = model_view * vec4(a_pos.xyz, 1.0);
v_pos = view_pos.xyz;
v_nv = normal * a_nv;
v_uv = a_uv;
gl_Position = u_proj * view_pos;
}
"""
__glsl_frag = """
#version 130
out vec4 frag_color;
in vec3 v_pos;
in vec3 v_nv;
in vec3 v_uv;
uniform sampler2DArray u_texture;
void main()
{
vec3 N = normalize(v_nv);
vec3 V = -normalize(v_pos);
float ka = 0.1;
float kd = max(0.0, dot(N, V)) * 0.9;
vec4 color = texture(u_texture, v_uv.xyz);
frag_color = vec4(color.rgb * (ka + kd), color.a);
}
"""
def __init__(self, w, h):
self.__caption = 'OpenGL Window'
self.__vp_size = [w, h]
pygame.display.gl_set_attribute(pygame.GL_DEPTH_SIZE, 24)
self.__screen = pygame.display.set_mode(self.__vp_size, pygame.DOUBLEBUF| pygame.OPENGL)
self.__program = compileProgram(
compileShader( self.__glsl_vert, GL_VERTEX_SHADER ),
compileShader( self.__glsl_frag, GL_FRAGMENT_SHADER ),
)
self.___attrib = { a : glGetAttribLocation (self.__program, a) for a in ['a_pos', 'a_nv', 'a_uv'] }
print(self.___attrib)
self.___uniform = { u : glGetUniformLocation (self.__program, u) for u in ['u_model', 'u_view', 'u_proj'] }
print(self.___uniform)
v = [[-1,-1,1], [1,-1,1], [1,1,1], [-1,1,1], [-1,-1,-1], [1,-1,-1], [1,1,-1], [-1,1,-1]]
n = [[0,0,1], [1,0,0], [0,0,-1], [-1,0,0], [0,1,0], [0,-1,0]]
e = [[0,1,2,3], [1,5,6,2], [5,4,7,6], [4,0,3,7], [3,2,6,7], [1,0,4,5]]
t = [[0, 0], [1, 0], [1, 1], [0, 1]]
index_array = [si*4+[0, 1, 2, 0, 2, 3][vi] for si in range(6) for vi in range(6)]
attr_array = []
for si in range(len(e)):
for i, vi in enumerate(e[si]):
attr_array += [*v[vi], *n[si], *t[i], si]
self.__no_vert = len(attr_array) // 10
self.__no_indices = len(index_array)
vertex_attributes = (ctypes.c_float * len(attr_array))(*attr_array)
indices = (ctypes.c_uint32 * self.__no_indices)(*index_array)
self.__vao = glGenVertexArrays(1)
self.__vbo, self.__ibo = glGenBuffers(2)
glBindVertexArray(self.__vao)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.__ibo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, self.__vbo)
glBufferData(GL_ARRAY_BUFFER, vertex_attributes, GL_STATIC_DRAW)
float_size = ctypes.sizeof(ctypes.c_float)
glVertexAttribPointer(self.___attrib['a_pos'], 3, GL_FLOAT, False, 9*float_size, None)
glVertexAttribPointer(self.___attrib['a_nv'], 3, GL_FLOAT, False, 9*float_size, ctypes.c_void_p(3*float_size))
glVertexAttribPointer(self.___attrib['a_uv'], 3, GL_FLOAT, False, 9*float_size, ctypes.c_void_p(6*float_size))
glEnableVertexAttribArray(self.___attrib['a_pos'])
glEnableVertexAttribArray(self.___attrib['a_nv'])
glEnableVertexAttribArray(self.___attrib['a_uv'])
glEnable(GL_DEPTH_TEST)
glUseProgram(self.__program)
glActiveTexture(GL_TEXTURE0)
sizeX, sizeY = image_size
self.tex_obj = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D_ARRAY, self.tex_obj)
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, sizeX, sizeY, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, None)
for i in range(6):
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, sizeX, sizeY, 1, GL_RGBA, GL_UNSIGNED_BYTE, image_planes[i])
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
def run(self):
self.__starttime = 0
self.__starttime = self.elapsed_ms()
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
self.__mainloop()
pygame.display.flip()
pygame.quit()
def elapsed_ms(self):
return pygame.time.get_ticks() - self.__starttime
def __mainloop(self):
proj, view, model = glm.mat4(1), glm.mat4(1), glm.mat4(1)
aspect = self.__vp_size[0]/self.__vp_size[1]
proj = glm.perspective(glm.radians(90.0), aspect, 0.1, 10.0)
view = glm.lookAt(glm.vec3(0,-3,0), glm.vec3(0, 0, 0), glm.vec3(0,0,1))
angle1 = self.elapsed_ms() * math.pi * 2 / 5000.0
angle2 = self.elapsed_ms() * math.pi * 2 / 7333.0
model = glm.rotate(model, angle1, glm.vec3(1, 0, 0))
model = glm.rotate(model, angle2, glm.vec3(0, 1, 0))
glUniformMatrix4fv(self.___uniform['u_proj'], 1, GL_FALSE, glm.value_ptr(proj) )
glUniformMatrix4fv(self.___uniform['u_view'], 1, GL_FALSE, glm.value_ptr(view) )
glUniformMatrix4fv(self.___uniform['u_model'], 1, GL_FALSE, glm.value_ptr(model) )
glClearColor(0.2, 0.3, 0.3, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glDrawElements(GL_TRIANGLES, self.__no_indices, GL_UNSIGNED_INT, None)
window = MyWindow(800, 600)
window.run()

May anyone explain to me why the texture doesn't show? [PyOpenGL]

The relevant methods to see are: init, genTexture, onDisplayEvent and table_leg_model.
The 'wood1.png' is a 64x64 image.
Code :
import Image
from math import cos
from math import pi
from math import sin
from numpy import array
from numpy import uint8
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from sys import argv
# Classes ----------------------------------------------------------------------
class AppGL(object):
def __init__(self, title, position=(100, 100), size=(400, 400)):
# Properties -----------------------------------------------------------
self.angle_delta = 4.0
self.position = position
self.rotateX = [0, 1.0, 0.0, 0.0]
self.rotateY = [0, 0.0, 1.0, 0.0]
self.size = size
self.translate = [0.0, 0.0, 0.0]
self.textures_index = {
'wood1': 0,
}
self.textures = array([0] * len(self.textures_index), uint8)
#-----------------------------------------------------------------------
# General initialization
glClearColor(0.0, 0.0, 0.0, 1.0)
glEnable(GL_DEPTH_TEST)
glEnable(GL_TEXTURE_2D)
glGenTextures(len(self.textures), self.textures)
self.genTexture('wood1', 'textures/wood1.png')
#-----------------------------------------------------------------------
# GLUT initialization --------------------------------------------------
glutInit(argv)
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowPosition(*self.position)
glutInitWindowSize(*self.size)
glutCreateWindow(title)
#-----------------------------------------------------------------------
# Callbacks ------------------------------------------------------------
glutDisplayFunc(self.onDisplayEvent)
glutKeyboardFunc(self.onKeyEvent)
glutMotionFunc(self.onMouseMotionEvent)
glutMouseFunc(self.onMouseButtonEvent)
glutReshapeFunc(self.onReshapeEvent)
glutSpecialFunc(self.onSpecialKeyEvent)
#-----------------------------------------------------------------------
# Arrays ---------------------------------------------------------------
data = []
#data.extend(table_model(0.4, 40))
data.extend(table_leg_model())
#data.extend(table_model(0.2, 40))
glInterleavedArrays(GL_T2F_V3F, 0, array(data, "f"))
#-----------------------------------------------------------------------
def genTexture(self, index, path):
img = Image.open(path)
texture_data = array(list(img.getdata()), uint8)
glBindTexture(GL_TEXTURE_2D, self.textures[self.textures_index[index]])
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, texture_data)
def onDisplayEvent(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
gluLookAt(0, 0, 4, 0, 0, -1, 0, 1, 0)
glTranslatef(*self.translate)
glRotatef(*self.rotateX)
glRotatef(*self.rotateY)
# Visual scene ---------------------------------------------------------
glPushMatrix()
# Table -----------------------~
#glDrawElements(GL_POLYGON, 39, GL_UNSIGNED_INT, array(xrange(0, 80, 2), "d"))
#glDrawElements(GL_POLYGON, 39, GL_UNSIGNED_INT, array(xrange(1, 80, 2), "d"))
#glDrawElements(GL_QUAD_STRIP, 80, GL_UNSIGNED_INT, array(xrange(0, 80), "d"))
getMatrixHead()
glTranslatef(-0.1, -0.1, 0)
#glDrawElements(GL_QUAD_STRIP, 10, GL_UNSIGNED_INT, array(xrange(80, 90), "d"))
glDrawElements(GL_QUAD_STRIP, 10, GL_UNSIGNED_INT, array(xrange(0, 10), "d"))
#getMatrixHead()
#glTranslatef(0, 0, 1)
#glDrawElements(GL_POLYGON, 39, GL_UNSIGNED_INT, array(xrange(90, 170, 2), "d"))
#glDrawElements(GL_POLYGON, 39, GL_UNSIGNED_INT, array(xrange(91, 170, 2), "d"))
#glDrawElements(GL_QUAD_STRIP, 80, GL_UNSIGNED_INT, array(xrange(90, 170), "d"))
glPopMatrix()
#-----------------------------------------------------------------------
glutSwapBuffers()
def onKeyEvent(self, key, x, y):
change = True
if key == 'a':
self.translate[0] += 1
elif key == 'd':
self.translate[0] -= 1
elif key == 's':
self.translate[1] += 1
elif key == 'w':
self.translate[1] -= 1
elif key == 'q':
self.translate[2] += 1
elif key == 'e':
self.translate[2] -= 1
else:
change = False
if change: glutPostRedisplay()
def onMouseMotionEvent(self, x, y):
pass
def onMouseButtonEvent(self, button, state, x, y):
pass
def onReshapeEvent(self, width, height):
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, width / height, 1.0, 100.0)
glMatrixMode(GL_MODELVIEW)
def onSpecialKeyEvent(self, key, x, y):
change = True
if key == GLUT_KEY_UP:
self.rotateX[0] += self.angle_delta
elif key == GLUT_KEY_DOWN:
self.rotateX[0] -= self.angle_delta
elif key == GLUT_KEY_LEFT:
self.rotateY[0] += self.angle_delta
elif key == GLUT_KEY_RIGHT:
self.rotateY[0] -= self.angle_delta
else:
change = False
if change: glutPostRedisplay()
def run(self):
glutMainLoop()
#-------------------------------------------------------------------------------
# Functions --------------------------------------------------------------------
def getMatrixHead():
glPopMatrix()
glPushMatrix()
def table_model(radius, number_of_points):
delta = 2 * pi / (number_of_points - 1)
points = []
for i in xrange(number_of_points):
points.extend((radius * cos(i * delta), radius * sin(i * delta), 0.05))
points.extend((radius * cos(i * delta), radius * sin(i * delta), 0))
return points
def table_leg_model():
return (
0, 0, 0, 0.2, 0,
0, 1, 0, 0.2, 1.0,
1, 0, 0, 0, 0,
1, 1, 0, 0, 1.0,
#0, 0, 0.2, 0, 0,
#0, 1, 0.2, 0, 1.0,
#1, 0, 0.2, 0.2, 0,
#1, 1, 0.2, 0.2, 1.0,
#0, 0, 0, 0.2, 0,
#0, 1, 0, 0.2, 1.0,
)
#-------------------------------------------------------------------------------
# Main -------------------------------------------------------------------------
if __name__ == '__main__':
AppGL("Moe's Tavern", (300, 100), (800, 600)).run()
#-------------------------------------------------------------------------------
The source code can also be found here ~> https://github.com/EPadronU/TavernGL/blob/master/appgl.py
I'll just run down the list of what stroke me curious:
The function getMatrixHead makes no sense, at least the naming. At best it will just drop what's been on the stack and make a copy of what's below.
Then you make the typical newbie error of trying to "initialize" OpenGL. Don't do that. Except for loading textures or VBO data make OpenGL calls only from the display function and nowhere else. If you made a backtrace whenever a OpenGL function is called it should only happen because ultimately because display was called. If you had done it that way you'd not have made OpenGL called before there was an actual OpenGL context: Only after a OpenGL context has been created OpenGL calls have an effect. If using GLUT that's after calling glutCreateWindow
Now look at that code:
glEnable(GL_DEPTH_TEST)
glEnable(GL_TEXTURE_2D)
glGenTextures(len(self.textures), self.textures)
self.genTexture('wood1', 'textures/wood1.png')
#-----------------------------------------------------------------------
# GLUT initialization --------------------------------------------------
glutInit(argv)
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowPosition(*self.position)
glutInitWindowSize(*self.size)
glutCreateWindow(title)
You're making OpenGL calls before there is a context. If you had written it in the following way it would have worked (I also took the liberty at giving it a nice informative loading screen)
import Image
from math import cos
from math import pi
from math import sin
from numpy import array
from numpy import uint8
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from sys import argv
# Classes ----------------------------------------------------------------------
class AppGL(object):
def __init__(self, title, position=(100, 100), size=(400, 400)):
# Properties -----------------------------------------------------------
self.angle_delta = 4.0
self.position = position
self.rotateX = [0, 1.0, 0.0, 0.0]
self.rotateY = [0, 0.0, 1.0, 0.0]
self.size = size
self.translate = [0.0, 0.0, 0.0]
self.textures = dict()
#-----------------------------------------------------------------------
# GLUT initialization --------------------------------------------------
glutInit(argv)
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowPosition(*self.position)
glutInitWindowSize(*self.size)
glutCreateWindow(title)
#-----------------------------------------------------------------------
# Callbacks ------------------------------------------------------------
glutDisplayFunc(self.onDisplayEvent)
glutKeyboardFunc(self.onKeyEvent)
glutMotionFunc(self.onMouseMotionEvent)
glutMouseFunc(self.onMouseButtonEvent)
glutReshapeFunc(self.onReshapeEvent)
glutSpecialFunc(self.onSpecialKeyEvent)
#-----------------------------------------------------------------------
# Arrays ---------------------------------------------------------------
self.tablelegmodel = array( list(table_leg_model()), "f")
#-----------------------------------------------------------------------
def loadTexture(self, path):
if path in self.textures.keys():
glBindTexture(GL_TEXTURE_2D, self.textures[path])
return
glDrawBuffer(GL_FRONT)
glClearColor(0.25, 0.25, 0.75, 1.)
glClear(GL_COLOR_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glLoadIdentity()
glRasterPos3f(-0.9, 0.9, 0)
glDisable(GL_TEXTURE_2D)
glDisable(GL_LIGHTING)
glutBitmapString(GLUT_BITMAP_HELVETICA_18, "Loading Texture " + path)
glFinish()
glDrawBuffer(GL_BACK)
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
img = Image.open(path)
texture_data = array(list(img.getdata()), uint8)
texID = array([0], uint8)
glGenTextures(1, texID)
texID = texID[0]
self.textures[path] = texID
glBindTexture(GL_TEXTURE_2D, texID)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.size[0], img.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, texture_data)
def onDisplayEvent(self):
width, height = self.size
aspect = float(width) / float(height)
glClearColor(0.0, 0.0, 0.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, aspect, 1.0, 100.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(0, 0, 4, 0, 0, -1, 0, 1, 0)
glTranslatef(*self.translate)
glRotatef(*self.rotateX)
glRotatef(*self.rotateY)
# Visual scene ---------------------------------------------------------
glEnable(GL_DEPTH_TEST)
glPushMatrix()
glTranslatef(-0.1, -0.1, 0)
self.loadTexture('textures/wood1.png')
glEnable(GL_TEXTURE_2D)
glInterleavedArrays(GL_T2F_V3F, 0, self.tablelegmodel)
glDrawElements(GL_QUAD_STRIP, 10, GL_UNSIGNED_INT, array(xrange(0, 10), "d"))
glPopMatrix()
#-----------------------------------------------------------------------
glutSwapBuffers()
def onKeyEvent(self, key, x, y):
if key == 'a':
self.translate[0] += 1
elif key == 'd':
self.translate[0] -= 1
elif key == 's':
self.translate[1] += 1
elif key == 'w':
self.translate[1] -= 1
elif key == 'q':
self.translate[2] += 1
elif key == 'e':
self.translate[2] -= 1
else:
return
glutPostRedisplay()
def onMouseMotionEvent(self, x, y):
pass
def onMouseButtonEvent(self, button, state, x, y):
pass
def onReshapeEvent(self, width, height):
self.size = width, height
glutPostRedisplay()
def onSpecialKeyEvent(self, key, x, y):
if key == GLUT_KEY_UP:
self.rotateX[0] += self.angle_delta
elif key == GLUT_KEY_DOWN:
self.rotateX[0] -= self.angle_delta
elif key == GLUT_KEY_LEFT:
self.rotateY[0] += self.angle_delta
elif key == GLUT_KEY_RIGHT:
self.rotateY[0] -= self.angle_delta
else:
return
glutPostRedisplay()
def run(self):
glutMainLoop()
#-------------------------------------------------------------------------------
def table_model(radius, number_of_points):
delta = 2 * pi / (number_of_points - 1)
points = []
for i in xrange(number_of_points):
points.append((radius * cos(i * delta), radius * sin(i * delta), 0.05))
points.append((radius * cos(i * delta), radius * sin(i * delta), 0))
return points
def table_leg_model():
return (
0, 0, 0, 0.2, 0,
0, 1, 0, 0.2, 1.0,
1, 0, 0, 0, 0,
1, 1, 0, 0, 1.0,
#0, 0, 0.2, 0, 0,
#0, 1, 0.2, 0, 1.0,
#1, 0, 0.2, 0.2, 0,
#1, 1, 0.2, 0.2, 1.0,
#0, 0, 0, 0.2, 0,
#0, 1, 0, 0.2, 1.0,
)
#-------------------------------------------------------------------------------
# Main -------------------------------------------------------------------------
if __name__ == '__main__':
AppGL("Moe's Tavern", (300, 100), (800, 600)).run()
#-------------------------------------------------------------------------------

Categories

Resources