From a6fa3c1802cbd62ceb9d5d8d8073a58e6f7e3efe Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Thu, 10 Sep 2020 03:19:50 -0700 Subject: [PATCH] Add color space parameter to texture creation --- src/game/bootloader.cpp | 10 +++++---- src/rasterizer/color-space.hpp | 30 ++++++++++++++++++++++++++ src/rasterizer/texture-2d.cpp | 31 ++++++++++++++++++++++----- src/rasterizer/texture-2d.hpp | 31 +++++++++++++++++++++------ src/renderer/passes/material-pass.cpp | 11 ++++++++-- src/renderer/passes/material-pass.hpp | 9 +++++++- src/resources/texture-2d-loader.cpp | 5 ++++- 7 files changed, 107 insertions(+), 20 deletions(-) create mode 100644 src/rasterizer/color-space.hpp diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index aacfc1d..0f277a0 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -490,6 +490,7 @@ void setup_rendering(game_context* ctx) ctx->overworld_material_pass->set_fallback_material(ctx->fallback_material); ctx->overworld_material_pass->shadow_map_pass = ctx->overworld_shadow_map_pass; ctx->overworld_material_pass->shadow_map = ctx->shadow_map_depth_texture; + ctx->app->get_event_dispatcher()->subscribe(ctx->overworld_material_pass); ctx->overworld_outline_pass = new outline_pass(ctx->rasterizer, ctx->framebuffer_hdr, ctx->resource_manager); ctx->overworld_outline_pass->set_outline_width(0.25f); ctx->overworld_outline_pass->set_outline_color(float4{1.0f, 1.0f, 1.0f, 1.0f}); @@ -516,6 +517,7 @@ void setup_rendering(game_context* ctx) ctx->underworld_clear_pass->set_cleared_buffers(true, true, false); ctx->underworld_material_pass = new material_pass(ctx->rasterizer, ctx->framebuffer_hdr, ctx->resource_manager); ctx->underworld_material_pass->set_fallback_material(ctx->fallback_material); + ctx->app->get_event_dispatcher()->subscribe(ctx->underworld_material_pass); shader_program* underworld_final_shader = ctx->resource_manager->load("underground-final.glsl"); ctx->underworld_final_pass = new simple_render_pass(ctx->rasterizer, &ctx->rasterizer->get_default_framebuffer(), underworld_final_shader); ctx->underground_color_texture_property = ctx->underworld_final_pass->get_material()->add_property("color_texture"); @@ -875,8 +877,6 @@ void setup_systems(game_context* ctx) ctx->ui_system->set_tool_menu_control(ctx->control_system->get_tool_menu_control()); event_dispatcher->subscribe(ctx->ui_system); event_dispatcher->subscribe(ctx->ui_system); - - } void setup_controls(game_context* ctx) @@ -1167,9 +1167,8 @@ void setup_callbacks(game_context* ctx) ( [ctx](double t, double dt) { - // Update tweens - ctx->time_tween->update(); (*ctx->time_tween)[1] = t; + ctx->overworld_scene->update_tweens(); ctx->underworld_scene->update_tweens(); ctx->ui_scene->update_tweens(); @@ -1212,6 +1211,9 @@ void setup_callbacks(game_context* ctx) ctx->application_controls->update(); ctx->menu_controls->update(); ctx->camera_controls->update(); + + // Update tweens + ctx->time_tween->update(); } ); diff --git a/src/rasterizer/color-space.hpp b/src/rasterizer/color-space.hpp new file mode 100644 index 0000000..df1a4f4 --- /dev/null +++ b/src/rasterizer/color-space.hpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 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 . + */ + +#ifndef ANTKEEPER_COLOR_SPACE_HPP +#define ANTKEEPER_COLOR_SPACE_HPP + +enum class color_space +{ + linear, ///< Linear color space + srgb ///< sRGB color space +}; + +#endif // ANTKEEPER_COLOR_SPACE_HPP + diff --git a/src/rasterizer/texture-2d.cpp b/src/rasterizer/texture-2d.cpp index 0a07060..6f9184b 100644 --- a/src/rasterizer/texture-2d.cpp +++ b/src/rasterizer/texture-2d.cpp @@ -47,7 +47,7 @@ static constexpr GLenum pixel_type_lut[] = GL_FLOAT }; -static constexpr GLenum internal_format_lut[][8] = +static constexpr GLenum linear_internal_format_lut[][8] = { {GL_NONE, GL_NONE, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT32, GL_NONE, GL_DEPTH_COMPONENT32F}, @@ -60,7 +60,18 @@ static constexpr GLenum internal_format_lut[][8] = {GL_RGB8, GL_RGB8, GL_RGB16, GL_RGB16, GL_RGB32F, GL_RGB32F, GL_RGB16F, GL_RGB32F}, {GL_RGBA8, GL_RGBA8, GL_RGBA16, GL_RGBA16, GL_RGBA32F, GL_RGBA32F, GL_RGBA16F, GL_RGBA32F}, {GL_RGBA8, GL_RGBA8, GL_RGBA16, GL_RGBA16, GL_RGBA32F, GL_RGBA32F, GL_RGBA16F, GL_RGBA32F} +}; +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} }; static constexpr GLint swizzle_mask_lut[][4] = @@ -98,7 +109,7 @@ static constexpr GLenum mag_filter_lut[] = GL_LINEAR }; -texture_2d::texture_2d(int width, int height, ::pixel_type type, ::pixel_format format, const void* data): +texture_2d::texture_2d(int width, int height, ::pixel_type type, ::pixel_format format, ::color_space color_space, const void* data): gl_texture_id(0), dimensions({0, 0}), wrapping({texture_wrapping::repeat, texture_wrapping::repeat}), @@ -106,7 +117,7 @@ texture_2d::texture_2d(int width, int height, ::pixel_type type, ::pixel_format max_anisotropy(0.0f) { glGenTextures(1, &gl_texture_id); - resize(width, height, type, format, data); + resize(width, height, type, format, color_space, data); set_wrapping(std::get<0>(wrapping), std::get<1>(wrapping)); set_filters(std::get<0>(filters), std::get<1>(filters)); set_max_anisotropy(max_anisotropy); @@ -117,13 +128,23 @@ texture_2d::~texture_2d() glDeleteTextures(1, &gl_texture_id); } -void texture_2d::resize(int width, int height, ::pixel_type type, ::pixel_format format, const void* data) +void texture_2d::resize(int width, int height, ::pixel_type type, ::pixel_format format, ::color_space color_space, const void* data) { dimensions = {width, height}; pixel_type = type; pixel_format = format; + this->color_space = color_space; - GLenum gl_internal_format = internal_format_lut[static_cast(format)][static_cast(type)]; + GLenum gl_internal_format; + if (color_space == ::color_space::srgb) + { + gl_internal_format = srgb_internal_format_lut[static_cast(format)][static_cast(type)]; + } + else + { + gl_internal_format = linear_internal_format_lut[static_cast(format)][static_cast(type)]; + } + GLenum gl_format = pixel_format_lut[static_cast(format)]; const GLint* gl_swizzle_mask = swizzle_mask_lut[static_cast(format)]; diff --git a/src/rasterizer/texture-2d.hpp b/src/rasterizer/texture-2d.hpp index 24abba0..710345e 100644 --- a/src/rasterizer/texture-2d.hpp +++ b/src/rasterizer/texture-2d.hpp @@ -20,7 +20,9 @@ #ifndef ANTKEEPER_TEXTURE_2D_HPP #define ANTKEEPER_TEXTURE_2D_HPP +#include #include +#include "rasterizer/color-space.hpp" #include "rasterizer/pixel-format.hpp" #include "rasterizer/pixel-type.hpp" @@ -38,8 +40,12 @@ class texture_2d public: /** * Creates a 2D texture. + * + * @param color_space Specifies the color space of the pixel data. + * + * @warning If the sRGB color space is specified, pixel data will be stored internally as 8 bits per channel, and automatically converted to linear space before reading. */ - texture_2d(int width, int height, ::pixel_type type = ::pixel_type::uint_8, ::pixel_format format = ::pixel_format::rgba, const void* data = nullptr); + texture_2d(int width, int height, ::pixel_type type = ::pixel_type::uint_8, ::pixel_format format = ::pixel_format::rgba, ::color_space color_space = ::color_space::linear, const void* data = nullptr); /** * Destroys a 2D texture. @@ -48,8 +54,10 @@ public: /** * Resizes the texture. + * + * @warning If the sRGB color space is specified, pixel data will be stored internally as 8 bits per channel, and automatically converted to linear space before reading. */ - void resize(int width, int height, ::pixel_type type, ::pixel_format format, const void* data); + void resize(int width, int height, ::pixel_type type, ::pixel_format format, ::color_space color_space, const void* data); /** * Sets the texture wrapping modes. @@ -75,13 +83,16 @@ public: void set_max_anisotropy(float anisotropy); /// Returns the dimensions of the texture, in pixels. - const std::tuple& get_dimensions() const; + const std::array& get_dimensions() const; /// Returns the pixel type enumeration. const pixel_type& get_pixel_type() const; /// Returns the pixel format enumeration. const pixel_format& get_pixel_format() const; + + /// Returns the color space enumeration. + const color_space& get_color_space() const; /// Returns the wrapping modes of the texture. const std::tuple get_wrapping() const; @@ -89,7 +100,7 @@ public: /// Returns the filtering modes of the texture. const std::tuple get_filters() const; - /// Returs the maximum anisotropy. + /// Returns the maximum anisotropy. float get_max_anisotropy() const; private: @@ -97,15 +108,16 @@ private: friend class shader_input; unsigned int gl_texture_id; - std::tuple dimensions; + std::array dimensions; ::pixel_type pixel_type; ::pixel_format pixel_format; + ::color_space color_space; std::tuple wrapping; std::tuple filters; float max_anisotropy; }; -inline const std::tuple& texture_2d::get_dimensions() const +inline const std::array& texture_2d::get_dimensions() const { return dimensions; } @@ -114,12 +126,17 @@ inline const pixel_type& texture_2d::get_pixel_type() const { return pixel_type; } - + inline const pixel_format& texture_2d::get_pixel_format() const { return pixel_format; } +inline const color_space& texture_2d::get_color_space() const +{ + return color_space; +} + inline const std::tuple texture_2d::get_wrapping() const { return wrapping; diff --git a/src/renderer/passes/material-pass.cpp b/src/renderer/passes/material-pass.cpp index c389d8e..349c4d7 100644 --- a/src/renderer/passes/material-pass.cpp +++ b/src/renderer/passes/material-pass.cpp @@ -57,6 +57,7 @@ material_pass::material_pass(::rasterizer* rasterizer, const ::framebuffer* fram render_pass(rasterizer, framebuffer), fallback_material(nullptr), time_tween(nullptr), + mouse_position({0.0f, 0.0f}), focal_point_tween(nullptr), shadow_map_pass(nullptr), shadow_map(nullptr) @@ -415,6 +416,8 @@ void material_pass::render(render_context* context) const // Upload context-dependent shader parameters if (parameters->time) parameters->time->upload(time); + if (parameters->mouse) + parameters->mouse->upload(mouse_position); if (parameters->resolution) parameters->resolution->upload(resolution); if (parameters->view) @@ -513,6 +516,7 @@ const material_pass::parameter_set* material_pass::load_parameter_set(const shad // Connect inputs parameters->time = program->get_input("time"); + parameters->mouse = program->get_input("mouse"); parameters->resolution = program->get_input("resolution"); parameters->model = program->get_input("model"); parameters->view = program->get_input("view"); @@ -548,6 +552,11 @@ const material_pass::parameter_set* material_pass::load_parameter_set(const shad return parameters; } +void material_pass::handle_event(const mouse_moved_event& event) +{ + mouse_position = {static_cast(event.x), static_cast(event.y)}; +} + bool operation_compare(const render_operation& a, const render_operation& b) { if (!a.material) @@ -555,8 +564,6 @@ bool operation_compare(const render_operation& a, const render_operation& b) else if (!b.material) return true; - - bool xray_a = a.material->get_flags() & MATERIAL_FLAG_X_RAY; bool xray_b = b.material->get_flags() & MATERIAL_FLAG_X_RAY; diff --git a/src/renderer/passes/material-pass.hpp b/src/renderer/passes/material-pass.hpp index f91dde3..f4e3077 100644 --- a/src/renderer/passes/material-pass.hpp +++ b/src/renderer/passes/material-pass.hpp @@ -24,6 +24,8 @@ #include "renderer/material.hpp" #include "animation/tween.hpp" #include "utility/fundamental-types.hpp" +#include "event/event-handler.hpp" +#include "event/input-events.hpp" #include class camera; @@ -36,7 +38,8 @@ class shadow_map_pass; /** * Renders scene objects using their material-specified shaders and properties. */ -class material_pass: public render_pass +class material_pass: public render_pass, + public event_handler { public: material_pass(::rasterizer* rasterizer, const ::framebuffer* framebuffer, resource_manager* resource_manager); @@ -55,12 +58,15 @@ public: const texture_2d* shadow_map; private: + virtual void handle_event(const mouse_moved_event& event); + /** * Sets of known shader input parameters. Each time a new shader is encountered, a parameter set will be created and its inputs connected to the shader program. A null input indiciates that the shader doesn't have that parameter. */ struct parameter_set { const shader_input* time; + const shader_input* mouse; const shader_input* resolution; const shader_input* model; const shader_input* view; @@ -99,6 +105,7 @@ private: mutable std::unordered_map parameter_sets; const material* fallback_material; const tween* time_tween; + float2 mouse_position; const tween* focal_point_tween; texture_2d* soft_shadows_texture; diff --git a/src/resources/texture-2d-loader.cpp b/src/resources/texture-2d-loader.cpp index f86887f..0f1ae3a 100644 --- a/src/resources/texture-2d-loader.cpp +++ b/src/resources/texture-2d-loader.cpp @@ -58,9 +58,12 @@ texture_2d* resource_loader::load(resource_manager* resource_manager delete image; throw std::runtime_error(stream.str().c_str()); } + + // Assume linear color space + ::color_space color_space = ::color_space::linear; // Create texture - texture_2d* texture = new texture_2d(image->get_width(), image->get_height(), type, format, image->get_pixels()); + texture_2d* texture = new texture_2d(image->get_width(), image->get_height(), type, format, color_space, image->get_pixels()); // Free loaded image delete image;