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

时间:2018-09-15 01:26:44

标签: opengl

这是我的第一个OpenGL程序。我已经在WebGL中写了几乎相同的东西,它能起作用。我正在将其翻译为OpenGL。但是,我在许多地方都使用了示例代码,我不知道一切是否有意义。显然有什么错误我无法弄清楚,导致输出接近但仍然不同。

我正在创建一个2x2纹理,用数据{1.0,2.0,3.0,4.0}填充它,并使用一个简单的着色器将其复制到相同大小的输出纹理。得到的是:  结果:[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;
}

0 个答案:

没有答案