-1

How to resolve an error that I'm getting trying to assign values to memory allocated by glMapBufferRange This is a problematic function, due to not having casts in python. I am trying to assign values to this memory, though am experiencing the error stated in the title. I have also tried to create a np.array with a dimension of the size material but to no avail. Perhaps just not doing it correctly.

Update and SUCCESS! With the amazing help of Rabbid76 and the fixes first to allocate and be able to assign to glMapBufferRange memory, and then to the sbmloader.py the program renders successfully. Thank you.

Final results also found on my github PythonOpenGLSuperBible7Glut

support files: hdrbloom_support.zip

expected output rendering is what the actual results are rendering:

expected output rendering

source code:

#!/usr/bin/python3

import sys
import time
import ctypes

fullscreen = True
sys.path.append("./shared")

from sbmloader import SBMObject    # location of sbm file format loader
from ktxloader import KTXObject    # location of ktx file format loader
from textoverlay import OVERLAY_
from shader import shader_load, link_from_shaders

from sbmath import m3dDegToRad, m3dRadToDeg, m3dTranslateMatrix44, m3dRotationMatrix44, \
    m3dMultiply, m3dOrtho, m3dPerspective, rotation_matrix, translate, m3dScaleMatrix44, \
    scale, m3dLookAt, normalize

try:
    from OpenGL.GLUT import *
    from OpenGL.GL import *
    from OpenGL.GLU import *
    from OpenGL.raw.GL.ARB.vertex_array_object import glGenVertexArrays, glBindVertexArray
except:
    print ('''
    ERROR: PyOpenGL not installed properly.
        ''')
    sys.exit()

import numpy as np
from math import cos, sin
import glm
identityMatrix = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]

myobject = SBMObject()
ktxobject = KTXObject()
overlay = OVERLAY_()

MAX_SCENE_WIDTH     = 2048
MAX_SCENE_HEIGHT    = 2048
SPHERE_COUNT        = 32


tex_src = GLuint(0)
tex_lut = GLuint(0)

render_fbo = GLuint(0)
filter_fbo = [ GLuint(0) for _ in range(2) ]

tex_scene = GLuint(0)
tex_brightpass = GLuint(0)
tex_depth = GLuint(0)
tex_filter = [ GLuint(0) for _ in range(2) ]

program_render  = GLuint(0)
program_filter  = GLuint(0)
program_resolve  = GLuint(0)
vao  = GLuint(0)
exposure = 1.0
mode = 0
paused = False
bloom_factor = 1.0
show_bloom = True
show_scene = True
show_prefilter = False
bloom_thresh_min = 0.8
bloom_thresh_max = 1.2

class UNIFORMS_:

    class scene:
        bloom_thresh_min = 0.8
        bloom_thresh_max = 1.2

    class resolve:
        exposure = 1.0
        bloom_factor = 1.0
        scene_factor = 0

uniforms = UNIFORMS_()

ubo_transform = GLuint(0)
ubo_material = GLuint(0)

def load_shaders():
    global program_render
    global program_filter
    global program_resolve
    global uniforms

    shaders = [GLuint(0), GLuint(0)]

    if (program_render):
        glDeleteProgram(program_render)

    shaders[0] = shader_load("hdrbloom-scene.vs.glsl", GL_VERTEX_SHADER)
    shaders[1] = shader_load("hdrbloom-scene.fs.glsl", GL_FRAGMENT_SHADER)
    program_render = link_from_shaders(shaders, 2, True)

    uniforms.scene.bloom_thresh_min = glGetUniformLocation(program_render, "bloom_thresh_min")
    uniforms.scene.bloom_thresh_max = glGetUniformLocation(program_render, "bloom_thresh_max")

    if (program_filter):
        glDeleteProgram(program_filter)

    shaders[0] = shader_load("hdrbloom-filter.vs.glsl", GL_VERTEX_SHADER)
    shaders[1] = shader_load("hdrbloom-filter.fs.glsl", GL_FRAGMENT_SHADER)
    program_filter = link_from_shaders(shaders, 2, True)

    if (program_resolve):
        glDeleteProgram(program_resolve)

    shaders[0] = shader_load("hdrbloom-resolve.vs.glsl", GL_VERTEX_SHADER)
    shaders[1] = shader_load("hdrbloom-resolve.fs.glsl", GL_FRAGMENT_SHADER)
    program_resolve = link_from_shaders(shaders, 2, True)

    uniforms.resolve.exposure = glGetUniformLocation(program_resolve, "exposure")
    uniforms.resolve.bloom_factor = glGetUniformLocation(program_resolve, "bloom_factor")
    uniforms.resolve.scene_factor = glGetUniformLocation(program_resolve, "scene_factor")



