فهرست منبع

Move texture initialization into correct places.

Sam Jaffe 6 سال پیش
والد
کامیت
bf0ca5c14b

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

@@ -28,4 +28,7 @@ namespace graphics {
   namespace shaders {
     enum class type : unsigned int;
   }
+  namespace textures {
+    enum class format : unsigned int;
+  }
 }

+ 3 - 1
graphics/include/game/graphics/manager.hpp

@@ -74,6 +74,7 @@ namespace graphics {
     texture const & get(identity<texture> identity) const;
 
   private:
+    void prepare_uniforms() const;
     identity<texture> texture_or_uniform(std::string const & path,
                                          std::string const & uniform) const;
 
@@ -81,7 +82,8 @@ namespace graphics {
                            std::string const & path) const = 0;
     virtual shader_program compile(identity<shader> fragment,
                                    identity<shader> vertex) const = 0;
-    virtual texture compile(std::string const & path) const = 0;
+    virtual texture compile(textures::format color, math::vec2i size,
+                            void const * buffer) const = 0;
 
     std::unique_ptr<struct manager_cache> pcache_;
   };

+ 2 - 12
graphics/include/game/graphics/texture.hpp

@@ -12,19 +12,9 @@
 #include "vector/vector.hpp"
 
 namespace graphics {
-  class texture : public identity<texture> {
-  public:
-    texture(std::string const & str);
+  struct texture : public identity<texture> {
+    texture(unsigned int id, math::vec2i const & size);
 
-    static texture const & WHITE();
-    static texture const & DARK_YELLOW();
-    static texture const & LIGHT_BLUE();
-
-  private:
-    texture(std::pair<unsigned int, math::vec2i>);
-    texture(char const *, math::vec2i);
-
-  public:
     math::vec2i const size;
   };
 }

+ 9 - 1
graphics/src/helper.hpp

@@ -13,11 +13,19 @@
 
 #include "game/graphics/graphics_fwd.h"
 #include "game/math/math_fwd.hpp"
+#include "vector/vector.hpp"
 
 namespace graphics {
   struct uniform;
   namespace textures {
-    enum class format { RGB, RGBA };
+    enum class format : unsigned int { RGB, RGBA };
+    struct external_data {
+      external_data(std::string const & abs_path);
+      ~external_data();
+      format color;
+      math::vec2i size;
+      void * buffer;
+    };
     unsigned int init(format, math::vec2i, void const *);
   }
   namespace shaders {

+ 18 - 9
graphics/src/manager.cxx

@@ -107,7 +107,8 @@ identity<texture> manager::get(std::string const & path) const {
   auto & cache = pcache_->textures;
   auto found = cache.values.find(path);
   if (found != cache.values.end()) { return found->second; }
-  return cache.emplace(path, compile(path));
+  textures::external_data data(path);
+  return cache.emplace(path, compile(data.color, data.size, data.buffer));
 }
 
 object manager::create_object(identity<material> fromMaterial,
@@ -126,10 +127,20 @@ material const & manager::get(identity<material> identity) const {
 texture const & manager::get(identity<texture> identity) const {
   auto & cache = pcache_->textures;
   auto it = cache.keys.find(identity);
-  if (it == cache.keys.end()) { return texture::WHITE(); }
+  //  if (it == cache.keys.end()) { return texture::WHITE(); }
   return cache.values.find(it->second)->second;
 }
 
+void manager::prepare_uniforms() const {
+  // Initialize the three default uniform-textures immediately
+  auto & cache = pcache_->textures;
+  if (cache.values.count("u_normalMap") != 0) return;
+  auto RGBA = textures::format::RGBA;
+  cache.emplace("u_normalMap", compile(RGBA, {{1, 1}}, "\x80\x80\xFF\xFF"));
+  cache.emplace("u_specularMap", compile(RGBA, {{1, 1}}, "\x80\x80\x00\xFF"));
+  cache.emplace("u_diffuseMap", compile(RGBA, {{1, 1}}, "\xFF\xFF\xFF\xFF"));
+}
+
 identity<texture>
 manager::texture_or_uniform(std::string const & path,
                             std::string const & uniform) const {
@@ -140,12 +151,10 @@ manager::texture_or_uniform(std::string const & path,
       // TODO: Logging
     }
   }
-  if (uniform == "u_normalMap") {
-    return texture::LIGHT_BLUE();
-  } else if (uniform == "u_specularMap") {
-    return texture::DARK_YELLOW();
-  } else if (uniform == "u_diffuseMap") {
-    return texture::WHITE();
-  }
+  prepare_uniforms();
+  // The uniform is primed into the cache already.
+  auto & cache = pcache_->textures;
+  auto found = cache.values.find(path);
+  if (found != cache.values.end()) { return found->second; }
   throw;
 }

+ 69 - 67
graphics/src/openGL/opengl_manager.cxx

@@ -22,6 +22,7 @@
 #include "game/graphics/material.hpp"
 #include "game/graphics/shader.hpp"
 #include "game/graphics/shader_program.hpp"
+#include "game/graphics/texture.hpp"
 #include "game/util/env.hpp"
 #include "game/util/files.hpp"
 #include "game/util/time.hpp"
@@ -66,73 +67,74 @@ namespace {
   }
 }
 
-namespace graphics { namespace textures {
-  unsigned int init(format color_fmt, math::vec2i dimension,
-                    void const * data) {
-    unsigned int id;
-    // Enable texturings
-    //    glEnable( GL_TEXTURE_2D );
-
-    // Tell OpenGL that our pixel data is single-byte aligned
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
-    // Ask OpenGL for an unused texName (ID number) to use for this texture
-    glGenTextures(1, &id);
-
-    // Tell OpenGL to bind (set) this as the currently active texture
-    glBindTexture(GL_TEXTURE_2D, id);
-    // Set texture clamp vs. wrap (repeat)
-
-    // one of: GL_CLAMP_TO_EDGE, GL_REPEAT, GL_MIRRORED_REPEAT,
-    // GL_MIRROR_CLAMP_TO_EDGE, ...
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-    // the format our source pixel data is currently in; any of: GL_RGB,
-    // GL_RGBA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, ...
-    int bufferFormat = glfmt(color_fmt);
-
-    // the format we want the texture to me on the card; allows us to translate
-    // into a different texture format as we upload to OpenGL
-    int internalFormat = bufferFormat;
-
-    /* glTexImage2D: Load a 2d texture image
-     * target: Creating this as a 2d texture.
-     * level: Which mipmap level to use as the "root" (0 = the highest-quality,
-     *  full-res image), if mipmaps are enabled.
-     * internalFormat: Type of texel format we want OpenGL to use for this
-     *  texture internally on the video card.
-     * width: Texel-width of image; for maximum compatibility, use 2^N + 2^B,
-     *  where N is some integer in the range [3,10], and B is the border
-     *  thickness [0,1]
-     * height: Texel-height of image; for maximum compatibility, use 2^M + 2^B,
-     *  where M is some integer in the range [3,10], and B is the border
-     *  thickness [0,1]
-     * border: Border size, in texels (must be 0 or 1)
-     * format: Pixel format describing the composition of the pixel data in
-     *  buffer
-     * type: Pixel color components are unsigned bytes (one byte per color/alpha
-     *  channel)
-     * pixels: Location of the actual pixel data bytes/buffer
-     */
-    glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, dimension.x(), dimension.y(),
-                 0, bufferFormat, GL_UNSIGNED_BYTE, data);
-
-    glGenerateMipmap(GL_TEXTURE_2D);
-
-    // Set magnification (texel > pixel) and minification (texel < pixel)
-    // filters one of: GL_NEAREST, GL_LINEAR
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    // one of: GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST,
-    // GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST,
-    // GL_LINEAR_MIPMAP_LINEAR
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
-                    GL_NEAREST_MIPMAP_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5);
-
-    return id;
-  }
-}}
+texture opengl_manager::compile(textures::format color, math::vec2i size,
+                                void const * buffer) const {
+  //  textures::external_data data(env::resource_file(path));
+  //  unsigned int init(format color_fmt, math::vec2i dimension,
+  //                    void const * data) {
+  unsigned int id;
+  // Enable texturings
+  //    glEnable( GL_TEXTURE_2D );
+
+  // Tell OpenGL that our pixel data is single-byte aligned
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+  // Ask OpenGL for an unused texName (ID number) to use for this texture
+  glGenTextures(1, &id);
+
+  // Tell OpenGL to bind (set) this as the currently active texture
+  glBindTexture(GL_TEXTURE_2D, id);
+  // Set texture clamp vs. wrap (repeat)
+
+  // one of: GL_CLAMP_TO_EDGE, GL_REPEAT, GL_MIRRORED_REPEAT,
+  // GL_MIRROR_CLAMP_TO_EDGE, ...
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+  // the format our source pixel data is currently in; any of: GL_RGB,
+  // GL_RGBA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, ...
+  int bufferFormat = glfmt(color);
+
+  // the format we want the texture to me on the card; allows us to translate
+  // into a different texture format as we upload to OpenGL
+  int internalFormat = bufferFormat;
+
+  /* glTexImage2D: Load a 2d texture image
+   * target: Creating this as a 2d texture.
+   * level: Which mipmap level to use as the "root" (0 = the highest-quality,
+   *  full-res image), if mipmaps are enabled.
+   * internalFormat: Type of texel format we want OpenGL to use for this
+   *  texture internally on the video card.
+   * width: Texel-width of image; for maximum compatibility, use 2^N + 2^B,
+   *  where N is some integer in the range [3,10], and B is the border
+   *  thickness [0,1]
+   * height: Texel-height of image; for maximum compatibility, use 2^M + 2^B,
+   *  where M is some integer in the range [3,10], and B is the border
+   *  thickness [0,1]
+   * border: Border size, in texels (must be 0 or 1)
+   * format: Pixel format describing the composition of the pixel data in
+   *  buffer
+   * type: Pixel color components are unsigned bytes (one byte per color/alpha
+   *  channel)
+   * pixels: Location of the actual pixel data bytes/buffer
+   */
+  glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, size.x(), size.y(), 0,
+               bufferFormat, GL_UNSIGNED_BYTE, buffer);
+
+  glGenerateMipmap(GL_TEXTURE_2D);
+
+  // Set magnification (texel > pixel) and minification (texel < pixel)
+  // filters one of: GL_NEAREST, GL_LINEAR
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+  // one of: GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST,
+  // GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST,
+  // GL_LINEAR_MIPMAP_LINEAR
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+                  GL_NEAREST_MIPMAP_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5);
+
+  return texture{id, size};
+}
 
 shader opengl_manager::compile(shaders::type tp,
                                std::string const & path) const {

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

@@ -27,7 +27,8 @@ namespace graphics {
     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;
+    texture compile(textures::format color, math::vec2i size,
+                    void const * buffer) const override;
 
     opengl_uniform_data & data(identity<shader_program> id);
 

+ 13 - 28
graphics/src/texture.cpp

@@ -25,44 +25,29 @@ unsigned char * stbi_load(char const *, int *, int *, int *, int);
 void stbi_image_free(void *);
 
 using namespace graphics;
+using namespace textures;
 
-static textures::format format(int comps) {
+static format as_format(int comps) {
   switch (comps) {
   case 3:
-    return textures::format::RGB;
+    return format::RGB;
   case 4:
-    return textures::format::RGBA;
+    return format::RGBA;
   default:
     throw;
   }
 }
 
-std::pair<unsigned int, math::vec2i> create(std::string const & path) {
+external_data::external_data(std::string const & rel_path) {
+  std::string abs_path = env::resource_file(rel_path);
   int components = 0;
-  math::vec2i size;
-  std::string file = env::resource_file(path);
-  auto data = stbi_load(file.c_str(), &size.x(), &size.y(), &components, 0);
-  scope(exit) { stbi_image_free(data); };
-  return {textures::init(format(components), size, data), size};
+  buffer = stbi_load(abs_path.c_str(), &size.x(), &size.y(), &components, 0);
+  color = as_format(components);
 }
 
-texture::texture(std::string const & path) : texture(create(path)) {}
-
-texture::texture(std::pair<unsigned int, math::vec2i> pair)
-    : identity<texture>(pair.first), size(pair.second) {}
-
-texture::texture(char const * data, math::vec2i size)
-    : identity<texture>(textures::init(format(4), size, data)), size(size) {}
-
-texture const & texture::WHITE() {
-  static auto t = texture("\xFF\xFF\xFF\xFF", {{1, 1}});
-  return t;
-}
-texture const & texture::DARK_YELLOW() {
-  static auto t = texture("\x80\x80\x00\xFF", {{1, 1}});
-  return t;
-}
-texture const & texture::LIGHT_BLUE() {
-  static auto t = texture("\x80\x80\xFF\xFF", {{1, 1}});
-  return t;
+external_data::~external_data() {
+  if (buffer) { stbi_image_free(buffer); }
 }
+
+texture::texture(unsigned int id, math::vec2i const & size)
+    : identity<texture>(id), size(size) {}