[英]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.