Initial import
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
objs/
|
||||
oglpg
|
||||
20
Makefile
Normal file
20
Makefile
Normal 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
487
main.cc
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user