Opengl is not using the correct texture - c

I have recently started learning opengl on learnopengl.com. I am the chapter about textures. I have managed to load 2 textures however when I tell opengl to render the texture currently bound to GL_TEXTURE0 it instead draws the texture currently bound to GL_TEXTURE1.
My main.c file looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "glad/glad.h"
#include "GLFW/glfw3.h"
#include "stb/stb_image_init.h"
#define WIDTH 1080
#define HEIGHT 720
typedef unsigned int uint;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void process_input(GLFWwindow* window);
void check_shader_compilation(GLuint shader_object, GLenum shader_type);
void check_shader_linking(GLuint shader_program);
char* get_shader_code(const char* path);
int main(void) {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Triangle", NULL, NULL);
if (window == NULL) {
printf("Unable to create glfw window!\n");
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
printf("Couldn't initialize glad!\n");
return -1;
}
glViewport(0, 0, WIDTH, HEIGHT);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
char* vertex_shader_code = get_shader_code("shaders/vertex.glsl");
GLuint vertex_shader_object = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader_object, 1, &vertex_shader_code, NULL);
glCompileShader(vertex_shader_object);
check_shader_compilation(vertex_shader_object, GL_VERTEX_SHADER);
free(vertex_shader_code);
char* fragment_shader_code = get_shader_code("shaders/fragment.glsl");
GLuint fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader_object, 1, &fragment_shader_code, NULL);
glCompileShader(fragment_shader_object);
check_shader_compilation(fragment_shader_object, GL_FRAGMENT_SHADER);
free(fragment_shader_code);
uint shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader_object);
glAttachShader(shader_program, fragment_shader_object);
glLinkProgram(shader_program);
glUseProgram(shader_program);
check_shader_linking(shader_program);
float rectangle_data[] = {
// Coords Colors Texture coords
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Bottom Left
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // Top Left
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top Right
};
unsigned int indicies[] = {
0, 2, 3,
0, 1, 3,
};
uint vao, vbo, ebo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ARRAY_BUFFER, sizeof(rectangle_data), rectangle_data, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float)*8, (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float)*8, (void*)(sizeof(float)*3));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float)*8, (void*)(sizeof(float)*6));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
float border_color[] = { 1.0f, 0.0f, 0.0f, 1.0f };
uint texture_buffer, texture2_buffer;
glGenBuffers(1, &texture_buffer);
glBindTexture(GL_TEXTURE_2D, texture_buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
stbi_set_flip_vertically_on_load(true);
int width = 0, height = 0, n_channels = 0;
unsigned char* texture_image = stbi_load("assets/textures/luffy.jpg", &width, &height, &n_channels, 0);
if (texture_image) {
printf("Loaded texture0!\n");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_image);
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
printf("Couldn't find the image for the texture\n");
exit(-1);
}
stbi_image_free(texture_image);
glGenBuffers(1, &texture2_buffer);
glBindTexture(GL_TEXTURE_2D, texture2_buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
int t2_width = 0, t2_height = 0, t2_n_channels = 0;
unsigned char* texture2_image = stbi_load("assets/textures/face.png", &t2_width, &t2_height, &t2_n_channels, 0);
if (texture2_image) {
printf("Loaded texture1!\n");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, t2_width, t2_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture2_image);
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
printf("Couldn't find the image for texture2\n");
exit(-1);
}
stbi_image_free(texture2_image);
glUseProgram(shader_program);
glUniform1i(glGetUniformLocation(shader_program, "luffy"), 0);
glUniform1i(glGetUniformLocation(shader_program, "face"), 1);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
while (!glfwWindowShouldClose(window)) {
process_input(window);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_buffer);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2_buffer);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwPollEvents();
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ebo);
glDeleteShader(vertex_shader_object);
glDeleteShader(fragment_shader_object);
glDeleteProgram(shader_program);
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
void process_input(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_Q) == true) {
glfwSetWindowShouldClose(window, true);
}
}
void check_shader_compilation(GLuint shader_object, GLenum shader_type) {
char* print_shader_type;
switch (shader_type) {
case GL_VERTEX_SHADER:
print_shader_type = "vertex";
break;
case GL_FRAGMENT_SHADER:
print_shader_type = "fragment";
break;
default:
printf("Cannot check for shader compilation, the shader_type is not GL_VERTEX_SHADER or GL_FRAGMENT_SHADER!\n");
exit(-1);
}
int shader_status;
glGetShaderiv(shader_object, GL_COMPILE_STATUS, &shader_status);
if (!shader_status) {
int message_length;
GLchar error[1024];
glGetShaderInfoLog(shader_object, 1024, &message_length, error);
printf("Could not compile the %s shader: \n %s\n", print_shader_type, error);
exit(-1);
}
else {
printf("Compiled the %s shader!\n", print_shader_type);
}
}
void check_shader_linking(GLuint shader_program) {
int linking_status;
glGetProgramiv(shader_program, GL_LINK_STATUS, &linking_status);
if (!linking_status) {
int message_length;
GLchar error[1024];
glGetProgramInfoLog(shader_program, 1024, &message_length, error);
printf("Could not link the shader program:\n %s\n", error);
exit(-1);
}
else {
printf("Linked the shader program!\n");
}
}
char* get_shader_code(const char* path) {
FILE* shader_file = fopen(path, "rb");
if (!shader_file) {
printf("Incorrect file path for shader: %s\n", path);
exit(-1);
}
fseek(shader_file, 0, SEEK_END);
int file_size = ftell(shader_file);
rewind(shader_file);
char* shader_code = malloc(file_size + 1);
shader_code[file_size] = '\0';
fread(shader_code, sizeof(char), file_size, shader_file);
return shader_code;
}
My Vertex shader is:
#version 330
layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 colors;
layout (location = 2) in vec2 texCoords;
out vec3 vertex_colors;
out vec2 tex_coords;
void main() {
gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);
vertex_colors = colors;
tex_coords = texCoords;
}
And my fragment shader is:
#version 330 core
out vec4 fragColor;
in vec3 vertex_colors;
in vec2 tex_coords;
uniform sampler2D luffy;
uniform sampler2D face;
void main() {
fragColor = texture(luffy, tex_coords);
}
Whenever I run the program, it texture it uses is the image in face.png, whereas I told it to use the image in luffy.jpg.

