opengl 黑色正方形渲染,而不是OpenCV图像

ocebsuys  于 2023-01-13  发布在  其他
关注(0)|答案(1)|浏览(145)

我正在尝试用ushort数据类型渲染两张大小为256x256的图片。一张必须是灰度的,另一张必须是RGB的。但是,两张图片都渲染为黑色方块。我相信错误出在我的openGL纹理定义中,但我不确定。
下面是我的代码的最小版本。

#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <glad/glad.h>    
#include <GLFW/glfw3.h>
#include <opencv2/opencv.hpp>

using namespace cv;

int main()
{
    //init glfw, window, glad, imgui
    glfwInit();
    const char* glsl_version = "#version 330 core";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    GLFWwindow* window = glfwCreateWindow(600, 400, "test", NULL, NULL);
    glfwMakeContextCurrent(window);
    gladLoadGL();
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    ImGui::CreateContext();
    ImGui::StyleColorsDark();
    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init(glsl_version);

    //define image data
    ushort value;
    Mat_<ushort> grey = Mat_<ushort>(256, 256);
    Mat_<Vec3w> rgb = Mat_<Vec3w>(256, 256);

    for (int i = 0; i < grey.rows; i++)
        for (int j = 0; j < grey.cols; j++)
        {
            value = (i + j) / 256.0 * USHRT_MAX;
            grey.at<ushort>(i, j) = value;
            rgb.at<Vec3w>(i, j) = Vec3w(value, value, value);
        }

    
    //create textures
    GLuint greyID;
    GLuint rgbID;

    glGenTextures(1, &greyID);
    glBindTexture(GL_TEXTURE_2D, greyID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, 256, 256, 0, GL_RED, GL_UNSIGNED_SHORT, grey.data);

    glGenTextures(1, &rgbID);
    glBindTexture(GL_TEXTURE_2D, rgbID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16UI, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT, rgb.data);

    while (!(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS))
    {
        glfwPollEvents();

        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        ImGui::Begin("Images");
        ImGui::Image((void*)(intptr_t)greyID, ImVec2(256, 256));
        ImGui::SameLine();
        ImGui::Image((void*)(intptr_t)rgbID, ImVec2(256, 256));
        ImGui::End();

        ImGui::Render();

        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        glfwSwapBuffers(window);
    }

    ImGui::DestroyContext();
    glfwDestroyWindow(window);
    glfwTerminate();
    return 1;
}

结果如下:

vyu0f0g1

vyu0f0g11#

您的代码有两个问题。
首先,正如评论中所讨论的,在您的情况下,您可能希望使用GL_RGB16而不是GL_RGB16UI,这样可以解决纹理错误。
第二个问题是,您需要添加

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glBindTexture之后。
原因是默认的缩小过滤器是GL_NEAREST_MIPMAP_LINEAR,但是你只提供了第一个mip贴图级别(所以纹理是不完整的)。或者,你也可以降低最大级别。查看wiki了解更多信息。
修复这两个问题后,您的程序可以正常工作:

您可能还需要计算颜色为

value = min((i + j) / 256.0), 1.0) * USHRT_MAX;

相关问题