Прямое копирование входной текстуры на выход приводит к неожиданным результатам в OpenGL - PullRequest
0 голосов
/ 15 сентября 2018

Это моя первая программа 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;
}

Ответы [ 2 ]

0 голосов
/ 15 сентября 2018

Очевидно, что что-то не так, что я не могу понять, и это приводит к тому, что вывод будет близким, но все же другим.
Изменил мои координаты на них, и он начал работать.Конечно, я не понимаю, почему

Когда вы рисуете прямоугольник, вы используете полосу треугольника примитивного типа 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
0 голосов
/ 15 сентября 2018

Изменил мои координаты на эти, и он начал работать.Конечно, я не понимаю, почему:

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
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...