Sivansh Gupta
Sivansh Gupta

Reputation: 11

pyopengl blackscreen not drawing

cant seem to draw a triangle

import pygame
from pygame.locals import *
import numpy as np
from OpenGL.GL import *

pygame.init()
display = (600,600)
clock = pygame.time.Clock()
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
positions = [
    -0.5, -0.5,
    0,     0.5,
    0.5, -0.5
]
positions = np.array(positions, dtype=np.float32)
buffer = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, buffer)
glBufferData(GL_ARRAY_BUFFER, positions.size, positions, GL_STATIC_DRAW)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, 0) 
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
            pygame.quit()
    if not run:
        break

    glDrawArrays(GL_TRIANGLES, 0, 3)

    pygame.display.flip()

is this a python problem or am i writing it wrong ?

Upvotes: 1

Views: 252

Answers (2)

Rabbid76
Rabbid76

Reputation: 211277

The 2nd argument of glBufferData is the buffer size in bytes:

glBufferData(GL_ARRAY_BUFFER, positions.size, positions, GL_STATIC_DRAW)

glBufferData(GL_ARRAY_BUFFER, positions.size*4, positions, GL_STATIC_DRAW)

The parameter size can be omitted:

glBufferData(GL_ARRAY_BUFFER, positions, GL_STATIC_DRAW)

If a named buffer object is bound, then the 6th parameter of glVertexAttribPointer is treated as a byte offset into the buffer object's data store. But the type of the parameter is a pointer anyway (c_void_p). So if the offset is 0, then the 6th parameter can either be None or c_void_p(0) else the offset has to be caste to c_void_p(0):

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, 0)

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, None) 

Complete example:

import pygame
from pygame.locals import *
import numpy as np
from OpenGL.GL import *

pygame.init()
display = (600,600)
clock = pygame.time.Clock()
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
positions = [
    -0.5, -0.5,
    0,     0.5,
    0.5, -0.5
]
positions = np.array(positions, dtype=np.float32)

buffer = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, buffer)
glBufferData(GL_ARRAY_BUFFER, positions, GL_STATIC_DRAW)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, None) 

run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    glClear(GL_COLOR_BUFFER_BIT)
    glDrawArrays(GL_TRIANGLES, 0, 3)
    pygame.display.flip()

pygame.quit()

Upvotes: 3

jackw11111
jackw11111

Reputation: 1547

It is hard to know what example will work without knowing what GL version your hardware supports (print (glGetString(GL_VERSION))), but here is a compatibility demo that should work, but you should consider modifying it to at least OpenGL3.3/GLSL 330:

import pygame
from pygame.locals import *
import numpy as np
from OpenGL.GL import *

pygame.init()
display = (600,600)
clock = pygame.time.Clock()
pygame.display.set_mode(display, DOUBLEBUF|OPENGL)

positions = [
-0.5, -0.5,
0,     0.5,
0.5, -0.5
]

vertex_shader_source = """#version 120
                     attribute vec2 aPos;
                     varying vec2 pos;
                     void main()
                     {
                        gl_Position = vec4(aPos.x, aPos.y, 0, 1);
                        pos = aPos;
                     }"""

fragment_shader_source = """#version 120
                        varying vec2 pos;
                        void main()
                        {
                           gl_FragColor = vec4(pos.x, pos.y,0,1);
                        }"""

vertex_shader = glCreateShader(GL_VERTEX_SHADER)
glShaderSource(vertex_shader, vertex_shader_source)
glCompileShader(vertex_shader)
if glGetShaderiv(vertex_shader, GL_COMPILE_STATUS) != GL_TRUE:
    raise RuntimeError(glGetShaderInfoLog(vertex_shader))

fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(fragment_shader, fragment_shader_source)
glCompileShader(fragment_shader)
if glGetShaderiv(fragment_shader, GL_COMPILE_STATUS) != GL_TRUE:
    raise RuntimeError(glGetShaderInfoLog(fragment_shader))

shader_program = glCreateProgram()
glAttachShader(shader_program, vertex_shader)
glAttachShader(shader_program, fragment_shader)

glLinkProgram(shader_program)

positions = np.array(positions, dtype=np.float32)
VAO = glGenVertexArrays(1)
VBO = glGenBuffers(1)
glBindVertexArray(VAO)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
# using positions.size * np.dtype(np.float32).itemsize
# to get the size (in bytes) of the vertex data
glBufferData(GL_ARRAY_BUFFER, positions.size * np.dtype(np.float32).itemsize, \
positions, GL_STATIC_DRAW)
glEnableVertexAttribArray(0)

aPos = glGetAttribLocation(shader_program, 'aPos')
glEnableVertexAttribArray(aPos)
# ctypes.c_void_p(0) to specify the offset (0 wont work)
glVertexAttribPointer(aPos, 2, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))

if glGetProgramiv(shader_program, GL_LINK_STATUS) != GL_TRUE:
    raise RuntimeError(glGetProgramInfoLog(shader_program))

glClearColor(0,0,1,1);

run = True
while run:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
            pygame.quit()
    if not run:
        break

    glClear(GL_COLOR_BUFFER_BIT)
    glUseProgram(shader_program)
    glBindVertexArray(VAO)
    glDrawArrays(GL_TRIANGLES, 0, 3)

    pygame.display.flip()

Result:

pygame triangle example

Upvotes: 0

Related Questions