I have been learning OpenGL for a while now, and I decided to try to make my own “game engine”.
My first step is to create a class for a 3D object.
The constructor assigns its arguments to class variables (for example, the object’s position).
There are also three other functions: void init() - initializes OpenGL stuff, void update() - updates the model, view and projection matrices, void draw() - draws the object.
But it doesn’t work. The program doesn’t draw anything and I can’t find the error.
Code (it doesn’t let me post links):
main.cpp
#define GLEW_STATIC
#define GLM_FORCE_RADIANS
#include <glew.h>
#include <GLFW\glfw3.h>
#include <glm\glm.hpp>
#include <glm\gtc\matrix_transform.hpp>
#include <glm\gtc ype_ptr.hpp>
#include <SOIL.h>
#include <iostream>
#include <fstream>
#include <string>
#include <chrono>
#include "shaders.h"
#include "object.h"
using namespace std;
float vertices [] =
{
// cube
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f
};
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(1024, 768, "opengl tutorial", nullptr, nullptr);
if (window == nullptr)
{
cout << "Failed to create window" << endl;
glfwTerminate();
system("pause");
return -1;
}
glfwMakeContextCurrent(window);
cout << "Address of window: " << window << endl;
glewExperimental = GL_TRUE;
glewInit();
glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
string vsStr = loadShader("vertex.glsl");
const char* vsSource = vsStr.c_str();
glShaderSource(vs, 1, &vsSource, nullptr);
glCompileShader(vs);
char vsLog[512];
glGetShaderInfoLog(vs, 512, nullptr, vsLog);
cout << "Vertex shader output: " << endl;
cout << vsLog << endl;
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
string fsStr = loadShader("fragment.glsl");
const char* fsSource = fsStr.c_str();
glShaderSource(fs, 1, &fsSource, nullptr);
glCompileShader(fs);
char fsLog[512];
glGetShaderInfoLog(fs, 512, nullptr, fsLog);
cout << "Fragment shader output: " << endl;
cout << fsLog << endl;
GLuint prog = glCreateProgram();
glAttachShader(prog, vs);
glAttachShader(prog, fs);
glLinkProgram(prog);
float rot = 0.0f;
glm::mat4 model;
model = glm::mat4(1.0f) * glm::rotate(model, glm::radians(rot), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 view;
view = glm::lookAt(glm::vec3(0.0f, 1.2f, 3.5f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 proj;
proj = glm::perspective(glm::radians(45.0f), 1024.0f / 768.0f, 1.0f, 10.0f);
object cube(vertices, 36, "box-texture.png", prog, glm::vec3(0.0f, 0.0f, 0.0f), view, proj);
cube.init();
while (!glfwWindowShouldClose(window))
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
int currentL = glfwGetKey(window, GLFW_KEY_LEFT);
int currentR = glfwGetKey(window, GLFW_KEY_RIGHT);
if (currentL == GLFW_PRESS)
{
rot += 1.0f;
}
else if (currentR == GLFW_PRESS)
{
rot -= 1.0f;
}
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
cube.update();
cube.draw();
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteShader(vs);
glDeleteShader(fs);
glfwTerminate();
return 0;
}
object.h
#pragma once
#include <glew.h>
#include <GLFW\glfw3.h>
#include <glm\gtc\matrix_transform.hpp>
#include <glm\gtc ype_ptr.hpp>
#include <SOIL.h>
#include "shaders.h"
#include <iostream>
using namespace std;
// 3D object
class object
{
public:
GLuint vbo;
GLuint vao;
GLuint texture;
GLuint prog; // shader program to use
glm::vec3 position;
float* vertices;
int count; // number of vertices
const char* texName; // texture file name
glm::mat4 model; //
glm::mat4 view; // matrices
glm::mat4 proj; //
GLint posAttrib; //
GLint colAttrib; // attributes
GLint texAttrib; //
GLint uniModel; //
GLint uniView; // uniforms
GLint uniProj; //
object(float* _vertices, int _count, const char* _texName, GLuint _prog, glm::vec3 _pos, glm::mat4 _view, glm::mat4 _proj)
{
vertices = _vertices;
prog = _prog;
position = _pos;
count = _count;
texName = _texName;
model = glm::mat4(1.0f) * glm::translate(model, position);
view = _view;
proj = _proj;
}
void init()
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glUseProgram(prog);
posAttrib = glGetAttribLocation(prog, "pos"); // position
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), nullptr);
colAttrib = glGetAttribLocation(prog, "vColor"); // color
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*) (3 * sizeof(float)));
texAttrib = glGetAttribLocation(prog, "tex_coord"); // tex coords
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*) (6 * sizeof(float)));
uniModel = glGetUniformLocation(prog, "model");
uniView = glGetUniformLocation(prog, "view");
uniProj = glGetUniformLocation(prog, "proj");
int w, h;
unsigned char* texData = SOIL_load_image(texName, &w, &h, nullptr, SOIL_LOAD_RGB);
if (texData == nullptr)
{
cout << "The texture is nullptr" << endl;
system("pause");
}
else
{
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, texData);
SOIL_free_image_data(texData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));
}
}
void update()
{
glUseProgram(prog);
model = glm::mat4(1.0f) * glm::translate(model, position);
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));
}
void draw()
{
// binding stuff before drawing (in case more objects are drawn)
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindTexture(GL_TEXTURE_2D, texture);
glDrawArrays(GL_TRIANGLES, 0, count);
}
~object()
{
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
glDeleteTextures(1, &texture);
}
};
You can notice that I’m loading shaders with my own function from another file, but that has nothing to do with this.
Thanks