Browse Source

Start adding renderer code.
- Define a batch renderer to minimize material-context switching.
- Move hash implementations to their own file in the gameutils toolkit.

Sam Jaffe 6 years ago
parent
commit
4086c6ca8c

+ 4 - 0
graphics/graphics.xcodeproj/project.pbxproj

@@ -16,6 +16,7 @@
 		CD62FCF82290DC9000376440 /* opengl_helper.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD62FCF62290DC9000376440 /* opengl_helper.cxx */; };
 		CD62FCFA2290E2E500376440 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD62FCF92290E2E500376440 /* OpenGL.framework */; };
 		CD62FD062291970F00376440 /* libgameutils.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CD62FD052291970F00376440 /* libgameutils.dylib */; };
+		CD62FD1E2292412900376440 /* renderer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD62FD1C2292412900376440 /* renderer.cxx */; };
 		CDA34D9A22517A3D008036A7 /* libmath.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CDA34D9922517A3D008036A7 /* libmath.dylib */; };
 /* End PBXBuildFile section */
 
@@ -62,6 +63,7 @@
 		CD62FCF62290DC9000376440 /* opengl_helper.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = opengl_helper.cxx; sourceTree = "<group>"; };
 		CD62FCF92290E2E500376440 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
 		CD62FD052291970F00376440 /* libgameutils.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; path = libgameutils.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		CD62FD1C2292412900376440 /* renderer.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = renderer.cxx; sourceTree = "<group>"; };
 		CDA34D86225171AA008036A7 /* game */ = {isa = PBXFileReference; lastKnownFileType = folder; name = game; path = include/game; sourceTree = "<group>"; };
 		CDA34D9922517A3D008036A7 /* libmath.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; path = libmath.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
@@ -136,6 +138,7 @@
 		CD62FD1A22923B8E00376440 /* renderer */ = {
 			isa = PBXGroup;
 			children = (
+				CD62FD1C2292412900376440 /* renderer.cxx */,
 			);
 			name = renderer;
 			sourceTree = "<group>";
@@ -278,6 +281,7 @@
 				CD3AC6FD1D2C06B5002B4BB0 /* shader.cpp in Sources */,
 				CD3AC7191D2C0950002B4BB0 /* shader_program.cpp in Sources */,
 				CD3AC6F21D2C03B7002B4BB0 /* material.cpp in Sources */,
+				CD62FD1E2292412900376440 /* renderer.cxx in Sources */,
 				CD3AC6F81D2C0518002B4BB0 /* texture.cpp in Sources */,
 				CD3AC7261D2C0C63002B4BB0 /* object.cpp in Sources */,
 				CD62FCF82290DC9000376440 /* opengl_helper.cxx in Sources */,

+ 4 - 3
graphics/include/game/graphics/object.hpp

@@ -9,11 +9,12 @@
 
 #include "game/math/math_fwd.hpp"
 #include "game/math/shape.hpp"
+#include "game/util/flyweight.hpp"
 #include "vector/vector.hpp"
 
-#include "material.hpp"
-
 namespace graphics {
+  class material;
+
   struct bound {
     math::vec2 corner;
     math::vec2 size;
@@ -22,7 +23,7 @@ namespace graphics {
   struct object {
     bound location;
     math::dim2::quad points;
-    material material;
+    flyweight<material> material;
     bound frame;
   }; // size:56, align:4
 }

+ 60 - 0
graphics/include/game/graphics/renderer.hpp

@@ -0,0 +1,60 @@
+//
+//  renderer.hpp
+//  graphics
+//
+//  Created by Sam Jaffe on 5/19/19.
+//  Copyright © 2019 Sam Jaffe. All rights reserved.
+//
+
+#pragma once
+
+#include "game/math/math_fwd.hpp"
+#include "game/util/flyweight.hpp"
+#include "game/util/hash.hpp"
+#include "vector/vector.hpp"
+
+namespace graphics {
+  class material;
+  class renderer_impl;
+  struct vertex;
+
+  class renderer {
+  public:
+    virtual ~renderer() {}
+    virtual void draw(flyweight<material>, math::matr4 const &,
+                      std::vector<vertex> const &) = 0;
+    virtual void clear() = 0;
+    virtual void flush() = 0;
+  };
+
+  class direct_renderer : public renderer {
+  public:
+    direct_renderer(renderer_impl * impl) : pimpl(impl) {}
+    void draw(flyweight<material>, math::matr4 const &,
+              std::vector<vertex> const &) override;
+    void clear() override;
+    void flush() override;
+
+  private:
+    renderer_impl * pimpl;
+  };
+
+  class batch_renderer : public renderer {
+  public:
+    batch_renderer(renderer * impl, std::size_t batch_size = 0);
+    void draw(flyweight<material>, math::matr4 const &,
+              std::vector<vertex> const &) override;
+    void clear() override { impl_->clear(); }
+    void flush() override;
+
+  private:
+    void check();
+    void write();
+
+  private:
+    renderer * impl_;
+    std::unordered_map<flyweight<material>, std::vector<vertex>> batches_;
+    std::size_t batch_size_;
+    std::size_t elements_;
+  };
+}

+ 0 - 36
graphics/src/helper.hpp

@@ -43,40 +43,4 @@ namespace std {
       return std::hash<unsigned int>()(static_cast<unsigned int>(tp));
     }
   };
-
-  template <typename T> struct hash<flyweight<T>> {
-    std::size_t operator()(flyweight<T> tp) const {
-      return std::hash<unsigned int>()(tp.id);
-    }
-  };
-
-  template <typename T, typename S> struct hash<std::pair<T, S>> {
-    std::size_t operator()(std::pair<T, S> const & pair) const {
-      return std::hash<T>()(pair.first) ^ std::hash<S>()(pair.second);
-    }
-  };
-
-  template <std::size_t I> struct tuple_hash;
-
-  template <> struct tuple_hash<0> {
-    template <typename... As>
-    std::size_t operator()(std::tuple<As...> const &) const {
-      return 0;
-    }
-  };
-
-  template <std::size_t I> struct tuple_hash {
-    template <typename... As>
-    std::size_t operator()(std::tuple<As...> const & tuple) const {
-      using elt = typename std::tuple_element<I - 1, std::tuple<As...>>::type;
-      return std::hash<elt>()(std::get<I - 1>(tuple)) ^
-             tuple_hash<I - 1>()(tuple);
-    }
-  };
-
-  template <typename... As> struct hash<std::tuple<As...>> {
-    std::size_t operator()(std::tuple<As...> const & tuple) const {
-      return tuple_hash<sizeof...(As)>()(tuple);
-    }
-  };
 }

+ 1 - 0
graphics/src/material.cpp

@@ -8,6 +8,7 @@
 #include "game/graphics/material.hpp"
 
 #include "game/graphics/texture.hpp"
+#include "game/util/hash.hpp"
 #include "helper.hpp"
 
 using namespace graphics;

+ 48 - 0
graphics/src/renderer.cxx

@@ -0,0 +1,48 @@
+//
+//  renderer.cxx
+//  graphics
+//
+//  Created by Sam Jaffe on 5/19/19.
+//  Copyright © 2019 Sam Jaffe. All rights reserved.
+//
+
+#include "game/graphics/renderer.hpp"
+#include <vector>
+
+#include "matrix/matrix.hpp"
+
+using namespace graphics;
+
+// TODO (sjaffe): Move to own file
+struct graphics::vertex {
+  math::vec2 position, texture_coords;
+  math::vector::vector<unsigned char, 4> color;
+};
+
+batch_renderer::batch_renderer(renderer * impl, std::size_t batch_size)
+    : impl_(impl), batches_(), batch_size_(batch_size), elements_(0) {}
+
+// TODO (sjaffe): object-to-world matrix...
+void batch_renderer::draw(flyweight<material> material, math::matr4 const &,
+                          std::vector<vertex> const & verts) {
+  auto & batch_verts = batches_[material];
+  batch_verts.insert(batch_verts.end(), verts.begin(), verts.end());
+  check();
+}
+
+void batch_renderer::flush() {
+  write();
+  impl_->flush();
+}
+
+void batch_renderer::check() {
+  if (batch_size_ && elements_ >= batch_size_) { write(); }
+}
+
+void batch_renderer::write() {
+  for (auto & pair : batches_) {
+    impl_->draw(pair.first, math::matr4(), pair.second);
+  }
+  batches_.clear();
+  elements_ = 0;
+}

+ 1 - 0
graphics/src/shader.cpp

@@ -9,6 +9,7 @@
 
 #include <unordered_map>
 
+#include "game/util/hash.hpp"
 #include "helper.hpp"
 
 using namespace graphics;

+ 1 - 0
graphics/src/shader_program.cpp

@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "game/graphics/shader.hpp"
+#include "game/util/hash.hpp"
 #include "helper.hpp"
 
 using namespace graphics;

+ 1 - 0
graphics/src/texture.cpp

@@ -17,6 +17,7 @@
 #include "stb/stb_image.h"
 #pragma clang diagnostic pop
 
+#include "game/util/hash.hpp"
 #include "helper.hpp"
 
 unsigned char * stbi_load(char const *, int *, int *, int *, int);

+ 52 - 0
util/include/game/util/hash.hpp

@@ -0,0 +1,52 @@
+//
+//  hash.hpp
+//  gameutils
+//
+//  Created by Sam Jaffe on 5/19/19.
+//  Copyright © 2019 Sam Jaffe. All rights reserved.
+//
+
+#pragma once
+
+#include <tuple>
+#include <utility>
+
+template <typename> class flyweight;
+
+namespace std {
+  template <typename T> struct hash<flyweight<T>> {
+    std::size_t operator()(flyweight<T> tp) const {
+      return std::hash<unsigned int>()(tp.id);
+    }
+  };
+
+  template <typename T, typename S> struct hash<std::pair<T, S>> {
+    std::size_t operator()(std::pair<T, S> const & pair) const {
+      return std::hash<T>()(pair.first) ^ std::hash<S>()(pair.second);
+    }
+  };
+
+  template <std::size_t I> struct tuple_hash;
+
+  template <> struct tuple_hash<0> {
+    template <typename... As>
+    std::size_t operator()(std::tuple<As...> const &) const {
+      return 0;
+    }
+  };
+
+  template <std::size_t I> struct tuple_hash {
+    template <typename... As>
+    std::size_t operator()(std::tuple<As...> const & tuple) const {
+      using elt = typename std::tuple_element<I - 1, std::tuple<As...>>::type;
+      return std::hash<elt>()(std::get<I - 1>(tuple)) ^
+             tuple_hash<I - 1>()(tuple);
+    }
+  };
+
+  template <typename... As> struct hash<std::tuple<As...>> {
+    std::size_t operator()(std::tuple<As...> const & tuple) const {
+      return tuple_hash<sizeof...(As)>()(tuple);
+    }
+  };
+}