]> git.localhorst.tv Git - blobs.git/commitdiff
creature skin overhaul
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 28 Nov 2017 20:39:09 +0000 (21:39 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 28 Nov 2017 20:39:09 +0000 (21:39 +0100)
assets
src/app/app.cpp
src/app/states.cpp
src/creature/Creature.hpp
src/creature/Genome.hpp
src/creature/creature.cpp
src/graphics/CreatureSkin.hpp
src/graphics/shader.cpp
src/math/glm.hpp
src/world/world.cpp

diff --git a/assets b/assets
index 51cf5cf9b1bda806e44dd77fb31041f90d06ce2b..3c715b39e3aece21fc1f0fd6042611e79bfbeb44 160000 (submodule)
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 51cf5cf9b1bda806e44dd77fb31041f90d06ce2b
+Subproject commit 3c715b39e3aece21fc1f0fd6042611e79bfbeb44
index f2d0e5904d209ccba1113692877974e36e884ac8..a732ca64b21cc8cc5130864a740f47b5ccc47291 100644 (file)
@@ -216,15 +216,12 @@ Assets::Assets()
 
        textures.skins.Bind();
        textures.skins.Reserve(256, 256, 9, format);
-       LoadSkinTexture("1", textures.skins, 0);
-       LoadSkinTexture("2", textures.skins, 1);
-       LoadSkinTexture("3", textures.skins, 2);
-       LoadSkinTexture("4", textures.skins, 3);
-       LoadSkinTexture("5", textures.skins, 4);
-       LoadSkinTexture("6", textures.skins, 5);
-       LoadSkinTexture("7", textures.skins, 6);
-       LoadSkinTexture("8", textures.skins, 7);
-       LoadSkinTexture("9", textures.skins, 8);
+       LoadSkinTexture("plain", textures.skins, 0);
+       LoadSkinTexture("stripes", textures.skins, 1);
+       LoadSkinTexture("dots", textures.skins, 2);
+       LoadSkinTexture("lines", textures.skins, 3);
+       LoadSkinTexture("spots", textures.skins, 4);
+       LoadSkinTexture("circles", textures.skins, 5);
        textures.skins.FilterTrilinear();
 }
 
