| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- //
- // manager.cxx
- // graphics
- //
- // Created by Sam Jaffe on 5/25/19.
- // Copyright © 2019 Sam Jaffe. All rights reserved.
- //
- #include "game/graphics/manager.hpp"
- #include "game/graphics/material.hpp"
- #include "game/graphics/object.hpp"
- #include "game/graphics/shader.hpp"
- #include "game/graphics/shader_program.hpp"
- #include "game/graphics/texture.hpp"
- #include "game/math/shape.hpp"
- #include "game/util/hash.hpp"
- #include "helper.hpp"
- using namespace graphics;
- template <typename> struct key;
- template <typename T> using key_t = typename key<T>::type;
- template <> struct key<texture> { using type = std::string; };
- template <> struct key<shader> {
- using type = std::pair<shaders::type, std::string>;
- };
- template <> struct key<shader_program> {
- using type = std::pair<std::string, std::string>;
- };
- template <> struct key<material> {
- using type = std::tuple<identity<shader_program>, std::string, std::string>;
- };
- template <typename T> struct cache {
- identity<T> emplace(key_t<T> const & key, T && value);
- std::unordered_map<identity<T>, key_t<T>> keys;
- std::unordered_map<key_t<T>, T> values;
- };
- template <typename T>
- identity<T> cache<T>::emplace(key_t<T> const & key, T && value) {
- keys.emplace(value, key);
- return values.emplace(key, std::forward<T>(value)).first->second;
- }
- struct graphics::manager_impl {
- cache<material> materials;
- cache<shader> shaders;
- cache<shader_program> programs;
- cache<texture> textures;
- };
- manager::manager() : pimpl_(new manager_impl) {}
- manager::~manager() {}
- identity<material> manager::get(identity<shader_program> program,
- std::string const & texture,
- std::string const & uniform) const {
- auto key = std::make_tuple(program, texture, uniform);
- auto & cache = pimpl_->materials;
- auto found = cache.values.find(key);
- 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)});
- math::vec2i size = get(uniforms[0].texture).size;
- // if (!uniforms.empty()) { size = ...; }
- return cache.emplace(key, material(program, size, uniforms));
- }
- material const & manager::get(identity<material> identity) const {
- auto & cache = pimpl_->materials;
- return cache.values.find(cache.keys.find(identity)->second)->second;
- }
- texture const & manager::get(identity<texture> identity) const {
- auto & cache = pimpl_->textures;
- auto it = cache.keys.find(identity);
- if (it == cache.keys.end()) { return texture::WHITE(); }
- return cache.values.find(it->second)->second;
- }
- identity<shader> manager::get(shaders::type type,
- std::string const & path) const {
- auto key = std::make_pair(type, path);
- auto & cache = pimpl_->shaders;
- auto found = cache.values.find(key);
- if (found != cache.values.end()) { return found->second; }
- return cache.emplace(key, shader(type, path));
- }
- identity<texture>
- manager::texture_or_uniform(std::string const & path,
- std::string const & uniform) const {
- if (!path.empty()) {
- try {
- return get(path);
- } catch (std::exception const & e) {
- // 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();
- }
- throw;
- }
- identity<shader_program> manager::get(std::string const & fragment,
- std::string const & vertex) const {
- auto key = std::make_pair(fragment, vertex);
- auto & cache = pimpl_->programs;
- auto found = cache.values.find(key);
- if (found != cache.values.end()) { return found->second; }
- auto fragment_shader = get(shaders::type::FRAGMENT, fragment);
- auto vertex_shader = get(shaders::type::VERTEX, vertex);
- return cache.emplace(key, shader_program(fragment_shader, vertex_shader));
- }
- identity<texture> manager::get(std::string const & path) const {
- auto & cache = pimpl_->textures;
- auto found = cache.values.find(path);
- if (found != cache.values.end()) { return found->second; }
- return cache.emplace(path, texture(path));
- }
- object manager::create_object(identity<material> fromMaterial,
- math::vec2 atPosition,
- math::vec2 frameWidth) const {
- math::dim2::rectangle bounds{atPosition, frameWidth * get(fromMaterial).size};
- return {bounds, bounds, fromMaterial, {make_vector(0.f, 0.f), frameWidth}};
- }
|