Python PyOpenGL:渲染。。。好。。。真的吗

Python PyOpenGL:渲染。。。好。。。真的吗,python,opengl,pyopengl,Python,Opengl,Pyopengl,我已经在一个使用python和OpenGL的项目上工作了一段时间。我之前发布过一个类似的问题,但后来我做了更多的研究,并切换到非弃用函数。下面(显然是将其转换为Python版本)我最终得到了以下代码: import sys import OpenGL from OpenGL.GL import * from OpenGL.GL.shaders import * from OpenGL.GLU import * from OpenGL.GLUT import * from OpenGL.GLUT

我已经在一个使用python和OpenGL的项目上工作了一段时间。我之前发布过一个类似的问题,但后来我做了更多的研究,并切换到非弃用函数。下面(显然是将其转换为Python版本)我最终得到了以下代码:

import sys
import OpenGL

from OpenGL.GL import *
from OpenGL.GL.shaders import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from OpenGL.GLUT.freeglut import *
from OpenGL.arrays import vbo
import pygame
import Image
import numpy    

class AClass:
    def __init__(self):
        self.Splash = True    #There's actually more here, but it's impertinent
    def TexFromPNG(self, filename):
        img = Image.open(filename) # .jpg, .bmp, etc. also work
        img_data = numpy.array(list(img.getdata()), 'B')
        texture = glGenTextures(1)
        glPixelStorei(GL_UNPACK_ALIGNMENT,1)
        glBindTexture(GL_TEXTURE_2D, texture)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
        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_UNSIGNED_BYTE, img_data)
        return texture
    def MakeBuffer(self, target, data, size):
        TempBuffer = glGenBuffers(1)
        glBindBuffer(target, TempBuffer)
        glBufferData(target, size, data, GL_STATIC_DRAW)
        return TempBuffer
    def ReadFile(self, filename):
        tempfile = open(filename,'r')
        source = tempfile.read()
        temprfile.close()
        return source
    def run(self):
        glutInitDisplayMode(GLUT_RGBA)

        glutInitWindowSize(256,244)
        self.window = glutCreateWindow("test")
        glutReshapeFunc(self.reshape)
        glutDisplayFunc(self.draw)
        glutKeyboardFunc(self.keypress)

        self.MainTex = glGenTextures(1)
        self.SplashTex = self.TexFromPNG("Resources/Splash.png")
        MainVertexData = numpy.array([-1,-1,1,-1,-1,1,1,1],numpy.float32)
        FullWindowVertices = numpy.array([0,1,2,3],numpy.ushort)
        self.MainVertexData = self.MakeBuffer(GL_ARRAY_BUFFER,MainVertexData,len(MainVertexData))
        self.FullWindowVertices = self.MakeBuffer(GL_ELEMENT_ARRAY_BUFFER,FullWindowVertices,len(FullWindowVertices))
        self.BaseProgram = compileProgram(compileShader(self.ReadFile("Shaders/Mainv.glsl"),
                                         GL_VERTEX_SHADER),
                                         compileShader(self.ReadFile("Shaders/Mainf.glsl"),
                                         GL_FRAGMENT_SHADER))
        glutMainLoop()
    def reshape(self, width, height):
        self.width = width
        self.height = height
        glutPostRedisplay()
    def draw(self):
        glViewport(0, 0, self.width, self.height)        

        glClearDepth(1)
        glClearColor(0,0,0,0)
        glClear(GL_COLOR_BUFFER_BIT)
        glEnable(GL_TEXTURE_2D)
        if self.Splash:
            glUseProgram(self.BaseProgram)
            pos = glGetAttribLocation(self.BaseProgram, "position")
            glActiveTexture(GL_TEXTURE0)
            glBindTexture(GL_TEXTURE_2D, self.SplashTex)
            glUniform1i(glGetUniformLocation(self.BaseProgram,"texture"), 0)

            glBindBuffer(GL_ARRAY_BUFFER,self.MainVertexData)
            glVertexAttribPointer(pos,
                                  2,
                                  GL_FLOAT,
                                  GL_FALSE,
                                  0,
                                  numpy.array([0],numpy.uint8))
            glEnableVertexAttribArray(pos)
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,self.FullWindowVertices)
            glDrawElements(GL_TRIANGLE_STRIP,
                           4,
                           GL_UNSIGNED_SHORT,
                           numpy.array([0],numpy.uint8))
            glDisableVertexAttribArray(pos)
        else:
            glBindTexture(GL_TEXTURE_2D, self.MainTex)



        glutSwapBuffers()
