1
$\begingroup$

This code should draw the "Hello Triangle" (1) that everyone starts off with but it's not showing up. Since it's in Blender, I used (3) as a reference for when to draw. That's why the code itself does not include ClearColor because I assume Blender handles it before the draw() is called.

I've verified that the vertex buffer is filled with the correct positions by using glGetBufferSubData (code not shown). The shaders also compile without error logs. That leaves the draw call itself as the problem. I believe the render target is the 3DView because glClearColor() does change its color. It doesn't appear to be a culling problem because I've tested 3000 random verts over a [-10,10] 2D range along with turning culling off using glDisable(GL_CULL_FACE) but nothing shows. Of course, even if it did render, Blender's own UI rendering breaks after draw() finishes.. I'm not sure what I'm doing wrong. These problems apply to B2.79b and B2.80 as of the 3/21/19 build.

I have read the release notes (2) and I understand that its not advised to use bgl but it specifically advises against the the use of immediate mode and the fixed function pipeline, which isn't what I'm using.

Any and all help is greatly appreciated.

  1. http://web.archive.org/web/20140127190601/http://www.arcsynthesis.org/gltut/Basics/Tut01%20Dissecting%20Display.html
  2. https://wiki.blender.org/wiki/Reference/Release_Notes/2.80/Python_API/Draw_API

  3. https://docs.blender.org/api/blender2.8/gpu.html

_

import bpy
from bgl import *
from sys import getsizeof 

strVertexShader = """
#version 330

layout(location = 0) in vec3 position;
void main()
{
    gl_Position =  vec4(position,1.0);
}
"""

strFragmentShader ="""
#version 330

out vec4 outputColor;
void main(){ 
  outputColor = vec4(1.0, 1.0, 1.0, 1.0);
}
"""
theProgram = None

NULL_OBJ = Buffer(GL_INT,1,[0])

size = 1
positions = [0.75 * size, 0.75* size, 0.0* size,
            0.75 * size, -0.75* size, 0.0* size,
            -0.75* size, -0.75* size, 0.0* size]
vertexPositions_ptr = Buffer(GL_FLOAT,len(positions),positions)

#python doesnt support pointers, so we use bgl buffer objects instead
vertexBuffer = Buffer(GL_INT,1)

def init_vertex_buffer():
    glGenBuffers(1,vertexBuffer)

    #I verified that the buffer is written to with the vertices using glGetBufferSubData(code not shown)
    glBindBuffer(GL_ARRAY_BUFFER,vertexBuffer[0])
    glBufferData(GL_ARRAY_BUFFER,getsizeof(vertexPositions_ptr),vertexPositions_ptr,GL_DYNAMIC_DRAW)

    glBindBuffer(GL_ARRAY_BUFFER,0) 

def init_program():
    shader_list = []
    shader_list.append(create_shader(GL_VERTEX_SHADER,strVertexShader))
    shader_list.append(create_shader(GL_FRAGMENT_SHADER, strFragmentShader))

    global theProgram
    theProgram = create_program(shader_list)

    for shader in shader_list:
        glDeleteShader(shader)

def create_shader(shader_type,shader_code):
    shader = glCreateShader(shader_type)
    glShaderSource(shader,shader_code)
    glCompileShader(shader)

    #the shaders appear to be created just fine, no error logs.
    status = Buffer(GL_INT,1)
    glGetShaderiv(shader,GL_COMPILE_STATUS,status)
    if status[0] == GL_FALSE:
        infoLogLength = Buffer(GL_INT,1)
        glGetShaderiv(shader,GL_INFO_LOG_LENGTH,infoLogLength)

        infoLog = Buffer(GL_BYTE,infoLogLength[0]+1)
        glGetShaderInfoLog(shader,infoLogLength[0],infoLogLength,infoLog)

        str_shader_type = '[Unk Shader type]'
        if shader_type == GL_VERTEX_SHADER:
            str_shader_type = 'vertex'
        elif shader_type == GL_FRAGMENT_SHADER:
            str_shader_type = 'fragment'

        print('[ERROR] Shader compile error in {0} shader:\n{1}'.format(str_shader_type,buffer_to_string(infoLog)))
        del infoLog
        del infoLogLength
    del status

    return shader

def buffer_to_string(buffer):
    chars = []
    for char in buffer.to_list():
        chars.append(chr(char))
    return ''.join(chars)

def create_program(shader_list):
    program = glCreateProgram()
    for shader in shader_list:
        glAttachShader(program,shader)

    glLinkProgram(program)

    status = Buffer(GL_INT,1)
    glGetProgramiv(program,GL_LINK_STATUS,status)
    if status[0] == GL_FALSE:
        infoLogLength = Buffer(GL_INT,1)
        glGetProgramiv(program,GL_INFO_LOG_LENGTH,infoLogLength)

        infoLog = Buffer(GL_BYTE,infoLogLength[0]+1)
        glGetProgramInfoLog(program,infoLogLength[0],infoLogLength,infoLog)

        print('[ERROR] Linker error: {0}'.format(buffer_to_string(infoLog)))
        del infoLog
        del infoLogLength
    del status

    for shader in shader_list:
        glDetachShader(program,shader)

    return program

def draw():
    glUseProgram(theProgram)

    glBindBuffer(GL_ARRAY_BUFFER,vertexBuffer[0])
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,12,NULL_OBJ)

    #nothing shows and Blender's UI rendering breaks...
    glDrawArrays(GL_TRIANGLES,0,3)

    glDisableVertexAttribArray(0)
    glUseProgram(0)
    glBindBuffer(GL_ARRAY_BUFFER,0)

    error = glGetError()
    if error != 0:
        print(glGetError())

init_program()
init_vertex_buffer()   

bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
$\endgroup$
  • $\begingroup$ Hmm, this might be related to devtalk.blender.org/t/… (one cannot pass void as last argument to glVertexAttribPointer at the moment because it requires a Buffer object). This patch might fix it: developer.blender.org/D2404 or this one? developer.blender.org/P450 $\endgroup$ – Gottfried Hofmann Mar 30 at 15:49
  • $\begingroup$ After applying this patch here I can draw the triangle - the problem is glVertexAttribPointer - developer.blender.org/D2404 $\endgroup$ – Gottfried Hofmann Mar 30 at 17:37
  • $\begingroup$ thank you! I appreciate it. I suppose I'll just have to wait till the patch is applied. $\endgroup$ – Guilty Ghost Mar 31 at 4:05
  • $\begingroup$ It's finally working with current builds - glVertexAttribPointer now takes bgl.Buffer() or None $\endgroup$ – Gottfried Hofmann Apr 16 at 12:17
  • $\begingroup$ Thank you! The triangle draws though the UI rendering still breaks. I suppose this is a bug that I'll have to report. It breaks when the draw handler is added to the SpaceDopeSheetEditor and SpaceGraphSheetEditor. $\endgroup$ – Guilty Ghost Apr 30 at 21:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.