You never create any texture objects:
glGenBuffers(1, &texture_buffer);
glBindTexture(GL_TEXTURE_2D, texture_buffer);
glGenBuffers is for buffer objects, not for texture objects. You have to use glGenTextures. (Also calling your variable texture_buffer here is very confusing. There are buffer textures in the GL, but you're not using those here).
And since you use a core profile, the glBindTexture() call will just generate a GL error and have no other effect, becuase the object name you try to bind never was generated by glGenTextures. So in effect, you are working with texture object 0 here, and load both images to that texture object, with the latter overwriting the former. In a core profiler, using texture object 0 actually shouldn't work, but many drivers still allow it (as it was allowed in legacy GL), so that you actually see any texture at all is not guaranteed either.

Related

Square not showing up in the 3D space when using cglm

I used matrices from cglm to modify the camera and what I should've seen on the screen is a small square, but nothing shows up. I have this code:
#define GLEW_STATIC
#define STB_IMAGE_IMPLEMENTATION
#include<stdio.h>
#include<stdlib.h>
#include<GL/glew.h>
#include<GLFW/glfw3.h>
#include<stdbool.h>
#include<string.h>
#include<stb/stb_image.h>
#include<cglm/cglm.h>
const unsigned int width = 1054;
const unsigned int height = 1057;
GLint uniColor;
GLint xploc;
GLint yploc;
void key_callback();
int main(){
if(!glfwInit()){
printf("Failed to initialize glfw!\n");
return 1;
}else{
printf("Successfully initialized glfw!\n");
}
//Set up GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(width, height, "Title", NULL, NULL);
glfwSetKeyCallback(window, key_callback);
if(!window){
printf("Window creation failed!\n");
return 1;
}else{
printf("Window created successfully!\n");
}
glfwMakeContextCurrent(window);
//Initialize GLEW
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK){
printf("Failed to initialize glew!\n");
return 1;
}else{
printf("Successfully initialized glew!\n");
}
//Set the swap interval to 1 millisecond
glfwSwapInterval(1);
//Set the vertices of the square
float Vertices[] = {
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f
};
//Set indices to make the square work
GLuint indices[] = {
0, 2, 1,
0, 3, 2
};
//Ignore this - it was the original square, but then I realized how I actually needed to make it work
float VerticesSquare[] = {
-0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f
};
printf("GLfloat variable called successfully\n");
//Create, compile and link the shaders to the shader program
GLuint ShaderProgram = glCreateProgram();
GLuint ShaderObjv = glCreateShader(GL_VERTEX_SHADER);
GLuint ShaderObjf = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar* pvs[1];
const GLchar* pfs[1];
//Set the shader code
const char* pVertexShaderText = "#version 330 core\n"
"layout(location = 0) in vec3 Position;\n"
"layout(location = 1) in vec3 incolor;\n"
"layout(location = 2) in vec2 Tex;\n"
"out vec3 outcolor;\n"
"out vec2 texcoords;\n"
"uniform uint xp;\n"
"uniform uint yp;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 proj;\n"
"void main(){\n"
" gl_Position = proj * view * model * vec4(Position, 1.0f);\n"
"outcolor = incolor;\n"
"texcoords = Tex;\n"
"}";
const char* pFragmentShaderText = "#version 330 core\n"
"uniform vec3 color;\n"
"uniform sampler2D tex0;\n"
"in vec3 outcolor;\n"
"in vec2 texcoords;\n"
"out vec4 FragColor;\n"
"void main(){\n"
" FragColor = vec4(outcolor, 1.0f);\n"
"}";
pvs[0] = pVertexShaderText;
pfs[0] = pFragmentShaderText;
GLint LenghtsVertex[1];
GLint LenghtsFragment[1];
LenghtsVertex[0] = strlen(pVertexShaderText);
LenghtsFragment[0] = strlen(pFragmentShaderText);
glShaderSource(ShaderObjv, 1, pvs, LenghtsVertex);
glShaderSource(ShaderObjf, 1, pfs, LenghtsFragment);
glCompileShader(ShaderObjv);
glCompileShader(ShaderObjf);
//Shader error handling
GLint successvs;
glGetShaderiv(ShaderObjv, GL_COMPILE_STATUS, &successvs);
if(!successvs){
GLchar InfoLog1[1024];
glGetShaderInfoLog(ShaderObjv, sizeof(InfoLog1), NULL, InfoLog1);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", GL_VERTEX_SHADER, InfoLog1);
return 1;
}
GLint successfs;
glGetShaderiv(ShaderObjf, GL_COMPILE_STATUS, &successfs);
if(!successfs){
GLchar InfoLog2[1024];
glGetShaderInfoLog(ShaderObjf, sizeof(InfoLog2), NULL, InfoLog2);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", GL_FRAGMENT_SHADER, InfoLog2);
return 1;
}
glAttachShader(ShaderProgram, ShaderObjv);
glAttachShader(ShaderProgram, ShaderObjf);
glLinkProgram(ShaderProgram);
GLint success;
glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &success);
if(!success){
GLchar InfoLog3[1024];
glGetProgramInfoLog(ShaderProgram, sizeof(InfoLog3), NULL, InfoLog3);
fprintf(stderr, "Error linking shader program: '%s'\n", InfoLog3);
return 1;
}
glValidateProgram(ShaderProgram);
GLint successl;
glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &successl);
if(!successl){
GLchar InfoLog4[1024];
glGetProgramInfoLog(ShaderProgram, sizeof(InfoLog4), NULL, InfoLog4);
fprintf(stderr, "Error validating shader program: '%s'\n", InfoLog4);
return 1;
}
glUseProgram(ShaderProgram);
//Set the vectors for the camera location
vec3 camerapos = {0.0f, 0.0f, -4.0f};
vec3 center = {0.0f, 0.0f, 0.0f};
vec3 yup = {0.0f, 1.0f, 0.0f};
//Create the matrices and make them be identity matrices
mat4 model;
mat4 view;
mat4 proj;
glm_mat4_identity(model);
glm_mat4_identity(view);
glm_mat4_identity(proj);
//Create the camera
glm_lookat(camerapos, center, yup, view);
glm_perspective(glm_rad(45.0f), (float)(width/height), 0.1f, 100.0f, proj);
//Set the uniform locations
GLint uniColor = glGetUniformLocation(ShaderProgram, "color");
GLint tex0uni = glGetUniformLocation(ShaderProgram, "tex0");
GLint xploc = glGetUniformLocation(ShaderProgram, "xp");
GLint yploc = glGetUniformLocation(ShaderProgram, "yp");
GLint modelloc = glGetUniformLocation(ShaderProgram, "model");
GLint viewloc = glGetUniformLocation(ShaderProgram, "view");
GLint projloc = glGetUniformLocation(ShaderProgram, "proj");
//Set the uniforms
glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);
glUniform1i(tex0uni, 0);
glUniform1ui(xploc, 1);
glUniform1ui(yploc, 1);
glUniformMatrix4fv(modelloc, 1, GL_FALSE, (float*)model);
glUniformMatrix4fv(viewloc, 1, GL_FALSE, (float*)view);
glUniformMatrix4fv(projloc, 1, GL_FALSE, (float*)proj);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//Create the buffers
GLuint VBO;
GLuint VAO = 0;
GLuint EBO;
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
printf("Buffer created successfully\n");
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
printf("Buffer data set up successfully\n");
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
printf("Enabling buffer successfull\n");
//Set the texture (I won't be using it for now)
int texwidth, texheight, texnum;
stbi_set_flip_vertically_on_load(true);
unsigned char* bytes = stbi_load("image.png", &texwidth, &texheight, &texnum, 0);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float flatcolor[] = {1.0f, 1.0f, 1.0f, 1.0f};
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, flatcolor);
printf("Set parameters successfully\n");
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texwidth, texheight, 0, GL_RGB, GL_UNSIGNED_BYTE, bytes);
glGenerateMipmap(GL_TEXTURE_2D);
printf("Texture set successfully\n");
//Set the VertexAttribPointers at locations 0, 1 and 2
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
printf("First pointer succeeded\n");
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
printf("Second pointer succeeded\n");
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
printf("Third pointer succeeded\n");
printf("Setting up VectexAttribPointer successfull\n");
while(!glfwWindowShouldClose(window)){
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//glDrawArrays(GL_TRIANGLES, 0, 3);
//Draw the elements
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
GLenum err;
if((err = glGetError()) != GL_NO_ERROR){
printf("OpenGL error: %d\n", err);
}
glfwSwapBuffers(window);
}
return 0;
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if(key == GLFW_KEY_R && action == GLFW_PRESS){
glUniform3f(uniColor, 1.0f, 0.0f, 0.0f);
}else if(key == GLFW_KEY_G && action == GLFW_PRESS){
glUniform3f(uniColor, 0.0f, 1.0f, 0.0f);
}else if(key == GLFW_KEY_B && action == GLFW_PRESS){
glUniform3f(uniColor, 0.0f, 0.0f, 1.0f);
}else if(key == GLFW_KEY_D && action == GLFW_PRESS){
glUniform1ui(xploc, 2);
}else if(key == GLFW_KEY_A && action == GLFW_PRESS){
glUniform1ui(xploc, 1);
}
}
I searched cglm's documentation, but didn't find a fix. There were some old stackoverflow questions on similar topics, but none actually solved my problem. I figured it has something to do with how I supply information to cglm's functions. I added comments, so it is easier to read.
As it turns out (float)(width/height) was supposed to be (float)width/(float)height as the first example was actually outputting 0 or 1, rather than 0.99716177861.

