Я пытаюсь осуществить выбор полигонов, щелкнув сначала по идентификаторам треугольников в закадровом буфере кадров, а затем прочитав значения пикселей в выбранных местах с помощью 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:
Вершины верны:
Треугольник с идентификатором 0 окрашен как (0, 0, 0,0) как и ожидалось:
Площадь вне треугольника равна (255, 255, 255, 255), как и ожидалось (glClearColor - белый):
Треугольник с идентификатором 1 окрашен как (255, 0, 0, 0).Должно быть (1, 0, 0, 0):
Та же проблема возникает для идентификатора> 1. Почему это так?Как сделать так, чтобы цвет был (ID, 0, 0, 0), как показано в фрагментном шейдере?