简体   繁体   English

颜色不适用于 glDrawArrays (Pyglet)

[英]Color doesn't apply as expected with glDrawArrays (Pyglet)

If I draw rectangles with the following code:如果我使用以下代码绘制矩形:

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)

...The colors I get are one off. ...我得到的颜色是一种。 If I draw Red, Green, Blue, Violet squares, I actually get Green, Blue, Violet, Red.如果我画红色、绿色、蓝色、紫色方块,我实际上会得到绿色、蓝色、紫色、红色。

If I swap the color and draw lines like this:如果我交换颜色并绘制如下线条:

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)

Then all but the last will draw the colors correctly.然后除了最后一个之外的所有内容都会正确绘制颜色。 The last defaults to white.最后一个默认为白色。 UNLESS I draw over and over in a loop.除非我在循环中一遍又一遍地绘制。 Then it is ok.然后就可以了。

What is happening?怎么了? I'm not great at OpenGL and I'm not sure where to look.我不太擅长 OpenGL,也不知道去哪里找。

Full example:完整示例:

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)

Wrong order.错误的顺序。 Right now glVertexPointer() is using whatever buffer you happened to have bound.现在glVertexPointer()正在使用您碰巧绑定的任何缓冲区。

Bind then Pointer:绑定然后指针:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM