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