Why am I getting a black screen with this opengl application? - c

I must be missing something really simple here, I've been staring at my code for the last hour and just can't see it. The code should just create a texture with random pure color or pure black pixels, then draw it to the screen. Right now though it's just producing a black screen...
My guess is it has something to with my vertex or uv positions.
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
const char TITLE[] = "GL TEST";
const int WIDTH = 800;
const int HEIGHT = 600;
const char BASIC_VERT_SHADER[] =
"#version 330\n"
"in vec2 vs_position;"
"in vec2 vs_uvCoord;"
"out vec2 fs_uvCoord;"
"void main()"
"{"
"fs_uvCoord = vs_uvCoord;"
"gl_Position = vec4(vs_position, 1.f, 1.f);"
"}";
const char BASIC_FRAG_SHADER[] =
"#version 330\n"
"uniform sampler2D texture;"
"in vec2 fs_uvCoord;"
"out vec4 frag_color;"
"void main()"
"{"
"frag_color = texture2D(texture, fs_uvCoord);"
"}";
const float TEXTURE_UV[] =
{
0.f, 0.f,
1.f, 0.f,
1.f, 1.f,
0.f, 1.f
};
const float VERT_POS[] =
{
-1.f, -1.f,
1.f, -1.f,
1.f, 1.f,
-1.f, 1.f
};
GLFWwindow* setupGraphics()
{
GLFWwindow* window;
if ( !glfwInit() )
{
fputs("failed to initialize glfw!\n", stderr);
exit(1);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // opengl 3.x
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // opengl 3.3
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // needed for osx
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, NULL, NULL);
if (!window)
{
fputs("failed to create window!\n", stderr);
exit(1);
}
glfwMakeContextCurrent(window);
glewExperimental = true;
if ( glewInit() != GLEW_OK )
{
fputs("failed to initialize glew!\n", stderr);
exit(1);
}
if ( !GLEW_VERSION_3_3 )
{
fputs("opengl 3.3 support is required!\n", stderr);
exit(1);
}
return window;
};
unsigned int compileShader(const char* shaderSource, GLenum type)
{
unsigned int shaderID = glCreateShader(type);
glShaderSource(shaderID, 1, &shaderSource , NULL);
glCompileShader(shaderID);
int status;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &status);
if ( status == GL_FALSE )
{
int errorLength;
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &errorLength);
char errorString[errorLength+1];
glGetShaderInfoLog(shaderID, errorLength, NULL, errorString);
fprintf(stderr, "glsl compile error: %s", errorString);
exit(1);
}
return shaderID;
}
unsigned int compileShaderProgram(const char* vsSource, const char* fsSource)
{
unsigned int programID = glCreateProgram();
unsigned int vsID = compileShader(vsSource, GL_VERTEX_SHADER);
unsigned int fsID = compileShader(fsSource, GL_FRAGMENT_SHADER);
glAttachShader(programID, vsID);
glAttachShader(programID, fsID);
glLinkProgram(programID);
int status;
glGetProgramiv(programID, GL_LINK_STATUS, &status);
if ( status == GL_FALSE )
{
int errorLength;
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &errorLength);
char errorString[errorLength+1];
glGetProgramInfoLog(programID, errorLength, NULL, errorString);
fprintf(stderr, "glsl linking error: %s", errorString);
exit(1);
}
glDetachShader(programID, vsID);
glDetachShader(programID, fsID);
glDeleteShader(vsID);
glDeleteShader(fsID);
return programID;
}
unsigned int randomTexture(int width, int height)
{
unsigned int textureID;
int size = width * height;
unsigned char* buffer = malloc( size * sizeof(unsigned char) );
for (int i = 0; i < size; i++)
{
if ( rand() & 1 )
{
buffer[i] = 0x00;
}
else
{
buffer[i] = 0xFF;
}
}
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_R8,
width, height, 0, GL_RED,
GL_UNSIGNED_BYTE, buffer
);
free(buffer);
return textureID;
}
int main()
{
GLenum glError;
GLFWwindow* window;
unsigned int shader;
unsigned int texture;
unsigned int vertPosBuffer;
unsigned int uvCoordBuffer;
unsigned int vertexArray;
int textureUniform;
int vertPosAttribute;
int uvCoordAttribute;
srand( time(NULL) );
window = setupGraphics();
shader = compileShaderProgram(BASIC_VERT_SHADER, BASIC_FRAG_SHADER);
textureUniform = glGetUniformLocation(shader, "texture");
vertPosAttribute = glGetAttribLocation(shader, "vs_position");
uvCoordAttribute = glGetAttribLocation(shader, "vs_uvCoord");
texture = randomTexture(WIDTH, HEIGHT);
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glGenBuffers(1, &vertPosBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), VERT_POS, GL_STATIC_DRAW);
glVertexAttribPointer(vertPosAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &uvCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), TEXTURE_UV, GL_STATIC_DRAW);
glVertexAttribPointer(uvCoordAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
while ( !glfwWindowShouldClose(window) )
{
glClear( GL_COLOR_BUFFER_BIT );
glClearColor(0.f, 0.f, 0.f, 1.f);
glUseProgram(shader);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(textureUniform, 0);
glBindVertexArray(vertexArray);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glfwSwapBuffers(window);
glfwPollEvents();
while((glError = glGetError()) != GL_NO_ERROR)
{
fprintf(stderr, "gl error: %d\n", glError);
exit(1);
}
}
glDeleteVertexArrays(1, &vertexArray);
glDeleteBuffers(1, &vertPosBuffer);
glDeleteBuffers(1, &uvCoordBuffer);
glDeleteTextures(1, &texture);
glDeleteProgram(shader);
return 0;
}