glutInit(sys.argv)
test = AClass()
test.run()
着色器/Mainv.glsl和着色器/Mainf.glsl包含:

#version 110

attribute vec2 position;

varying vec2 texcoord;

void main()
{
    gl_Position = vec4(position, 0.0, 1.0);
    texcoord = position * vec2(0.5) + vec2(0.5);
}
以及:

分别


这段代码为我提供了一个(清晰的颜色)GLUT窗口,这似乎表明它出于某种原因没有渲染我的三角形,但我不知道为什么会这样,我也找不到任何不使用不推荐的函数的PyOpenGL示例,因此,我看不出他们是否做了与我不一样的事情。

在修复了以下内容后,我成功地使您的代码正常工作:

  • glBufferData以字节为单位,而不是以元素为单位:顶点数据(浮点)需要乘以4,索引数据(短整数)需要乘以2
  • 如果使用VBOs(即您现在使用的VBOs),则GLVERTEXATTRIBPORTER的最后一个参数是当前绑定到ARRAY_BUFFER的目标的偏移量;在您的情况下,它应该是一个空指针,即使用pyOpenGL时为None
  • GLDraweElements的行为方式相同:最后一个参数是元素\数组\缓冲区的偏移量,即在本例中为无

我的测试图像显示在那之后,虽然颜色是乱七八糟的。我没有尝试调试,因为您用于解码png文件的选项可能特定于您的数据:)

我认为这对于任何开始使用PyOpenGL和可编程pipleline的人来说都是一个有用的参考,因此我根据Bethor和Josiah的上述评论更正了代码,并将其简化了一点(将着色器嵌入为字符串)。此代码适用于我。它假定您在同一目录中有test.png

import sys import OpenGL from OpenGL.GL import * from OpenGL.GL.shaders import * from OpenGL.GLU import * from OpenGL.GLUT import * from OpenGL.GLUT.freeglut import * from OpenGL.arrays import vbo import Image import numpy # vertex shader strVS = """ attribute vec2 position; varying vec2 texcoord; void main() { gl_Position = vec4(position, 0.0, 1.0); texcoord = position * vec2(0.5) + vec2(0.5); } """ # fragment shader strFS = """ uniform sampler2D texture; varying vec2 texcoord; void main() { gl_FragColor = texture2D(texture, texcoord); } """ class AClass: def __init__(self): self.Splash = True #There's actually more here, but it's impertinent def TexFromPNG(self, filename): img = Image.open(filename) # .jpg, .bmp, etc. also work img_data = numpy.array(list(img.getdata()), 'B') texture = glGenTextures(1) glPixelStorei(GL_UNPACK_ALIGNMENT,1) glBindTexture(GL_TEXTURE_2D, texture) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) 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_RGBA, GL_UNSIGNED_BYTE, img_data) return texture def MakeBuffer(self, target, data, size): TempBuffer = glGenBuffers(1) glBindBuffer(target, TempBuffer) glBufferData(target, size, data, GL_STATIC_DRAW) return TempBuffer def run(self): glutInitDisplayMode(GLUT_RGBA) glutInitWindowSize(256,244) self.window = glutCreateWindow("test") glutReshapeFunc(self.reshape) glutDisplayFunc(self.draw) self.MainTex = glGenTextures(1) self.SplashTex = self.TexFromPNG("test.png") MainVertexData = numpy.array([-1,-1,1,-1,-1,1,1,1],numpy.float32) FullWindowVertices = numpy.array([0,1,2,3],numpy.ushort) self.MainVertexData = self.MakeBuffer(GL_ARRAY_BUFFER,MainVertexData,4*len(MainVertexData)) self.FullWindowVertices = self.MakeBuffer(GL_ELEMENT_ARRAY_BUFFER,FullWindowVertices,2*len(FullWindowVertices)) self.BaseProgram = compileProgram(compileShader(strVS, GL_VERTEX_SHADER), compileShader(strFS, GL_FRAGMENT_SHADER)) glutMainLoop() def reshape(self, width, height): self.width = width self.height = height glutPostRedisplay() def draw(self): glViewport(0, 0, self.width, self.height) glClearDepth(1) glClearColor(0,0,0,0) glClear(GL_COLOR_BUFFER_BIT) glEnable(GL_TEXTURE_2D) if self.Splash: glUseProgram(self.BaseProgram) pos = glGetAttribLocation(self.BaseProgram, "position") glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, self.SplashTex) glUniform1i(glGetUniformLocation(self.BaseProgram,"texture"), 0) glBindBuffer(GL_ARRAY_BUFFER,self.MainVertexData) glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(pos) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,self.FullWindowVertices) glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, None) glDisableVertexAttribArray(pos) else: glBindTexture(GL_TEXTURE_2D, self.MainTex) glutSwapBuffers() glutInit(sys.argv) test = AClass() test.run() 导入系统 导入OpenGL 从OpenGL.GL导入* 从OpenGL.GL.shaders导入* 从OpenGL.GLU导入* 从OpenGL.GLUT导入* 从OpenGL.GLUT.freeglut导入* 从OpenGL.Array导入vbo 导入图像 进口numpy #顶点着色器 strVS=”“” 属性向量2位置; 可变矢量2 texcoord; void main() { gl_位置=vec4(位置,0.0,1.0); texcoord=位置*vec2(0.5)+vec2(0.5); } """ #片段着色器 strFS=“” 二维纹理均匀; 可变矢量2 texcoord; void main() { gl_FragColor=纹理2D(纹理,texcoord); } """ 类AClass: 定义初始化(自): self.Splash=True#这里实际上还有更多,但这是不恰当的 def TEXTFROMPNG(自身,文件名): img=Image.open(filename)#.jpg、.bmp等也可以 img_data=numpy.array(list(img.getdata()),'B') 纹理=glGenTextures(1) glPixelStorei(GLU解包对齐,1) glBindTexture(GL_纹理_2D,纹理) GLTEX参数F(GL_纹理\u 2D、GL_纹理\u包裹、GL_夹紧\u到边) GLTEX参数F(GL_纹理\u 2D、GL_纹理\u包裹\u T、GL_夹紧\u到边) glTexParameterf(GL_纹理2D、GL_纹理MAG_过滤器、GL_线性) GLTEX参数F(GL_纹理_2D、GL_纹理_最小过滤器、GL_线性) GLTEXAGE2D(GL_纹理_2D,0,GL_RGBA,图像大小[0],图像大小[1],0,GL_RGBA,GL_无符号字节,图像数据) 返回纹理 def MakeBuffer(自身、目标、数据、大小): TempBuffer=glGenBuffers(1) glBindBuffer(目标,临时缓冲区) glBufferData(目标、大小、数据、GL\U静态图) 返回临时缓冲区 def运行(自): glutInitDisplayMode(GLUT_RGBA) GLUTINITWindowsSize(256244) self.window=glutCreateWindow(“测试”) GLUTREFORMEFUNC(自我重塑) glutDisplayFunc(自绘制) self.MainTex=glGenTextures(1) self.SplashTex=self.TexFromPNG(“test.png”) MainVertexData=numpy.array([-1,-1,1,-1,1,1],numpy.float32) FullWindowVertices=numpy.array([0,1,2,3],numpy.ushort) self.MainVertexData=self.MakeBuffer(GL_数组_缓冲区,MainVertexData,4*len(MainVertexData)) self.FullWindowVertices=self.MakeBuffer(GL_元素_数组_缓冲区,FullWindowVertices,2*len(FullWindowVertices)) self.BaseProgram=编译程序, GL_顶点_着色器), 编译头(strFS, GL_碎片_着色器) glutMainLoop() def重塑(自身、宽度、高度): self.width=宽度 自我高度=高度 再发现 def牵引(自): glViewport(0,0,self.width,self.height) glClearDepth(1) glClearColor(0,0,0,0) glClear(GLU颜色缓冲位) glEnable(GL_纹理_2D) 如果是自溅: glUseProgram(self.BaseProgram) pos=GLGetAttriblLocation(self.BaseProgram,“位置”) 玻璃纹理(GL_纹理0) glBindTexture(GL_纹理_2D,self.SplashTex) glUniform1i(glGetUniformLocation(self.BaseProgram,“纹理”),0) glBindBuffer(GL_数组_缓冲区,self.MainVertexData) glVertexAttribPointer(位置, 2. 浮球, GL_FALSE, 0, (无) GlenableVertexAttributeArray(pos) glBindBuffer(GL\u元素\u数组\u缓冲区,self.FullWindowVertices) 玻璃元件(玻璃三角带), 4. GL_无符号_短, (无) GLDisableVertexAttributeArray(pos) 其他: glBindTexture(GL_TEXTURE_2D,self.MainTex) glutSwapBuffers() glutInit(sys.argv) test=AClass() test.run() 以下是输出:


如果可能的话,您应该将代码简化为一个简单的测试用例,在发布之前显示您的问题 import sys import OpenGL from OpenGL.GL import * from OpenGL.GL.shaders import * from OpenGL.GLU import * from OpenGL.GLUT import * from OpenGL.GLUT.freeglut import * from OpenGL.arrays import vbo import Image import numpy # vertex shader strVS = """ attribute vec2 position; varying vec2 texcoord; void main() { gl_Position = vec4(position, 0.0, 1.0); texcoord = position * vec2(0.5) + vec2(0.5); } """ # fragment shader strFS = """ uniform sampler2D texture; varying vec2 texcoord; void main() { gl_FragColor = texture2D(texture, texcoord); } """ class AClass: def __init__(self): self.Splash = True #There's actually more here, but it's impertinent def TexFromPNG(self, filename): img = Image.open(filename) # .jpg, .bmp, etc. also work img_data = numpy.array(list(img.getdata()), 'B') texture = glGenTextures(1) glPixelStorei(GL_UNPACK_ALIGNMENT,1) glBindTexture(GL_TEXTURE_2D, texture) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) 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_RGBA, GL_UNSIGNED_BYTE, img_data) return texture def MakeBuffer(self, target, data, size): TempBuffer = glGenBuffers(1) glBindBuffer(target, TempBuffer) glBufferData(target, size, data, GL_STATIC_DRAW) return TempBuffer def run(self): glutInitDisplayMode(GLUT_RGBA) glutInitWindowSize(256,244) self.window = glutCreateWindow("test") glutReshapeFunc(self.reshape) glutDisplayFunc(self.draw) self.MainTex = glGenTextures(1) self.SplashTex = self.TexFromPNG("test.png") MainVertexData = numpy.array([-1,-1,1,-1,-1,1,1,1],numpy.float32) FullWindowVertices = numpy.array([0,1,2,3],numpy.ushort) self.MainVertexData = self.MakeBuffer(GL_ARRAY_BUFFER,MainVertexData,4*len(MainVertexData)) self.FullWindowVertices = self.MakeBuffer(GL_ELEMENT_ARRAY_BUFFER,FullWindowVertices,2*len(FullWindowVertices)) self.BaseProgram = compileProgram(compileShader(strVS, GL_VERTEX_SHADER), compileShader(strFS, GL_FRAGMENT_SHADER)) glutMainLoop() def reshape(self, width, height): self.width = width self.height = height glutPostRedisplay() def draw(self): glViewport(0, 0, self.width, self.height) glClearDepth(1) glClearColor(0,0,0,0) glClear(GL_COLOR_BUFFER_BIT) glEnable(GL_TEXTURE_2D) if self.Splash: glUseProgram(self.BaseProgram) pos = glGetAttribLocation(self.BaseProgram, "position") glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, self.SplashTex) glUniform1i(glGetUniformLocation(self.BaseProgram,"texture"), 0) glBindBuffer(GL_ARRAY_BUFFER,self.MainVertexData) glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(pos) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,self.FullWindowVertices) glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, None) glDisableVertexAttribArray(pos) else: glBindTexture(GL_TEXTURE_2D, self.MainTex) glutSwapBuffers() glutInit(sys.argv) test = AClass() test.run()