Texturing; OBJ loader
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
||||
objs/
|
||||
oglpg
|
||||
*.trace
|
||||
*~
|
||||
|
||||
6
Makefile
6
Makefile
@@ -1,8 +1,8 @@
|
||||
CXX=g++
|
||||
CXXOPTS=-Og -ggdb -Wall -Wextra -pedantic -std=c++11
|
||||
CXXOPTS=-Og -ggdb -Wall -Wextra -pedantic -Wno-unused-function -Wno-unused-parameter -std=c++11
|
||||
LDOPTS=-flto
|
||||
LIBS=-lGL -lSDL2
|
||||
CXXSRCS=main.cc
|
||||
LIBS=-lGL -lSDL2 -lSDL2_image -lobj
|
||||
CXXSRCS=main.cc objectParser.cc
|
||||
OBJS=$(addprefix objs/,$(CXXSRCS:.cc=.o))
|
||||
|
||||
objs/%.o: %.cc
|
||||
|
||||
121
common.hh
Normal file
121
common.hh
Normal file
@@ -0,0 +1,121 @@
|
||||
#ifndef __OPENGLPLAYGROUND_COMMON_HH__
|
||||
#define __OPENGLPLAYGROUND_COMMON_HH__
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
class Exception {
|
||||
public:
|
||||
Exception() {
|
||||
}
|
||||
|
||||
virtual ~Exception() {}
|
||||
|
||||
virtual std::string toString() const = 0;
|
||||
};
|
||||
|
||||
class POSIXException : public Exception {
|
||||
public:
|
||||
POSIXException(int err): Exception(), _err(err) {
|
||||
}
|
||||
|
||||
virtual ~POSIXException() {}
|
||||
|
||||
int getErr() const {return _err;}
|
||||
|
||||
virtual std::string toString() const {
|
||||
return std::string("POSIXException: ") + std::strerror(_err);
|
||||
}
|
||||
|
||||
private:
|
||||
int _err;
|
||||
};
|
||||
|
||||
class GLException : public Exception {
|
||||
public:
|
||||
GLException(GLenum err) : Exception(), _err(err) {
|
||||
}
|
||||
|
||||
virtual ~GLException() {}
|
||||
|
||||
GLenum 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 SDLException : public Exception {
|
||||
public:
|
||||
SDLException() : Exception(), _msg(SDL_GetError()) {
|
||||
}
|
||||
|
||||
virtual ~SDLException() {}
|
||||
|
||||
virtual std::string toString() const {
|
||||
return "SDLException: " + _msg;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _msg;
|
||||
};
|
||||
|
||||
static void checkGlError() {
|
||||
GLenum err;
|
||||
if ((err = glGetError()) != GL_NO_ERROR)
|
||||
throw GLException(err);
|
||||
}
|
||||
|
||||
static std::string fileToString(std::string const& name) {
|
||||
std::FILE *file = std::fopen(name.c_str(), "r");
|
||||
if (!file) {
|
||||
throw POSIXException(errno);
|
||||
}
|
||||
|
||||
std::string ret;
|
||||
char buf[512];
|
||||
std::size_t p;
|
||||
while((p = std::fread(buf, 1, 511, file)) > 0) {
|
||||
buf[p] = '\0';
|
||||
ret.append(buf);
|
||||
}
|
||||
if (!std::feof(file)) {
|
||||
std::fclose(file);
|
||||
throw POSIXException(errno);
|
||||
}
|
||||
|
||||
std::fclose(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
412
main.cc
412
main.cc
@@ -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;
|
||||
}
|
||||
|
||||
281
objectParser.cc
Normal file
281
objectParser.cc
Normal file
@@ -0,0 +1,281 @@
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <map>
|
||||
#include <tr1/functional>
|
||||
#include <obj.hpp>
|
||||
|
||||
#include "objectParser.hh"
|
||||
|
||||
using namespace obj;
|
||||
|
||||
using std::tr1::placeholders::_1;
|
||||
using std::tr1::placeholders::_2;
|
||||
using std::tr1::placeholders::_3;
|
||||
using std::tr1::placeholders::_4;
|
||||
|
||||
|
||||
class ObjectParser {
|
||||
private:
|
||||
void texture_vertex_callback(obj::float_type u, obj::float_type v)
|
||||
{
|
||||
if ((u > 1.0f) || (u < 0.0f))
|
||||
std::cout << "Warning: Clamping texture coordinate U to [0.0, 1.0]" << std::endl;
|
||||
uint16_t c_u = static_cast<uint16_t>(fminf(1.0f, fmaxf(0.0f, u))*65535.0);
|
||||
if ((v > 1.0f) || (v < 0.0f))
|
||||
std::cout << "Warning: Clamping texture coordinate V to [0.0, 1.0]" << std::endl;
|
||||
uint16_t c_v = static_cast<uint16_t>(fminf(1.0f, fmaxf(0.0f, v))*65535.0);
|
||||
_texCoords.emplace_back(c_u, c_v);
|
||||
std::cout << "vt " << c_u << " " << c_v << "\n";
|
||||
}
|
||||
|
||||
void geometric_vertex_callback(obj::float_type x, obj::float_type y, obj::float_type z)
|
||||
{
|
||||
_vertices.emplace_back(x, y, z);
|
||||
std::cout << "v " << x << " " << y << " " << z << "\n";
|
||||
}
|
||||
|
||||
void vertex_normal_callback(obj::float_type x, obj::float_type y, obj::float_type z)
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
signed :2;
|
||||
signed z:10;
|
||||
signed y:10;
|
||||
signed x:10;
|
||||
} bits;
|
||||
uint32_t all;
|
||||
} pack_10;
|
||||
if ((x > 1.0f) || (x < -1.0f))
|
||||
std::cout << "Warning: Clamping normal X to [-1.0, 1.0]" << std::endl;
|
||||
pack_10.bits.x = static_cast<int>(fminf(1.0f, fmaxf(-1.0f, x))*511.0);
|
||||
if ((y > 1.0f) || (y < -1.0f))
|
||||
std::cout << "Warning: Clamping normal Y to [-1.0, 1.0]" << std::endl;
|
||||
pack_10.bits.y = static_cast<int>(fminf(1.0f, fmaxf(-1.0f, y))*511.0);
|
||||
if ((z > 1.0f) || (z < -1.0f))
|
||||
std::cout << "Warning: Clamping normal Z to [-1.0, 1.0]" << std::endl;
|
||||
pack_10.bits.z = static_cast<int>(fminf(1.0f, fmaxf(-1.0f, z))*511.0);
|
||||
_normals.push_back(pack_10.all);
|
||||
std::cout << "vn " << pack_10.bits.x << " " << pack_10.bits.y << " " << pack_10.bits.z << "\n";
|
||||
}
|
||||
|
||||
void triangular_face_geometric_vertices_callback(index_type a, index_type b, index_type c)
|
||||
{
|
||||
}
|
||||
|
||||
size_t _find_vertex_tc_pair(index_2_tuple_type const& a)
|
||||
{
|
||||
auto pair_it = _vertex_tc_pairs_map.find(std::tuple<std::size_t, std::size_t>(std::tr1::get<0>(a), std::tr1::get<1>(a)));
|
||||
size_t pair_pos;
|
||||
if (pair_it != _vertex_tc_pairs_map.end())
|
||||
pair_pos = pair_it->second;
|
||||
else {
|
||||
_vertex_tc_pairs.emplace_back(std::get<0>(_vertices[std::tr1::get<0>(a)-1]),
|
||||
std::get<1>(_vertices[std::tr1::get<0>(a)-1]),
|
||||
std::get<2>(_vertices[std::tr1::get<0>(a)-1]),
|
||||
std::get<0>(_texCoords[std::tr1::get<1>(a)-1]),
|
||||
std::get<1>(_texCoords[std::tr1::get<1>(a)-1]));
|
||||
pair_pos = _vertex_tc_pairs.size()-1;
|
||||
_vertex_tc_pairs_map.emplace(std::tuple<std::size_t, std::size_t>(std::tr1::get<0>(a), std::tr1::get<1>(a)),
|
||||
pair_pos);
|
||||
}
|
||||
return pair_pos;
|
||||
}
|
||||
|
||||
void triangular_face_geometric_vertices_texture_vertices_callback(index_2_tuple_type a, index_2_tuple_type b, index_2_tuple_type c)
|
||||
{
|
||||
if ((_vertices.size() < std::tr1::get<0>(a)) ||
|
||||
(_vertices.size() < std::tr1::get<0>(b)) ||
|
||||
(_vertices.size() < std::tr1::get<0>(c)))
|
||||
throw ParseException("Vertex Index out of range");
|
||||
if ((_texCoords.size() < std::tr1::get<1>(a)) ||
|
||||
(_texCoords.size() < std::tr1::get<1>(b)) ||
|
||||
(_texCoords.size() < std::tr1::get<1>(c)))
|
||||
throw ParseException("Texture Coordinate Index out of range");
|
||||
|
||||
std::cout << "f (" << std::tr1::get<0>(a) << ", " << std::tr1::get<1>(a) << ")" <<
|
||||
" (" << std::tr1::get<0>(b) << ", " << std::tr1::get<1>(b) << ")" <<
|
||||
" (" << std::tr1::get<0>(c) << ", " << std::tr1::get<1>(c) << ")\n";
|
||||
|
||||
size_t a_pos = _find_vertex_tc_pair(a);
|
||||
size_t b_pos = _find_vertex_tc_pair(b);
|
||||
size_t c_pos = _find_vertex_tc_pair(c);
|
||||
_faces.emplace_back(a_pos, b_pos, c_pos);
|
||||
|
||||
std::cout << "\t [" << a_pos << ", " << b_pos << ", " << c_pos << "]\n";
|
||||
}
|
||||
|
||||
void triangular_face_geometric_vertices_vertex_normals_callback(index_2_tuple_type a, index_2_tuple_type b, index_2_tuple_type c)
|
||||
{
|
||||
}
|
||||
|
||||
void triangular_face_geometric_vertices_texture_vertices_vertex_normals_callback(index_3_tuple_type a, index_3_tuple_type b,
|
||||
index_3_tuple_type c)
|
||||
{
|
||||
}
|
||||
|
||||
void quadrilateral_face_geometric_vertices_callback(index_type a, index_type b, index_type c, index_type d)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void quadrilateral_face_geometric_vertices_texture_vertices_callback(index_2_tuple_type a, index_2_tuple_type b,
|
||||
index_2_tuple_type c, index_2_tuple_type d)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void quadrilateral_face_geometric_vertices_vertex_normals_callback(index_2_tuple_type a, index_2_tuple_type b,
|
||||
index_2_tuple_type c, index_2_tuple_type d)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void quadrilateral_face_geometric_vertices_texture_vertices_vertex_normals_callback(index_3_tuple_type a, index_3_tuple_type b,
|
||||
index_3_tuple_type c, index_3_tuple_type d)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_begin_callback(index_type a, index_type b, index_type c)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_vertex_callback(index_type a)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_end_callback()
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_texture_vertices_begin_callback(index_2_tuple_type a, index_2_tuple_type b,
|
||||
index_2_tuple_type c)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_texture_vertices_vertex_callback(index_2_tuple_type a)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_texture_vertices_end_callback()
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_vertex_normals_begin_callback(index_2_tuple_type a, index_2_tuple_type b,
|
||||
index_2_tuple_type c)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_vertex_normals_vertex_callback(index_2_tuple_type a)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_vertex_normals_end_callback()
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_texture_vertices_vertex_normals_begin_callback(index_3_tuple_type a, index_3_tuple_type b,
|
||||
index_3_tuple_type c)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_texture_vertices_vertex_normals_vertex_callback(index_3_tuple_type a)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void polygonal_face_geometric_vertices_texture_vertices_vertex_normals_end_callback()
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
std::vector<std::tuple<float, float, float> > _vertices;
|
||||
std::vector<std::tuple<uint16_t, uint16_t> > _texCoords;
|
||||
std::vector<uint32_t> _normals;
|
||||
|
||||
std::map<std::tuple<std::size_t, std::size_t>, std::size_t > _vertex_tc_pairs_map;
|
||||
std::vector<std::tuple<float, float, float, uint16_t, uint16_t> > _vertex_tc_pairs;
|
||||
std::vector<std::tuple<std::size_t, std::size_t, std::size_t> > _faces;
|
||||
|
||||
public:
|
||||
ObjectParser() {
|
||||
}
|
||||
|
||||
~ObjectParser() {
|
||||
}
|
||||
|
||||
void parse(std::string const& filename)
|
||||
{
|
||||
obj::obj_parser obj_parser(obj::obj_parser::triangulate_faces | obj::obj_parser::translate_negative_indices);
|
||||
obj_parser.geometric_vertex_callback(std::tr1::bind(&ObjectParser::geometric_vertex_callback, this, _1, _2, _3));
|
||||
obj_parser.texture_vertex_callback(std::tr1::bind(&ObjectParser::texture_vertex_callback, this, _1, _2));
|
||||
obj_parser.vertex_normal_callback(std::tr1::bind(&ObjectParser::vertex_normal_callback, this, _1, _2, _3));
|
||||
obj_parser.face_callbacks
|
||||
(std::tr1::bind(&ObjectParser::triangular_face_geometric_vertices_callback, this, _1, _2, _3),
|
||||
std::tr1::bind(&ObjectParser::triangular_face_geometric_vertices_texture_vertices_callback, this, _1, _2, _3),
|
||||
std::tr1::bind(&ObjectParser::triangular_face_geometric_vertices_vertex_normals_callback, this, _1, _2, _3),
|
||||
std::tr1::bind(&ObjectParser::triangular_face_geometric_vertices_texture_vertices_vertex_normals_callback, this, _1, _2, _3),
|
||||
std::tr1::bind(&ObjectParser::quadrilateral_face_geometric_vertices_callback, this, _1, _2, _3, _4),
|
||||
std::tr1::bind(&ObjectParser::quadrilateral_face_geometric_vertices_texture_vertices_callback, this, _1, _2, _3, _4),
|
||||
std::tr1::bind(&ObjectParser::quadrilateral_face_geometric_vertices_vertex_normals_callback, this, _1, _2, _3, _4),
|
||||
std::tr1::bind(&ObjectParser::quadrilateral_face_geometric_vertices_texture_vertices_vertex_normals_callback, this, _1, _2, _3, _4),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_begin_callback, this, _1, _2, _3),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_vertex_callback, this, _1),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_end_callback, this),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_begin_callback, this, _1, _2, _3),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_vertex_callback, this, _1),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_end_callback, this),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_vertex_normals_begin_callback, this, _1, _2, _3),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_vertex_normals_vertex_callback, this, _1),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_vertex_normals_end_callback, this),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_vertex_normals_begin_callback, this, _1, _2, _3),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_vertex_normals_vertex_callback, this, _1),
|
||||
std::tr1::bind(&ObjectParser::polygonal_face_geometric_vertices_texture_vertices_vertex_normals_end_callback, this));
|
||||
obj_parser.parse(filename);
|
||||
}
|
||||
|
||||
std::vector<objVertexAttribs> buildVA()
|
||||
{
|
||||
std::vector<objVertexAttribs> ret;
|
||||
for (auto const& ent : _vertex_tc_pairs) {
|
||||
objVertexAttribs tmp;
|
||||
tmp.vertex[0] = std::get<0>(ent);
|
||||
tmp.vertex[1] = std::get<1>(ent);
|
||||
tmp.vertex[2] = std::get<2>(ent);
|
||||
tmp.texCoords[0] = std::get<3>(ent);
|
||||
tmp.texCoords[1] = std::get<4>(ent);
|
||||
ret.push_back(tmp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<uint16_t> buildIndices() const
|
||||
{
|
||||
std::vector<uint16_t> ret;
|
||||
for (auto const& ent : _faces) {
|
||||
ret.push_back(std::get<0>(ent));
|
||||
ret.push_back(std::get<1>(ent));
|
||||
ret.push_back(std::get<2>(ent));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
std::tuple<std::vector<objVertexAttribs>, std::vector<uint16_t> > readObject(std::string const& filename)
|
||||
{
|
||||
ObjectParser parser;
|
||||
parser.parse(filename);
|
||||
return std::tuple<std::vector<objVertexAttribs>, std::vector<uint16_t> >(parser.buildVA(), parser.buildIndices());
|
||||
}
|
||||
34
objectParser.hh
Normal file
34
objectParser.hh
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef __OPENGLPLAYGROUND_OBJECTPARSER_HH__
|
||||
#define __OPENGLPLAYGROUND_OBJECTPARSER_HH__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common.hh"
|
||||
|
||||
class ParseException : public Exception {
|
||||
public:
|
||||
ParseException(std::string const& msg) : Exception(), _msg(msg) {
|
||||
}
|
||||
|
||||
virtual ~ParseException() {}
|
||||
|
||||
std::string const& getMsg() const {return _msg;}
|
||||
|
||||
virtual std::string toString() const {
|
||||
return "ParseException: " + _msg;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _msg;
|
||||
};
|
||||
|
||||
struct objVertexAttribs {
|
||||
float vertex[3];
|
||||
uint16_t texCoords[2];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
||||
std::tuple<std::vector<objVertexAttribs>, std::vector<uint16_t> > readObject(std::string const& filename);
|
||||
|
||||
#endif
|
||||
33
objects/woodbox.obj
Normal file
33
objects/woodbox.obj
Normal file
@@ -0,0 +1,33 @@
|
||||
v 0.0 0.0 0.0
|
||||
v 1.0 0.0 0.0
|
||||
v 0.0 1.0 0.0
|
||||
v 1.0 1.0 0.0
|
||||
|
||||
v 0.0 0.0 -1.0
|
||||
v 1.0 0.0 -1.0
|
||||
v 0.0 1.0 -1.0
|
||||
v 1.0 1.0 -1.0
|
||||
|
||||
vt 0.0 0.0
|
||||
vt 1.0 0.0
|
||||
vt 0.0 1.0
|
||||
vt 1.0 1.0
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 1.0 0.0 0.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn -1.0 0.0 0.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
|
||||
f 1/1 3/3 4/4 2/2
|
||||
|
||||
f 2/1 4/3 8/4 6/2
|
||||
|
||||
f 6/1 8/3 7/4 5/2
|
||||
|
||||
f 5/1 7/3 3/4 1/2
|
||||
|
||||
f 5/1 1/3 2/4 6/2
|
||||
|
||||
f 3/1 7/3 8/4 4/2
|
||||
205
shaders.hh
Normal file
205
shaders.hh
Normal file
@@ -0,0 +1,205 @@
|
||||
#ifndef __OPENGLPLAYGROUND_SHADERS_HH__
|
||||
#define __OPENGLPLAYGROUND_SHADERS_HH__
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "common.hh"
|
||||
|
||||
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 {
|
||||
auto search = _uniformLocCache.find(name);
|
||||
if (search != _uniformLocCache.end())
|
||||
return search->second;
|
||||
|
||||
int ret = glGetUniformLocation(_progID, name.c_str());
|
||||
if (ret == -1)
|
||||
throw GLException(glGetError());
|
||||
_uniformLocCache.emplace(name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int getAttribLocation(std::string const& name) const {
|
||||
auto search = _attribLocCache.find(name);
|
||||
if (search != _attribLocCache.end())
|
||||
return search->second;
|
||||
|
||||
int ret = glGetAttribLocation(_progID, name.c_str());
|
||||
if (ret == -1)
|
||||
throw GLException(glGetError());
|
||||
_attribLocCache.emplace(name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
GeometryShader* _geom;
|
||||
VertexShader& _vertex;
|
||||
FragmentShader& _frag;
|
||||
unsigned _progID;
|
||||
|
||||
mutable std::unordered_map<std::string, GLint> _uniformLocCache, _attribLocCache;
|
||||
};
|
||||
|
||||
#endif
|
||||
9
shaders/color.fs
Normal file
9
shaders/color.fs
Normal file
@@ -0,0 +1,9 @@
|
||||
#version 330 core
|
||||
|
||||
in vec3 fragColor;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
void main(void) {
|
||||
color = vec4(fragColor, 1.0);
|
||||
}
|
||||
14
shaders/color.vs
Normal file
14
shaders/color.vs
Normal file
@@ -0,0 +1,14 @@
|
||||
#version 330 core
|
||||
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat4 modelview_matrix;
|
||||
|
||||
in vec3 vertex;
|
||||
in vec3 vertecColor;
|
||||
|
||||
out vec3 fragColor;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = projection_matrix * modelview_matrix * vec4(vertex, 1.0);
|
||||
fragColor = vertexColor;
|
||||
}
|
||||
11
shaders/textured.fs
Normal file
11
shaders/textured.fs
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
|
||||
uniform sampler2D texBase;
|
||||
|
||||
in vec2 fragTC;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
void main(void) {
|
||||
color = texture(texBase, fragTC);
|
||||
}
|
||||
14
shaders/textured.vs
Normal file
14
shaders/textured.vs
Normal file
@@ -0,0 +1,14 @@
|
||||
#version 330 core
|
||||
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat4 modelview_matrix;
|
||||
|
||||
in vec3 vertex;
|
||||
in vec2 vertexTC;
|
||||
|
||||
out vec2 fragTC;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = projection_matrix * modelview_matrix * vec4(vertex, 1.0);
|
||||
fragTC = vertexTC;
|
||||
}
|
||||
95
texture.hh
Normal file
95
texture.hh
Normal file
@@ -0,0 +1,95 @@
|
||||
#ifndef __OPENGLPLAYGROUND_TEXTURE_HH__
|
||||
#define __OPENGLPLAYGROUND_TEXTURE_HH__
|
||||
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "common.hh"
|
||||
|
||||
static unsigned ilog2(unsigned in)
|
||||
{
|
||||
unsigned ret = 0u;
|
||||
while (in >>= 1) ++ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
class Texture2D {
|
||||
public:
|
||||
Texture2D(unsigned width, unsigned height) {
|
||||
_glCreate(width, height);
|
||||
}
|
||||
|
||||
Texture2D(std::string const& file) {
|
||||
SDL_Surface *surf = IMG_Load(file.c_str());
|
||||
if (!surf)
|
||||
throw SDLException();
|
||||
|
||||
try {
|
||||
_glCreate(surf->w, surf->h);
|
||||
try {
|
||||
assert(surf->format->format == SDL_PIXELFORMAT_RGB24); // TODO: Proper support of many formats
|
||||
if (SDL_MUSTLOCK(surf))
|
||||
SDL_LockSurface(surf);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGB, GL_UNSIGNED_BYTE, surf->pixels);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
checkGlError();
|
||||
} catch(...) {
|
||||
glDeleteTextures(1, &_texID);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
SDL_FreeSurface(surf);
|
||||
throw;
|
||||
}
|
||||
SDL_FreeSurface(surf);
|
||||
}
|
||||
|
||||
~Texture2D() {
|
||||
glDeleteTextures(1, &_texID);
|
||||
}
|
||||
|
||||
void bind() {
|
||||
glBindTexture(GL_TEXTURE_2D, _texID);
|
||||
checkGlError();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void _glCreate(unsigned width, unsigned height) {
|
||||
glGenTextures(1, &_texID);
|
||||
checkGlError();
|
||||
try {
|
||||
glBindTexture(GL_TEXTURE_2D, _texID);
|
||||
unsigned logWidth = ilog2(width), logHeight = ilog2(height);
|
||||
unsigned levels = std::max(logWidth,logHeight)+1u;
|
||||
if(SDL_GL_ExtensionSupported("GL_ARB_texture_storage"))
|
||||
glTexStorage2D(GL_TEXTURE_2D, levels, GL_RGB8, width, height);
|
||||
else {
|
||||
std::printf("Warning: extension GL_ARB_texture_storage not supported!\n");
|
||||
for (unsigned i = 0u; i < levels; ++i)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, i, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
width = std::max(1u, (width / 2u));
|
||||
height = std::max(1u, (height / 2u));
|
||||
}
|
||||
}
|
||||
checkGlError();
|
||||
} catch(...) {
|
||||
glDeleteTextures(1, &_texID);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint _texID;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
BIN
textures/Wood_Box_Texture.jpg
Normal file
BIN
textures/Wood_Box_Texture.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 206 KiB |
BIN
textures/Wood_Box_Texture_NRM.png
Normal file
BIN
textures/Wood_Box_Texture_NRM.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 306 KiB |
Reference in New Issue
Block a user