The major issue is that you have forgotten to enable the generic vertex attribute arrays. See glEnableVertexAttribArray
glGenBuffers(1, &vertPosBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), VERT_POS, GL_STATIC_DRAW);
glVertexAttribPointer(vertPosAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray( vertPosAttribute ); // <-----------------
glGenBuffers(1, &uvCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, 8*sizeof(float), TEXTURE_UV, GL_STATIC_DRAW);
glVertexAttribPointer(uvCoordAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray( uvCoordAttribute ); // <-----------------
As mentioned in the comments to your question you should set the textue minifying filter to GL_LINEAR or GL_NEAREST, since you do not use mipmaps:
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_R8,
width, height, 0, GL_RED,
GL_UNSIGNED_BYTE, buffer.data()
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
A triangle stripe which creates a quad is setup like this:
const float TEXTURE_UV[] =
{
0.f, 0.f,
1.f, 0.f,
0.f, 1.f,
1.f, 1.f
};
const float VERT_POS[] =
{
-1.f, -1.f,
1.f, -1.f,
-1.f, 1.f,
1.f, 1.f
};
But you can draw a trangle fan instead:
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

Related

Opengl is not using the correct texture

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.

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();
}

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);
}

OpenGL 4.x textures not working

I'm new here.
I'm having trouble with textures in OpenGL 4.4, I just get a black screen.
Here's my code (I suspect everything before glGenBuffers() is unimportant but you never know):
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "eternity.h"
#include "error.h"
#define STB_IMAGE_IMPLEMENTATION
#define STBI_FAILURE_USERMSG
#include "stb_image.h"
int main(int argc, char *argv[])
{
if (argc < 2)
DIE("%s\n", "not enough arguments");
GLuint width = 0, height = 0, bpp = 0;
unsigned char *image_raw;
if ((image_raw = stbi_load("image.jpg", &width, &height, &bpp, 0)) == NULL)
DIE("stbi error: %s\n", stbi_failure_reason());
uint8_t rv;
if (rv = initialize_glfw())
DIE("%s%" PRIu8 "\n", "initialize_glfw() failed with code ", rv);
glfwSetErrorCallback(glfw_error_callback);
glfw *glfw = malloc(sizeof(glfw));
if (!(glfw->window = glfwCreateWindow(
width,
height,
"Eternity",
NULL,
NULL)))
{
glfwTerminate();
DIE("%s\n", "glfwCreateWindow failed");
}
glfwMakeContextCurrent(glfw->window);
glfwSetKeyCallback(glfw->window, glfw_key_callback);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
eternity_cleanup(glfw);
DIE("%s\n", "glewInit() failed");
}
printf("OpenGL %s\n", glGetString(GL_VERSION));
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
GLshort vertices[] = {
-1, 1, 0,
1, 1, 0,
-1, -1, 0,
1, -1, 0
};
GLushort texcoords[] = {
0, 0,
1, 0,
0, 1,
1, 1
};
gl gl = {0}; // This is just a struct
glGenBuffers(1, &(gl.points_vbo));
glBindBuffer(GL_ARRAY_BUFFER, gl.points_vbo);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLshort), vertices, GL_STATIC_DRAW);
glGenBuffers(1, &(gl.texcoords_vbo));
glBindBuffer(GL_ARRAY_BUFFER, gl.texcoords_vbo);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLushort), texcoords, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, gl.points_vbo); // EDIT: I added this line
glGenVertexArrays(1, &(gl.vao));
glBindVertexArray(gl.vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_SHORT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_UNSIGNED_SHORT, GL_FALSE, 0, NULL);
setup_shaders(&gl);
GLenum format;
switch (bpp * 8)
{
case 24:
format = GL_RGB;
break;
case 32:
format = GL_RGBA;
break;
}
GLuint texture_id = 0;
glGenTextures(1, &texture_id);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, width, height, 0, format, GL_UNSIGNED_BYTE, image_raw);
stbi_image_free(image_raw);
glBindTexture(GL_TEXTURE_2D, texture_id);
check_error();
while (!glfwWindowShouldClose(glfw->window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(gl.shader_program);
glBindVertexArray(gl.vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glfwSwapBuffers(glfw->window);
glfwPollEvents();
}
glDeleteTextures(1, &texture_id);
eternity_cleanup(glfw);
}
void setup_shaders(gl *gl)
{
const GLchar *vs_source =
"#version 440\n"
"layout(location = 0) in vec3 vp;"
"layout(location = 1) in vec2 vt;"
"out vec2 texcoord;"
"void main() { gl_Position = vec4(vp, 1.0);"
"texcoord = vt; }",
*fs_source =
"#version 440\n"
"out vec4 frag_color;"
"in vec2 texcoord;"
"uniform sampler2D texture;"
"void main() { frag_color = texture2D(texture, texcoord); }";
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vs_source, NULL);
glCompileShader(vs);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fs_source, NULL);
glCompileShader(fs);
gl->shader_program = glCreateProgram();
glAttachShader(gl->shader_program, fs);
glAttachShader(gl->shader_program, vs);
glLinkProgram(gl->shader_program);
glDeleteShader(vs);
glDeleteShader(fs);
}
uint8_t initialize_glfw(void)
{
int major = 0, minor = 0, rev = 0;
glfwGetVersion(&major, &minor, &rev);
printf("GLFW %d.%d rev %d\n", major, minor, rev);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, minor);
glfwWindowHint(GLFW_CONTEXT_REVISION, rev);
glfwWindowHint(GLFW_SAMPLES, 8);
if (!glfwInit())
return 1;
return 0;
}
void glfw_error_callback(int error, const char *description)
{
printf("glfw error callback triggered\n");
fprintf(stderr, "%d: %s\n", error, description);
}
void glfw_key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void eternity_cleanup(glfw* glfw)
{
glfwDestroyWindow(glfw->window);
free(glfw);
glfwTerminate();
}
I'm not sure if I've forgotten to do something here or if I'm doing something incorrectly, I have tried very hard to fix this but the black screen persists.
I feel like the problem is in my shaders (hardcoded in setup_shaders()), or maybe around glTexImage2D()?
edit:
I found that if I call glBindBuffer again right before glGenVertexArrays, then I get a light blue screen, and the specific image that I am loading is predominantly this exact shade of blue, so I believe I am sampling a single pixel.
I have updated the source code with a comment where I added a line.
My problem is now that I am sampling only one pixel.