index d1e092e70a8589dc70387d9d72793b7868e461ef..b1a20db92a50740934dfac6849065940c84e4ab6 100644 (file)
@@ -135,6 +135,8 @@ void MasterState::OnRender(graphics::Viewport &viewport) {
        // TODO: extend to nearby bodies as well
        for (auto c : cam.Reference().Creatures()) {
                assets.shaders.creature_skin.SetM(cam.Model(cam.Reference()) * glm::mat4(c->LocalTransform()));
+               assets.shaders.creature_skin.SetBaseColor(c->BaseColor());
+               assets.shaders.creature_skin.SetHighlightColor(c->HighlightColor());
                c->Draw(viewport);
        }
 
index f443e48940d2caa20da318c706f196f939a667fd..f36a2db1f1172770855a9eebdfc6554202689b6f 100644 (file)
@@ -57,6 +57,15 @@ public:
        Genome::Properties<double> &GetProperties() noexcept { return properties; }
        const Genome::Properties<double> &GetProperties() const noexcept { return properties; }
 
+       const Genome::PropertySet<double> &CurProps() const noexcept { return properties.props[cur_prop]; }
+       const Genome::PropertySet<double> &NextProps() const noexcept { return properties.props[cur_prop + 1]; }
+
+       void BaseColor(const glm::dvec3 &c) noexcept { base_color = c; }
+       const glm::dvec3 &BaseColor() const noexcept { return base_color; }
+
+       void HighlightColor(const glm::dvec3 &c) noexcept { highlight_color = c; }
+       glm::dvec4 HighlightColor() const noexcept;
+
        void Mass(double m) noexcept { mass = m; size = std::cbrt(mass / density); }
        double Mass() const noexcept { return mass; }
        void Grow(double amount) noexcept;
@@ -66,6 +75,7 @@ public:
 
        double Size() const noexcept;
        double Age() const noexcept;
+       double AgeLerp(double from, double to) const noexcept;
        // change of giving birth per tick
        double Fertility() const noexcept;
 
@@ -110,6 +120,9 @@ private:
        Genome::Properties<double> properties;
        int cur_prop;
 
+       glm::dvec3 base_color;
+       glm::dvec3 highlight_color;
+
        double mass;
        double density;
        double size;
index a7be0e1c6f6f4e342a59ba18bb70d6a78d5ba152..b14efc1a756396dd405906786eaffe7f1bc96fea 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "../math/Distribution.hpp"
 #include "../math/GaloisLFSR.hpp"
+#include "../math/glm.hpp"
 
 #include <vector>
 
@@ -22,6 +23,7 @@ struct Genome {
                T age;
                T mass;
                T fertility;
+               T highlight;
        };
        template<class T>
        struct Properties {
@@ -70,7 +72,8 @@ struct Genome {
                return {
                        p.age.FakeNormal(rand.SNorm()),
                        p.mass.FakeNormal(rand.SNorm()),
-                       p.fertility.FakeNormal(rand.SNorm())
+                       p.fertility.FakeNormal(rand.SNorm()),
+                       glm::clamp(p.highlight.FakeNormal(rand.SNorm()), 0.0, 1.0)
                };
        }
 
index 1196a3c8ca0341200cf2fe9ec26f3c36afbc5b79..92fa36795b2cea94e40f8c395c98e5cdb59c1e83 100644 (file)
@@ -33,6 +33,8 @@ Creature::Creature(world::Simulation &sim)
 , genome()
 , properties()
 , cur_prop(0)
+, base_color(1.0)
+, highlight_color(0.0)
 , mass(1.0)
 , density(1.0)
 , size(1.0)
@@ -51,8 +53,13 @@ Creature::Creature(world::Simulation &sim)
 Creature::~Creature() {
 }
 
+glm::dvec4 Creature::HighlightColor() const noexcept {
+       return glm::dvec4(highlight_color, AgeLerp(CurProps().highlight, NextProps().highlight));
+}
+
 void Creature::Grow(double amount) noexcept {
-       Mass(std::min(properties.props[cur_prop].mass, mass + amount));
+       const double max_mass = AgeLerp(CurProps().mass, NextProps().mass);
+       Mass(std::min(max_mass, mass + amount));
 }
 
 void Creature::Hurt(double dt) noexcept {
@@ -82,9 +89,12 @@ double Creature::Age() const noexcept {
        return sim.Time() - birth;
 }
 
+double Creature::AgeLerp(double from, double to) const noexcept {
+       return glm::mix(from, to, glm::smoothstep(CurProps().age, NextProps().age, Age()));
+}
+
 double Creature::Fertility() const noexcept {
-       // TODO: lerp based on age?
-       return properties.props[cur_prop].fertility / 3600.0;
+       return AgeLerp(CurProps().fertility, NextProps().fertility) / 3600.0;
 }
 
 void Creature::AddGoal(std::unique_ptr<Goal> &&g) {
@@ -103,11 +113,12 @@ bool GoalCompare(const std::unique_ptr<Goal> &a, const std::unique_ptr<Goal> &b)
 
 void Creature::Tick(double dt) {
        if (cur_prop < 5 && Age() > properties.props[cur_prop + 1].age) {
-               ++cur_prop;
-               if (cur_prop == 5) {
+               if (cur_prop == 4) {
                        std::cout << "[" << int(sim.Time()) << "s] "
                                << name << " died of old age" << std::endl;
                        Die();
+               } else {
+                       ++cur_prop;
                }
        }
 
@@ -301,26 +312,32 @@ void Spawn(Creature &c, world::Planet &p) {
        genome.properties.Birth().age = { 0.0, 0.0 };
        genome.properties.Birth().mass = { 0.5, 0.05 };
        genome.properties.Birth().fertility = { 0.0, 0.0 };
+       genome.properties.Birth().highlight = { 0.0, 0.0 };
 
        genome.properties.Child().age = { 30.0, 1.0 };
        genome.properties.Child().mass = { 0.7, 0.05 };
        genome.properties.Child().fertility = { 0.0, 0.0 };
+       genome.properties.Child().highlight = { 0.2, 0.05 };
 
        genome.properties.Youth().age = { 60.0, 5.0 };
        genome.properties.Youth().mass = { 0.9, 0.1 };
        genome.properties.Youth().fertility = { 0.5, 0.03 };
+       genome.properties.Youth().highlight = { 0.9, 0.1 };
 
        genome.properties.Adult().age = { 120.0, 10.0 };
        genome.properties.Adult().mass = { 1.2, 0.1 };
        genome.properties.Adult().fertility = { 0.4, 0.01 };
+       genome.properties.Adult().highlight = { 0.7, 0.1 };
 
        genome.properties.Elder().age = { 360.0, 30.0 };
        genome.properties.Elder().mass = { 1.0, 0.05 };
        genome.properties.Elder().fertility = { 0.1, 0.01 };
+       genome.properties.Elder().highlight = { 0.6, 0.1 };
 
        genome.properties.Death().age = { 480.0, 60.0 };
        genome.properties.Death().mass = { 0.9, 0.05 };
        genome.properties.Death().fertility = { 0.0, 0.0 };
+       genome.properties.Death().highlight = { 0.5, 0.1 };
 
        glm::dvec3 color_avg(0.0);
        double color_divisor = 0.0;
@@ -333,7 +350,7 @@ void Spawn(Creature &c, world::Planet &p) {
                        { 0.1,  0.0005 },  // penalty
                        { 0.0,  0.0 },     // growth
                });
-               color_avg += c.GetSimulation().Resources()[p.Atmosphere()].base_color;
+               color_avg += c.GetSimulation().Resources()[p.Atmosphere()].base_color * 0.1;
                color_divisor += 0.1;
        }
        if (liquid > -1) {
@@ -344,7 +361,7 @@ void Spawn(Creature &c, world::Planet &p) {
                        { 0.01, 0.002 }, // penalty
                        { 0.1, 0.0 },   // growth
                });
-               color_avg += c.GetSimulation().Resources()[liquid].base_color;
+               color_avg += c.GetSimulation().Resources()[liquid].base_color * 0.5;
                color_divisor += 0.5;
        }
        if (solid > -1) {
@@ -405,6 +422,19 @@ void Genome::Configure(Creature &c) const {
                c.AddNeed(std::move(need));
        }
 
+       glm::dvec3 base_color(
+               std::fmod(base_hue.FakeNormal(random.SNorm()) + 1.0, 1.0),
+               glm::clamp(base_saturation.FakeNormal(random.SNorm()), 0.0, 1.0),
+               glm::clamp(base_lightness.FakeNormal(random.SNorm()), 0.0, 1.0)
+       );
+       glm::dvec3 highlight_color(
+               std::fmod(base_color.x + 0.5, 1.0),
+               1.0 - base_color.y,
+               1.0 - base_color.z
+       );
+       c.BaseColor(hsl2rgb(base_color));
+       c.HighlightColor(hsl2rgb(highlight_color));
+
        c.Mass(c.GetProperties().props[0].mass);
        c.Density(mass / volume);
        c.GetSteering().MaxAcceleration(1.4);
@@ -416,7 +446,6 @@ void Genome::Configure(Creature &c) const {
 void Split(Creature &c) {
        Creature *a = new Creature(c.GetSimulation());
        const Situation &s = c.GetSituation();
-       // TODO: generate names
        a->Name(c.GetSimulation().Assets().name.Sequential());
        // TODO: mutate
        c.GetGenome().Configure(*a);
index c24a746062173b9ec5351da349e3086acede7a2f..b61c108a9b973dc618483aabdfab79eb01357959 100644 (file)
@@ -31,6 +31,8 @@ public:
        void SetV(const glm::mat4 &v) noexcept;
        void SetVP(const glm::mat4 &v, const glm::mat4 &p) noexcept;
        void SetMVP(const glm::mat4 &m, const glm::mat4 &v, const glm::mat4 &p) noexcept;
+       void SetBaseColor(const glm::vec3 &) noexcept;
+       void SetHighlightColor(const glm::vec4 &) noexcept;
        void SetTexture(ArrayTexture &) noexcept;
        void SetLight(int n, const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept;
        void SetNumLights(int n) noexcept;
@@ -55,8 +57,10 @@ private:
        GLuint m_handle;
        GLuint mv_handle;
        GLuint mvp_handle;
-       GLuint sampler_handle;
 
+       GLuint base_color_handle;
+       GLuint highlight_color_handle;
+       GLuint sampler_handle;
        GLuint num_lights_handle;
        GLuint light_handle[MAX_LIGHTS * 3];
 
index 6a08bb5f99be5402edda61b239be9e145b58cb40..0890dfdc8d308bf84f1de0c47db381bc35fca1e5 100644 (file)
@@ -546,6 +546,8 @@ CreatureSkin::CreatureSkin()
                "in vec3 frag_tex_uv;\n"
                "in vec3 normal;\n"
 
+               "uniform vec3 base_color;\n"
+               "uniform vec4 highlight_color;\n"
                "uniform sampler2DArray tex_sampler;\n"
                "uniform int num_lights;\n"
                "uniform LightSource light[8];\n"
@@ -553,14 +555,15 @@ CreatureSkin::CreatureSkin()
                "out vec3 color;\n"
 
                "void main() {\n"
-                       "vec3 tex_color = texture(tex_sampler, frag_tex_uv).rgb;\n"
-                       "vec3 total_light = tex_color * vec3(0.1, 0.1, 0.1);\n"
+                       "vec4 tex_color = texture(tex_sampler, frag_tex_uv);\n"
+                       "vec3 mat_color = mix(base_color, highlight_color.rgb, tex_color.r * tex_color.a * highlight_color.a);\n"
+                       "vec3 total_light = mat_color * vec3(0.1, 0.1, 0.1);\n"
                        "for (int i = 0; i < num_lights; ++i) {\n"
                                "vec3 to_light = light[i].position - vtx_viewspace;\n"
                                "float distance = length(to_light) + length(vtx_viewspace);\n"
                                "vec3 light_dir = normalize(to_light);\n"
                                "float attenuation = light[i].strength / (distance * distance);\n"
-                               "vec3 diffuse = attenuation * max(0.0, dot(normal, light_dir)) * light[i].color * tex_color;\n"
+                               "vec3 diffuse = attenuation * max(0.0, dot(normal, light_dir)) * light[i].color * mat_color;\n"
                                "vec3 view_dir = vec3(0.0, 0.0, 1.0);\n"
                                "vec3 specular = vec3(0.0, 0.0, 0.0);\n"
                                "if (dot(normal, light_dir) >= 0.0) {\n"
@@ -579,6 +582,8 @@ CreatureSkin::CreatureSkin()
        m_handle = prog.UniformLocation("M");
        mv_handle = prog.UniformLocation("MV");
        mvp_handle = prog.UniformLocation("MVP");
+       base_color_handle = prog.UniformLocation("base_color");
+       highlight_color_handle = prog.UniformLocation("highlight_color");
        sampler_handle = prog.UniformLocation("tex_sampler");
        num_lights_handle = prog.UniformLocation("num_lights");
        for (int i = 0; i < MAX_LIGHTS; ++i) {
@@ -636,6 +641,14 @@ void CreatureSkin::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::m
        prog.Uniform(mvp_handle, mvp);
 }
 
+void CreatureSkin::SetBaseColor(const glm::vec3 &c) noexcept {
+       prog.Uniform(base_color_handle, c);
+}
+
+void CreatureSkin::SetHighlightColor(const glm::vec4 &c) noexcept {
+       prog.Uniform(highlight_color_handle, c);
+}
+
 void CreatureSkin::SetTexture(ArrayTexture &tex) noexcept {
        glActiveTexture(GL_TEXTURE0);
        tex.Bind();
index 46843db4ca2850603d4ca9001dab12b1cc302bae..80126aaa31908e7d309d68ac4fdbeba58da2013a 100644 (file)
@@ -55,8 +55,8 @@ template<class T>
 inline T hsl2rgb(const T &hsl) {
        using Vec3 = glm::tvec3<typename T::value_type>;
        using Vec4 = glm::tvec4<typename T::value_type>;
-       const Vec4 K(0.0, -1.0/3.0, 2.0/3.0, -1.0);
-       const Vec3 p(glm::abs(glm::fract(Vec3(hsl.h) + Vec3(K)) * 6.0 - Vec3(K.w)));
+       const Vec4 K(1.0, 2.0/3.0, 1.0/3.0, 3.0);
+       const Vec3 p(glm::abs(glm::fract(Vec3(hsl.x) + Vec3(K)) * 6.0 - Vec3(K.w)));
        T rgb = hsl.z * glm::mix(Vec3(K.x), glm::clamp(p - Vec3(K.x), 0.0, 1.0), hsl.y);
        return rgb;
 }
index eee12833b39ca80d467d0f8fc19868284f796419..dd7d28d3d06d34c92095df1a4c126ba8a44e2bd5 100644 (file)
@@ -347,34 +347,34 @@ void Planet::BuildVAO(const Set<TileType> &ts) {
                        for (int y = 0; y < sidelength; ++y) {
                                for (int x = 0; x < sidelength; ++x, ++index) {
                                        float tex = ts[TileAt(surface, x, y).type].texture;
-                                       const float tex_u_begin = surface < 3 ? 1.0f : 0.0f;
-                                       const float tex_u_end = surface < 3 ? 0.0f : 1.0f;
+                                       const float tex_v_begin = surface < 3 ? 1.0f : 0.0f;
+                                       const float tex_v_end = surface < 3 ? 0.0f : 1.0f;
                                        attrib[4 * index + 0].position[(surface + 0) % 3] = x + 0 - offset;
                                        attrib[4 * index + 0].position[(surface + 1) % 3] = y + 0 - offset;
                                        attrib[4 * index + 0].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
-                                       attrib[4 * index + 0].tex_coord[0] = tex_u_begin;
-                                       attrib[4 * index + 0].tex_coord[1] = 1.0f;
+                                       attrib[4 * index + 0].tex_coord[0] = 0.0f;
+                                       attrib[4 * index + 0].tex_coord[1] = tex_v_begin;
                                        attrib[4 * index + 0].tex_coord[2] = tex;
 
                                        attrib[4 * index + 1].position[(surface + 0) % 3] = x + 0 - offset;
                                        attrib[4 * index + 1].position[(surface + 1) % 3] = y + 1 - offset;
                                        attrib[4 * index + 1].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
-                                       attrib[4 * index + 1].tex_coord[0] = tex_u_end;
-                                       attrib[4 * index + 1].tex_coord[1] = 1.0f;
+                                       attrib[4 * index + 1].tex_coord[0] = 0.0f;
+                                       attrib[4 * index + 1].tex_coord[1] = tex_v_end;
                                        attrib[4 * index + 1].tex_coord[2] = tex;
 
                                        attrib[4 * index + 2].position[(surface + 0) % 3] = x + 1 - offset;
                                        attrib[4 * index + 2].position[(surface + 1) % 3] = y + 0 - offset;
                                        attrib[4 * index + 2].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
-                                       attrib[4 * index + 2].tex_coord[0] = tex_u_begin;
-                                       attrib[4 * index + 2].tex_coord[1] = 0.0f;
+                                       attrib[4 * index + 2].tex_coord[0] = 1.0f;
+                                       attrib[4 * index + 2].tex_coord[1] = tex_v_begin;
                                        attrib[4 * index + 2].tex_coord[2] = tex;
 
                                        attrib[4 * index + 3].position[(surface + 0) % 3] = x + 1 - offset;
                                        attrib[4 * index + 3].position[(surface + 1) % 3] = y + 1 - offset;
                                        attrib[4 * index + 3].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
-                                       attrib[4 * index + 3].tex_coord[0] = tex_u_end;
-                                       attrib[4 * index + 3].tex_coord[1] = 0.0f;
+                                       attrib[4 * index + 3].tex_coord[0] = 1.0f;
+                                       attrib[4 * index + 3].tex_coord[1] = tex_v_end;
                                        attrib[4 * index + 3].tex_coord[2] = tex;
                                }
                        }