Ошибка типа: ожидаемый экземпляр c_float_Array_12_Array_3, полученный glm.vec3, ошибка сегмента - PullRequest
0 голосов
/ 04 июля 2019

Как устранить ошибку, которую я получаю, пытаясь присвоить значения памяти, выделенной glMapBufferRange Это проблематичная функция из-за отсутствия приведения в python. Я пытаюсь присвоить значения этой памяти, хотя испытываю ошибку, указанную в заголовке. Я также пытался создать np.array с размером material, но безрезультатно. Возможно, просто не делает это правильно.

Обновление и УСПЕХ! С помощью потрясающей помощи Rabbid76 и исправлений сначала выделите и сможете назначить память glMapBufferRange, а затем файл sbmloader.py, программа будет успешно отображаться. Спасибо.

Окончательные результаты также найдены на моем github PythonOpenGLSuperBible7Glut

файлы поддержки: hdrbloom_support.zip

ожидаемый результат рендеринга - это то, что фактические результаты рендеринга:

expected output rendering

исходный код:

#!/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()

перенесено из: hdrbloom.cpp Пример Superbible Opengl 7-е изд. p.490

1 Ответ

1 голос
/ 04 июля 2019

Прежде всего обратите внимание, что расположение памяти структуры (std140) в едином блоке

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

равно

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

Пожалуйста,прочитайте Должен ли я когда-либо использовать vec3 внутри объекта буфера хранения унифицированного буфера или шейдера?
и см. Спецификация профиля ядра API OpenGL 4.6;7.6.2.2 Стандартная структура унифицированного блока , стр. 144.

Таким образом, размер буфера равен 12 * ctypes.sizeof(ctypes.c_float)

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

Создать буфер для массива унифицированных блоков:

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

Отображение двумерного массива с формой (SPHERE_COUNT, 12) в буферную память:

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

Размер 2-го унифицированного блока

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

равен

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

Отображение двумерного массива с формой ((SPHERE_COUNT+2), 16) в буферную память:

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 не отображаетэкземпляры.Это должно быть что-то вроде:

 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 и show_scene - логические значения, они никогда не будут равны 0.0.Либо униформа float bloom_factor или float scene_factor должна быть больше, чем 0,0, иначе цвет фрагмента будет черным.

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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...