Невозможно отобразить полный VAO, если данные VBO были частично обновлены с помощью glBufferSubData().Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Невозможно отобразить полный VAO, если данные VBO были частично обновлены с помощью glBufferSubData().

Сообщение Anonymous »

Я пытаюсь визуализировать несколько моделей, загруженных из файлов OBJ, с помощью одного VBO с использованием VAO. Помимо VBO у меня есть еще два буфера — CBO (цвета) и IBO (индексы).

Код: Выделить всё

import pygame
from pathlib import Path
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GL import shaders
import numpy as np
import pywavefront
from math import sin, cos, tan, atan2

def calcFrustumScale(fFovDeg):
degToRad = np.pi * 2.0 / 360.0
fFovRad = fFovDeg * degToRad
return 1.0 / tan(fFovRad / 2.0)

def calcLerpFactor(fElapsedTime, fLoopDuration):
fValue = (fElapsedTime % fLoopDuration) / fLoopDuration
if fValue >  0.5:
fValue = 1.0 - fValue
return fValue * 2.0

def computeAngleRad(fElapsedTime, fLoopDuration):
fScale = np.pi * 2.0 / fLoopDuration
fCurrTimeThroughLoop = fElapsedTime % fLoopDuration
return fCurrTimeThroughLoop * fScale

def load_model(single_model_path: Path, color: np.array = np.array([*np.random.uniform(0.0, 1.0, 3), 1.0], dtype='float32')):
scene = pywavefront.Wavefront(single_model_path, collect_faces=True)

model = {
'vertex' : np.array(scene.vertices, dtype='float32'),
'face' : np.array(scene.mesh_list[0].faces, dtype='uint32')
}
model['color'] = np.full((len(model['vertex']), 4), color, dtype='float32')

return model

def get_rotate_y(elapsed_time):
angle_rad = computeAngleRad(elapsed_time, 2.0)
_cos = cos(angle_rad)
_sin = sin(angle_rad)

transform = np.identity(4, dtype='float32')
transform[0][0] = _cos
transform[2][0] = _sin
transform[0][2] = -_sin
transform[2][2] = _cos
# offset
transform[0][3] = 0.0 #-5.0
transform[1][3] = 0.0 #5.0
transform[2][3] = -10
return transform

def rand_range(start, stop, step):
r = np.random.randint(0, int((stop - start) / step))
return r, r * step + start

def model_info(model: dict):
print('Model (static) vertex bytesize:\t', model['vertex'].nbytes)
print('Model (static) face bytesize:  \t', model['face'].nbytes)
print('Model (static) color bytesize: \t', model['color'].nbytes)

color_rnd = np.array([*np.random.uniform(0.0, 1.0, 3), 1.0], dtype='float32')
print(color_rnd)

modelToCameraMatrixUnif = None
cameraToClipMatrixUnif = None

# Global display variables
cameraToClipMatrix = np.zeros((4,4), dtype='float32')
fFrustumScale = calcFrustumScale(45.0)

model_static = load_model(Path('cube_static.obj'))
model_dynamic = [
load_model(_m, color=np.array([*np.random.uniform(0.0, 1.0, 3), 1.0], dtype='float32'))
for _m in list(Path('.').glob('cube_dynamic_*.obj'))
]
model_info(model_static)

VBO_BUFFER_SIZE = 1000 * np.array([0, 0, 0], dtype='float32').nbytes
print('VBO total bytesize:', VBO_BUFFER_SIZE)

IBO_BUFFER_SIZE = 1000 * np.array([0, 0, 0, 1], dtype='float32').nbytes
print('IBO total bytesize:', IBO_BUFFER_SIZE)

CBO_BUFFER_SIZE = 1000 * np.array([0, 0, 0], dtype='uint32').nbytes
print('CBO total bytesize:', CBO_BUFFER_SIZE)

vertex_shader = '''
#version 330

layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;

smooth out vec4 theColor;

uniform mat4 cameraToClipMatrix;
uniform mat4 modelToCameraMatrix;

void main()
{
vec4 cameraPos = modelToCameraMatrix * position;
gl_Position = cameraToClipMatrix * cameraPos;
theColor = color;
}
'''

