使用glDrawArrays(Pyglet)不会按预期应用颜色

时间:2017-10-28 02:39:31

标签: 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)

...我得到的颜色是一次性的。如果我绘制红色,绿色,蓝色,紫色方块,我实际上得到绿色,蓝色,紫色,红色。

如果我交换颜色并画出这样的线条:

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()

1 个答案:

答案 0 :(得分:1)

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

订单错误。现在glVertexPointer()正在使用您遇到的任何缓冲区。

绑定然后指针:

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