opengl 在对立方体贴图进行采样后创建2D图像[重复]

xyhw6mcr  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(124)

此问题在此处已有答案

How to correctly make a depth cubemap for shadow mapping?(1个答案)
Omnidirectional shadow mapping with depth cubemap(2个答案)
3小时前关闭

最新更新

目标:通过以给定的Angular 步长采样,使用球面坐标生成深度立方体贴图,生成场景的360度视图。其中x和y分别表示水平角或方位角和仰角,并且每个像素处的实际值是深度。
输出:到目前为止,我没有得到任何错误,只是一个空白的2D图像。我不知道为什么我没有得到任何输出
这是另一个尝试在这个…FYI,depth_cube_tex是先前利用深度信息生成的深度立方体图。
我的取样程序如下,

# SAMPLING CUBEMAP
##################
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS)

# angular ranges and step
angle_step = 0.025
hangle = np.array([0, 360, angle_step], dtype=np.float32)
vangle = np.array([-90, 90, angle_step], dtype=np.float32)

width = int( (hangle[1]-hangle[0]) / hangle[2])
height = int( (vangle[1]-vangle[0]) / hangle[2])

# create scene fbo
scene_buffer = glGenFramebuffers(1)
glBindFramebuffer(GL_FRAMEBUFFER, scene_buffer)

# generate color depth buffer and attache it to scene fbo
color_depth = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, color_depth)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, None)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_depth, 0) 

# send information to sampling shader
cubemap_sampling_shader.use()
cubemap_sampling_shader.set_uniform_int('depth_cube', depth_cube_tex)
cubemap_sampling_shader.set_uniform_vec3('display_size', glm.vec2(width,height))
cubemap_sampling_shader.set_uniform_float('angle_step', angle_step)

#draw onto my scene buffer
glBindVertexArray(quad_vao)
glBindTexture(GL_TEXTURE_2D, color_depth)
glDrawArrays(GL_TRIANGLES, 0, 6)
glBindVertexArray(0)

# save output ?
zbuffer = glReadPixelsf(0, 0, width, height, GL_RED, GL_FLOAT)
zbuffer = zbuffer.reshape((height, width))
np.save('Scene', np.flipud(zbuffer))

glBindFramebuffer(GL_FRAMEBUFFER, 0) #scene_buffer

字符串
cubemap_sampling着色器程序具有以下顶点着色器:

#version 330 core
layout (location = 0) in vec2 aPos;

void main()
{ 
    gl_Position = vec4(aPos.x, aPos.y, 0.0f, 1.0f);
}


和片段着色器

#version 330 core

uniform samplerCube depth_cube; 
uniform float angle_step;
uniform vec2 display_size; // width, height of display

out float depth;

void main()
{
    // psi is the horizontal deviation angle
    float psi = (gl_FragCoord.x - display_size.x / 2 ) * radians(angle_step);
    
    // theta is the vertical deviation angle
    float theta = (gl_FragCoord.y - display_size.y / 2 ) * radians(angle_step);
    
    // create sampling direction vector
    float x = sin(theta) * sin(psi);
    float z = cos(theta) * sin(psi);
    float y = cos(theta);
    depth = texture(depth_cube,vec3(x,y,z)).s;
}


我的quad_vao只是两个三角形,在Normalize Device Coords中横跨整个屏幕。

bfhwhh0e

bfhwhh0e1#

好吧...这就是我想要的。我决定读入一个立方体贴图(从LearnOpenGL借用,参见link),而不是使用我最初生成的深度立方体贴图,以简化我的思维。在这样做的过程中,我意识到有几件事我真的没有一个好的答案(我会指出这些)。
下面是代码,

def loadCubemap(faces : list[str]) -> int:

    textureID = glGenTextures(1)
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureID)

    for i in range(len(faces)):
        try:
            img = Image.open(faces[i])

            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, img.width, img.height, 0, GL_RGB, GL_UNSIGNED_BYTE, img.tobytes())

            img.close()
            
        except:
            print("Cubemap texture failed to load at path: " + faces[i])

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    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)
    glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS)

    return textureID

# initialize camera
camera = Camera(position=(0,0,0))
camera.width = 720
camera.height = 360

# initialize opengl
glfw.init()
glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
glfw.window_hint(glfw.DEPTH_BITS, 32) # not here before

# create glfw window
window = glfw.create_window(camera.width, camera.height, 'LearnOpengl', None, None)
if window is None:
    print("Failed to create GLFW window")
    glfw.terminate()           
glfw.make_context_current(window)

