Commit 8c03e399 authored by Johannes Braun's avatar Johannes Braun
Browse files

Added image difference heatmap generator executable

parent e2dc4cc2
......@@ -10,12 +10,62 @@ layout(rgba32f) uniform image2D u_result_heatmap;
layout(local_size_variable) in;
vec4 colormap_hsv2rgb(float h, float s, float v) {
float r = v;
float g = v;
float b = v;
if (s > 0.0) {
h *= 6.0;
int i = int(h);
float f = h - float(i);
if (i == 1) {
r *= 1.0 - s * f;
b *= 1.0 - s;
} else if (i == 2) {
r *= 1.0 - s;
b *= 1.0 - s * (1.0 - f);
} else if (i == 3) {
r *= 1.0 - s;
g *= 1.0 - s * f;
} else if (i == 4) {
r *= 1.0 - s * (1.0 - f);
g *= 1.0 - s;
} else if (i == 5) {
g *= 1.0 - s;
b *= 1.0 - s * f;
} else {
g *= 1.0 - s * (1.0 - f);
b *= 1.0 - s;
}
}
return vec4(r, g, b, 1.0);
}
vec4 colormap(float x) {
if (x < 0.0) {
return vec4(0.0, 0.0, 0.0, 1.0);
} else if (1.0 < x) {
return vec4(0.0, 0.0, 0.0, 1.0);
} else {
float h = clamp(-9.42274071356572E-01 * x + 8.74326827903982E-01, 0.0, 1.0);
float s = 1.0;
float v = clamp(4.90125513855204E+00 * x + 9.18879034690780E-03, 0.0, 1.0);
return colormap_hsv2rgb(h, s, v);
}
}
void main()
{
ivec2 pixel = ivec2(gl_GlobalInvocationID.xy);
vec4 pixel_first = u_first_image.imageLoad(pixel);
vec4 pixel_second = u_second_image.imageLoad(pixel);
vec4 diff = abs(pixel_first - pixel_second);
float val = length(diff);
vec3 color = colormap(val).xyz;
u_result_heatmap.imageStore(pixel, abs(pixel_first - pixel_second));
u_result_heatmap.imageStore(pixel, vec4(color, 1));
}
#include <core/base/program.h>
#include <core/rendering/texture_renderer.h>
#include <core/state.h>
#include <core/res/resources.h>
#include <util/files.h>
#include <util/images.h>
#include <iostream>
#include <imgui/imgui_glfw.h>
using namespace glare;
std::vector<std::string> extensions =
{
".hdr", ".png"
};
float zoom = 1.f;
void on_scroll(double xoffset, double yoffset)
{
zoom += 0.1f*float(yoffset);
zoom = glm::max(zoom, 0.01f);
}
int main(int argc, char* argv[])
{
core::state::initialize(files::asset("/preferences/default.xml"));
core::Callbacks::addScrollCallback("main", on_scroll);
auto texture_renderer = core::DefaultTextureRenderers::makeCenterTextureRenderer();
texture_renderer->addPreDrawCallback([](const core::Program& program)
{
program.uniform("u_scale", zoom);
});
std::shared_ptr<core::TextureRGBA_32F> image;
std::shared_ptr<core::TextureRGBA_32F> heatmap_other_image;
std::shared_ptr<core::TextureRGBA_32F> heatmap;
std::sort(extensions.begin(), extensions.end());
core::Program heatmap_generator(files::shader("/heatmap/heatmap.comp"));
core::state::mainLoop([&texture_renderer, &image, &heatmap_other_image, &heatmap, &heatmap_generator](double)
{
static int current_tab = 0;
if(image && (current_tab == 0 || (current_tab == 1 && !heatmap)))
texture_renderer->draw(*image);
else if (heatmap)
{
texture_renderer->draw(*heatmap);
}
ImGui::BeginTabbed("Images", std::array<std::string, 2>{"Load image", "Heatmap"}, current_tab);
switch (current_tab)
{
default:
case 0:
{
static auto root = files::asset("screenshots");
// Go to parent directory
if (ImGui::Button("..", ImVec2(ImGui::GetContentRegionAvailWidth(), 32)))
root = root.parent_path();
for (auto& p : fs::directory_iterator(root)) {
fs::path path = p;
// Either draw directory button or...
if (is_directory(path) && ImGui::Button(path.filename().string().c_str(), ImVec2(ImGui::GetContentRegionAvailWidth(), 40)))
root = path;
// ... draw a button which loads a dae file.
else if (std::binary_search(extensions.begin(), extensions.end(), path.extension().string()) && ImGui::FeatureButton(path.filename().string().c_str(), ImVec2(ImGui::GetContentRegionAvailWidth(), 32)))
{
image = core::Resources::getInstance().getTextureHDR(path);
zoom = 1.f;
}
}
}
break;
case 1:
{
static auto root = files::asset("screenshots");
ImGui::Title("Select an image to generate a heatmap...");
if (heatmap)
{
static char buf[64] = {};
ImGui::InputText("File name", buf, 128);
static bool hdr = false;
ImGui::Checkbox("Save as HDR", &hdr);
if (ImGui::FeatureButton("Save", ImVec2(ImGui::GetContentRegionAvailWidth(), 0)))
{
std::string name = std::string(buf) + (hdr?".hdr":".png");
fs::path output = root / name;
core::textures::saveTexture(output, *heatmap);
}
ImGui::Separator();
}
// Go to parent directory
if (ImGui::Button("..", ImVec2(ImGui::GetContentRegionAvailWidth(), 32)))
root = root.parent_path();
for (auto& p : fs::directory_iterator(root)) {
fs::path path = p;
// Either draw directory button or...
if (is_directory(path) && ImGui::Button(path.filename().string().c_str(), ImVec2(ImGui::GetContentRegionAvailWidth(), 40)))
root = path;
// ... draw a button which loads a dae file.
else if (std::binary_search(extensions.begin(), extensions.end(), path.extension().string()) && ImGui::FeatureButton(path.filename().string().c_str(), ImVec2(ImGui::GetContentRegionAvailWidth(), 32)))
{
heatmap_other_image = core::Resources::getInstance().getTextureHDR(path);
if (!image)
{
Log_Error << "Please select a source image first!";
}
else if (heatmap_other_image->getSize() != image->getSize())
{
Log_Error << "Selected an image with different dimensions!";
}
else
{
heatmap = std::make_shared<core::TextureRGBA_32F>(image->getSize().x, image->getSize().y);
heatmap_generator.use();
heatmap_generator.uniform("u_first_image", image->makeImageResident(gl::Access::eReadOnly));
heatmap_generator.uniform("u_second_image", heatmap_other_image->makeImageResident(gl::Access::eReadOnly));
heatmap_generator.uniform("u_result_heatmap", heatmap->makeImageResident(gl::Access::eWriteOnly));
heatmap_generator.dispatch2d(image->getSize().x, 24, image->getSize().y, 24);
}
zoom = 1.f;
}
}
}
break;
}
ImGui::EndTabbed();
});
}
\ No newline at end of file
#include <core/base/program.h>
#include <core/rendering/texture_renderer.h>
#include <core/state.h>
#include <core/res/resources.h>
#include <util/files.h>
#include <util/images.h>
#include <iostream>
using namespace glare;
......@@ -11,7 +14,42 @@ int main(int argc, char* argv[])
core::state::initialize(files::asset("/preferences/default.xml"));
auto texture_renderer = core::DefaultTextureRenderers::makeSimpleRenderer();
while(true)
{
std::cout << "Put in your first HDR image and press enter: ";
std::string link_to_first_hdr;
std::cin >> link_to_first_hdr;
if (link_to_first_hdr == "")
break;
std::cout << "Put in your second HDR image and press enter: ";
std::string link_to_second_hdr;
std::cin >> link_to_second_hdr;
auto first = core::Resources::getInstance().getTextureHDR(link_to_first_hdr);
auto second = core::Resources::getInstance().getTextureHDR(link_to_second_hdr);
assert(first->getSize() == second->getSize());
auto result = std::make_shared<core::TextureRGBA_32F>(first->getSize().x, first->getSize().y);
core::Program heatmap_generator(files::shader("/heatmap/heatmap.comp"));
heatmap_generator.use();
heatmap_generator.uniform("u_first_image", first->makeImageResident(gl::Access::eReadOnly));
heatmap_generator.uniform("u_second_image", second->makeImageResident(gl::Access::eReadOnly));
heatmap_generator.uniform("u_result_heatmap", result->makeImageResident(gl::Access::eWriteOnly));
heatmap_generator.dispatch2d(first->getSize().x, 24, first->getSize().y, 24);
auto out_name = fs::path(link_to_first_hdr).filename().string() + "++++" + fs::path(link_to_second_hdr).filename().string() + ".png";
core::textures::saveTexture(files::asset("/screenshots/") / out_name, *result);
core::state::mainLoop([&texture_renderer, &result](double)
{
texture_renderer->draw(*result);
});
}
system("pause");
}
\ No newline at end of file
......@@ -12,6 +12,14 @@ namespace glare
});
}
std::shared_ptr<TextureRGBA_32F> Resources::getTextureHDR(const fs::path& path, bool force_reload)
{
return m_texture_storage_hdr.get(path.string(), force_reload, [&]() -> std::shared_ptr<TextureRGBA_32F>
{
return textures::loadTexture<TextureRGBA_32F>(path);
});
}
std::shared_ptr<SoundBuffer> Resources::getAudioBuffer(const fs::path &path, bool force_reload)
{
return m_audio_storage.get(path.string(), force_reload, [&]() -> std::shared_ptr<SoundBuffer>
......
......@@ -38,6 +38,7 @@ namespace glare
{
public:
std::shared_ptr<core::TextureRGBA_UB> getTexture(const fs::path &path, bool force_reload = false);
std::shared_ptr<core::TextureRGBA_32F> getTextureHDR(const fs::path &path, bool force_reload = false);
std::shared_ptr<core::Font> getFont(const fs::path &path, bool force_reload = false);
std::shared_ptr<core::GraphNode> getColladaFile(const fs::path &scene_path, float import_scale = 1.f, bool force_reload = false);
......@@ -49,6 +50,7 @@ namespace glare
private:
ResourceStorage<core::TextureRGBA_UB> m_texture_storage;
ResourceStorage<core::TextureRGBA_32F> m_texture_storage_hdr;
ResourceStorage<core::Font> m_fonts_storage;
ResourceStorage<core::GraphNode> m_collada_scenes_storage;
ResourceStorage<core::SoundBuffer> m_audio_storage;
......@@ -59,19 +61,21 @@ namespace glare
{
static std::mutex mtx;
std::unique_lock<std::mutex> lock(mtx);
auto element = m_storage[id].lock();
if (!element || force_reload)
if (m_storage.count(id) == 0 || m_storage[id].expired())
force_reload = true;
if (force_reload)
{
element = do_when_not_available();
m_storage[id] = element;
auto element = do_when_not_available();
m_storage.emplace(id, element);
return element;
}
else
{
return m_storage[id].lock();
Log_Debug << "Loading resource " << id << " from resource storage.";
}
return element;
}
template <typename T>
void ResourceStorage<T>::put(const std::string &id, std::shared_ptr<T> object)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment