New update: Okay here is what I got so far…
Objective: Generate a 360 degree view of a scene by sampling a depth cubemap using spherical coordinates. x and y represent the horizontal, or azimuth, and elevation angles respectively and the actual value at each pixel is the depth.
Output: So far I have not been able to achieve this. I am not getting any errors just a blank 2D image.
Here are what I consider to be the essential parts of the process. First creating a cubemap to store depth information,
# CREATE EMPTY CUBEMAP
######################
CM = 2
depth_map_fbo = glGenFramebuffers(1)
glBindFramebuffer(GL_FRAMEBUFFER, depth_map_fbo)
depth_cube_tex = glGenTextures(1)
glBindTexture(GL_TEXTURE_CUBE_MAP, depth_cube_tex)
for i in range(6):
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, GL_DEPTH_COMPONENT32, CM*1024, CM*1024,
0, GL_DEPTH_COMPONENT, GL_FLOAT, None)
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST) # or GL_LINEAR?
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE)
# attach depth texture to fbo depth buffer
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_cube_tex, 0)
glDrawBuffer(GL_NONE)
glReadBuffer(GL_NONE)
glBindFramebuffer(GL_FRAMEBUFFER, 0)
Second, obtaining depth information for a simple scene made out of 3 cubes and a floor,
# CREATE A DEPTH CUBE
#####################
rotation_dict= {0: [ 0, 90, 0, 90, 'X+', 'Right'],
1: [ 0, -90, 0, -180, 'X-', 'Left'],
2: [ 90, 180, -90, 90, 'Y+', 'Top'],
3: [ -90, 180, 180, 0, 'Y-', 'Bottom'],
4: [ 0, 0, -90, 180, 'Z+', 'Back'],
5: [ 0, 180, 0, -180, 'Z-', 'Front']}
# cubemap camera
cubemap_camera.width = CM*1024
cubemap_camera.height = CM*1024
cubemap_camera.zoom = 90.0
# # bind depth map buffer
glBindFramebuffer(GL_FRAMEBUFFER, depth_map_fbo)
# set viewport size to cubemap size
glViewport(0, 0, CM*1024, CM*1024)
# activate cubemap shader
cubemap_shader.use()
# create a projection matrix
projection = glm.perspective(glm.radians(90.0), 1.0, 0.1, 100)
cubemap_shader.set_uniform_mat4('projection', projection)
# RENDER TO DEPTH CUBEMAP
##########################
for i in range(6):
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X+i,
depth_cube_tex, 0)
# all fine?
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE):
raise RuntimeError("ERROR.FRAMEBUFFER. Framebuffer is not complete!")
# clear colors and buffers
glClearColor(0.1,0.1,0.1,0.1)
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT)
# rotate camera
cubemap_camera.pitch = rotation_dict[i][0] #0
cubemap_camera.yaw = rotation_dict[i][1] #1
cubemap_camera.update_camera_vectors()
# update view (lookat matrix)?
view = cubemap_camera.get_matrix_view()
cubemap_shader.set_uniform_mat4('view',view)
# load textures
cube_texture = texture_from_file(pth, Path(r'textures/marble.jpg') )
floor_texture = texture_from_file(pth, Path(r'textures/metal.png') )
# render cubes
glBindVertexArray(cube_vao)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D, cube_texture)
# update projection and view matrices for display camera
cubemap_shader.set_uniform_mat4('projection', projection)
view = cubemap_camera.get_matrix_view()
cubemap_shader.set_uniform_mat4('view',view)
# cube 1
model = glm.mat4(1.0)
model = glm.translate(model, glm.vec3(0.0, 0.0, -5.0))
cubemap_shader.set_uniform_mat4('model', model)
glDrawArrays(GL_TRIANGLES, 0, 36)
# cube 2
model = glm.mat4(1.0)
model = glm.translate(model, glm.vec3(-5.0, 0.0, 0.0))
cubemap_shader.set_uniform_mat4('model', model)
glDrawArrays(GL_TRIANGLES, 0, 36)
# cube 3
model = glm.mat4(1.0)
model = glm.translate(model, glm.vec3(0.0, 2.0, 0.0))
cubemap_shader.set_uniform_mat4('model', model)
glDrawArrays(GL_TRIANGLES, 0, 36)
glBindVertexArray(0) # remove binding
# render floor
glBindVertexArray(floor_vao)
glBindTexture(GL_TEXTURE_2D, floor_texture)
cubemap_shader.set_uniform_mat4('model', glm.mat4(1.0))
glDrawArrays(GL_TRIANGLES, 0, 6)
glBindVertexArray(0) # remove binding
# #output ?
# zbuffer = glReadPixelsf(0, 0, CM*1024, CM*1024, GL_DEPTH_COMPONENT, GL_FLOAT)
# zbuffer = zbuffer.reshape((CM*1024, CM*1024))
# np.save(f'{rotation_dict[i][5]}_cube', np.flipud(zbuffer))
glfw.swap_buffers(window)
# unbind fbo
glBindFramebuffer(GL_FRAMEBUFFER, 0)
Last, sampling the cubemap just created. This is the part that I am less certain. Particularly, the shaders...
# SAMPLING CUBEMAP
##################
hangle = np.array([0,360,0.05], dtype=np.float32)
vangle = np.array([-90,0, 0.05], dtype=np.float32)
width = int((hangle[1]-hangle[0]) / hangle[2])
height = int((vangle[1]-vangle[0]) / vangle[2])
# create scene buffer
scene_buffer = glGenFramebuffers(1)
glBindFramebuffer(GL_FRAMEBUFFER, scene_buffer)
# attach a render buffer
rbo = glGenRenderbuffers(1)
glBindRenderbuffer(GL_RENDERBUFFER, rbo)
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, width, height)
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo)
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE):
raise RuntimeError("ERROR.FRAMEBUFFER. Framebuffer is not complete!")
# send information to sampling shader
cubemap_sampling_shader.use()
cubemap_sampling_shader.set_uniform_vec3('hangle', hangle)
cubemap_sampling_shader.set_uniform_vec3('vangle', vangle)
cubemap_sampling_shader.set_uniform_int('cubetex', depth_cube_tex)
# #output ?
zbuffer = glReadPixelsf(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT)
zbuffer = zbuffer.reshape((height, width))
np.save('Scene', np.flipud(zbuffer))
glBindRenderbuffer(GL_RENDERBUFFER, 0)
As mention all I get for Scene (a numpy array) is a blank image made out of 0s.
My shaders for the sampling are: vertex,
#version 330 core
uniform vec3 hangle; // horizontal angular range and increment
uniform vec3 vangle; // vertical angular range and increment
out vec3 dir_vector;
void main(){
for (float theta = vangle.x; theta < float(vangle.y); theta+= vangle.z){
for (float psi = hangle.x; psi < float(hangle.y); psi+= hangle.z){
float x = sin(radians(theta)) * cos(radians(psi));
float z = sin(radians(theta)) * sin(radians(psi));
float y = cos(radians(theta));
dir_vector = vec3(x,y,z);
}
}
}
and fragment,
#version 330 core
in vec3 dir_vector;
uniform samplerCube cubetex;
void main(){
gl_FragDepth = texture(cubetex, dir_vector).z;
}