class Scene:

    def __init__(self, width, height):
        global myobject
        global vao
        global render_fbo
        global tex_scene
        global tex_brightpass
        global tex_depth
        global filter_fbo
        global tex_filter
        global tex_lut
        global ubo_transform
        global ubo_material

        self.width = width
        self.height = height


        buffers = [ GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 ]

        glGenVertexArrays(1, vao)
        glBindVertexArray(vao)

        load_shaders()

        exposureLUT   = [ 11.0, 6.0, 3.2, 2.8, 2.2, 1.90, 1.80, 1.80, 1.70, 1.70,  1.60, 1.60, 1.50, 1.50, 1.40, 1.40, 1.30, 1.20, 1.10, 1.00 ]

        glGenFramebuffers(1, render_fbo)
        glBindFramebuffer(GL_FRAMEBUFFER, render_fbo)

        tex_scene = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, tex_scene)
        glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA16F, MAX_SCENE_WIDTH, MAX_SCENE_HEIGHT)
        glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_scene, 0)

        tex_brightpass = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, tex_brightpass)
        glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA16F, MAX_SCENE_WIDTH, MAX_SCENE_HEIGHT)
        glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, tex_brightpass, 0)

        tex_depth = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, tex_depth)
        glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, MAX_SCENE_WIDTH, MAX_SCENE_HEIGHT)
        glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, tex_depth, 0)
        glDrawBuffers(2, buffers)

        #glGenFramebuffers(2, filter_fbo[0])
        filter_fbo = [ glGenFramebuffers(1) for _ in range(2)]

        #glGenTextures(2, tex_filter[0])
        tex_filter = [glGenTextures(1) for _ in range(2)]


        for i in range(0,2):

            glBindFramebuffer(GL_FRAMEBUFFER, filter_fbo[i])
            glBindTexture(GL_TEXTURE_2D, tex_filter[i])
            glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA16F, MAX_SCENE_WIDTH if i==0 else MAX_SCENE_HEIGHT, MAX_SCENE_HEIGHT if i==0 else MAX_SCENE_WIDTH)
            glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex_filter[i], 0)
            glDrawBuffers(1, buffers)

        glBindFramebuffer(GL_FRAMEBUFFER, 0)

        tex_lut = glGenTextures(1)
        glBindTexture(GL_TEXTURE_1D, tex_lut)
        glTexStorage1D(GL_TEXTURE_1D, 1, GL_R32F, 20)
        glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 20, GL_RED, GL_FLOAT, exposureLUT)
        glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)

        myobject.load("torus.sbm")

        glGenBuffers(1, ubo_transform)
        glBindBuffer(GL_UNIFORM_BUFFER, ubo_transform)
        glBufferData(GL_UNIFORM_BUFFER, (2 + SPHERE_COUNT) * glm.sizeof(glm.mat4), None, GL_DYNAMIC_DRAW)

        class material:
            diffuse_color = glm.vec3
            specular_color = glm.vec3
            specular_power = GLfloat(0)
            ambient_color = glm.vec3

        glGenBuffers(1, ubo_material)
        glBindBuffer(GL_UNIFORM_BUFFER, ubo_material)


        size_material = ctypes.sizeof(ctypes.c_float) * 12;

        glBufferData(GL_UNIFORM_BUFFER, SPHERE_COUNT * size_material, None, GL_STATIC_DRAW)

        mat = glMapBufferRange(GL_UNIFORM_BUFFER, 0, SPHERE_COUNT * size_material, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)
        m = (GLfloat * 12 * SPHERE_COUNT).from_address(mat)

        ambient = 0.002
        for i in range(SPHERE_COUNT):

            fi = 3.14159267 * i / 8.0

            m[i][0:3]  = (ctypes.c_float * 3)(sin(fi) * 0.5 + 0.5, sin(fi + 1.345) * 0.5 + 0.5, sin(fi + 2.567) * 0.5 + 0.5)
            m[i][4:7]  = (ctypes.c_float * 3)(2.8, 2.8, 2.9)
            m[i][7]    = 30
            m[i][8:11] = (ctypes.c_float * 3)(ambient * 0.025, ambient * 0.025, ambient * 0.025)

            ambient *= 1.5

        glUnmapBuffer(GL_UNIFORM_BUFFER)

    def display(self):
        global program_filter
        global program_resolve
        global program_render
        global tex_filter
        global exposure
        global vao
        global filter_fbo
        global ubo_transform
        global ubo_material
        global bloom_thresh_min
        global bloom_thresh_max
        global uniforms
        global tex_brightpass
        global myobject
        global render_fbo

        currentTime = time.time()

        black = [ 0.0, 0.0, 0.0, 1.0 ]
        one = 1.0
        last_time = 0.0
        total_time = 0.0

        if (not paused):
            total_time += (currentTime - last_time)

        last_time = currentTime
        t = total_time

        glViewport(0, 0, self.width, self.height)

        glBindFramebuffer(GL_FRAMEBUFFER, render_fbo)
        glClearBufferfv(GL_COLOR, 0, black)
        glClearBufferfv(GL_COLOR, 1, black)
        glClearBufferfv(GL_DEPTH, 0, one)

        glEnable(GL_DEPTH_TEST)
        glDepthFunc(GL_LESS)

        glUseProgram(program_render)

        glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo_transform)

        class transforms_t:
            mat_proj = glm.mat4
            mat_view = glm.mat4
            mat_model = [glm.mat4 for _ in range(SPHERE_COUNT)]

        size_transforms_t = glm.sizeof(glm.mat4) * (SPHERE_COUNT+2)

        mbuffer = glMapBufferRange(GL_UNIFORM_BUFFER, 0, size_transforms_t, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)
        bufferp = (GLfloat * 16 * (SPHERE_COUNT+2)).from_address(mbuffer)

        mat_proj = (GLfloat * 16)(*identityMatrix)
        mat_proj = m3dPerspective(m3dDegToRad(50.0), float(self.width) / float(self.height), 1.0, 1000.0)

        T = (GLfloat * 16)(*identityMatrix)
        m3dTranslateMatrix44(T, 0.0, 0.0, -20.0)

        bufferp[0] = mat_proj

        bufferp[1] = T

        for i in range(2, SPHERE_COUNT+2):

            fi = 3.141592 * i / 16.0
            # // float r = cosf(fi * 0.25f) * 0.4f + 1.0f
            r = 0.6 if (i & 2) else 1.5

            T1 = (GLfloat * 16)(*identityMatrix)
            m3dTranslateMatrix44(T1, cos(t + fi) * 5.0 * r, sin(t + fi * 4.0) * 4.0, sin(t + fi) * 5.0 * r)

            RY = (GLfloat * 16)(*identityMatrix)
            m3dRotationMatrix44(RY, currentTime * m3dDegToRad(30.0) * fi, sin(t + fi * 2.13) * 75.0, cos(t + fi * 1.37) * 92.0, 0.0)

            m_model = (GLfloat * 16)(*identityMatrix)
            m_model = m3dMultiply(T1, RY)            

            bufferp[i] = m_model


        glUnmapBuffer(GL_UNIFORM_BUFFER)
        glBindBufferBase(GL_UNIFORM_BUFFER, 1, ubo_material)

        glUniform1f(uniforms.scene.bloom_thresh_min, bloom_thresh_min)
        glUniform1f(uniforms.scene.bloom_thresh_max, bloom_thresh_max)

        myobject.render(SPHERE_COUNT)

        glDisable(GL_DEPTH_TEST)

        glUseProgram(program_filter)

        glBindVertexArray(vao)

        glBindFramebuffer(GL_FRAMEBUFFER, filter_fbo[0])
        glBindTexture(GL_TEXTURE_2D, tex_brightpass)
        glViewport(0, 0, self.height, self.width)

        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)

        glBindFramebuffer(GL_FRAMEBUFFER, filter_fbo[1])
        glBindTexture(GL_TEXTURE_2D, tex_filter[0])
        glViewport(0, 0, self.width, self.height)

        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)

        glUseProgram(program_resolve)

        glUniform1f(uniforms.resolve.exposure, exposure)

        if (show_prefilter):
            glUniform1f(uniforms.resolve.bloom_factor, 0.0)
            glUniform1f(uniforms.resolve.scene_factor, 1.0)

        else:
            glUniform1f(uniforms.resolve.bloom_factor, bloom_factor if show_bloom else 0.0)
            glUniform1f(uniforms.resolve.scene_factor, 1.0 if show_scene else  0.0 )


        glBindFramebuffer(GL_FRAMEBUFFER, 0)
        glActiveTexture(GL_TEXTURE1)
        glBindTexture(GL_TEXTURE_2D, tex_filter[1])
        glActiveTexture(GL_TEXTURE0)
        glBindTexture(GL_TEXTURE_2D, tex_brightpass if show_prefilter else tex_scene)

        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)


        glutSwapBuffers()

    def reshape(self, width, height):
        self.width = width
        self.height = height

    def keyboard(self, key, x, y ):
        global fullscreen

        print ('key:' , key)
        if key == b'\x1b': # ESC
            sys.exit()

        elif key == b'f' or key == b'F': #fullscreen toggle
            if (fullscreen == True):
                glutReshapeWindow(512, 512)
                glutPositionWindow(int((1360/2)-(512/2)), int((768/2)-(512/2)))
                fullscreen = False
            else:
                glutFullScreen()
                fullscreen = True

    def init(self):
        pass

    def timer(self, blah):
        glutPostRedisplay()
        glutTimerFunc( int(1/60), self.timer, 0)
        time.sleep(1/60.0)

