diff --git a/Makefile b/Makefile index d2723ef..f38ba2c 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ SOURCEFILES = cpp SRCDIR = src TMPDIR = build TARGET = gross -FILES = Chromosome main +FILES = Chromosome Fitness main #SOURCES = $(patsubst %,$(SRCDIR)/%.cpp,$(FILES)) OBJECTS = $(patsubst %,$(TMPDIR)/%.o,$(FILES)) diff --git a/compare.glsl b/compare.glsl index 5467416..233fcf0 100644 --- a/compare.glsl +++ b/compare.glsl @@ -4,16 +4,16 @@ // try isampler2D, ivec4 etc.? Probably not uniform vec2 size; -uniform vec2 offs; +// uniform vec2 offs; uniform sampler2D base; uniform sampler2D curr; void main(void) { - vec2 pos = (gl_FragCoord.xy-offs)/size; - pos.y = 1.0 - pos.y; + vec2 pos = gl_FragCoord.xy/size; vec4 color = texture2D(curr, pos); + pos.y = 1.0 - pos.y; vec4 basecolor = texture2D(base, pos); - color.xyz = abs(color.xyz - basecolor.xyz); + color.rgb = abs(color.rgb - basecolor.rgb); gl_FragColor = color; } diff --git a/src/Chromosome.cpp b/src/Chromosome.cpp index 2d1d14d..058803e 100644 --- a/src/Chromosome.cpp +++ b/src/Chromosome.cpp @@ -99,6 +99,11 @@ void Chromosome::mutate() void Chromosome::draw(sf::RenderTarget& target, sf::RenderStates states) const { + this->circle.setPosition(0, 0); + this->circle.setRadius(Chromosome::size.x + Chromosome::size.y); + this->circle.setOrigin(Chromosome::size); + this->circle.setFillColor(sf::Color::White); + target.draw(this->circle, states); for (auto gene : this->genes) { this->circle.setPosition(gene.position); this->circle.setRadius(gene.radius); @@ -115,9 +120,15 @@ size_t Chromosome::length() } +float Chromosome::maxRadius() +{ + return std::min(Chromosome::size.x, Chromosome::size.y)/2; +} + + Chromosome::Gene Chromosome::randomGene() { - float max_radius = std::min(Chromosome::size.x, Chromosome::size.y)/4; + float max_radius = this->maxRadius(); std::uniform_real_distribution<> xdist(0, Chromosome::size.x); std::uniform_real_distribution<> ydist(0, Chromosome::size.y); std::uniform_real_distribution<> rdist(0, sqrt(max_radius)); @@ -125,7 +136,12 @@ Chromosome::Gene Chromosome::randomGene() sf::Vector2f position(xdist(*Chromosome::re), ydist(*Chromosome::re)); float radius = (pow(rdist(*Chromosome::re), 2)); - sf::Color color(colordist(*Chromosome::re), colordist(*Chromosome::re), colordist(*Chromosome::re), 50); + sf::Color color( + colordist(*Chromosome::re), + colordist(*Chromosome::re), + colordist(*Chromosome::re), + 150 + ); Chromosome::Gene gene; gene.position = position; @@ -139,7 +155,7 @@ Chromosome::Gene Chromosome::randomGene() void Chromosome::mutateGene(Gene& gene) { std::uniform_int_distribution<> booldist(0, 1); - float max_radius = std::min(Chromosome::size.x, Chromosome::size.y)/4; + float max_radius = this->maxRadius(); if (booldist(*Chromosome::re)) { // position std::normal_distribution<> posdist(0, Chromosome::stddev_position); @@ -158,7 +174,7 @@ void Chromosome::mutateGene(Gene& gene) if (booldist(*Chromosome::re)) { // radius std::normal_distribution<> raddist(0, Chromosome::stddev_radius); gene.radius = std::clamp( - gene.radius + raddist(*Chromosome::re)*max_radius, + gene.radius + pow(raddist(*Chromosome::re)*sqrt(max_radius), 2), 0, max_radius ); @@ -169,6 +185,7 @@ void Chromosome::mutateGene(Gene& gene) gene.color.r = std::clamp(gene.color.r + coldist(*Chromosome::re), 0, 255); gene.color.g = std::clamp(gene.color.g + coldist(*Chromosome::re), 0, 255); gene.color.b = std::clamp(gene.color.b + coldist(*Chromosome::re), 0, 255); + gene.color.a = std::clamp(gene.color.a + coldist(*Chromosome::re), 0, 255); } } diff --git a/src/Chromosome.hpp b/src/Chromosome.hpp index 79946dc..1e6ac2d 100644 --- a/src/Chromosome.hpp +++ b/src/Chromosome.hpp @@ -34,6 +34,8 @@ protected: sf::Color color; }; + float maxRadius(); + Gene randomGene(); void mutateGene(Gene& gene); diff --git a/src/Fitness.cpp b/src/Fitness.cpp new file mode 100644 index 0000000..f6e9319 --- /dev/null +++ b/src/Fitness.cpp @@ -0,0 +1,63 @@ +#include "Fitness.hpp" + +#include + + + +Fitness::Fitness() {} + + +Fitness::Fitness(sf::Texture target, float scale) +{ + this->target = target; + + sf::Vector2u targetSize = this->target.getSize(); + this->tex.create(targetSize.x, targetSize.y); + this->sprite.setTexture(this->tex.getTexture()); + this->comp.create(targetSize.x*scale, targetSize.y*scale); +// this->comp.setSmooth(true); + + this->view.reset(sf::FloatRect(0, 0, targetSize.x, targetSize.y)); + this->view.setViewport(sf::FloatRect(0, 0, 1, 1)); +} + + +bool Fitness::loadShader(std::string filename) +{ + this->compshdr.loadFromFile(filename, sf::Shader::Fragment); + if (this->compshdr.isAvailable()) { + this->compshdr.setUniform("base", this->target); + this->compshdr.setUniform("curr", this->tex.getTexture()); + this->compshdr.setUniform("size", sf::Vector2f(this->comp.getSize())); + return true; + } else { + return false; + } +} + + +double Fitness::of(Chromosome chr) +{ + // first, render a reduced, shaderized version to RenderTextures + this->tex.clear(); + this->tex.draw(chr); + this->tex.display(); + + this->comp.clear(sf::Color::Blue); + this->comp.setView(this->view); + this->comp.draw(this->sprite, &this->compshdr); +// this->comp.draw(this->sprite); + this->comp.display(); + + // then, download the result as an image and add the pixels + sf::Image image = this->comp.getTexture().copyToImage(); + sf::Vector2u size = image.getSize(); + double fitness = 0; + for (unsigned int x=0; x + + + +class Fitness +{ +public: + Fitness(); + Fitness(sf::Texture target, float scale=0.5); + bool loadShader(std::string filename); + + double of(Chromosome chr); + + sf::Texture target; // base image to compare against + sf::RenderTexture tex; // big RenderWindow containg the Chromosome to be evaluated + sf::RenderTexture comp; // smaller RenderWindow which is downloaded as Image + +private: + sf::Sprite sprite; // sprite to render tex to comp + sf::Shader compshdr; // shader to perform pixel-wise image diff with + sf::View view; // reduces tex to comp size while drawing +}; diff --git a/src/main.cpp b/src/main.cpp index ccd94d4..df92492 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,7 @@ #include #include #include "Chromosome.hpp" +#include "Fitness.hpp" /* * UI Modes: @@ -109,11 +110,12 @@ int main() { const float winW = 480; const float winH = 480; std::mt19937_64 randomEngine; - randomEngine.seed(1); + randomEngine.seed(1337); sf::RenderWindow window(sf::VideoMode(winW, winH), "gross"); window.setMouseCursorVisible(false); // hide the cursor + /* test mating Chromosome::size = sf::Vector2f(winW/2, winH/2); Chromosome::re = &randomEngine; Chromosome father, mother, child, monster; @@ -125,6 +127,37 @@ int main() { vmother.setViewport(sf::FloatRect(.5, 0, .5, .5)); vchild.setViewport(sf::FloatRect(0, .5, .5, .5)); vmonster.setViewport(sf::FloatRect(.5, .5, .5, .5)); + */ + + Chromosome::size = sf::Vector2f(winW/2, winH/2); + Chromosome::re = &randomEngine; + Chromosome target, chr; + + sf::View vtarget(sf::FloatRect(0, 0, winW/2, winH/2)); + sf::View vchr(sf::FloatRect(0, 0, winW/2, winH/2)); + sf::View vtex(sf::FloatRect(0, 0, winW/2, winH/2)); + sf::View vcomp(sf::FloatRect(0, 0, winW/2, winH/2)); + vtarget.setViewport(sf::FloatRect(0, 0, 0.5, 0.5)); + vchr.setViewport(sf::FloatRect(0.5, 0, 0.5, 0.5)); + vtex.setViewport(sf::FloatRect(0, 0.5, 0.5, 0.5)); + vcomp.setViewport(sf::FloatRect(0.5, 0.5, 0.5, 0.5)); + for (int i=0; i<1000; ++i) target.mutate(); + + sf::RenderTexture targettex; + targettex.create(winW/2, winH/2); +// targettex.clear(sf::Color::White); + targettex.clear(); + targettex.draw(target); + targettex.display(); + + Fitness fitn(targettex.getTexture(), 1); + if (!fitn.loadShader("compare.glsl")) { + std::cout << "Shader not loaded" << std::endl; + return 123; + } + sf::Sprite starget(fitn.target); + sf::Sprite stex(fitn.tex.getTexture()); + sf::Sprite scomp(fitn.comp.getTexture()); /* // load images @@ -176,6 +209,7 @@ int main() { while (window.pollEvent(event)) { // Exit the app when a key is pressed if (event.type == sf::Event::KeyPressed) { + /* test mating father = Chromosome(); // mother = Chromosome(); for (int i=0; i<1000; ++i) { @@ -195,6 +229,17 @@ int main() { std::cout << "mother size: " << mother.length() << std::endl; std::cout << "child size: " << child.length() << std::endl; std::cout << "monster size: " << monster.length() << std::endl; + */ + + chr = target; +// for (int i=0; i<20; ++i) { + chr.mutate(); +// } + + std::cout << "----------SIZES----------" << std::endl; + std::cout << "target size: " << target.length() << std::endl; + std::cout << "chr size: " << chr.length() << std::endl; + std::cout << "fitness: " << fitn.of(chr) << std::endl; } } @@ -204,13 +249,39 @@ int main() { // sf::Vector2i mousePos = sf::Mouse::getPosition(window); // shader.setParameter("mouse", sf::Vector2f(mousePos.x, mousePos.y - winH)); - // Draw the sprites + /* test mating window.clear(); window.setView(vfather); window.draw(father); window.setView(vmother); window.draw(mother); window.setView(vchild); window.draw(child); window.setView(vmonster); window.draw(monster); window.display(); + */ + +// window.clear(sf::Color::White) + + window.clear(); + window.setView(vtarget); window.draw(starget); + window.setView(vchr); window.draw(chr); + window.setView(vtex); window.draw(stex); + window.setView(vcomp); window.draw(scomp); + window.display(); + + /* benchmark + sf::Clock clk; + clk.restart(); // start the timer + for (int h=0; h<10000; ++h) { + chr = target; +// for (int i=0; i<20; ++i) { + chr.mutate(); +// } + + fitn.of(chr); +// std::cout << fitn.of(chr) << "\n"; + } + std::cout << "10000 images: " << clk.getElapsedTime().asSeconds() << std::endl; + return 2; + */ /* window.draw(sprbase);