mixing 2d and 3d in opengl (using pyglet) - python

I am trying to mix 2d and 3d in opengl in pyglet, i.e. draw a 3d scene then switch to orthographic projection and draw stuff over the top. I draw the 3d stuff, push the projection matrix to the
stack, do a glOrtho projection matrix, draw the 2d stuff, then pop the previous matrix off the stack.
The 3d stuff draws fine but for some reason the 2d part isn't drawing at all, even on its own.
Here's the code:
class Window(pyglet.window.Window):
# resolution
width, height = 1024, 786
def __init__(self, width, height):
# initialise window
super(Window, self).__init__(width, height)
# set title
self.set_caption("OpenGL Doss")
# call update() at 30fps
pyglet.clock.schedule_interval(self.update, 1 / 30.0)
glEnable(GL_TEXTURE_2D) # enable textures
glShadeModel(GL_SMOOTH) # smooth shading of polygons
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) # make stuff look nice
self.world = World() # initialise world
self.label = pyglet.text.Label('Hello, world',
font_name='Times New Roman',
font_size=20,
width=10, height=10)
def on_resize(self, width, height):
print 'on resize'
if height == 0:
height = 1
glViewport(0, 0, width, height) # specify viewport
# load perspective projection matrix
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45, 1.0 * width / height, 0.1, 100.0)
#glLoadIdentity()
def on_draw(self):
self.set3d()
# draw 3d stuff
self.world.draw()
self.set2d()
# draw 2d stuff
self.draw2d()
self.unSet2d()
def update(self, dt):
"called at set interval during runtime"
#maze = self.world.maze
maze_platform = self.world.maze_platform
pacman = maze_platform.maze.pacman
maze_platform.update()
# send it world pointer
pacman.update(self.world)
def on_key_press(self, symbol, modifiers):
control.press(symbol, modifiers)
def on_key_release(self, symbol, modifiers):
control.release(symbol, modifiers)
def set3d(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glEnable(GL_DEPTH_TEST) # enable depth testing
# reset modelview matrix
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def set2d(self):
glDisable(GL_DEPTH_TEST)
# store the projection matrix to restore later
glMatrixMode(GL_PROJECTION)
glPushMatrix()
# load orthographic projection matrix
glLoadIdentity()
#glOrtho(0, float(self.width),0, float(self.height), 0, 1)
far = 8192
glOrtho(-self.width / 2., self.width / 2., -self.height / 2., self.height / 2., 0, far)
# reset modelview
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
#glClear(GL_COLOR_BUFFER_BIT)
def unSet2d(self):
# load back the projection matrix saved before
glMatrixMode(GL_PROJECTION)
glPopMatrix()
def draw2d(self):
z=-6
n=100
glTranslatef(0, 0.0, -z)
glBegin(GL_TRIANGLES)
glVertex3f(0.0, n, 0.0)
glVertex3f(-n, -n, 0)
glVertex3f(n, -n, 0)
glEnd()
def main():
window = Window(Window.width, Window.height)
pyglet.app.run()
print 'framerate:', pyglet.clock.get_fps(), '(error checking = %s)' % pyglet.options['debug_gl']
if __name__ == '__main__': main()
#command = 'main()'
#cProfile.run(command)

I would recommend that you fully reset the modelview and projection matrices on each render, and then don't use push/pop when you go from 3d to 2d.
However, I suspect that you are using bad coordinates so the scene is drawing outside the clip planes. In partciular I am a tad suspicious of putting the near clipping plane at zero. Normally 2d elements are drawn with z=0.
Try putting the near clip-plane at -1.
I'm also a bit unsure why you're calling glTranslatef(0, 0.0, -z) in draw2d, I wouldn't bother.

In draw2d() try glDisable(GL_TEXTURE_2D) and glColor3ub(255,255,255) before drawing your triangle.
Make sure to re-glEnable(GL_TEXTURE_2D) before calling world.draw() again if it uses textured geometry.

Related

OpenGL VBO VAO EBO can run without error but no graphics

This is my code:
block_VAO=0
draw=False
block_EBO_buffer_len=0
def print_blocks(x:int,y:int,z:int):
global draw,block_VAO,block_EBO_buffer_len
if not draw:
block_point_buffer=[]
block_color_buffer=[]
block_EBO_buffer=[]
block_point_buffer+=[x-0.5,y+0.5,z-0.5,#V0
x+0.5,y+0.5,z-0.5,#V1
x+0.5,y-0.5,z-0.5,#V2
x-0.5,y-0.5,z-0.5,#V3
x-0.5,y+0.5,z+0.5,#V4
x+0.5,y+0.5,z+0.5,#V5
x+0.5,y-0.5,z+0.5,#V6
x-0.5,y-0.5,z+0.5]#V7
block_EBO_buffer+=[0,1,5,4,
3,2,6,7,
0,3,7,4,
1,2,6,5,
0,1,2,3,
4,5,6,7]
#ADD
block_color_buffer+=[1.0,0.0,1.0,1.0]*24
color_EBO_buffer+=[0]*24
#ADD END
block_VBO=glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER,block_VBO)
a=numpy.array(block_point_buffer,dtype='float32')
glBufferData(GL_ARRAY_BUFFER,sys.getsizeof(a),a,GL_STATIC_DRAW)
block_EBO=glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,block_EBO)
a=numpy.array(block_EBO_buffer,dtype='uint32')
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sys.getsizeof(a),a,GL_STATIC_DRAW)
block_EBO_buffer_len=len(a)
#ADD
color_VBO=glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER,color_VBO)
a=numpy.array(block_color_buffer,dtype='uint32')
glBufferData(GL_ARRAY_BUFFER,sys.getsizeof(a),a,GL_STATIC_DRAW)
color_EBO=glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,color_EBO)
a=numpy.array(color_EBO_buffer,dtype='uint32')
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sys.getsizeof(a),a,GL_STATIC_DRAW)
#ADD END
block_VAO=glGenVertexArrays(1)
glBindVertexArray(block_VAO)
glBindBuffer(GL_ARRAY_BUFFER,block_VBO)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,block_EBO)
glVertexPointer(3,GL_FLOAT,0,None)
glEnableClientState(GL_VERTEX_ARRAY)
#ADD
glBindBuffer(GL_ARRAY_BUFFER,color_VBO)
glColorPointer(4,GL_FLOAT,0,None)
glEnableClientState(GL_COLOR_ARRAY)
#ADD END
glBindVertexArray(0)
draw=True
glBindVertexArray(block_VAO)
glDrawElements(GL_QUADS,block_EBO_buffer_len,GL_UNSIGNED_INT,None)
glBindVertexArray(0)
function print_blocks is in the mainloop. If I don't bind color to VAO(I mean run without new add code), it can be drawn normally.But after I bind, no graphics will appear.How can I do to make it draw normally?
I really have no thing to say now.Please!Please!Please!Please!Please!Please!
The Index Buffer (ELEMENT_ARRAY_BUFFER) binding is stored within the Vertex Array Object. When glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO) is called the element buffer object ID is stored in the currently bound Vertex Array Object. Therefore the VAO must be bound before the element buffer with glBindVertexArray(VAO).
Compared to the Index Buffer, the Vertex Buffer binding (ARRAY_BUFFER) is a global state.
Each attribute which is stated in the VAOs state vector may refer to a different ARRAY_BUFFER. When glVertexAttribPointer is called the buffer which is currently bound to the target ARRAY_BUFFER, is associated to the specified attribute index and the ID of the object is stored in the state vector of the currently bound VAO.
Therefor the VAO needs to be bound before the element buffer is bound and created.
Furthermore the type of the color attribute needs to be floating point:
a=numpy.array(block_color_buffer,dtype='uint32')
a=numpy.array(block_color_buffer,dtype='float32')
Besides that you cannot specify one mesh with multiple index buffers. See Why does OpenGL not support multiple index buffering?. You can just specify 1 array of indices.
Minimal example based on your original code:
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
import numpy
rotate = [33, 40, 20]
block_VAO=0
draw=False
block_EBO_buffer_len=0
def create_blocks(x:int, y:int, z:int):
global draw, block_VAO, block_EBO_buffer_len
if draw:
return
draw = True
block_point_buffer=[]
block_color_buffer=[]
block_EBO_buffer=[]
block_point_buffer+=[x-0.5,y+0.5,z-0.5,#V0
x+0.5,y+0.5,z-0.5,#V1
x+0.5,y-0.5,z-0.5,#V2
x-0.5,y-0.5,z-0.5,#V3
x-0.5,y+0.5,z+0.5,#V4
x+0.5,y+0.5,z+0.5,#V5
x+0.5,y-0.5,z+0.5,#V6
x-0.5,y-0.5,z+0.5]#V7
block_EBO_buffer+=[0,1,5,4,
3,2,6,7,
0,3,7,4,
1,2,6,5,
0,1,2,3,
4,5,6,7]
block_color_buffer+=[1.0,0.0,1.0,1.0]*8
block_VBO=glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER,block_VBO)
a=numpy.array(block_point_buffer,dtype='float32')
glBufferData(GL_ARRAY_BUFFER,sys.getsizeof(a),a,GL_STATIC_DRAW)
color_VBO=glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER,color_VBO)
a=numpy.array(block_color_buffer,dtype='float32')
glBufferData(GL_ARRAY_BUFFER,sys.getsizeof(a),a,GL_STATIC_DRAW)
block_VAO=glGenVertexArrays(1)
glBindVertexArray(block_VAO)
block_EBO=glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,block_EBO)
a=numpy.array(block_EBO_buffer,dtype='uint32')
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sys.getsizeof(a),a,GL_STATIC_DRAW)
block_EBO_buffer_len=len(a)
glBindBuffer(GL_ARRAY_BUFFER,block_VBO)
glVertexPointer(3,GL_FLOAT,0,None)
glEnableClientState(GL_VERTEX_ARRAY)
glBindBuffer(GL_ARRAY_BUFFER,color_VBO)
glColorPointer(4,GL_FLOAT,0,None)
glEnableClientState(GL_COLOR_ARRAY)
glBindVertexArray(0)
def display():
glMatrixMode(GL_MODELVIEW)
glClear(GL_COLOR_BUFFER_BIT)
glLoadIdentity()
glTranslatef(0, 0, -4.5)
glRotatef(rotate[0], 1, 0.0, 0)
glRotatef(rotate[1], 0, 1, 0)
glRotatef(rotate[2], 0, 0, 1)
glScalef(1, 1, 1)
glBindVertexArray(block_VAO)
glDrawElements(GL_QUADS,block_EBO_buffer_len,GL_UNSIGNED_INT,None)
glBindVertexArray(0)
rotate[1] += 0.1
glutSwapBuffers()
glutPostRedisplay()
def reshape(width, height):
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(40.0, width / height, 0.5, 20.0)
glMatrixMode(GL_MODELVIEW)
glutInit(sys.argv)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
glutInitWindowSize(400, 350)
glutCreateWindow(b"OpenGL Window")
create_blocks(0, 0, 0)
glClearColor(0.0, 0.0, 0.0, 0.0)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
glutDisplayFunc(display)
glutReshapeFunc(reshape)
glutMainLoop()