Why my openGL program shows a blank screen?

I created this simple hello triangle program from internet samples, but no matter how I try, I always get a blank screen. I would appreciate any help.
The development environment is Visual Studio on Windows 10 with CUDA 10.
The glGetError at the display callback return 0.
Here is the full source code:
#pragma comment(lib, "C:\\GL\\GLUT\\lib\\x64\\freeglut.lib")
#define GLEW_STATIC
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>
const char* vertexShaderSource = "#version 460 core\n"
"layout(location = 0) in vec3 aPos;\n"
"layout(location = 1) in vec3 aColor;\n"
"out vec4 vertexColor;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos, 1.0);\n"
" vertexColor = vec4(aColor, 1.0);\n"
"}\0";
unsigned int vertexShader;
const char* fragmentShaderSource = "#version 460 core\n"
"in vec4 vertexColor;\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vertexColor;\n"
"}\0";
unsigned int shaderProgram;
unsigned int VAO;
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
/* Exit on escape key press */
case '\x1B':
{
exit(EXIT_SUCCESS);
break;
}
}
}
void display()
{
glUseProgram(shaderProgram);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
printf("GL error=%d\n", glGetError()); fflush(stdout);
}
/* Main method */
int main(int argc, char** argv)
{
glutInitContextVersion(4, 6);
glutInit(&argc, argv);
glutInitWindowSize(800, 600);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Automaton");
printf("%s\n", glGetString(GL_VERSION));
glViewport(0, 0, 800, 600);
GLenum err = glewInit();
if (GLEW_OK != err)
{
printf("glew init %s\n", glewGetErrorString(err)); fflush(stdout);
return -1;
}
//
// Create shaders
//
int success;
char infoLog[512];
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
perror("Vertex shader failed.\n");
return -1;
}
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
perror("Vertex shader failed.\n");
return -1;
}
//
// Link shaders
//
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
perror("Linking error.\n");
return -1;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//
float vertices[] =
{
-1.0f, -1.0f, 0.0f, 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, 1.0f
};
GLuint attribPos = 0;
GLuint attribCol = 1;
//
unsigned int VBO;
glCreateBuffers(1, &VBO);
glCreateVertexArrays(1, &VAO);
glNamedBufferStorage(VBO, sizeof(vertices), vertices, GL_DYNAMIC_STORAGE_BIT);
GLuint vaoBindingPoint = 0;
glVertexArrayVertexBuffer(VAO, vaoBindingPoint, VBO, 0, 6 * sizeof(float));
glEnableVertexArrayAttrib(VAO, attribPos);
glEnableVertexArrayAttrib(VAO, attribCol);
glVertexArrayAttribFormat(VAO, attribPos, 3, GL_FLOAT, 0/*false*/, 0);
glVertexArrayAttribFormat(VAO, attribCol, 3, GL_FLOAT, 0/*false*/, 3 * sizeof(float));
glVertexArrayAttribBinding(VAO, attribPos, vaoBindingPoint);
glVertexArrayAttribBinding(VAO, attribCol, vaoBindingPoint);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glutKeyboardFunc(&keyboard);
glutDisplayFunc(&display);
glutMainLoop();
return EXIT_SUCCESS;
}
The program is running in a DELL PC with NVIDIA GPU 1050.
You have to call glutSwapBuffers to flush the display respectively perform a buffer swap:
void display()
{
glUseProgram(shaderProgram);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
printf("GL error=%d\n", glGetError()); fflush(stdout);
glutSwapBuffers();
}

