From e6760e11474d04c746cc7e9042803c519f2ac9ec Mon Sep 17 00:00:00 2001 From: Brett Date: Sat, 20 Jul 2024 21:02:27 -0400 Subject: [PATCH] there some weird stuff going on --- CMakeLists.txt | 2 +- include/config.h | 3 + include/float_operations.h | 52 ++++++ include/helper.h | 35 ++++ include/image_operations.h | 339 +++++++++++++++++++++++++++++++++++++ src/main.cpp | 328 ++++------------------------------- 6 files changed, 460 insertions(+), 299 deletions(-) create mode 100644 include/float_operations.h create mode 100644 include/image_operations.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c135a8..61d8656 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(image-gp-6 VERSION 0.0.14) +project(image-gp-6 VERSION 0.0.15) include(FetchContent) diff --git a/include/config.h b/include/config.h index 5277839..ff483f9 100644 --- a/include/config.h +++ b/include/config.h @@ -46,4 +46,7 @@ blt::gp::prog_config_t config = blt::gp::prog_config_t() .set_pop_size(POP_SIZE) .set_thread_count(0); +inline blt::gp::type_provider type_system; +inline blt::gp::gp_program program{type_system, SEED, config}; + #endif //IMAGE_GP_6_CONFIG_H diff --git a/include/float_operations.h b/include/float_operations.h new file mode 100644 index 0000000..0e7a534 --- /dev/null +++ b/include/float_operations.h @@ -0,0 +1,52 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program 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. + * + * This program 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 this program. If not, see . + */ + +#include +#include +#include + +#ifndef IMAGE_GP_6_FLOAT_OPERATIONS_H +#define IMAGE_GP_6_FLOAT_OPERATIONS_H + +inline blt::gp::operation_t f_add([](float a, float b) { + return a + b; +}, "add"); +inline blt::gp::operation_t f_sub([](float a, float b) { + return a - b; +}, "sub"); +inline blt::gp::operation_t f_mul([](float a, float b) { + return a * b; +}, "mul"); +inline blt::gp::operation_t f_pro_div([](float a, float b) { + return b == 0.0f ? 0.0f : (a / b); +}, "div"); +inline blt::gp::operation_t f_literal([]() { + return program.get_random().get_float(0.0, 1.0); +}, "float_lit"); + +template +void create_float_operations(blt::gp::operator_builder& builder) +{ + builder.add_operator(f_add); + builder.add_operator(f_sub); + builder.add_operator(f_mul); + builder.add_operator(f_pro_div); + builder.add_operator(f_literal, true); +} + +#endif //IMAGE_GP_6_FLOAT_OPERATIONS_H diff --git a/include/helper.h b/include/helper.h index 2842b49..d023391 100644 --- a/include/helper.h +++ b/include/helper.h @@ -19,6 +19,8 @@ #ifndef IMAGE_GP_6_HELPER_H #define IMAGE_GP_6_HELPER_H +#include + template constexpr static auto make_single(SINGLE_FUNC&& func) { @@ -41,4 +43,37 @@ constexpr static auto make_double(DOUBLE_FUNC&& func) }; } +struct context +{ + float x, y; +}; + +inline context get_ctx(blt::size_t i) +{ + context ctx{}; + i /= CHANNELS; + ctx.y = std::floor(static_cast(i) / static_cast(IMAGE_SIZE)); + ctx.x = static_cast(i) - (ctx.y * IMAGE_SIZE); + return ctx; +} + +inline context get_pop_ctx(blt::size_t i) +{ + auto const sq = static_cast(std::sqrt(POP_SIZE)); + context ctx{}; + ctx.y = std::floor(static_cast(i) / static_cast(sq)); + ctx.x = static_cast(i) - (ctx.y * sq); + return ctx; +} + +inline blt::size_t get_index(blt::size_t x, blt::size_t y) +{ + return y * IMAGE_SIZE + x; +} + +inline float perlin_noise(float x, float y, float z) +{ + return (stb_perlin_noise3(x, y, z, 0, 0, 0) + 1.0f) / 2.0f; +} + #endif //IMAGE_GP_6_HELPER_H diff --git a/include/image_operations.h b/include/image_operations.h new file mode 100644 index 0000000..330939b --- /dev/null +++ b/include/image_operations.h @@ -0,0 +1,339 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program 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. + * + * This program 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 this program. If not, see . + */ + +#include +#include +#include + +#ifndef IMAGE_GP_6_IMAGE_OPERATIONS_H +#define IMAGE_GP_6_IMAGE_OPERATIONS_H + +inline blt::gp::operation_t add(make_double(std::plus()), "add"); +inline blt::gp::operation_t sub(make_double(std::minus()), "sub"); +inline blt::gp::operation_t mul(make_double(std::multiplies()), "mul"); +inline blt::gp::operation_t pro_div([](const full_image_t& a, const full_image_t& b) { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + img.rgb_data[i] = b.rgb_data[i] == 0 ? 0 : (a.rgb_data[i] / b.rgb_data[i]); + return img; +}, "div"); +inline blt::gp::operation_t op_sin(make_single([](float a) { + return (std::sin(a) + 1.0f) / 2.0f; +}), "sin"); +inline blt::gp::operation_t op_cos(make_single([](float a) { + return (std::cos(a) + 1.0f) / 2.0f; +}), "cos"); +inline blt::gp::operation_t op_atan(make_single((float (*)(float)) &std::atan), "atan"); +inline blt::gp::operation_t op_exp(make_single((float (*)(float)) &std::exp), "exp"); +inline blt::gp::operation_t op_abs(make_single((float (*)(float)) &std::abs), "abs"); +inline blt::gp::operation_t op_log(make_single((float (*)(float)) &std::log), "log"); +inline blt::gp::operation_t op_v_mod([](const full_image_t& a, const full_image_t& b) { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + img.rgb_data[i] = b.rgb_data[i] <= 0 ? 0 : static_cast(blt::mem::type_cast(a.rgb_data[i]) % + blt::mem::type_cast(b.rgb_data[i])); + return img; +}, "v_mod"); + +inline blt::gp::operation_t bitwise_and([](const full_image_t& a, const full_image_t& b) { + using blt::mem::type_cast; + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + img.rgb_data[i] = static_cast(type_cast(a.rgb_data[i]) & type_cast(b.rgb_data[i])); + return img; +}, "and"); + +inline blt::gp::operation_t bitwise_or([](const full_image_t& a, const full_image_t& b) { + using blt::mem::type_cast; + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + img.rgb_data[i] = static_cast(type_cast(a.rgb_data[i]) | type_cast(b.rgb_data[i])); + return img; +}, "or"); + +inline blt::gp::operation_t bitwise_invert([](const full_image_t& a) { + using blt::mem::type_cast; + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + img.rgb_data[i] = static_cast(~type_cast(a.rgb_data[i])); + return img; +}, "invert"); + +inline blt::gp::operation_t bitwise_xor([](const full_image_t& a, const full_image_t& b) { + using blt::mem::type_cast; + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + { + auto in_a = type_cast(a.rgb_data[i]); + auto in_b = type_cast(b.rgb_data[i]); + img.rgb_data[i] = static_cast(in_a ^ in_b); + } + return img; +}, "xor"); + +inline blt::gp::operation_t dissolve([](const full_image_t& a, const full_image_t& b) { + using blt::mem::type_cast; + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + { + auto diff = (a.rgb_data[i] - b.rgb_data[i]) / 2.0f; + img.rgb_data[i] = a.rgb_data[i] + diff; + } + return img; +}, "dissolve"); + +inline blt::gp::operation_t band_pass([](const full_image_t& a, float min, float max) { + using blt::mem::type_cast; + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + { + if (a.rgb_data[i] >= min && a.rgb_data[i] <= max) + { + img.rgb_data[i] = a.rgb_data[i]; + } else if (a.rgb_data[i] < min) + { + auto dist_min = min == 0 ? 0.0f : (a.rgb_data[i] / min); + img.rgb_data[i] = a.rgb_data[i] * dist_min; + } else if (a.rgb_data[i] > max) + { + auto dist_max = max == 0 ? 0.0f : ((a.rgb_data[i] - max) / max); + img.rgb_data[i] = a.rgb_data[i] * dist_max; + } else { + img.rgb_data[i] = 0; + } + } + return img; +}, "band_pass"); + +inline blt::gp::operation_t hsv_to_rgb([](const full_image_t& a) { + using blt::mem::type_cast; + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_SIZE; i++) + { + auto h = static_cast(a.rgb_data[i * CHANNELS + 0]) % 360; + auto s = a.rgb_data[i * CHANNELS + 1]; + auto v = a.rgb_data[i * CHANNELS + 2]; + auto c = v * s; + auto x = c * static_cast(1 - std::abs(((h / 60) % 2) - 1)); + auto m = v - c; + + blt::vec3 rgb; + if (h >= 0 && h < 60) + rgb = {c, x, 0.0f}; + else if (h >= 60 && h < 120) + rgb = {x, c, 0.0f}; + else if (h >= 120 && h < 180) + rgb = {0.0f, c, x}; + else if (h >= 180 && h < 240) + rgb = {0.0f, x, c}; + else if (h >= 240 && h < 300) + rgb = {x, 0.0f, c}; + else if (h >= 300 && h < 360) + rgb = {c, 0.0f, x}; + + img.rgb_data[i * CHANNELS] = rgb.x() + m; + img.rgb_data[i * CHANNELS + 1] = rgb.y() + m; + img.rgb_data[i * CHANNELS + 2] = rgb.z() + m; + } + return img; +}, "hsv"); + +inline blt::gp::operation_t lit([]() { + full_image_t img{}; + auto r = program.get_random().get_float(0.0f, 1.0f); + auto g = program.get_random().get_float(0.0f, 1.0f); + auto b = program.get_random().get_float(0.0f, 1.0f); + for (blt::size_t i = 0; i < DATA_SIZE; i++) + { + img.rgb_data[i * CHANNELS] = r; + img.rgb_data[i * CHANNELS + 1] = g; + img.rgb_data[i * CHANNELS + 2] = b; + } + return img; +}, "lit"); +inline blt::gp::operation_t random_val([]() { + full_image_t img{}; + for (auto& i : img.rgb_data) + i = program.get_random().get_float(0.0f, 1.0f); + return img; +}, "color_noise"); +inline blt::gp::operation_t perlin([](const full_image_t& x, const full_image_t& y, const full_image_t& z, const full_image_t& scale) { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + { + auto s = scale.rgb_data[i]; + img.rgb_data[i] = perlin_noise(x.rgb_data[i] / s, y.rgb_data[i] / s, z.rgb_data[i] / s); + } + return img; +}, "perlin"); +inline blt::gp::operation_t perlin_terminal([]() { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + { + auto ctx = get_ctx(i); + img.rgb_data[i] = perlin_noise(ctx.x / IMAGE_SIZE, ctx.y / IMAGE_SIZE, static_cast(i % CHANNELS) / CHANNELS); + } + return img; +}, "perlin_term"); +inline blt::gp::operation_t perlin_warped([](const full_image_t& u, const full_image_t& v) { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) + { + auto ctx = get_ctx(i); + img.rgb_data[i] = perlin_noise(ctx.x / IMAGE_SIZE + u.rgb_data[i], ctx.y / IMAGE_SIZE + v.rgb_data[i], + static_cast(i % CHANNELS) / CHANNELS); + } + return img; +}, "perlin_warped"); +inline blt::gp::operation_t op_img_size([]() { + full_image_t img{}; + for (float& i : img.rgb_data) + { + i = IMAGE_SIZE; + } + return img; +}, "img_size"); +inline blt::gp::operation_t op_x_r([]() { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_SIZE; i++) + { + auto ctx = get_ctx(i).x; + img.rgb_data[i * CHANNELS] = ctx; + img.rgb_data[i * CHANNELS + 1] = 0; + img.rgb_data[i * CHANNELS + 2] = 0; + } + return img; +}, "x_r"); +inline blt::gp::operation_t op_x_g([]() { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_SIZE; i++) + { + auto ctx = get_ctx(i).x; + img.rgb_data[i * CHANNELS] = 0; + img.rgb_data[i * CHANNELS + 1] = ctx; + img.rgb_data[i * CHANNELS + 2] = 0; + } + return img; +}, "x_g"); +inline blt::gp::operation_t op_x_b([]() { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_SIZE; i++) + { + auto ctx = get_ctx(i).x; + img.rgb_data[i * CHANNELS] = 0; + img.rgb_data[i * CHANNELS + 1] = 0; + img.rgb_data[i * CHANNELS + 2] = ctx; + } + return img; +}, "x_b"); +inline blt::gp::operation_t op_x_rgb([]() { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_SIZE; i++) + { + auto ctx = get_ctx(i).x; + img.rgb_data[i * CHANNELS] = ctx; + img.rgb_data[i * CHANNELS + 1] = ctx; + img.rgb_data[i * CHANNELS + 2] = ctx; + } + return img; +}, "x_rgb"); +inline blt::gp::operation_t op_y_r([]() { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_SIZE; i++) + { + auto ctx = get_ctx(i).y; + img.rgb_data[i * CHANNELS] = ctx; + img.rgb_data[i * CHANNELS + 1] = 0; + img.rgb_data[i * CHANNELS + 2] = 0; + } + return img; +}, "y_r"); +inline blt::gp::operation_t op_y_g([]() { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_SIZE; i++) + { + auto ctx = get_ctx(i).y; + img.rgb_data[i * CHANNELS] = 0; + img.rgb_data[i * CHANNELS + 1] = ctx; + img.rgb_data[i * CHANNELS + 2] = 0; + } + return img; +}, "y_g"); +inline blt::gp::operation_t op_y_b([]() { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_SIZE; i++) + { + auto ctx = get_ctx(i).y; + img.rgb_data[i * CHANNELS] = 0; + img.rgb_data[i * CHANNELS + 1] = 0; + img.rgb_data[i * CHANNELS + 2] = ctx; + } + return img; +}, "y_b"); +inline blt::gp::operation_t op_y_rgb([]() { + full_image_t img{}; + for (blt::size_t i = 0; i < DATA_SIZE; i++) + { + auto ctx = get_ctx(i).y; + img.rgb_data[i * CHANNELS] = ctx; + img.rgb_data[i * CHANNELS + 1] = ctx; + img.rgb_data[i * CHANNELS + 2] = ctx; + } + return img; +}, "y_rgb"); + +template +void create_image_operations(blt::gp::operator_builder& builder) +{ + builder.add_operator(perlin); + builder.add_operator(perlin_terminal); + builder.add_operator(perlin_warped); + + builder.add_operator(add); + builder.add_operator(sub); + builder.add_operator(mul); + builder.add_operator(pro_div); + builder.add_operator(op_sin); + builder.add_operator(op_cos); + builder.add_operator(op_atan); + builder.add_operator(op_exp); + builder.add_operator(op_log); + builder.add_operator(op_abs); + builder.add_operator(op_v_mod); + builder.add_operator(bitwise_and); + builder.add_operator(bitwise_or); + builder.add_operator(bitwise_invert); + builder.add_operator(bitwise_xor); + builder.add_operator(dissolve); + builder.add_operator(band_pass); + builder.add_operator(hsv_to_rgb); + + bool state = false; + builder.add_operator(lit, true); + builder.add_operator(random_val); + builder.add_operator(op_x_r, state); + builder.add_operator(op_x_g, state); + builder.add_operator(op_x_b, state); + builder.add_operator(op_x_rgb, state); + builder.add_operator(op_y_r, state); + builder.add_operator(op_y_g, state); + builder.add_operator(op_y_b, state); + builder.add_operator(op_y_rgb, state); +} + +#endif //IMAGE_GP_6_IMAGE_OPERATIONS_H diff --git a/src/main.cpp b/src/main.cpp index acde118..1797cf4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,15 +36,17 @@ #include "opencv2/imgproc.hpp" #include #include "slr.h" +#include "float_operations.h" #include #include +#include blt::gfx::matrix_state_manager global_matrices; blt::gfx::resource_manager resources; blt::gfx::batch_renderer_2d renderer_2d(resources, global_matrices); blt::gfx::first_person_camera_2d camera; -static constexpr blt::size_t TYPE_COUNT = 1; +static constexpr blt::size_t TYPE_COUNT = 2; std::array fitness_values{}; double last_fitness = 0; @@ -53,6 +55,7 @@ double hovered_fitness_value = 0; bool evaluate = true; std::array has_literal_converter = { + true, true }; @@ -69,6 +72,16 @@ std::array(p1_in_ptr); + auto& p2_in = *static_cast(p2_in_ptr); + auto& c1_out = *static_cast(c1_out_ptr); + auto& c2_out = *static_cast(c2_out_ptr); + + auto diff = p1_in - p2_in; + c1_out = p1_in - diff; + c2_out = p2_in + diff; } }; @@ -79,49 +92,27 @@ std::array, TYPE for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) c1_out.rgb_data[i] = p1_in.rgb_data[i] + program.get_random().get_float(-1.0f, 1.0f); + }, + [](blt::gp::gp_program& program, void* p1_in_ptr, void* c1_out_ptr) { + auto& p1_in = *static_cast(p1_in_ptr); + auto& c1_out = *static_cast(c1_out_ptr); + + c1_out = p1_in + program.get_random().get_float(-1.0f, 1.0f); } }; class image_crossover_t : public blt::gp::crossover_t { public: - blt::expected apply(blt::gp::gp_program& program, const blt::gp::tree_t& p1, const blt::gp::tree_t& p2) final + blt::expected apply(blt::gp::gp_program& prog, const blt::gp::tree_t& p1, const blt::gp::tree_t& p2) final { - auto sel = program.get_random().choice(); + auto sel = prog.get_random().choice(); if (sel) - return blt::gp::crossover_t::apply(program, p1, p2); + return blt::gp::crossover_t::apply(prog, p1, p2); std::abort(); } }; -struct context -{ - float x, y; -}; - -inline context get_ctx(blt::size_t i) -{ - context ctx{}; - i /= CHANNELS; - ctx.y = std::floor(static_cast(i) / static_cast(IMAGE_SIZE)); - ctx.x = static_cast(i) - (ctx.y * IMAGE_SIZE); - return ctx; -} - -inline context get_pop_ctx(blt::size_t i) -{ - auto const sq = static_cast(std::sqrt(POP_SIZE)); - context ctx{}; - ctx.y = std::floor(static_cast(i) / static_cast(sq)); - ctx.x = static_cast(i) - (ctx.y * sq); - return ctx; -} - -inline blt::size_t get_index(blt::size_t x, blt::size_t y) -{ - return y * IMAGE_SIZE + x; -} - std::array generation_images; full_image_t base_image; @@ -129,240 +120,8 @@ blt::size_t last_run = 0; blt::i32 time_between_runs = 16; bool is_running = false; -blt::gp::type_provider type_system; -blt::gp::gp_program program{type_system, SEED, config}; std::unique_ptr gp_thread = nullptr; -blt::gp::operation_t add(make_double(std::plus()), "add"); -blt::gp::operation_t sub(make_double(std::minus()), "sub"); -blt::gp::operation_t mul(make_double(std::multiplies()), "mul"); -blt::gp::operation_t pro_div([](const full_image_t& a, const full_image_t& b) { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - img.rgb_data[i] = b.rgb_data[i] == 0 ? 0 : (a.rgb_data[i] / b.rgb_data[i]); - return img; -}, "div"); -blt::gp::operation_t op_sin(make_single([](float a) { - return (std::sin(a) + 1.0f) / 2.0f; -}), "sin"); -blt::gp::operation_t op_cos(make_single([](float a) { - return (std::cos(a) + 1.0f) / 2.0f; -}), "cos"); -blt::gp::operation_t op_atan(make_single((float (*)(float)) &std::atan), "atan"); -blt::gp::operation_t op_exp(make_single((float (*)(float)) &std::exp), "exp"); -blt::gp::operation_t op_abs(make_single((float (*)(float)) &std::abs), "abs"); -blt::gp::operation_t op_log(make_single((float (*)(float)) &std::log), "log"); -blt::gp::operation_t op_v_mod([](const full_image_t& a, const full_image_t& b) { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - img.rgb_data[i] = b.rgb_data[i] <= 0 ? 0 : static_cast(blt::mem::type_cast(a.rgb_data[i]) % - blt::mem::type_cast(b.rgb_data[i])); - return img; -}, "v_mod"); - -blt::gp::operation_t bitwise_and([](const full_image_t& a, const full_image_t& b) { - using blt::mem::type_cast; - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - img.rgb_data[i] = static_cast(type_cast(a.rgb_data[i]) & type_cast(b.rgb_data[i])); - return img; -}, "and"); - -blt::gp::operation_t bitwise_or([](const full_image_t& a, const full_image_t& b) { - using blt::mem::type_cast; - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - img.rgb_data[i] = static_cast(type_cast(a.rgb_data[i]) | type_cast(b.rgb_data[i])); - return img; -}, "or"); - -blt::gp::operation_t bitwise_invert([](const full_image_t& a) { - using blt::mem::type_cast; - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - img.rgb_data[i] = static_cast(~type_cast(a.rgb_data[i])); - return img; -}, "invert"); - -blt::gp::operation_t bitwise_xor([](const full_image_t& a, const full_image_t& b) { - using blt::mem::type_cast; - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - { - auto in_a = type_cast(a.rgb_data[i]); - auto in_b = type_cast(b.rgb_data[i]); - img.rgb_data[i] = static_cast(in_a ^ in_b); - } - return img; -}, "xor"); - -blt::gp::operation_t dissolve([](const full_image_t& a, const full_image_t& b) { - using blt::mem::type_cast; - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - { - auto diff = (a.rgb_data[i] - b.rgb_data[i]) / 2.0f; - img.rgb_data[i] = a.rgb_data[i] + diff; - } - return img; -}, "dissolve"); - -blt::gp::operation_t hsv_to_rgb([](const full_image_t& a) { - using blt::mem::type_cast; - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_SIZE; i++) - { - auto h = static_cast(a.rgb_data[i * CHANNELS + 0]) % 360; - auto s = a.rgb_data[i * CHANNELS + 1]; - auto v = a.rgb_data[i * CHANNELS + 2]; - auto c = v * s; - auto x = c * static_cast(1 - std::abs(((h / 60) % 2) - 1)); - auto m = v - c; - - blt::vec3 rgb; - if (h >= 0 && h < 60) - rgb = {c, x, 0.0f}; - else if (h >= 60 && h < 120) - rgb = {x, c, 0.0f}; - else if (h >= 120 && h < 180) - rgb = {0.0f, c, x}; - else if (h >= 180 && h < 240) - rgb = {0.0f, x, c}; - else if (h >= 240 && h < 300) - rgb = {x, 0.0f, c}; - else if (h >= 300 && h < 360) - rgb = {c, 0.0f, x}; - - img.rgb_data[i * CHANNELS] = rgb.x() + m; - img.rgb_data[i * CHANNELS + 1] = rgb.y() + m; - img.rgb_data[i * CHANNELS + 2] = rgb.z() + m; - } - return img; -}, "hsv"); - -blt::gp::operation_t lit([]() { - full_image_t img{}; - auto r = program.get_random().get_float(0.0f, 1.0f); - auto g = program.get_random().get_float(0.0f, 1.0f); - auto b = program.get_random().get_float(0.0f, 1.0f); - for (blt::size_t i = 0; i < DATA_SIZE; i++) - { - img.rgb_data[i * CHANNELS] = r; - img.rgb_data[i * CHANNELS + 1] = g; - img.rgb_data[i * CHANNELS + 2] = b; - } - return img; -}, "lit"); -blt::gp::operation_t random_val([]() { - full_image_t img{}; - for (auto& i : img.rgb_data) - i = program.get_random().get_float(0.0f, 1.0f); - return img; -}, "color_noise"); -static blt::gp::operation_t perlin([](const full_image_t& x, const full_image_t& y, const full_image_t& z, const full_image_t& scale) { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - { - auto s = scale.rgb_data[i]; - img.rgb_data[i] = stb_perlin_noise3(x.rgb_data[i] / s, y.rgb_data[i] / s, z.rgb_data[i] / s, 0, 0, 0); - } - return img; -}, "perlin"); -static blt::gp::operation_t perlin_terminal([]() { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - { - auto ctx = get_ctx(i); - img.rgb_data[i] = - stb_perlin_noise3(ctx.x / IMAGE_SIZE, ctx.y / IMAGE_SIZE, static_cast(i % CHANNELS) / CHANNELS, 0, 0, 0); - } - return img; -}, "perlin_term"); -static blt::gp::operation_t perlin_warped([](const full_image_t& u, const full_image_t& v) { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) - { - auto ctx = get_ctx(i); - img.rgb_data[i] = stb_perlin_noise3(ctx.x / IMAGE_SIZE + u.rgb_data[i], ctx.y / IMAGE_SIZE + v.rgb_data[i], - static_cast(i % CHANNELS) / CHANNELS, 0, 0, 0); - } - return img; -}, "perlin_warped"); -static blt::gp::operation_t op_img_size([]() { - full_image_t img{}; - for (float& i : img.rgb_data) - { - i = IMAGE_SIZE; - } - return img; -}, "img_size"); -static blt::gp::operation_t op_x_r([]() { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_SIZE; i++) - { - auto ctx = get_ctx(i).x; - img.rgb_data[i * CHANNELS] = ctx; - img.rgb_data[i * CHANNELS + 1] = 0; - img.rgb_data[i * CHANNELS + 2] = 0; - } - return img; -}, "x_r"); -static blt::gp::operation_t op_x_g([]() { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_SIZE; i++) - { - auto ctx = get_ctx(i).x; - img.rgb_data[i * CHANNELS] = 0; - img.rgb_data[i * CHANNELS + 1] = ctx; - img.rgb_data[i * CHANNELS + 2] = 0; - } - return img; -}, "x_g"); -static blt::gp::operation_t op_x_b([]() { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_SIZE; i++) - { - auto ctx = get_ctx(i).x; - img.rgb_data[i * CHANNELS] = 0; - img.rgb_data[i * CHANNELS + 1] = 0; - img.rgb_data[i * CHANNELS + 2] = ctx; - } - return img; -}, "x_b"); -static blt::gp::operation_t op_y_r([]() { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_SIZE; i++) - { - auto ctx = get_ctx(i).y; - img.rgb_data[i * CHANNELS] = ctx; - img.rgb_data[i * CHANNELS + 1] = 0; - img.rgb_data[i * CHANNELS + 2] = 0; - } - return img; -}, "y_r"); -static blt::gp::operation_t op_y_g([]() { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_SIZE; i++) - { - auto ctx = get_ctx(i).y; - img.rgb_data[i * CHANNELS] = 0; - img.rgb_data[i * CHANNELS + 1] = ctx; - img.rgb_data[i * CHANNELS + 2] = 0; - } - return img; -}, "y_g"); -static blt::gp::operation_t op_y_b([]() { - full_image_t img{}; - for (blt::size_t i = 0; i < DATA_SIZE; i++) - { - auto ctx = get_ctx(i).y; - img.rgb_data[i * CHANNELS] = 0; - img.rgb_data[i * CHANNELS + 1] = 0; - img.rgb_data[i * CHANNELS + 2] = ctx; - } - return img; -}, "y_b"); - constexpr float compare_values(float a, float b) { if (std::isnan(a) || std::isnan(b) || std::isinf(a) || std::isinf(b)) @@ -561,39 +320,11 @@ void init(const blt::gfx::window_data&) BLT_DEBUG("Setup Types and Operators"); type_system.register_type(); + type_system.register_type(); blt::gp::operator_builder builder{type_system}; - builder.add_operator(perlin); - builder.add_operator(perlin_terminal); - builder.add_operator(perlin_warped); - - builder.add_operator(add); - builder.add_operator(sub); - builder.add_operator(mul); - builder.add_operator(pro_div); - builder.add_operator(op_sin); - builder.add_operator(op_cos); - builder.add_operator(op_atan); - builder.add_operator(op_exp); - builder.add_operator(op_log); - builder.add_operator(op_abs); - builder.add_operator(op_v_mod); - builder.add_operator(bitwise_and); - builder.add_operator(bitwise_or); - builder.add_operator(bitwise_invert); - builder.add_operator(bitwise_xor); - builder.add_operator(dissolve); - builder.add_operator(hsv_to_rgb); - - builder.add_operator(lit, true); - builder.add_operator(random_val); - const bool state = false; - builder.add_operator(op_x_r, true); - builder.add_operator(op_x_g, true); - builder.add_operator(op_x_b, state); - builder.add_operator(op_y_r, state); - builder.add_operator(op_y_g, state); - builder.add_operator(op_y_b, state); + create_image_operations(builder); + create_float_operations(builder); program.set_operations(builder.build()); @@ -636,8 +367,9 @@ void update(const blt::gfx::window_data& data) const auto mouse_pos = blt::make_vec2(blt::gfx::calculateRay2D(data.width, data.height, global_matrices.getScale2D(), global_matrices.getView2D(), global_matrices.getOrtho())); - for (blt::size_t i = 0; i < config.population_size; i++) + for (blt::size_t i = 0; i < program.get_current_pop().get_individuals().size(); i++) { + auto& ind = program.get_current_pop().get_individuals()[i]; auto ctx = get_pop_ctx(i); float x = ctx.x * IMAGE_SIZE + ctx.x * IMAGE_PADDING; float y = ctx.y * IMAGE_SIZE + ctx.y * IMAGE_PADDING; @@ -652,7 +384,6 @@ void update(const blt::gfx::window_data& data) renderer_2d.drawRectangleInternal(blt::make_color(0.9, 0.9, 0.3), {x, y, IMAGE_SIZE + IMAGE_PADDING / 2.0f, IMAGE_SIZE + IMAGE_PADDING / 2.0f}, 10.0f); - auto& ind = program.get_current_pop().get_individuals()[i]; auto& io = ImGui::GetIO(); @@ -681,8 +412,9 @@ void update(const blt::gfx::window_data& data) hovered_fitness_value = fitness_values[i]; } + auto val = static_cast(ind.fitness.adjusted_fitness); renderer_2d.drawRectangleInternal( - blt::make_vec4(blt::vec3(static_cast(program.get_current_pop().get_individuals()[i].fitness.adjusted_fitness)), 1.0), + blt::make_color(val, val, val), {x, y, IMAGE_SIZE + IMAGE_PADDING / 2.0f, IMAGE_SIZE + IMAGE_PADDING / 2.0f}, 5.0f);