2

一段时间以来,我一直在使用 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()

Shaders/Mainv.glsl 和 Shaders/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);
}

和:

#version 110

uniform sampler2D texture;

varying vec2 texcoord;

void main()
{
    gl_FragColor = texture2D(texture, texcoord);
 }

分别。

这段代码为我提供了一个(清晰的颜色)GLUT 窗口,这似乎表明它由于某种原因没有渲染我的三角形,但我不知道为什么会这样,而且我真的找不到任何 PyOpenGL 的例子'不要使用不推荐使用的功能,所以我看不出他们是否做了与我不同的事情,我错过了。

4

2 回答 2

5

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

导入系统
导入 OpenGL

从 OpenGL.GL 导入 *
从 OpenGL.GL.shaders 导入 *
从 OpenGL.GLU 导入 *
从 OpenGL.GLUT 导入 *
从 OpenGL.GLUT.freeglut 导入 *
从 OpenGL.arrays 导入 vbo
导入图片
导入 numpy    

# 顶点着色器
strVS = """
属性 vec2 位置;

改变 vec2 texcoord;

无效的主要()
{
    gl_Position = vec4(位置, 0.0, 1.0);
    texcoord = 位置 * vec2(0.5) + vec2(0.5);
}
"""

# 片段着色器
strFS = """
统一的 sampler2D 纹理;

改变 vec2 texcoord;

无效的主要()
{
    gl_FragColor = texture2D(纹理, texcoord);
}
"""

A类:
    def __init__(self):
        self.Splash = True #这里其实还有很多,但是很无礼
    def TexFromPNG(自我,文件名):
        img = Image.open(filename) # .jpg、.bmp 等也可以
        img_data = numpy.array(list(img.getdata()), 'B')
        纹理 = glGenTextures(1)
        glPixelStorei(GL_UNPACK_ALIGNMENT,1)
        glBindTexture(GL_TEXTURE_2D,纹理)
        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)
        返回纹理
    def MakeBuffer(自我,目标,数据,大小):
        TempBuffer = glGenBuffers(1)
        glBindBuffer(目标,TempBuffer)
        glBufferData(目标,大小,数据,GL_STATIC_DRAW)
        返回临时缓冲区
    定义运行(自我):
        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),
                                          编译着色器(strFS,
                                                        GL_FRAGMENT_SHADER))
        过剩主循环()
    def 重塑(自我,宽度,高度):
        self.width = 宽度
        self.height = 身高
        过剩后重新显示()
    def 绘制(自我):
        glViewport(0, 0, self.width, self.height)        

        glClearDepth(1)
        glClearColor(0,0,0,0)
        glClear(GL_COLOR_BUFFER_BIT)
        glEnable(GL_TEXTURE_2D)
        如果 self.Splash:
            glUseProgram(self.BaseProgram)
            pos = glGetAttribLocation(self.BaseProgram, "位置")
            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,
                                  没有任何)
            glEnableVertexAttribArray(pos)
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,self.FullWindowVertices)
            glDrawElements(GL_TRIANGLE_STRIP,
                           4、
                           GL_UNSIGNED_SHORT,
                           没有任何)
            glDisableVertexAttribArray(pos)
        别的:
            glBindTexture(GL_TEXTURE_2D, self.MainTex)

        glutSwapBuffers()

glutInit(sys.argv)
测试 = AClass()
测试运行()

这是输出:

在此处输入图像描述

于 2012-10-02T08:12:52.953 回答
3

在修复以下问题后,我设法让您的代码正常工作:

  • glBufferData 以字节而不是元素为单位获取数据的大小:顶点数据(浮点数)需要乘以 4,索引数据(短整数)需要乘以 2
  • 如果使用 VBO(你是),glVertexAttribPointer 的最后一个参数是当前绑定到 ARRAY_BUFFER 的目标的偏移量;在您的情况下,它应该是一个空指针,即使用 pyOpenGL 时为 None
  • glDrawElements 的行为方式相同:最后一个参数是 ELEMENT_ARRAY_BUFFER 的偏移量,即在这种情况下为 None

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

于 2011-05-12T10:22:37.983 回答