fragment_shader = '''
#version 330

smooth in vec4 theColor;
out vec4 outputColor;

void main()
{
outputColor = theColor;
}
'''

vbo = None
cbo = None
ibo = None
vao = None

program = None

def initialize():
global model_static
global vbo, cbo, ibo, vao
global program
global modelToCameraMatrixUnif, cameraToClipMatrixUnif, cameraToClipMatrix

pygame.init()
display = (800, 800)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)

vertex_shader_id = shaders.compileShader(vertex_shader, GL_VERTEX_SHADER)
fragment_shader_id = shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER)
program = shaders.compileProgram(vertex_shader_id, fragment_shader_id)

glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glFrontFace(GL_CW)

glEnable(GL_DEPTH_TEST)
glDepthMask(GL_TRUE)
glDepthFunc(GL_LEQUAL)
glDepthRange(0.0, 1.0)

glUseProgram(program)
modelToCameraMatrixUnif = glGetUniformLocation(program, "modelToCameraMatrix")
cameraToClipMatrixUnif = glGetUniformLocation(program, "cameraToClipMatrix")
glUseProgram(0)

fzNear = 1.0
fzFar = 100.0

# Note that this and the transformation matrix below are both
# ROW-MAJOR ordered.  Thus, it is necessary to pass a transpose
# of the matrix to the glUniform assignment function.
cameraToClipMatrix[0][0] = fFrustumScale
cameraToClipMatrix[1][1] = fFrustumScale
cameraToClipMatrix[2][2] = (fzFar + fzNear) / (fzNear - fzFar)
cameraToClipMatrix[2][3] = -1.0
cameraToClipMatrix[3][2] = (2 * fzFar * fzNear) / (fzNear - fzFar)

glUseProgram(program)
glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, cameraToClipMatrix.transpose())
glUseProgram(0)

vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(
GL_ARRAY_BUFFER,
VBO_BUFFER_SIZE,
None,
GL_STATIC_DRAW)
glBufferSubData(
GL_ARRAY_BUFFER,
0,
model_static['vertex'].nbytes,
model_static['vertex'].ravel()
)
glBindBuffer(GL_ARRAY_BUFFER, 0)

cbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, cbo)
glBufferData(
GL_ARRAY_BUFFER,
CBO_BUFFER_SIZE,
None,
GL_STATIC_DRAW)
glBufferSubData(
GL_ARRAY_BUFFER,
0,
model_static['color'].nbytes,
model_static['color'].ravel()
)
glBindBuffer(GL_ARRAY_BUFFER, 0)

ibo = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
IBO_BUFFER_SIZE,
None,
GL_STATIC_DRAW)
glBufferSubData(
GL_ELEMENT_ARRAY_BUFFER,
0,
model_static['face'].nbytes,
model_static['face'].ravel()
)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)

vao = glGenVertexArrays(1)
glBindVertexArray(vao)
vertex_dim = 3
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, vertex_dim, GL_FLOAT, GL_FALSE, 0, None)

color_dim = 4
glBindBuffer(GL_ARRAY_BUFFER, cbo)
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, color_dim, GL_FLOAT, GL_FALSE, 0, None)

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)

glBindVertexArray(0)

def update_vbo(idx):
global vbo
global model_static

print('VBO 1st vertex', model_dynamic[idx]['vertex'][0])
offset = model_static['vertex'].nbytes
print('VBO offset', offset)

glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferSubData(
GL_ARRAY_BUFFER,
offset,
model_dynamic[idx]['vertex'].nbytes,
model_dynamic[idx]['vertex'].ravel()
)
glBindBuffer(GL_ARRAY_BUFFER, 0)

def update_cbo(idx):
global cbo
global model_static

print('CBO 1st color', model_dynamic[idx]['color'][0])
offset = model_static['color'].nbytes
print('CBO offset', offset)

glBindBuffer(GL_ARRAY_BUFFER, cbo)
glBufferSubData(
GL_ARRAY_BUFFER,
offset,
model_dynamic[idx]['color'].nbytes,
model_dynamic[idx]['color'].ravel()
)
glBindBuffer(GL_ARRAY_BUFFER, 0)

def update_ibo(idx):
global ibo
global model_static

