From e0c2247aa019eb49c29672a833920a36806e8ad8 Mon Sep 17 00:00:00 2001 From: Micah Elizabeth Scott <micah@scanlime.org> Date: Mon, 10 Mar 2014 16:38:50 -0700 Subject: [PATCH] C++ Rings example: Sample colors from an image --- examples/cpp/data/sky.png | Bin 0 -> 22696 bytes examples/cpp/rings.cpp | 104 +++++++++++++++++++++++++++----------- 2 files changed, 75 insertions(+), 29 deletions(-) create mode 100644 examples/cpp/data/sky.png diff --git a/examples/cpp/data/sky.png b/examples/cpp/data/sky.png new file mode 100644 index 0000000000000000000000000000000000000000..587b869486d85ed42389db7a31a33255bb4f9654 GIT binary patch literal 22696 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	flRAK<9`;tt>Iu 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 literal 0 HcmV?d00001 diff --git a/examples/cpp/rings.cpp b/examples/cpp/rings.cpp index 7807607..d15b7aa 100644 --- a/examples/cpp/rings.cpp +++ b/examples/cpp/rings.cpp @@ -1,6 +1,8 @@ /* * Three-dimensional pattern in C++ based on the "Rings" Processing example. * + * This version samples colors from an image, rather than using the HSV colorspace. + * * Uses noise functions modulated by sinusoidal rings, which themselves * wander and shift according to some noise functions. * @@ -8,80 +10,124 @@ */ #include <math.h> +#include <time.h> +#include <stdlib.h> #include "lib/color.h" #include "lib/effect.h" #include "lib/noise.h" +#include "lib/texture.h" class Rings : public Effect { public: Rings() - : d(0, 0, 0, 0) {} + : palette("data/sky.png"), + d(0, 0, 0, 0), + threshold(-1.0) + { + srand(time(0)); + seed = fmod(rand() / 1e3, 1e3); + } static const float xyzSpeed = 0.6; static const float xyzScale = 0.08; static const float wSpeed = 0.2; - static const float wRate = 0.001; + static const float wRate = 0.015; static const float ringScale = 1.5; static const float ringScaleRate = 0.01; static const float ringDepth = 0.2; static const float wanderSpeed = 0.04; - static const float wanderSize = 1.8; - static const float hueScale = 5.0; - static const float hueRate = 0.001; + static const float wanderSize = 1.2; + static const float brightnessContrast = 15.0; + static const float colorContrast = 2.0; + static const float targetBrightness = 0.1; + static const float thresholdGain = 0.1; + + // Sample colors along a curved path through a texture + Texture palette; + + // Pseudorandom number seed + float seed; // State variables Vec4 d; + float threshold; // Calculated once per frame - float hue, saturation; float spacing; + float colorParam; + float pixelTotal; + unsigned pixelCount; Vec3 center; virtual void beginFrame(const FrameInfo &f) { - hue = noise2(f.time * hueRate, 20.5) * hueScale; - - saturation = sq(std::min(std::max(0.7f * (0.5f + noise2(f.time * 0.01, 0.5)), 0.0f), 1.0f)); spacing = sq(0.5 + noise2(f.time * ringScaleRate, 1.5)) * ringScale; // Rotate movement in the XZ plane - float angle = noise2(f.time * 0.01, 30.5) * 10.0; - float speed = pow(fabsf(noise2(f.time * 0.01, 40.5)), 2.5) * xyzSpeed; + float angle = noise2(f.time * 0.01, seed + 30.5) * 10.0; + float speed = pow(fabsf(noise2(f.time * 0.01, seed + 40.5)), 2.5) * xyzSpeed; d[0] += cosf(angle) * speed * f.timeDelta; d[2] += sinf(angle) * speed * f.timeDelta; // Random wander along the W axis - d[3] += noise2(f.time * wRate, 3.5) * wSpeed * f.timeDelta; + d[3] += noise2(f.time * wRate, seed + 3.5) * wSpeed * f.timeDelta; // Update center position - center = Vec3(noise2(f.time * wanderSpeed, 50.9), - noise2(f.time * wanderSpeed, 51.4), - noise2(f.time * wanderSpeed, 51.7)) * wanderSize; - } + center = Vec3(noise2(f.time * wanderSpeed, seed + 50.9), + noise2(f.time * wanderSpeed, seed + 51.4), + noise2(f.time * wanderSpeed, seed + 51.7)) * wanderSize; - virtual void debug(const DebugInfo &di) - { - fprintf(stderr, "\t[rings] center = %f, %f, %f\n", center[0], center[1], center[2]); - fprintf(stderr, "\t[rings] d = %f, %f, %f, %f\n", d[0], d[1], d[2], d[3]); - fprintf(stderr, "\t[rings] hue = %f, saturation = %f\n", hue, saturation); + // Wander around the color palette + colorParam = seed + f.time * 0.05f; + + // Reset pixel total accumulators, used for the brightness calc in endFrame + pixelTotal = 0; + pixelCount = 0; } virtual void calculatePixel(Vec3& rgb, const PixelInfo &p) { float dist = len(p.point - center); Vec4 pulse = Vec4(sinf(d[2] + dist * spacing) * ringDepth, 0, 0, 0); - Vec4 s = Vec4(p.point * xyzScale, 0) + d; + Vec4 s = Vec4(p.point * xyzScale, seed) + d; Vec4 chromaOffset = Vec4(0, 0, 0, 10); - float n = fbm_noise4(s + pulse, 4) * 2.5f + 0.1f; - float m = fbm_noise4(s + chromaOffset, 2); + float n = (fbm_noise4(s + pulse, 4) + threshold) * brightnessContrast; + float m = fbm_noise4(s + chromaOffset, 2) * colorContrast; + + rgb = color(colorParam + m, sq(std::max(0.0f, n))); - hsv2rgb(rgb, - hue + 0.5 * m, - saturation, - std::min(0.9f, sq(std::max(0.0f, n))) - ); + // Keep a rough approximate brightness total, for closed-loop feedback + for (unsigned i = 0; i < 3; i++) { + pixelTotal += sq(std::min(1.0f, std::max(0.0f, rgb[i]))); + pixelCount++; + } + } + + virtual void endFrame(const FrameInfo &f) + { + // Adjust threshold in brightness-determining noise function, in order + // to try and keep the average pixel brightness at a particular level. + + if (pixelCount > 0) { + threshold += (targetBrightness - pixelTotal / pixelCount) * thresholdGain; + } + } + + virtual void debug(const DebugInfo &di) + { + fprintf(stderr, "\t[rings] seed = %f\n", seed); + fprintf(stderr, "\t[rings] center = %f, %f, %f\n", center[0], center[1], center[2]); + fprintf(stderr, "\t[rings] d = %f, %f, %f, %f\n", d[0], d[1], d[2], d[3]); + fprintf(stderr, "\t[rings] threshold = %f\n", threshold); + } + + virtual Vec3 color(float parameter, float brightness) + { + // Sample a color from our palette, using a lissajous curve within an image texture + return palette.sample( sinf(parameter) * 0.5f + 0.5f, + sinf(parameter * 0.86f) * 0.5f + 0.5f) * brightness; } }; -- GitLab