| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- //
- // 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/exception.h"
- #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_cache {
- cache<material> materials;
- cache<shader> shaders;
- cache<shader_program> programs;
- cache<texture> textures;
- };
- 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 unmapped_enum<materials::uniform>(uniform);
- }
- 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 = pcache_->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), uniform_id(uniform)});
- math::vec2i size = get(uniforms[0].texture).size;
- // if (!uniforms.empty()) { size = ...; }
- return cache.emplace(key, material(program, size, uniforms));
- }
- identity<shader> manager::get(shaders::type type,
- std::string const & path) const {
- auto key = std::make_pair(type, path);
- auto & cache = pcache_->shaders;
- auto found = cache.values.find(key);
- if (found != cache.values.end()) { return found->second; }
- return cache.emplace(key, compile(type, path));
- }
- identity<shader_program> manager::get(std::string const & fragment,
- std::string const & vertex) const {
- auto key = std::make_pair(fragment, vertex);
- auto & cache = pcache_->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, compile(fragment_shader, vertex_shader));
- }
- 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; }
- textures::external_data data(path);
- return cache.emplace(path, compile(data.color, data.size, data.buffer));
- }
- object manager::create_object(identity<material> fromMaterial,
- math::vec2 atPosition, math::vec2 frameWidth,
- float scale) const {
- math::dim2::rectangle bounds{atPosition, frameWidth * get(fromMaterial).size *
- (scale ? scale : 1.f)};
- return {bounds, bounds, fromMaterial, {make_vector(0.f, 0.f), frameWidth}};
- }
- material const & manager::get(identity<material> identity) const {
- auto & cache = pcache_->materials;
- return cache.values.find(cache.keys.find(identity)->second)->second;
- }
- 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(); }
- 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 {
- if (!path.empty()) {
- try {
- return get(path);
- } catch (std::exception const & e) {
- // TODO: Logging
- }
- }
- prepare_uniforms();
- // The uniform is primed into the cache already.
- auto & cache = pcache_->textures;
- return cache.values.find(uniform)->second;
- }
|