Hi everyone. This is my first OpenGL program, and I understand all of of the concepts (VAOs, VBOs, etc…) but just cannot get it to work.
//
// main.cpp
// opengl_rect_w_shader_header
//
// Created by Pramod on 21/05/2017.
// Copyright © 2017 Pramod. All rights reserved.
//
#include <iostream>
#include <SDL2/SDL.h>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
SDL_GLContext context;
SDL_Window * window;
bool initWindow(){
if (SDL_Init(SDL_INIT_VIDEO)<0){
std::cout << "Can't make SDL" << std::endl;
}
//what version we are using
SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
//SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
window = SDL_CreateWindow("Rectangle", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 512, 512, SDL_WINDOW_OPENGL);
if (!window){
std::cout << "No window created" << std::endl;
//window = NULL;
return false;
}
context = SDL_GL_CreateContext(window);
if (!context){
std::cout << "No context created" << std::endl;
return false;
}
//double buffering - 24bit z buffer (might need changing for different systems)
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//Makes buffer swap sync with VBLANK
SDL_GL_SetSwapInterval(1);
glViewport(0, 0, 512, 512);
std:: cout << "Initialised" << std::endl;
return true;
};
int main(int argc, const char * argv[]) {
initWindow();
/*
const char * vshaderFile = "vertex.txt";
const char * fshaderFile = "fragment.txt";
long length;
char * vertexBuf;
FILE * vertexFile = fopen(vshaderFile, "r");
if(!vertexFile) { std::cout << "Could not open vertex shader" << std::endl; }
fseek(vertexFile, 0, SEEK_END);
length = ftell(vertexFile);
vertexBuf = new char [length + 1];
fseek(vertexFile, 0, SEEK_SET);
fread(vertexBuf, length, 1, vertexFile);
fclose(vertexFile);
vertexBuf[length] = 0; //makes the terminating character null
//read fragment shader
long length2;
char * fragmentBuf;
FILE * fragmentFile = fopen(fshaderFile, "r");
if(!fragmentFile){ std::cout << "Could not open fragment shader" << std::endl; }
fseek(fragmentFile, 0, SEEK_END);
length2 = ftell(fragmentFile);
fragmentBuf = new char [length2 + 1];
fseek(fragmentFile, 0, SEEK_SET);
fread(fragmentBuf, length2, 1, fragmentFile);
fclose(fragmentFile);
fragmentBuf[length2] = 0;
*/
//makes the source pointers the buffers
const char *vShaderSource = "#version 330 core
"
"layout (location = 0) in vec3 aPos;
"
"void main()
"
"{
"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
"
"}\0";
const char *fShaderSource = "#version 330 core
"
"out vec4 FragColor;
"
"void main()
"
"{
"
" FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
"
"}
\0";
//compiles shaders
//fragment
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
//std::cout << glGetError() << std::endl;
glShaderSource(fragmentShader, 1, &fShaderSource, NULL);
glCompileShader(fragmentShader);
int success;
char infoLog[512];
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
" << infoLog << std::endl;
}
//vertex
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vShaderSource, NULL);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED
" << infoLog << std::endl;
}
//releases buffers
//delete[] fragmentBuf;
//delete[] vertexBuf;
//fragmentBuf = NULL;
//vertexBuf = NULL;
//links program
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED
" << infoLog << std::endl;
}
//deletes unneeded shaders
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
std:: cout << "Shaders complete" << std:: endl;
//std::cout << vShaderSource << std::endl << std::endl << fShaderSource << std::endl;
//=================================================================================================================
GLfloat vertices[3][4] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
GLint indices[3][2] = { // note that we start from 0!
0, 1, 3, // first Triangle
1, 2, 3 // second Triangle
};
GLuint VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof (float), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(int), indices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
// remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray(0);
bool loop = true;
glClearColor(0.5f, 0.1f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (void*)0);
//glBindVertexArray(0);
SDL_GL_SwapWindow(window);
std::cout << glGetError() << std::endl;
//std::cout << glCheckError() << std::endl;
while (loop) {
SDL_Event e;
while(SDL_PollEvent(&e)){
if (e.type == SDL_QUIT) loop = false;
if (e.type == SDL_KEYDOWN){
switch(e.key.keysym.sym){
case SDLK_ESCAPE:
loop = false;
break;
case SDLK_y:
std::cout << glGetString(GL_VERSION) << std::endl;
break;
}
std::cout << "Error: " << SDL_GetError() << std::endl;
std::cout << glGetError() << std::endl;
}
}
}
}
I have spent at least 3 months looking at this and wondering why it doesn’t work…
What happens when you run the program: Screen goes fuschia purple colour, but does not draw rectangle. I set the rectangle colour to white just to make sure it stood out against the background.
I made sure that I swap the buffer so that I can see the rectangle. I also checked every single function call against the prototypes and tutorials to make sure I had the right parameters.
GL version returned is 3.3, and error code is 0. SDL also returns no errors.
I can’t see what I have done wrong compared to the tutorial https://learnopengl.com/#!Getting-started/Hello-Triangle … Can someone else run this on their computer and see if the rectangle is drawn or not? (The code doesn’t have the #ifdef stuff to make it work on both Windows and Mac/Linux, sorry). Thank you.
edit: FIXED! I changed GL_UNSIGNED_BYTE in the glDrawElements to GL_UNSIGNED_INT. Phew! Thank you everyone! My first rectangle (well, square…) at last…