feat(of): ImageVis fx + 14 OS logos demos
ImageVis : charge un PNG et l'anime avec effets demoscene : - Mirror reflection bas (flip Y alpha gradient) - Ghost trail 3 couches en arrière (RGB shifted) - Chromatic aberration RGB (rouge gauche / bleu droite, kick boost) - Twister wobble : 12 bandes horizontales avec offset X sin(t,y) - Scanlines CRT 3px - Glitch tear horizontal sur kick > 0.5 - Boost luminance global sur kick 14 nouveaux BgKind (ImgWin1/311/95, ImgLotus, ImgDos, ImgAtari, ImgApple, ImgWB, ImgNeXT, ImgBeOS, ImgOS2, ImgIrix, ImgZX, ImgC64) qui chargent leurs PNG respectifs depuis sprites/. Intégrations dans démos : - AMIGA : ajout WORKBENCH (ImgWB) avec narration DH0 - C64 : BOOT acte utilise maintenant ImgC64 - INFERNO : ajout DOS PROMPT acte (ImgDos) - MEMORY LANE : ajout NEXTSTEP + BEOS actes - GREETINGS : 7 nouveaux actes 12s parade des logos OS WIN 1.0 / LOTUS 123 / ATARI / APPLE 6 / OS/2 WARP / IRIX SGI / ZX SPECTRUM GREETINGS demo passe de 11 à 18 actes (parade complète).
This commit is contained in:
+83
-5
@@ -135,6 +135,24 @@ void ofApp::setup() {
|
||||
oceanLoader_ = std::make_unique<oscope::ShaderVis>("shaders/ocean_loader");
|
||||
win95_ = std::make_unique<oscope::ShaderVis>("shaders/win95");
|
||||
sphereWave_ = std::make_unique<oscope::SphereWaveVis>();
|
||||
auto img = [](const char* fn){
|
||||
return std::make_unique<oscope::ImageVis>(
|
||||
ofToDataPath(std::string("sprites/") + fn, true));
|
||||
};
|
||||
imgWin1_ = img("windows_1_0.png");
|
||||
imgWin311_ = img("windows_311.png");
|
||||
imgWin95_ = img("windows_95.png");
|
||||
imgLotus_ = img("lotus_123.png");
|
||||
imgDos_ = img("msdos.png");
|
||||
imgAtari_ = img("atari_fuji.png");
|
||||
imgApple_ = img("apple_rainbow.png");
|
||||
imgWB_ = img("amiga_wb.png");
|
||||
imgNeXT_ = img("nextstep.png");
|
||||
imgBeOS_ = img("beos.png");
|
||||
imgOS2_ = img("os2_warp.png");
|
||||
imgIrix_ = img("irix.png");
|
||||
imgZX_ = img("zx_spectrum.png");
|
||||
imgC64_ = img("c64_basic.png");
|
||||
lissajous_->setup(W, H);
|
||||
spectro_->setup(W, H / 4);
|
||||
reactive_->setup(W, H);
|
||||
@@ -196,6 +214,12 @@ void ofApp::setup() {
|
||||
oceanLoader_->setup(W, H);
|
||||
win95_->setup(W, H);
|
||||
sphereWave_->setup(W, H);
|
||||
imgWin1_->setup(W, H); imgWin311_->setup(W, H); imgWin95_->setup(W, H);
|
||||
imgLotus_->setup(W, H); imgDos_->setup(W, H);
|
||||
imgAtari_->setup(W, H); imgApple_->setup(W, H);
|
||||
imgWB_->setup(W, H); imgNeXT_->setup(W, H); imgBeOS_->setup(W, H);
|
||||
imgOS2_->setup(W, H); imgIrix_->setup(W, H);
|
||||
imgZX_->setup(W, H); imgC64_->setup(W, H);
|
||||
|
||||
postfx_.setup(W, H);
|
||||
|
||||
@@ -416,6 +440,12 @@ void ofApp::update() {
|
||||
oceanLoader_->update(frame);
|
||||
win95_->update(frame);
|
||||
sphereWave_->update(frame);
|
||||
imgWin1_->update(frame); imgWin311_->update(frame); imgWin95_->update(frame);
|
||||
imgLotus_->update(frame); imgDos_->update(frame);
|
||||
imgAtari_->update(frame); imgApple_->update(frame);
|
||||
imgWB_->update(frame); imgNeXT_->update(frame); imgBeOS_->update(frame);
|
||||
imgOS2_->update(frame); imgIrix_->update(frame);
|
||||
imgZX_->update(frame); imgC64_->update(frame);
|
||||
|
||||
applyOscFx();
|
||||
|
||||
@@ -590,15 +620,19 @@ void ofApp::initDemos() {
|
||||
" PYRAMID OF MEMORY GIZA OF VECTORS "
|
||||
" A 4-SIDED MONUMENT FROM 1986 ", "B",
|
||||
BgKind::Pyramid},
|
||||
{"WORKBENCH", 22.0f, polSpe(), SS::Cascade,
|
||||
" WORKBENCH 1.3 KICKSTART READY "
|
||||
" DH0: DISK CONTAINS THE DEMO ", "M",
|
||||
BgKind::ImgWB},
|
||||
}};
|
||||
|
||||
// ─── 2 · C64 LOWLIFE ─────────────────────────────────────
|
||||
demos_[1] = {"C64 LOWLIFE", {
|
||||
{"BOOT", 15.0f, stars(), SS::Glitch,
|
||||
{"BOOT", 18.0f, stars(), SS::Glitch,
|
||||
" **** COMMODORE 64 BASIC V2 **** "
|
||||
" 64K RAM SYSTEM 38911 BASIC BYTES FREE "
|
||||
" READY. LOAD \"DEMO\",8,1 SEARCHING FOR DEMO ", "N",
|
||||
BgKind::Starfield},
|
||||
BgKind::ImgC64},
|
||||
{"PLASMA", 25.0f, all(), SS::Wavy3D,
|
||||
" *** PLASMA EFFECT *** SID CHIP 6581 SCREAMING "
|
||||
" 8 COULEURS INDEXEES PALETTE FIXE "
|
||||
@@ -763,9 +797,16 @@ void ofApp::initDemos() {
|
||||
|
||||
// ─── 9 · MEMORY LANE ─────────────────────────────────────
|
||||
demos_[8] = {"MEMORY LANE", {
|
||||
{"REWIND", 20.0f, starsWave(), SS::Mirror,
|
||||
{"REWIND", 18.0f, starsWave(), SS::Mirror,
|
||||
" *** AESTHETIC MODE *** SLOWING DOWN "
|
||||
" LET THE TAPE WHIRR ", "U", BgKind::Rotozoom},
|
||||
{"NEXTSTEP", 18.0f, polSpe(), SS::Chrome,
|
||||
" NEXTSTEP / OPENSTEP 1989 PURE OBJC ELEGANCE "
|
||||
" GREETINGS TO STEVE JOBS AND BERTRAND SERLET ", "U",
|
||||
BgKind::ImgNeXT},
|
||||
{"BEOS", 18.0f, polSpe(), SS::Cascade,
|
||||
" BEOS R5 1995 MULTITASK BEAUTIFUL "
|
||||
" JEAN LOUIS GASSEE WAS RIGHT ", "R", BgKind::ImgBeOS},
|
||||
{"STATUE", 30.0f, polSpe(), SS::Chrome,
|
||||
" AN ANGEL FROM THE STANFORD ARCHIVE "
|
||||
" LUCY 50K POINTS MARBLE FROZEN IN TIME ", "R",
|
||||
@@ -805,10 +846,29 @@ void ofApp::initDemos() {
|
||||
" TWISTER BARS SPACEBALLS STYLE ", "G", BgKind::Twister},
|
||||
{"COPPER", 15.0f, all(), SS::Rainbow,
|
||||
" COPPER LIST POETRY ", "G", BgKind::Twister},
|
||||
{"FRACTAL", 18.0f, all(), SS::Wavy3D,
|
||||
{"FRACTAL", 15.0f, all(), SS::Wavy3D,
|
||||
" FRACTAL ITERATIONS ", "L", BgKind::Kifs},
|
||||
{"MOBIUS", 18.0f, all(), SS::Mirror,
|
||||
{"MOBIUS", 15.0f, all(), SS::Mirror,
|
||||
" IMPOSSIBLE TOPOLOGY ", "L", BgKind::Mobius},
|
||||
{"WIN 1.0", 12.0f, polSpe(), SS::Bouncy,
|
||||
" 1985 WINDOWS 1.0 ", "M", BgKind::ImgWin1},
|
||||
{"LOTUS 123", 12.0f, polSpe(), SS::Cascade,
|
||||
" LOTUS 1-2-3 SPREADSHEET KING 1983 ", "M",
|
||||
BgKind::ImgLotus},
|
||||
{"ATARI", 12.0f, polSpe(), SS::Rainbow,
|
||||
" ATARI 1972 GAME OVER OR NEW HIGH SCORE ", "M",
|
||||
BgKind::ImgAtari},
|
||||
{"APPLE 6", 12.0f, polSpe(), SS::Mirror,
|
||||
" APPLE RAINBOW LOGO 1977 ", "M", BgKind::ImgApple},
|
||||
{"OS/2 WARP", 12.0f, polSpe(), SS::Cascade,
|
||||
" OS/2 WARP IBM 1996 "
|
||||
" THE OS THAT COULD HAVE BEEN ", "M", BgKind::ImgOS2},
|
||||
{"IRIX SGI", 12.0f, polSpe(), SS::Chrome,
|
||||
" SILICON GRAPHICS IRIX JURASSIC PARK MAGIC ",
|
||||
"M", BgKind::ImgIrix},
|
||||
{"ZX SPECTRUM",12.0f, polSpe(), SS::Rainbow,
|
||||
" SINCLAIR 1982 UK COMPUTING REVOLUTION ", "M",
|
||||
BgKind::ImgZX},
|
||||
{"ROLL CALL", 35.0f, all(), SS::Rainbow,
|
||||
" GREETINGS TO :: KXKM CREW :: HYPNEUM LAB :: SUPERCOLLIDER ::"
|
||||
" OPENFRAMEWORKS HACKERS :: COOKIE COLLECTIVE :: ALL LIVE CODERS "
|
||||
@@ -863,6 +923,10 @@ void ofApp::initDemos() {
|
||||
{"WILDFIRE", 25.0f, all(), SS::Glitch,
|
||||
" FLAMES RISE FAST EVERY KICK FUELS THE BLAZE "
|
||||
" GREETINGS TO HARDCODE AND TITAN ", "T", BgKind::Vortex},
|
||||
{"DOS PROMPT", 20.0f, polSpe(), SS::Glitch,
|
||||
" C:\\DEMOS\\>RUN INFERNO.EXE "
|
||||
" 640K OUGHT TO BE ENOUGH FOR ANYBODY ", "E",
|
||||
BgKind::ImgDos},
|
||||
{"FORGE", 25.0f, polSpe(), SS::Cascade,
|
||||
" THE METAL MELTS GEAR TURNS IN MOLTEN STEEL "
|
||||
" HEPHAESTUS WORKS THE ANVIL ", "P", BgKind::Gear},
|
||||
@@ -1232,6 +1296,20 @@ void ofApp::drawScope4(int W, int H) {
|
||||
case BgKind::OceanLoader: oceanLoader_->draw(0, 0, W, H); break;
|
||||
case BgKind::Win95: win95_->draw(0, 0, W, H); break;
|
||||
case BgKind::SphereWave: sphereWave_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgWin1: imgWin1_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgWin311: imgWin311_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgWin95: imgWin95_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgLotus: imgLotus_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgDos: imgDos_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgAtari: imgAtari_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgApple: imgApple_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgWB: imgWB_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgNeXT: imgNeXT_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgBeOS: imgBeOS_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgOS2: imgOS2_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgIrix: imgIrix_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgZX: imgZX_->draw(0, 0, W, H); break;
|
||||
case BgKind::ImgC64: imgC64_->draw(0, 0, W, H); break;
|
||||
}
|
||||
|
||||
// 1bis) HUD pseudo-aléatoire de valeurs sub-10 Hz.
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "visualizers/VectorCubesVis.h"
|
||||
#include "visualizers/ModelVis.h"
|
||||
#include "visualizers/SphereWaveVis.h"
|
||||
#include "visualizers/ImageVis.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -104,7 +105,10 @@ private:
|
||||
BoingBall, Mode7, PlasmaC64, DotTunnel,
|
||||
Gear, Cone, Pyramid, Rose3d, Geosphere, DNA,
|
||||
Workbench, MacOSClassic, AtariFuji, OceanLoader, Win95,
|
||||
SphereWave };
|
||||
SphereWave,
|
||||
ImgWin1, ImgWin311, ImgWin95, ImgLotus, ImgDos,
|
||||
ImgAtari, ImgApple, ImgWB, ImgNeXT, ImgBeOS,
|
||||
ImgOS2, ImgIrix, ImgZX, ImgC64 };
|
||||
struct DemoScene {
|
||||
const char* name;
|
||||
float durSec;
|
||||
@@ -219,6 +223,10 @@ private:
|
||||
std::unique_ptr<oscope::ShaderVis> oceanLoader_;
|
||||
std::unique_ptr<oscope::ShaderVis> win95_;
|
||||
std::unique_ptr<oscope::SphereWaveVis> sphereWave_;
|
||||
std::unique_ptr<oscope::ImageVis> imgWin1_, imgWin311_, imgWin95_;
|
||||
std::unique_ptr<oscope::ImageVis> imgLotus_, imgDos_, imgAtari_, imgApple_;
|
||||
std::unique_ptr<oscope::ImageVis> imgWB_, imgNeXT_, imgBeOS_, imgOS2_;
|
||||
std::unique_ptr<oscope::ImageVis> imgIrix_, imgZX_, imgC64_;
|
||||
|
||||
std::vector<float> ch1_, ch2_;
|
||||
Mode mode_ = Mode::Scope4;
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
#pragma once
|
||||
|
||||
// ImageVis : charge un PNG et l'affiche en background animé.
|
||||
// Animations : zoom pulsé sur kick, slow drift, hue cycle, scanlines CRT,
|
||||
// flicker pour effet rétro.
|
||||
|
||||
#include "Visualizer.h"
|
||||
#include "ofMain.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace oscope {
|
||||
|
||||
class ImageVis : public Visualizer {
|
||||
public:
|
||||
explicit ImageVis(const std::string& spritePath)
|
||||
: spritePath_(spritePath) {}
|
||||
|
||||
void setup(int w, int h) override {
|
||||
w_ = w; h_ = h;
|
||||
img_.load(spritePath_);
|
||||
if (img_.isAllocated()) {
|
||||
img_.setImageType(OF_IMAGE_COLOR_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
void update(const VisFrame& frame) override {
|
||||
t_ += static_cast<float>(ofGetLastFrameTime());
|
||||
bass_ = frame.bands.bass;
|
||||
mid_ = frame.bands.mid;
|
||||
treble_ = frame.bands.treble;
|
||||
kick_ = frame.bands.kick;
|
||||
}
|
||||
|
||||
void draw(int x, int y, int w, int h) override {
|
||||
if (!img_.isAllocated()) {
|
||||
ofPushStyle();
|
||||
ofSetColor(40);
|
||||
ofDrawRectangle(x, y, w, h);
|
||||
ofSetColor(255, 80, 80);
|
||||
ofDrawBitmapString("sprite missing : " + spritePath_, x+12, y+24);
|
||||
ofPopStyle();
|
||||
return;
|
||||
}
|
||||
ofPushStyle();
|
||||
// Fond noir
|
||||
ofSetColor(0);
|
||||
ofDrawRectangle(x, y, w, h);
|
||||
|
||||
// Calcule taille image affichée — fit dans la moitié de l'écran
|
||||
const float aspect = static_cast<float>(img_.getWidth()) /
|
||||
std::max(1.0f, static_cast<float>(img_.getHeight()));
|
||||
float drawH = static_cast<float>(h) * 0.65f;
|
||||
float drawW = drawH * aspect;
|
||||
if (drawW > w * 0.85f) {
|
||||
drawW = w * 0.85f;
|
||||
drawH = drawW / aspect;
|
||||
}
|
||||
// Pulse sur kick + lente respiration
|
||||
const float pulse = 1.0f + kick_ * 0.15f
|
||||
+ std::sin(t_ * 0.7f) * 0.04f;
|
||||
drawW *= pulse;
|
||||
drawH *= pulse;
|
||||
|
||||
// Drift lent X/Y
|
||||
const float dx = std::sin(t_ * 0.3f) * (w * 0.04f);
|
||||
const float dy = std::cos(t_ * 0.4f) * (h * 0.03f);
|
||||
const float cx = x + w * 0.5f + dx;
|
||||
const float cy = y + h * 0.5f + dy;
|
||||
|
||||
// Tint hue cycle léger sur les blancs/clairs (multiply mode visible)
|
||||
ofColor tint;
|
||||
tint.setHsb(static_cast<int>(std::fmod(t_ * 12.0f, 255.0f)),
|
||||
50,
|
||||
240);
|
||||
// Flicker pseudo-aléatoire occasionnel (vintage CRT)
|
||||
if (std::fmod(t_, 3.0f) < 0.05f) tint.a = 220;
|
||||
else tint.a = 255;
|
||||
|
||||
// === Effets demoscene sur l'image ===
|
||||
const float ix = cx - drawW * 0.5f;
|
||||
const float iy = cy - drawH * 0.5f;
|
||||
|
||||
// 1) Réflexion bas (mirror) — flip Y avec alpha gradient
|
||||
ofPushMatrix();
|
||||
ofTranslate(cx, iy + drawH * 1.95f);
|
||||
ofScale(1.0f, -0.7f, 1.0f);
|
||||
ofSetColor(255, 255, 255, 100);
|
||||
img_.draw(-drawW * 0.5f, 0, drawW, drawH);
|
||||
ofPopMatrix();
|
||||
|
||||
// 2) Ghost trail derrière — 3 copies offsets
|
||||
for (int g = 3; g >= 1; --g) {
|
||||
const float ox = std::cos(t_ * 0.6f + g) * 12.0f * g;
|
||||
const float oy = std::sin(t_ * 0.5f + g) * 8.0f * g;
|
||||
ofSetColor(180, 200, 255, 50 / g);
|
||||
img_.draw(ix + ox, iy + oy, drawW, drawH);
|
||||
}
|
||||
|
||||
// 3) Chromatic aberration RGB — 3 passes avec offset radial
|
||||
const float chroma = 4.0f + kick_ * 8.0f;
|
||||
ofEnableBlendMode(OF_BLENDMODE_ADD);
|
||||
ofSetColor(255, 0, 0, 80);
|
||||
img_.draw(ix - chroma, iy, drawW, drawH);
|
||||
ofSetColor(0, 0, 255, 80);
|
||||
img_.draw(ix + chroma, iy, drawW, drawH);
|
||||
ofDisableBlendMode();
|
||||
|
||||
// 4) Image principale tinted
|
||||
ofSetColor(tint);
|
||||
img_.draw(ix, iy, drawW, drawH);
|
||||
|
||||
// 5) Twister wobble : image redessinée découpée en 8 bandes
|
||||
// horizontales avec offset X par sin(y, t). Effet "wave".
|
||||
if (std::fmod(t_, 6.0f) < 2.5f) { // toggle pour pas saturer
|
||||
ofSetColor(255, 255, 255, 80);
|
||||
const int slices = 12;
|
||||
for (int s = 0; s < slices; ++s) {
|
||||
const float sy = drawH * s / slices;
|
||||
const float sh = drawH / slices + 1.0f;
|
||||
const float ox = std::sin(t_ * 2.0f + s * 0.7f) *
|
||||
(4.0f + bass_ * 12.0f);
|
||||
// Subset region : on dessine la bande cropée
|
||||
img_.drawSubsection(ix + ox, iy + sy, drawW, sh,
|
||||
0, img_.getHeight() * s / slices,
|
||||
img_.getWidth(),
|
||||
img_.getHeight() / slices + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// 6) Scanlines CRT
|
||||
ofSetColor(0, 0, 0, 40);
|
||||
for (int sy = y; sy < y + h; sy += 3) {
|
||||
ofDrawRectangle(x, sy, w, 1);
|
||||
}
|
||||
|
||||
// 7) Glitch tear horizontal — bandes qui glissent aléatoirement
|
||||
if (kick_ > 0.5f) {
|
||||
ofSetColor(255, 100, 200,
|
||||
static_cast<int>(60 * std::min(1.0f, kick_ * 2.0f)));
|
||||
const int gh = 3;
|
||||
for (int gy = static_cast<int>(iy); gy < iy + drawH; gy += 18) {
|
||||
const float gx = ofRandom(-30, 30);
|
||||
ofDrawRectangle(ix + gx, gy, drawW, gh);
|
||||
}
|
||||
}
|
||||
|
||||
// 8) Boost luminance sur kick
|
||||
if (kick_ > 0.4f) {
|
||||
ofSetColor(255, 220, 180,
|
||||
static_cast<int>(80 * std::min(1.0f, kick_ * 2.0f)));
|
||||
ofDrawRectangle(x, y, w, h);
|
||||
}
|
||||
ofPopStyle();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string spritePath_;
|
||||
int w_ = 0, h_ = 0;
|
||||
ofImage img_;
|
||||
float t_ = 0.0f;
|
||||
float bass_ = 0, mid_ = 0, treble_ = 0, kick_ = 0;
|
||||
};
|
||||
|
||||
} // namespace oscope
|
||||
Reference in New Issue
Block a user