OpenGL / GLSL: Kết xuất thành bản đồ khối?


13

Tôi đang cố gắng tìm ra cách hiển thị cảnh của mình thành bản đồ khối. Tôi đã bị mắc kẹt trong điều này một chút và hình dung tôi sẽ nhờ các bạn giúp đỡ. Tôi mới sử dụng OpenGL và đây là lần đầu tiên tôi sử dụng FBO.

Tôi hiện có một ví dụ hoạt động về việc sử dụng tệp bmp cubemap và loại mẫu samplerCube trong shader mảnh được đính kèm với GL_TEXTURE1. Tôi hoàn toàn không thay đổi mã shader. Tôi chỉ thay đổi thực tế là tôi sẽ không gọi hàm đang tải tệp bmp cubemap và cố gắng sử dụng mã dưới đây để kết xuất thành sơ đồ khối.

Bạn có thể thấy bên dưới tôi cũng đang đính kèm kết cấu lại vào GL_TEXTURE1. Điều này là như vậy khi tôi đặt đồng phục:

glUniform1i(getUniLoc(myProg, "Cubemap"), 1);

nó có thể truy cập nó trong shader mảnh của tôi thông qua uniform samplerCube Cubemap.

Tôi đang gọi chức năng dưới đây như vậy:

cubeMapTexture = renderToCubeMap(150, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);

Bây giờ, tôi nhận ra trong vòng vẽ bên dưới rằng tôi không thay đổi hướng xem để nhìn xuống trục + x, -x, + y, -y, + z, -z. Tôi thực sự chỉ muốn thấy một cái gì đó hoạt động trước khi thực hiện điều đó. Tôi hình dung ít nhất tôi nên nhìn thấy một cái gì đó trên đối tượng của mình theo cách mã hiện tại.

Tôi không thấy gì cả, chỉ là màu đen. Tôi đã làm cho nền của tôi màu trắng vẫn là đối tượng màu đen. Tôi đã loại bỏ ánh sáng và tô màu để chỉ lấy mẫu kết cấu hình khối và vẫn màu đen.

Tôi nghĩ vấn đề có thể là các loại định dạng khi đặt kết cấu của tôi là GL_RGB8, GL_RGBA nhưng tôi cũng đã thử:

GL_RGBA, GL_RGBA GL_RGB, GL_RGB

Tôi nghĩ rằng đây sẽ là tiêu chuẩn vì chúng tôi đang kết xuất thành một kết cấu được gắn vào bộ đệm khung, nhưng tôi đã thấy các ví dụ khác nhau sử dụng các giá trị enum khác nhau.

Tôi cũng đã thử ràng buộc kết cấu bản đồ khối trong mỗi cuộc gọi vẽ mà tôi muốn sử dụng bản đồ khối:

glBindTexture(GL_TEXTURE_CUBE_MAP, cubeMapTexture);

Ngoài ra, tôi không tạo bộ đệm độ sâu cho FBO mà tôi thấy trong hầu hết các ví dụ, vì tôi chỉ muốn bộ đệm màu cho bản đồ khối của mình. Tôi thực sự đã thêm một để xem nếu đó là vấn đề và vẫn nhận được kết quả tương tự. Tôi có thể làm mờ nó lên khi tôi cố gắng.

Bất kỳ trợ giúp có thể chỉ cho tôi đi đúng hướng sẽ được đánh giá cao.

GLuint renderToCubeMap(int size, GLenum InternalFormat, GLenum Format, GLenum Type)
    {

    // color cube map
    GLuint textureObject;
    int face;
    GLenum status;

    //glEnable(GL_TEXTURE_2D);
    glActiveTexture(GL_TEXTURE1);
    glGenTextures(1, &textureObject);
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureObject);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    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);

    for (face = 0; face < 6; face++) {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, InternalFormat, size, size, 0, Format, Type, NULL);
    }

    // framebuffer object
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, textureObject, 0);

    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    printf("%d\"\n", status);
        printf("%d\n", GL_FRAMEBUFFER_COMPLETE);

    glViewport(0,0,size, size);

    for (face = 1; face < 6; face++) {

        drawSpheres();
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, textureObject, 0);

    }

     //Bind 0, which means render to back buffer, as a result, fb is unbound
       glBindFramebuffer(GL_FRAMEBUFFER, 0);

       return textureObject;
    }

