python - 颜色未按预期应用 glDrawArrays (Pyglet)

标签 python opengl pyglet

如果我用以下代码绘制矩形:

def render(shape):
    gl.glLoadIdentity()
    gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)
    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, shape.vbo_id)

    gl.glColor4ub(shape.color[0], shape.color[1], shape.color[2], 255)
    gl.glDrawArrays(shape.draw_mode, 0, shape.size)

...我得到的颜色是一次性的。如果我画红色、绿色、蓝色、紫色方 block ,我实际上会得到绿色、蓝色、紫色、红色。

如果我交换颜色并像这样画线:

def render(shape):

    gl.glLoadIdentity()
    gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)
    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, shape.vbo_id)

    # SWAPPED
    gl.glDrawArrays(shape.draw_mode, 0, shape.size)
    gl.glColor4ub(shape.color[0], shape.color[1], shape.color[2], 255)

然后,除了最后一个之外的所有颜色都会正确绘制。最后一个默认为白色。除非我一遍又一遍地循环绘制。然后就可以了。

发生了什么事?我不太擅长 OpenGL,而且不知道该去哪里查看。

完整示例:

import pyglet
import ctypes
import pyglet.gl as gl

RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
VIOLET = (255, 0, 255)


def start_render():

    gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
    gl.glMatrixMode(gl.GL_MODELVIEW)
    gl.glEnableClientState(gl.GL_VERTEX_ARRAY)


def set_viewport(left, right, bottom, top):

    # gl.glViewport(0, 0, _window.height, _window.height)
    gl.glMatrixMode(gl.GL_PROJECTION)
    gl.glLoadIdentity()
    gl.glOrtho(left, right, bottom, top, -1, 1)
    gl.glMatrixMode(gl.GL_MODELVIEW)
    gl.glLoadIdentity()


def open_window(width, height, window_title):

    window = pyglet.window.Window(width=width, height=height,
                                  caption=window_title)
    set_viewport(0, width - 1, 0, height - 1)
    window.invalid = False

    return window


class VertexBuffer:

    def __init__(self, vbo_id: gl.GLuint, size: float, draw_mode: int):
        self.vbo_id = vbo_id
        self.size = size
        self.draw_mode = draw_mode
        self.color = None
        self.line_width = 0


def create_rectangle(center_x, center_y, width, height, color):

    x1 = -width / 2 + center_x
    y1 = -height / 2 + center_y

    x2 = width / 2 + center_x
    y2 = -height / 2 + center_y

    x3 = width / 2 + center_x
    y3 = height / 2 + center_y

    x4 = -width / 2 + center_x
    y4 = height / 2 + center_y

    data = [x1, y1,
            x2, y2,
            x3, y3,
            x4, y4]

    # print(data)
    vbo_id = gl.GLuint()

    gl.glGenBuffers(1, ctypes.pointer(vbo_id))

    # Create a buffer with the data
    # This line of code is a bit strange.
    # (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number
    # (*data) initalizes the list with the floats. *data turns the list into a
    # tuple.
    data2 = (gl.GLfloat * len(data))(*data)

    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id)
    gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2,
                    gl.GL_STATIC_DRAW)

    shape_mode = gl.GL_QUADS

    shape = VertexBuffer(vbo_id, len(data) // 2, shape_mode)

    shape.color = color
    return shape


def render(shape):

    gl.glLoadIdentity()
    gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)
    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, shape.vbo_id)

    gl.glColor4ub(shape.color[0], shape.color[1], shape.color[2], 255)
    gl.glDrawArrays(shape.draw_mode, 0, shape.size)


class MyApp:
    def __init__(self):
        self.r1 = None
        self.r2 = None
        self.r3 = None
        self.r4 = None
        self.window = None

    def setup(self):
        self.window = open_window(800, 600, "Test 2")

        self.r1 = create_rectangle(100, 100, 50, 50, RED)     # Green
        self.r2 = create_rectangle(200, 200, 50, 50, GREEN)   # Blue
        self.r3 = create_rectangle(300, 300, 50, 50, BLUE)    # Violet
        self.r4 = create_rectangle(400, 400, 50, 50, VIOLET)  # Red

        pyglet.clock.schedule_interval(self.draw, 1/60)

    def draw(self, dt):
        start_render()
        render(self.r1)
        render(self.r2)
        render(self.r3)
        render(self.r4)


def main1():
    # This just draws one frame and stops.
    window = open_window(800, 600, "Test 1")

    r1 = create_rectangle(100, 100, 50, 50, RED)
    r2 = create_rectangle(200, 200, 50, 50, GREEN)
    r3 = create_rectangle(300, 300, 50, 50, BLUE)
    r4 = create_rectangle(400, 400, 50, 50, VIOLET)

    start_render()
    render(r1)
    render(r2)
    render(r3)
    render(r4)
    window.flip()

    pyglet.app.run()


def main2():
    # This main function repeatedly updates the screen.
    app = MyApp()
    app.setup()

    pyglet.app.run()


main1()

最佳答案

gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)
                                      ^ what VBO is bound?
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, shape.vbo_id)

顺序错误。现在 glVertexPointer() 正在使用您碰巧绑定(bind)的任何缓冲区。

绑定(bind)然后指针:

gl.glBindBuffer(gl.GL_ARRAY_BUFFER, shape.vbo_id)  
gl.glVertexPointer(2, gl.GL_FLOAT, 0, 0)

关于python - 颜色未按预期应用 glDrawArrays (Pyglet),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46985716/

相关文章:

c - opengl矩阵数学乘法

python - 无法在 Django 中上传图片

opengl - 在GLSL中使用OpenGL Toon Shader

python - pandas.unique() 的奇怪内存消耗

math - glsl 和不同值的透视校正

Pyglet,如何使ESCAPE键不关闭窗口?

python - 在 3D 动画中在摄像机前绘制新的球体

python - Win32 事件循环似乎是程序瓶颈

python - 从多序列比对中输出相同的列

python - 如何使用Python和托管身份/SAS凭据从VM访问Azure存储帐户