How can I create 3D with pyglet?

I tried to create a cube in pyglet:
import pyglet
from pyglet.gl import *
window = pyglet.window.Window(400,400,"Paka Paka",True)
#window.event
def on_draw():
window.clear()
glBegin(GL_QUADS)
glVertex3f(0,40,0)
glColor3f(1,0,0)
glVertex3f(100,40,0)
glColor3f(0,1,0)
glVertex3f(100,140,0)
glColor3f(0,0,1)
glVertex3f(100,40,100)
glColor3f(1,1,0)
glVertex3f(100,140,100)
glColor3f(1,0,1)
glVertex3f(0,140,100)
glColor3f(0,1,1)
glVertex3f(0,40,100)
glColor3f(2,0,0)
glVertex3f(0,140,0)
glColor3f(0,0,2)
glEnd()
pyglet.app.run()
and when I run the program, I saw a black screen.
(except up)
should I need to change vertex kind or something different?
edit: I used the codes given by Rabbid76. but it didn't worked.
Seme of the geometry is clipped by the near respectively far plane of the (default) orthographic projection.
I recommend to setup a projection matrix by glOrtho. e.g.:
glOrtho(-200, 200, -200, 200, -200, 200)
respectively
glOrtho(0, 400, 400, 400, -200, 200)
Further more it is recommended to flush a single buffered window by glFlush()
Set the projection at the begin of on_draw and call glFlush() at the end:
#window.event
def on_draw():
w, h = 400, 400
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-w/2, w/2, -h/2, h/2, -200, 200)
glMatrixMode(GL_MODELVIEW)
window.clear()
glBegin(GL_QUADS)
# [...]
glEnd()
glFlush()

