寻找一个使用GLFW的简单OpenGL(3.2+)Python示例 [英] Looking for a simple OpenGL (3.2+) Python example that uses GLFW
问题描述
我正在寻找Python中一个简单的现代OpenGL(3.2+)示例.
我尝试使用GLUT和freeGLUT,但无法在OS X(Mavericks)上获得3.2上下文.(这似乎是GLUT/freeGLUT的已知问题.)
GLFW似乎是GLUT的现代轻量级替代品,但是它似乎没有正式的Python绑定,我找不到一个简单的示例,该示例在GLUTW和Python中使用OpenGL的3.2核心配置文件功能.>
(我在这个问题上苦苦挣扎,因此对其他人可能有用,我按照
代码列表如下:
导入OpenGL从OpenGL.GL导入*从OpenGL.GLUT导入*导入numpy,math,sys,os进口面筋将cyglfw3导入为glfwstrVS ="#version 330核心vec3 aVert中的layout(location = 0);统一的mat4 uMVMatrix;统一的mat4 uPMatrix;统一的vec4 uColor;均匀漂浮的uTheta;出vec4 vCol;vec2 vTexCoord;void main(){//旋转变换mat4腐烂= mat4(vec4(cos(uTheta),sin(uTheta),0.0,0.0),vec4(-sin(uTheta),cos(uTheta),0.0,0.0),vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0));//变换顶点gl_Position = uPMatrix * uMVMatrix *腐烂* vec4(aVert,1.0);//设置颜色vCol = vec4(uColor.rgb,1.0);//设置纹理坐标vTexCoord = aVert.xy + vec2(0.5,0.5);}"strFS ="#version 330核心在vec4 vCol中;在vec2 vTexCoord中;均匀采样器2D tex2D;均匀的bool showCircle;出vec4 fragColor;void main(){如果(showCircle){//丢弃圆外的片段如果(距离(vTexCoord,vec2(0.5,0.5))> 0.5){丢弃;}别的 {fragColor = texture(tex2D,vTexCoord);}}别的 {fragColor = texture(tex2D,vTexCoord);}}"类场景:""OpenGL 3D场景类""#初始化def __init __():#创建着色器self.program = glutils.loadShaders(strVS,strFS)glUseProgram(self.program)self.pMatrixUniform = glGetUniformLocation(self.program,'uPMatrix')self.mvMatrixUniform = glGetUniformLocation(self.program,"uMVMatrix")self.colorU = glGetUniformLocation(self.program,"uColor")# 颜色self.col0 = [1.0,0.0,0.0,1.0]# 质地self.tex2D = glGetUniformLocation(self.program,"tex2D")#定义四边形顶点quadV = [-0.5,-0.5、0.0,0.5,-0.5、0.0,-0.5、0.5、0.0,0.5、0.5、0.0]#设置顶点数组对象(VAO)self.vao = glGenVertexArrays(1)glBindVertexArray(self.vao)#个顶点self.vertexBuffer = glGenBuffers(1)glBindBuffer(GL_ARRAY_BUFFER,self.vertexBuffer)vertexData = numpy.array(quadV,numpy.float32)glBufferData(GL_ARRAY_BUFFER,4 * len(vertexData),vertexData,GL_STATIC_DRAW)#启用顶点数组glEnableVertexAttribArray(0)#设置缓冲区数据glBindBuffer(GL_ARRAY_BUFFER,self.vertexBuffer)glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,无)#解除绑定VAOglBindVertexArray(0)# 时间self.t = 0# 质地self.texId = glutils.loadTexture('test.png')#显示圈子?self.showCircle =假# 步def步骤(自己):#增量角度self.t =(self.t +1)%360#以弧度设置着色器角度glUniform1f(glGetUniformLocation(self.program,'uTheta'),math.radians(self.t))# 使成为def渲染(self,pMatrix,mvMatrix):#使用着色器glUseProgram(self.program)#设置项目矩阵glUniformMatrix4fv(self.pMatrixUniform,1,GL_FALSE,pMatrix)#设置模型视图矩阵glUniformMatrix4fv(self.mvMatrixUniform,1,GL_FALSE,mvMatrix)#显示圈子?glUniform1i(glGetUniformLocation(self.program,'showCircle'),self.showCircle)#启用纹理glActiveTexture(GL_TEXTURE0)glBindTexture(GL_TEXTURE_2D,self.texId)glUniform1i(self.tex2D,0)#绑定VAOglBindVertexArray(self.vao)# 画glDrawArrays(GL_TRIANGLE_STRIP,0,4)#解除绑定VAOglBindVertexArray(0)RenderWindow类:""GLFW渲染窗口类""def __init __():#保存当前工作目录cwd = os.getcwd()#初始化glfw-这会更改cwdglfw.Init()#恢复cwdos.chdir(cwd)#版本提示glfw.WindowHint(glfw.CONTEXT_VERSION_MAJOR,3)glfw.WindowHint(glfw.CONTEXT_VERSION_MINOR,3)glfw.WindowHint(glfw.OPENGL_FORWARD_COMPAT,GL_TRUE)glfw.WindowHint(glfw.OPENGL_PROFILE,glfw.OPENGL_CORE_PROFILE)#制作一个窗户self.width,self.height = 640,480self.aspect = self.width/float(self.height)self.win = glfw.CreateWindow(self.width,self.height,"test")#使上下文为最新glfw.MakeContextCurrent(self.win)#初始化GLglViewport(0,0,self.width,self.height)glEnable(GL_DEPTH_TEST)glClearColor(0.5,0.5,0.5,1.0)#设置窗口回调glfw.SetMouseButtonCallback(self.win,self.onMouseButton)glfw.SetKeyCallback(self.win,self.onKeyboard)glfw.SetWindowSizeCallback(self.win,self.onSize)#创建3Dself.scene =场景()#退出标志self.exitNow = Falsedef onMouseButton(自我,胜利,按钮,动作,mod):#print'mouse button:',win,button,action,mods经过def onKeyboard(自我,胜利,关键,扫描码,行动,mod):#print'keyboard:',win,key,scancode,action,mods如果动作== glfw.PRESS:#ESC退出如果键== glfw.KEY_ESCAPE:self.exitNow =真别的:#切换剪切self.scene.showCircle =不是self.scene.showCircledef onSize(自我,胜利,宽度,高度):#print'onsize:',胜利,宽度,高度self.width =宽度self.height =高度self.aspect =宽度/浮动(高度)glViewport(0,0,self.width,self.height)def运行(自己):#初始化计时器glfw.SetTime(0.0)t = 0.0而不是glfw.WindowShouldClose(self.win)而不是self.exitNow:#每x秒更新一次currT = glfw.GetTime()如果currT-t> 0.1:# 更新时间t =当前# 清除glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)#建立投影矩阵pMatrix = glutils.perspective(45.0,self.aspect,0.1,100.0)mvMatrix = glutils.lookAt([0.0,0.0,-2.0],[0.0,0.0,0.0],[0.0,1.0,0.0])# 使成为self.scene.render(pMatrix,mvMatrix)# 步self.scene.step()glfw.SwapBuffers(self.win)#轮询和处理事件glfw.PollEvents()# 结尾glfw.Terminate()# 主功能def main():打印'starting simpleglfw ...'rw = RenderWindow()rw.run()#呼叫主要如果__name__ =='__main__':主要的()
I am looking for a simple modern OpenGL (3.2+)example in Python.
I tried with GLUT and freeGLUT, but I am not able to get a 3.2 context on OS X (Mavericks). (This seems to be a known issue with GLUT/freeGLUT).
GLFW seems to be a modern lightweight alternative to GLUT, but it doesn't seem to have an official Python binding, and I could not find a simple example that uses 3.2 core profile features of OpenGL with GLFW and Python.
(I struggled with this problem, and so it could be useful for others, I am answering below as per SO guidelines.)
The code below uses PyOpenGL, PIL (for textures), numpy, GLFW and the corresponding Python binding cyglfw3.
Here is a screenshot of the output:
The main code is appended below. It uses some utility methods from a file called glutils.py (for loading texture, compiling shaders, etc.) which you can find here:
https://github.com/electronut/pp/tree/master/simplegl
Code listing follows:
import OpenGL
from OpenGL.GL import *
from OpenGL.GLUT import *
import numpy, math, sys, os
import glutils
import cyglfw3 as glfw
strVS = """
#version 330 core
layout(location = 0) in vec3 aVert;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform vec4 uColor;
uniform float uTheta;
out vec4 vCol;
out vec2 vTexCoord;
void main() {
// rotational transform
mat4 rot = mat4(
vec4( cos(uTheta), sin(uTheta), 0.0, 0.0),
vec4(-sin(uTheta), cos(uTheta), 0.0, 0.0),
vec4(0.0, 0.0, 1.0, 0.0),
vec4(0.0, 0.0, 0.0, 1.0)
);
// transform vertex
gl_Position = uPMatrix * uMVMatrix * rot * vec4(aVert, 1.0);
// set color
vCol = vec4(uColor.rgb, 1.0);
// set texture coord
vTexCoord = aVert.xy + vec2(0.5, 0.5);
}
"""
strFS = """
#version 330 core
in vec4 vCol;
in vec2 vTexCoord;
uniform sampler2D tex2D;
uniform bool showCircle;
out vec4 fragColor;
void main() {
if (showCircle) {
// discard fragment outside circle
if (distance(vTexCoord, vec2(0.5, 0.5)) > 0.5) {
discard;
}
else {
fragColor = texture(tex2D, vTexCoord);
}
}
else {
fragColor = texture(tex2D, vTexCoord);
}
}
"""
class Scene:
""" OpenGL 3D scene class"""
# initialization
def __init__(self):
# create shader
self.program = glutils.loadShaders(strVS, strFS)
glUseProgram(self.program)
self.pMatrixUniform = glGetUniformLocation(self.program,
'uPMatrix')
self.mvMatrixUniform = glGetUniformLocation(self.program,
"uMVMatrix")
self.colorU = glGetUniformLocation(self.program, "uColor")
# color
self.col0 = [1.0, 0.0, 0.0, 1.0]
# texture
self.tex2D = glGetUniformLocation(self.program, "tex2D")
# define quad vertices
quadV = [
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
-0.5, 0.5, 0.0,
0.5, 0.5, 0.0
]
# set up vertex array object (VAO)
self.vao = glGenVertexArrays(1)
glBindVertexArray(self.vao)
# vertices
self.vertexBuffer = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer)
vertexData = numpy.array(quadV, numpy.float32)
glBufferData(GL_ARRAY_BUFFER, 4*len(vertexData), vertexData,
GL_STATIC_DRAW)
# enable vertex array
glEnableVertexAttribArray(0)
# set buffer data
glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, None)
# unbind VAO
glBindVertexArray(0)
# time
self.t = 0
# texture
self.texId = glutils.loadTexture('test.png')
# show circle?
self.showCircle = False
# step
def step(self):
# increment angle
self.t = (self.t + 1) % 360
# set shader angle in radians
glUniform1f(glGetUniformLocation(self.program, 'uTheta'),
math.radians(self.t))
# render
def render(self, pMatrix, mvMatrix):
# use shader
glUseProgram(self.program)
# set proj matrix
glUniformMatrix4fv(self.pMatrixUniform, 1, GL_FALSE, pMatrix)
# set modelview matrix
glUniformMatrix4fv(self.mvMatrixUniform, 1, GL_FALSE, mvMatrix)
# show circle?
glUniform1i(glGetUniformLocation(self.program, 'showCircle'),
self.showCircle)
# enable texture
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, self.texId)
glUniform1i(self.tex2D, 0)
# bind VAO
glBindVertexArray(self.vao)
# draw
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
# unbind VAO
glBindVertexArray(0)
class RenderWindow:
"""GLFW Rendering window class"""
def __init__(self):
# save current working directory
cwd = os.getcwd()
# initialize glfw - this changes cwd
glfw.Init()
# restore cwd
os.chdir(cwd)
# version hints
glfw.WindowHint(glfw.CONTEXT_VERSION_MAJOR, 3)
glfw.WindowHint(glfw.CONTEXT_VERSION_MINOR, 3)
glfw.WindowHint(glfw.OPENGL_FORWARD_COMPAT, GL_TRUE)
glfw.WindowHint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
# make a window
self.width, self.height = 640, 480
self.aspect = self.width/float(self.height)
self.win = glfw.CreateWindow(self.width, self.height, "test")
# make context current
glfw.MakeContextCurrent(self.win)
# initialize GL
glViewport(0, 0, self.width, self.height)
glEnable(GL_DEPTH_TEST)
glClearColor(0.5, 0.5, 0.5,1.0)
# set window callbacks
glfw.SetMouseButtonCallback(self.win, self.onMouseButton)
glfw.SetKeyCallback(self.win, self.onKeyboard)
glfw.SetWindowSizeCallback(self.win, self.onSize)
# create 3D
self.scene = Scene()
# exit flag
self.exitNow = False
def onMouseButton(self, win, button, action, mods):
#print 'mouse button: ', win, button, action, mods
pass
def onKeyboard(self, win, key, scancode, action, mods):
#print 'keyboard: ', win, key, scancode, action, mods
if action == glfw.PRESS:
# ESC to quit
if key == glfw.KEY_ESCAPE:
self.exitNow = True
else:
# toggle cut
self.scene.showCircle = not self.scene.showCircle
def onSize(self, win, width, height):
#print 'onsize: ', win, width, height
self.width = width
self.height = height
self.aspect = width/float(height)
glViewport(0, 0, self.width, self.height)
def run(self):
# initializer timer
glfw.SetTime(0.0)
t = 0.0
while not glfw.WindowShouldClose(self.win) and not self.exitNow:
# update every x seconds
currT = glfw.GetTime()
if currT - t > 0.1:
# update time
t = currT
# clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
# build projection matrix
pMatrix = glutils.perspective(45.0, self.aspect, 0.1, 100.0)
mvMatrix = glutils.lookAt([0.0, 0.0, -2.0], [0.0, 0.0, 0.0],
[0.0, 1.0, 0.0])
# render
self.scene.render(pMatrix, mvMatrix)
# step
self.scene.step()
glfw.SwapBuffers(self.win)
# Poll for and process events
glfw.PollEvents()
# end
glfw.Terminate()
# main() function
def main():
print 'starting simpleglfw...'
rw = RenderWindow()
rw.run()
# call main
if __name__ == '__main__':
main()
这篇关于寻找一个使用GLFW的简单OpenGL(3.2+)Python示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!