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);