]> git.localhorst.tv Git - blank.git/commitdiff
initial testing
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Wed, 11 Feb 2015 20:01:35 +0000 (21:01 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Wed, 11 Feb 2015 20:01:35 +0000 (21:01 +0100)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
src/init.cpp [new file with mode: 0644]
src/init.hpp [new file with mode: 0644]
src/main.cpp [new file with mode: 0644]
src/shader.cpp [new file with mode: 0644]
src/shader.hpp [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..0f9ba43
--- /dev/null
@@ -0,0 +1,5 @@
+*.d
+*.o
+*.swp
+*.swo
+blank
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..a3855ad
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,34 @@
+CXX = g++ --std=c++11
+LDXX = g++
+
+LIBS = sdl2 glew
+
+PKGFLAGS := $(shell pkg-config --cflags $(LIBS))
+PKGLIBS := $(shell pkg-config --libs $(LIBS))
+
+CPPFLAGS ?=
+CPPFLAGS += $(PKGFLAGS)
+CXXFLAGS ?=
+CXXFLAGS += -Wall
+LDXXFLAGS ?=
+LDXXFLAGS += $(PKGLIBS)
+
+SRC = $(wildcard src/*.cpp)
+OBJ = $(SRC:.cpp=.o)
+DEP = $(SRC:.cpp=.d)
+BIN = blank
+
+all: $(BIN)
+
+clean:
+       rm -f $(BIN) $(OBJ) $(DEP)
+
+.PHONY: all clean
+
+-include $(DEP)
+
+$(BIN): $(OBJ)
+       $(LDXX) -o $@ $(CXXFLAGS) $(LDXXFLAGS) $^
+
+%.o: %.cpp
+       $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ -MMD -MP -MF"$*".d -MT"$@" $<
diff --git a/src/init.cpp b/src/init.cpp
new file mode 100644 (file)
index 0000000..9010e00
--- /dev/null
@@ -0,0 +1,133 @@
+#include "init.hpp"
+
+#include <algorithm>
+#include <SDL.h>
+#include <stdexcept>
+#include <string>
+#include <GL/glew.h>
+
+
+namespace {
+
+void sdl_error(std::string msg) {
+       const char *error = SDL_GetError();
+       if (*error != '\0') {
+               msg += ": ";
+               msg += error;
+               SDL_ClearError();
+       }
+       throw std::runtime_error(msg);
+}
+
+}
+
+namespace blank {
+
+InitSDL::InitSDL() {
+       if (SDL_Init(SDL_INIT_VIDEO) != 0) {
+               sdl_error("SDL_Init(SDL_INIT_VIDEO)");
+       }
+}
+
+InitSDL::~InitSDL() {
+       SDL_Quit();
+}
+
+
+InitGL::InitGL() {
+       if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3) != 0) {
+               sdl_error("SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3)");
+       }
+       if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3) != 0) {
+               sdl_error("SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3)");
+       }
+       if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE) != 0) {
+               sdl_error("SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE)");
+       }
+
+       if (SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1) != 0) {
+               sdl_error("SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1)");
+       }
+}
+
+InitGL::~InitGL() {
+
+}
+
+
+Window::Window()
+: handle(SDL_CreateWindow(
+       "blank",
+       SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+       960, 600,
+       SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
+)) {
+       if (!handle) {
+               sdl_error("SDL_CreateWindow");
+       }
+}
+
+Window::~Window() {
+       SDL_DestroyWindow(handle);
+}
+
+GLContext Window::CreateContext() {
+       return GLContext(handle);
+}
+
+void Window::Flip() {
+       SDL_GL_SwapWindow(handle);
+}
+
+
+GLContext::GLContext(SDL_Window *win)
+: handle(SDL_GL_CreateContext(win)) {
+       if (!handle) {
+               sdl_error("SDL_GL_CreateContext");
+       }
+}
+
+GLContext::~GLContext() {
+       if (handle) {
+               SDL_GL_DeleteContext(handle);
+       }
+}
+
+
+GLContext::GLContext(GLContext &&other)
+: handle(other.handle) {
+       other.handle = nullptr;
+}
+
+GLContext &GLContext::operator =(GLContext &&other) {
+       std::swap(handle, other.handle);
+       return *this;
+}
+
+void GLContext::EnableVSync() {
+       if (SDL_GL_SetSwapInterval(1) != 0) {
+               sdl_error("SDL_GL_SetSwapInterval");
+       }
+}
+
+
+InitGLEW::InitGLEW() {
+       glewExperimental = GL_TRUE;
+       GLenum glew_err = glewInit();
+       if (glew_err != GLEW_OK) {
+               std::string msg("glewInit: ");
+               const GLubyte *errBegin = glewGetErrorString(glew_err);
+               const GLubyte *errEnd = errBegin;
+               while (*errEnd != '\0') {
+                       ++errEnd;
+               }
+               msg.append(errBegin, errEnd);
+               throw std::runtime_error(msg);
+       }
+}
+
+InitGLEW::~InitGLEW() {
+
+}
+
+}
diff --git a/src/init.hpp b/src/init.hpp
new file mode 100644 (file)
index 0000000..0256d40
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef BLANK_INIT_HPP_
+#define BLANK_INIT_HPP_
+
+#include <SDL.h>
+
+
+namespace blank {
+
+class GLContext;
+
+
+class InitSDL {
+
+public:
+       InitSDL();
+       ~InitSDL();
+
+       InitSDL(const InitSDL &) = delete;
+       InitSDL &operator =(const InitSDL &) = delete;
+
+};
+
+
+class InitGL {
+
+public:
+       InitGL();
+       ~InitGL();
+
+       InitGL(const InitGL &) = delete;
+       InitGL &operator =(const InitGL &) = delete;
+
+};
+
+
+class Window {
+
+public:
+       Window();
+       ~Window();
+
+       Window(const Window &) = delete;
+       Window &operator =(const Window &) = delete;
+
+       GLContext CreateContext();
+
+       void Flip();
+
+private:
+       SDL_Window *handle;
+
+};
+
+
+class GLContext {
+
+public:
+       explicit GLContext(SDL_Window *);
+       ~GLContext();
+
+       GLContext(GLContext &&);
+       GLContext &operator =(GLContext &&);
+
+       GLContext(const GLContext &) = delete;
+       GLContext &operator =(const GLContext &) = delete;
+
+       static void EnableVSync();
+
+private:
+       SDL_GLContext handle;
+
+};
+
+
+class InitGLEW {
+
+public:
+       InitGLEW();
+       ~InitGLEW();
+
+       InitGLEW(const InitGLEW &) = delete;
+       InitGLEW &operator =(const InitGLEW &) = delete;
+
+};
+
+}
+
+#endif
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644 (file)
index 0000000..33071f1
--- /dev/null
@@ -0,0 +1,157 @@
+#include <iostream>
+#include <SDL.h>
+#include <GL/glew.h>
+#include <glm/glm.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+
+#include "init.hpp"
+#include "shader.hpp"
+
+using namespace std;
+using namespace blank;
+
+
+constexpr GLfloat vtx_coords[] = {
+       -1.0f, -1.0f, -1.0f,
+        1.0f, -1.0f, -1.0f,
+        0.0f,  1.0f, -1.0f,
+};
+
+
+int main(int argc, char *argv[]) {
+
+       InitSDL init_sdl;
+       InitGL init_gl;
+       Window window;
+
+       GLContext ctx = window.CreateContext();
+       InitGLEW init_glew;
+       GLContext::EnableVSync();
+
+
+       Shader vtx_shader(GL_VERTEX_SHADER);
+       vtx_shader.Source(
+               "#version 330 core\n"
+               "layout(location = 0) in vec3 vertexPosition_modelspace;\n"
+               "uniform mat4 MVP;\n"
+               "void main() {\n"
+                       "vec4 v = vec4(vertexPosition_modelspace, 1);\n"
+                       "gl_Position = MVP * v;\n"
+               "}\n"
+       );
+       vtx_shader.Compile();
+
+       if (!vtx_shader.Compiled()) {
+               cerr << "vertex shader compile error" << endl;
+               vtx_shader.Log(cerr);
+               return 4;
+       }
+
+       Shader frag_shader(GL_FRAGMENT_SHADER);
+       frag_shader.Source(
+               "#version 330 core\n"
+               "out vec3 color;\n"
+               "void main() {\n"
+                       "color = vec3(1, 1, 1);\n"
+               "}\n"
+       );
+       frag_shader.Compile();
+
+       if (!frag_shader.Compiled()) {
+               cerr << "fragment shader compile error" << endl;
+               frag_shader.Log(cerr);
+               return 4;
+       }
+
+
+       Program program;
+       program.Attach(vtx_shader);
+       program.Attach(frag_shader);
+       program.Link();
+
+       if (!program.Linked()) {
+               cerr << "program link error" << endl;
+               program.Log(cerr);
+               return 4;
+       }
+
+
+       GLuint VertexArrayID;
+       glGenVertexArrays(1, &VertexArrayID);
+       glBindVertexArray(VertexArrayID);
+
+
+       GLuint vtx_buf;
+       glGenBuffers(1, &vtx_buf);
+       glBindBuffer(GL_ARRAY_BUFFER, vtx_buf);
+       glBufferData(GL_ARRAY_BUFFER, sizeof(vtx_coords), vtx_coords, GL_STATIC_DRAW);
+
+
+       glm::mat4 projection = glm::perspective(
+               45.0f, // FOV in degrees
+               1.0f,  // aspect ratio
+               0.1f,  // near clip
+               100.0f // far clip
+       );
+       glm::mat4 view = glm::lookAt(
+               glm::vec3(0, 0,  0),  // observer
+               glm::vec3(0, 0, -1), // target
+               glm::vec3(0, 1,  0) // up
+       );
+       glm::mat4 model(1.0f); // identity: no transformation
+       glm::mat4 mvp = projection * view * model;
+
+       GLuint mvp_id = program.UniformLocation("MVP");
+
+
+       glClearColor(0.0, 0.0, 0.0, 1.0);
+
+
+       bool running = true;
+       Uint32 last = SDL_GetTicks();
+       while (running) {
+               Uint32 now = SDL_GetTicks();
+               int delta = now - last;
+
+               SDL_Event event;
+               while (SDL_PollEvent(&event)) {
+                       switch (event.type) {
+                               case SDL_QUIT:
+                                       running = false;
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+
+               glClear(GL_COLOR_BUFFER_BIT);
+
+               program.Use();
+
+               glUniformMatrix4fv(mvp_id, 1, GL_FALSE, &mvp[0][0]);
+
+               glEnableVertexAttribArray(0);
+               glBindBuffer(GL_ARRAY_BUFFER, vtx_buf);
+               glVertexAttribPointer(
+                       0,        // attribute 0 (for shader)
+                       3,        // size
+                       GL_FLOAT, // type
+                       GL_FALSE, // normalized
+                       0,        // stride
+                       nullptr   // offset
+               );
+               glDrawArrays(
+                       GL_TRIANGLES, // how
+                       0,            // start
+                       3             // len
+               );
+               glDisableVertexAttribArray(0);
+
+               window.Flip();
+
+               last = now;
+       }
+
+       return 0;
+
+}
diff --git a/src/shader.cpp b/src/shader.cpp
new file mode 100644 (file)
index 0000000..985b96e
--- /dev/null
@@ -0,0 +1,123 @@
+#include "shader.hpp"
+
+#include <algorithm>
+#include <memory>
+#include <ostream>
+#include <stdexcept>
+#include <string>
+
+
+namespace {
+
+void gl_error(std::string msg) {
+       const GLubyte *errBegin = gluErrorString(glGetError());
+       if (errBegin && *errBegin != '\0') {
+               const GLubyte *errEnd = errBegin;
+               while (*errEnd != '\0') {
+                       ++errEnd;
+               }
+               msg += ": ";
+               msg.append(errBegin, errEnd);
+       }
+       throw std::runtime_error(msg);
+}
+
+}
+
+namespace blank {
+
+Shader::Shader(GLenum type)
+: handle(glCreateShader(type)) {
+       if (handle == 0) {
+               gl_error("glCreateShader");
+       }
+}
+
+Shader::~Shader() {
+       if (handle != 0) {
+               glDeleteShader(handle);
+       }
+}
+
+Shader::Shader(Shader &&other)
+: handle(other.handle) {
+       other.handle = 0;
+}
+
+Shader &Shader::operator =(Shader &&other) {
+       std::swap(handle, other.handle);
+       return *this;
+}
+
+
+void Shader::Source(const GLchar *src) {
+       const GLchar* src_arr[] = { src };
+       glShaderSource(handle, 1, src_arr, nullptr);
+}
+
+void Shader::Compile() {
+       glCompileShader(handle);
+}
+
+bool Shader::Compiled() const {
+       GLint compiled = GL_FALSE;
+       glGetShaderiv(handle, GL_COMPILE_STATUS, &compiled);
+       return compiled == GL_TRUE;
+}
+
+void Shader::Log(std::ostream &out) const {
+       int log_len = 0, max_len = 0;
+       glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &max_len);
+       std::unique_ptr<char[]> log(new char[max_len]);
+       glGetShaderInfoLog(handle, max_len, &log_len, log.get());
+       out.write(log.get(), log_len);
+}
+
+
+void Shader::AttachToProgram(GLuint id) const {
+       glAttachShader(id, handle);
+}
+
+
+Program::Program()
+: handle(glCreateProgram()) {
+       if (handle == 0) {
+               gl_error("glCreateProgram");
+       }
+}
+
+Program::~Program() {
+       if (handle != 0) {
+               glDeleteProgram(handle);
+       }
+}
+
+
+void Program::Attach(Shader &shader) {
+       shader.AttachToProgram(handle);
+}
+
+void Program::Link() {
+       glLinkProgram(handle);
+}
+
+bool Program::Linked() const {
+       GLint linked = GL_FALSE;
+       glGetProgramiv(handle, GL_LINK_STATUS, &linked);
+       return linked == GL_TRUE;
+}
+
+void Program::Log(std::ostream &out) const {
+       int log_len = 0, max_len = 0;
+       glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &max_len);
+       std::unique_ptr<char[]> log(new char[max_len]);
+       glGetProgramInfoLog(handle, max_len, &log_len, log.get());
+       out.write(log.get(), log_len);
+}
+
+
+GLint Program::UniformLocation(const GLchar *name) const {
+       return glGetUniformLocation(handle, name);
+}
+
+}
diff --git a/src/shader.hpp b/src/shader.hpp
new file mode 100644 (file)
index 0000000..c112c53
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef BLANK_SHADER_HPP_
+#define BLANK_SHADER_HPP_
+
+#include <iosfwd>
+#include <GL/glew.h>
+
+
+namespace blank {
+
+class Shader {
+
+public:
+       explicit Shader(GLenum type);
+       ~Shader();
+
+       Shader(Shader &&);
+       Shader &operator =(Shader &&);
+
+       Shader(const Shader &) = delete;
+       Shader &operator =(const Shader &) = delete;
+
+       void Source(const GLchar *src);
+       void Compile();
+       bool Compiled() const;
+       void Log(std::ostream &) const;
+
+       void AttachToProgram(GLuint id) const;
+
+private:
+       GLuint handle;
+
+};
+
+
+class Program {
+
+public:
+       Program();
+       ~Program();
+
+       Program(const Program &) = delete;
+       Program &operator =(const Program &) = delete;
+
+       void Attach(Shader &);
+       void Link();
+       bool Linked() const;
+       void Log(std::ostream &) const;
+
+       GLint UniformLocation(const GLchar *name) const;
+
+       void Use() const { glUseProgram(handle); }
+
+private:
+       GLuint handle;
+
+};
+
+}
+
+#endif