if __name__ == '__main__':
    glutInit()
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
    glutInitWindowSize(512, 512)
    w1 = glutCreateWindow('OpenGL SuperBible - HDR Bloom')
    glutInitWindowPosition(int((1360/2)-(512/2)), int((768/2)-(512/2)))
    fullscreen = False
    #glutFullScreen()
    scene = Scene(512,512)
    glutReshapeFunc(scene.reshape)
    glutDisplayFunc(scene.display)
    glutKeyboardFunc(scene.keyboard)
    glutIdleFunc(scene.display)
    #glutTimerFunc( int(1/60), scene.timer, 0)
    scene.init()
    glutMainLoop()

ported from: hdrbloom.cpp a Superbible Opengl example 7th ed. p.490

Stan S.
  • 237
  • 7
  • 22
  • On this indeed fine day, may I ask you sir to post the full error message your code is so unfortunately outputting? – ForceBru Jul 04 '19 at 09:41
  • Indeed sire, something like the heinous: `Traceback (most recent call last): File "hdrbloom.py", line 411, in scene = Scene(512,512) File "hdrbloom.py", line 235, in __init__ m[i][0] = glm.vec3(sin(fi) * 0.5 + 0.5, sin(fi + 1.345) * 0.5 + 0.5, sin(fi + 2.567) * 0.5 + 0.5) TypeError: expected c_float_Array_12_Array_3 instance, got glm.vec3 Segmentation fault (core dumped)' – Stan S. Jul 04 '19 at 09:44
  • 1
    Please put the error message in the question rather than as a comment. – G.M. Jul 04 '19 at 10:14
  • You probably want to use something like [`glm.value_ptr(glm.vec3(...`](https://glm.g-truc.net/0.9.2/api/a00248.html#gac21518f95a134dbe3c61460c89264b08) to get the data pointer associated with the `glm::vec3` type. – G.M. Jul 04 '19 at 10:18

1 Answers1

1

First of all note, that the memory layout of the (std140) structure in the uniform block

struct material_t
{
   vec3    diffuse_color;
   vec3    specular_color;
   float   specular_power;
   vec3    ambient_color;
};

is

diffuse_color  : 3 floats (x, y, z), 1 float  alignment
specular_color : 3 floats (x, y, z),
specular_power : 1 float,            
ambient_color  : 3 floats (x, y, z), 1 float  alignment

Please read Should I ever use a vec3 inside of a uniform buffer or shader storage buffer object?
and see OpenGL 4.6 API Core Profile Specification; 7.6.2.2 Standard Uniform Block Layout, page 144.

Thus the size of the buffer is 12 * ctypes.sizeof(ctypes.c_float)

size_material = ctypes.sizeof(ctypes.c_float) * 12;

Create the buffer for the uniform block array:

layout (binding = 1, std140) uniform MATERIAL_BLOCK
{
   material_t  material[32];
} materials;
glBufferData(GL_UNIFORM_BUFFER, SPHERE_COUNT * size_material, None, GL_STATIC_DRAW)

Map a 2 dimensional array, with shape (SPHERE_COUNT, 12) to the buffer memory:

mat = glMapBufferRange(GL_UNIFORM_BUFFER, 0, SPHERE_COUNT * size_material, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)
m = (GLfloat * 12 * SPHERE_COUNT).from_address(mat)

Assign the values in the loop by array assignment:

ambient = 0.002
for i in range(SPHERE_COUNT):

    fi = 3.14159267 * i / 8.0

    m[i][0:3]  = (ctypes.c_float * 3)(sin(fi) * 0.5 + 0.5, sin(fi + 1.345) * 0.5 + 0.5, sin(fi + 2.567) * 0.5 + 0.5)
    m[i][4:7]  = (ctypes.c_float * 3)(2.8, 2.8, 2.9)
    m[i][7]    = 30
    m[i][8:11] = (ctypes.c_float * 3)(ambient * 0.025, ambient * 0.025, ambient * 0.025)

    ambient *= 1.5

The size of the 2nd uniform block

layout (binding = 0, std140) uniform TRANSFORM_BLOCK
{
   mat4    mat_proj;
   mat4    mat_view;
   mat4    mat_model[32];
} transforms;

is

size_transforms_t = glm.sizeof(glm.mat4) * (SPHERE_COUNT+2)

Map a 2 dimensional array, with shape ((SPHERE_COUNT+2), 16) to the buffer memory:

mbuffer = glMapBufferRange(GL_UNIFORM_BUFFER, 0, size_transforms_t, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)
bufferp = (GLfloat * 16 * (SPHERE_COUNT+2)).from_address(mbuffer)

SBMObject.render_sub_object doesn't render the instances. It has to be somthing like:

 def render_sub_object(self, object_index, instance_count, base_instance):
        global index_type

        glBindVertexArray(self.vao)

        if instance_count == 0:
            glDrawArrays(GL_TRIANGLES, 0, self.vertexcount)
        else:
            glDrawArraysInstancedBaseInstance(GL_TRIANGLES,
                                               0,
                                               self.vertexcount,
                                               instance_count,
                                               base_instance)

        # [...]

show_prefilter, show_bloom and show_scene are boolean values, they'll never be equal 0.0. Either the uniform float bloom_factor or float scene_factor has to be grater then 0.0, else the fragment color is black.

glUniform1f(uniforms.resolve.bloom_factor, bloom_factor if show_bloom==0 else 0.0)
glUniform1f(uniforms.resolve.scene_factor, 1.0 if show_scene==0 else 0.0)
glUniform1f(uniforms.resolve.bloom_factor, bloom_factor if show_bloom else 0.0)
glUniform1f(uniforms.resolve.scene_factor, 1.0 if show_scene else 0.0 )

glBindTexture(GL_TEXTURE_2D, tex_brightpass if show_prefilter==0 else tex_scene)
glBindTexture(GL_TEXTURE_2D, tex_brightpass if show_prefilter else tex_scene)

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • I have uploaded your excellent source code fixes. I am still getting a blank screen. Perhaps you can take another look. Overall, this answer has been perfect and gotten me past the `glMapBufferRange` memory assignment issues and definitely going to be an accepted answer. Thank you. – Stan S. Jul 04 '19 at 12:01
  • @StanS. Is the issue finally solved or is there still a black screen? – Rabbid76 Jul 04 '19 at 15:03
  • Kindly, there is still the black screen. I thought it was one of the globals not listed but they seem all there. I'd appreciate if you can do your magic, excellent insight. Thank you. – Stan S. Jul 04 '19 at 15:15
  • That is a fantastic answer, great pickup, and and an amazing result that is rendered. Thank you so much also for the smbloader fix. It's perfect! Thank you very very much! – Stan S. Jul 04 '19 at 17:19