Bạn đã thử nghiệm để thấy rằng drawSphereschức năng của bạn thực sự vẽ một cái gì đó có thể nhìn thấy? Liệu các chức năng thực sự vẽ một cái gì đó? Điều gì xảy ra nếu bạn thay đổi drawSpheresđể chỉ xóa bộ đệm khung?
Nicol Bolas

Đúng. Tôi đang thực hiện hai lần. Một trong các mã trên, thực sự 6 cuộc gọi ở trên. Sau đó, tôi đang gọi drawSpheres khi kết xuất với bộ đệm khung 0 và nó hiện lên.
Joey Green

Ngoài ra, tôi đã đặt nền của mình thành màu trắng. Không phải màu trắng ít nhất sẽ xuất hiện trong kết cấu?
Joey Green

Mã của bạn có hoạt động tốt đối với một FBO bình thường không? Theo cách hiểu của tôi, một bản đồ hình khối chỉ có sáu kết cấu và bạn phải kết xuất thành từng phần riêng biệt ..
Jari Komppa

Câu trả lời:


10

Chà, tôi không thể đảm bảo rằng điều này sẽ giúp bạn biết được chuyện gì đang xảy ra. Đơn giản là bạn chưa đăng đủ thông tin về những gì bạn đang làm để theo dõi bất kỳ lỗi cụ thể nào. Mặc dù tôi có thể sửa một điều của bạn rất nhanh:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, textureObject, 0);

...

for (face = 1; face < 6; face++) {
    drawSpheres();
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, textureObject, 0);
}

Điều này sẽ chỉ gọi drawSpheres năm lần. Tôi đoán bạn muốn gọi nó 6 lần.

Nhưng tôi có thể gửi một câu trả lời làm việc.Lưu ý rằng mã này được thiết kế để chạy cùng với loạt bài hướng dẫn của tôi , vì vậy nó làm tham chiếu đến mã không có mặt. Nhưng điều này chủ yếu là những thứ như tạo lưới và vv; không có gì thực sự quan trọng

Dưới đây là những điểm nổi bật. Các shader cho đối tượng hình cầu chính.

Máy tạo bóng Vertex:

#version 330

layout(std140) uniform;

layout(location = 0) in vec4 position;
layout(location = 2) in vec3 normal;

out vec3 modelSpaceNormal;

uniform Projection
{
    mat4 cameraToClipMatrix;
};

uniform mat4 modelToCameraMatrix;

void main()
{
    gl_Position = cameraToClipMatrix * (modelToCameraMatrix * position);
    modelSpaceNormal = normal;
}

Mảnh vỡ mảnh:

#version 330

in vec3 modelSpaceNormal;

uniform samplerCube cubeTexture;

out vec4 outputColor;

void main()
{
    outputColor = texture(cubeTexture, modelSpaceNormal);
//  outputColor = vec4(normalize(modelSpaceNormal), 1.0);
}

Việc tạo kết cấu hình khối sẽ được sử dụng làm mục tiêu kết xuất:

void CreateCubeTexture()
{
    glGenTextures(1, &g_cubeTexture);
    glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    std::vector<GLubyte> testData(CUBE_TEXTURE_SIZE * CUBE_TEXTURE_SIZE * 256, 128);
    std::vector<GLubyte> xData(CUBE_TEXTURE_SIZE * CUBE_TEXTURE_SIZE * 256, 255);

    for(int loop = 0; loop < 6; ++loop)
    {
        if(loop)
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + loop, 0, GL_RGBA8,
                CUBE_TEXTURE_SIZE, CUBE_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &testData[0]);
        }
        else
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + loop, 0, GL_RGBA8,
                CUBE_TEXTURE_SIZE, CUBE_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &xData[0]);
        }
    }

    glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}

Tôi thực sự điền vào kết cấu với dữ liệu (thay vì chuyển NULL sang glTexImage2D) như một công cụ gỡ lỗi. Nó đảm bảo rằng mọi thứ đều hoạt động trước khi bắt đầu sử dụng kết cấu làm mục tiêu kết xuất.

Ngoài ra, lưu ý rằng tôi cung cấp BASE_LEVEL và MAX_LEVEL. Tôi luôn luôn làm điều đó với kết cấu của tôi ngay sau khi tạo. Đó chỉ là một thói quen tốt, vì đôi khi OpenGL có thể rất kén chọn về tính hoàn thiện của kết cấu và kim tự tháp mipmap. Thay vì ghi nhớ các quy tắc, tôi chỉ đặt chúng theo các giá trị chính xác.

