一次即可完成分层渲染立方体贴图

时间:2018-12-16 15:50:23

标签: opengl glsl opengl-3 geometry-shader

我正在尝试使用几何着色器和gl_Layer制作一个动态立方体贴图,其中每个面都有自己的纹理,但无法正常工作。或者我有一个黑色的立方体贴图,什么也没有,或者什么都没有...

这是我初始化纹理和fbo的地方:

void init(void) {
    //Triangle test
    GLfloat data[] = {
            0, 0, 0,
            1, 0, 0,
            0, 1, 0
    };

    glGenVertexArrays(1, &_vaoTriangles);
    glBindVertexArray(_vaoTriangles);
    glEnableVertexAttribArray(0);
    glGenBuffers(1, &_vboPoints);
    glBindBuffer(GL_ARRAY_BUFFER, _vboTriangles);
    glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0);
    glBindBuffer(GL_ARRAY_BUFFER ,0);
    glBindVertexArray(0);

    const GLfloat skybox[] = {
            // positions
            -1.0f,  1.0f, -1.0f,
            -1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            1.0f,  1.0f, -1.0f,
            -1.0f,  1.0f, -1.0f,

            -1.0f, -1.0f,  1.0f,
            -1.0f, -1.0f, -1.0f,
            -1.0f,  1.0f, -1.0f,
            -1.0f,  1.0f, -1.0f,
            -1.0f,  1.0f,  1.0f,
            -1.0f, -1.0f,  1.0f,

            1.0f, -1.0f, -1.0f,
            1.0f, -1.0f,  1.0f,
            1.0f,  1.0f,  1.0f,
            1.0f,  1.0f,  1.0f,
            1.0f,  1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,

            -1.0f, -1.0f,  1.0f,
            -1.0f,  1.0f,  1.0f,
            1.0f,  1.0f,  1.0f,
            1.0f,  1.0f,  1.0f,
            1.0f, -1.0f,  1.0f,
            -1.0f, -1.0f,  1.0f,

            -1.0f,  1.0f, -1.0f,
            1.0f,  1.0f, -1.0f,
            1.0f,  1.0f,  1.0f,
            1.0f,  1.0f,  1.0f,
            -1.0f,  1.0f,  1.0f,
            -1.0f,  1.0f, -1.0f,

            -1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f,  1.0f,
            1.0f, -1.0f, -1.0f,
            1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f,  1.0f,
            1.0f, -1.0f,  1.0f
    };

    glGenVertexArrays(1, &_vao);
    glBindVertexArray(_vao);
    glEnableVertexAttribArray(0);
    glGenBuffers(1, &_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(skybox), skybox, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const void *)0);
    glBindBuffer(GL_ARRAY_BUFFER ,0);
    glBindVertexArray(0);

    glGenTextures(1, &texture_cubemap);
    glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cubemap);
    int face;
    for(face = 0; face < 6; face++)
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+face, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

    glGenFramebuffers(1, &_fbo);
    glBindFramebuffer(1, _fbo);
    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_cubemap, 0);

//    glGenRenderbuffers(1, &_depthFbo);
//    glBindRenderbuffer(GL_RENDERBUFFER, _depthFbo);
//    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 256, 256);
//    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthFbo);

//    GLenum drawBuffers[1] = {GL_COLOR_ATTACHMENT0};
//    glDrawBuffers(1, drawBuffers);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

此处渲染:

void render(void) {
    glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
    glViewport(0, 0, 256, 256);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.2, 0.2, 0.2, 0);
    glUseProgram(pIdTriangles);
    glBindVertexArray(_vaoTriangles);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glBindVertexArray(0);
    glUseProgram(0);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0, width, height);
    glClearColor(0, 0, 0, 1.0);
    glUseProgram(pId);
//...Matrices stuff
    glBindVertexArray(_vao);
    gl4duSendMatrices();
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_CUBE_MAP, texture_cubemap);
    glUniform1i(glGetUniformLocation(pId, "skybox"), 0);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertexArray(0);
    glUseProgram(0);

我的天空盒着色器:

//Vertex shader
#version 330


