Jelajahi Sumber

Migrate "material uniform id" into the driver-impl.

Sam Jaffe 6 tahun lalu
induk
melakukan
fb6f0da68b

+ 3 - 0
graphics/include/game/graphics/graphics_fwd.h

@@ -22,6 +22,9 @@ namespace graphics {
   struct shader;
   struct shader_program;
   class texture;
+  namespace materials {
+    enum class uniform : unsigned int;
+  }
   namespace shaders {
     enum class type : unsigned int;
   }

+ 2 - 3
graphics/include/game/graphics/material.hpp

@@ -16,15 +16,14 @@
 namespace graphics {
   struct uniform {
     identity<texture> texture;
-    int uniform_id; // TODO (sjaffe): use an enum and hide remapping?
+    materials::uniform
+        uniform_id; // TODO (sjaffe): use an enum and hide remapping?
   };
 
   struct material : public identity<material> {
     material(identity<shader_program> const & sp, math::vec2i size,
              std::vector<uniform> const & uniforms);
 
-    void activate() const;
-
     identity<shader_program> program;
     math::vec2i size;
     std::vector<uniform> uniforms;

+ 8 - 1
graphics/src/helper.hpp

@@ -30,8 +30,9 @@ namespace graphics {
                          std::string const & uniform);
   }
   namespace materials {
+    enum class uniform : unsigned int { NORMAL, DIFFUSE, SPECULAR };
     void activate(identity<shader_program> program,
-                  std::vector<uniform> const & uniforms);
+                  std::vector<graphics::uniform> const & uniforms);
   }
 }
 
@@ -41,4 +42,10 @@ namespace std {
       return std::hash<unsigned int>()(static_cast<unsigned int>(tp));
     }
   };
+
+  template <> struct hash<graphics::materials::uniform> {
+    std::size_t operator()(graphics::materials::uniform uf) const {
+      return std::hash<unsigned int>()(static_cast<unsigned int>(uf));
+    }
+  };
 }

+ 13 - 2
graphics/src/manager.cxx

