代码之家  ›  专栏  ›  技术社区  ›  Jeff Saremi

直接将输入纹理复制到输出会在OpenGL中产生意外的结果

  •  1
  • Jeff Saremi  · 技术社区  · 6 年前

    这是我的第一个OpenGL程序。我在WebGL中写了几乎相同的东西。我正在把它翻译成OpenGL。然而,我使用的样本代码从许多地方,我不知道如果一切都有意义。很明显,有一些错误,我不能弄清楚,导致输出接近,但仍然不同。

    结果:[1,2,0,4,]

    下面我将粘贴我的代码和着色器脚本。感谢您审阅。

    顶点着色器:

    #version 330 core
    layout (location = 0) in vec3 position;
    layout (location = 1) in vec2 texCoord;
    out vec2 TexCoord;
    
    void main()
    {
     gl_Position = vec4(position, 1.0f);
     TexCoord = texCoord;
    }
    

    碎片着色器:

    #version 330 core
    precision highp float;
    in vec2 TexCoord;
    out vec4 TexelValue;
    // Texture samplers
    uniform sampler2D A;
    
    void main()
    {
        TexelValue = vec4(texture(A, TexCoord).r);
    }
    

    删除错误检查的代码:

    // Window dimensions
    const GLuint WIDTH = 800, HEIGHT = 600;
    
    void createTexture(GLuint texture, int width, int height, GLint internalFormat, GLenum format, GLenum type, const void *data)
    {
        glBindTexture(GL_TEXTURE_2D, texture);
        // Set our texture parameters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        // set texenv to replace instead of the default modulate
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, data);
    }
    
    void uploadAndBindGeometry(const void* vertices, int verticesByteLength)
    {
        GLuint VBO, VAO;
        glGenVertexArrays(1, &VAO);
        glGenBuffers(1, &VBO);
        glBindVertexArray(VAO);
    
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, verticesByteLength, vertices, GL_STATIC_DRAW);
    
        // Position attribute
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid *)0);
        glEnableVertexAttribArray(0);
        // Texture Coordinate attribute
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid *)(3 * sizeof(GLfloat)));
        glEnableVertexAttribArray(1);
    }
    
    void bindInputTexture(int index, GLuint texture, GLint location)
    {
        glActiveTexture(GL_TEXTURE0 + index);
        glBindTexture(GL_TEXTURE_2D, texture);
        glUniform1i(location, index);
    }
    
    void initFBO(GLuint *fb, int width, int height) {
        glGenFramebuffersEXT(1, fb);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, *fb);
        glViewport(0, 0, width, height);
    }
    // The MAIN function, from here we start the application and run the game loop
    int main()
    {
        glfwInit();
        GLuint fb;
    
        // Set all the required options for GLFW
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
        glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    
        // Create a GLFWwindow object that we can use for GLFW's functions
        GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
    
        int screenWidth, screenHeight;
        glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
        glfwMakeContextCurrent(window);
    
        // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
        glewExperimental = GL_TRUE;
        glewGetExtension("GL_ARB_texture_float");
        glewGetExtension("GL_EXT_framebuffer_object");
        glewGetExtension("GL_ARB_color_buffer_float");
    
        glDisable(GL_BLEND);
        glDisable(GL_ALPHA);
        glDisable(GL_DEPTH);
        glDisable(GL_STENCIL);
    
        // Build and compile our shader program
        Shader ourShader("core.vs", "core.frag");
    
        // Set up vertex data (and buffer(s)) and attribute pointers
        GLfloat vertices[] =
        {
            // Positions          // Texture Coords
            1.0f,  1.0f, 0.0f,   1.0f, 1.0f, // Top Right
            1.0f, -1.0f, 0.0f,   1.0f, 0.0f, // Bottom Right
            -1.0f, -1.0f, 0.0f,  0.0f, 0.0f, // Bottom Left
            -1.0f,  1.0f, 0.0f,  0.0f, 1.0f  // Top Left
        };
        uploadAndBindGeometry(vertices, sizeof(vertices));
    
        // Load and create textures
        float adata[] = { 1.0,2.0,3.0,4.0 };
        int adims[] = { 2, 2 };
        int cdims[] = { 2, 2 };
        float cdata[2 * 2] = { 0 };
    
        // ===================
        // Texture
        // ===================
        GLuint texture[2];
        glGenTextures(2, &texture[0]);
        createTexture(texture[0], adims[1], adims[0], GL_R32F, GL_RED, GL_FLOAT, (void*)adata);
        createTexture(texture[1], cdims[1], cdims[0], GL_R32F, GL_RED, GL_FLOAT, (void*)NULL);
    
        // Draw the triangle
        ourShader.Use();
        initFBO(&fb, cdims[1], cdims[0]);
        glBindTexture(GL_TEXTURE_2D, texture[1]);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
    
        int locationA = glGetUniformLocation(ourShader.Program, "A");
        bindInputTexture(0, texture[0], locationA);
    
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        glFlush();
        // read output
        glReadBuffer(GL_COLOR_ATTACHMENT0);
        glReadPixels(0, 0, cdims[1], cdims[0], GL_RED, GL_FLOAT, cdata);
        std::cout << "Result: [";
        for (int i = 0; i < 2 * 2; ++i)
        {
            std::cout << cdata[i] << ",";
        }
        std::cout << "]" << std::endl;
    
        // Terminate GLFW, clearing any resources allocated by GLFW.
        glfwTerminate();
    
        return EXIT_SUCCESS;
    }
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Rabbid76    6 年前

    很明显,有一些错误,我不能弄清楚,导致输出接近,但仍然不同。
    把我的坐标改成这些,它就开始工作了。我当然不明白为什么

    绘制矩形时,使用基本体类型“三角形条纹” GL_TRIANGLE_STRIP

    三角形条带中顶点坐标的顺序如下所示:

    0     2     4
     x     x     x
     |   / |   / |
     | /   | /   |
     x     x     x
      1     3     5
    

    你问题的顶点

    GLfloat vertices[] =
    {
        // Positions          // Texture Coords
         1.0f,  1.0f, 0.0f,   1.0f, 1.0f, // Top Right
         1.0f, -1.0f, 0.0f,   1.0f, 0.0f, // Bottom Right
        -1.0f, -1.0f, 0.0f,   0.0f, 0.0f, // Bottom Left
        -1.0f,  1.0f, 0.0f,   0.0f, 1.0f  // Top Left
    };
    

    顺序如下:

    3       0
     x     x
     |     |
     |     |
     x-----x
    2       1
    

    GL_TRIANGLE_FAN


    新的和更改的顶点

    GLfloat vertices[] =
    {
        -1.0,  1.0,  0.0, 0.0, 1.0,  // upper left
        -1.0, -1.0,  0.0, 0.0, 0.0,  // lower left
         1.0,  1.0,  0.0, 1.0, 1.0,  // upper right
         1.0, -1.0,  0.0, 1.0, 0.0   // lower right
    };
    

    0     2
     x     x
     |   / |
     | /   |
     x     x
      1     3
    
        2
  •  1
  •   Jeff Saremi    6 年前

    把我的坐标改成这些,它就开始工作了。当然我不明白为什么:

    GLfloat vertices[] =
    {
        -1.0, 1.0,  0.0, 0.0, 1.0,  // upper left
        -1.0, -1.0, 0.0, 0.0, 0.0,  // lower left
        1.0,  1.0,  0.0, 1.0, 1.0,  // upper right
        1.0,  -1.0, 0.0, 1.0, 0.0   // lower right
    };