2D OpenGL Rendering, FBO is completely black / wont render properly

I've got a problem todo with opengl rendering to framebuffer objects, everything in my render code works competely fine without the fbo being bound but as soon as I bind the fbo the result is just black. Shaders are working properly and I've gone over it multiple times so hopefully someone can help me out here. Thanks in advance! :)
SCREEN SHADER CODE:
/// Vertex
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void
main(void)
{
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
TexCoords = aTexCoords;
}
/// Fragment
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D main_texture;
void
main(void)
{
FragColor = texture(main_texture, TexCoords);
}
RENDERER RenderSprite CODE:
void
RenderSprite(Renderer *renderer,
Texture *texture,
vec2 position, f32 rotation, vec2 scale,
vec2 origin, vec4 colour)
{
UseShader(renderer->shader);
mat4 model = GLM_MAT4_IDENTITY_INIT;
vec3 rot_mult = { 0.0f, 0.0f, 1.0f };
vec3 origin_offset = { (origin[0]+1) * scale[0], (origin[1]) * scale[1], 0.0f };
vec3 inv_origin_offset = { -origin_offset[0], -origin_offset[1], 0.0f };
glm_translate(model, inv_origin_offset);
vec3 position_offset = { position[0], position[1], 0.0f };
glm_translate(model, position_offset);
glm_translate(model, origin_offset);
glm_rotate(model, rotation * DEG2RAD, rot_mult);
glm_translate(model, inv_origin_offset);
vec3 scale_vec3 = { texture->width * scale[0], texture->height * scale[1], 1.0f };
glm_scale(model, scale_vec3);
/*************************************************************************/
SetShaderMat4f(renderer->shader, "model", model);
SetShaderVec4f_arr(renderer->shader, "tint", colour);
glActiveTexture(GL_TEXTURE0);
BindTexture(texture);
glBindVertexArray(texture->vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
QUAD VAO INIT CODE:
unsigned int vbo;
float vertices[] =
{
-1.0f, -1.0f, 0.0f, 0.0f,
+1.0f, +1.0f, +1.0f, +1.0f,
-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, +1.0f, +1.0f
};
glGenVertexArrays(1, &quad_vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(quad_vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
FBO VARS (at the top of the .c file):
static Texture *test_texture; // <- temp
static unsigned int quad_vao;
static unsigned int fbo;
static unsigned int colour;
FBO INIT CODE:
glGenFramebuffers(1, &fbo);
glGenTextures(1, &colour);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glBindTexture(GL_TEXTURE_2D, colour);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WINDOW_WIDTH, WINDOW_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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colour, 0);
FBO RENDER CODE:
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// just draws a sprite (works completely fine without fbo bound)
vec2 position = { 0.0f, 0.0f };
vec2 scale = { 4.0f, 4.0f };
vec2 origin = { 0.0f, 0.0f };
vec4 tint = { 1.0f, 1.0f, 1.0f, 1.0f };
RenderSprite(game->renderer, test_texture,
position, 0, scale,
origin, tint);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
UseShader(GetShader(SHADER_screen)); // grabs a shader from the shader manager
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, colour);
glBindVertexArray(quad_vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
You have 2 vertex shader inputs:
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;
Hence you have to specify 2 arrays of generic vertex attribute data (for the attribute indices 0 and 1):
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));

OpenGL Matrix transformation not working

I am following the tutorials on learnopengl.com and I have come across an issues. I am writing my program in C rather than C++ and am using the linmath library for my matrix transformation and I have the files shader.c and texture.c. I believe that the issue is with my matrix transformation but I can't figure out where I've gone wrong. The program runs and it compiles, the window is created and the background colour is correct however the object does not show.
Here is the source:
#include <stdio.h>
#include <stdlib.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "linmath.h"
#include "shader.h"
#include "texture.h"
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
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);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL){
printf("Failed to create GLFW window");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
printf("Failed to initialize GLAD");
return -1;
}
Shader ourShader;
ourShader.ID = loadShader("3.3.shader.vs", "3.3.shader.fs");
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
Texture tex1 = loadTexture("container.jpg");
Texture tex2 = loadTexture("awesomeface.png");
// tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
// -------------------------------------------------------------------------------------------
useShader(ourShader.ID);
setIntShader("texture1", 0, ourShader.ID);
setIntShader("texture2", 1, ourShader.ID);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// bind textures on corresponding texture units
bindTexture(tex1, GL_TEXTURE0);
bindTexture(tex2, GL_TEXTURE1);
// activate shader
useShader(ourShader.ID);
// create transformations
mat4x4 model;
mat4x4 m;
mat4x4 view;
mat4x4 projection;
mat4x4_rotate(model, m, 1.0f, 0.0f, 0.0f, -0.95993f);
mat4x4_translate(view, 0.0f, 0.0f, -3.0f);
mat4x4_perspective(projection, 0.785f, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
// pass them to the shaders
setMat4Shader("model", model, ourShader.ID);
setMat4Shader("view", view, ourShader.ID);
setMat4Shader("projection", projection, ourShader.ID);
// render container
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window)
{
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
shader.c
#include "shader.h"
GLuint loadShader(const char * vertex_file_path,const char * fragment_file_path){
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
char* VertexShaderCode;
FILE * vertexFile = fopen(vertex_file_path, "r");
if( vertexFile == NULL ){
printf("Impossible to open the file !\n");
return LOAD_FAILURE;
}
long vertex_file_size;
fseek(vertexFile, 0, SEEK_END);
vertex_file_size = ftell(vertexFile);
rewind(vertexFile);
VertexShaderCode = malloc((vertex_file_size + 1) * (sizeof(char)));
fread(VertexShaderCode, sizeof(char), vertex_file_size, vertexFile);
fclose(vertexFile);
VertexShaderCode[vertex_file_size] = 0;
// Read the Fragment Shader code from the file
char* FragmentShaderCode;
FILE * fragmentFile = fopen(fragment_file_path, "r");
if( fragmentFile == NULL ){
printf("Impossible to open the file !\n");
return LOAD_FAILURE;
}
long fragment_file_size;
fseek(fragmentFile, 0, SEEK_END);
fragment_file_size = ftell(fragmentFile);
rewind(fragmentFile);
FragmentShaderCode = malloc((fragment_file_size + 1) * (sizeof(char)));
fread(FragmentShaderCode, sizeof(char), fragment_file_size, fragmentFile);
fclose(fragmentFile);
FragmentShaderCode[fragment_file_size] = 0;
const char* vsCode = VertexShaderCode;
const char* fsCode = FragmentShaderCode;
// 2. compile shaders
unsigned int vertex, fragment;
int success;
char infoLog[512];
// vertex shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vsCode, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
// fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fsCode, NULL);
glCompileShader(fragment);
checkCompileErrors(fragment, "FRAGMENT");
// shader Program
GLuint ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
checkCompileErrors(ID, "PROGRAM");
// delete the shaders as they're linked into our program now and no longer necessery
glDeleteShader(vertex);
glDeleteShader(fragment);
return ID;
}
void useShader(unsigned int ID){
glUseProgram(ID);
}
void setBoolShader(const char * name, int value, unsigned int ID)
{
glUniform1i(glGetUniformLocation(ID, name), value);
}
void setIntShader(const char * name, int value, unsigned int ID)
{
glUniform1i(glGetUniformLocation(ID, name), value);
}
void setFloatShader(const char * name, float value, unsigned int ID)
{
glUniform1f(glGetUniformLocation(ID, name), value);
}
void setMat4Shader(const char * name, mat4x4 mat, unsigned int ID)
{
glUniformMatrix4fv(glGetUniformLocation(ID, name), 1, GL_FALSE, *mat);
}
void checkCompileErrors(GLuint shader, char type[])
{
GLint success;
GLchar infoLog[1024];
if(strncmp(type, "PROGRAM", 7) != 0)
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
printf("ERROR::SHADER_COMPILATION_ERROR of type: %s \n %s \n", type, infoLog);
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if(!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
printf("ERROR::SHADER_COMPILATION_ERROR of type: %s \n %s \n", type, infoLog);
}
}
}
texture.c
#include "texture.h"
Texture loadTexture(const char* path){
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// set the texture wrapping/filtering options (on the currently bound texture object)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//load texture
int width, height, nrChannels;
unsigned char *data = SOIL_load_image(path, &width, &height, &nrChannels, SOIL_LOAD_RGB);
if(data){
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
} else{
printf("Failed to load Image");
}
SOIL_free_image_data(data);
Texture t;
t.ID = texture;
t.path = path;
return t;
}
void bindTexture(Texture texture, GLenum unit){
// bind textures on corresponding texture units
glActiveTexture(unit);
glBindTexture(GL_TEXTURE_2D, texture.ID);
}
vertex shader
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
Fragment Shader
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
// texture samplers
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
// linearly interpolate between both textures (80% container, 20% awesomeface)
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
}

Drawing triangle in OpenGL is insanely slow

I am making a simple program with GLFW3 and OpenGL. After almost 10 hours of researching, I was FINALLY able to draw a triangle (It took me so long because I did not want to use functions such as glVertex3f() and my dumb graphics card only supports OpenGL up to 2.1). So after doing a small celebration dance, I realized that not only was the triangle not taking up the whole screen when I resized, it takes more than a second to resize! Here's my code:
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
static const GLfloat vertices[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
static void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glVertexPointer(3, GL_FLOAT, 0, NULL);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
static void error_callback(int error, const char* description) {
fputs(description, stderr);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
int main(void) {
GLFWwindow* window;
glfwSetErrorCallback(error_callback);
if (!glfwInit()) {
fprintf(stderr, "Initiating GLFW failed.");
return -1;
}
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
if (!window) {
fprintf(stderr, "Creating a window failed.");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwSetKeyCallback(window, key_callback);
GLuint triangleVBO;
glGenBuffers(1, &triangleVBO);
glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);
glClearColor(0, 0, 0.2, 1);
while (!glfwWindowShouldClose(window)) {
drawScene();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
I am using a 32-bit Linux and OpenGL 2.1

Resources