@@ -55,6 +55,17 @@ struct graphics::manager_cache {
 manager::manager() : pcache_(new manager_cache) {}
 manager::~manager() {}
 
+materials::uniform uniform_id(std::string const & uniform) {
+  if (uniform == "u_normalMap") {
+    return materials::uniform::NORMAL;
+  } else if (uniform == "u_specularMap") {
+    return materials::uniform::SPECULAR;
+  } else if (uniform == "u_diffuseMap") {
+    return materials::uniform::DIFFUSE;
+  }
+  throw;
+}
+
 identity<material> manager::get(identity<shader_program> program,
                                 std::string const & texture,
                                 std::string const & uniform) const {
@@ -64,8 +75,8 @@ identity<material> manager::get(identity<shader_program> program,
   if (found != cache.values.end()) { return found->second; }
 
   std::vector<struct uniform> uniforms;
-  uniforms.push_back({texture_or_uniform(texture, uniform),
-                      shaders::uniform_location(program, uniform)});
+  uniforms.push_back(
+      {texture_or_uniform(texture, uniform), uniform_id(uniform)});
   math::vec2i size = get(uniforms[0].texture).size;
   //  if (!uniforms.empty()) { size = ...; }
   return cache.emplace(key, material(program, size, uniforms));

+ 0 - 2
graphics/src/material.cpp

@@ -24,5 +24,3 @@ material::material(identity<shader_program> const & sp, math::vec2i size,
                    std::vector<uniform> const & uniforms)
     : identity<material>(next_id()), program(sp), size(size),
       uniforms(uniforms) {}
-
-void material::activate() const { materials::activate(program, uniforms); }

+ 14 - 22
graphics/src/openGL/opengl_manager.cxx

@@ -199,6 +199,20 @@ shader_program opengl_manager::compile(identity<shader> fragmentShader,
   return shader_program{id, fragmentShader, vertexShader};
 }
 
+opengl_uniform_data & opengl_manager::data(identity<shader_program> program) {
+  auto & data = data_[program];
+  // TODO: perform this in compile()
+  if (data.uniform_id.empty()) {
+    glUseProgram(program.id);
+    using materials::uniform;
+    data.uniform_id = {
+        {uniform::NORMAL, glGetUniformLocation(program.id, "u_normalMap")},
+        {uniform::DIFFUSE, glGetUniformLocation(program.id, "u_diffuseMap")},
+        {uniform::SPECULAR, glGetUniformLocation(program.id, "u_specularMap")}};
+  }
+  return data;
+}
+
 namespace graphics { namespace shaders {
   void activate(identity<shader_program> program) {
     // 100. Use the shader program ID to "turn it on" for all subsequent drawing
@@ -248,26 +262,4 @@ namespace graphics { namespace shaders {
     // for GL_TEXTURE3, texture unit 3
     glUniform1i(emissiveMap, 3);
   }
-
-  int uniform_location(identity<shader_program> program,
-                       std::string const & uniform) {
-    return glGetUniformLocation(program.id, uniform.c_str());
-  }
-}}
-
-namespace graphics { namespace materials {
-  void activate(identity<shader_program> program,
-                std::vector<uniform> const & uniforms) {
-    glUseProgram(program.id);
-
-    for (unsigned int i = 0; i < uniforms.size(); i++) {
-      const uniform & uniform = uniforms[i];
-      glActiveTexture(i + GL_TEXTURE0);
-      //      glEnable(GL_TEXTURE_2D);
-      glBindTexture(GL_TEXTURE_2D, uniform.texture.id);
-      glUniform1i(uniform.uniform_id, i);
-    }
-
-    glActiveTexture(GL_TEXTURE0);
-  }
 }}

+ 2 - 2
graphics/src/openGL/opengl_renderer.cxx

@@ -24,7 +24,7 @@
 using namespace graphics;
 
 opengl_renderer::opengl_renderer()
-    : mgr(new opengl_manager), active_material(0) {
+    : manager_(new opengl_manager), active_material(0) {
   glGenVertexArrays(1, &vertex_array_object);
   glBindVertexArray(vertex_array_object);
   glGenBuffers(1, &vertex_buffer_object);
@@ -108,7 +108,7 @@ void opengl_renderer::activate(material const & mat) {
     glActiveTexture(i + GL_TEXTURE0);
     //      glEnable(GL_TEXTURE_2D);
     glBindTexture(GL_TEXTURE_2D, uniform.texture.id);
-    glUniform1i(uniform.uniform_id, i);
+    glUniform1i(manager_->data(mat.program)[uniform.uniform_id], i);
   }
 
   glActiveTexture(GL_TEXTURE0);

+ 14 - 2
graphics/src/openGL/opengl_renderer.h

@@ -8,6 +8,7 @@
 
 #pragma once
 
+#include "../helper.hpp"
 #include "game/graphics/manager.hpp"
 #include "game/util/identity.hpp"
 #include "renderer_impl.hpp"
@@ -16,11 +17,22 @@
 #include "matrix/matrix_helpers.hpp"
 
 namespace graphics {
+  struct opengl_uniform_data {
+    unsigned int operator[](materials::uniform id) { return uniform_id[id]; }
+    std::unordered_map<materials::uniform, unsigned int> uniform_id;
+  };
+
   class opengl_manager : public manager {
+  public:
     shader compile(shaders::type type, std::string const & path) const override;
     shader_program compile(identity<shader> fragment,
                            identity<shader> vertex) const override;
     texture compile(std::string const & path) const override;
+
+    opengl_uniform_data & data(identity<shader_program> id);
+
+  private:
+    std::unordered_map<identity<shader_program>, opengl_uniform_data> data_;
   };
 
   class opengl_renderer : public renderer_impl {
@@ -34,7 +46,7 @@ namespace graphics {
     void flush() override;
 
     std::shared_ptr<class manager const> manager() const override {
-      return mgr;
+      return manager_;
     }
 
   private:
@@ -43,7 +55,7 @@ namespace graphics {
   private:
     const math::matr4 identity{math::matrix::identity<float, 4>()};
 
-    std::shared_ptr<class manager> mgr;
+    std::shared_ptr<opengl_manager> manager_;
     unsigned int active_material;
 
     math::matr4 world_to_clip{identity};