Đây là chức năng vẽ chính:

void display()
{
    //Draw the cubemap.
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, g_framebuffer);
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, g_depthbuffer);

    for(int loop = 0; loop < 6; ++loop)
        DrawFace(loop);

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

    //Draw the main scene.
    //The projection matrix is in a uniform buffer.
    ProjectionBlock projData;
    projData.cameraToClipMatrix = glm::perspective(90.0f,
        (g_viewportSize.x / (float)g_viewportSize.y), g_fzNear, g_fzFar);

    glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

    glViewport(0, 0, (GLsizei)g_viewportSize.x, (GLsizei)g_viewportSize.y);

    glClearColor(0.75f, 0.75f, 1.0f, 1.0f);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glutil::MatrixStack modelMatrix;
    modelMatrix.ApplyMatrix(g_viewPole.CalcMatrix());

    if(g_pSphere)
    {
        glutil::PushStack push(modelMatrix);

        glUseProgram(g_progMain.theProgram);
        glUniformMatrix4fv(g_progMain.modelToCameraMatrixUnif, 1, GL_FALSE,
            glm::value_ptr(modelMatrix.Top()));

        glActiveTexture(GL_TEXTURE0 + g_cubeTexUnit);
        glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);

        g_pSphere->Render("lit");

        glBindTexture(GL_TEXTURE_CUBE_MAP, 0);

        glUseProgram(0);
    }

    glutPostRedisplay();
    glutSwapBuffers();
}

Điều này làm cho tham chiếu đến DrawFace, vẽ khuôn mặt đã cho của sơ đồ khối. Điều đó được thực hiện như sau:

void DrawFace(int iFace)
{
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
        GL_TEXTURE_CUBE_MAP_POSITIVE_X + iFace, g_cubeTexture, 0);

    GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
    if(status != GL_FRAMEBUFFER_COMPLETE)
        printf("Status error: %08x\n", status);

    //The projection matrix is in a uniform buffer.
    ProjectionBlock projData;
    projData.cameraToClipMatrix = glm::perspective(90.0f, 1.0f, g_fzNear, g_fzFar);

    glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

    glViewport(0, 0, (GLsizei)CUBE_TEXTURE_SIZE, (GLsizei)CUBE_TEXTURE_SIZE);

    const glm::vec4 &faceColor = g_faceColors[iFace];
    glClearColor(faceColor.x, faceColor.y, faceColor.z, faceColor.w);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    if(g_pSphere)
    {
        glutil::MatrixStack modelMatrix;
        modelMatrix.Translate(g_faceSphereLocs[iFace]);

        glUseProgram(g_progUnlit.theProgram);
        glUniformMatrix4fv(g_progUnlit.modelToCameraMatrixUnif, 1, GL_FALSE,
            glm::value_ptr(modelMatrix.Top()));

        const glm::vec4 &sphereColor = g_faceSphereColors[iFace];
        glUniform4fv(g_progUnlit.objectColorUnif, 1, glm::value_ptr(sphereColor));

        glActiveTexture(GL_TEXTURE0 + g_cubeTexUnit);
        glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);

        g_pSphere->Render("flat");

        glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
        glUseProgram(0);
    }
}

Hàm này tham chiếu đến một tập hợp các bảng toàn cầu mà tôi sử dụng để cung cấp cho mỗi mặt một màu nền riêng biệt, một màu hình cầu riêng biệt và để định vị hình cầu (trong không gian camera) đúng cho khuôn mặt đó.

Các điểm nổi bật cho DrawFace là.

Theo nguyên tắc chung, trừ khi tôi có kiến thức nhất định về trạng thái đó, tôi đặt trạng thái đó. Tôi đặt chế độ xem mỗi lần tôi gọi DrawFace. Tôi đặt ma trận chiếu mỗi lần. Đó là những thứ thừa thãi; Tôi có thể đặt chúng trở lại displaytrước vòng lặp gọiDrawFace , giống như tôi làm với FBO hiện tại và trình kết xuất độ sâu.

Nhưng tôi cũng xóa bộ đệm, khác nhau cho mỗi khuôn mặt (vì mỗi khuôn mặt có một màu khác nhau).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.