Texturing; OBJ loader

This commit is contained in:
2014-11-14 22:36:38 +01:00
parent 0be3e0a50e
commit df90fbf952
15 changed files with 956 additions and 281 deletions

412
main.cc
View File

@@ -1,11 +1,12 @@
#include <cstdio>
#include <cmath>
#include <string>
#include <unordered_map>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
//#include <GL/glext.h>
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
@@ -13,29 +14,59 @@
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
const char vertexShader[] = "#version 330 core\n"
"uniform mat4 projection_matrix;\n"
"uniform mat4 modelview_matrix;\n"
"\n"
"in vec3 vertex;\n"
"in vec3 vertexColor;\n"
"\n"
"out vec3 fragColor;\n"
"\n"
"void main(void) {\n"
"\tgl_Position = projection_matrix * modelview_matrix * vec4(vertex, 1.0);\n"
"\tfragColor = vertexColor;\n"
"}\n";
#include "common.hh"
#include "shaders.hh"
#include "texture.hh"
#include "objectParser.hh"
const char fragShader[] = "#version 330 core\n"
"in vec3 fragColor;\n"
"\n"
"out vec3 color;\n"
"\n"
"void main(void) {\n"
"\tcolor = fragColor;\n"
//"\tgl_FragDepth = gl_FragCoord.z;\n"
"}\n";
const float cubeVertexData[][5] = {{0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f ,0.0f, 1.0f},
{1.0f, 1.0f, 0.0f, 1.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 0.0f, 0.0f},
{1.0f, 0.0f, -1.0f, 1.0f, 0.0f},
{1.0f, 1.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 1.0f, -1.0f, 1.0f, 1.0f},
{1.0f, 0.0f, -1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, -1.0f, 1.0f, 0.0f},
{1.0f, 1.0f, -1.0f, 0.0f, 1.0f},
{0.0f, 1.0f, -1.0f, 1.0f, 1.0f},
{0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, -1.0f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, -1.0f, 1.0f, 0.0f},
{0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, 1.0f, 1.0f},
{0.0f, 1.0f, 0.0f, 0.0f, 0.0f},
{1.0f, 1.0f, 0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, -1.0f, 0.0f, 1.0f},
{1.0f, 1.0f, -1.0f, 1.0f, 1.0f}};
const uint8_t cubeIndices[] = {0, 1, 2,
1, 2, 3,
4, 5, 6,
5, 6, 7,
8, 9, 10,
9, 10, 11,
12, 13, 14,
13, 14, 15,
16, 17, 18,
17, 18, 19,
20, 21, 22,
21, 22, 23};
const float vertices[][3] = {{0.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f},
@@ -66,6 +97,21 @@ const float colors[][3] = {{1.0f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f},
{1.0f, 0.0f, 0.0f}};
const float texcoords[][2] = {{0.0f, 0.0f},
{1.0f, 0.0f},
{0.0f, 1.0f},
{1.0f, 1.0f},
{1.0f, 1.0f},
{1.0f, 0.0f},
{0.0f, 1.0f},
{0.0f, 0.0f},
{0.0f, 0.0f},
{0.0f, 0.0f},
{0.0f, 0.0f},
{0.0f, 0.0f}};
const unsigned indices[] = {0, 2, 1,
2, 3, 1,
@@ -90,236 +136,20 @@ const unsigned indicesPyramid[] = {8, 10, 9,
8, 9, 11,
9, 10, 11};
class GLException{
public:
GLException(GLenum err) : _err(err) {
}
virtual ~GLException() {}
int getErr() const {return _err;}
std::string errToString() const {
std::string ret;
if (_err == GL_INVALID_ENUM)
ret += "GL_INVALID_ENUM ";
if (_err == GL_INVALID_VALUE)
ret += "GL_INVALID_VALUE ";
if (_err == GL_INVALID_OPERATION)
ret += "GL_INVALID_OPERATION ";
if (_err == GL_INVALID_FRAMEBUFFER_OPERATION)
ret += "GL_INVALID_FRAMEBUFFER_OPERATION ";
if (_err == GL_OUT_OF_MEMORY)
ret += "GL_OUT_OF_MEMORY ";
if (_err == GL_STACK_UNDERFLOW)
ret += "GL_STACK_UNDERFLOW ";
if (_err == GL_STACK_OVERFLOW)
ret += "GL_STACK_OVERFLOW ";
return ret;
}
virtual std::string toString() const {
return "GLException: " + errToString() + "(" + std::to_string(_err) + ")";
}
private:
GLenum _err;
};
class ShaderException : public GLException {
public:
ShaderException(std::string const& msg) : GLException(glGetError()), _msg(msg) {
}
virtual ~ShaderException() {}
std::string const& getMsg() const {return _msg;}
virtual std::string toString() const {
return "ShaderException: " + _msg;
}
private:
std::string _msg;
};
class Program;
class Shader {
public:
Shader() : _shaderID(0) {
}
Shader(std::string const& program, GLenum type) {
_shaderID = glCreateShader(type);
const char* const arr[] = {program.c_str()};
glShaderSource(_shaderID, 1, arr, NULL);
glCompileShader(_shaderID);
int state;
glGetShaderiv(_shaderID, GL_COMPILE_STATUS, &state);
if (!state) {
int logLength;
glGetShaderiv(_shaderID, GL_INFO_LOG_LENGTH, &logLength);
char *log = new char[logLength];
glGetShaderInfoLog(_shaderID, logLength, NULL, log);
std::string msg(log);
delete[] log;
glDeleteShader(_shaderID);
throw ShaderException(msg);
}
}
virtual ~Shader() {
glDeleteShader(_shaderID);
}
protected:
unsigned getID() const {
return _shaderID;
}
friend class Program;
unsigned int _shaderID;
};
class VertexShader : public Shader {
public:
VertexShader(std::string const& program) : Shader(program, GL_VERTEX_SHADER) {
}
virtual ~VertexShader() {
}
};
class FragmentShader : public Shader {
public:
FragmentShader(std::string const& program) : Shader(program, GL_FRAGMENT_SHADER) {
}
virtual ~FragmentShader() {
}
};
class GeometryShader : public Shader {
public:
GeometryShader(std::string const& program) : Shader(program, GL_GEOMETRY_SHADER) {
}
virtual ~GeometryShader() {
}
};
class Program {
public:
Program(VertexShader& vertex, FragmentShader& frag) : _geom(nullptr), _vertex(vertex), _frag(frag) {
_progID = glCreateProgram();
glAttachShader(_progID, _vertex.getID());
glAttachShader(_progID, _frag.getID());
glLinkProgram(_progID);
int state;
glGetProgramiv(_progID, GL_LINK_STATUS, &state);
if (!state) {
int logLength;
glGetProgramiv(_progID, GL_INFO_LOG_LENGTH, &logLength);
char *log = new char[logLength];
glGetProgramInfoLog(_progID, logLength, NULL, log);
std::string msg(log);
delete[] log;
glDeleteProgram(_progID);
throw ShaderException(msg);
}
glDetachShader(_progID, _vertex.getID());
glDetachShader(_progID, _frag.getID());
}
Program(GeometryShader& geom, VertexShader& vertex, FragmentShader& frag) : _geom(&geom), _vertex(vertex), _frag(frag) {
_progID = glCreateProgram();
glAttachShader(_progID, _geom->getID());
glAttachShader(_progID, _vertex.getID());
glAttachShader(_progID, _frag.getID());
glLinkProgram(_progID);
int state;
glGetProgramiv(_progID, GL_LINK_STATUS, &state);
if (!state) {
int logLength;
glGetProgramiv(_progID, GL_INFO_LOG_LENGTH, &logLength);
char *log = new char[logLength];
glGetProgramInfoLog(_progID, logLength, NULL, log);
std::string msg(log);
delete[] log;
glDeleteProgram(_progID);
throw ShaderException(msg);
}
glDetachShader(_progID, _geom->getID());
glDetachShader(_progID, _vertex.getID());
glDetachShader(_progID, _frag.getID());
}
~Program() {
glDeleteProgram(_progID);
}
void use() const {
glUseProgram(_progID);
}
int getUniformLocation(std::string const& name) const {
int ret = glGetUniformLocation(_progID, name.c_str());
if (ret == -1)
throw GLException(glGetError());
return ret;
}
int getAttribLocation(std::string const& name) const {
int ret = glGetAttribLocation(_progID, name.c_str());
if (ret == -1)
throw GLException(glGetError());
return ret;
}
private:
GeometryShader* _geom;
VertexShader& _vertex;
FragmentShader& _frag;
unsigned _progID;
};
void checkGlError() {
GLenum err;
if ((err = glGetError()) != GL_NO_ERROR)
throw GLException(err);
}
int main(int argc, char *argv[])
{
SDL_Window *window;
int retcode = 0;
SDL_Init(SDL_INIT_VIDEO);
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::printf("Could not init SDL: %s\n", SDL_GetError());
return 1;
}
if (IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG) == 0) {
std::printf("Could not init SDL_image: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
@@ -327,7 +157,7 @@ int main(int argc, char *argv[])
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
//SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
@@ -337,7 +167,7 @@ int main(int argc, char *argv[])
SDL_WINDOWPOS_UNDEFINED,
640,
480,
/*SDL_WINDOW_FULLSCREEN_DESKTOP |*/ SDL_WINDOW_OPENGL);
SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_OPENGL);
if (!window) {
std::printf("Could not create window: %s\n", SDL_GetError());
@@ -374,9 +204,7 @@ int main(int argc, char *argv[])
0.1f, 100.0f);
glm::mat4 view = glm::lookAt(glm::vec3(0, 0, 10),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0));
// glm::mat4 model = glm::rotate(0.0f, glm::vec3(1.0f, 0.0f, 0.0f));
glm::vec3(0, 1, 0));
// sf::Font font;
// if (!font.loadFromFile("DejaVuSans.ttf")) {
// std::printf("Error loading font\n");
@@ -391,16 +219,29 @@ int main(int argc, char *argv[])
// sf::Clock clock;
// sf::Time last = clock.getElapsedTime();
checkGlError();
Texture2D cubeTex("textures/Wood_Box_Texture.jpg");
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
if (SDL_GL_ExtensionSupported("GL_EXT_texture_filter_anisotropic"))
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 4.0f);
else
std::printf("Warning: extension GL_EXT_texture_filter_anisotropic not supported\n");
auto box = readObject("objects/woodbox.obj");
VertexShader vs{vertexShader};
FragmentShader fs{fragShader};
VertexShader vs{fileToString("shaders/textured.vs")};
FragmentShader fs{fileToString("shaders/textured.fs")};
Program prog(vs, fs);
checkGlError();
prog.use();
glUniformMatrix4fv(prog.getUniformLocation("projection_matrix"), 1, GL_FALSE,
glm::value_ptr(proj));
glUniform1i(prog.getUniformLocation("texBase"), 0);
int vertexAL = prog.getAttribLocation("vertex");
//int vertexColorAL = prog.getAttribLocation("vertexColor");
int vertexTCAL = prog.getAttribLocation("vertexTC");
checkGlError();
GLuint buf;
@@ -408,13 +249,35 @@ int main(int argc, char *argv[])
glBindBuffer(GL_ARRAY_BUFFER, buf);
checkGlError();
glBufferData(GL_ARRAY_BUFFER, 2*sizeof(float)*3*12, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*12, (void*)vertices[0]);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(float)*3*12, sizeof(float)*3*12, (void*)colors[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*24*5, NULL, GL_STATIC_DRAW);
//glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*24*5, (void*)cubeVertexData[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(objVertexAttribs)*std::get<0>(box).size(),
(void*)std::get<0>(box).data());
GLuint arr;
glGenVertexArrays(1, &arr);
glBindVertexArray(arr);
// glBufferData(GL_ARRAY_BUFFER, sizeof(float)*(2*3*12+2*12), NULL, GL_STATIC_DRAW);
// glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*12, (void*)vertices[0]);
// glBufferSubData(GL_ARRAY_BUFFER, sizeof(float)*3*12, sizeof(float)*3*12, (void*)colors[0]);
// glBufferSubData(GL_ARRAY_BUFFER, sizeof(float)*2*3*12, sizeof(float)*2*12, (void*)texcoords[0]);
GLuint arr[2];
glGenVertexArrays(2, arr);
checkGlError();
// glBindVertexArray(arr[0]);
// glEnableVertexAttribArray(vertexAL);
// glEnableVertexAttribArray(vertexColorAL);
// glEnableVertexAttribArray(vertexTCAL);
// glVertexAttribPointer(vertexAL, 3, GL_FLOAT, GL_FALSE, 0, 0);
// glVertexAttribPointer(vertexColorAL, 3, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(float)*3*12));
// glVertexAttribPointer(vertexTCAL, 2, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(float)*2*3*12));
glBindVertexArray(arr[0]);
glEnableVertexAttribArray(vertexAL);
glEnableVertexAttribArray(vertexTCAL);
glVertexAttribPointer(vertexAL, 3, GL_FLOAT, GL_FALSE, sizeof(objVertexAttribs), offsetof(objVertexAttribs, vertex));
glVertexAttribPointer(vertexTCAL, 2, GL_UNSIGNED_SHORT, GL_TRUE, sizeof(objVertexAttribs),
(void*)offsetof(objVertexAttribs, texCoords));
checkGlError();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -440,26 +303,19 @@ int main(int argc, char *argv[])
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
checkGlError();
prog.use();
glm::mat4 model = glm::rotate(SDL_GetTicks()*0.001f, glm::vec3(1.0f, 0.0f, 0.0f));
glUniformMatrix4fv(prog.getUniformLocation("modelview_matrix"), 1, GL_FALSE,
glm::value_ptr(view*model));
// glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, indices);
glDrawElements(GL_TRIANGLES, std::get<1>(box).size(), GL_UNSIGNED_SHORT, std::get<1>(box).data());
checkGlError();
glEnableVertexAttribArray(prog.getAttribLocation("vertex"));
glEnableVertexAttribArray(prog.getAttribLocation("vertexColor"));
checkGlError();
glVertexAttribPointer(prog.getAttribLocation("vertex"), 3, GL_FLOAT, GL_FALSE, 0, 0);
checkGlError();
glVertexAttribPointer(prog.getAttribLocation("vertexColor"), 3, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(float)*3*12));
checkGlError();
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, indices);
checkGlError();
glUniformMatrix4fv(prog.getUniformLocation("modelview_matrix"), 1, GL_FALSE,
glm::value_ptr(view));
checkGlError();
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, indicesPyramid);
checkGlError();
// glUniformMatrix4fv(prog.getUniformLocation("modelview_matrix"), 1, GL_FALSE,
// glm::value_ptr(view));
// glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, indicesPyramid);
// checkGlError();
// glUseProgram(0);
// sf::Time now = clock.getElapsedTime();
@@ -471,7 +327,7 @@ int main(int argc, char *argv[])
SDL_GL_SwapWindow(window);
}
}catch(GLException &ex) {
}catch(Exception &ex) {
std::printf("%s\n", ex.toString().c_str());
retcode = 1;
}