Browse Source

Add loader for JSON texture data

master
C. J. Howard 9 months ago
parent
commit
b1b1dbd62f
9 changed files with 174 additions and 165 deletions
  1. +1
    -0
      CMakeLists.txt
  2. +15
    -25
      src/game/bootloader.cpp
  3. +9
    -8
      src/gl/texture-2d.cpp
  4. +2
    -1
      src/gl/texture-wrapping.hpp
  5. +1
    -3
      src/renderer/passes/material-pass.cpp
  6. +1
    -1
      src/resources/biome-loader.cpp
  7. +2
    -55
      src/resources/material-loader.cpp
  8. +0
    -72
      src/resources/texture-2d-loader.cpp
  9. +143
    -0
      src/resources/texture-loader.cpp

+ 1
- 0
CMakeLists.txt View File

@ -4,6 +4,7 @@ option(VERSION_STRING "Project version string" "0.0.0")
project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX)
# Find dependency packages
find_package(dr_wav REQUIRED CONFIG)
find_package(stb REQUIRED CONFIG)

+ 15
- 25
src/game/bootloader.cpp View File

@ -336,6 +336,7 @@ void setup_resources(game_context* ctx)
// Include resource search paths in order of priority
ctx->resource_manager->include("/shaders/");
ctx->resource_manager->include("/models/");
ctx->resource_manager->include("/images/");
ctx->resource_manager->include("/textures/");
ctx->resource_manager->include("/materials/");
ctx->resource_manager->include("/entities/");
@ -448,11 +449,11 @@ void setup_rendering(game_context* ctx)
// Create HDR framebuffer (32F color, 32F depth)
ctx->framebuffer_hdr_color = new gl::texture_2d(viewport_dimensions[0], viewport_dimensions[1], gl::pixel_type::float_32, gl::pixel_format::rgb);
ctx->framebuffer_hdr_color->set_wrapping(gl::texture_wrapping::clamp, gl::texture_wrapping::clamp);
ctx->framebuffer_hdr_color->set_wrapping(gl::texture_wrapping::extend, gl::texture_wrapping::extend);
ctx->framebuffer_hdr_color->set_filters(gl::texture_min_filter::linear, gl::texture_mag_filter::linear);
ctx->framebuffer_hdr_color->set_max_anisotropy(0.0f);
ctx->framebuffer_hdr_depth = new gl::texture_2d(viewport_dimensions[0], viewport_dimensions[1], gl::pixel_type::float_32, gl::pixel_format::ds);
ctx->framebuffer_hdr_depth->set_wrapping(gl::texture_wrapping::clamp, gl::texture_wrapping::clamp);
ctx->framebuffer_hdr_depth->set_wrapping(gl::texture_wrapping::extend, gl::texture_wrapping::extend);
ctx->framebuffer_hdr_depth->set_filters(gl::texture_min_filter::linear, gl::texture_mag_filter::linear);
ctx->framebuffer_hdr_depth->set_max_anisotropy(0.0f);
ctx->framebuffer_hdr = new gl::framebuffer(viewport_dimensions[0], viewport_dimensions[1]);
@ -467,7 +468,7 @@ void setup_rendering(game_context* ctx)
shadow_map_resolution = ctx->config->get<int>("shadow_map_resolution");
}
ctx->shadow_map_depth_texture = new gl::texture_2d(shadow_map_resolution, shadow_map_resolution, gl::pixel_type::float_32, gl::pixel_format::d);
ctx->shadow_map_depth_texture->set_wrapping(gl::texture_wrapping::clamp, gl::texture_wrapping::clamp);
ctx->shadow_map_depth_texture->set_wrapping(gl::texture_wrapping::extend, gl::texture_wrapping::extend);
ctx->shadow_map_depth_texture->set_filters(gl::texture_min_filter::linear, gl::texture_mag_filter::linear);
ctx->shadow_map_depth_texture->set_max_anisotropy(0.0f);
ctx->shadow_map_framebuffer = new gl::framebuffer(shadow_map_resolution, shadow_map_resolution);
@ -477,18 +478,14 @@ void setup_rendering(game_context* ctx)
int bloom_width = viewport_dimensions[0] >> 1;
int bloom_height = viewport_dimensions[1] >> 1;
ctx->bloom_texture = new gl::texture_2d(bloom_width, bloom_height, gl::pixel_type::float_16, gl::pixel_format::rgb);
ctx->bloom_texture->set_wrapping(gl::texture_wrapping::clamp, gl::texture_wrapping::clamp);
ctx->bloom_texture->set_wrapping(gl::texture_wrapping::extend, gl::texture_wrapping::extend);
ctx->bloom_texture->set_filters(gl::texture_min_filter::linear, gl::texture_mag_filter::linear);
ctx->bloom_texture->set_max_anisotropy(0.0f);
ctx->framebuffer_bloom = new gl::framebuffer(bloom_width, bloom_height);
ctx->framebuffer_bloom->attach(gl::framebuffer_attachment_type::color, ctx->bloom_texture);
// Load blue noise texture
gl::texture_2d* blue_noise_map = ctx->resource_manager->load<gl::texture_2d>("blue-noise.png");
blue_noise_map->set_wrapping(gl::texture_wrapping::repeat, gl::texture_wrapping::repeat);
blue_noise_map->set_wrapping(gl::texture_wrapping::repeat, gl::texture_wrapping::repeat);
blue_noise_map->set_filters(gl::texture_min_filter::nearest, gl::texture_mag_filter::nearest);
blue_noise_map->set_filters(gl::texture_min_filter::nearest, gl::texture_mag_filter::nearest);
gl::texture_2d* blue_noise_map = ctx->resource_manager->load<gl::texture_2d>("blue-noise.tex");
// Load fallback material
ctx->fallback_material = ctx->resource_manager->load<material>("fallback.mtl");
@ -583,21 +580,14 @@ void setup_rendering(game_context* ctx)
// Load marker albedo textures
ctx->marker_albedo_textures = new gl::texture_2d*[8];
ctx->marker_albedo_textures[0] = ctx->resource_manager->load<gl::texture_2d>("marker-clear-albedo.png");
ctx->marker_albedo_textures[1] = ctx->resource_manager->load<gl::texture_2d>("marker-yellow-albedo.png");
ctx->marker_albedo_textures[2] = ctx->resource_manager->load<gl::texture_2d>("marker-green-albedo.png");
ctx->marker_albedo_textures[3] = ctx->resource_manager->load<gl::texture_2d>("marker-blue-albedo.png");
ctx->marker_albedo_textures[4] = ctx->resource_manager->load<gl::texture_2d>("marker-purple-albedo.png");
ctx->marker_albedo_textures[5] = ctx->resource_manager->load<gl::texture_2d>("marker-pink-albedo.png");
ctx->marker_albedo_textures[6] = ctx->resource_manager->load<gl::texture_2d>("marker-red-albedo.png");
ctx->marker_albedo_textures[7] = ctx->resource_manager->load<gl::texture_2d>("marker-orange-albedo.png");
for (int i = 0; i < 8; ++i)
{
gl::texture_2d* texture = ctx->marker_albedo_textures[i];
texture->set_wrapping(gl::texture_wrapping::clamp, gl::texture_wrapping::clamp);
texture->set_filters(gl::texture_min_filter::nearest, gl::texture_mag_filter::nearest);
texture->set_max_anisotropy(0.0f);
}
ctx->marker_albedo_textures[0] = ctx->resource_manager->load<gl::texture_2d>("marker-clear-albedo.tex");
ctx->marker_albedo_textures[1] = ctx->resource_manager->load<gl::texture_2d>("marker-yellow-albedo.tex");
ctx->marker_albedo_textures[2] = ctx->resource_manager->load<gl::texture_2d>("marker-green-albedo.tex");
ctx->marker_albedo_textures[3] = ctx->resource_manager->load<gl::texture_2d>("marker-blue-albedo.tex");
ctx->marker_albedo_textures[4] = ctx->resource_manager->load<gl::texture_2d>("marker-purple-albedo.tex");
ctx->marker_albedo_textures[5] = ctx->resource_manager->load<gl::texture_2d>("marker-pink-albedo.tex");
ctx->marker_albedo_textures[6] = ctx->resource_manager->load<gl::texture_2d>("marker-red-albedo.tex");
ctx->marker_albedo_textures[7] = ctx->resource_manager->load<gl::texture_2d>("marker-orange-albedo.tex");
// Create renderer
ctx->renderer = new renderer();
@ -668,7 +658,7 @@ void setup_scenes(game_context* ctx)
const gl::texture_2d* splash_texture = ctx->resource_manager->load<gl::texture_2d>("splash.png");
const gl::texture_2d* splash_texture = ctx->resource_manager->load<gl::texture_2d>("splash.tex");
auto splash_dimensions = splash_texture->get_dimensions();
ctx->splash_billboard_material = new material();
ctx->splash_billboard_material->set_shader_program(ctx->resource_manager->load<gl::shader_program>("ui-element-textured.glsl"));

