I'm trying to make a game that uses pygame and OpenGL in python 3, but i keep getting the same error:
OpenGL.error.GLError: GLError(
err = 1282,
description = b'invalid operation',
baseOperation = glClear,
cArguments = (16640,)
)
Here is my code:
PART A - Create and Configure
Surface = pygame.display.set_mode((WIDTH, HEIGHT), pygame.OPENGL)
glViewport(0, 0, WIDTH, HEIGHT)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(-8.0, 8.0, -6.0, 6.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
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)
PART B - Creating Texture
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).convert_alpha()
textureData = pygame.image.tostring(textureSurface, "RGBA", True)
self.w, self.h = textureSurface.get_size()
self.texID=glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, self.texID)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, textureSurface.get_width(),
textureSurface.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
textureData )
except Exception as E:
print(E)
print ("can't open the texture: %s"%(fileName))
def __del__(self):
glDeleteTextures(self.texID)
def get_width(self):
return self.w
def get_height(self):
return self.h
PART C - Prepering the screen
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)
PART D - Adding Texture
def blit(texture, x, y):
glPushMatrix()
glTranslatef(x, y, 0.0)
glBindTexture(GL_TEXTURE_2D, texture.texID)
I looked it up, and apparently PyOpenGL 3 has this unfixed bug when try to render more than one texture. I use python 3.3, and dont wanna downgrade to 2.x, and i cant find a OpenGL 2 for python 3. Is there an away around this bug? Am i doing something wrong?
The OpenGL Context is thread local. If you try to invoke an OpenGL statement from another thread without making current the OpenGL context current, you will get an INVALID_OPERATION error.
Unfortunately, PyGame does not offer a function to make the OpenGL context explicitly current.
Another possibility is that you missed closing a glBegin/glEndsequence withglEnd` somewhere.
Related
I used Glut for making window and wanted to draw triangle, then on click button redraw it, but after clearing window I can't draw again. Does something wrong with Buffer depth and buffer bit? If I cleared it do I need to setup both again in my draw function?
def drawSomething():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glTranslatef(-2.5, 0.5, -6.0)
glColor3f( 1.0, 1.5, 0.0 )
glPolygonMode(GL_FRONT, GL_FILL)
glBegin(GL_TRIANGLES)
glVertex3f(2.0,-1.2,0.0)
glVertex3f(2.6,0.0,0.0)
glVertex3f(2.9,-1.2,0.0)
glEnd()
glFlush()
def funcForUpdate():
glClearColor(0.0, 0.0, 0.0, 0)
glClear(GL_COLOR_BUFFER_BIT)
glEnable(GL_TEXTURE_2D)
glBegin(GL_QUADS)
glTexCoord2f(0.0, 0.0)
glVertex2f(0.0, 0.0)
glTexCoord2f(0.0, 1.0)
glVertex2f(0.0, width)
glTexCoord2f(1.0, 1.0)
glVertex2f(height, width)
glTexCoord2f(1.0, 0.0)
glVertex2f(height, 0.0)
glEnd()
glFlush()
def resizeUpdateFunc(width, height):
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluOrtho2D(0.0, width, 0.0, height)
def handleKey(bkey,x,y):
key = bkey.decode("utf-8")
if key == "a":
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
drawSomething()
glFlush()
glutInit()
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
glutInitWindowSize(width, height)
glutInitWindowPosition(0, 0)
glutCreateWindow("test")
drawSomething()
glutDisplayFunc(funcForUpdate)
glutReshapeFunc(resizeUpdateFunc)
glutKeyboardFunc(handleKey)
glutMainLoop()
See glutDisplayFunc:
[...] sets the display callback for the current window. [...] The redisplay state for a window can be either set explicitly by calling glutPostRedisplay or implicitly as the result of window damage reported by the window system.
In fact, a triangle is drawn in drawSomething, but it is immediately overdrawn in funcForUpdate.
Add a state drawTriangle and set the state in handleKey:
drawTriangle = False
def handleKey(bkey, x, y):
global drawTriangle
key = bkey.decode("utf-8")
if key == "a":
drawTriangle = not drawTriangle
glutPostRedisplay()
Draw depending on the variable drawTriangle in funcForUpdate:
def funcForUpdate():
glClearColor(0, 0, 0, 0)
glClear(GL_COLOR_BUFFER_BIT)
# [...]
if drawTriangle:
# [...]
glFlush()
A complete example:
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
drawTriangle = False
def funcForUpdate():
glClearColor(0, 0, 0, 0)
glClear(GL_COLOR_BUFFER_BIT)
glColor3f(1, 1, 0)
glBegin(GL_QUADS)
glVertex2f(0.0, 0.0)
glVertex2f(0, height)
glVertex2f(width, height)
glVertex2f(width, 0)
glEnd()
if drawTriangle:
glPushMatrix()
glLoadIdentity()
glTranslate(width/2, height/2, 0)
glColor3f(1, 0, 0)
glBegin(GL_TRIANGLES)
glVertex3f(-width/4, -height/4, 0)
glVertex3f(width/4, -height/4, 0)
glVertex3f(width/4, height/4, 0)
glEnd()
glPopMatrix()
glFlush()
def resizeUpdateFunc(width, height):
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0.0, width, 0.0, height)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def handleKey(bkey, x, y):
global drawTriangle
key = bkey.decode("utf-8")
if key == "a":
drawTriangle = not drawTriangle
glutPostRedisplay()
width, height = 320, 200
glutInit()
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
glutInitWindowSize(width, height)
glutInitWindowPosition(0, 0)
glutCreateWindow("test")
glutDisplayFunc(funcForUpdate)
glutReshapeFunc(resizeUpdateFunc)
glutKeyboardFunc(handleKey)
glutMainLoop()
I'm trying to render an image with OpenGL using Pyglet. So far I've been able to setup the framebuffer and texture, render into it and save it as a PNG image. But I can't find out how to use Pyglets font rendering.
import numpy as np
import pyglet
from pyglet.gl import *
from ctypes import byref, sizeof, POINTER
width = 800
height = 600
cpp = 4
# Create the framebuffer (rendering target).
buf = gl.GLuint(0)
glGenFramebuffers(1, byref(buf))
glBindFramebuffer(GL_FRAMEBUFFER, buf)
# Create the texture (internal pixel data for the framebuffer).
tex = gl.GLuint(0)
glGenTextures(1, byref(tex))
glBindTexture(GL_TEXTURE_2D, tex)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, None)
# Bind the texture to the framebuffer.
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0)
# Something may have gone wrong during the process, depending on the
# capabilities of the GPU.
res = glCheckFramebufferStatus(GL_FRAMEBUFFER)
if res != GL_FRAMEBUFFER_COMPLETE:
raise RuntimeError('Framebuffer not completed')
glViewport(0, 0, width, height)
# DRAW BEGIN
# =====================
glClearColor(0.1, 0.1, 0.1, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 0.5, 0.02)
glRectf(-0.75, -0.75, 0.75, 0.75)
glColor3f(1.0, 1.0, 1.0)
label = pyglet.text.Label(
"Hello, World", font_name='Times New Roman', font_size=36,
x=0, y=0, anchor_x='center', anchor_y='center')
label.draw()
# =====================
# DRAW END
# Read the buffer contents into a numpy array.
data = np.empty((height, width, cpp), dtype=np.float32)
glReadPixels(0, 0, width, height, GL_RGBA, GL_FLOAT, data.ctypes.data_as(POINTER(GLfloat)))
# Save the image.
import imageio
data = np.uint8(data * 255)
imageio.imwrite("foo.png", data)
The text does not appear on the framebuffer. How can I render the label on the framebuffer?
For rendering labels in Pyglet, first, an orthographic projection should be set up. In the given example, do it as follows:
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, width, 0, height, -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glColor3f(1.0, 1.0, 1.0)
label = pyglet.text.Label(
"Hello, World", font_name='Times New Roman', font_size=36,
x=width/2, y=height/2, anchor_x='center', anchor_y='center')
label.draw()
Then, the label is rendered as expected. (Note: moved the label's offset to the image center, i.e. x=width/2, y=height/2,)
foo.png (output framebuffer image)
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 want to implement shadowmapping in python using pyglet.
It already works, but just if my window has dimensions of powers of 2.
I want two things to change:
Render the depth buffer with another resolution than 2^x, 2^y
Render the depth buffer with a higher resolution than the window.
The Problem with 1. is, that when I change the resolution to something odd and use
buffers = get_buffer_manager()
self.depth_tex = buffers.get_depth_buffer().get_texture()
I get an error: pyglet.image.ImageException: Depth texture requires that buffer dimensions be powers of 2
The Problem #2 is that only the size of the window is written to the depth buffer, the rest is 1. So if my window has the size 512x512 and I set the viewport for the z-buffer to 1024x1024, the z-buffer has a 1024x1024 rectangle with a part of the picture in it, the rest is white.
Code:
class MyWindow(pyglet.window.Window):
def __init__(self):
super(JuliaWindow, self).__init__(caption = 'julia', width=512, height=512)
....
def on_draw(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
# if no depth texture exists (mesh is static)
if not self.depth_tex:
#try it, it won't work (white buffer)
#glViewport(0,0,1024,1024)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60,self.width/float(self.height),0.5,20)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(2.0,1.5,2.5,0.0,0.0,0.0,0.0,1.0,0.0)
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE)
mv = (GLfloat * 16)()
glGetFloatv(GL_MODELVIEW_MATRIX, mv)
p = (GLfloat * 16)()
glGetFloatv(GL_PROJECTION_MATRIX, p)
self.shaderD.bind()
self.batch.draw()
self.shaderD.unbind()
buffers = get_buffer_manager()
self.depth_tex = buffers.get_depth_buffer().get_texture()
glBindTexture(self.depth_tex.target, self.depth_tex.id)
#reset viewport
#glViewport(0,0,self.width,self.height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60,self.width/float(self.height),0.5,20)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(self.x, self.y, self.z,0.0,0.0,0.0,0.0,1.0,0.0)
self.shader.bind()
self.shader.uniform_matrixf('depthMV', list(a))
self.shader.uniform_matrixf('depthP', list(b))
glClear(GL_DEPTH_BUFFER_BIT)
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE)
self.batch.draw()
self.shader.unbind()
I'm trying to use the OpenGL module with Python.
Here is my source:
pygame.init()
screen = pygame.display.set_mode((800, 600), HWSURFACE|OPENGL|DOUBLEBUF)
def init():
glEnable(GL_DEPTH_TEST)
glShadeModel(GL_FLAT)
glClearColor(1.0, 1.0, 1.0, 0.0)
glEnable(GL_COLOR_MATERIAL)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glLight(GL_LIGHT0, GL_POSITION, (0, 1, 1, 0))
def draw():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glColor3fv((25, 123, 180))
glBegin(GL_TRIANGLES)
glVertex3f( 0.0, 10.0, 0.0)
glVertex3f(-10.0,-10.0, 0.0)
glVertex3f( 10.0,-10.0, 0.0)
glEnd()
def run():
init()
while True:
draw()
pygame.display.flip()
run()
Can anyone see what is wrong? I'm just trying to draw a simple 3 pointed vertex, yet nothing shows up on the screen. Occasionally I get a bright pink screen. I'm confident it's a basic error.
You need to setup view and projection matrices.
http://www.opengl.org/resources/faq/technical/transformations.htm#tran0090