layout(location=0) in vec3 positionSkybox;

uniform mat4 projectionMatrix;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
out vec3 UV;

void main() {
    vec4 pos = projectionMatrix * viewMatrix /* modelMatrix */* vec4(positionSkybox, 1);
    gl_Position = pos.xyww;
    UV = positionSkybox;
}

//Fragment shader
#version 330

//layout(location=0) in vec4 outColor;

out vec4 fragColor;
uniform samplerCube skybox;
in vec3 UV;

void main() {
    fragColor = texture(skybox, UV);
}

模型的着色器:

//Vertex shader
#version 330

layout(location=0) in vec3 positionTriangles;

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

void main() {
    gl_Position = /*projectionMatrix */ /*viewMatrix */ modelMatrix * vec4(positionTriangles, 1);
}

//Geometry shader
#version 330

layout(triangles) in;
layout(triangle_strip, max_vertices=18) out;

uniform mat4 projectionMatrix;

out vec4 colors;
void main() {
    int i, layer;
    for(layer = 0; layer < 6; ++layer){
        gl_Layer = layer;
        for(i = 0; i < gl_in.length(); i++){
            gl_Position = /*projectionMatrix */ gl_in[0].gl_Position;
            colors = vec4(0, 1, 0, 1);
            EmitVertex();
        }
    }
    EndPrimitive();
}

//Fragment shader 
#version 330

out vec4 fragColor;

in vec4 colors;
void main() {
    fragColor = colors;//vec4(1, 0, 0, 1);
}

感谢您的帮助...

编辑: 我的Skybox仅在以下情况下可用:

    glBindFramebuffer(GL_FRAMEBUFFER, **0**);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0, 256, 256);
    glClearColor(0.2, 0.2, 0.2, 0);
    glUseProgram(pIdTriangles);
    glBindVertexArray(_vaoTriangles);
//Draw the triangles

    glBindFramebuffer(GL_FRAMEBUFFER, **_fbo**);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0, width, height);
    glClearColor(0, 1, 0, 1);
    glUseProgram(pId);
//Draw the skybox

但是必须在默认帧缓冲区上渲染的是天弓,对吗?

1 个答案:

答案 0 :(得分:1)

您必须完成每个图层的基本图元,在迭代图层的循环中移动EndPrimitive()

此外,在您的代码中,三角形的第一个顶点被使用了3次,但是第2个和第3个坐标被遗漏了。 将gl_in[0].gl_Position更改为gl_in[i].gl_Position

要渲染立方体贴图的不同面,您需要为立方体贴图的每一面使用不同的视图矩阵。您必须在各个方向(右,左,前,后,上,下)“看”。
投影矩阵必须是透视投影,视野角为90度,纵横比为1.0: 另请参阅教程"OpenGL: One-pass rendering to a cube map",以获取更多详细信息。

例如由usnig glm::lookAtglm::perspective

glm::mat4 cubeView[6] =
{ 
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 1.0f, 0.0f, 0.0f), glm::vec3(0.0f,-1.0f, 0.0f)), // +X
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f,-1.0f, 0.0f)), // -X
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)), // +Y
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f,-1.0f, 0.0f), glm::vec3(0.0f, 0.0f,-1.0f)), // -Y
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 0.0f, 1.0f), glm::vec3(0.0f,-1.0f, 0.0f)), // +Z
    glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 0.0f,-1.0f), glm::vec3(0.0f,-1.0f, 0.0f)), // -Z
};

glm::mat4 cubeProj = glm::perspective(glm::radians(90.0f), 1.0f, near_plane, far_plane);
uniform mat4 cubeProjMatrix;
uniform mat4 cubeViewMatrix[6];

void main() {
    int i, layer;
    for(layer = 0; layer < 6; ++layer){
        gl_Layer = layer;
        for(i = 0; i < gl_in.length(); i++)
        {
            gl_Position = cubeProjMatrix * cubeViewMatrix[layer] * gl_in[i].gl_Position;
            colors = vec4(0, 1, 0, 1);
            EmitVertex();
        }
        EndPrimitive(); // <---- insert 
    }
    //EndPrimitive();   // <---- delete
}