+ 9
- 8
src/gl/texture-2d.cpp View File

@ -66,14 +66,14 @@ static constexpr GLenum linear_internal_format_lut[][8] =
static constexpr GLenum srgb_internal_format_lut[][8] =
{
{GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8},
{GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8},
{GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8},
{GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8},
{GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8},
{GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8, GL_SRGB8},
{GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8},
{GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8}
{GL_NONE, GL_NONE, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT32, GL_NONE, GL_DEPTH_COMPONENT32F},
{GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, GL_NONE, GL_DEPTH32F_STENCIL8},
{GL_SRGB8, GL_SRGB8, GL_R16, GL_R16, GL_R32F, GL_R32F, GL_R16F, GL_R32F},
{GL_SRGB8, GL_SRGB8, GL_RG16, GL_RG16, GL_RG32F, GL_RG32F, GL_RG16F, GL_RG32F},
{GL_SRGB8, GL_SRGB8, GL_RGB16, GL_RGB16, GL_RGB32F, GL_RGB32F, GL_RGB16F, GL_RGB32F},
{GL_SRGB8, GL_SRGB8, GL_RGB16, GL_RGB16, GL_RGB32F, GL_RGB32F, GL_RGB16F, GL_RGB32F},
{GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_RGBA16, GL_RGBA16, GL_RGBA32F, GL_RGBA32F, GL_RGBA16F, GL_RGBA32F},
{GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GL_RGBA16, GL_RGBA16, GL_RGBA32F, GL_RGBA32F, GL_RGBA16F, GL_RGBA32F}
};
static constexpr GLint swizzle_mask_lut[][4] =
@ -90,6 +90,7 @@ static constexpr GLint swizzle_mask_lut[][4] =
static constexpr GLenum wrapping_lut[] =
{
GL_CLAMP_TO_BORDER,
GL_CLAMP_TO_EDGE,
GL_REPEAT,
GL_MIRRORED_REPEAT

+ 2
- 1
src/gl/texture-wrapping.hpp View File

@ -24,7 +24,8 @@ namespace gl {
enum class texture_wrapping
{
clamp,
clip,
extend,
repeat,
mirrored_repeat
};

+ 1
- 3
src/renderer/passes/material-pass.cpp View File

@ -62,9 +62,7 @@ material_pass::material_pass(gl::rasterizer* rasterizer, const gl::framebuffer*
shadow_map(nullptr),
shadow_strength(1.0f)
{
soft_shadows_texture = resource_manager->load<gl::texture_2d>("tree-shadow.png");
soft_shadows_texture->set_wrapping(gl::texture_wrapping::clamp, gl::texture_wrapping::clamp);
soft_shadows_texture->set_filters(gl::texture_min_filter::linear_mipmap_linear, gl::texture_mag_filter::linear);
soft_shadows_texture = resource_manager->load<gl::texture_2d>("forest-gobo.tex");
max_ambient_light_count = MATERIAL_PASS_MAX_AMBIENT_LIGHT_COUNT;
max_point_light_count = MATERIAL_PASS_MAX_POINT_LIGHT_COUNT;

+ 1
- 1
src/resources/biome-loader.cpp View File

@ -44,7 +44,7 @@ static bool load_array(T* value, std::size_t size, const nlohmann::json& json, c
std::size_t i = 0;
for (auto it = element.value().cbegin(); (it != element.value().cend()) && (i < size); ++it)
{
*(value++) = it.value().get<float>();
*(value++) = it.value().get<T>();
++i;
}

+ 2
- 55
src/resources/material-loader.cpp View File

@ -30,29 +30,6 @@
#include <vector>
#include <map>
static const std::map<std::string, gl::texture_wrapping> texture_wrapping_map =
{
{"clamp", gl::texture_wrapping::clamp},
{"repeat", gl::texture_wrapping::repeat},
{"mirrored_repeat", gl::texture_wrapping::mirrored_repeat},
};
static const std::map<std::string, gl::texture_min_filter> texture_min_filter_map =
{
{"nearest", gl::texture_min_filter::nearest},
{"linear", gl::texture_min_filter::linear},
{"nearest_mipmap_nearest", gl::texture_min_filter::nearest_mipmap_nearest},
{"linear_mipmap_nearest", gl::texture_min_filter::linear_mipmap_nearest},
{"nearest_mipmap_linear", gl::texture_min_filter::nearest_mipmap_linear},
{"linear_mipmap_linear", gl::texture_min_filter::linear_mipmap_linear}
};
static const std::map<std::string, gl::texture_mag_filter> texture_mag_filter_map =
{
{"nearest", gl::texture_mag_filter::nearest},
{"linear", gl::texture_mag_filter::linear},
};
static bool load_bool_property(material* material, const string_table_row& row, int vector_size, int array_size)
{
if (row.size() - 4 != vector_size * array_size || vector_size < 1 || vector_size > 4)
@ -252,7 +229,7 @@ static bool load_float_matrix_property(material* material, const string_table_ro
static bool load_texture_2d_property(material* material, const string_table_row& row, resource_manager* resource_manager, int array_size)
{
if (row.size() - 4 != array_size * 6)
if (row.size() - 4 != array_size * 1)
{
return false;
}
@ -260,37 +237,7 @@ static bool load_texture_2d_property(material* material, const string_table_row&
const gl::texture_2d** values = new const gl::texture_2d*[array_size];
for (std::size_t i = 0; i < array_size; ++i)
{
std::size_t offset = 4 + i;
const std::string& filename = row[offset];
gl::texture_wrapping wrap_s = gl::texture_wrapping::clamp;
gl::texture_wrapping wrap_t = gl::texture_wrapping::clamp;
gl::texture_min_filter min_filter = gl::texture_min_filter::linear_mipmap_linear;
gl::texture_mag_filter mag_filter = gl::texture_mag_filter::linear;
if (auto it = texture_wrapping_map.find(row[offset + 1]); it != texture_wrapping_map.end())
{
wrap_s = it->second;
}
if (auto it = texture_wrapping_map.find(row[offset + 2]); it != texture_wrapping_map.end())
{
wrap_t = it->second;
}
if (auto it = texture_min_filter_map.find(row[offset + 3]); it != texture_min_filter_map.end())
{
min_filter = it->second;
}
if (auto it = texture_mag_filter_map.find(row[offset + 4]); it != texture_mag_filter_map.end())
{
mag_filter = it->second;
}
float max_anisotropy = static_cast<float>(std::stod(row[offset + 5]));
gl::texture_2d* texture = resource_manager->load<gl::texture_2d>(row[4 + i]);
texture->set_wrapping(wrap_s, wrap_t);
texture->set_filters(min_filter, mag_filter);
texture->set_max_anisotropy(max_anisotropy);
values[i] = texture;
values[i] = resource_manager->load<gl::texture_2d>(row[4 + i]);
}
material_property<const gl::texture_2d*>* property = material->add_property<const gl::texture_2d*>(row[1], array_size);

+ 0
- 72
src/resources/texture-2d-loader.cpp View File

@ -1,72 +0,0 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "resources/resource-loader.hpp"
#include "resources/image.hpp"
#include "gl/pixel-type.hpp"
#include "gl/pixel-format.hpp"
#include "gl/texture-2d.hpp"
#include <sstream>
template <>
gl::texture_2d* resource_loader<gl::texture_2d>::load(resource_manager* resource_manager, PHYSFS_File* file)
{
// Load image
::image* image = resource_loader<::image>::load(resource_manager, file);
// Determine pixel type
gl::pixel_type type = (image->is_hdr()) ? gl::pixel_type::float_32 : gl::pixel_type::uint_8;
// Determine pixel format
gl::pixel_format format;
if (image->get_channels() == 1)
{
format = gl::pixel_format::r;
}
else if (image->get_channels() == 2)
{
format = gl::pixel_format::rg;
}
else if (image->get_channels() == 3)
{
format = gl::pixel_format::rgb;
}
else if (image->get_channels() == 4)
{
format = gl::pixel_format::rgba;
}
else
{
std::stringstream stream;
stream << std::string("Texture cannot be created from an image with an unsupported number of color channels (") << image->get_channels() << std::string(").");
delete image;
throw std::runtime_error(stream.str().c_str());
}
// Assume linear color space
gl::color_space color_space = gl::color_space::linear;
// Create texture
gl::texture_2d* texture = new gl::texture_2d(image->get_width(), image->get_height(), type, format, color_space, image->get_pixels());
// Free loaded image
delete image;
return texture;
}

+ 143
- 0
src/resources/texture-loader.cpp View File

@ -0,0 +1,143 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "resources/resource-loader.hpp"
#include "resources/resource-manager.hpp"
#include "resources/image.hpp"
#include "gl/pixel-type.hpp"
#include "gl/pixel-format.hpp"
#include "gl/color-space.hpp"
#include "gl/texture-2d.hpp"
#include "gl/texture-wrapping.hpp"
#include "gl/texture-filter.hpp"
#include <sstream>
#include <nlohmann/json.hpp>
#include <physfs.h>
template <>
gl::texture_2d* resource_loader<gl::texture_2d>::load(resource_manager* resource_manager, PHYSFS_File* file)
{
// Read file into buffer
std::size_t size = static_cast<int>(PHYSFS_fileLength(file));
std::string buffer;
buffer.resize(size);
PHYSFS_readBytes(file, &buffer[0], size);
// Parse json from file buffer
nlohmann::json json = nlohmann::json::parse(buffer);
// Read image filename
std::string image_filename;
if (auto element = json.find("image"); element != json.end())
image_filename = element.value().get<std::string>();
// Read color space
gl::color_space color_space = gl::color_space::linear;
if (auto element = json.find("color_space"); element != json.end())
{
std::string value = element.value().get<std::string>();
if (value == "linear")
color_space = gl::color_space::linear;
else if (value == "srgb")
color_space = gl::color_space::srgb;
}
// Read extension mode
gl::texture_wrapping wrapping = gl::texture_wrapping::repeat;
if (auto element = json.find("extension"); element != json.end())
{
std::string value = element.value().get<std::string>();
if (value == "clip")
wrapping = gl::texture_wrapping::clip;
else if (value == "extend")
wrapping = gl::texture_wrapping::extend;
else if (value == "repeat")
wrapping = gl::texture_wrapping::repeat;
else if (value == "mirrored_repeat")
wrapping = gl::texture_wrapping::mirrored_repeat;
}
// Read interpolation mode
gl::texture_min_filter min_filter = gl::texture_min_filter::linear_mipmap_linear;
gl::texture_mag_filter mag_filter = gl::texture_mag_filter::linear;
if (auto element = json.find("interpolation"); element != json.end())
{
std::string value = element.value().get<std::string>();
if (value == "linear")
{
min_filter = gl::texture_min_filter::linear_mipmap_linear;
mag_filter = gl::texture_mag_filter::linear;
}
else if (value == "closest")
{
min_filter = gl::texture_min_filter::nearest_mipmap_nearest;
mag_filter = gl::texture_mag_filter::nearest;
}
}
// Read max anisotropy
float max_anisotropy = 0.0f;
if (auto element = json.find("max_anisotropy"); element != json.end())
max_anisotropy = element.value().get<float>();
// Load image
::image* image = resource_manager->load<::image>(image_filename);
// Determine pixel type
gl::pixel_type type = (image->is_hdr()) ? gl::pixel_type::float_32 : gl::pixel_type::uint_8;
// Determine pixel format
gl::pixel_format format;
if (image->get_channels() == 1)
{
format = gl::pixel_format::r;
}
else if (image->get_channels() == 2)
{
format = gl::pixel_format::rg;
}
else if (image->get_channels() == 3)
{
format = gl::pixel_format::rgb;
}
else if (image->get_channels() == 4)
{
format = gl::pixel_format::rgba;
}
else
{
std::stringstream stream;
stream << std::string("Texture cannot be created from an image with an unsupported number of color channels (") << image->get_channels() << std::string(").");
delete image;
throw std::runtime_error(stream.str().c_str());
}
// Create texture
gl::texture_2d* texture = new gl::texture_2d(image->get_width(), image->get_height(), type, format, color_space, image->get_pixels());
// Set wrapping and filtering
texture->set_wrapping(wrapping, wrapping);
texture->set_filters(min_filter, mag_filter);
texture->set_max_anisotropy(max_anisotropy);
// Free loaded image
resource_manager->unload(image_filename);
return texture;
}

Loading…
Cancel
Save