From 3bf3536271e4afa8a8a93c75e2ab1256c0bf718a Mon Sep 17 00:00:00 2001 From: Eleni Maria Stea Date: Thu, 27 Jul 2017 09:39:36 +0300 Subject: [PATCH] graphics api abstraction --- .gitignore | 7 +++ data/ground.obj | 8 +++- src/gfxapi.cc | 99 ++++++++++++++++++++++++++++++++++++++++++ src/gfxapi.h | 26 +++++++++++ src/main.cc | 110 +++++++++++++++++++++++++++-------------------- src/opengl/opengl.cc | 20 +++++++++ src/opengl/opengl.h | 1 + src/opengl/shader-gl.cc | 2 +- src/renderer.cc | 3 -- src/scene.cc | 27 +++--------- src/shader_manager.cc | 24 +++-------- src/vulkan/vk.cc | 4 ++ src/vulkan/vk.h | 1 + 13 files changed, 240 insertions(+), 92 deletions(-) create mode 100644 .gitignore create mode 100644 src/gfxapi.cc create mode 100644 src/gfxapi.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..526e077 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.o +*.d +*.swp +*.orig +demo +.vscode/ + diff --git a/data/ground.obj b/data/ground.obj index abe9cb7..4ec4564 100644 --- a/data/ground.obj +++ b/data/ground.obj @@ -7,7 +7,11 @@ v 1.000000 0.000000 1.000000 v -1.000000 0.000000 -1.000000 v 1.000000 0.000000 -1.000000 vn 0.0000 1.0000 0.0000 +vt 0 1 +vt 1 1 +vt 0 0 +vt 1 0 usemtl ground_mtl s off -f 2//1 3//1 1//1 -f 2//1 4//1 3//1 +f 2/2/1 3/3/1 1/1/1 +f 2/2/1 4/4/1 3/3/1 diff --git a/src/gfxapi.cc b/src/gfxapi.cc new file mode 100644 index 0000000..d4464f1 --- /dev/null +++ b/src/gfxapi.cc @@ -0,0 +1,99 @@ +#include "opengl/opengl.h" +#include "vulkan/vk.h" + +#include "gfxapi.h" + +#include "opengl/mesh-gl.h" +#include "opengl/texture-gl.h" +#include "opengl/shader-gl.h" + +#include "vulkan/mesh-vk.h" +#include "vulkan/texture-vk.h" + +static Gfx_API api; + +void (*gfx_clear)(float r, float g, float b); +void (*gfx_viewport)(int x, int y, int width, int height); + + +bool gfx_init(Gfx_API api) +{ + switch(api) { + case GFX_GL: + if(!init_opengl()) + return false; + break; + case GFX_VK: + if(!init_vulkan()) + return false; + break; + default: + return false; + } + + ::api = api; + return true; +} + +void gfx_cleanup() +{ + switch(api) { + case GFX_GL: + cleanup_opengl(); + break; + case GFX_VK: + cleanup_vulkan(); + break; + } +} + +Mesh *gfx_create_mesh() +{ + switch(api) { + case GFX_GL: + return new MeshGL; + case GFX_VK: + return new MeshVK; + } +} +Texture *gfx_create_texture() +{ + switch(api) { + case GFX_GL: + return new TextureGL; + case GFX_VK: + return new TextureVK; + } +} + +ShaderProgram *gfx_create_shader_program() +{ + switch(api) { + case GFX_GL: + return new ShaderProgramGL; + case GFX_VK: + // return new ShaderProgramVK; + return 0; + } +} + +Shader *gfx_create_shader() +{ + switch(api) { + case GFX_GL: + return new ShaderGL; + case GFX_VK: + // return new ShaderVK; + return 0; + } +} + +char *gfx_get_shader_path() +{ + switch(api) { + case GFX_GL: + return (char *)"gl_shaders"; + case GFX_VK: + return (char *)"vk_shaders"; + } +} \ No newline at end of file diff --git a/src/gfxapi.h b/src/gfxapi.h new file mode 100644 index 0000000..d3dcd4d --- /dev/null +++ b/src/gfxapi.h @@ -0,0 +1,26 @@ +#ifndef GFXAPI_H_ +#define GFXAPI_H_ + +class Mesh; +class Texture; +class ShaderProgram; +class Shader; + +enum Gfx_API { + GFX_GL, + GFX_VK +}; + +extern void (*gfx_clear)(float r, float g, float b); +extern void (*gfx_viewport)(int x, int y, int width, int height); + +bool gfx_init(Gfx_API api); +void gfx_cleanup(); + +Mesh *gfx_create_mesh(); +Texture *gfx_create_texture(); +ShaderProgram *gfx_create_shader_program(); +Shader *gfx_create_shader(); +char *gfx_get_shader_path(); + +#endif // GFXAPI_H_ \ No newline at end of file diff --git a/src/main.cc b/src/main.cc index 4ba8df3..6d7f4e7 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -5,6 +7,7 @@ #include +#include "gfxapi.h" #include "global.h" /* TODO: fix those */ @@ -13,14 +16,13 @@ #include "object.h" #include "renderer.h" #include "scene.h" -#include "shader_manager.h" #include "opengl/opengl.h" #include "vulkan/vk.h" /* static functions */ -static bool init(); +static bool init(Gfx_API api); static void cleanup(); static void display(); @@ -33,7 +35,6 @@ static void clbk_reshape(GLFWwindow *win, int width, int height); /* global variables */ -bool use_vulkan = false; Mat4 mprojection; GLFWwindow *win; @@ -47,27 +48,38 @@ float dist = 4; ShaderManager *sdr_man; /* variables */ + static float aspect; -static Scene *scene; static OrbitCamera *camera; -static Renderer *rdefault; // default renderer + +static Scene *scene_cow; +static Renderer *rcow; + +static Scene *scene_ground; +static Renderer *rground; // default renderer + +/* *** */ int main(int argc, char **argv) { + Gfx_API api; + for(int i=0; iset_orbit_params(phi, theta, dist); - scene = new Scene; - if(!scene->load("data/spot/spot.obj")) { - fprintf(stderr, "Failed to load scene.\n"); + scene_ground = new Scene; + if(!scene_ground->load("data/ground.obj")) { + fprintf(stderr, "Failed to load scene: ground.obj.\n"); + return false; + } + + scene_cow = new Scene; + if(!scene_cow->load("data/spot/spot.obj")) { + fprintf(stderr, "Failed to load scene: spot.obj.\n"); return false; } - rdefault = new Renderer; - rdefault->camera = camera; - rdefault->scene = scene; + rground = new Renderer; + rground->camera = camera; + rground->scene = scene_ground; - if(!rdefault->create()) { + if(!rground->create()) { fprintf(stderr, "Failed to create default renderer.\n"); return false; } + rcow = new Renderer; + rcow->camera = camera; + rcow->scene = scene_cow; + + if(!rcow->create()) { + fprintf(stderr, "Failed to create renderer for cows.\n"); + return false; + } + // TODO delete: debugging - for(size_t i=0; iobjects.size(); ++i) { + for(size_t i=0; iobjects.size(); ++i) { printf("object: %d\n", (int)i); - printf("mesh: %s\n", scene->objects[i]->mesh->name.c_str()); - printf("material: %s\n", scene->objects[i]->material->name.c_str()); + printf("mesh: %s\n", scene_ground->objects[i]->mesh->name.c_str()); + printf("material: %s\n", scene_ground->objects[i]->material->name.c_str()); printf("transform:\n"); - scene->objects[i]->transform.print(); + scene_ground->objects[i]->transform.print(); } return true; } @@ -138,15 +159,14 @@ static void cleanup() { delete sdr_man; delete camera; - delete scene; - delete rdefault; - if(use_vulkan) { - cleanup_vulkan(); - } - else { - cleanup_opengl(); - } + delete scene_cow; + delete rcow; + + delete scene_ground; + delete rground; + + gfx_cleanup(); } static void clbk_key(GLFWwindow *win, int key, int scancode, int action, int mods) @@ -178,7 +198,7 @@ static void clbk_motion(GLFWwindow *win, double x, double y) } if(button[1]) { - dist += dy; + dist += dy * 0.1; if(dist < 0.0) { dist = 0.0; } @@ -193,15 +213,9 @@ static void clbk_mouse(GLFWwindow *win, int bn, int action, int mods) static void clbk_reshape(GLFWwindow *win, int width, int height) { - if(use_vulkan) { - //TODO - return; - } - else { - glViewport(0, 0, width, height); - aspect = (float)width / (float)height; - mprojection = calc_projection_matrix(45, aspect, 0.5, 1000.0); - } + gfx_viewport(0, 0, width, height); + aspect = (float)width / (float)height; + mprojection = calc_projection_matrix(45, aspect, 0.5, 1000.0); win_h = height; win_w = width; @@ -210,5 +224,9 @@ static void clbk_reshape(GLFWwindow *win, int width, int height) static void display() { camera->set_orbit_params(phi, theta, dist); - rdefault->draw(); + + gfx_clear(0.76, 0.3, 0.43); + + rground->draw(); + rcow->draw(); } \ No newline at end of file diff --git a/src/opengl/opengl.cc b/src/opengl/opengl.cc index 46363f4..ffa1d47 100644 --- a/src/opengl/opengl.cc +++ b/src/opengl/opengl.cc @@ -1,12 +1,16 @@ #include #include +#include "gfxapi.h" #include "opengl/opengl.h" extern GLFWwindow *win; extern int win_h; extern int win_w; +static void clear(float r, float g, float b); +static void viewport(int x, int y, int width, int height); + bool init_opengl() { if(!glfwInit()) { @@ -16,6 +20,7 @@ bool init_opengl() glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); + glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE); if(!(win = glfwCreateWindow(win_w, win_h, "glcow", 0, 0))) { fprintf(stderr, "Failed to create window.\n"); @@ -27,6 +32,10 @@ bool init_opengl() glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); + glEnable(GL_FRAMEBUFFER_SRGB); // linear colorspace + + gfx_clear = clear; + gfx_viewport = viewport; return true; } @@ -37,4 +46,15 @@ void cleanup_opengl() glfwDestroyWindow(win); } glfwTerminate(); +} + +static void clear(float r, float g, float b) +{ + glClearColor(r, g, b, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +static void viewport(int x, int y, int width, int height) +{ + glViewport(x, y, width, height); } \ No newline at end of file diff --git a/src/opengl/opengl.h b/src/opengl/opengl.h index 1a1fa8a..1a9a86f 100644 --- a/src/opengl/opengl.h +++ b/src/opengl/opengl.h @@ -7,4 +7,5 @@ bool init_opengl(); void cleanup_opengl(); GLFWwindow *create_opengl_window(); +void clear_gl(); #endif // OPENGL_H_ diff --git a/src/opengl/shader-gl.cc b/src/opengl/shader-gl.cc index 1ce36b7..898e5c5 100644 --- a/src/opengl/shader-gl.cc +++ b/src/opengl/shader-gl.cc @@ -132,7 +132,7 @@ bool ShaderProgramGL::link() bool ShaderProgramGL::use() const { - if(!is_linked) { //&& !link()) { + if(!is_linked) { return false; } diff --git a/src/renderer.cc b/src/renderer.cc index 8d2c70c..06efbee 100644 --- a/src/renderer.cc +++ b/src/renderer.cc @@ -69,9 +69,6 @@ void Renderer::draw() const if(!camera || !scene) return; - glClearColor(0.5, 0.5, 0.5, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - if(!sprog->link()) return; diff --git a/src/scene.cc b/src/scene.cc index 99c3b01..d033a8f 100644 --- a/src/scene.cc +++ b/src/scene.cc @@ -10,18 +10,13 @@ #include +#include "gfxapi.h" + #include "mesh.h" #include "object.h" #include "scene.h" #include "texture.h" -#include "opengl/mesh-gl.h" -#include "vulkan/mesh-vk.h" - -#include "opengl/texture-gl.h" -#include "vulkan/texture-vk.h" - -extern bool use_vulkan; static Mesh *load_mesh(const aiScene *scene, unsigned int index); static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int index, const char *tex_fname); @@ -149,14 +144,7 @@ static Mesh *load_mesh(const aiScene *scene, unsigned int index) return 0; } - Mesh *mesh; - if(use_vulkan) { - mesh = new MeshVK; - } - else { - mesh = new MeshGL; - } - + Mesh *mesh = gfx_create_mesh(); mesh->name = std::string(amesh->mName.data); for(unsigned int i=0; imNumVertices; i++) { @@ -260,12 +248,9 @@ static Material *load_material(const aiScene *ascene, Scene *scene, unsigned int mat->dtex = scene->find_texture(tex_fname.c_str()); if(!mat->dtex) { printf("!mat->dtex\n"); - if(use_vulkan) { - mat->dtex = new TextureVK; - } - else { - mat->dtex = new TextureGL; - } + + mat->dtex = gfx_create_texture(); + if(!mat->dtex->load(tex_fname.c_str())) { fprintf(stderr, "Failed to load texture data: %s.\n", tex_fname.c_str()); delete mat->dtex; diff --git a/src/shader_manager.cc b/src/shader_manager.cc index 87c0451..7ebbce6 100644 --- a/src/shader_manager.cc +++ b/src/shader_manager.cc @@ -1,10 +1,10 @@ #include +#include "gfxapi.h" + #include "shader_manager.h" #include "opengl/shader-gl.h" -extern bool use_vulkan; - ShaderManager::ShaderManager() {} ShaderManager::~ShaderManager() {} @@ -22,13 +22,7 @@ Shader *ShaderManager::load_shader(const char *name, SType type) return it->second; } - Shader *sdr; - if(use_vulkan) { - // sdr = new ShaderVK; - } - else { - sdr = new ShaderGL; - } + Shader *sdr = gfx_create_shader(); std::string fname = path.empty() ? std::string(name) : path + "/" + std::string(name); @@ -52,7 +46,7 @@ void ShaderManager::delete_shaders() ShaderProgram *ShaderManager::create_shader_program(const char *vname, const char *fname) { - path = use_vulkan ? "vk_shaders" : "gl_shaders"; + path = std::string(gfx_get_shader_path()); Shader *vsdr = load_shader(vname, SDR_VERTEX); if(!vsdr) @@ -62,15 +56,7 @@ ShaderProgram *ShaderManager::create_shader_program(const char *vname, const cha if(!fsdr) return 0; - ShaderProgram *sprog; - - if(use_vulkan) { - // TODO - return 0; - } - else { - sprog = new ShaderProgramGL; - } + ShaderProgram *sprog = gfx_create_shader_program(); if(!sprog->create()) { return 0; diff --git a/src/vulkan/vk.cc b/src/vulkan/vk.cc index a49fa5c..24941b5 100644 --- a/src/vulkan/vk.cc +++ b/src/vulkan/vk.cc @@ -13,4 +13,8 @@ void cleanup_vulkan() GLFWwindow *create_vulkan_window() { return 0; +} + +void clbk_clear_vk() +{ } \ No newline at end of file diff --git a/src/vulkan/vk.h b/src/vulkan/vk.h index b73432b..b391a52 100644 --- a/src/vulkan/vk.h +++ b/src/vulkan/vk.h @@ -8,4 +8,5 @@ bool init_vulkan(); void cleanup_vulkan(); GLFWwindow *create_vulkan_window(); +void clbk_clear_vk(); #endif // VK_H_ -- 1.7.10.4