Шейдер, конвертирующий ненулевую uint в 255 - PullRequest
0 голосов
/ 10 марта 2019

Я пытаюсь осуществить выбор полигонов, щелкнув сначала по идентификаторам треугольников в закадровом буфере кадров, а затем прочитав значения пикселей в выбранных местах с помощью glReadPixels.Я передаю идентификатор в виде целого числа без знака в каждую вершину (и я подтвердил, что буфер верен из apitrace) и вывожу его как uvec4 во фрагментном шейдере.Я установил кадровый буфер как текстуру RGBA8UI (также подтвердил, что юниты верны из apitrace).Нет ошибки opengl, а также проверено, что кадровый буфер завершен.

Проблема в том, что выходное изображение, где идентификаторы всегда должны быть, имеет значение 255. Область, покрытая треугольниками, модифицируется из значения glClearно они не (id, 0, 0, 0), но всегда (255, 0, 0, 0).Исключением являются идентификаторы с идентификатором 0. Кажется, что где-то в шейдере идентификатор конвертируется в 255, если идентификатор не равен 0. Это ожидаемое поведение из приведенного ниже кода?Я делаю что-то не так?

Буфер вершин:

x (float), y (float), z (float), tx (float), ty (float), id (unsigned int)

Вершинный шейдер:

#version 330 core

// Input
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in uint id;

// Output (Varying)
out vec2 v_texCoord;
flat out uint v_id;

// Uniform
uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;

void main()
{
    v_texCoord = texCoord;
    v_id = id;
    gl_Position = u_projection * u_view * u_model * vec4(position, 1.0);
}

Фрагментный шейдер:

#version 330 core

// Input (Varying)
in vec2 v_texCoord;
flat in uint v_id;

// Output
layout(location = 0) out uvec4 color;

void main()
{
    color = uvec4(v_id, 0, 0, 0);
}

GL_VERSION is3.3.0. NVIDIA 419.35 и вчера я обновили драйвер.

- Правка -

Мне отказали в предоставлении информации, поэтому я создал отдельнуюпроект, который просто показывает мою точку зрения выше с остальным кодом ниже:

#include <glad/glad.h> // Must be included before GLFW header
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>

const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 800;

