После добавления кадрового буфера и последующего рисования в нем координата фрагмента кадрового буфера по умолчанию y становится -600 внизу, а вверху равна 0, а не внизу равна 0, а сверху равна 600.
Я возился с размером окна, размером буфера кадра и окном просмотра. Но ничто не изменило координату осколка с отрицательной.
В тот момент, когда я рисую в буфере кадра, координата фрагмента меняется.
Чтобы проверить координату фрагмента, я проверяю, превышает ли координата y -300, и если да, то делаю цвет ярче. Так как доходит до -600, то загорается половина экрана.
Вот код для воспроизведения ошибки, шейдеры для простоты включены на одну страницу:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
// vertex shader
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
// fragment shader
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"vec4 light = vec4(0.1f, 0.1f, 0.1f, 0.1f);\n"
"void main()\n"
"{\n"
"if (gl_FragCoord.y > -300)\n"
"{\n"
"light = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"
"}\n"
"FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f) * light;\n"
"}\n\0";
const int Width = 800;
const int Height = 600;
int main()
{
glfwInit();
GLFWwindow* window = glfwCreateWindow(Width, Height, "Test",
NULL, NULL);
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// vertex shader
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// fragment shader
unsigned int fragmentShader =
glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// link shaders
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float square[] = {
-1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, -1.0f,
1.0f, 1.0f,
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(square), square,
GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 *
sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
float vertices[] = {
// pos // tex
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
unsigned int FBO;
unsigned int quadVAO;
unsigned int texture;
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &VBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 *
sizeof(float), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// load framebuffer
glGenFramebuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Width, Height, 0,
GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture, 0);
// renderbufferobject
unsigned int RBO;
glGenRenderbuffers(1, &RBO);
glBindRenderbuffer(GL_RENDERBUFFER, RBO);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
Width, Height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) ==
GL_FRAMEBUFFER_COMPLETE)
{
std::cout << "FBO connected" << "\n";
}
else
{
std::cout << "Unable to connect to FBO" <<
glCheckFramebufferStatus(GL_FRAMEBUFFER) << "\n";
}
// render loop
while (!glfwWindowShouldClose(window))
{
// frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glClearColor(0.11f, 0.16f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
// draw square
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
// not drawing here stops the issue
glDrawArrays(GL_TRIANGLES, 0, 6);
// back to default frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
glClearColor(0.11f, 0.16f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw square
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Спасибо, что показали мне glfwGetFramebufferSize()
, к сожалению glviewport()
до или после любой привязки FBO не имеет значения.
Я обнаружил одну странную вещь: после рисования в FBO, если я привязываю другой FBO, а затем вызываю glClear(GL_COLOR_BUFFER_BIT) перед возвращением к FBO по умолчанию, координата фрагмента y возвращается в нормальное состояние.
Выяснил, что это глюк драйвера, запустил на другом компьютере, координаты фрагмента не изменились.
IIRC состояние
glViewport()
является частью FBO и влияет наgl_FragCoord
; меняет ли что-нибудь вызовglViewport()
с размером фреймбуфера после привязки FBO?