I am struggling to figure out why my GLEW/GLFW application won't render a simple square, so I have dismantled it into a single file to try to figure out what's missing.
The code below successfully opens a window, clears to the off green/blue colour I set, but does not render the square. If I add a mistake to the frag shader, it renders the pixels black where the square should be drawn (but surprisingly doesn't crash the program).
I get no errors returned from the glGetError()
calls in render_func()
.
Here is the code I am running with everything except the shader compilation code (which I lifted straight from another project that works fine) to cut down on the example code I'm sharing.
#ifndef GLEW_STATIC
#define GLEW_STATIC
#endif
#include "GL/glew.h"
#ifndef GLFW_INCLUDE_NONE
#define GLFW_INCLUDE_NONE
#endif
#include "GLFW/glfw3.h"
#ifndef GLM_FORCE_CTOR_INIT
#define GLM_FORCE_CTOR_INIT
#endif
#include "glm/glm.hpp"
#include <array>
#include <memory>
constexpr static std::array<glm::vec3, 4> vertices {{ {-0.5, -0.5, 0.0}, {-0.5, 0.5, 0.0}, {0.5, 0.5, 0.0}, {0.5, -0.5, 0.0} }};
constexpr static std::array<uint32_t , 6> indices {{ 0, 1, 2, 2, 3, 0 }};
const std::string vertex_shader_source = R"(
#version 460 core
layout (location = 0) in vec3 attrib_pos;
out vec3 frag_pos;
void main()
{
frag_pos = attrib_pos;
}
)";
const std::string fragment_shader_source = R"(
#version 460 core
in vec3 frag_pos;
out vec4 o_frag_colour;
void main()
{
o_frag_colour = vec4(1.0, 0.5, 0.0, 1.0);
}
)";
GLFWwindow* init_window()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
GLFWwindow* window = glfwCreateWindow(800, 600, "GLFW Window", nullptr, nullptr);
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height){ glViewport(0, 0, width, height); });
glfwSetErrorCallback([](int error, const char* description){
std::cout << "nodget::App::init_glfw() - ERROR - " << std::to_string(error) << ":\n" << description << std::endl;
throw;
});
glewExperimental = GL_TRUE;
glewInit();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glFrontFace(GL_CW);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
return window;
}
uint32_t init_vertex_array()
{
using VERTEX_ELEMENT_TYPE = decltype(vertices)::value_type;
using INDEX_ELEMENT_TYPE = decltype(indices)::value_type;
uint32_t VAO, VBO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
std::cout << "vertices.size() * sizeof(Vertex) " << vertices.size() * sizeof(VERTEX_ELEMENT_TYPE) << std::endl;
std::cout << "indices.size() * sizeof(uint32_t) " << indices.size() * sizeof(INDEX_ELEMENT_TYPE) << std::endl;
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(VERTEX_ELEMENT_TYPE), vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(INDEX_ELEMENT_TYPE), indices.data(), GL_STATIC_DRAW);
enum {
VERTEX_POSITION_ATTRIB_INDEX = 0
};
glEnableVertexAttribArray(VERTEX_POSITION_ATTRIB_INDEX);
glVertexAttribPointer(VERTEX_POSITION_ATTRIB_INDEX, 3, GL_FLOAT, false, sizeof(glm::vec3), (void*)0);
glBindVertexArray(0);
return VAO;
}
void render_func(GLFWwindow* window, uint32_t vao_id, uint32_t shader_id)
{
auto error = glGetError();
if (error != GL_NO_ERROR) {
std::cout << "Pre Loop Error: " << error << std::endl;
}
while(true) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_id);
glBindVertexArray(vao_id);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
error = glGetError();
if (error != GL_NO_ERROR) {
std::cout << "Mid Loop Error: " << error << std::endl;
}
}
}
int main()
{
auto window = init_window();
auto vao_id = init_vertex_array();
const std::shared_ptr<nodget::Shader> shader = std::make_shared<nodget::Shader>(std::move(vertex_shader_source), std::move(fragment_shader_source));
shader->init_func();
render_func(window, vao_id, shader->id);
}
CodePudding user response:
You must write the clip space coordinate to gl_Position
. gl_Position
is used for primitive assembly:
#version 460 core
layout (location = 0) in vec3 attrib_pos;
out vec3 frag_pos;
void main()
{
frag_pos = attrib_pos;
gl_Position = vec4(attrib_pos, 1.0);
}