I'm having a strange problem, and I don't know what could be causing it. My current code is identical to how I've done this before. I'm trying to render a rectangle using VBO and orthographic projection.
My results:
What I expect:
3x3 rectangle in the top left corner
#include <stdio.h>
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include "lodepng.h"
static const int FALSE = 0;
static const int TRUE = 1;
static const char* VERT_SHADER =
"#version 330\n"
"layout(location=0) in vec4 VertexPosition; "
"layout(location=1) in vec2 UV;"
"uniform mat4 uProjectionMatrix;"
/*"out vec2 TexCoords;"*/
"void main(void) {"
" gl_Position = uProjectionMatrix*VertexPosition;"
/*" TexCoords = UV;"*/
"}";
static const char* FRAG_SHADER =
"#version 330\n"
/*"uniform sampler2D uDiffuseTexture;"
"uniform vec4 uColor;"
"in vec2 TexCoords;"*/
"out vec4 FragColor;"
"void main(void) {"
/* " vec4 texel = texture2D(uDiffuseTexture, TexCoords);"
" if(texel.a <= 0) {"
" discard;"
" }"
" FragColor = texel;"*/
" FragColor = vec4(1.f);"
"}";
static int g_running;
static GLFWwindow *gl_window;
static float gl_projectionMatrix[16];
/*
Structures
*/
typedef struct _Vertex {
float x, y, z, w;
float u, v;
} Vertex;
typedef struct _Position {
float x, y;
} Position;
typedef struct _Bitmap {
unsigned char *pixels;
unsigned int width, height;
} Bitmap;
typedef struct _Texture {
GLuint id;
unsigned int width, height;
} Texture;
typedef struct _VertexBuffer {
GLuint bufferObj, vertexArray;
} VertexBuffer;
typedef struct _ShaderProgram {
GLuint vertexShader, fragmentShader, program;
} ShaderProgram;
/*
http://en.wikipedia.org/wiki/Orthographic_projection
*/
void createOrthoProjection(float *projection, float width, float height, float far, float near) {
const float left = 0;
const float right = width;
const float top = 0;
const float bottom = height;
projection[0] = 2.f / (right - left);
projection[1] = 0.f;
projection[2] = 0.f;
projection[3] = -(right+left) / (right-left);
projection[4] = 0.f;
projection[5] = 2.f / (top - bottom);
projection[6] = 0.f;
projection[7] = -(top + bottom) / (top - bottom);
projection[8] = 0.f;
projection[9] = 0.f;
projection[10] = -2.f / (far-near);
projection[11] = (far+near)/(far-near);
projection[12] = 0.f;
projection[13] = 0.f;
projection[14] = 0.f;
projection[15] = 1.f;
}
/*
Textures
*/
void loadBitmap(const char *filename, Bitmap *bitmap, int *success) {
int error = lodepng_decode32_file(&bitmap->pixels, &bitmap->width, &bitmap->height, filename);
if (error != 0) {
printf("Failed to load bitmap. ");
printf(lodepng_error_text(error));
success = FALSE;
return;
}
}
void destroyBitmap(Bitmap *bitmap) {
free(bitmap->pixels);
}
void createTexture(Texture *texture, const Bitmap *bitmap) {
texture->id = 0;
glGenTextures(1, &texture->id);
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_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->width, bitmap->height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, bitmap->pixels);
glBindTexture(GL_TEXTURE_2D, 0);
}
void destroyTexture(Texture *texture) {
glDeleteTextures(1, &texture->id);
texture->id = 0;
}
/*
Vertex Buffer
*/
void createVertexBuffer(VertexBuffer *vertexBuffer, Vertex *vertices) {
glGenBuffers(1, &vertexBuffer->bufferObj);
glGenVertexArrays(1, &vertexBuffer->vertexArray);
glBindVertexArray(vertexBuffer->vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->bufferObj);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * 6, (const GLvoid*)vertices, GL_STATIC_DRAW);
const unsigned int uvOffset = sizeof(float) * 4;
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)uvOffset);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void destroyVertexBuffer(VertexBuffer *vertexBuffer) {
glDeleteBuffers(1, &vertexBuffer->bufferObj);
glDeleteVertexArrays(1, &vertexBuffer->vertexArray);
}
void bindVertexBuffer(VertexBuffer *vertexBuffer) {
glBindVertexArray(vertexBuffer->vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer->bufferObj);
}
void drawVertexBufferMode(GLenum mode) {
glDrawArrays(mode, 0, 6);
}
void drawVertexBuffer() {
drawVertexBufferMode(GL_TRIANGLES);
}
void unbindVertexBuffer() {
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
/*
Shaders
*/
void compileShader(ShaderProgram *shaderProgram, const char *vertexSrc, const char *fragSrc) {
GLenum err;
shaderProgram->vertexShader = glCreateShader(GL_VERTEX_SHADER);
shaderProgram->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
if (shaderProgram->vertexShader == 0) {
printf("Failed to create vertex shader.");
return;
}
if (shaderProgram->fragmentShader == 0) {
printf("Failed to create fragment shader.");
return;
}
glShaderSource(shaderProgram->vertexShader, 1, &vertexSrc, NULL);
glCompileShader(shaderProgram->vertexShader);
glGetShaderiv(shaderProgram->vertexShader, GL_COMPILE_STATUS, &err);
if (err != GL_TRUE) {
printf("Failed to compile vertex shader.");
return;
}
glShaderSource(shaderProgram->fragmentShader, 1, &fragSrc, NULL);
glCompileShader(shaderProgram->fragmentShader);
glGetShaderiv(shaderProgram->fragmentShader, GL_COMPILE_STATUS, &err);
if (err != GL_TRUE) {
printf("Failed to compile fragment shader.");
return;
}
shaderProgram->program = glCreateProgram();
glAttachShader(shaderProgram->program, shaderProgram->vertexShader);
glAttachShader(shaderProgram->program, shaderProgram->fragmentShader);
glLinkProgram(shaderProgram->program);
glGetProgramiv(shaderProgram->program, GL_LINK_STATUS, &err);
if (err != GL_TRUE) {
printf("Failed to link shader.");
return;
}
}
void destroyShader(ShaderProgram *shaderProgram) {
glDetachShader(shaderProgram->program, shaderProgram->vertexShader);
glDetachShader(shaderProgram->program, shaderProgram->fragmentShader);
glDeleteShader(shaderProgram->vertexShader);
glDeleteShader(shaderProgram->fragmentShader);
glDeleteProgram(shaderProgram->program);
}
GLuint getUniformLocation(const char *name, ShaderProgram *program) {
GLuint result = 0;
result = glGetUniformLocation(program->program, name);
return result;
}
void setUniformMatrix(float *matrix, const char *name, ShaderProgram *program) {
GLuint loc = getUniformLocation(name, program);
if (loc == -1) {
printf("Failed to get uniform location in setUniformMatrix.\n");
return;
}
glUniformMatrix4fv(loc, 1, GL_FALSE, matrix);
}
/*
General functions
*/
static int isRunning() {
return g_running && !glfwWindowShouldClose(gl_window);
}
static void initializeGLFW(GLFWwindow **window, int width, int height, int *success) {
if (!glfwInit()) {
printf("Failed it inialize GLFW.");
*success = FALSE;
return;
}
glfwWindowHint(GLFW_RESIZABLE, 0);
*window = glfwCreateWindow(width, height, "Alignments", NULL, NULL);
if (!*window) {
printf("Failed to create window.");
glfwTerminate();
*success = FALSE;
return;
}
glfwMakeContextCurrent(*window);
GLenum glewErr = glewInit();
if (glewErr != GLEW_OK) {
printf("Failed to initialize GLEW.");
printf(glewGetErrorString(glewErr));
*success = FALSE;
return;
}
glClearColor(0.f, 0.f, 0.f, 1.f);
glViewport(0, 0, width, height);
*success = TRUE;
}
int main(int argc, char **argv) {
int err = FALSE;
initializeGLFW(&gl_window, 480, 320, &err);
glDisable(GL_DEPTH_TEST);
if (err == FALSE) {
return 1;
}
createOrthoProjection(gl_projectionMatrix, 480.f, 320.f, 0.f, 1.f);
g_running = TRUE;
ShaderProgram shader;
compileShader(&shader, VERT_SHADER, FRAG_SHADER);
glUseProgram(shader.program);
setUniformMatrix(&gl_projectionMatrix, "uProjectionMatrix", &shader);
Vertex rectangle[6];
VertexBuffer vbo;
rectangle[0] = (Vertex){0.f, 0.f, 0.f, 1.f, 0.f, 0.f}; // Top left
rectangle[1] = (Vertex){3.f, 0.f, 0.f, 1.f, 1.f, 0.f}; // Top right
rectangle[2] = (Vertex){0.f, 3.f, 0.f, 1.f, 0.f, 1.f}; // Bottom left
rectangle[3] = (Vertex){3.f, 0.f, 0.f, 1.f, 1.f, 0.f}; // Top left
rectangle[4] = (Vertex){0.f, 3.f, 0.f, 1.f, 0.f, 1.f}; // Bottom left
rectangle[5] = (Vertex){3.f, 3.f, 0.f, 1.f, 1.f, 1.f}; // Bottom right
createVertexBuffer(&vbo, &rectangle);
bindVertexBuffer(&vbo);
while (isRunning()) {
glClear(GL_COLOR_BUFFER_BIT);
glfwPollEvents();
drawVertexBuffer();
glfwSwapBuffers(gl_window);
}
unbindVertexBuffer(&vbo);
glUseProgram(0);
destroyShader(&shader);
destroyVertexBuffer(&vbo);
glfwTerminate();
return 0;
}