OpenGL - shaders, symbol is defined with 2 different types in v. and f. shaders

I'm learning OpenGL from this tutorial: http://openglbook.com/the-book/ . I have problem with shaders. I'm getting error during compiling/linking shaders but I don't know what I'm doing wrong.
Error:
Symbol ex_Color is defined with 2 different types in vertex and
fragment shaders.
Shaders (I modified them a bit because of GLSL version):
const GLchar* VertexShader =
{
"#version 130\n"\
"in vec4 in_Position;\n"\
"in vec4 in_Color;\n"\
"out vec4 ex_Color;\n"\
"void main(void)\n"\
"{\n"\
" gl_Position = in_Position;\n"\
" ex_Color = in_Color;\n"\
"}\n"
};
const GLchar* FragmentShader =
{
"#version 130\n"\
"precision mediump float;\n"\
"in vec4 ex_Color;\n"\
"out vec4 out_Color;\n"\
"void main(void)\n"\
"{\n"\
" out_Color = ex_Color;\n"\
"}\n"
};
Source code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#define WINDOW_TITLE_PREFIX "Chapter 2"
int CurrentWidth = 800,
CurrentHeight = 600,
WindowHandle = 0;
unsigned FrameCount = 0;
GLuint
VertexShaderId,
FragmentShaderId,
ProgramId,
VaoId,
VboId,
ColorBufferId;
const GLchar* VertexShader =
{
"#version 130\n"\
"in vec4 in_Position;\n"\
"in vec4 in_Color;\n"\
"out vec4 ex_Color;\n"\
"void main(void)\n"\
"{\n"\
" gl_Position = in_Position;\n"\
" ex_Color = in_Color;\n"\
"}\n"
};
const GLchar* FragmentShader =
{
"#version 130\n"\
"precision mediump float;\n"\
"in vec4 ex_Color;\n"\
"out vec4 out_Color;\n"\
"void main(void)\n"\
"{\n"\
" out_Color = ex_Color;\n"\
"}\n"
};
void Initialize(int, char*[]);
void InitWindow(int, char*[]);
void ResizeFunction(int, int);
void RenderFunction(void);
void TimerFunction(int);
void IdleFunction(void);
void Cleanup(void);
void CreateVBO(void);
void DestroyVBO(void);
void CreateShaders(void);
void DestroyShaders(void);
int main(int argc, char* argv[])
{
Initialize(argc, argv);
glutMainLoop();
exit(EXIT_SUCCESS);
}
void Initialize(int argc, char* argv[])
{
GLenum GlewInitResult;
InitWindow(argc, argv);
glewExperimental = GL_TRUE;
GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult) {
fprintf(
stderr,
"ERROR: %s\n",
glewGetErrorString(GlewInitResult)
);
exit(EXIT_FAILURE);
}
fprintf(
stdout,
"INFO: OpenGL Version: %s (GLSL = %s)\n",
glGetString(GL_VERSION),
glGetString(GL_SHADING_LANGUAGE_VERSION)
);
CreateShaders();
CreateVBO();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
void InitWindow(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitContextVersion(3, 1);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutSetOption(
GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS
);
glutInitWindowSize(CurrentWidth, CurrentHeight);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX);
if(WindowHandle < 1) {
fprintf(
stderr,
"ERROR: Could not create a new rendering window.\n"
);
exit(EXIT_FAILURE);
}
glutReshapeFunc(ResizeFunction);
glutDisplayFunc(RenderFunction);
glutIdleFunc(IdleFunction);
glutTimerFunc(0, TimerFunction, 0);
glutCloseFunc(Cleanup);
}
void ResizeFunction(int Width, int Height)
{
CurrentWidth = Width;
CurrentHeight = Height;
glViewport(0, 0, CurrentWidth, CurrentHeight);
}
void RenderFunction(void)
{
++FrameCount;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
glutPostRedisplay();
}
void IdleFunction(void)
{
glutPostRedisplay();
}
void TimerFunction(int Value)
{
if (0 != Value) {
char* TempString = (char*)
malloc(512 + strlen(WINDOW_TITLE_PREFIX));
sprintf(
TempString,
"%s: %d Frames Per Second # %d x %d",
WINDOW_TITLE_PREFIX,
FrameCount * 4,
CurrentWidth,
CurrentHeight
);
glutSetWindowTitle(TempString);
free(TempString);
}
FrameCount = 0;
glutTimerFunc(250, TimerFunction, 1);
}
void Cleanup(void)
{
DestroyShaders();
DestroyVBO();
}
void CreateVBO(void)
{
GLfloat Vertices[] = {
-0.8f, -0.8f, 0.0f, 1.0f,
0.0f, 0.8f, 0.0f, 1.0f,
0.8f, -0.8f, 0.0f, 1.0f
};
GLfloat Colors[] = {
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f
};
GLenum ErrorCheckValue = glGetError();
glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);
glGenBuffers(1, &VboId);
glBindBuffer(GL_ARRAY_BUFFER, VboId);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glGenBuffers(1, &ColorBufferId);
glBindBuffer(GL_ARRAY_BUFFER, ColorBufferId);
glBufferData(GL_ARRAY_BUFFER, sizeof(Colors), Colors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
fprintf(
stderr,
"ERROR: Could not create a VBO: %s \n",
gluErrorString(ErrorCheckValue)
);
exit(-1);
}
}
void DestroyVBO(void)
{
GLenum ErrorCheckValue = glGetError();
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &ColorBufferId);
glDeleteBuffers(1, &VboId);
glBindVertexArray(0);
glDeleteVertexArrays(1, &VaoId);
ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
fprintf(
stderr,
"ERROR: Could not destroy the VBO: %s \n",
gluErrorString(ErrorCheckValue)
);
exit(-1);
}
}
void CreateShaders(void)
{
GLenum ErrorCheckValue = glGetError();
VertexShaderId = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(VertexShaderId, 1, &VertexShader, NULL);
glCompileShader(VertexShaderId);
GLint vertex_shader_status;
glGetShaderiv(FragmentShaderId, GL_COMPILE_STATUS, &vertex_shader_status);
if (vertex_shader_status == 0)
{
GLint logLength;
glGetShaderiv(FragmentShaderId, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(FragmentShaderId, logLength, &logLength, log);
fprintf(
stderr,
"ERROR: Could not create the vertex shader: %s \n",
log
);
free(log);
}
glDeleteShader(FragmentShaderId);
}
FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL);
glCompileShader(FragmentShaderId);
ProgramId = glCreateProgram();
glAttachShader(ProgramId, VertexShaderId);
glAttachShader(ProgramId, FragmentShaderId);
glBindAttribLocation(ProgramId, 0, "in_Position");
glBindAttribLocation(ProgramId, 1, "in_Color");
glLinkProgram(ProgramId);
glUseProgram(ProgramId);
GLint logLength, status;
glValidateProgram(ProgramId);
glGetProgramiv(ProgramId, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(ProgramId, logLength, &logLength, log);
fprintf(
stderr,
"ERROR: Could not create the program: %s \n",
log
);
free(log);
}
glGetProgramiv(ProgramId, GL_VALIDATE_STATUS, &status);
if (status == 0) {
fprintf(
stderr,
"ERROR: Could not create the program: \n"
);
}
ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
fprintf(
stderr,
"ERROR: Could not create the shaders: %s \n",
gluErrorString(ErrorCheckValue)
);
exit(-1);
}
}
void DestroyShaders(void)
{
GLenum ErrorCheckValue = glGetError();
glUseProgram(0);
glDetachShader(ProgramId, VertexShaderId);
glDetachShader(ProgramId, FragmentShaderId);
glDeleteShader(FragmentShaderId);
glDeleteShader(VertexShaderId);
glDeleteProgram(ProgramId);
ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
fprintf(
stderr,
"ERROR: Could not destroy the shaders: %s \n",
gluErrorString(ErrorCheckValue)
);
exit(-1);
}
}
I have Mobility Radeon HD4570 graphics card (OpenGL 3.1, GLSL 1.30).
"precision mediump float;" changes the type of all floats defined in that shader. Is there a reason you're using that declaration? Note that GLSL per specification attaches no meaning to it at all. It was added for compatibility with GLES.
If I'm not mistaken then floats by default have highp precision in vertex shader. Add mediump to out vec ex_Color in vertex shader.

Resources