# load textures
# -------------
faces = [
    pth / "textures/skybox/right.jpg",
    pth / "textures/skybox/left.jpg",
    pth / "textures/skybox/top.jpg",
    pth / "textures/skybox/bottom.jpg",
    pth / "textures/skybox/front.jpg",
    pth / "textures/skybox/back.jpg",
]

cubemapTexture = loadCubemap(faces)

# Create VAO and VBO of quad for rendering

# vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
#    positions /  texture   
quad_vertices = np.array( 
    [-1.0,  1.0,  0.0, 1.0,
    -1.0, -1.0,  0.0, 0.0,
    1.0, -1.0,  1.0, 0.0,

    -1.0,  1.0,  0.0, 1.0,
    1.0, -1.0,  1.0, 0.0,
    1.0,  1.0,  1.0, 1.0],
    dtype= np.float32)

# create quad vao and vbo
quad_vao = glGenVertexArrays(1)
glBindVertexArray(quad_vao)

quad_vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, quad_vbo)
glBufferData(GL_ARRAY_BUFFER, quad_vertices.nbytes, quad_vertices, GL_STATIC_DRAW)

# position attribute
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * 4, ctypes.c_void_p(0)) 
glEnableVertexAttribArray(0) # position

# texture attribute
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * 4, ctypes.c_void_p(2 * 4))

# compile shader
shader = Shader(pth / 'depthcube/shader/equirectangular.vs', pth / 'depthcube/shader/equirectangular.fs')

# SAMPLING PARAMETERS
hangle = np.array([0, 360, 0.025])
vangle = np.array([-90, 90, 0.025])
width = int((hangle[1]-hangle[0]) / hangle[2])
height = int((vangle[1]-vangle[0]) / vangle[2])

字符串
一个指针在这里。宽度和高度的尺寸可以具有GL_MAX_VIEWPORT_DIMS的最大值。因此,采样的精细程度是有限的。我想知道是否可以以某种方式增加。

# CREATE FRAMEBUFFER

fbo = glGenFramebuffers(1)
glBindFramebuffer(GL_FRAMEBUFFER, fbo)

texcolor = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texcolor)
#glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, None)
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, None)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texcolor, 0)
glBindFramebuffer(GL_FRAMEBUFFER, 0)

# RENDER
glViewport(0,0,width,height)

# use shader
shader.use()

shader.set_uniform_float('hrange', hangle[1]-hangle[0])
shader.set_uniform_float('vrange', vangle[1]-vangle[0])
shader.set_uniform_vec2('size_display', glm.vec2(width,height))
shader.set_uniform_vec2('offset', glm.vec2(-90.0, -45.0))
shader.set_uniform_int('depthcube', 0) #cubemapTexture WHY 0???


这是一个有趣的观点,我被困了最长的时间。我想,为了将立方体贴图引入到我的着色器中,我需要传递立方体贴图的纹理ID,即。上面的loadCubemap()函数返回的值。我错了,相反,为了让进程工作,我只是传递了0的值。我没有一个很好的解释为什么会这样,所以也许有人可以解释这一点。

# render to fbo
glBindFramebuffer(GL_FRAMEBUFFER, fbo)

glClearColor(0.0, 0.0, 0.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT)

shader.use()
glBindVertexArray(quad_vao)
glDrawArrays(GL_TRIANGLES, 0, 6)
#glBindVertexArray(0)

glfw.swap_buffers(window)

# save #output ?
zbuffer = glReadPixelsf(0, 0, width, height, GL_RED, GL_FLOAT)
zbuffer = zbuffer.reshape((height, width))
np.save('Scene', np.flipud(zbuffer))

# unbind
glBindFramebuffer(GL_FRAMEBUFFER, 0)


shader程序具有以下顶点着色器:

#version 330 core

layout (location = 0) in vec2 position; 

void main(){
    gl_Position = vec4(position.x, position.y, 0.0f, 1.0f);
}


和片段着色器,

#version 330 core

uniform vec2 size_display;
uniform vec2 offset;
uniform float hrange;
uniform float vrange;
uniform samplerCube depthcube;

//out vec4 color;
out float color;

void main()
{
    // scale coordinates (0,1)
    vec2 scaleCoord = gl_FragCoord.xy / size_display;

    // convert offset to radians
    vec2 off = vec2(radians(offset.x), radians(offset.y));

    // center the view
    vec2 angles = ((scaleCoord * 2.0) - vec2(1.0)) * vec2(radians(hrange/2), radians(vrange/2)) + off;

    // sampling vector
    vec3 samplingVec = vec3(-cos(angles.y) * cos(angles.x), sin(angles.y), cos(angles.y) * sin(angles.x));

    // output
    color = texture(depthcube, samplingVec).r;


使用上面的代码,我能够使用球面坐标(适用于OpenGl规范)对立方体贴图进行采样。

相关问题