Initial import

This commit is contained in:
2014-11-14 14:16:52 +01:00
commit 0be3e0a50e
3 changed files with 509 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
objs/
oglpg

20
Makefile Normal file
View File

@@ -0,0 +1,20 @@
CXX=g++
CXXOPTS=-Og -ggdb -Wall -Wextra -pedantic -std=c++11
LDOPTS=-flto
LIBS=-lGL -lSDL2
CXXSRCS=main.cc
OBJS=$(addprefix objs/,$(CXXSRCS:.cc=.o))
objs/%.o: %.cc
$(CXX) $(CXXOPTS) -c -MMD -MP -o $@ $<
@cp objs/$*.d objs/$*.P; rm -f objs/$*.d
oglpg: $(OBJS)
$(CXX) $(CXXOPTS) $(LDOPTS) -o $@ $(OBJS) $(LIBS)
clean:
rm -f oglpg $(OBJS) $(addprefix objs/,$(CXXSRCS:.cc=.P))
.PHONY: clean
-include $(addprefix objs/,$(CXXSRCS:.cc=.P))

487
main.cc Normal file
View File

@@ -0,0 +1,487 @@
#include <cstdio>
#include <cmath>
#include <string>
#include <SDL2/SDL.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
//#include <GL/glext.h>
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#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";
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 vertices[][3] = {{0.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{1.0f, 1.0f, 0.0f},
{0.0f, 0.0f, -1.0f},
{1.0f, 0.0f, -1.0f},
{0.0f, 1.0f, -1.0f},
{1.0f, 1.0f, -1.0f},
{-1.0f, -2.0f, -5.0f},
{-1.5f, -1.0f, -4.5f},
{-0.5f, -1.0f, -4.5f},
{-1.0f, -1.0f, -5.5f}};
const float colors[][3] = {{1.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, 1.0f},
{1.0f, 0.0f, 1.0f},
{1.0f, 1.0f, 1.0f},
{0.0f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f},
{1.0f, 0.0f, 0.0f}};
const unsigned indices[] = {0, 2, 1,
2, 3, 1,
0, 4, 1,
1, 4, 5,
1, 7, 3,
1, 5, 7,
2, 3, 7,
2, 7, 6,
4, 6, 0,
0, 6, 2,
4, 5, 6,
5, 7, 6
};
const unsigned indicesPyramid[] = {8, 10, 9,
8, 11, 10,
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);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
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_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);
window = SDL_CreateWindow("SDL2 Test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
/*SDL_WINDOW_FULLSCREEN_DESKTOP |*/ SDL_WINDOW_OPENGL);
if (!window) {
std::printf("Could not create window: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
SDL_GLContext glcontext = SDL_GL_CreateContext(window);
if (!glcontext) {
std::printf("Could not create GL context: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
try {
while(glGetError() != GL_NO_ERROR);
{
int depth, stencil, aa, major, minor;
SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depth);
SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencil);
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &aa);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
std::printf("Depth: %d, Stencil: %d, AA: %d, GL %d.%d\n",
depth, stencil, aa, major, minor);
}
int width, height;
SDL_GetWindowSize(window, &width, &height);
glm::mat4 proj = glm::perspectiveFov(75.0f, static_cast<float>(width), static_cast<float>(height),
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));
// sf::Font font;
// if (!font.loadFromFile("DejaVuSans.ttf")) {
// std::printf("Error loading font\n");
// return 1;
// }
// sf::Text fpsText{"0", font, 12};
// fpsText.setPosition({200, 200});
// window.setFramerateLimit(60);
// sf::Clock clock;
// sf::Time last = clock.getElapsedTime();
checkGlError();
VertexShader vs{vertexShader};
FragmentShader fs{fragShader};
Program prog(vs, fs);
checkGlError();
prog.use();
glUniformMatrix4fv(prog.getUniformLocation("projection_matrix"), 1, GL_FALSE,
glm::value_ptr(proj));
checkGlError();
GLuint buf;
glGenBuffers(1, &buf);
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]);
GLuint arr;
glGenVertexArrays(1, &arr);
glBindVertexArray(arr);
checkGlError();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
checkGlError();
bool close = false;
while (!close) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_KEYDOWN:
close = true;
break;
case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_CLOSE)
close = true;
break;
}
}
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));
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();
// glUseProgram(0);
// sf::Time now = clock.getElapsedTime();
// sf::Time elapsed = now - last;
// last = now;
// fpsText.setString(std::to_string(static_cast<int>(std::roundf(1.0f/elapsed.asSeconds()))));
// fpsText.setPosition({1680-fpsText.getLocalBounds().width, 0});
// window.draw(fpsText);
SDL_GL_SwapWindow(window);
}
}catch(GLException &ex) {
std::printf("%s\n", ex.toString().c_str());
retcode = 1;
}
SDL_GL_DeleteContext(glcontext);
SDL_DestroyWindow(window);
// Clean up
SDL_Quit();
return retcode;
}