print('IBO 1st face', model_dynamic[idx]['face'][0])
offset = model_static['face'].nbytes
print('IBO offset', offset)

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)
glBufferSubData(
GL_ELEMENT_ARRAY_BUFFER,
offset,
model_dynamic[idx]['face'].nbytes,
model_dynamic[idx]['face'].ravel()
)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)

def render():
global idx
global model_static, model_dynamic
global vao
global modelToCameraMatrixUnif

glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

glUseProgram(program)

elapsed_time = pygame.time.get_ticks() / 1000.0
transform_func = get_rotate_y
transformMatrix = transform_func(elapsed_time=elapsed_time)

glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, transformMatrix.transpose())

glBindVertexArray(vao)
index_count = model_static['face'].size + model_dynamic[idx]['face'].size
#print(model_static['face'].size, model_dynamic[idx]['face'].size, index_count)
glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT,  None)
glBindVertexArray(0)

glUseProgram(0)

pygame.display.flip()

idx = 0

def main():
global idx

initialize()

frame_count = 0
idx_prev = 0

while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
quit()

if event.type == pygame.KEYUP:
if event.key == pygame.K_u:
idx = (idx + 1) % 2
print(idx)

if idx != idx_prev:
print('Switching dynamic content ({})'.format(idx))

update_vbo(idx)
update_cbo(idx)
update_ibo(idx)

idx_prev = idx

render()

frame_count += 1

if __name__ == '__main__':
main()
Все модели, которые я загружаю в код ниже, представляют собой простые кубы (8 вершин, 12 примитивных граней) с некоторыми изменениями в масштабировании, вращении и перемещении, чтобы я мог визуализировать различия.< /p>
Объем памяти для каждого типа буфера следующий:
  • VBO — 1000 вершины, каждая из которых состоит из 3 компонентов float32 (т. е. 3*4 = 12 байт на вершину)
  • CBO – 1000 цветов, каждый из которых состоит из 4 компоненты float32 (RGBA, поэтому 4*4 = 16 байт на цвет)
  • IBO — 1000 граней, каждая из которых состоит из 3 компонентов uint32 (так что 3*4 = 12 байт на примитивную грань)
Изначально я выделил полный размер и сразу использую glBufferSubData() загрузить мою статическую модель. В отличие от динамической, статическую модель я не буду менять до завершения программы. Я перебираю динамическую модель. Каждая динамическая модель в настоящее время имеет тот же размер в байтах (включая количество вершин, цветов и граней), что и статическая.
Каждый раз, когда пользователь нажимает определенную клавишу, я увеличиваю индекс, который выбирает следующую динамическую модель (все загружается с помощью PyWavefront).
Когда я запускаю свой код, я получаю
Изображение

в качестве исходного вида. Однако при нажатии клавиши отображается, что я переключаю динамические модели (), я не могу отобразить какие-либо визуальные изменения на экране. Я ожидаю увидеть
Изображение

а затем
Изображение

рядом с первоначально отрендеренной моделью. Изображение ниже должно показать, как я представляю (отчасти) мой окончательный рендер для одной из динамических моделей:
[img]https: //i.sstatic.net/6ZMnqZBM.png[/img]


Подробнее здесь: https://stackoverflow.com/questions/784 ... ing-glbuff
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Qt и OpenGL: невозможно инициализировать VBO или VAO openGL после первого вызова PaintGL?
    Anonymous » » в форуме C++
    0 Ответы
    21 Просмотры
    Последнее сообщение Anonymous
  • Qt и OpenGL: невозможно инициализировать OpenGL VBO или VAO после первого вызова PaintGL?
    Anonymous » » в форуме C++
    0 Ответы
    36 Просмотры
    Последнее сообщение Anonymous
  • Правильное использование vbo и vao [дубликат]
    Anonymous » » в форуме C++
    0 Ответы
    28 Просмотры
    Последнее сообщение Anonymous
  • GlBufferSubData для одного треугольника не работает
    Гость » » в форуме C++
    0 Ответы
    43 Просмотры
    Последнее сообщение Гость
  • VAO не рендерится, OpenGL
    Anonymous » » в форуме C++
    0 Ответы
    18 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Python»