int main()
{
    // glfw: initialize and configure
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // glfw window creation
    GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // glad: load all OpenGL function pointers
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    std::cout << glGetString(GL_VERSION) << std::endl;


    // Vertex and fragment shaders
    GLuint shader = glCreateProgram();
    {
        GLint isSuccess = false;
        GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
        GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

        // Vertex shader
        {
            const GLchar* vertexShaderSource =
                "#version 330 core\n"
                "layout(location = 0) in vec2 position;\n"
                "layout(location = 1) in uint id;\n"
                "flat out uint v_id;\n"
                "void main() {v_id = id; gl_Position = vec4(position.x, position.y, 0.0, 1.0);}\n";
            glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
            glCompileShader(vertexShader);
            glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isSuccess);
            std::cout << "Vertex shader compile status: " << isSuccess << std::endl;
        }

        // Fragment shader
        {
            const GLchar* fragmentShaderSource =
                "#version 330 core\n"
                "layout(location = 0) out uvec4 color;\n"
                "flat in uint v_id;\n"
                "void main() {color = uvec4(v_id, 0, 0, 0);}\n";
            glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
            glCompileShader(fragmentShader);
            glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isSuccess);
            std::cout << "Fragment shader compile status: " << isSuccess << std::endl;
        }

        glAttachShader(shader, vertexShader);
        glAttachShader(shader, fragmentShader);
        glLinkProgram(shader);
        glGetProgramiv(shader, GL_LINK_STATUS, &isSuccess);
        std::cout << "Shader link status: " << isSuccess << std::endl;

        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
    }

    // Vertex Buffer
    GLuint vertexBuffer;
    {
        glGenBuffers(1, &vertexBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        GLfloat data[] = {
            //  x      y     id
            -1.0f,  0.0f,  0.0f,
            -1.0f, -1.0f,  0.0f,
             0.0f, -1.0f,  0.0f,
             0.0f,  1.0f,  0.0f,
             0.0f,  0.0f,  0.0f,
             1.0f,  0.0f,  0.0f
        };
        GLuint* data2 = ((GLuint *)data);
        data2[2] = 0;
        data2[5] = 0;
        data2[8] = 0;
        data2[11] = 1;
        data2[14] = 1;
        data2[17] = 1;
        std::cout << "Size of GLuint: " << sizeof(GLuint) << std::endl;
        std::cout << "Size of GLfloat: " << sizeof(GLfloat) << std::endl;
        std::cout << "Size of vertex buffer: " << sizeof(data) << std::endl;
        glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

    // Vertex Array
    GLuint vertexArray;
    {
        glGenVertexArrays(1, &vertexArray);
        glBindVertexArray(vertexArray);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 1, GL_UNSIGNED_INT, GL_FALSE, 3 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
    }

    // Texture for framebuffer
    GLuint texture;
    glGenTextures(1, &texture);
    {
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, WINDOW_WIDTH, WINDOW_HEIGHT, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, nullptr);

        glBindTexture(GL_TEXTURE_2D, 0);
    }

    // Framebuffer
    GLuint framebuffer;
    {
        GLenum completenessStatus;
        glGenFramebuffers(1, &framebuffer);
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
        std::cout << "Framebuffer status: " << (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) << std::endl;
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

    // Clear
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    GLenum error = glGetError();
    std::cout << "No error: " << (error == GL_NO_ERROR) << std::endl;

    // Draw
    while (!glfwWindowShouldClose(window))
    {
        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
            glfwSetWindowShouldClose(window, true);

        glClear(GL_COLOR_BUFFER_BIT);

        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
        {
            glDisable(GL_DITHER);
            glClear(GL_COLOR_BUFFER_BIT);

            glUseProgram(shader);
            glBindVertexArray(vertexArray);
            glActiveTexture(GL_TEXTURE0);

            glDrawArrays(GL_TRIANGLES, 0, 6);
            glEnable(GL_DITHER);
        }
        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteProgram(shader);
    glDeleteBuffers(1, &vertexBuffer);
    glDeleteVertexArrays(1, &vertexArray);
    glDeleteFramebuffers(1, &framebuffer);
    glDeleteTextures(1, &texture);

    return 0;
}

Вывод:

3.3.0 NVIDIA 419.35
Vertex shader compile status: 1
Fragment shader compile status: 1
Shader link status: 1
Size of GLuint: 4
Size of GLfloat: 4
Size of vertex buffer: 72
Framebuffer status: 1
No error: 1

Framebuffer - RGBA8UI:

Framebuffer is RGBA8UI

Вершины верны:

Vertices are correct

Треугольник с идентификатором 0 окрашен как (0, 0, 0,0) как и ожидалось:

Triangle ID 0

Площадь вне треугольника равна (255, 255, 255, 255), как и ожидалось (glClearColor - белый):

Outside triangle

Треугольник с идентификатором 1 окрашен как (255, 0, 0, 0).Должно быть (1, 0, 0, 0):

Triangle ID 1

Та же проблема возникает для идентификатора> 1. Почему это так?Как сделать так, чтобы цвет был (ID, 0, 0, 0), как показано в фрагментном шейдере?

1 Ответ

1 голос
/ 11 марта 2019

Вы должны использовать glVertexAttribIPointer (фокус на I) при определении массива общих данных атрибута вершины для атрибута вершины in uint id;.
Если данные атрибута вершины определены как glVertexAttribPointer, они будут преобразованы в значения с плавающей запятой.

См. Спецификация профиля ядра API OpenGL 4.6;10,2.ТЕКУЩИЕ ЗНАЧЕНИЯ VERTEX ATTRIBUTE;стр. 344

Команды VertexAttribI* указывают значения со знаком или без знака с фиксированной точкой , которые хранятся как целые числа со знаком или без знака соответственно.Такие значения называются чистыми целыми числами.

...

Все остальные команды VertexAttrib* указывают значения, которые преобразуются непосредственно во внутреннее плавающеепредставление точки .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...