Using PyOpenGL to display OpenCV image

I was looking for a basic python program which will display webcam feed using OpenCV and PyOpenGL. I did some searches, and came up with a code posted in stackoverflow
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()
What i'm trying to do is to use OpenGL to display the camera-feed (in full screen) instead of cv2.imshow. I have a hope that it might be faster than imshow.
Can anyone please explain to me display, reshape and idle functions
also i cant run this code because it expects some argument which i still cant figure out.

OpenGL - Show Texture Only

I'm working on a 2D isometric game, using pygame and pyopengl.
I'm drawing sprites as quads, with a texture. I managed to get the alpha transparency to work for the texture, but the quad itself is still filled in a solid color (whatever colour gl pipeline is set with at the time).
How do I hide the quad shape, and just show the texture?
Here is a pic showing the problem (gl pipeline set to pink/purple color):
The code is a bit messy, and I've been blindly copy 'n pasting gl calls hoping it solves the problem so there are bound to be quite a few calls in the wrong place or duplicated (or both).
GL Setup code (called once at start of script)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glViewport(0, 0, screen_size[0], screen_size[1])
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0.0, screen_size[0], 0.0, screen_size[1], 0.0, 1.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glDisable(GL_LIGHTING)
glEnable(GL_TEXTURE_2D)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
Drawing setup code (called once at the start of each frame)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glViewport(0, 0, screen_size[0], screen_size[1])
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0.0, screen_size[0], 0.0, screen_size[1], 0.0, 1.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glDisable(GL_LIGHTING)
glEnable(GL_TEXTURE_2D)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
Quad draw code (called for every sprite draw call):
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_TEXTURE_2D)
glEnable(GL_ALPHA_TEST)
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)
# Start new transformation matrix
glPushMatrix()
# Apply translation
glTranslatef(self.rect.centerx, self.rect.centery, 0.0)
# Start gl drawing cursor
glColor4f(1.0, 0.0, 1.0, 1.0)
# Bind the texture to this draw session
glBindTexture(GL_TEXTURE_2D, self.texture.id)
# Start drawing a quad
glBegin(GL_QUADS)
# Grab new copy of rect, and move to the origin
r = self.rect.copy()
r.center = (0, 0)
# Draw top left point
glTexCoord2f(1.0, 0.0)
glVertex2f(*r.topleft)
# Draw top right point
glTexCoord2f(0.0, 0.0)
glVertex2f(*r.topright)
# Draw bottom right point
glTexCoord2f(0.0, 1.0)
glVertex2f(*r.bottomright)
# Draw bottom left point
glTexCoord2f(1.0, 1.0)
glVertex2f(*r.bottomleft)
# End quad
glEnd()
# Apply transformation matrix
glPopMatrix()
The colored background behind your tiles is probably due to this line when you set up your texture:
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
Just remove this as the default texture environment settings are probably fine for standard tile rendering. As an example of what messing with these parameters can do, if you wanted glColor calls to "tint" your texture instead, then replace GL_DECAL with GL_BLEND.
There is no need for any of those lighting calls included in your code as far as I can tell unless you are working with 3d models and ancient per-vertex lighting (I assume you are not since this is a 2d isometric game). Also you only need blending for this, no need for alpha testing. Assuming you are working with images with alpha (RGBA format), here is a simple demo that displays two tiles with a transparent background (supply your own image of course instead of ./images/grass.png):
import pygame
from pygame.locals import *
from OpenGL.GL import *
import sys
class Sprite(object):
def __init__(self):
self.x = 0
self.y = 0
self.width = 0
self.height = 0
self.texture = glGenTextures(1)
def load_texture(self, texture_url):
tex = pygame.image.load(texture_url)
tex_surface = pygame.image.tostring(tex, 'RGBA')
tex_width, tex_height = tex.get_size()
glBindTexture(GL_TEXTURE_2D, self.texture)
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, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_surface)
glBindTexture(GL_TEXTURE_2D, 0)
self.width = tex_width
self.height = tex_height
def set_position(self, x, y):
self.x = x
self.y = y
def render(self):
#glColor(1, 1, 1, 1)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glBindTexture(GL_TEXTURE_2D, self.texture)
glBegin(GL_QUADS)
glTexCoord(0, 0)
glVertex(self.x, self.y, 0)
glTexCoord(0, 1)
glVertex(self.x, self.y + self.height, 0)
glTexCoord(1, 1)
glVertex(self.x + self.width, self.y + self.height, 0)
glTexCoord(1, 0)
glVertex(self.x + self.width, self.y, 0)
glEnd()
glBindTexture(GL_TEXTURE_2D, 0)
def init_gl():
window_size = width, height = (550, 400)
pygame.init()
pygame.display.set_mode(window_size, OPENGL | DOUBLEBUF)
glEnable(GL_TEXTURE_2D)
glMatrixMode(GL_PROJECTION)
glOrtho(0, width, height, 0, -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
if __name__ == "__main__":
init_gl()
tile1 = Sprite()
tile1.load_texture("./images/grass.png")
tile1.set_position(50, 100)
tile2 = Sprite()
tile2.load_texture("./images/grass.png")
tile2.set_position(80, 130)
tiles = [tile1, tile2]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
glClear(GL_COLOR_BUFFER_BIT)
glColor(1, 0, 0, 1)
for tile in tiles:
tile.render()
pygame.display.flip()
Let me know if this helps!
Well, either use blending, so that the alpha value actually has effect on opacity. Or use alpha testing, so that incoming fragments with an alpha below/above a certain threshold are discarded.
Blending requires to sort geometry back to front. And given what you want to do alpha testing may be the easier, more straightforward solution.
Update:
Either way it's imperative that the texture's alpha value makes it through to the fragment. If you were using shaders this would be as simple as making sure that the fragment output alpha would receive its value from the texture. But you're using the fixed function pipeline and the mess that's the texture environment state machine.
Using only a single texture your best bet would be a GL_REPLACE texture mode (completely ignores the vertex color). Or GL_MODULATE that takes the vertex color into account. Right now you're assumingly using GL_DECAL mode.
My suggestion: Drop the fixed function pipeline and use shaders. Much easier to get things related to texturing working. Also you'll hard pressed to find hardware that's not using shaders anyway (unless you're planning to run your program on stuff that's been built before 2004).

PyOpenGL(or PyGame) pixel-sized textures

I downloaded a simple sample program for using textures with PyOpenGL, Python & PyGame, but when I tried to replace the original texture with this:
(If you don't see that, its a 2x2 pixels square, where all the pixels has different colors)
than it gave me THIS:
I DON'T WANT THIS UGLY WINDOW LOGO!!
The code I downloaded:
#!/usr/bin/env python
from OpenGL.GL import *
from OpenGL.GLU import *
import pygame
from pygame.locals import *
class Texture():
# simple texture class
# designed for 32 bit png images (with alpha channel)
def __init__(self,fileName):
self.texID=0
self.LoadTexture(fileName)
def LoadTexture(self,fileName):
try:
textureSurface = pygame.image.load(fileName)
textureData = pygame.image.tostring(textureSurface, "RGBA", 1)
self.texID=glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, self.texID)
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA,
textureSurface.get_width(), textureSurface.get_height(),
0, GL_RGBA, GL_UNSIGNED_BYTE, textureData )
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
except:
print "can't open the texture: %s"%(fileName)
def __del__(self):
glDeleteTextures(self.texID)
class Main():
def resize(self,(width, height)):
if height==0:
height=1
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
#gluOrtho2D(-8.0, 8.0, -6.0, 6.0)
glFrustum(-2,2,-2,2,1,8)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def init(self):
#set some basic OpenGL settings and control variables
glShadeModel(GL_SMOOTH)
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glDisable(GL_DEPTH_TEST)
glDisable(GL_LIGHTING)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
#glEnable(GL_BLEND)
self.tutorial_texture=Texture("pixels.png")
self.demandedFps=30.0
self.done=False
self.x,self.y,self.z=0.0 , 0.0, -4.0
self.rX,self.rZ=0,0
def draw(self):
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glDisable(GL_LIGHTING)
glEnable(GL_TEXTURE_2D)
#glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glPushMatrix()
glTranslatef(self.x, self.y, self.z)
glRotate(-self.rZ/3,0,0,1)
glRotate(-self.rX/3,1,0,0)
glColor4f(1.0, 1.0, 1.0,1.0)
glBindTexture(GL_TEXTURE_2D,self.tutorial_texture.texID)
glBegin(GL_QUADS)
glTexCoord2f(0.0,1.0)
glVertex3f(-1.0, 1.0,0.0)
glTexCoord2f(1.0,1.0)
glVertex3f(1.0, 1.0,-1.0)
glTexCoord2f(1.0,0.0)
glVertex3f(1.0, -1.0,0.0)
glTexCoord2f(0.0,0.0)
glVertex3f(-1.0, -1.0,1.0)
glEnd()
glBegin(GL_LINES)
glColor(1,17,0)
glVertex(0,0,0)
glVertex(3,0,0)
glColor(1,0,1)
glVertex(0,0,0)
glVertex(0,3,0)
glColor(0,1,1)
glVertex(0,0,0)
glVertex(0,0,3)
glEnd()
glPopMatrix()
def Input(self,fl):
#mpb=pygame.mouse.get_pressed() # mouse pressed buttons
kpb=pygame.key.get_pressed() # keyboard pressed buttons
msh=pygame.mouse.get_rel() # mouse shift
if kpb[K_ESCAPE] or kpb[K_q]:
self.done=True
if kpb[K_UP]:
self.y+=0.1
if kpb[K_DOWN]:
self.y-=0.1
if kpb[K_RIGHT]:
self.x+=0.1
if kpb[K_LEFT]:
self.x-=0.1
if fl: self.rZ-=msh[0]/3; self.rX-=msh[1]/3
def __init__(self):
glOrtho(0, 800, 0, 600, 0.0, 100.0)
video_flags = OPENGL|DOUBLEBUF|RESIZABLE
pygame.init()
pygame.display.set_mode((800,800), video_flags)
pygame.display.set_caption("www.jason.gd")
self.resize((800,800))
self.init()
fl=0
clock = pygame.time.Clock()
while 1:
for event in pygame.event.get():
if event.type == QUIT or self.done:
pygame.quit ()
break
if event.type==MOUSEBUTTONDOWN:
if event.button==4: self.z+=0.1
if event.button==5: self.z-=0.1
if event.button==2: fl=1
if event.type==MOUSEBUTTONUP:
if event.button==2: fl=0
if event.type==VIDEORESIZE: self.resize((event.w,event.h))
self.Input(fl)
self.draw()
pygame.display.flip()
#limit fps
clock.tick(self.demandedFps)
if __name__ == '__main__': Main()
When I tried to use bigger(512x512 px) textures, it worked fine.
How can I let the OpenGL to DO NOT mix the pixel borders? Or- the PyGame did this?
What you see here is the GL_LINEAR texture magnification mode (aka "bilinear filtering", which your code explicitely requests) in combination with the default GL_REPEAT texture coordinate repetition at the borders.
I'm not 100% sure which one of the two things you don't want.
You might try changing GL_LINEAR to GL_NEAREST:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
and/or adding
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE)

Categories