0x499f…3001

All memos sent from and to 0x499f…3001.

PILLARSstyle.immutables.artbody { background-color: #0d0d0d; color: #ffffff; } .bg-light { background-color: #0d0d0d!important; } h1, h2, h3 { color: #ffffff; } .text-white { color: #ffffff!important; } .btn-success { background-color: #ffffff; border-color: #ffffff; color: #0d0d0d; } .btn-success:hover { background-color: #ececec; border-color: #ececec; color: #0d0d0d; } .btn-success:focus { background-color: #ffffff; border-color: #ffffff; box-shadow: none; } .btn-secondary { background-color: #1a1a1a; border-color: #333333; color: #ffffff; } .btn-secondary:hover { background-color: #1a1a1a; border-color: #8d8d8d; color: #ffffff; } .btn-secondary:focus { background-color: #1a1a1a; border-color: #333333; box-shadow: none; } .btn-outline-secondary { border-color: transparent; color: #666666; } .btn-outline-secondary:hover { color: #ffffff; background-color: transparent; border-color: #8d8d8d; } .btn-outline-secondary:not(:disabled):not(.disabled):active { color: #ffffff; background-color: transparent; border-color: #ffffff; } .btn-outline-secondary:focus { box-shadow: none; } .btn:focus { box-shadow: none; } .btn-info { color: #666666; background-color: transparent; border-color: transparent; } .btn-info:hover { color: #8d8d8d; background-color: transparent; border-color: #8d8d8d; } .btn-warning { color: #666666; background-color: transparent; border-color: transparent; } .btn-warning:hover { color: #a4a4a4; background-color: transparent; border-color: #a4a4a4; } .btn-outline-warning { color: #a4a4a4; border-color: #a4a4a4; } .btn-outline-warning:hover { color: #ffffff; background-color: #1a1a1a; border-color: #ffffff; } .modal-content { background-color: #0d0d0df7; color: #ffffff; } .modal-header { border-bottom: 1px solid #333333; } .modal-footer { border-top: 1px solid #333333; align-items: center; justify-content: center; } .close { color: #666666; } .close:hover { color: #ffffff; } .table { color: #ececec; } .table td { border-top: 1px solid #333333; } .table-bordered td, .table-bordered th { border: 1px solid #333333; } .form-control { color: #ffffff; background-color: transparent; border: 1px solid #333333; } .form-control:focus { color: #ffffff; background-color: transparent; border-color: #8d8d8d; box-shadow: none; } .input-group-text { color: #666666; background-color: transparent; border: 0; } .nav-tabs { border-bottom: 1px solid #333333; } .nav-tabs .nav-link.active { color: #ffffff; background-color: transparent; border-color: #ffffff #ffffff #0d0d0d; } a { color: #666666; } a:hover { color: #ffffff; } .card { border: none; background-color: #1a1a1a; } .card-img, .card-img-bottom { background-color: #0d0d0d; border: 1px solid #333333; border-bottom: 0; cursor: zoom-in; } .overlay-dark { background-color: rgba(13,13,13,.9); border: 1px solid #333333; border-top: 0; } .navbar-toggler { background-color: #1a1a1a; } .wmde-markdown { color: #b0b0b0; } .wmde-markdown a { color: #ffffff; } .btn-primary { background-color: #8d8d8d; border-color: #8d8d8d; color: #0d0d0d; } .btn-primary:hover { background-color: #a4a4a4; border-color: #a4a4a4; color: #0d0d0d; } .btn-primary:focus { background-color: #8d8d8d; border-color: #8d8d8d; box-shadow: none; } .btn-outline-primary { color: #8d8d8d; border-color: #8d8d8d; } .btn-outline-primary:hover { color: #0d0d0d; background-color: #8d8d8d; border-color: #8d8d8d; } .btn-danger { background-color: #b6b6b6; border-color: #b6b6b6; color: #0d0d0d; } .btn-danger:hover { background-color: #cecece; border-color: #cecece; color: #0d0d0d; } .btn-outline-danger { color: #b6b6b6; border-color: #b6b6b6; } .btn-outline-danger:hover { color: #0d0d0d; background-color: #b6b6b6; border-color: #b6b6b6; } .btn-outline-success { color: #ececec; border-color: #ececec; } .btn-outline-success:hover { color: #0d0d0d; background-color: #ececec; border-color: #ececec; } .btn-outline-info { color: #9b9b9b; border-color: #9b9b9b; } .btn-outline-info:hover { color: #0d0d0d; background-color: #9b9b9b; border-color: #9b9b9b; } .form-check { color: #666666; } .d-flex { color: #ececec; }
PILLARSinfo.immutables.art# PILLARS A guidepost on the road through time. A “herm” was a stone post with a head carved into it, set at a boundary or where one road met another. They were named for Hermes — messenger, god of roads and thresholds, the one who carried word between worlds and walked travelers over the edges of things. A herm was not decoration. It was placed where a person would need it: at the fork, at the border, at the point where the way stopped being obvious. It told you where you were, and it spoke on behalf of someone not present. These are herms for a road nobody can step off. We are all traveling through time at the same speed, in one direction, without a map, and the crossings that matter are not marked on the ground. A PILLAR is a temporal guidepost set along your path. It keeps the hour, marks the season, and at the turnings it has something to say. ## It Speaks A PILLAR speaks on the new moon and on the full moon — roughly twice a month, twenty-four or twenty-five times a year. Herms stood at physical boundaries; this one speaks at temporal ones. The words are its own. **The oracle is carried inside the stone:** its learned weights, its vocabulary and the code that gives it speech are written into the work itself, and there is no puppeteer controlling it from afar. It composes each sentence in front of you from the transaction it was cast from and from the date. Ask on the same day from anywhere and you are told the same thing. What it says is not advice and is not an answer. It tells you something. What you do with it is yours. --- ## Consulting the PILLAR A PILLAR needs nothing. Neglect it for a year and it will have said twenty-five things you did not hear, and be none the worse for it. Nothing you do sustains it and nothing you neglect can harm it, which is an unusual arrangement with something you are asked to keep. You are not its caretaker. It is the one doing the tending. It keeps the months for you and hands you a sentence to carry through the fortnight. It tells you where the year has got to, what the sky is doing, when the season turns and when it will turn back. It weathers at your side for as long as you last, and then for a long time after. It does not know when you will need what it says, and does not wait to find out. It speaks on the turn of the month and leaves the sentence standing, which is why one so often seems to have been waiting for you: it spoke early and the moment caught up. ### Watch the Moon The practice is the rhythm, not the reading. Go to it at the dark moon and at the full moon — the two hinges of the month — and it will have something for you. Nothing is required of you in between. The dark moon is the closed hand: the month has not happened yet. What it says then is best taken as something to set out with. The full moon is the open one: the month is at its height and everything in it is visible, including what you would rather not look at. The same sentence lands differently on the two days, and after a year you will know which of the two your PILLAR is better at. ### Carry the Sentence Between one utterance and the next, the PILLAR holds what it last said. It does not refresh, and there is nothing else to get from it that fortnight. This is deliberate. You are meant to carry the sentence, not consume it. Read it on the day, then leave it alone and let it work on the ordinary hours — the argument you were already having, the decision you have been circling, the thing you have not said. An oracle that could be asked again immediately would only ever be a way of avoiding the first answer. Come back to it near the end of the fortnight. It will have collected whatever happened to you, which is the whole trick. ### Learn Your PILLAR Its manner is set for life and will not adjust itself to suit you. What that manner is you already know from its hexagram; what you cannot know in advance is how it wears. So watch for the preoccupation. Doors. Water. The ledger. Stone. Across several utterances you will find the thing your stone is always, in the end, talking about — which is worth more than any single sentence, because it tells you the angle everything is being said from. Do not read one utterance and decide what your PILLAR is. Read a year of them. ### Read the Six Lines On the day it changes its mind, the shaft resolves into six carved lines before it speaks. That is its hexagram, fixed at the moment it was set down and never altered. The lines are not a second prophecy. They are the announcement that what follows is new — the stone clearing its throat. If you arrive and see them, you have come on a speaking day and the words are fresh. If you arrive and see only the stone, what it tells you is what it has been telling everyone since the last turning. The figure is also the PILLAR's nature — its voice, its temperature, the words it keeps returning to — which is set out under **The Hexagram**, below. Seeing your own carved into the shaft is worth more once you know what it decides. The same figure is cut small and permanently above the brow: six strokes read left to right from the first line up, parted in the middle where a line is broken. One of the six is marked, and **only the mark moves**. The figure is cut once and never recut. What advances, on each of the four turns of the year, is which line carries the mark — so it comes back round every eighteen months, and in that time the stone has been every version of itself and none of them has been a different stone. In the old reading a changing line is what lets one figure be read through another, and it does that here. Read the marked line the other way and you have the PILLAR's relating figure: not a new hexagram for the stone, but a second one held beside its own for the season. What it lends is a subject. Your stone is still the stone of doors and gates; this season it is also thinking about water. ### Notice the Season The same stone does not say the same kind of thing as the seasons turn. The term it stands in picks which of its four manners it uses, so it moves through its own voices as the year advances and comes back round. The pattern is fixed and it is yours: another stone warns in a different month, and there is no season that is grim for all of them. The season moves one thing more, and this is the part worth watching for. At each turn the changing line advances, and the relating figure it opens onto lends the stone a second subject for the whole of that season — a preoccupation that is not its own, held beside the one that is. Four times a year the borrowed subject changes; every eighteen months the cycle returns. It is a leaning and not a takeover. Counted over many utterances a stone reaches for its own words about eighteen times in a hundred and for the borrowed ones about thirteen, against four for a figure it has nothing to do with — three times the background, and still short of its own. About one utterance in ten comes out differently for it. You will not notice it in a single reading. Over a season you will start to see what else the stone has been circling, and over eighteen months you will have watched it circle six different things and come back to the first. Its manner and its temperature are untouched by any of this. A PILLAR borrows a subject for a season; it never borrows a voice. Which means the utterances arrange into a shape you can only see across a year, and only for your own PILLAR. When a reading feels unusually hard or unusually generous, look at the term before you take it personally. You may simply have come in the cold. ### Mark the Rare Nights Sometimes the sky is doing something while it speaks, and the two are not equally rare. A PILLAR catches every eclipse of its life — all of them, without exception — and that is not luck. An eclipse can only happen at a new or full moon, and those are the only days it opens its mouth. So roughly one utterance in seven arrives during an eclipse somewhere on earth, about four a year. Frequent enough to be a rhythm rather than an omen. Meteor showers are the rare ones, because they answer to the sun rather than the moon and have no reason to fall on a speaking day. A PILLAR meets one about every eighteen months, and can go six years without. Neither makes for a better prophecy. They are marked utterances, not favored ones — and the shower nights are the ones worth writing down. ### Ask, if You Must Press **C** and it will take a question. It cannot answer, it will not try, and it knows nothing about you. It replies in its own manner, colored a little by the words you used, and it will give the same reply to the same question for ever. So asking is useful for exactly one thing, and it is not information. The reply comes back oblique, and what you notice is your own reaction to it — the reading you reach for first, the meaning you supply, the part you resist. That was the answer, and it was yours before you asked. ### The Chronicle Press **T** and the chronicle opens: the years it has spoken in, then the months of a year, then what it said in that month. Click a row to open it and the heading to come back, or use the keys — arrows move, enter goes in, escape comes back out. Nothing was recorded. There is no archive to download and no log to fetch. Knowing which years and months it spoke in costs nothing, because that follows from the moon alone — but open a month and the stone has to think, and you will feel it think. It is working that utterance out again from the transaction and the date, which is all it ever needed. The pause is not a loading bar. It is the PILLAR being asked, again, what that day was. Which has a strange consequence worth sitting with. Whoever holds a PILLAR in the distant future can recover what it said in a historic winter, and the person who owned it then need never have looked at it once. The history belongs to the stone for the benefit of those who consult it. Close it and what it worked out is gone. Nothing is lost, because none of it was ever kept. ### Keep the Record Press **S** to save the whole turn — stone, lines, words — as it moved. Press **P** for the moment you are looking at. Press **A** and the frame closes on the head: the capital, the face, the top of the shaft. It is the same stone, drawn the same way, standing nearer. Left uncropped in a small circle — a timeline, a chat list — the image gives you more sky and plain than carving, and the sky is the one thing here that is not yours. Press **P** to save the avatar. Press **A** again to step back. One thing does change in that frame, and only there. An omen normally keeps its own hour: an eclipse manifests between nine and three and an aurora after dark. A profile picture is looked at whenever somebody looks at it, so in the crop the omen is always present, whatever the clock says. It is the rarest thing a PILLAR carries and the least worth hiding. In the full frame it still waits for its hour. Keep them. Twenty-five a year is a small enough number to hold, and a year of them read together says something no single one does. The stone is aging while you do it, on the same road, so a record kept long enough becomes a record of you both. --- ## The Stone Weathers Nothing is stored to achieve any of this: the hour is read from the clock, the weathering from elapsed time, the sky from the arithmetic of the sky, and everything else from the transaction that minted the edition. A PILLAR can be recomputed exactly as it stood on any date, past or future, by anyone holding the code. There is no table of dates inside to go stale. A PILLAR asked about a time that will outlast its keeper answers from the same arithmetic as one asked about tomorrow. Every PILLAR bears the mark, `][`, struck into the lower right. ## How Many Six hundred and forty are set down — sixty-four tens, which is the arithmetic behind the number rather than a promise about how they land. Ten to a figure is what it would take for every voice the oracle has to be carried by a handful of stones rather than by one. They do not come out in even portions. The figure is read from the transaction rather than dealt, so some voices end up with six pillars and some with eighteen — an unevenness nobody arranged, and a rarity nobody wrote down. What six hundred and forty buys is the near certainty that none of the sixty-four goes unspoken — about one chance in three hundred that any voice is missing. At half the number it is closer to one chance in three, and a piece with a voice it built and never used is worse than a smaller piece. ## The Meridian Each PILLAR stands at a meridian and keeps that meridian's time. Its sun climbs and sets on the local clock, the moon takes its turn, and the shadow swings and lengthens to match — short and underfoot at that meridian's noon, reaching across the plain at its dusk. No two are lit alike at the same moment, and a wall of them shows the world's daylight spread across it. Your PILLAR is not on your clock. It stands where it stands. If it keeps a meridian half a world from yours, its day turns while you sleep, and you will come to it after the fact — which is the ordinary condition of anyone consulting an oracle. ## The Hexagram A hexagram is six lines, each broken or whole — and it has been since about 1000 BC. There are sixty-four, named in King Wen order, which is a traditional sequence with no generating rule. It cannot be derived; it can only be known. Yours might be **2. Field**, or **48. Welling**, or **1. Force**. Three things follow from it, and together they are what makes one PILLAR sound unlike another. **Its idiom.** There are sixteen ways the oracle can open its mouth — *you shall*, *beware the*, *seek not*, *who shall*, *let not*, and so on. Your PILLAR is allowed **four of the sixteen**, and which four is decided by its hexagram. All sixty-four hexagrams get a different set. This is why one stone warns where another foretells and a third only ever asks: it is not a mood, it is the whole range it has. **Its temperature.** How far the model is allowed to wander when it chooses each next word, between **0.62 and 0.80**. A cool PILLAR speaks plainly and a hot one is strange, sometimes barely coherent — and it stays that way for fifty years. There are nineteen possible temperatures. A difficult PILLAR is not a broken one, and the strange ones repay a patience the plain ones do not need. **Its preoccupation.** Sixteen small sets of words, one to a PILLAR: doors and gates, or water and tide, or stone and boundary, or light and lamp and fire, or dust and ash and bone. When the oracle has a choice between two sentences it will reach for the one containing its own words. Measured over hundreds of utterances it lands on them about 19% of the time, against 4% for another PILLAR's — so it is a leaning rather than a drumbeat, and it takes several utterances to notice. That is the point. An oracle with a subject is not the same thing as an oracle that can talk about nothing else. **What the hexagram does not do is choose the words.** Two PILLARS carrying the same figure share an idiom, a temperature and a preoccupation, and still say entirely different things — the sentence itself is seeded from the transaction. Not that the oracle has infinite things to say: measured over fifty thousand utterances, about one in seventy repeats a sentence some other PILLAR has already given, and it is almost always a short one. A PILLAR repeats itself far more rarely, perhaps once in eight years. Sharing a hexagram is sharing an accent, not a script. And the six lines on the shaft are the number itself in binary, which is the same thing written twice: once as a figure a diviner would recognize, once as the bits a machine reads. --- ## Metadata Eight traits are settled by the minting transaction and never change. These are the ones rarity is counted from. | Attribute | Possible Values | |------------|-----------| | Order | Plain, Fluted, Banded, Tapered, Stepped, Broken | | Stone | Granite, Sandstone, Basalt, Marble, Serpentine, Porphyry, Obsidian, Alabaster | | Eyes | Bracket, Carved, Hollow, Single, Blind, Lit | | Mouth | Seam, Grille, Set, Vent, Sealed | | Capital | None, Abacus, Cornice, Torch, Wreath, Halo, Obelisk, Crown | | Ground | Survey, Cracked, Dune, Saltflat, Void | | Weather | None, Chipped, Fissure, Moss | | Omen | None, Aurora, Eclipse | Three more are fixed at mint and score nothing. A place is not a prize, and a figure is not a prize either. Meridian is reported as the place; Offset is the same fact in hours, because a name is only useful if you know what it means. | Attribute | Possible Values | |------------|-----------| | Meridian | One of twenty-seven named places, one for each whole-hour offset | | Offset | The hours from GMT that the name stands for, GMT−12 to GMT+14 | | Hexagram | One of the sixty-four, in King Wen order, with its six lines | Five are read from the date rather than the transaction, and will read differently tomorrow. They are reported because they are what the PILLAR is working from, not because they are rare — a distribution compiled from them disagrees with one compiled next week. | Attribute | Possible Values | |------------|-----------| | Condition | Pristine, Weathered, Worn, Ancient — read from elapsed time | | Term | One of the twenty-four solar terms, from the sun's place on the ecliptic | | Sky | Clear, one of eight meteor showers, or a solar or lunar eclipse | | Changing | Which of the six lines is turning, advancing once a season | | Relating | The figure read through the marked line this season. The PILLAR's own Hexagram is unchanged | `Sky` reports the day's celestial event. The changing sky the PILLAR visibly stands under is deliberately left out of metadata: it turns over four times a day, and an attribute that changes between one compile and the next is worse than no attribute. Meridian is what decides it, and Meridian is reported. An Omen only shows at the hour that suits it: an aurora needs darkness, an eclipse needs a sun to cover. A PILLAR carrying one reveals it on its own schedule rather than the viewer's — except under **A**, where it always shows, because a rarity nobody can wear is not much of a rarity. Rarity is summed improbability across the eight fixed traits, so one very rare trait outranks several merely uncommon ones. It is settled at mint and untouched by weather or hour: a PILLAR's rarity was decided when it was set down, not by how long it has stood. Its rarity, and nothing beyond that — what a stone comes to be worth to whoever keeps it is a different question, settled over years rather than in a single transaction, and this table has no opinion on it. The tiers are Common, Marker, Landmark, Monument — which is what a stone by a road is called, as it becomes worth the walk. ## Technical Notes For anyone who wants to open the stone. None of this is needed to use one. **The oracle.** A decoder-only transformer of 332,640 parameters: five layers, four heads, width 56, a 32-token context and a vocabulary of 2,501 words. Weights are quantized to int8 with float32 scales; the norms and biases stay in float32. It was written by hand in numpy with manual backpropagation, checked against finite differences, and trained on 49,201 lines cut from public-domain philosophy, the prophetic books of the King James Bible, and the Nostradamus quatrains in translation, together with 986 lines written for the piece. **Where it lives, and where it runs.** The weights, the vocabulary, the inference code and the almanac are all part of the artwork's own bytes, stored in the calldata of an Ethereum transaction and referenced by the immutables.art contract. Nothing is fetched at view time and no model is called. But the arithmetic is done in your browser, not by the EVM: Ethereum holds the stone, the stone holds the oracle, and a browser animates it. That is a different claim from on-chain *inference*, and the weaker one — it is also, at 16.3 million gas for the whole work, the only one that is affordable. Running this network in the EVM would cost billions. **Fitting it in one transaction.** Since Fusaka activated in December 2025, EIP-7825 has capped a single Ethereum transaction at 2^24 gas, regardless of how much room remains in the block. For a data-heavy transaction like this one, the EIP-7623 floor makes nonzero calldata effectively cost forty gas a byte. A pure-data transaction can therefore carry at most 418,905 nonzero calldata bytes; a larger one is not merely expensive but invalid. The work as written is 573,676 bytes. So the model is Huffman-coded and packed five characters to four bytes, turning 454,048 base64 characters into 327,295 bytes of text, and the commentary comes out, because that prose is this document and is posted once already. What is left is 406,693 bytes and 16.3 million gas, with about twelve thousand to spare. A canonical Huffman code was chosen over gzip on purpose: the quantized weights are close to random past their distribution of values, so gzip beats plain entropy coding by under four per cent, and the decoder is forty lines rather than three thousand. What is posted can never be corrected, and forty lines can be read by eye. **What a sentence depends on.** The transaction hash and the date, and nothing else. The hash gives the hexagram, which fixes the four openings, the temperature and the favored words; the hash and the day together seed the sampler. The day also fixes which line of the figure is changing, and the figure that line points at lends a second set of favored words for the season. The search asks the model up to forty times and keeps the first reply that passes the acceptance rule, which rejects doubled words, dangling clauses, article disagreement, and relative clauses that never become sentences. **Whether it will say the same thing in fifty years.** `Math.sqrt` is required to be correctly rounded and is safe on any engine. `Math.exp` and `Math.tanh` are not, and the network calls both — so a last-bit difference could in principle pick a different token and everything after it would diverge. Perturbing both and comparing 480 utterances: no change at one ULP, none at 1e-9, none at 1e-6, four at 1e-5. The tolerance is therefore at least several billion times the difference two honest implementations produce, with the true boundary somewhere above 1e-6 and varying by generation. The int8 quantization is why — coarse weights make wide gaps between tokens, so a sampling threshold almost never lands near a boundary. The compression that made it fit is what made it reproducible. `check_determinism.js` is kept with the work: in twenty years it is the test of whether a new engine can still speak for a PILLAR. **The sky.** Solar position from Meeus chapter 25, lunar phase from chapter 49, eclipses from chapter 54 computing gamma and the shadow's size, and Terrestrial Time converted to civil time by the Espenak–Meeus polynomials. Checked against independent references: 224 solar eclipses in the twenty-first century, matching NASA's count; every named eclipse from 1999 to 2045 with the right type; season lengths within half an hour of the known unequal values. **The chronicle.** Which days a PILLAR has spoken on is `speaksOn`, pure arithmetic over the moon, so the year and month menus are free — no model runs to build them. Opening a month calls `readingFor(PILLAR, day)` for the one or two utterances that month holds, about seven tenths of a second each, with the thread handed back between them. Nothing is cached and nothing is written: closing it discards the lot, and every line of it can be worked out again. Verified by reconstructing a PILLAR’s readings cold and out of order and comparing them against the same PILLAR’s life lived day by day — 27 of 27 identical, and unchanged by whatever the stone had been doing in between. **One dependency.** The artwork is a p5.js sketch, and p5 must be supplied by whatever is showing it. The surface it uses is small — the drawing is `fill` and `rect` and nothing else — but it is honest to say the stone needs that much of a hand to stand up. --- ## Colophon **Artist:** Gutenblock **Code License:** [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) **Edition License:** [NIFTY](https://www.nftlicense.org/) PILLARS is posted by the operator of immutables.art, on immutables.art. Said here rather than left to be discovered.
WayOfTheWormH0x8ed8d8169998a1414ca45f16e84127bed7ed38642a4acf41f7c1ceeb8eae6eef``` "Who, then, will wiggle where The Worm wills?"; let propCache, isSetup = false; const vDim = 800, size = vDim * 0.75, vFrameRate = 30, steps = 500, dlAdv = (steps / 12) | 0, bgColor = "#0A0A09", wormPink = "#EC008C", themes = { ephemeral: ["#FFF", "#F8CB1B"], mech: [wormPink, "#ADFF2F"], wriggler: ["#FF0040", "#7300E6B2", false, "#FFF"], classic: [wormPink, "#ADFF2F"], prophet: ["#8052FF", "#FFFFFFCC"], saint: ["#FFB152", "#9169FFCC"], ephemeral_h: [bgColor, "#F8CB1B", "#FFFFFF"], mech_h: [bgColor, "#ADFF2F", "#FFFFFF"], wriggler_h: [bgColor, "#7300E6B2", "#FFFFFF", "#FF0040"], classic_h: [bgColor, "#FFFFFFCC", wormPink], prophet_h: [bgColor, "#FFFFFFCC", "#8052FF", "#9169FF"], saint_h: [bgColor, "#9169FFCC", "#FFB152"], }, drawWorm = (points) => { if (!config.flourishFlag) config.flourishFlag = {}; const length = points.length, headLength = (steps * 0.075) | 0, segmentLength = (steps / 8) | 0; let mechFlourish, flourishPosition; p.noStroke(); // Start drawing outline. for (let i = 0; i < dlAdv; i++) { p.fill(!i ? config.wormOutline : config.wormOutline + "44"); p.circle(...points[i].slice(0, 2), config.wormOutlineSize); } for (let i = 0; i < length; i++) { // Draw ahead for outline. if (i + dlAdv < length) { p.fill( i + dlAdv === length - 1 ? config.wormOutline: config.wormOutline + "44" ); p.circle(...points[i + dlAdv].slice(0, 2), config.wormOutlineSize); } let sOff = (length - headLength) % segmentLength, segment = (segmentLength + ((sOff - i) % segmentLength)) % segmentLength, tail = i < segmentLength, head = i + headLength >= length; // Draw mech segments. if (config.form === "mech" && !tail && i < length - headLength / 2) { if (!segment) { if (i < length - headLength) { flourishPosition = i - 2; mechFlourish = config.flourishFlag[i]; if (!mechFlourish) { mechFlourish = config.flourishFlag[i] = p.random([ -1, -1, -1, 1, 2, p.random(1, 2), p.random(3.1, 3.9), ]); } } p.fill(config.wormOutline); p.circle(...points[i - 2].slice(0, 2), config.wormSize + 8); p.fill( config.form === "mech" && !config.hologram && head ? "#FFF" : config.wormColor ); p.circle(...points[i - 2].slice(0, 2), config.wormSize); p.circle(...points[i - 1].slice(0, 2), config.wormSize); } if (segment && !head && mechFlourish >= 3) { let f0 = points[i - 2], f1 = points[i - 1], a = p.atan2(f1[1] - f0[1], f1[0] - f0[0]), o = p.PI * ((2 / 3) * (mechFlourish - 2)), line = [ f0[0] + (config.wormSize / 2) * p.cos(a + o), f0[1] + (config.wormSize / 2) * p.sin(a + o), ]; p.fill(config.wormOutline); p.circle(...line, 6.5); } else if ( segment && segment < segmentLength / 2 && mechFlourish >= 0 ) { let f0 = points[flourishPosition], f1 = points[flourishPosition + 1], a = p.atan2(f1[1] - f0[1], f1[0] - f0[0]), o = p.PI * ((2 / 3) * mechFlourish), bolt = [ f0[0] + (config.wormSize / 2 - 12) * p.cos(a + o), f0[1] + (config.wormSize / 2 - 12) * p.sin(a + o), ]; mechFlourish = -1; p.fill(config.wormOutline); p.circle(...bolt, 8); } if (segment < steps / 100) continue; } // Wriggler horns. if (config.wriggler && i === length - 1) { p.fill(config.wormOutline); p.stroke(config.wormOutline); p.strokeWeight(3); p.triangle( points[i][0] + 0.45 * config.wormSize * p.cos((13 * p.PI) / 20), points[i][1] - 0.45 * config.wormSize * p.sin((13 * p.PI) / 20), points[i][0] + 0.65 * config.wormSize * p.cos((14 * p.PI) / 20), points[i][1] - 0.65 * config.wormSize * p.sin((14 * p.PI) / 20), points[i][0] + 0.45 * config.wormSize * p.cos((15 * p.PI) / 20), points[i][1] - 0.45 * config.wormSize * p.sin((15 * p.PI) / 20) ); p.triangle( points[i][0] + 0.45 * config.wormSize * p.cos((7 * p.PI) / 20), points[i][1] - 0.45 * config.wormSize * p.sin((7 * p.PI) / 20), points[i][0] + 0.65 * config.wormSize * p.cos((6 * p.PI) / 20), points[i][1] - 0.65 * config.wormSize * p.sin((6 * p.PI) / 20), points[i][0] + 0.45 * config.wormSize * p.cos((5 * p.PI) / 20), points[i][1] - 0.45 * config.wormSize * p.sin((5 * p.PI) / 20) ); p.noStroke(); } // Draw the actual worm body. p.fill( config.form === "mech" && !config.hologram && head ? "#FFF": config.wormColor ); p.circle(...points[i].slice(0, 2), config.wormSize); } }, drawFaceNormal = (l) => { p.fill(config.theme[3] || config.wormOutline); p.noStroke(); p.circle(l[0] - config.wormSize / 6, l[1] - config.wormSize / 24, 6); p.circle(l[0] + config.wormSize / 6, l[1] - config.wormSize / 24, 6); p.noFill(); p.strokeWeight(5); p.stroke(config.wormOutline); p.arc( l[0], l[1] + 5 + config.wormSize / 12, config.wormSize / 5, config.wormSize / 5, 0, p.PI ); if (config.wriggler) { p.line( l[0] - (5 * config.wormSize) / 24, l[1] - config.wormSize / 6, l[0] - config.wormSize / 8, l[1] - config.wormSize / 12 ); p.line( l[0] + (5 * config.wormSize) / 24, l[1] - config.wormSize / 6, l[0] + config.wormSize / 8, l[1] - config.wormSize / 12 ); } }, drawFuckFace = (l, v) => { p.fill("#FFF"); p.stroke(bgColor); p.strokeWeight(3.5); p.ellipse( l[0] - config.wormSize / 6, l[1] - config.wormSize / 12, config.wormSize / 3, config.wormSize / 2.8 ); p.ellipse( l[0] + config.wormSize / 6, l[1] - config.wormSize / 12, config.wormSize / 3, config.wormSize / 2.8 ); p.fill(bgColor); p.noStroke(); p.circle( l[0] + v[0] - config.wormSize / 6, l[1] + v[1] - config.wormSize / 12, config.wormSize / 6 ); p.circle( l[0] + v[0] + config.wormSize / 6, l[1] + v[1] - config.wormSize / 12, config.wormSize / 6 ); p.fill(config.wormOutline); p.stroke(config.wormOutline); p.strokeWeight(5); p.arc( l[0], l[1] + config.wormSize / 5, config.wormSize / 5, config.wormSize / 5, 0, p.PI, p.CHORD ); }, drawFacePeaceful = (l) => { p.stroke(config.theme[3] || config.wormOutline); p.strokeWeight(5); p.noFill(); p.arc( l[0] - config.wormSize / 4.8, l[1] - config.wormSize / 24, config.wormSize / 6, config.wormSize / 6, p.PI / 12, (p.PI * 11) / 12 ); p.arc( l[0] + config.wormSize / 4.8, l[1] - config.wormSize / 24, config.wormSize / 6, config.wormSize / 6, p.PI / 12, (p.PI * 11) / 12 ); p.line( l[0] - config.wormSize / 12, l[1] + 5 + config.wormSize / 12, l[0] + config.wormSize / 12, l[1] + 5 + config.wormSize / 12 ); }, drawSingleHalo = (l, a = 0, o = 0.7) => { p.stroke(config.mech && !config.hologram ? wormPink : "#FFFFFF"); p.strokeWeight(4); p.noFill(); p.push(); p.translate(l[0], l[1] - config.wormSize * o); p.rotate(a); p.ellipse(0, 0, config.wormSize * 0.7, config.wormSize / 5); p.pop(); }, drawDoubleHalo = (l) => { drawSingleHalo(l, p.PI / 6, 0.8); drawSingleHalo(l, -p.PI / 6, 0.8); }, drawGrid = (_, vFrame) => { if (config.inverseGrid) { p.background(config.gridColor.substring(0, 7)); p.stroke(bgColor); } else { p.stroke(config.gridColor); } p.strokeWeight(12); let drift = (vFrame % config.driftSpeed) / config.driftSpeed; for (let i = 1; i < config.horizon; i++) { let y = vDim * (-0.16 + 1.2 * p.tan(p.atan2(1, ((i + drift) * 10) / config.horizon))); p.line(-vDim / 2, y, vDim / 2, y); } for (let i = 0; i < 2 * config.horizon; i++) { let x = vDim * (-4 + (4 * i) / config.horizon); p.line(0, vDim * -0.1, x, vDim / 2); } p.noStroke(); p.fill("#DEADC0DE"); const gradient = p.drawingContext.createLinearGradient( 0, -vDim / 2, 0, vDim / 2 ); gradient.addColorStop(0.48, bgColor); gradient.addColorStop(0.6, bgColor + "00"); p.drawingContext.fillStyle = gradient; p.square(-vDim / 2, -vDim / 2, vDim); }, drawRays = (x, vFrame) => { p.push(); const window = 4, slice = x.slice(-window), sum = slice.reduce((a, x) => [a[0] + x[0], a[1] + x[1]]), drift = p.sin(((p.PI / 16) * vFrame) / config.driftSpeed); p.translate(sum[0] / window, sum[1] / window); p.stroke(config.bgFeatureColor); p.strokeWeight(8); for (let i = 0; i < 48; i++) { p.rotate(p.PI / 24); p.line(-vDim / 2, (drift * vDim) / 16, vDim, 0); } p.pop(); }, drawTriangle = (_, vFrame) => { p.background("#100539"); const angle = p.PI * (((config.triangleDirection * vFrame) % 2000) / 1000 - 0.5); p.noStroke(); p.fill(config.triangleColor + "24"); p.triangle( vDim * 0.8 * p.cos(angle), vDim * 0.8 * p.sin(angle), vDim * 0.8 * p.cos(angle + (2 / 3) * p.PI), vDim * 0.8 * p.sin(angle + (2 / 3) * p.PI), vDim * 0.8 * p.cos(angle + (4 / 3) * p.PI), vDim * 0.8 * p.sin(angle + (4 / 3) * p.PI) ); p.fill(config.triangleColor + "12"); p.triangle( vDim * 0.7 * p.cos(angle), vDim * 0.7 * p.sin(angle), vDim * 0.7 * p.cos(angle + (2 / 3) * p.PI), vDim * 0.7 * p.sin(angle + (2 / 3) * p.PI), vDim * 0.7 * p.cos(angle + (4 / 3) * p.PI), vDim * 0.7 * p.sin(angle + (4 / 3) * p.PI) ); p.noStroke(); p.fill("#DEADC0DE"); const gradient = p.drawingContext.createRadialGradient( 0, 0, 0, 0, 0, vDim * (5 / 6 + (1 / 6) * p.sin(6 * angle)) ); gradient.addColorStop(0, config.triangleGradient + "cc"); gradient.addColorStop(0.5, config.triangleGradient + "4d"); gradient.addColorStop(1, config.triangleGradient + "00"); p.drawingContext.fillStyle = gradient; p.square(-vDim / 2, -vDim / 2, vDim); }; let config; p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (!props.transactionHash || !props.square) return; if (!isSetup) { propCache = props; return; } // Seed the p5js random seed using 32 bits from the hash. const seedOffset = 2 + 8 * (props.tokenId % 8); p.randomSeed( +("0x" + props.transactionHash.substring(seedOffset, seedOffset + 8)) ); // Set up the style. let formNum = p.random(), faceNum = p.random(), form = formNum < 0.33 ? "ephemeral": formNum < 0.61 ? "mech": formNum < 0.65 ? "prophet": formNum < 0.97 ? "classic": formNum < 0.996 ? "wriggler": "saint", classic = form === "classic", mech = form === "mech", ephemeral = form === "ephemeral", wriggler = form === "wriggler", prophet = form === "prophet", saint = form === "saint", hologram = p.random() < 0.62, theme = themes[form + (hologram ? "_h" : "")], wormColor = theme[0], wormOutline = theme[2] || bgColor, bgFeatureColor = theme[1], wormSize = p.randomGaussian(60 + p.random(20), 10), wormOutlineSize = wormSize + 9, cycle = p.randomGaussian(60, 5) | 0, length = size * p.random(0.29, 0.52) - wormSize, flusterSpeed = p.random(3) | 0, fluster = p.random(size / 6), xInc = (p.random(8) | 0) + 1, yInc = (p.random(8) | 0) + 1, xOff = p.random(p.TWO_PI), yOff = p.random(p.TWO_PI), flusterInc = (p.random(8) | 0) + 6, flusterOff = p.random(5), dSteps = steps, speed = length * xInc + length * yInc + 2 * fluster * flusterInc, jSpeed = length * xInc + length * yInc + (fluster * flusterInc * flusterInc) / 3, dur = (steps * 2 * (1 + p.abs(p.randomGaussian()))) / speed, jit = (steps / jSpeed) * (1.2 + 0.6 * p.abs(p.randomGaussian())); if (wriggler && p.random() < 0.2) { jit *= -1; } if (p.random() < 0.12) { const inc = (1 + p.random(4)) | 0; dur *= inc; dSteps *= inc; } if (p.random() < 0.04) { jit *= p.random(0.1, 0.4); } let bgr = p.random(), bgStats = {}, [bg, drawBackground] = bgr < 0.4 ? ["Grid", drawGrid]: bgr < 0.55 ? ["Rays", drawRays]: bgr < 0.8 ? ["Light", drawTriangle]: ["Void", () => {}]; if (bg === "Grid") { bgStats = { gridColor: p.random() < 0.1 ? "#FFFFFF": wriggler || prophet || p.random() < 0.2 ? bgFeatureColor: "#ADFF2F", horizon: p.randomGaussian(p.random(10, 20), 2) | 0, inverseGrid: p.random() < 0.1, }; if (bgStats.inverseGrid) { bg = "Inverted Grid"; } } else if (bg === "Rays") { const factor = p.randomGaussian(p.random(0.1, 0.3), 0.02); jit *= factor; flusterSpeed *= factor; } else if (bg === "Light") { bgStats = { triangleDirection: p.random([-1, 1]), triangleColor: wriggler ? bgFeatureColor.substring(0, 7): p.random([wormPink, "#38BCE6"]), triangleGradient: p.random([ "#36bce6", "#9f7af2", ...(classic ? ["#f8cb1b"] : []), ...(wriggler ? ["#ff5d40"] : []), ]), }; } let [face, drawFace] = wriggler ? ["Scheming", drawFaceNormal]: faceNum < 0.08 ? ["Peaceful", drawFacePeaceful]: faceNum < 0.11 && !hologram ? ["Lil Fk", drawFuckFace]: ["Smile", drawFaceNormal]; config = { square: props.square, startTime: p.millis(), drawBackground: drawBackground, drawFace: drawFace, drawHalo: ephemeral ? drawSingleHalo: mech ? drawDoubleHalo: (prophet || saint) && p.random() < 0.4 ? drawSingleHalo: () => {}, form: form, theme: theme, classic: classic, wriggler: wriggler, mech: mech, hologram: hologram, bgFeatureColor: bgFeatureColor, ...bgStats, wormColor: wormColor, wormSize: wormSize, wormOutline: wormOutline, wormOutlineSize: wormOutlineSize, driftSpeed: p.randomGaussian(20, 3), cycle: cycle, length: length, jit: jit, dur: dur, dSteps: dSteps, xInc: xInc, xOff: xOff, xOffSize: p.random(1, 5) | 0, xOffSpeed: p.random(3) | 0, yInc: yInc, yOff: yOff, yOffSize: p.random(1, 5) | 0, yOffSpeed: p.random(3) | 0, fluster: fluster, flusterSpeed: flusterSpeed, flusterOff: flusterOff, flusterAmpOff: p.random(cycle), flusterInc: flusterInc, }; window.config = config; // Metadata. let subject = mech ? "Mech Worm MK1": ephemeral ? "The Ephemeral Worm": wriggler ? "The Wriggler": prophet ? "Worm Prophet": saint ? "Worm Saint": "The Earthly Worm"; if (hologram) { subject += wriggler || saint ? " Apparition": prophet ? " Revelation": " Hologram"; } console.log("metadata: ", { Subject: subject, Background: bg, Expression: face, transactionHash: props.transactionHash, }); p.windowResized(); }; p.draw = () => { if (!isSetup || !config) return; p.scale(p.width / vDim); p.translate(vDim / 2, vDim / 2); p.strokeJoin(p.ROUND); const vFrame = (vFrameRate * (p.millis() - config.startTime)) / 1000; let points = []; let { jit } = config; if (config.paused) { jit *= -25 * p.cos((p.TWO_PI * vFrame) / 200); } else { jit *= vFrame; } for (let i = 0; i < config.dSteps; i++) { let j = (jit * p.PI) / 60 + (i / config.dSteps) * config.dur; points.push([ config.length * p.sin(j * config.xInc + config.xOff) + config.fluster * p.sin(config.flusterOff + j * config.flusterInc), config.length * p.cos(j * config.yInc + config.yOff) + config.fluster * p.cos(config.flusterOff + j * config.flusterInc), ]); } p.background(bgColor); config.drawBackground([...points], vFrame); drawWorm([...points]); const ultimate = points.pop(), penultimate = points.pop(), faceVector = [ultimate[0] - penultimate[0], ultimate[1] - penultimate[1]]; config.drawFace( [ultimate[0] + faceVector[0], ultimate[1] + faceVector[1]], faceVector ); config.drawHalo(points.pop()); }; p.setup = () => { isSetup = true; if (propCache) { p.updateWithProps(propCache); } }; p.windowResized = () => { if (!isSetup || !config || !config.square) return; const SCALE = 0.8, WIDTH = (window.innerWidth / config.square) * SCALE, HEIGHT = (window.innerHeight / config.square) * SCALE, DIM = p.min(WIDTH, HEIGHT); p.resizeCanvas(DIM, DIM); }; ```
WayOfTheWorm``` "Who, then, will wiggle where The Worm wills?"; let propCache, isSetup = false; const vDim = 800, size = vDim * 0.75, vFrameRate = 30, steps = 500, dlAdv = (steps / 12) | 0, bgColor = "#0A0A09", wormPink = "#EC008C", themes = { ephemeral: ["#FFF", "#F8CB1B"], mech: [wormPink, "#ADFF2F"], wriggler: ["#FF0040", "#7300E6B2", false, "#FFF"], classic: [wormPink, "#ADFF2F"], prophet: ["#8052FF", "#FFFFFFCC"], saint: ["#FFB152", "#9169FFCC"], ephemeral_h: [bgColor, "#F8CB1B", "#FFFFFF"], mech_h: [bgColor, "#ADFF2F", "#FFFFFF"], wriggler_h: [bgColor, "#7300E6B2", "#FFFFFF", "#FF0040"], classic_h: [bgColor, "#FFFFFFCC", wormPink], prophet_h: [bgColor, "#FFFFFFCC", "#8052FF", "#9169FF"], saint_h: [bgColor, "#9169FFCC", "#FFB152"], }, drawWorm = (points) => { if (!config.flourishFlag) config.flourishFlag = {}; const length = points.length, headLength = (steps * 0.075) | 0, segmentLength = (steps / 8) | 0; let mechFlourish, flourishPosition; p.noStroke(); // Start drawing outline. for (let i = 0; i < dlAdv; i++) { p.fill(!i ? config.wormOutline : config.wormOutline + "44"); p.circle(...points[i].slice(0, 2), config.wormOutlineSize); } for (let i = 0; i < length; i++) { // Draw ahead for outline. if (i + dlAdv < length) { p.fill( i + dlAdv === length - 1 ? config.wormOutline: config.wormOutline + "44" ); p.circle(...points[i + dlAdv].slice(0, 2), config.wormOutlineSize); } let sOff = (length - headLength) % segmentLength, segment = (segmentLength + ((sOff - i) % segmentLength)) % segmentLength, tail = i < segmentLength, head = i + headLength >= length; // Draw mech segments. if (config.form === "mech" && !tail && i < length - headLength / 2) { if (!segment) { if (i < length - headLength) { flourishPosition = i - 2; mechFlourish = config.flourishFlag[i]; if (!mechFlourish) { mechFlourish = config.flourishFlag[i] = p.random([ -1, -1, -1, 1, 2, p.random(1, 2), p.random(3.1, 3.9), ]); } } p.fill(config.wormOutline); p.circle(...points[i - 2].slice(0, 2), config.wormSize + 8); p.fill( config.form === "mech" && !config.hologram && head ? "#FFF" : config.wormColor ); p.circle(...points[i - 2].slice(0, 2), config.wormSize); p.circle(...points[i - 1].slice(0, 2), config.wormSize); } if (segment && !head && mechFlourish >= 3) { let f0 = points[i - 2], f1 = points[i - 1], a = p.atan2(f1[1] - f0[1], f1[0] - f0[0]), o = p.PI * ((2 / 3) * (mechFlourish - 2)), line = [ f0[0] + (config.wormSize / 2) * p.cos(a + o), f0[1] + (config.wormSize / 2) * p.sin(a + o), ]; p.fill(config.wormOutline); p.circle(...line, 6.5); } else if ( segment && segment < segmentLength / 2 && mechFlourish >= 0 ) { let f0 = points[flourishPosition], f1 = points[flourishPosition + 1], a = p.atan2(f1[1] - f0[1], f1[0] - f0[0]), o = p.PI * ((2 / 3) * mechFlourish), bolt = [ f0[0] + (config.wormSize / 2 - 12) * p.cos(a + o), f0[1] + (config.wormSize / 2 - 12) * p.sin(a + o), ]; mechFlourish = -1; p.fill(config.wormOutline); p.circle(...bolt, 8); } if (segment < steps / 100) continue; } // Wriggler horns. if (config.wriggler && i === length - 1) { p.fill(config.wormOutline); p.stroke(config.wormOutline); p.strokeWeight(3); p.triangle( points[i][0] + 0.45 * config.wormSize * p.cos((13 * p.PI) / 20), points[i][1] - 0.45 * config.wormSize * p.sin((13 * p.PI) / 20), points[i][0] + 0.65 * config.wormSize * p.cos((14 * p.PI) / 20), points[i][1] - 0.65 * config.wormSize * p.sin((14 * p.PI) / 20), points[i][0] + 0.45 * config.wormSize * p.cos((15 * p.PI) / 20), points[i][1] - 0.45 * config.wormSize * p.sin((15 * p.PI) / 20) ); p.triangle( points[i][0] + 0.45 * config.wormSize * p.cos((7 * p.PI) / 20), points[i][1] - 0.45 * config.wormSize * p.sin((7 * p.PI) / 20), points[i][0] + 0.65 * config.wormSize * p.cos((6 * p.PI) / 20), points[i][1] - 0.65 * config.wormSize * p.sin((6 * p.PI) / 20), points[i][0] + 0.45 * config.wormSize * p.cos((5 * p.PI) / 20), points[i][1] - 0.45 * config.wormSize * p.sin((5 * p.PI) / 20) ); p.noStroke(); } // Draw the actual worm body. p.fill( config.form === "mech" && !config.hologram && head ? "#FFF": config.wormColor ); p.circle(...points[i].slice(0, 2), config.wormSize); } }, drawFaceNormal = (l) => { p.fill(config.theme[3] || config.wormOutline); p.noStroke(); p.circle(l[0] - config.wormSize / 6, l[1] - config.wormSize / 24, 6); p.circle(l[0] + config.wormSize / 6, l[1] - config.wormSize / 24, 6); p.noFill(); p.strokeWeight(5); p.stroke(config.wormOutline); p.arc( l[0], l[1] + 5 + config.wormSize / 12, config.wormSize / 5, config.wormSize / 5, 0, p.PI ); if (config.wriggler) { p.line( l[0] - (5 * config.wormSize) / 24, l[1] - config.wormSize / 6, l[0] - config.wormSize / 8, l[1] - config.wormSize / 12 ); p.line( l[0] + (5 * config.wormSize) / 24, l[1] - config.wormSize / 6, l[0] + config.wormSize / 8, l[1] - config.wormSize / 12 ); } }, drawFuckFace = (l, v) => { p.fill("#FFF"); p.stroke(bgColor); p.strokeWeight(3.5); p.ellipse( l[0] - config.wormSize / 6, l[1] - config.wormSize / 12, config.wormSize / 3, config.wormSize / 2.8 ); p.ellipse( l[0] + config.wormSize / 6, l[1] - config.wormSize / 12, config.wormSize / 3, config.wormSize / 2.8 ); p.fill(bgColor); p.noStroke(); p.circle( l[0] + v[0] - config.wormSize / 6, l[1] + v[1] - config.wormSize / 12, config.wormSize / 6 ); p.circle( l[0] + v[0] + config.wormSize / 6, l[1] + v[1] - config.wormSize / 12, config.wormSize / 6 ); p.fill(config.wormOutline); p.stroke(config.wormOutline); p.strokeWeight(5); p.arc( l[0], l[1] + config.wormSize / 5, config.wormSize / 5, config.wormSize / 5, 0, p.PI, p.CHORD ); }, drawFacePeaceful = (l) => { p.stroke(config.theme[3] || config.wormOutline); p.strokeWeight(5); p.noFill(); p.arc( l[0] - config.wormSize / 4.8, l[1] - config.wormSize / 24, config.wormSize / 6, config.wormSize / 6, p.PI / 12, (p.PI * 11) / 12 ); p.arc( l[0] + config.wormSize / 4.8, l[1] - config.wormSize / 24, config.wormSize / 6, config.wormSize / 6, p.PI / 12, (p.PI * 11) / 12 ); p.line( l[0] - config.wormSize / 12, l[1] + 5 + config.wormSize / 12, l[0] + config.wormSize / 12, l[1] + 5 + config.wormSize / 12 ); }, drawSingleHalo = (l, a = 0, o = 0.7) => { p.stroke(config.mech && !config.hologram ? wormPink : "#FFFFFF"); p.strokeWeight(4); p.noFill(); p.push(); p.translate(l[0], l[1] - config.wormSize * o); p.rotate(a); p.ellipse(0, 0, config.wormSize * 0.7, config.wormSize / 5); p.pop(); }, drawDoubleHalo = (l) => { drawSingleHalo(l, p.PI / 6, 0.8); drawSingleHalo(l, -p.PI / 6, 0.8); }, drawGrid = (_, vFrame) => { if (config.inverseGrid) { p.background(config.gridColor.substring(0, 7)); p.stroke(bgColor); } else { p.stroke(config.gridColor); } p.strokeWeight(12); let drift = (vFrame % config.driftSpeed) / config.driftSpeed; for (let i = 1; i < config.horizon; i++) { let y = vDim * (-0.16 + 1.2 * p.tan(p.atan2(1, ((i + drift) * 10) / config.horizon))); p.line(-vDim / 2, y, vDim / 2, y); } for (let i = 0; i < 2 * config.horizon; i++) { let x = vDim * (-4 + (4 * i) / config.horizon); p.line(0, vDim * -0.1, x, vDim / 2); } p.noStroke(); p.fill("#DEADC0DE"); const gradient = p.drawingContext.createLinearGradient( 0, -vDim / 2, 0, vDim / 2 ); gradient.addColorStop(0.48, bgColor); gradient.addColorStop(0.6, bgColor + "00"); p.drawingContext.fillStyle = gradient; p.square(-vDim / 2, -vDim / 2, vDim); }, drawRays = (x, vFrame) => { p.push(); const window = 4, slice = x.slice(-window), sum = slice.reduce((a, x) => [a[0] + x[0], a[1] + x[1]]), drift = p.sin(((p.PI / 16) * vFrame) / config.driftSpeed); p.translate(sum[0] / window, sum[1] / window); p.stroke(config.bgFeatureColor); p.strokeWeight(8); for (let i = 0; i < 48; i++) { p.rotate(p.PI / 24); p.line(-vDim / 2, (drift * vDim) / 16, vDim, 0); } p.pop(); }, drawTriangle = (_, vFrame) => { p.background("#100539"); const angle = p.PI * (((config.triangleDirection * vFrame) % 2000) / 1000 - 0.5); p.noStroke(); p.fill(config.triangleColor + "24"); p.triangle( vDim * 0.8 * p.cos(angle), vDim * 0.8 * p.sin(angle), vDim * 0.8 * p.cos(angle + (2 / 3) * p.PI), vDim * 0.8 * p.sin(angle + (2 / 3) * p.PI), vDim * 0.8 * p.cos(angle + (4 / 3) * p.PI), vDim * 0.8 * p.sin(angle + (4 / 3) * p.PI) ); p.fill(config.triangleColor + "12"); p.triangle( vDim * 0.7 * p.cos(angle), vDim * 0.7 * p.sin(angle), vDim * 0.7 * p.cos(angle + (2 / 3) * p.PI), vDim * 0.7 * p.sin(angle + (2 / 3) * p.PI), vDim * 0.7 * p.cos(angle + (4 / 3) * p.PI), vDim * 0.7 * p.sin(angle + (4 / 3) * p.PI) ); p.noStroke(); p.fill("#DEADC0DE"); const gradient = p.drawingContext.createRadialGradient( 0, 0, 0, 0, 0, vDim * (5 / 6 + (1 / 6) * p.sin(6 * angle)) ); gradient.addColorStop(0, config.triangleGradient + "cc"); gradient.addColorStop(0.5, config.triangleGradient + "4d"); gradient.addColorStop(1, config.triangleGradient + "00"); p.drawingContext.fillStyle = gradient; p.square(-vDim / 2, -vDim / 2, vDim); }; let config; p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (!props.transactionHash || !props.square) return; if (!isSetup) { propCache = props; return; } // Seed the p5js random seed using 32 bits from the hash. const seedOffset = 2 + 8 * (props.tokenId % 8); p.randomSeed( +("0x" + props.transactionHash.substring(seedOffset, seedOffset + 8)) ); // Set up the style. let formNum = p.random(), faceNum = p.random(), form = formNum < 0.33 ? "ephemeral": formNum < 0.61 ? "mech": formNum < 0.65 ? "prophet": formNum < 0.97 ? "classic": formNum < 0.996 ? "wriggler": "saint", classic = form === "classic", mech = form === "mech", ephemeral = form === "ephemeral", wriggler = form === "wriggler", prophet = form === "prophet", saint = form === "saint", hologram = p.random() < 0.62, theme = themes[form + (hologram ? "_h" : "")], wormColor = theme[0], wormOutline = theme[2] || bgColor, bgFeatureColor = theme[1], wormSize = p.randomGaussian(60 + p.random(20), 10), wormOutlineSize = wormSize + 9, cycle = p.randomGaussian(60, 5) | 0, length = size * p.random(0.29, 0.52) - wormSize, flusterSpeed = p.random(3) | 0, fluster = p.random(size / 6), xInc = (p.random(8) | 0) + 1, yInc = (p.random(8) | 0) + 1, xOff = p.random(p.TWO_PI), yOff = p.random(p.TWO_PI), flusterInc = (p.random(8) | 0) + 6, flusterOff = p.random(5), dSteps = steps, speed = length * xInc + length * yInc + 2 * fluster * flusterInc, jSpeed = length * xInc + length * yInc + (fluster * flusterInc * flusterInc) / 3, dur = (steps * 2 * (1 + p.abs(p.randomGaussian()))) / speed, jit = (steps / jSpeed) * (1.2 + 0.6 * p.abs(p.randomGaussian())); if (wriggler && p.random() < 0.2) { jit *= -1; } if (p.random() < 0.12) { const inc = (1 + p.random(4)) | 0; dur *= inc; dSteps *= inc; } if (p.random() < 0.04) { jit *= p.random(0.1, 0.4); } let bgr = p.random(), bgStats = {}, [bg, drawBackground] = bgr < 0.4 ? ["Grid", drawGrid]: bgr < 0.55 ? ["Rays", drawRays]: bgr < 0.8 ? ["Light", drawTriangle]: ["Void", () => {}]; if (bg === "Grid") { bgStats = { gridColor: p.random() < 0.1 ? "#FFFFFF": wriggler || prophet || p.random() < 0.2 ? bgFeatureColor: "#ADFF2F", horizon: p.randomGaussian(p.random(10, 20), 2) | 0, inverseGrid: p.random() < 0.1, }; if (bgStats.inverseGrid) { bg = "Inverted Grid"; } } else if (bg === "Rays") { const factor = p.randomGaussian(p.random(0.1, 0.3), 0.02); jit *= factor; flusterSpeed *= factor; } else if (bg === "Light") { bgStats = { triangleDirection: p.random([-1, 1]), triangleColor: wriggler ? bgFeatureColor.substring(0, 7): p.random([wormPink, "#38BCE6"]), triangleGradient: p.random([ "#36bce6", "#9f7af2", ...(classic ? ["#f8cb1b"] : []), ...(wriggler ? ["#ff5d40"] : []), ]), }; } let [face, drawFace] = wriggler ? ["Scheming", drawFaceNormal]: faceNum < 0.08 ? ["Peaceful", drawFacePeaceful]: faceNum < 0.11 && !hologram ? ["Lil Fk", drawFuckFace]: ["Smile", drawFaceNormal]; config = { square: props.square, startTime: p.millis(), drawBackground: drawBackground, drawFace: drawFace, drawHalo: ephemeral ? drawSingleHalo: mech ? drawDoubleHalo: (prophet || saint) && p.random() < 0.4 ? drawSingleHalo: () => {}, form: form, theme: theme, classic: classic, wriggler: wriggler, mech: mech, hologram: hologram, bgFeatureColor: bgFeatureColor, ...bgStats, wormColor: wormColor, wormSize: wormSize, wormOutline: wormOutline, wormOutlineSize: wormOutlineSize, driftSpeed: p.randomGaussian(20, 3), cycle: cycle, length: length, jit: jit, dur: dur, dSteps: dSteps, xInc: xInc, xOff: xOff, xOffSize: p.random(1, 5) | 0, xOffSpeed: p.random(3) | 0, yInc: yInc, yOff: yOff, yOffSize: p.random(1, 5) | 0, yOffSpeed: p.random(3) | 0, fluster: fluster, flusterSpeed: flusterSpeed, flusterOff: flusterOff, flusterAmpOff: p.random(cycle), flusterInc: flusterInc, }; window.config = config; // Metadata. let subject = mech ? "Mech Worm MK1": ephemeral ? "The Ephemeral Worm": wriggler ? "The Wriggler": prophet ? "Worm Prophet": saint ? "Worm Saint": "The Earthly Worm"; if (hologram) { subject += wriggler || saint ? " Apparition": prophet ? " Revelation": " Hologram"; } console.log("metadata: ", { Subject: subject, Background: bg, Expression: face, transactionHash: props.transactionHash, }); p.windowResized(); }; p.draw = () => { if (!isSetup || !config) return; p.scale(p.width / vDim); p.translate(vDim / 2, vDim / 2); p.strokeJoin(p.ROUND); const vFrame = (vFrameRate * (p.millis() - config.startTime)) / 1000; let points = []; let { jit } = config; if (config.paused) { jit *= -25 * p.cos((p.TWO_PI * vFrame) / 200); } else { jit *= vFrame; } for (let i = 0; i < config.dSteps; i++) { let j = (jit * p.PI) / 60 + (i / config.dSteps) * config.dur; points.push([ config.length * p.sin(j * config.xInc + config.xOff) + config.fluster * p.sin(config.flusterOff + j * config.flusterInc), config.length * p.cos(j * config.yInc + config.yOff) + config.fluster * p.cos(config.flusterOff + j * config.flusterInc), ]); } p.background(bgColor); config.drawBackground([...points], vFrame); drawWorm([...points]); const ultimate = points.pop(), penultimate = points.pop(), faceVector = [ultimate[0] - penultimate[0], ultimate[1] - penultimate[1]]; config.drawFace( [ultimate[0] + faceVector[0], ultimate[1] + faceVector[1]], faceVector ); config.drawHalo(points.pop()); }; p.setup = () => { p5.disableFriendlyErrors = true; isSetup = true; if (propCache) { p.updateWithProps(propCache); } }; p.windowResized = () => { if (!isSetup || !config || !config.square) return; const SCALE = 0.8, WIDTH = (window.innerWidth / config.square) * SCALE, HEIGHT = (window.innerHeight / config.square) * SCALE, DIM = p.min(WIDTH, HEIGHT); p.resizeCanvas(DIM, DIM); }; ```
WayOfTheWorm# Way of the Worm _by [Mark Egli]_ An on-chain generative tribute to [The Worm]. Free to mint for select wallets at [markegli.com/worm](https://markegli.com/worm) while supplies last. **Code License:** [CC0 1.0] **Edition License:** [CC0 1.0] [Mark Egli]: https://markegli.com [The Worm]: https://theworm.wtf [CC0 1.0]: https://creativecommons.org/publicdomain/zero/1.0/ ## Traits * Subject * Background * Expression
unknown sendersent to0x499f4943…3001·#15,306,064·0xaee40627…b9a7e2
Az```javascript "it rests among the stars / gathered up in the furthest firmament"; let canvas, // p5js canvas. state; // Keep all shared state in one place. //-[ setup functions ]--------------------------------------------------------// // Creates the p5js canvas and disables looping. // The rest of the setup is done when the Immutables properties are received. p.setup = _ => { canvas = p.createCanvas(1, 1); canvas.style("display", "block"); p.frameRate(10); p.noLoop(); }; // Responds to the properties provided by Immutables. p.myCustomRedrawAccordingToNewPropsHandler = properties => { if (!properties.transactionHash) return; // Check if existing state already matches the new properties. if ( state && state.transactionHash == properties.transactionHash && state.editionId == properties.editionId ) { state.square = properties.square; p.windowResized(); return; } // Pull bits from the hash to seed the RNG. p.randomSeed("0x" + properties.transactionHash.substr(2 + 8 * (properties.editionId % 8), 8)); // Intialize the state. state = { ...properties, animate: properties.square == 1, progress: 0, }; setStyling(); placeForegroundStars(); drawConstellation(); placeBackgroundStars(); addDust(); describe(); // Resize the window and turn looping on or off as needed. p.windowResized(); state.animate ? p.loop() : (p.noLoop(), p.redraw()); }; p.windowResized = _ => { if (!state) return; const minDim = p.min(p.windowWidth, p.windowHeight) * .8 / state.square | 0; if (minDim === p.width) return; p.resizeCanvas(minDim, minDim); state.resize = true; }; p.keyTyped = _ => { if (!state || state.square != 1) return; if (p.key == "A") { if (state.animate) { state.animate = false; p.noLoop(); p.redraw(); } else { state.animate = true; state.progress = 0; p.loop(); } } if (p.key == "B") { state.simple = !state.simple; } if (p.key == "C") { state.clear = !state.clear; } }; const setStyling = _ => { // Determine star size. state.chibi = p.random() < .06; state.dashed = p.random() < .06; state.sparse = p.random() < .18; const gap = state.chibi ? .7 : .5; state.drawLine = !state.dashed ? line => p.line(...line.slice(0, 4)) : line => { const dashes = p.max(1, line[6] / 3 | 0), scale = dashes - gap; for (let i = 0; i < dashes; i++) { p.line( p.lerp(line[0], line[2], i / scale), p.lerp(line[1], line[3], i / scale), p.lerp(line[0], line[2], (i + 1 - gap) / scale), p.lerp(line[1], line[3], (i + 1 - gap) / scale) ); } }; let color = p.random(); state.color = color < .12 ? [224, 42, 32, "Fire"] : color < .24 ? [96, 128, 247, "Water"] : color < .36 ? [148, 164, 196, "Air"] : [239, 239, 153, "Earth"]; }, placeForegroundStars = _ => { state.stars = []; const mainSizer = _ => state.chibi ? p.random(1.3, 1.8) : 1; // Place 2 to 4 stars somewhat uniformly. const preset = p.random(2, 5) | 0, angleOffset = p.random(p.TWO_PI / preset); for (let i = 0; i < preset; i++) { const dist = p.random(14, 20), angle = angleOffset + (i * p.TWO_PI + p.random(p.PI)) / preset, position = [dist * p.cos(angle), dist * p.sin(angle)]; let star = makeStar(position, .75, mainSizer()); state.stars.push(star); } // Place the remaining stars randomly. const starCount = 4 + p.abs(p.randomGaussian(1, 3)) | 0; for (let i = preset; i < starCount; i++) { const position = getOpening(state.stars); if (position) { let star = makeStar(position, .75, mainSizer()); state.stars.push(star); } } }, drawConstellation = _ => { state.lines = []; const connectableStars = [...state.stars], lineCount = state.stars.length * 1.3 + p.randomGaussian(.8, 2.3) | 0; while (state.lines.length < lineCount && connectableStars.length > 1) { const index1 = p.random(connectableStars.length) | 0, index2 = p.random(connectableStars.length) | 0; // Make sure different stars were selected. if (index1 === index2) { if (p.random() < .25) { // Random chance to remove this star from consideration. connectableStars.splice(index1, 1); } continue; } const star1 = connectableStars[index1], star2 = connectableStars[index2], xdiff = star2[0] - star1[0], ydiff = star2[1] - star1[1]; // Check if the stars are too close. if (xdiff * xdiff + ydiff * ydiff < 25) { if (p.random() < .33) { // Random chance to remove a star from consideration. const dist1 = star1[0] * star1[0] + star1[1] * star1[1], dist2 = star2[0] * star2[0] + star2[1] * star2[1], removeIndex = p.random(dist1 + dist2) < dist1 ? index1 : index2; connectableStars.splice(removeIndex, 1); } continue; } // Check if this line would cover a star. let covering = false; for (let star of state.stars) { if (star !== star1 && star !== star2 && isBetween(star1, star2, star, xdiff, ydiff)) { covering = star; break; } } if (covering) { let i = connectableStars.indexOf(covering); if (i >= 0 && p.random() < .2) { // Random chance to remove a star from consideration. const dist1 = star1[0] * star1[0] + star1[1] * star1[1], dist2 = star2[0] * star2[0] + star2[1] * star2[1], removeIndex = p.random(dist1 + dist2) < dist1 ? index1 : index2; connectableStars.splice(removeIndex, 1); } continue; } // Check if this line conflicts with another line. let intersections = 0, duplicate = false; for (let line of state.lines) { // Check if these lines have the same endpoints. if (line[4] === star1 && line[5] === star2 || line[4] === star2 && line[5] === star1) { duplicate = true; break; } // Check if these lines intersect. if (intersects(star1, star2, line)) { intersections++; } } if (duplicate) { if (p.random() < .4) { // Random chance to remove a star from consideration. const dist1 = star1[0] * star1[0] + star1[1] * star1[1], dist2 = star2[0] * star2[0] + star2[1] * star2[1], removeIndex = p.random(dist1 + dist2) < dist1 ? index1 : index2; connectableStars.splice(removeIndex, 1); } continue; } // The more intersections, the more likely this line will not be used. if (p.random() >= (1 / (intersections * lineCount / 2 + 1))) continue; if (intersections) state.intersections = true; state.lines.push(lineBetween(star1, star2, xdiff, ydiff)); } }, placeBackgroundStars = _ => { const totalStarCount = (state.sparse ? 20 : 35) + p.abs(p.randomGaussian(0, 15)) | 0; for (let i = state.stars.length; i < totalStarCount; i++) { const position = getOpening(state.stars, 22); if (position) { // Check that this new star isn't on a constellation line. let covered = false; for (let line of state.lines) { if (isOn(line, position, 2.5 + 1.5 * state.chibi)) { covered = true; break; } } if (!covered) { state.stars.push(makeStar(position, .15, p.random(.4, 1))); } } } }, addDust = _ => { state.dust = []; const dustCount = (state.sparse ? 80 : 350) + p.abs(p.randomGaussian(0, 100)) | 0; for (let i = 0; i < dustCount; i++) { const mote = makeStar( getOpening([], p.random(18, 24)), .05, p.random(.2, .6) * p.random(.25, 1) ); // Dust motes are dimmer than foreground and background stars. mote[3] *= p.random(.4, .7); state.dust.push(mote); } }, describe = _ => { let cycle = false; const groups = new Map(), getId = group => group.id || getId(group.parent), getRoot = group => group.parent && getRoot(group.parent) || group, lockId = group => group.id || (group.id = lockId(group.parent)); // Figure out how many groups of stars/lines there are. // In graph theory I guess these are "components"? // IDK it's been at least 15 years since I took a data structure class. for (let i = 0; i < state.lines.length; i++) { const line = state.lines[i], group1 = groups.get(line[4]), group2 = groups.get(line[5]); if (!group1) { if (!group2) { // Don't laugh at my disjoint-set data structure please. const newGroup = {id: i + 1}; groups.set(line[4], newGroup); groups.set(line[5], newGroup); } else { groups.set(line[4], group2); } } else { // group1 exists. if (!group2) { groups.set(line[5], group1); } else { if (getId(group1) !== getId(group2)) { // The worst possible way to union sets, probably. // There's definite O(n^2) energy, but n is small, so... const root = getRoot(group2); delete root.id; root.parent = group1; } else { // The group has run back into itself, so we have a cycle. cycle = true; } } } } // Collect the group IDs from all lines. const groupIds = new Map(); for (let group of groups.values()) { groupIds.set(lockId(group), true); } const lineTraits = []; if (state.intersections) lineTraits.push("Star-crossed"); if (groupIds.size > 1) lineTraits.push("Fragmented"); if (!cycle && state.lines.length > 1) lineTraits.push("Simple"); if (state.lines.length == 1) lineTraits.push("Minimalist"); if (!state.lines.length) lineTraits.push("Missing"); // Put an "and" between the last two traits. if (lineTraits.length > 1) { const last = lineTraits.pop() lineTraits.push(lineTraits.pop() + " and " + last); } const figureDescription = lineTraits.join(", ") + (lineTraits.length ? " " : "") + (state.dashed ? "Asterism" : "Constellation"), starDescription = (state.sparse ? "Sparse" : "Crowded") + " and " + (state.chibi ? "Luminous" : "Twinkling"), metadata = { "Figure": figureDescription, "Stars": starDescription, "Element": state.color[3], "transactionHash": state.transactionHash, }; console.log("metadata:", metadata); }; //-[ draw functions ]---------------------------------------------------------// p.draw = _ => { if (!state) return; // When not animating, fast forward to a frame where everything is drawn. const frame = state.animate ? state.progress : 1000; // Advance a frame unless this is a resize. if (!state.resize) { state.progress++; } else { state.resize = false; } // The canvas is 25 by 25, origin in the middle, rotated by time of day-ish. p.resetMatrix(); p.scale(p.width / 50); p.translate(25, 25); if (state.animate) { p.rotate(((new Date()).getTime() % 86164100) / 86164100 * p.TWO_PI); } p.noStroke(); p.blendMode(p.BLEND); p.background(16); p.blendMode(p.SCREEN); // Draw elements from back to front. Stardust first. if (!state.simple) for (let i = 0; i < state.dust.length; i++) { const dust = state.dust[i]; p.fill( p.constrain((dust[3] + (state.animate ? p.random(-10, 10) : 0)) * p.constrain((frame - i / 40) / p.random(10, 14), 0, 1), 0, 255) ); dust[dust.length - 1](); } // Then stars. for (let i = 0; i < state.stars.length; i++) { const star = state.stars[i]; p.fill( p.constrain((star[3] + (state.animate ? p.random(-20, 10) : 0)) * p.constrain((frame - i / 2) / 8, 0, 1), 0, 255) ); star[star.length - 1](); } // Then the asterism. p.strokeCap(p.ROUND); p.strokeWeight(state.chibi ? .66 : .4); if (!state.clear) for (let i = 0; i < state.lines.length; i++) { const line = state.lines[i]; let color = state.color.slice(0, 3); let flicker = !state.animate ? 1 : p.random(.93, 1) * p.random(.93, 1) * p.constrain( (frame - 6 - .6 * state.lines.length - i / 5 + p.random(2)) / 5, 0, 1 ); for (let i = 0; i < color.length; i++) { color[i] *= flicker; } p.stroke(...color); state.drawLine(line); } }; //-[ helper functions ]-------------------------------------------------------// const getOpening = (stars, distance = 18) => { let collision, tries = 0; do { collision = false; tries++; let point; // Random point in a circle with radius 20, using rejection sampling. do { point = [p.random(-distance, distance), p.random(-distance, distance)]; } while (point[0] * point[0] + point[1] * point[1] > distance * distance); for (let star of stars) { let xdiff = star[0] - point[0], ydiff = star[1] - point[1]; if (xdiff * xdiff + ydiff * ydiff < 2 * star[2] * star[2]) { collision = true; break; } } if (!collision) return point; } while (tries < 100); }, makeStar = (position, burstPercent, scale) => { const size = (scale || 1) * p.random(.6, .9), margin = state.chibi ? 1 : .6, brightness = p.random(240, 255); if (p.random() < burstPercent) { const blunt = p.random(.01, .07), fatness = p.random(.3, .6), sides = p.max(3, p.randomGaussian(5.5, .25) | 0), rotation = p.random(p.PI / sides), angle = p.TWO_PI / sides; // IDK. const maxInner = p.sin(p.HALF_PI - angle / 2), halfCutSquared = (1 - p.cos(p.PI * (1 - 1 / sides))) / 2, minInner = p.sqrt(1 - halfCutSquared), inner = minInner + (maxInner - minInner) * fatness; return [...position, size * 1.5 + margin, brightness, _ => { p.push(); p.translate(...position); p.rotate(rotation); p.scale(size); p.beginShape(); for (let s = 0; s < sides; s++) { p.vertex(p.cos(angle * (s - blunt)), p.sin(angle * (s - blunt))); p.vertex(p.cos(angle * (s + blunt)), p.sin(angle * (s + blunt))); p.vertex( inner * p.cos(angle * (s + .5)), inner * p.sin(angle * (s + .5)) ); } p.endShape(p.CLOSE); p.pop(); }]; } else { return [...position, size + margin, brightness, _ => { p.ellipse(...position, size, size); }]; } }, lineBetween = (star1, star2, xdiff, ydiff) => { const distance = p.sqrt(xdiff * xdiff + ydiff * ydiff), xOff = xdiff / distance, yOff = ydiff / distance, s1Dist = star1[2], s2Dist = star2[2]; return [ star1[0] + s1Dist * xOff, star1[1] + s1Dist * yOff, star2[0] - s2Dist * xOff, star2[1] - s2Dist * yOff, star1, star2, distance, ]; }, distanceSquared = (a, b) => { let x = a[0] - b[0], y = a[1] - b[1]; return x * x + y * y; }, isBetween = (star1, star2, covered, xdiff, ydiff, threshold = 2.5) => { let lengthSquared = xdiff * xdiff + ydiff * ydiff; let perpDistance = p.abs(ydiff * (covered[0] - star1[0]) - xdiff * (covered[1] - star1[1])) / p.sqrt(lengthSquared); return ( perpDistance < threshold && distanceSquared(star1, covered) < lengthSquared && distanceSquared(star2, covered) < lengthSquared ) }, // Same as `isBetween` except that it takes a line instead of endpoints. isOn = (line, point, threshold = 2.5) => isBetween( [line[0], line[1]], [line[2], line[3]], point, line[2] - line[0], line[3] - line[1], threshold ), clockwise = (star1, star2, star3) => (star3[1] - star1[1]) * (star2[0] - star1[0]) < (star2[1] - star1[1]) * (star3[0] - star1[0]), intersects = (star1, star2, line) => clockwise(star1, line, line.slice(2, 4)) != clockwise(star2, line, line.slice(2, 4)) && clockwise(star1, star2, line) != clockwise(star1, star2, line.slice(2, 4)); ```
Firmament```javascript "it rests among the stars / gathered up in the furthest firmament"; let canvas, // p5js canvas. state; // Keep all shared state in one place. //-[ setup functions ]--------------------------------------------------------// // Creates the p5js canvas and disables looping. // The rest of the setup is done when the Immutables properties are received. p.setup = _ => { canvas = p.createCanvas(1, 1); canvas.style("display", "block"); p.frameRate(10); p.noLoop(); }; // Responds to the properties provided by Immutables. p.myCustomRedrawAccordingToNewPropsHandler = properties => { if (!properties.transactionHash) return; // Check if existing state already matches the new properties. if ( state && state.transactionHash == properties.transactionHash && state.editionId == properties.editionId ) { state.square = properties.square; p.windowResized(); return; } // Pull bits from the hash to seed the RNG. p.randomSeed("0x" + properties.transactionHash.substr(2 + 8 * (properties.editionId % 8), 8)); // Intialize the state. state = { ...properties, animate: properties.square == 1, progress: 0, }; setStyling(); placeForegroundStars(); drawConstellation(); placeBackgroundStars(); addDust(); describe(); // Resize the window and turn looping on or off as needed. p.windowResized(); state.animate ? p.loop() : (p.noLoop(), p.redraw()); }; p.windowResized = _ => { if (!state) return; const minDim = p.min(p.windowWidth, p.windowHeight) * .8 / state.square | 0; if (minDim === p.width) return; p.resizeCanvas(minDim, minDim); state.resize = true; }; p.keyTyped = _ => { if (!state || state.square != 1) return; if (p.key == "A") { if (state.animate) { state.animate = false; p.noLoop(); p.redraw(); } else { state.animate = true; state.progress = 0; p.loop(); } } if (p.key == "B") { state.simple = !state.simple; } if (p.key == "C") { state.clear = !state.clear; } }; const setStyling = _ => { // Determine star size. state.chibi = p.random() < .06; state.dashed = p.random() < .06; state.sparse = p.random() < .18; const gap = state.chibi ? .7 : .5; state.drawLine = !state.dashed ? line => p.line(...line.slice(0, 4)) : line => { const dashes = p.max(1, line[6] / 3 | 0), scale = dashes - gap; for (let i = 0; i < dashes; i++) { p.line( p.lerp(line[0], line[2], i / scale), p.lerp(line[1], line[3], i / scale), p.lerp(line[0], line[2], (i + 1 - gap) / scale), p.lerp(line[1], line[3], (i + 1 - gap) / scale) ); } }; let color = p.random(); state.color = color < .12 ? [224, 42, 32, "Fire"] : color < .24 ? [96, 128, 247, "Water"] : color < .36 ? [148, 164, 196, "Air"] : [239, 239, 153, "Earth"]; }, placeForegroundStars = _ => { state.stars = []; const mainSizer = _ => state.chibi ? p.random(1.3, 1.8) : 1; // Place 2 to 4 stars somewhat uniformly. const preset = p.random(2, 5) | 0, angleOffset = p.random(p.TWO_PI / preset); for (let i = 0; i < preset; i++) { const dist = p.random(14, 20), angle = angleOffset + (i * p.TWO_PI + p.random(p.PI)) / preset, position = [dist * p.cos(angle), dist * p.sin(angle)]; let star = makeStar(position, .75, mainSizer()); state.stars.push(star); } // Place the remaining stars randomly. const starCount = 4 + p.abs(p.randomGaussian(1, 3)) | 0; for (let i = preset; i < starCount; i++) { const position = getOpening(state.stars); if (position) { let star = makeStar(position, .75, mainSizer()); state.stars.push(star); } } }, drawConstellation = _ => { state.lines = []; const connectableStars = [...state.stars], lineCount = state.stars.length * 1.3 + p.randomGaussian(.8, 2.3) | 0; while (state.lines.length < lineCount && connectableStars.length > 1) { const index1 = p.random(connectableStars.length) | 0, index2 = p.random(connectableStars.length) | 0; // Make sure different stars were selected. if (index1 === index2) { if (p.random() < .25) { // Random chance to remove this star from consideration. connectableStars.splice(index1, 1); } continue; } const star1 = connectableStars[index1], star2 = connectableStars[index2], xdiff = star2[0] - star1[0], ydiff = star2[1] - star1[1]; // Check if the stars are too close. if (xdiff * xdiff + ydiff * ydiff < 25) { if (p.random() < .33) { // Random chance to remove a star from consideration. const dist1 = star1[0] * star1[0] + star1[1] * star1[1], dist2 = star2[0] * star2[0] + star2[1] * star2[1], removeIndex = p.random(dist1 + dist2) < dist1 ? index1 : index2; connectableStars.splice(removeIndex, 1); } continue; } // Check if this line would cover a star. let covering = false; for (let star of state.stars) { if (star !== star1 && star !== star2 && isBetween(star1, star2, star, xdiff, ydiff)) { covering = star; break; } } if (covering) { let i = connectableStars.indexOf(covering); if (i >= 0 && p.random() < .2) { // Random chance to remove a star from consideration. const dist1 = star1[0] * star1[0] + star1[1] * star1[1], dist2 = star2[0] * star2[0] + star2[1] * star2[1], removeIndex = p.random(dist1 + dist2) < dist1 ? index1 : index2; connectableStars.splice(removeIndex, 1); } continue; } // Check if this line conflicts with another line. let intersections = 0, duplicate = false; for (let line of state.lines) { // Check if these lines have the same endpoints. if (line[4] === star1 && line[5] === star2 || line[4] === star2 && line[5] === star1) { duplicate = true; break; } // Check if these lines intersect. if (intersects(star1, star2, line)) { intersections++; } } if (duplicate) { if (p.random() < .4) { // Random chance to remove a star from consideration. const dist1 = star1[0] * star1[0] + star1[1] * star1[1], dist2 = star2[0] * star2[0] + star2[1] * star2[1], removeIndex = p.random(dist1 + dist2) < dist1 ? index1 : index2; connectableStars.splice(removeIndex, 1); } continue; } // The more intersections, the more likely this line will not be used. if (p.random() >= (1 / (intersections * lineCount / 2 + 1))) continue; if (intersections) state.intersections = true; state.lines.push(lineBetween(star1, star2, xdiff, ydiff)); } }, placeBackgroundStars = _ => { const totalStarCount = (state.sparse ? 20 : 35) + p.abs(p.randomGaussian(0, 15)) | 0; for (let i = state.stars.length; i < totalStarCount; i++) { const position = getOpening(state.stars, 22); if (position) { // Check that this new star isn't on a constellation line. let covered = false; for (let line of state.lines) { if (isOn(line, position, 2.5 + 1.5 * state.chibi)) { covered = true; break; } } if (!covered) { state.stars.push(makeStar(position, .15, p.random(.4, 1))); } } } }, addDust = _ => { state.dust = []; const dustCount = (state.sparse ? 80 : 350) + p.abs(p.randomGaussian(0, 100)) | 0; for (let i = 0; i < dustCount; i++) { const mote = makeStar( getOpening([], p.random(18, 24)), .05, p.random(.2, .6) * p.random(.25, 1) ); // Dust motes are dimmer than foreground and background stars. mote[3] *= p.random(.4, .7); state.dust.push(mote); } }, describe = _ => { let cycle = false; const groups = new Map(), getId = group => group.id || getId(group.parent), getRoot = group => group.parent && getRoot(group.parent) || group, lockId = group => group.id || (group.id = lockId(group.parent)); // Figure out how many groups of stars/lines there are. // In graph theory I guess these are "components"? // IDK it's been at least 15 years since I took a data structure class. for (let i = 0; i < state.lines.length; i++) { const line = state.lines[i], group1 = groups.get(line[4]), group2 = groups.get(line[5]); if (!group1) { if (!group2) { // Don't laugh at my disjoint-set data structure please. const newGroup = {id: i + 1}; groups.set(line[4], newGroup); groups.set(line[5], newGroup); } else { groups.set(line[4], group2); } } else { // group1 exists. if (!group2) { groups.set(line[5], group1); } else { if (getId(group1) !== getId(group2)) { // The worst possible way to union sets, probably. // There's definite O(n^2) energy, but n is small, so... const root = getRoot(group2); delete root.id; root.parent = group1; } else { // The group has run back into itself, so we have a cycle. cycle = true; } } } } // Collect the group IDs from all lines. const groupIds = new Map(); for (let group of groups.values()) { groupIds.set(lockId(group), true); } const lineTraits = []; if (state.intersections) lineTraits.push("Star-crossed"); if (groupIds.size > 1) lineTraits.push("Fragmented"); if (!cycle && state.lines.length > 1) lineTraits.push("Simple"); if (state.lines.length == 1) lineTraits.push("Minimalist"); if (!state.lines.length) lineTraits.push("Missing"); // Put an "and" between the last two traits. if (lineTraits.length > 1) { const last = lineTraits.pop() lineTraits.push(lineTraits.pop() + " and " + last); } const figureDescription = lineTraits.join(", ") + (lineTraits.length ? " " : "") + (state.dashed ? "Asterism" : "Constellation"), starDescription = (state.sparse ? "Sparse" : "Crowded") + " and " + (state.chibi ? "Luminous" : "Twinkling"), metadata = { "Figure": figureDescription, "Stars": starDescription, "Element": state.color[3], "transactionHash": state.transactionHash, }; console.log("metadata:", metadata); }; //-[ draw functions ]---------------------------------------------------------// p.draw = _ => { if (!state) return; // When not animating, fast forward to a frame where everything is drawn. const frame = state.animate ? state.progress : 1000; // Advance a frame unless this is a resize. if (!state.resize) { state.progress++; } else { state.resize = false; } // The canvas is 25 by 25, origin in the middle, rotated by time of day-ish. p.resetMatrix(); p.scale(p.width / 50); p.translate(25, 25); if (state.animate) { p.rotate(((new Date()).getTime() % 86164100) / 86164100 * p.TWO_PI); } p.noStroke(); p.blendMode(p.BLEND); p.background(16); p.blendMode(p.SCREEN); // Draw elements from back to front. Stardust first. if (!state.simple) for (let i = 0; i < state.dust.length; i++) { const dust = state.dust[i]; p.fill( p.constrain((dust[3] + (state.animate ? p.random(-10, 10) : 0)) * p.constrain((frame - i / 40) / p.random(10, 14), 0, 1), 0, 255) ); dust[dust.length - 1](); } // Then stars. for (let i = 0; i < state.stars.length; i++) { const star = state.stars[i]; p.fill( p.constrain((star[3] + (state.animate ? p.random(-20, 10) : 0)) * p.constrain((frame - i / 2) / 8, 0, 1), 0, 255) ); star[star.length - 1](); } // Then the asterism. p.strokeCap(p.ROUND); p.strokeWeight(state.chibi ? .66 : .4); if (!state.clear) for (let i = 0; i < state.lines.length; i++) { const line = state.lines[i]; let color = state.color.slice(0, 3); let flicker = !state.animate ? 1 : p.random(.93, 1) * p.random(.93, 1) * p.constrain( (frame - 6 - .6 * state.lines.length - i / 5 + p.random(2)) / 5, 0, 1 ); for (let i = 0; i < color.length; i++) { color[i] *= flicker; } p.stroke(...color); state.drawLine(line); } }; //-[ helper functions ]-------------------------------------------------------// const getOpening = (stars, distance = 18) => { let collision, tries = 0; do { collision = false; tries++; let point; // Random point in a circle with radius 20, using rejection sampling. do { point = [p.random(-distance, distance), p.random(-distance, distance)]; } while (point[0] * point[0] + point[1] * point[1] > distance * distance); for (let star of stars) { let xdiff = star[0] - point[0], ydiff = star[1] - point[1]; if (xdiff * xdiff + ydiff * ydiff < 2 * star[2] * star[2]) { collision = true; break; } } if (!collision) return point; } while (tries < 100); }, makeStar = (position, burstPercent, scale) => { const size = (scale || 1) * p.random(.6, .9), margin = state.chibi ? 1 : .6, brightness = p.random(240, 255); if (p.random() < burstPercent) { const blunt = p.random(.01, .07), fatness = p.random(.3, .6), sides = p.max(3, p.randomGaussian(5.5, .25) | 0), rotation = p.random(p.PI / sides), angle = p.TWO_PI / sides; // IDK. const maxInner = p.sin(p.HALF_PI - angle / 2), halfCutSquared = (1 - p.cos(p.PI * (1 - 1 / sides))) / 2, minInner = p.sqrt(1 - halfCutSquared), inner = minInner + (maxInner - minInner) * fatness; return [...position, size * 1.5 + margin, brightness, _ => { p.push(); p.translate(...position); p.rotate(rotation); p.scale(size); p.beginShape(); for (let s = 0; s < sides; s++) { p.vertex(p.cos(angle * (s - blunt)), p.sin(angle * (s - blunt))); p.vertex(p.cos(angle * (s + blunt)), p.sin(angle * (s + blunt))); p.vertex( inner * p.cos(angle * (s + .5)), inner * p.sin(angle * (s + .5)) ); } p.endShape(p.CLOSE); p.pop(); }]; } else { return [...position, size + margin, brightness, _ => { p.ellipse(...position, size, size); }]; } }, lineBetween = (star1, star2, xdiff, ydiff) => { const distance = p.sqrt(xdiff * xdiff + ydiff * ydiff), xOff = xdiff / distance, yOff = ydiff / distance, s1Dist = star1[2], s2Dist = star2[2]; return [ star1[0] + s1Dist * xOff, star1[1] + s1Dist * yOff, star2[0] - s2Dist * xOff, star2[1] - s2Dist * yOff, star1, star2, distance, ]; }, distanceSquared = (a, b) => { let x = a[0] - b[0], y = a[1] - b[1]; return x * x + y * y; }, isBetween = (star1, star2, covered, xdiff, ydiff, threshold = 2.5) => { let lengthSquared = xdiff * xdiff + ydiff * ydiff; let perpDistance = p.abs(ydiff * (covered[0] - star1[0]) - xdiff * (covered[1] - star1[1])) / p.sqrt(lengthSquared); return ( perpDistance < threshold && distanceSquared(star1, covered) < lengthSquared && distanceSquared(star2, covered) < lengthSquared ) }, // Same as `isBetween` except that it takes a line instead of endpoints. isOn = (line, point, threshold = 2.5) => isBetween( [line[0], line[1]], [line[2], line[3]], point, line[2] - line[0], line[3] - line[1], threshold ), clockwise = (star1, star2, star3) => (star3[1] - star1[1]) * (star2[0] - star1[0]) < (star2[1] - star1[1]) * (star3[0] - star1[0]), intersects = (star1, star2, line) => clockwise(star1, line, line.slice(2, 4)) != clockwise(star2, line, line.slice(2, 4)) && clockwise(star1, star2, line) != clockwise(star1, star2, line.slice(2, 4)); ```
unknown sendersent to0x499f4943…3001·#15,305,629·0xc327021a…5218a1
# Firmament _by [Mark Egli]_ Hopes, fears and dreams, traced in celestial realms, wheeling overhead. <p><img src="https://ipfs.io/ipfs/QmfZ4S1siFWYHCEim8NzAQ1z6nXSaDy2UaibqNF4LF2GXt" alt="Firmament Rinkeby Mint #2" title="Firmament Rinkeby Mint #2" style="width:100%;max-width:1024px;border-radius:15px;" /></p> **Code License:** [CC BY-NC-SA 4.0] **Edition License:** [NIFTY] [Mark Egli]: https://markegli.com [CC BY-NC-SA 4.0]: https://creativecommons.org/licenses/by-nc-sa/4.0/ [NIFTY]: https://www.nftlicense.org/ ## Controls | Input | Action | |:----------|:-------| | Shift + A | Toggle animation | | Shift + B | Toggle faint stars | | Shift + C | Toggle constellation lines | ## Traits ### Figure * Asterism or Constellation * _Star-crossed_ * _Fragmented_ * _Simple_ * _Minimalist_ * _Missing_ ### Stars * Crowded or Sparse * Luminous or Twinkling ### Element * Air, Earth, Fire or Water
Firmament# Firmament _by [Mark Egli]_ Hopes, fears and dreams, traced in celestial realms, wheeling overhead. <p><img src="https://ipfs.io/ipfs/QmfZ4S1siFWYHCEim8NzAQ1z6nXSaDy2UaibqNF4LF2GXt" alt="Firmament Rinkeby Mint #2" title="Firmament Rinkeby Mint #2" style="width:100%;max-width:1024px;border-radius:15px;" /></p> **Code License:** [CC BY-NC-SA 4.0] **Edition License:** [NIFTY] [Mark Egli]: https://markegli.com [CC BY-NC-SA 4.0]: https://creativecommons.org/licenses/by-nc-sa/4.0/ [NIFTY]: https://www.nftlicense.org/ ## Controls | Input | Action | |:----------|:-------| | Shift + A | Toggle animation | | Shift + B | Toggle faint stars | | Shift + C | Toggle constellation lines | ## Traits ### Figure * Asterism or Constellation * _Star-crossed_ * _Fragmented_ * _Simple_ * _Minimalist_ * _Missing_ ### Stars * Crowded or Sparse * Luminous or Twinkling ### Element * Air, Earth, Fire or Water
unknown sendersent to0x499f4943…3001·#15,255,285·0xed3becb1…95fe2f
H0xc7baaa5cab68007340396847497c487dc1311fc51ac186f0c170b7aaaf73af53``` const DEFAULT_DIM = 400; let background; let ballArea; let balls; let blendMode; let borders; let margin; let metadata; let quantized; let trailWipe; let waitTime; let wrap; function Ball(index, color) { // Start centered. this.x = ballArea / 2; this.y = ballArea / 2; this.size = p.floor(p.random(3, 51)); // Initial direction and speed. const direction = p.random(p.TWO_PI); const speed = 7 * p.sqrt(p.random()); this.xspeed = speed * p.sin(direction); this.yspeed = speed * p.cos(direction); if (quantized) { this.xspeed = p.round(this.xspeed); this.yspeed = p.round(this.yspeed); } this.color = color; metadata[`Ball #${index + 1} - Size`] = this.size; metadata[`Ball #${index + 1} - X Speed`] = this.xspeed; metadata[`Ball #${index + 1} - Y Speed`] = this.yspeed; metadata[`Ball #${index + 1} - Color`] = this.color.toString("#rrggbb"); this.update = function() { this.x += this.xspeed; this.y += this.yspeed; if (wrap) { this.wrap(); } else { this.bounce(); } }; this.display = function() { p.fill(this.color); p.ellipse(this.x, this.y, this.size, this.size); if (wrap) { p.ellipse(this.x - ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x - ballArea, this.y, this.size, this.size); p.ellipse(this.x - ballArea, this.y + ballArea, this.size, this.size); p.ellipse(this.x, this.y - ballArea, this.size, this.size); p.ellipse(this.x, this.y + ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y, this.size, this.size); p.ellipse(this.x + ballArea, this.y + ballArea, this.size, this.size); } }; this.bounce = function() { if (this.x < 0) { this.x *= -1; this.xspeed *= -1; } else if (this.x > ballArea) { this.x = 2 * ballArea - this.x; this.xspeed *= -1; } if (this.y < 0) { this.y *= -1; this.yspeed *= -1; } else if (this.y > ballArea) { this.y = 2 * ballArea - this.y; this.yspeed *= -1; } }; this.wrap = function() { if (this.x < 0) { this.x += ballArea; } else if (this.x > ballArea) { this.x -= ballArea; } if (this.y < 0) { this.y += ballArea; } else if (this.y > ballArea) { this.y -= ballArea; } }; } p.myCustomRedrawAccordingToNewPropsHandler = props => { if (props.transactionHash && props.square) { const WIDTH = (window.innerWidth) / props.square * 0.8; const HEIGHT = (window.innerHeight) / props.square * 0.8; const DIM = p.min(WIDTH, HEIGHT); p.createCanvas(DIM, DIM); p.frameRate(60); metadata = {}; // Seed the p5js random seed using the first 32 bits of the hash. if(props.editionId && ((props.editionId >= 586 && props.editionId <= 635) || (props.editionId >= 938 && props.editionId <= 962) ) ) { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "True"; const burn = 150 * (props.editionId % 50); for (let i = 0; i < burn; i++) { p.random(); } } else { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "False"; } // Set up the style. let getBallColor; let styleThreshold = 0; const style = p.random(100); p.colorMode(p.HSL, 1); blendMode = p.BLEND; margin = 25 * p.floor(p.random(4)); ballArea = DEFAULT_DIM - 2 * margin; borders = p.random(7) >= 1; quantized = p.random(18) >= 1; waitTime = p.floor(p.random(300)); wrap = p.random(10) < 1; const trail = p.random(6) < 1; const ballCount = p.floor(p.random(2, 4) * p.random(2, 5)); if (style < (styleThreshold += 16)) { metadata["Style"] = "Monochrome"; const hue = p.random(); const saturation = p.random(); getBallColor = _ => p.color(hue, saturation, p.random()); const lightness = p.random(); background = p.color(hue, saturation, lightness); trailWipe = p.color(hue, saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 14)) { metadata["Style"] = "Spectrum"; const hue = p.random(); const span = 0.25 + p.random(0.25); getBallColor = i => p.color(hue + span * (i / (ballCount - 1)), p.random(0.5, 1), p.random(1, 2) / 3); const saturation = p.random(0.25, 0.75); const lightness = p.random(); const backgroundHue = hue + p.random(span); background = p.color(backgroundHue, 1 - saturation, lightness); trailWipe = p.color(backgroundHue, 1 - saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 20)) { metadata["Style"] = "Spotlight"; blendMode = p.ADD; borders = !borders; getBallColor = _ => p.color(p.floor(p.random(6)) / 6, p.random() < 0.1, p.random() ** 1.5); background = p.color(0); trailWipe = p.color(0, 0, 0, trail ? 2 / 3 : 1); } else { metadata["Style"] = "Random"; p.colorMode(p.RGB, 1); getBallColor = _ => p.color(p.random(), p.random(), p.random()); const red = p.random(), green = p.random(), blue = p.random(); background = p.color(red, green, blue); trailWipe = p.color(red, green, blue, trail ? 2 / 3 : 1); } p.background(background); metadata["Background"] = background.toString("#rrggbb"); metadata["Borders"] = borders ? "Yes" : "No"; metadata["Dwell Before Bang"] = waitTime; metadata["Edges"] = wrap ? "Wrap" : "Bounce"; metadata["Margin"] = margin; metadata["Number of Balls"] = ballCount; metadata["Speeds"] = quantized ? "Quantized" : "Varied"; metadata["Trails"] = trail ? "Yes" : "No"; metadata["transactionHash"] = props.transactionHash; // Create ball objects. balls = []; for (var i = 0; i < ballCount; i++) { balls[i] = new Ball(i, getBallColor(i)); } metadata["Stillness"] = balls.some(ball => !ball.xspeed && !ball.yspeed) ? "Yes" : "No"; console.log("metadata: ", metadata); } }; p.draw = _ => { if (balls.length) { // Allows all calculations to be based on DEFAULT_DIM. p.scale(p.width / DEFAULT_DIM); p.translate(margin, margin); p.blendMode(p.BLEND); p.background(trailWipe); p.blendMode(blendMode); if (borders) { p.stroke(0); p.strokeWeight(+borders); } else { p.noStroke(); } // Update and draw each ball. if (p.frameCount == 1 || p.frameCount > waitTime) { for (var i = 0; i < balls.length; i++) { balls[i].update(); balls[i].display(); } } else { for (var i = 0; i < balls.length; i++) { balls[i].display(); } } p.fill(background); if (margin && wrap) { p.noStroke(); p.rect(-margin, -margin, DEFAULT_DIM, margin); p.rect(-margin, -margin, margin, DEFAULT_DIM); p.rect(-margin, ballArea, DEFAULT_DIM, margin); p.rect(ballArea, -margin, margin, DEFAULT_DIM); } } } ```
BigBangH0xc7baaa5cab68007340396847497c487dc1311fc51ac186f0c170b7aaaf73af53``` const DEFAULT_DIM = 400; let background; let ballArea; let balls; let blendMode; let borders; let margin; let metadata; let quantized; let trailWipe; let waitTime; let wrap; function Ball(index, color) { // Start centered. this.x = ballArea / 2; this.y = ballArea / 2; this.size = p.floor(p.random(3, 51)); // Initial direction and speed. const direction = p.random(p.TWO_PI); const speed = 7 * p.sqrt(p.random()); this.xspeed = speed * p.sin(direction); this.yspeed = speed * p.cos(direction); if (quantized) { this.xspeed = p.round(this.xspeed); this.yspeed = p.round(this.yspeed); } this.color = color; metadata[`Ball #${index + 1} - Size`] = this.size; metadata[`Ball #${index + 1} - X Speed`] = this.xspeed; metadata[`Ball #${index + 1} - Y Speed`] = this.yspeed; metadata[`Ball #${index + 1} - Color`] = this.color.toString("#rrggbb"); this.update = function() { this.x += this.xspeed; this.y += this.yspeed; if (wrap) { this.wrap(); } else { this.bounce(); } }; this.display = function() { p.fill(this.color); p.ellipse(this.x, this.y, this.size, this.size); if (wrap) { p.ellipse(this.x - ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x - ballArea, this.y, this.size, this.size); p.ellipse(this.x - ballArea, this.y + ballArea, this.size, this.size); p.ellipse(this.x, this.y - ballArea, this.size, this.size); p.ellipse(this.x, this.y + ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y, this.size, this.size); p.ellipse(this.x + ballArea, this.y + ballArea, this.size, this.size); } }; this.bounce = function() { if (this.x < 0) { this.x *= -1; this.xspeed *= -1; } else if (this.x > ballArea) { this.x = 2 * ballArea - this.x; this.xspeed *= -1; } if (this.y < 0) { this.y *= -1; this.yspeed *= -1; } else if (this.y > ballArea) { this.y = 2 * ballArea - this.y; this.yspeed *= -1; } }; this.wrap = function() { if (this.x < 0) { this.x += ballArea; } else if (this.x > ballArea) { this.x -= ballArea; } if (this.y < 0) { this.y += ballArea; } else if (this.y > ballArea) { this.y -= ballArea; } }; } p.myCustomRedrawAccordingToNewPropsHandler = props => { if (props.transactionHash && props.square) { const WIDTH = (window.innerWidth) / props.square * 0.8; const HEIGHT = (window.innerHeight) / props.square * 0.8; const DIM = p.min(WIDTH, HEIGHT); p.createCanvas(DIM, DIM); p.frameRate(60); metadata = {}; // Seed the p5js random seed using the first 32 bits of the hash. if(props.editionId && ((props.editionId >= 586 && props.editionId <= 635) || (props.editionId >= 938 && props.editionId <= 962) ) ) { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "True"; const burn = 150 * (props.editionId % 50); for (let i = 0; i < burn; i++) { p.random(); } } else { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "False"; } // Set up the style. let getBallColor; let styleThreshold = 0; const style = p.random(100); p.colorMode(p.HSL, 1); blendMode = p.BLEND; margin = 25 * p.floor(p.random(4)); ballArea = DEFAULT_DIM - 2 * margin; borders = p.random(7) >= 1; quantized = p.random(18) >= 1; waitTime = p.floor(p.random(300)); wrap = p.random(10) < 1; const trail = p.random(6) < 1; const ballCount = p.floor(p.random(2, 4) * p.random(2, 5)); if (style < (styleThreshold += 16)) { metadata["Style"] = "Monochrome"; const hue = p.random(); const saturation = p.random(); getBallColor = _ => p.color(hue, saturation, p.random()); const lightness = p.random(); background = p.color(hue, saturation, lightness); trailWipe = p.color(hue, saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 14)) { metadata["Style"] = "Spectrum"; const hue = p.random(); const span = 0.25 + p.random(0.25); getBallColor = i => p.color(hue + span * (i / (ballCount - 1)), p.random(0.5, 1), p.random(1, 2) / 3); const saturation = p.random(0.25, 0.75); const lightness = p.random(); const backgroundHue = hue + p.random(span); background = p.color(backgroundHue, 1 - saturation, lightness); trailWipe = p.color(backgroundHue, 1 - saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 20)) { metadata["Style"] = "Spotlight"; blendMode = p.ADD; borders = !borders; getBallColor = _ => p.color(p.floor(p.random(6)) / 6, p.random() < 0.1, p.random() ** 1.5); background = p.color(0); trailWipe = p.color(0, 0, 0, trail ? 2 / 3 : 1); } else { metadata["Style"] = "Random"; p.colorMode(p.RGB, 1); getBallColor = _ => p.color(p.random(), p.random(), p.random()); const red = p.random(), green = p.random(), blue = p.random(); background = p.color(red, green, blue); trailWipe = p.color(red, green, blue, trail ? 2 / 3 : 1); } p.background(background); metadata["Background"] = background.toString("#rrggbb"); metadata["Borders"] = borders ? "Yes" : "No"; metadata["Dwell Before Bang"] = waitTime; metadata["Edges"] = wrap ? "Wrap" : "Bounce"; metadata["Margin"] = margin; metadata["Number of Balls"] = ballCount; metadata["Speeds"] = quantized ? "Quantized" : "Varied"; metadata["Trails"] = trail ? "Yes" : "No"; metadata["transactionHash"] = props.transactionHash; // Create ball objects. balls = []; for (var i = 0; i < ballCount; i++) { balls[i] = new Ball(i, getBallColor(i)); } metadata["Stillness"] = balls.some(ball => !ball.xspeed && !ball.yspeed) ? "Yes" : "No"; console.log("metadata: ", metadata); } }; p.draw = _ => { if (balls.length) { // Allows all calculations to be based on DEFAULT_DIM. p.scale(p.width / DEFAULT_DIM); p.translate(margin, margin); p.blendMode(p.BLEND); p.background(trailWipe); p.blendMode(blendMode); if (borders) { p.stroke(0); p.strokeWeight(+borders); } else { p.noStroke(); } // Update and draw each ball. if (p.frameCount == 1 || p.frameCount > waitTime) { for (var i = 0; i < balls.length; i++) { balls[i].update(); balls[i].display(); } } else { for (var i = 0; i < balls.length; i++) { balls[i].display(); } } p.fill(background); if (margin && wrap) { p.noStroke(); p.rect(-margin, -margin, DEFAULT_DIM, margin); p.rect(-margin, -margin, margin, DEFAULT_DIM); p.rect(-margin, ballArea, DEFAULT_DIM, margin); p.rect(ballArea, -margin, margin, DEFAULT_DIM); } } } ```
unknown sendersent to0x499f4943…3001·#15,255,253·0xc7baaa5c…73af53
``` const DEFAULT_DIM = 400; let background; let ballArea; let balls; let blendMode; let borders; let margin; let metadata; let quantized; let trailWipe; let waitTime; let wrap; function Ball(index, color) { // Start centered. this.x = ballArea / 2; this.y = ballArea / 2; this.size = p.floor(p.random(3, 51)); // Initial direction and speed. const direction = p.random(p.TWO_PI); const speed = 7 * p.sqrt(p.random()); this.xspeed = speed * p.sin(direction); this.yspeed = speed * p.cos(direction); if (quantized) { this.xspeed = p.round(this.xspeed); this.yspeed = p.round(this.yspeed); } this.color = color; metadata[`Ball #${index + 1} - Size`] = this.size; metadata[`Ball #${index + 1} - X Speed`] = this.xspeed; metadata[`Ball #${index + 1} - Y Speed`] = this.yspeed; metadata[`Ball #${index + 1} - Color`] = this.color.toString("#rrggbb"); this.update = function() { this.x += this.xspeed; this.y += this.yspeed; if (wrap) { this.wrap(); } else { this.bounce(); } }; this.display = function() { p.fill(this.color); p.ellipse(this.x, this.y, this.size, this.size); if (wrap) { p.ellipse(this.x - ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x - ballArea, this.y, this.size, this.size); p.ellipse(this.x - ballArea, this.y + ballArea, this.size, this.size); p.ellipse(this.x, this.y - ballArea, this.size, this.size); p.ellipse(this.x, this.y + ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y, this.size, this.size); p.ellipse(this.x + ballArea, this.y + ballArea, this.size, this.size); } }; this.bounce = function() { if (this.x < 0) { this.x *= -1; this.xspeed *= -1; } else if (this.x > ballArea) { this.x = 2 * ballArea - this.x; this.xspeed *= -1; } if (this.y < 0) { this.y *= -1; this.yspeed *= -1; } else if (this.y > ballArea) { this.y = 2 * ballArea - this.y; this.yspeed *= -1; } }; this.wrap = function() { if (this.x < 0) { this.x += ballArea; } else if (this.x > ballArea) { this.x -= ballArea; } if (this.y < 0) { this.y += ballArea; } else if (this.y > ballArea) { this.y -= ballArea; } }; } p.myCustomRedrawAccordingToNewPropsHandler = props => { if (props.transactionHash && props.square) { const WIDTH = (window.innerWidth) / props.square * 0.8; const HEIGHT = (window.innerHeight) / props.square * 0.8; const DIM = p.min(WIDTH, HEIGHT); p.createCanvas(DIM, DIM); p.frameRate(60); metadata = {}; // Seed the p5js random seed using the first 32 bits of the hash. if(props.editionId && ((props.editionId >= 587 && props.editionId <= 635) || (props.editionId >= 939 && props.editionId <= 962) ) ) { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "True"; const burn = 150 * (props.editionId % 50); for (let i = 0; i < burn; i++) { p.random(); } } else { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "False"; } // Set up the style. let getBallColor; let styleThreshold = 0; const style = p.random(100); p.colorMode(p.HSL, 1); blendMode = p.BLEND; margin = 25 * p.floor(p.random(4)); ballArea = DEFAULT_DIM - 2 * margin; borders = p.random(7) >= 1; quantized = p.random(18) >= 1; waitTime = p.floor(p.random(300)); wrap = p.random(10) < 1; const trail = p.random(6) < 1; const ballCount = p.floor(p.random(2, 4) * p.random(2, 5)); if (style < (styleThreshold += 16)) { metadata["Style"] = "Monochrome"; const hue = p.random(); const saturation = p.random(); getBallColor = _ => p.color(hue, saturation, p.random()); const lightness = p.random(); background = p.color(hue, saturation, lightness); trailWipe = p.color(hue, saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 14)) { metadata["Style"] = "Spectrum"; const hue = p.random(); const span = 0.25 + p.random(0.25); getBallColor = i => p.color(hue + span * (i / (ballCount - 1)), p.random(0.5, 1), p.random(1, 2) / 3); const saturation = p.random(0.25, 0.75); const lightness = p.random(); const backgroundHue = hue + p.random(span); background = p.color(backgroundHue, 1 - saturation, lightness); trailWipe = p.color(backgroundHue, 1 - saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 20)) { metadata["Style"] = "Spotlight"; blendMode = p.ADD; borders = !borders; getBallColor = _ => p.color(p.floor(p.random(6)) / 6, p.random() < 0.1, p.random() ** 1.5); background = p.color(0); trailWipe = p.color(0, 0, 0, trail ? 2 / 3 : 1); } else { metadata["Style"] = "Random"; p.colorMode(p.RGB, 1); getBallColor = _ => p.color(p.random(), p.random(), p.random()); const red = p.random(), green = p.random(), blue = p.random(); background = p.color(red, green, blue); trailWipe = p.color(red, green, blue, trail ? 2 / 3 : 1); } p.background(background); metadata["Background"] = background.toString("#rrggbb"); metadata["Borders"] = borders ? "Yes" : "No"; metadata["Dwell Before Bang"] = waitTime; metadata["Edges"] = wrap ? "Wrap" : "Bounce"; metadata["Margin"] = margin; metadata["Number of Balls"] = ballCount; metadata["Speeds"] = quantized ? "Quantized" : "Varied"; metadata["Trails"] = trail ? "Yes" : "No"; metadata["transactionHash"] = props.transactionHash; // Create ball objects. balls = []; for (var i = 0; i < ballCount; i++) { balls[i] = new Ball(i, getBallColor(i)); } metadata["Stillness"] = balls.some(ball => !ball.xspeed && !ball.yspeed) ? "Yes" : "No"; console.log("metadata: ", metadata); } }; p.draw = _ => { if (balls.length) { // Allows all calculations to be based on DEFAULT_DIM. p.scale(p.width / DEFAULT_DIM); p.translate(margin, margin); p.blendMode(p.BLEND); p.background(trailWipe); p.blendMode(blendMode); if (borders) { p.stroke(0); p.strokeWeight(+borders); } else { p.noStroke(); } // Update and draw each ball. if (p.frameCount == 1 || p.frameCount > waitTime) { for (var i = 0; i < balls.length; i++) { balls[i].update(); balls[i].display(); } } else { for (var i = 0; i < balls.length; i++) { balls[i].display(); } } p.fill(background); if (margin && wrap) { p.noStroke(); p.rect(-margin, -margin, DEFAULT_DIM, margin); p.rect(-margin, -margin, margin, DEFAULT_DIM); p.rect(-margin, ballArea, DEFAULT_DIM, margin); p.rect(ballArea, -margin, margin, DEFAULT_DIM); } } } ```
BigBang``` const DEFAULT_DIM = 400; let background; let ballArea; let balls; let blendMode; let borders; let margin; let metadata; let quantized; let trailWipe; let waitTime; let wrap; function Ball(index, color) { // Start centered. this.x = ballArea / 2; this.y = ballArea / 2; this.size = p.floor(p.random(3, 51)); // Initial direction and speed. const direction = p.random(p.TWO_PI); const speed = 7 * p.sqrt(p.random()); this.xspeed = speed * p.sin(direction); this.yspeed = speed * p.cos(direction); if (quantized) { this.xspeed = p.round(this.xspeed); this.yspeed = p.round(this.yspeed); } this.color = color; metadata[`Ball #${index + 1} - Size`] = this.size; metadata[`Ball #${index + 1} - X Speed`] = this.xspeed; metadata[`Ball #${index + 1} - Y Speed`] = this.yspeed; metadata[`Ball #${index + 1} - Color`] = this.color.toString("#rrggbb"); this.update = function() { this.x += this.xspeed; this.y += this.yspeed; if (wrap) { this.wrap(); } else { this.bounce(); } }; this.display = function() { p.fill(this.color); p.ellipse(this.x, this.y, this.size, this.size); if (wrap) { p.ellipse(this.x - ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x - ballArea, this.y, this.size, this.size); p.ellipse(this.x - ballArea, this.y + ballArea, this.size, this.size); p.ellipse(this.x, this.y - ballArea, this.size, this.size); p.ellipse(this.x, this.y + ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y - ballArea, this.size, this.size); p.ellipse(this.x + ballArea, this.y, this.size, this.size); p.ellipse(this.x + ballArea, this.y + ballArea, this.size, this.size); } }; this.bounce = function() { if (this.x < 0) { this.x *= -1; this.xspeed *= -1; } else if (this.x > ballArea) { this.x = 2 * ballArea - this.x; this.xspeed *= -1; } if (this.y < 0) { this.y *= -1; this.yspeed *= -1; } else if (this.y > ballArea) { this.y = 2 * ballArea - this.y; this.yspeed *= -1; } }; this.wrap = function() { if (this.x < 0) { this.x += ballArea; } else if (this.x > ballArea) { this.x -= ballArea; } if (this.y < 0) { this.y += ballArea; } else if (this.y > ballArea) { this.y -= ballArea; } }; } p.myCustomRedrawAccordingToNewPropsHandler = props => { if (props.transactionHash && props.square) { const WIDTH = (window.innerWidth) / props.square * 0.8; const HEIGHT = (window.innerHeight) / props.square * 0.8; const DIM = p.min(WIDTH, HEIGHT); p.createCanvas(DIM, DIM); p.frameRate(60); metadata = {}; // Seed the p5js random seed using the first 32 bits of the hash. if(props.editionId && ((props.editionId >= 587 && props.editionId <= 635) || (props.editionId >= 939 && props.editionId <= 962) ) ) { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "True"; const burn = 150 * (props.editionId % 50); for (let i = 0; i < burn; i++) { p.random(); } } else { p.randomSeed(+props.transactionHash.substr(0, 10)); metadata["ExtraRandom"] = "False"; } // Set up the style. let getBallColor; let styleThreshold = 0; const style = p.random(100); p.colorMode(p.HSL, 1); blendMode = p.BLEND; margin = 25 * p.floor(p.random(4)); ballArea = DEFAULT_DIM - 2 * margin; borders = p.random(7) >= 1; quantized = p.random(18) >= 1; waitTime = p.floor(p.random(300)); wrap = p.random(10) < 1; const trail = p.random(6) < 1; const ballCount = p.floor(p.random(2, 4) * p.random(2, 5)); if (style < (styleThreshold += 16)) { metadata["Style"] = "Monochrome"; const hue = p.random(); const saturation = p.random(); getBallColor = _ => p.color(hue, saturation, p.random()); const lightness = p.random(); background = p.color(hue, saturation, lightness); trailWipe = p.color(hue, saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 14)) { metadata["Style"] = "Spectrum"; const hue = p.random(); const span = 0.25 + p.random(0.25); getBallColor = i => p.color(hue + span * (i / (ballCount - 1)), p.random(0.5, 1), p.random(1, 2) / 3); const saturation = p.random(0.25, 0.75); const lightness = p.random(); const backgroundHue = hue + p.random(span); background = p.color(backgroundHue, 1 - saturation, lightness); trailWipe = p.color(backgroundHue, 1 - saturation, lightness, trail ? 2 / 3 : 1); } else if (style < (styleThreshold += 20)) { metadata["Style"] = "Spotlight"; blendMode = p.ADD; borders = !borders; getBallColor = _ => p.color(p.floor(p.random(6)) / 6, p.random() < 0.1, p.random() ** 1.5); background = p.color(0); trailWipe = p.color(0, 0, 0, trail ? 2 / 3 : 1); } else { metadata["Style"] = "Random"; p.colorMode(p.RGB, 1); getBallColor = _ => p.color(p.random(), p.random(), p.random()); const red = p.random(), green = p.random(), blue = p.random(); background = p.color(red, green, blue); trailWipe = p.color(red, green, blue, trail ? 2 / 3 : 1); } p.background(background); metadata["Background"] = background.toString("#rrggbb"); metadata["Borders"] = borders ? "Yes" : "No"; metadata["Dwell Before Bang"] = waitTime; metadata["Edges"] = wrap ? "Wrap" : "Bounce"; metadata["Margin"] = margin; metadata["Number of Balls"] = ballCount; metadata["Speeds"] = quantized ? "Quantized" : "Varied"; metadata["Trails"] = trail ? "Yes" : "No"; metadata["transactionHash"] = props.transactionHash; // Create ball objects. balls = []; for (var i = 0; i < ballCount; i++) { balls[i] = new Ball(i, getBallColor(i)); } metadata["Stillness"] = balls.some(ball => !ball.xspeed && !ball.yspeed) ? "Yes" : "No"; console.log("metadata: ", metadata); } }; p.draw = _ => { if (balls.length) { // Allows all calculations to be based on DEFAULT_DIM. p.scale(p.width / DEFAULT_DIM); p.translate(margin, margin); p.blendMode(p.BLEND); p.background(trailWipe); p.blendMode(blendMode); if (borders) { p.stroke(0); p.strokeWeight(+borders); } else { p.noStroke(); } // Update and draw each ball. if (p.frameCount == 1 || p.frameCount > waitTime) { for (var i = 0; i < balls.length; i++) { balls[i].update(); balls[i].display(); } } else { for (var i = 0; i < balls.length; i++) { balls[i].display(); } } p.fill(background); if (margin && wrap) { p.noStroke(); p.rect(-margin, -margin, DEFAULT_DIM, margin); p.rect(-margin, -margin, margin, DEFAULT_DIM); p.rect(-margin, ballArea, DEFAULT_DIM, margin); p.rect(ballArea, -margin, margin, DEFAULT_DIM); } } } ```
unknown sendersent to0x499f4943…3001·#15,155,272·0x82b67b4d…418d64
``` let TX; let TXN; let EID; let DIM; let WIDTH; let HEIGHT; let decPairs; let perlinSeed; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } console.log("decPairs :", decPairs); } printMetadata = () => { metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } let tShader; let SCALE; let wHW; let sGreen; let vShader, fShader; p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); getHashData(1); // SEEDING p.randomSeed(+props.transactionHash.substr(0, 10)); perlinSeed = p.random(0, 255); p.noiseSeed(perlinSeed); console.log("randomSeed: ", +props.transactionHash.substr(0, 10)); console.log("noiseSeed: ", perlinSeed); console.log("transaction: ", TX); vShader = ` attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform float u_frame2; void main() { vTexCoord = aTexCoord; vec4 positionVec4 = vec4(aPosition, 1.0); positionVec4.xy = positionVec4.xy * ${p.random() * 10 + 2} -1.; gl_Position = positionVec4; } `; fShader = ` precision mediump float; varying vec2 vTexCoord; uniform float u_frame; uniform vec2 u_resolution; void main() { vec2 coord = gl_FragCoord.xy/u_resolution.xy; coord ${p.random() > 0.5 ? "*" : "/"}= coord / ${p.random() * 10.0} -1.*${p.random() > 0.5 ? "sin" : "cos"}(u_frame*0.1); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)*10.1, -1. + ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); float dd = distance(coord, vec2(cos(coord.y), ${p.random() > 0.5 ? "sin" : "cos"}(coord.x))); float dd2 = distance(coord, vec2(cos(dd), ${p.random() > 0.5 ? "sin" : "cos"}(dd))); float dd3 = distance(coord, vec2(u_frame, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)) / dd3; float dd4 = distance(coord, vec2(1, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); float dd5 = smoothstep(u_frame, fract(dd3*dd2), ${p.random() > 0.5 ? "sin" : "cos"}(dd4)); dd ${p.random() > 0.5 ? "*" : "+"}= dd2 * dd3 / dd4*dd5; float ddf = mix(${p.random()}, ${p.random()}, dd5); vec3 df = vec3(${p.random() > 0.5 ? "sin" : "cos"}(fract(dd5)), ${p.random() > 0.5 ? "sin" : "cos"}(fract(${p.random() > 0.5 ? "dd2" : "dd3"})), ${p.random() > 0.5 ? "sin" : "cos"}(fract(dd3*0.1))); ddf ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), df.x); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "df.y" : "df.z"}, df.z); coord ${p.random() > 0.5 ? "*" : "+"}= smoothstep(u_frame, df.x, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); df ${p.random() > 0.5 ? "*" : "+"}= mix(sin(u_frame)*${p.random()}, ${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); dd5 ${p.random() > 0.5 ? "*" : "+"}= dot(${p.random() > 0.5 ? "dd" : "dd2"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); coord ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random() > 0.5 ? "dd2" : "dd5"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), dd5); gl_FragColor = vec4(${p.random() > 0.5 ? "df.b" : "df.r"},fract(${p.random() > 0.5 ? "coord.x" : "coord.y"}/${p.random() > 0.5 ? "dd5" : "dd4"}),${p.random() > 0.5 ? "sin" : "cos"}(${p.random() > 0.5 ? "df.b" : "df.g"}*${p.random() > 0.5 ? "u_frame" : p.random()}),1./${p.random()}); } `; p.createCanvas(DIM, DIM, p.WEBGL); const gl = p.canvas.getContext('webgl') gl.disable(gl.DEPTH_TEST) p.frameRate(30); SCALE = DIM / 400; wHW = 400 sGreen = (p.random()*1000)+500 tShader = p.createShader(vShader, fShader); p.pixelDensity(1) p.background(sGreen) printMetadata(); } p.redraw(); }; p.draw = () => { p.push(); p.translate(-DIM / 2, -DIM / 2); p.scale(SCALE); p.pop(); tShader.setUniform('u_resolution', [DIM, DIM]); tShader.setUniform('u_frame', (sGreen+p.frameCount)*0.005); p.shader(tShader); p.square(0, 0, wHW); p.resetShader(); p.random(); } ```
``` let TX; let TXN; let EID; let DIM; let WIDTH; let HEIGHT; let decPairs; let perlinSeed; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } console.log("decPairs :", decPairs); } printMetadata = () => { metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } let tShader; let SCALE; let wHW; let sGreen; let vShader, fShader; p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); getHashData(1); // SEEDING p.randomSeed(+props.transactionHash.substr(0, 10)); perlinSeed = p.random(0, 255); p.noiseSeed(perlinSeed); console.log("randomSeed: ", +props.transactionHash.substr(0, 10)); console.log("noiseSeed: ", perlinSeed); console.log("transaction: ", TX); vShader = ` attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform float u_frame2; void main() { vTexCoord = aTexCoord; vec4 positionVec4 = vec4(aPosition, 1.0); positionVec4.xy = positionVec4.xy * ${p.random() * 10 + 2} -1.; gl_Position = positionVec4; } `; fShader = ` precision mediump float; varying vec2 vTexCoord; uniform float u_frame; uniform vec2 u_resolution; void main() { vec2 coord = gl_FragCoord.xy/u_resolution.xy; coord ${p.random() > 0.5 ? "*" : "/"}= coord / ${p.random() * 10.0} -1.*${p.random() > 0.5 ? "sin" : "cos"}(u_frame*0.1); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)*10.1, -1. + ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); float dd = distance(coord, vec2(cos(coord.y), ${p.random() > 0.5 ? "sin" : "cos"}(coord.x))); float dd2 = distance(coord, vec2(cos(dd), ${p.random() > 0.5 ? "sin" : "cos"}(dd))); float dd3 = distance(coord, vec2(u_frame, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)) / dd3; float dd4 = distance(coord, vec2(1, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); float dd5 = smoothstep(u_frame, fract(dd3*dd2), ${p.random() > 0.5 ? "sin" : "cos"}(dd4)); dd ${p.random() > 0.5 ? "*" : "+"}= dd2 * dd3 / dd4*dd5; float ddf = mix(${p.random()}, ${p.random()}, dd5); vec3 df = vec3(${p.random() > 0.5 ? "sin" : "cos"}(fract(dd5)), ${p.random() > 0.5 ? "sin" : "cos"}(fract(${p.random() > 0.5 ? "dd2" : "dd3"})), ${p.random() > 0.5 ? "sin" : "cos"}(fract(dd3*0.1))); ddf ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), df.x); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "df.y" : "df.z"}, df.z); coord ${p.random() > 0.5 ? "*" : "+"}= smoothstep(u_frame, df.x, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); df ${p.random() > 0.5 ? "*" : "+"}= mix(sin(u_frame)*${p.random()}, ${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); dd5 ${p.random() > 0.5 ? "*" : "+"}= dot(${p.random() > 0.5 ? "dd" : "dd2"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); coord ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random() > 0.5 ? "dd2" : "dd5"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), dd5); gl_FragColor = vec4(${p.random() > 0.5 ? "df.b" : "df.r"},fract(${p.random() > 0.5 ? "coord.x" : "coord.y"}/${p.random() > 0.5 ? "dd5" : "dd4"}),${p.random() > 0.5 ? "sin" : "cos"}(${p.random() > 0.5 ? "df.b" : "df.g"}*${p.random() > 0.5 ? "u_frame" : p.random()}),1./${p.random()}); } `; p.createCanvas(DIM, DIM, p.WEBGL); const gl = p.canvas.getContext('webgl') gl.disable(gl.DEPTH_TEST) p.frameRate(30); SCALE = DIM / 400; wHW = 400 sGreen = (p.random()*1000)+500 tShader = p.createShader(vShader, fShader); p.pixelDensity(1) p.background(sGreen) printMetadata(); } p.redraw(); }; p.draw = () => { p.push(); p.translate(-DIM / 2, -DIM / 2); p.scale(SCALE); p.pop(); tShader.setUniform('u_resolution', [DIM, DIM]); tShader.setUniform('u_frame', (sGreen+p.frameCount)*0.005); p.shader(tShader); p.square(0, 0, wHW); p.resetShader(); p.random(); } ```
unknown sendersent to0x499f4943…3001·#15,154,336·0xd46762ee…0e6a00
``` // ----------------------- CODE STARTS HERE -------------------------- // let TX; let TXN; let EID; let DIM; let WIDTH; let HEIGHT; let decPairs; let perlinSeed; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } console.log("decPairs :", decPairs); } printMetadata = () => { metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } //----------------- ARTIST STARTS CUSTOM FUNCTIONS HERE -----------------// let HW = Math.min(window.innerWidth, window.innerHeight); let tShader; let SCALE; let wHW; let sGreen; let vShader, fShader; //------------------ ARTIST ENDS CUSTOM FUNCTIONS HERE ------------------// p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); getHashData(1); // SEEDING p.randomSeed(+props.transactionHash.substr(0, 10)); perlinSeed = p.random(0, 255); p.noiseSeed(perlinSeed); console.log("randomSeed: ", +props.transactionHash.substr(0, 10)); console.log("noiseSeed: ", perlinSeed); console.log("transaction: ", TX); //--------------------- ARTIST STARTS SETUP HERE -----------------------// vShader = ` attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform float u_frame2; void main() { vTexCoord = aTexCoord; vec4 positionVec4 = vec4(aPosition, 1.0); positionVec4.xy = positionVec4.xy * ${p.random() * 10 + 2} -1.; gl_Position = positionVec4; } `; fShader = ` precision mediump float; varying vec2 vTexCoord; uniform float u_frame; uniform vec2 u_resolution; void main() { vec2 coord = gl_FragCoord.xy/u_resolution.xy; coord ${p.random() > 0.5 ? "*" : "/"}= coord / ${p.random() * 10.0} -1.*${p.random() > 0.5 ? "sin" : "cos"}(u_frame*0.1); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)*10.1, -1. + ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); float dd = distance(coord, vec2(cos(coord.y), ${p.random() > 0.5 ? "sin" : "cos"}(coord.x))); float dd2 = distance(coord, vec2(cos(dd), ${p.random() > 0.5 ? "sin" : "cos"}(dd))); float dd3 = distance(coord, vec2(u_frame, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)) / dd3; float dd4 = distance(coord, vec2(1, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); float dd5 = smoothstep(u_frame, fract(dd3*dd2), ${p.random() > 0.5 ? "sin" : "cos"}(dd4)); dd ${p.random() > 0.5 ? "*" : "+"}= dd2 * dd3 / dd4*dd5; float ddf = mix(${p.random()}, ${p.random()}, dd5); vec3 df = vec3(${p.random() > 0.5 ? "sin" : "cos"}(fract(dd5)), ${p.random() > 0.5 ? "sin" : "cos"}(fract(${p.random() > 0.5 ? "dd2" : "dd3"})), ${p.random() > 0.5 ? "sin" : "cos"}(fract(dd3*0.1))); ddf ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), df.x); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "df.y" : "df.z"}, df.z); coord ${p.random() > 0.5 ? "*" : "+"}= smoothstep(u_frame, df.x, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); df ${p.random() > 0.5 ? "*" : "+"}= mix(sin(u_frame)*${p.random()}, ${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); dd5 ${p.random() > 0.5 ? "*" : "+"}= dot(${p.random() > 0.5 ? "dd" : "dd2"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); coord ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random() > 0.5 ? "dd2" : "dd5"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), dd5); gl_FragColor = vec4(${p.random() > 0.5 ? "df.b" : "df.r"},fract(${p.random() > 0.5 ? "coord.x" : "coord.y"}/${p.random() > 0.5 ? "dd5" : "dd4"}),${p.random() > 0.5 ? "sin" : "cos"}(${p.random() > 0.5 ? "df.b" : "df.g"}*${p.random() > 0.5 ? "u_frame" : p.random()}),1./${p.random()}); } `; p.createCanvas(HW, HW, p.WEBGL); const gl = p.canvas.getContext('webgl') gl.disable(gl.DEPTH_TEST) p.frameRate(30); SCALE = HW / 400; wHW = 400 sGreen = (p.random()*1000)+500 tShader = p.createShader(vShader, fShader); p.pixelDensity(1) p.background(sGreen) //----------------------------------------------------------------------// printMetadata(); } p.redraw(); }; p.draw = () => { //-------------------- ARTIST STARTS DRAWING HERE ----------------------// //if (frameCount == 75) noLoop(); p.push(); p.translate(-HW / 2, -HW / 2); p.scale(SCALE); p.pop(); tShader.setUniform('u_resolution', [HW, HW]); tShader.setUniform('u_frame', (sGreen+p.frameCount)*0.005); p.shader(tShader); p.square(0, 0, wHW); p.resetShader(); //----------------------------------------------------------------------// } // ------------------------- CODE ENDS HERE --------------------------- // ```
``` // ----------------------- CODE STARTS HERE -------------------------- // let TX; let TXN; let EID; let DIM; let WIDTH; let HEIGHT; let decPairs; let perlinSeed; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } console.log("decPairs :", decPairs); } printMetadata = () => { metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } //----------------- ARTIST STARTS CUSTOM FUNCTIONS HERE -----------------// let HW = Math.min(window.innerWidth, window.innerHeight); let tShader; let SCALE; let wHW; let sGreen; let vShader, fShader; //------------------ ARTIST ENDS CUSTOM FUNCTIONS HERE ------------------// p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); getHashData(1); // SEEDING p.randomSeed(+props.transactionHash.substr(0, 10)); perlinSeed = p.random(0, 255); p.noiseSeed(perlinSeed); console.log("randomSeed: ", +props.transactionHash.substr(0, 10)); console.log("noiseSeed: ", perlinSeed); console.log("transaction: ", TX); //--------------------- ARTIST STARTS SETUP HERE -----------------------// vShader = ` attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform float u_frame2; void main() { vTexCoord = aTexCoord; vec4 positionVec4 = vec4(aPosition, 1.0); positionVec4.xy = positionVec4.xy * ${p.random() * 10 + 2} -1.; gl_Position = positionVec4; } `; fShader = ` precision mediump float; varying vec2 vTexCoord; uniform float u_frame; uniform vec2 u_resolution; void main() { vec2 coord = gl_FragCoord.xy/u_resolution.xy; coord ${p.random() > 0.5 ? "*" : "/"}= coord / ${p.random() * 10.0} -1.*${p.random() > 0.5 ? "sin" : "cos"}(u_frame*0.1); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)*10.1, -1. + ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); float dd = distance(coord, vec2(cos(coord.y), ${p.random() > 0.5 ? "sin" : "cos"}(coord.x))); float dd2 = distance(coord, vec2(cos(dd), ${p.random() > 0.5 ? "sin" : "cos"}(dd))); float dd3 = distance(coord, vec2(u_frame, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)) / dd3; float dd4 = distance(coord, vec2(1, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); float dd5 = smoothstep(u_frame, fract(dd3*dd2), ${p.random() > 0.5 ? "sin" : "cos"}(dd4)); dd ${p.random() > 0.5 ? "*" : "+"}= dd2 * dd3 / dd4*dd5; float ddf = mix(${p.random()}, ${p.random()}, dd5); vec3 df = vec3(${p.random() > 0.5 ? "sin" : "cos"}(fract(dd5)), ${p.random() > 0.5 ? "sin" : "cos"}(fract(${p.random() > 0.5 ? "dd2" : "dd3"})), ${p.random() > 0.5 ? "sin" : "cos"}(fract(dd3*0.1))); ddf ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), df.x); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "df.y" : "df.z"}, df.z); coord ${p.random() > 0.5 ? "*" : "+"}= smoothstep(u_frame, df.x, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); df ${p.random() > 0.5 ? "*" : "+"}= mix(sin(u_frame)*${p.random()}, ${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); dd5 ${p.random() > 0.5 ? "*" : "+"}= dot(${p.random() > 0.5 ? "dd" : "dd2"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); coord ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random() > 0.5 ? "dd2" : "dd5"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), dd5); gl_FragColor = vec4(${p.random() > 0.5 ? "df.b" : "df.r"},fract(${p.random() > 0.5 ? "coord.x" : "coord.y"}/${p.random() > 0.5 ? "dd5" : "dd4"}),${p.random() > 0.5 ? "sin" : "cos"}(${p.random() > 0.5 ? "df.b" : "df.g"}*${p.random() > 0.5 ? "u_frame" : p.random()}),1./${p.random()}); } `; p.createCanvas(HW, HW, p.WEBGL); const gl = p.canvas.getContext('webgl') gl.disable(gl.DEPTH_TEST) p.frameRate(30); SCALE = HW / 400; wHW = 400 sGreen = (p.random()*1000)+500 tShader = p.createShader(vShader, fShader); p.pixelDensity(1) p.background(sGreen) //----------------------------------------------------------------------// printMetadata(); } p.redraw(); }; p.draw = () => { //-------------------- ARTIST STARTS DRAWING HERE ----------------------// //if (frameCount == 75) noLoop(); p.push(); p.translate(-HW / 2, -HW / 2); p.scale(SCALE); p.pop(); tShader.setUniform('u_resolution', [HW, HW]); tShader.setUniform('u_frame', (sGreen+p.frameCount)*0.005); p.shader(tShader); p.square(0, 0, wHW); p.resetShader(); //----------------------------------------------------------------------// } // ------------------------- CODE ENDS HERE --------------------------- // ```
unknown sendersent to0x499f4943…3001·#15,151,822·0xed56b4a9…fd4c6e
``` // ----------------------- CODE STARTS HERE -------------------------- // let TX; let TXN; let EID; let DIM; let WIDTH; let HEIGHT; let decPairs; let perlinSeed; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } console.log("decPairs :", decPairs); } printMetadata = () => { metadataObj.traitName1 = "Change traitName and put your value here"; metadataObj.traitName2 = "Change traitName and put your value here"; metadataObj.traitName3 = "Change traitName and put your value here"; metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } //----------------- ARTIST STARTS CUSTOM FUNCTIONS HERE -----------------// let HW = Math.min(window.innerWidth, window.innerHeight); let tShader; let SCALE; let wHW; let sGreen; let vShader, fShader; //------------------ ARTIST ENDS CUSTOM FUNCTIONS HERE ------------------// p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); getHashData(1); // SEEDING p.randomSeed(+props.transactionHash.substr(0, 10)); perlinSeed = p.random(0, 255); p.noiseSeed(perlinSeed); console.log("randomSeed: ", +props.transactionHash.substr(0, 10)); console.log("noiseSeed: ", perlinSeed); console.log("transaction: ", TX); //--------------------- ARTIST STARTS SETUP HERE -----------------------// vShader = ` attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform float u_frame2; void main() { vTexCoord = aTexCoord; vec4 positionVec4 = vec4(aPosition, 1.0); positionVec4.xy = positionVec4.xy * ${p.random() * 10 + 2} -1.; gl_Position = positionVec4; } `; fShader = ` precision mediump float; varying vec2 vTexCoord; uniform float u_frame; uniform vec2 u_resolution; void main() { vec2 coord = gl_FragCoord.xy/u_resolution.xy; coord ${p.random() > 0.5 ? "*" : "/"}= coord / ${p.random() * 10.0} -1.*${p.random() > 0.5 ? "sin" : "cos"}(u_frame*0.1); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)*10.1, -1. + ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); float dd = distance(coord, vec2(cos(coord.y), ${p.random() > 0.5 ? "sin" : "cos"}(coord.x))); float dd2 = distance(coord, vec2(cos(dd), ${p.random() > 0.5 ? "sin" : "cos"}(dd))); float dd3 = distance(coord, vec2(u_frame, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)) / dd3; float dd4 = distance(coord, vec2(1, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); float dd5 = smoothstep(u_frame, fract(dd3*dd2), ${p.random() > 0.5 ? "sin" : "cos"}(dd4)); dd ${p.random() > 0.5 ? "*" : "+"}= dd2 * dd3 / dd4*dd5; float ddf = mix(${p.random()}, ${p.random()}, dd5); vec3 df = vec3(${p.random() > 0.5 ? "sin" : "cos"}(fract(dd5)), ${p.random() > 0.5 ? "sin" : "cos"}(fract(${p.random() > 0.5 ? "dd2" : "dd3"})), ${p.random() > 0.5 ? "sin" : "cos"}(fract(dd3*0.1))); ddf ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), df.x); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "df.y" : "df.z"}, df.z); coord ${p.random() > 0.5 ? "*" : "+"}= smoothstep(u_frame, df.x, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); df ${p.random() > 0.5 ? "*" : "+"}= mix(sin(u_frame)*${p.random()}, ${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); dd5 ${p.random() > 0.5 ? "*" : "+"}= dot(${p.random() > 0.5 ? "dd" : "dd2"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); coord ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random() > 0.5 ? "dd2" : "dd5"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), dd5); gl_FragColor = vec4(${p.random() > 0.5 ? "df.b" : "df.r"},fract(${p.random() > 0.5 ? "coord.x" : "coord.y"}/${p.random() > 0.5 ? "dd5" : "dd4"}),${p.random() > 0.5 ? "sin" : "cos"}(${p.random() > 0.5 ? "df.b" : "df.g"}*${p.random() > 0.5 ? "u_frame" : p.random()}),1./${p.random()}); } `; p.createCanvas(HW, HW, p.WEBGL); const gl = p.canvas.getContext('webgl') gl.disable(gl.DEPTH_TEST) p.frameRate(30); SCALE = HW / 400; wHW = 400 sGreen = (p.random()*1000)+500 tShader = p.createShader(vShader, fShader); p.pixelDensity(1) p.background(sGreen) //----------------------------------------------------------------------// printMetadata(); } p.redraw(); }; p.draw = () => { //-------------------- ARTIST STARTS DRAWING HERE ----------------------// //if (frameCount == 75) noLoop(); p.push(); p.translate(-HW / 2, -HW / 2); p.scale(SCALE); p.pop(); tShader.setUniform('u_resolution', [HW, HW]); tShader.setUniform('u_frame', (sGreen+p.frameCount)*0.005); p.shader(tShader); p.square(0, 0, wHW); p.resetShader(); //----------------------------------------------------------------------// } // ------------------------- CODE ENDS HERE --------------------------- // ```
``` // ----------------------- CODE STARTS HERE -------------------------- // let TX; let TXN; let EID; let DIM; let WIDTH; let HEIGHT; let decPairs; let perlinSeed; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } console.log("decPairs :", decPairs); } printMetadata = () => { metadataObj.traitName1 = "Change traitName and put your value here"; metadataObj.traitName2 = "Change traitName and put your value here"; metadataObj.traitName3 = "Change traitName and put your value here"; metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } //----------------- ARTIST STARTS CUSTOM FUNCTIONS HERE -----------------// let HW = Math.min(window.innerWidth, window.innerHeight); let tShader; let SCALE; let wHW; let sGreen; let vShader, fShader; //------------------ ARTIST ENDS CUSTOM FUNCTIONS HERE ------------------// p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); getHashData(1); // SEEDING p.randomSeed(+props.transactionHash.substr(0, 10)); perlinSeed = p.random(0, 255); p.noiseSeed(perlinSeed); console.log("randomSeed: ", +props.transactionHash.substr(0, 10)); console.log("noiseSeed: ", perlinSeed); console.log("transaction: ", TX); //--------------------- ARTIST STARTS SETUP HERE -----------------------// vShader = ` attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform float u_frame2; void main() { vTexCoord = aTexCoord; vec4 positionVec4 = vec4(aPosition, 1.0); positionVec4.xy = positionVec4.xy * ${p.random() * 10 + 2} -1.; gl_Position = positionVec4; } `; fShader = ` precision mediump float; varying vec2 vTexCoord; uniform float u_frame; uniform vec2 u_resolution; void main() { vec2 coord = gl_FragCoord.xy/u_resolution.xy; coord ${p.random() > 0.5 ? "*" : "/"}= coord / ${p.random() * 10.0} -1.*${p.random() > 0.5 ? "sin" : "cos"}(u_frame*0.1); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)*10.1, -1. + ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); float dd = distance(coord, vec2(cos(coord.y), ${p.random() > 0.5 ? "sin" : "cos"}(coord.x))); float dd2 = distance(coord, vec2(cos(dd), ${p.random() > 0.5 ? "sin" : "cos"}(dd))); float dd3 = distance(coord, vec2(u_frame, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)) / dd3; float dd4 = distance(coord, vec2(1, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); float dd5 = smoothstep(u_frame, fract(dd3*dd2), ${p.random() > 0.5 ? "sin" : "cos"}(dd4)); dd ${p.random() > 0.5 ? "*" : "+"}= dd2 * dd3 / dd4*dd5; float ddf = mix(${p.random()}, ${p.random()}, dd5); vec3 df = vec3(${p.random() > 0.5 ? "sin" : "cos"}(fract(dd5)), ${p.random() > 0.5 ? "sin" : "cos"}(fract(${p.random() > 0.5 ? "dd2" : "dd3"})), ${p.random() > 0.5 ? "sin" : "cos"}(fract(dd3*0.1))); ddf ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), df.x); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "df.y" : "df.z"}, df.z); coord ${p.random() > 0.5 ? "*" : "+"}= smoothstep(u_frame, df.x, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); df ${p.random() > 0.5 ? "*" : "+"}= mix(sin(u_frame)*${p.random()}, ${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); dd5 ${p.random() > 0.5 ? "*" : "+"}= dot(${p.random() > 0.5 ? "dd" : "dd2"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); coord ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random() > 0.5 ? "dd2" : "dd5"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), dd5); gl_FragColor = vec4(${p.random() > 0.5 ? "df.b" : "df.r"},fract(${p.random() > 0.5 ? "coord.x" : "coord.y"}/${p.random() > 0.5 ? "dd5" : "dd4"}),${p.random() > 0.5 ? "sin" : "cos"}(${p.random() > 0.5 ? "df.b" : "df.g"}*${p.random() > 0.5 ? "u_frame" : p.random()}),1./${p.random()}); } `; p.createCanvas(HW, HW, p.WEBGL); const gl = p.canvas.getContext('webgl') gl.disable(gl.DEPTH_TEST) p.frameRate(30); SCALE = HW / 400; wHW = 400 sGreen = (p.random()*1000)+500 tShader = p.createShader(vShader, fShader); p.pixelDensity(1) p.background(sGreen) //----------------------------------------------------------------------// printMetadata(); } p.redraw(); }; p.draw = () => { //-------------------- ARTIST STARTS DRAWING HERE ----------------------// //if (frameCount == 75) noLoop(); p.push(); p.translate(-HW / 2, -HW / 2); p.scale(SCALE); p.pop(); tShader.setUniform('u_resolution', [HW, HW]); tShader.setUniform('u_frame', (sGreen+p.frameCount)*0.005); p.shader(tShader); p.square(0, 0, wHW); p.resetShader(); //----------------------------------------------------------------------// } // ------------------------- CODE ENDS HERE --------------------------- // ```
unknown sendersent to0x499f4943…3001·#15,151,791·0x4124432e…bb2bbe
``` // ----------------------- CODE STARTS HERE -------------------------- // let TX; let TXN; let EID; let DIM; let WIDTH; let HEIGHT; let decPairs; let perlinSeed; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } console.log("decPairs :", decPairs); } printMetadata = () => { metadataObj.traitName1 = "Change traitName and put your value here"; metadataObj.traitName2 = "Change traitName and put your value here"; metadataObj.traitName3 = "Change traitName and put your value here"; metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } //----------------- ARTIST STARTS CUSTOM FUNCTIONS HERE -----------------// let HW = Math.min(window.innerWidth, window.innerHeight); let tShader; let SCALE; let wHW; let sGreen; let vShader, fShader; //------------------ ARTIST ENDS CUSTOM FUNCTIONS HERE ------------------// p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); getHashData(1); // SEEDING p.randomSeed(+props.transactionHash.substr(0, 10)); perlinSeed = p.random(0, 255); p.noiseSeed(perlinSeed); console.log("randomSeed: ", +props.transactionHash.substr(0, 10)); console.log("noiseSeed: ", perlinSeed); console.log("transaction: ", TX); //--------------------- ARTIST STARTS SETUP HERE -----------------------// vShader = ` attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform float u_frame2; void main() { vTexCoord = aTexCoord; vec4 positionVec4 = vec4(aPosition, 1.0); positionVec4.xy = positionVec4.xy * ${p.random() * 10 + 2} -1.; gl_Position = positionVec4; } `; fShader = ` precision mediump float; varying vec2 vTexCoord; uniform float u_frame; uniform vec2 u_resolution; void main() { vec2 coord = gl_FragCoord.xy/u_resolution.xy; coord ${p.random() > 0.5 ? "*" : "/"}= coord / ${p.random() * 10.0} -1.*${p.random() > 0.5 ? "sin" : "cos"}(u_frame*0.1); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)*10.1, -1. + ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); float dd = distance(coord, vec2(cos(coord.y), ${p.random() > 0.5 ? "sin" : "cos"}(coord.x))); float dd2 = distance(coord, vec2(cos(dd), ${p.random() > 0.5 ? "sin" : "cos"}(dd))); float dd3 = distance(coord, vec2(u_frame, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)) / dd3; float dd4 = distance(coord, vec2(1, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); float dd5 = smoothstep(u_frame, fract(dd3*dd2), ${p.random() > 0.5 ? "sin" : "cos"}(dd4)); dd ${p.random() > 0.5 ? "*" : "+"}= dd2 * dd3 / dd4*dd5; float ddf = mix(${p.random()}, ${p.random()}, dd5); vec3 df = vec3(${p.random() > 0.5 ? "sin" : "cos"}(fract(dd5)), ${p.random() > 0.5 ? "sin" : "cos"}(fract(${p.random() > 0.5 ? "dd2" : "dd3"})), ${p.random() > 0.5 ? "sin" : "cos"}(fract(dd3*0.1))); ddf ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), df.x); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "df.y" : "df.z"}, df.z); coord ${p.random() > 0.5 ? "*" : "+"}= smoothstep(u_frame, df.x, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); df ${p.random() > 0.5 ? "*" : "+"}= mix(sin(u_frame)*${p.random()}, ${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); dd5 ${p.random() > 0.5 ? "*" : "+"}= dot(${p.random() > 0.5 ? "dd" : "dd2"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); coord ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random() > 0.5 ? "dd2" : "dd5"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), dd5); gl_FragColor = vec4(${p.random() > 0.5 ? "df.b" : "df.r"},fract(${p.random() > 0.5 ? "coord.x" : "coord.y"}/${p.random() > 0.5 ? "dd5" : "dd4"}),${p.random() > 0.5 ? "sin" : "cos"}(${p.random() > 0.5 ? "df.b" : "df.g"}*${p.random() > 0.5 ? "u_frame" : p.random()}),1./${p.random()}); } `; p.createCanvas(HW, HW, p.WEBGL); const gl = p.canvas.getContext('webgl') gl.disable(gl.DEPTH_TEST) p.frameRate(30); SCALE = HW / 400; wHW = 400 sGreen = (p.random()*1000)+500 tShader = p.createShader(vShader, fShader); p.pixelDensity(1) p.background(sGreen) //----------------------------------------------------------------------// printMetadata(); } p.redraw(); }; p.draw = () => { //-------------------- ARTIST STARTS DRAWING HERE ----------------------// //if (frameCount == 75) noLoop(); p.push(); p.translate(-HW / 2, -HW / 2); p.scale(SCALE); p.pop(); tShader.setUniform('u_resolution', [HW, HW]); tShader.setUniform('u_frame', (sGreen+p.frameCount)*0.005); p.shader(tShader); p.square(0, 0, wHW); p.resetShadep.random(); //----------------------------------------------------------------------// } // ------------------------- CODE ENDS HERE --------------------------- // ```
``` // ----------------------- CODE STARTS HERE -------------------------- // let TX; let TXN; let EID; let DIM; let WIDTH; let HEIGHT; let decPairs; let perlinSeed; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } console.log("decPairs :", decPairs); } printMetadata = () => { metadataObj.traitName1 = "Change traitName and put your value here"; metadataObj.traitName2 = "Change traitName and put your value here"; metadataObj.traitName3 = "Change traitName and put your value here"; metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } //----------------- ARTIST STARTS CUSTOM FUNCTIONS HERE -----------------// let HW = Math.min(window.innerWidth, window.innerHeight); let tShader; let SCALE; let wHW; let sGreen; let vShader, fShader; //------------------ ARTIST ENDS CUSTOM FUNCTIONS HERE ------------------// p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); getHashData(1); // SEEDING p.randomSeed(+props.transactionHash.substr(0, 10)); perlinSeed = p.random(0, 255); p.noiseSeed(perlinSeed); console.log("randomSeed: ", +props.transactionHash.substr(0, 10)); console.log("noiseSeed: ", perlinSeed); console.log("transaction: ", TX); //--------------------- ARTIST STARTS SETUP HERE -----------------------// vShader = ` attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform float u_frame2; void main() { vTexCoord = aTexCoord; vec4 positionVec4 = vec4(aPosition, 1.0); positionVec4.xy = positionVec4.xy * ${p.random() * 10 + 2} -1.; gl_Position = positionVec4; } `; fShader = ` precision mediump float; varying vec2 vTexCoord; uniform float u_frame; uniform vec2 u_resolution; void main() { vec2 coord = gl_FragCoord.xy/u_resolution.xy; coord ${p.random() > 0.5 ? "*" : "/"}= coord / ${p.random() * 10.0} -1.*${p.random() > 0.5 ? "sin" : "cos"}(u_frame*0.1); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)*10.1, -1. + ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); float dd = distance(coord, vec2(cos(coord.y), ${p.random() > 0.5 ? "sin" : "cos"}(coord.x))); float dd2 = distance(coord, vec2(cos(dd), ${p.random() > 0.5 ? "sin" : "cos"}(dd))); float dd3 = distance(coord, vec2(u_frame, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)) / dd3; float dd4 = distance(coord, vec2(1, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); float dd5 = smoothstep(u_frame, fract(dd3*dd2), ${p.random() > 0.5 ? "sin" : "cos"}(dd4)); dd ${p.random() > 0.5 ? "*" : "+"}= dd2 * dd3 / dd4*dd5; float ddf = mix(${p.random()}, ${p.random()}, dd5); vec3 df = vec3(${p.random() > 0.5 ? "sin" : "cos"}(fract(dd5)), ${p.random() > 0.5 ? "sin" : "cos"}(fract(${p.random() > 0.5 ? "dd2" : "dd3"})), ${p.random() > 0.5 ? "sin" : "cos"}(fract(dd3*0.1))); ddf ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), df.x); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "df.y" : "df.z"}, df.z); coord ${p.random() > 0.5 ? "*" : "+"}= smoothstep(u_frame, df.x, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); df ${p.random() > 0.5 ? "*" : "+"}= mix(sin(u_frame)*${p.random()}, ${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); dd5 ${p.random() > 0.5 ? "*" : "+"}= dot(${p.random() > 0.5 ? "dd" : "dd2"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); coord ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random() > 0.5 ? "dd2" : "dd5"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), dd5); gl_FragColor = vec4(${p.random() > 0.5 ? "df.b" : "df.r"},fract(${p.random() > 0.5 ? "coord.x" : "coord.y"}/${p.random() > 0.5 ? "dd5" : "dd4"}),${p.random() > 0.5 ? "sin" : "cos"}(${p.random() > 0.5 ? "df.b" : "df.g"}*${p.random() > 0.5 ? "u_frame" : p.random()}),1./${p.random()}); } `; p.createCanvas(HW, HW, p.WEBGL); const gl = p.canvas.getContext('webgl') gl.disable(gl.DEPTH_TEST) p.frameRate(30); SCALE = HW / 400; wHW = 400 sGreen = (p.random()*1000)+500 tShader = p.createShader(vShader, fShader); p.pixelDensity(1) p.background(sGreen) //----------------------------------------------------------------------// printMetadata(); } p.redraw(); }; p.draw = () => { //-------------------- ARTIST STARTS DRAWING HERE ----------------------// //if (frameCount == 75) noLoop(); p.push(); p.translate(-HW / 2, -HW / 2); p.scale(SCALE); p.pop(); tShader.setUniform('u_resolution', [HW, HW]); tShader.setUniform('u_frame', (sGreen+p.frameCount)*0.005); p.shader(tShader); p.square(0, 0, wHW); p.resetShadep.random(); //----------------------------------------------------------------------// } // ------------------------- CODE ENDS HERE --------------------------- // ```
unknown sendersent to0x499f4943…3001·#15,151,516·0x6e5ade28…afd566
// ----------------------- CODE STARTS HERE -------------------------- // let TX; let TXN; let EID; let DIM; let WIDTH; let HEIGHT; let decPairs; let perlinSeed; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } console.log("decPairs :", decPairs); } printMetadata = () => { metadataObj.traitName1 = "Change traitName and put your value here"; metadataObj.traitName2 = "Change traitName and put your value here"; metadataObj.traitName3 = "Change traitName and put your value here"; metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } //----------------- ARTIST STARTS CUSTOM FUNCTIONS HERE -----------------// let HW = Math.min(window.innerWidth, window.innerHeight); let tShader; let SCALE; let wHW; let sGreen; let vShader, fShader; //------------------ ARTIST ENDS CUSTOM FUNCTIONS HERE ------------------// p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); getHashData(1); // SEEDING p.randomSeed(+props.transactionHash.substr(0, 10)); perlinSeed = p.random(0, 255); p.noiseSeed(perlinSeed); console.log("randomSeed: ", +props.transactionHash.substr(0, 10)); console.log("noiseSeed: ", perlinSeed); console.log("transaction: ", TX); //--------------------- ARTIST STARTS SETUP HERE -----------------------// vShader = ` attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform float u_frame2; void main() { vTexCoord = aTexCoord; vec4 positionVec4 = vec4(aPosition, 1.0); positionVec4.xy = positionVec4.xy * ${p.random() * 10 + 2} -1.; gl_Position = positionVec4; } `; fShader = ` precision mediump float; varying vec2 vTexCoord; uniform float u_frame; uniform vec2 u_resolution; void main() { vec2 coord = gl_FragCoord.xy/u_resolution.xy; coord ${p.random() > 0.5 ? "*" : "/"}= coord / ${p.random() * 10.0} -1.*${p.random() > 0.5 ? "sin" : "cos"}(u_frame*0.1); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)*10.1, -1. + ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); float dd = distance(coord, vec2(cos(coord.y), ${p.random() > 0.5 ? "sin" : "cos"}(coord.x))); float dd2 = distance(coord, vec2(cos(dd), ${p.random() > 0.5 ? "sin" : "cos"}(dd))); float dd3 = distance(coord, vec2(u_frame, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)) / dd3; float dd4 = distance(coord, vec2(1, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); float dd5 = smoothstep(u_frame, fract(dd3*dd2), ${p.random() > 0.5 ? "sin" : "cos"}(dd4)); dd ${p.random() > 0.5 ? "*" : "+"}= dd2 * dd3 / dd4*dd5; float ddf = mix(${p.random()}, ${p.random()}, dd5); vec3 df = vec3(${p.random() > 0.5 ? "sin" : "cos"}(fract(dd5)), ${p.random() > 0.5 ? "sin" : "cos"}(fract(${p.random() > 0.5 ? "dd2" : "dd3"})), ${p.random() > 0.5 ? "sin" : "cos"}(fract(dd3*0.1))); ddf ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), df.x); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "df.y" : "df.z"}, df.z); coord ${p.random() > 0.5 ? "*" : "+"}= smoothstep(u_frame, df.x, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); df ${p.random() > 0.5 ? "*" : "+"}= mix(sin(u_frame)*${p.random()}, ${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); dd5 ${p.random() > 0.5 ? "*" : "+"}= dot(${p.random() > 0.5 ? "dd" : "dd2"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); coord ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random() > 0.5 ? "dd2" : "dd5"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), dd5); gl_FragColor = vec4(${p.random() > 0.5 ? "df.b" : "df.r"},fract(${p.random() > 0.5 ? "coord.x" : "coord.y"}/${p.random() > 0.5 ? "dd5" : "dd4"}),${p.random() > 0.5 ? "sin" : "cos"}(${p.random() > 0.5 ? "df.b" : "df.g"}*${p.random() > 0.5 ? "u_frame" : p.random()}),1./${p.random()}); } `; p.createCanvas(HW, HW, p.WEBGL); const gl = p.canvas.getContext('webgl') gl.disable(gl.DEPTH_TEST) p.frameRate(30); SCALE = HW / 400; wHW = 400 sGreen = (p.random()*1000)+500 tShader = p.createShader(vShader, fShader); p.pixelDensity(1) p.background(sGreen) //----------------------------------------------------------------------// printMetadata(); } p.redraw(); }; p.draw = () => { //-------------------- ARTIST STARTS DRAWING HERE ----------------------// //if (frameCount == 75) noLoop(); p.push(); p.translate(-HW / 2, -HW / 2); p.scale(SCALE); p.pop(); tShader.setUniform('u_resolution', [HW, HW]); tShader.setUniform('u_frame', (sGreen+p.frameCount)*0.005); p.shader(tShader); p.square(0, 0, wHW); p.resetShadep.random(); //----------------------------------------------------------------------// } // ------------------------- CODE ENDS HERE --------------------------- //
// ----------------------- CODE STARTS HERE -------------------------- // let TX; let TXN; let EID; let DIM; let WIDTH; let HEIGHT; let decPairs; let perlinSeed; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } console.log("decPairs :", decPairs); } printMetadata = () => { metadataObj.traitName1 = "Change traitName and put your value here"; metadataObj.traitName2 = "Change traitName and put your value here"; metadataObj.traitName3 = "Change traitName and put your value here"; metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } //----------------- ARTIST STARTS CUSTOM FUNCTIONS HERE -----------------// let HW = Math.min(window.innerWidth, window.innerHeight); let tShader; let SCALE; let wHW; let sGreen; let vShader, fShader; //------------------ ARTIST ENDS CUSTOM FUNCTIONS HERE ------------------// p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); getHashData(1); // SEEDING p.randomSeed(+props.transactionHash.substr(0, 10)); perlinSeed = p.random(0, 255); p.noiseSeed(perlinSeed); console.log("randomSeed: ", +props.transactionHash.substr(0, 10)); console.log("noiseSeed: ", perlinSeed); console.log("transaction: ", TX); //--------------------- ARTIST STARTS SETUP HERE -----------------------// vShader = ` attribute vec3 aPosition; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform float u_frame2; void main() { vTexCoord = aTexCoord; vec4 positionVec4 = vec4(aPosition, 1.0); positionVec4.xy = positionVec4.xy * ${p.random() * 10 + 2} -1.; gl_Position = positionVec4; } `; fShader = ` precision mediump float; varying vec2 vTexCoord; uniform float u_frame; uniform vec2 u_resolution; void main() { vec2 coord = gl_FragCoord.xy/u_resolution.xy; coord ${p.random() > 0.5 ? "*" : "/"}= coord / ${p.random() * 10.0} -1.*${p.random() > 0.5 ? "sin" : "cos"}(u_frame*0.1); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)*10.1, -1. + ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); float dd = distance(coord, vec2(cos(coord.y), ${p.random() > 0.5 ? "sin" : "cos"}(coord.x))); float dd2 = distance(coord, vec2(cos(dd), ${p.random() > 0.5 ? "sin" : "cos"}(dd))); float dd3 = distance(coord, vec2(u_frame, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "sin" : "cos"}(u_frame)) / dd3; float dd4 = distance(coord, vec2(1, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame))); float dd5 = smoothstep(u_frame, fract(dd3*dd2), ${p.random() > 0.5 ? "sin" : "cos"}(dd4)); dd ${p.random() > 0.5 ? "*" : "+"}= dd2 * dd3 / dd4*dd5; float ddf = mix(${p.random()}, ${p.random()}, dd5); vec3 df = vec3(${p.random() > 0.5 ? "sin" : "cos"}(fract(dd5)), ${p.random() > 0.5 ? "sin" : "cos"}(fract(${p.random() > 0.5 ? "dd2" : "dd3"})), ${p.random() > 0.5 ? "sin" : "cos"}(fract(dd3*0.1))); ddf ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), df.x); coord ${p.random() > 0.5 ? "*" : "+"}= vec2(${p.random() > 0.5 ? "df.y" : "df.z"}, df.z); coord ${p.random() > 0.5 ? "*" : "+"}= smoothstep(u_frame, df.x, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); df ${p.random() > 0.5 ? "*" : "+"}= mix(sin(u_frame)*${p.random()}, ${p.random()}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); dd5 ${p.random() > 0.5 ? "*" : "+"}= dot(${p.random() > 0.5 ? "dd" : "dd2"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame)); coord ${p.random() > 0.5 ? "*" : "+"}= mix(${p.random() > 0.5 ? "dd2" : "dd5"}, ${p.random() > 0.5 ? "sin" : "cos"}(u_frame), dd5); gl_FragColor = vec4(${p.random() > 0.5 ? "df.b" : "df.r"},fract(${p.random() > 0.5 ? "coord.x" : "coord.y"}/${p.random() > 0.5 ? "dd5" : "dd4"}),${p.random() > 0.5 ? "sin" : "cos"}(${p.random() > 0.5 ? "df.b" : "df.g"}*${p.random() > 0.5 ? "u_frame" : p.random()}),1./${p.random()}); } `; p.createCanvas(HW, HW, p.WEBGL); const gl = p.canvas.getContext('webgl') gl.disable(gl.DEPTH_TEST) p.frameRate(30); SCALE = HW / 400; wHW = 400 sGreen = (p.random()*1000)+500 tShader = p.createShader(vShader, fShader); p.pixelDensity(1) p.background(sGreen) //----------------------------------------------------------------------// printMetadata(); } p.redraw(); }; p.draw = () => { //-------------------- ARTIST STARTS DRAWING HERE ----------------------// //if (frameCount == 75) noLoop(); p.push(); p.translate(-HW / 2, -HW / 2); p.scale(SCALE); p.pop(); tShader.setUniform('u_resolution', [HW, HW]); tShader.setUniform('u_frame', (sGreen+p.frameCount)*0.005); p.shader(tShader); p.square(0, 0, wHW); p.resetShadep.random(); //----------------------------------------------------------------------// } // ------------------------- CODE ENDS HERE --------------------------- //
unknown sendersent to0x499f4943…3001·#14,119,488·0xf0c36560…659b66
``` "the dream spins outward / slipping from our clenched hands"; let canvas, // p5js canvas. state; // Keep all shared state in one place. const body = document.body, halfRoot3 = p.sqrt(.75), //-[ Geometry functions ]---------------------------------------------------// // v - point or vector - [x, y] // l - line - [a, b, c] where ax + by = c // Returns the line passing through points v1 and v2. line = (v1, v2) => { let a = v2[1] - v1[1], b = v1[0] - v2[0]; return [a, b, a * v1[0] + b * v1[1]]; }, // Adds v2 to v1 and returns the result. // Modifies v1 in place for performance reasons. add = (v1, v2) => (v1[0] += v2[0], v1[1] += v2[1], v1), // Returns the difference between v1 and v2. subtract = (v1, v2) => [v1[0] - v2[0], v1[1] - v2[1]], // Creates a unit vector with angle a. unit = a => [p.cos(a), p.sin(a)], // Scales v by s. // Modifies the vector in place for performance reasons. scale = (v, s) => (v[0] *= s, v[1] *= s, v), // Returns the length of v. length = v => p.sqrt(v[0] * v[0] + v[1] * v[1]), // Returns the unit vector from v1 toward v2. direction = (v1, v2) => { let v3 = subtract(v2, v1); return scale(v3, 1 / length(v3)); }, // Returns the squared distance between v1 and v2. distSquared = (v1, v2) => { let [x, y] = subtract(v1, v2); return x * x + y * y; }, // Returns the line perpendicular to l that passes through point v. perpendicular = (v, l) => [-l[1], l[0], -l[1] * v[0] + l[0] * v[1]], // Returns the midpoint between v1 and v2. midpoint = (v1, v2) => [(v1[0] + v2[0]) / 2, (v1[1] + v2[1]) / 2], // Returns the line that bisects the segment between v1 and v2. bisect = (v1, v2) => perpendicular(midpoint(v1, v2), line(v1, v2)), // Returns the point where l1 and l2 intersect. intersect = (l1, l2) => { let det = l1[0] * l2[1] - l2[0] * l1[1]; // Ignore parallel case where determinate == 0. return [ (l2[1] * l1[2] - l1[1] * l2[2]) / det, (l1[0] * l2[2] - l2[0] * l1[2]) / det ]; }, // Returns the circumscribed circle for up to 3 given points. // The return value is in the format [x, y, r^2]. circumscribe = vs => { if (!vs.length) return [0, 0, 0]; if (vs.length == 1) return [vs[0][0], vs[0][1], 0]; if (vs.length == 2) { return [...midpoint(...vs), distSquared(vs[0], vs[1]) / 4]; } let center = intersect(bisect(vs[0], vs[1]), bisect(vs[1], vs[2])); return [...center, distSquared(center, vs[0])]; }, // Returns the minimal enclosing circle for the given points. // The return value is in the format [x, y, r^2]. enclose = (vs, pBounds) => { if (pBounds.length == 3 || !vs.length) return circumscribe(pBounds); let tailCircle = enclose(vs.slice(1), pBounds), v = vs[0], inside = distSquared(tailCircle, v) < tailCircle[2]; return inside || pBounds.some(vB => vB[0] == v[0] && vB[1] == v[1]) ? tailCircle : enclose(vs.slice(1), [v, ...pBounds]); }, // Returns a point on a Bezier curve in one dimension. bezier = (v0, v1, v2, v3, t) => { let t2 = t * t; let t3 = t2 * t; return v0 * (-t3 + 3 * t2 - 3 * t + 1) + v1 * (3 * t3 - 6 * t2 + 3 * t) + v2 * 3 * (t2 - t3) + v3 * t3; }, // Returns a point on a Bezier curve in three dimensions. bezier3d = (p0, p1, p2, p3, t) => [ bezier(p0[0], p1[0], p2[0], p3[0], t), bezier(p0[1], p1[1], p2[1], p3[1], t), bezier(p0[2], p1[2], p2[2], p3[2], t) ], //-[ Randomness functions ]-------------------------------------------------// gaussian = (sd = 1) => p.randomGaussian(0, sd), agaussian = (sd = 1) => p.abs(gaussian(sd)), randomBool = (t = .5) => p.random() < t, // Allows the provided value to be glitched by using the replace function. glitch = (name, value, replace, post) => { if (!randomBool(state.glitch)) return value; let replacement = replace(); if (replacement != value) { state.glitches[name] = true; // Record the glitch. post && post(); // Execute the post function if provided. } return replacement; }, //-[ Shape functions ]------------------------------------------------------// // Creates an array with length n. Lambda l is used to populate the values. array = (n, l) => Array.from(Array(n), (_, i) => l(i)), // Creates a rounded hexagon as a list of vertices. hexagon = (node, roundRadius = .25, roundPoints = 5) => { let [x, y, r, a] = node; // Given max radius, adjust to min radius. r *= 1 - roundRadius * (1 - halfRoot3); return array(6, i => { let vertexAngle = a + p.PI / 3 * i; return array(roundPoints, j => { let roundAngle = vertexAngle + p.PI / 3 * j / (roundPoints - 1); return [ x + r * (1 - roundRadius) * p.cos(vertexAngle + p.PI / 6) + r * roundRadius * p.cos(roundAngle), y + r * (1 - roundRadius) * p.sin(vertexAngle + p.PI / 6) + r * roundRadius * p.sin(roundAngle) ]; }) }).flat(); // Join the groups of points from each corner into one big array. }, // Creates a circle as a 30-sided polygon. circle = (node, points = 30) => array(points, i => [ node[0] + node[2] * p.cos(node[3] + p.PI / 6 + i / points * p.TWO_PI), node[1] + node[2] * p.sin(node[3] + p.PI / 6 + i / points * p.TWO_PI) ]), // Returns a copy of a node with the values slightly smeared. smear = (node, distance) => { let [x, y, r, a] = node; return [ x + gaussian(distance / 2), y + gaussian(distance / 2), r + agaussian(distance), a + gaussian(distance / r) ]; }, //-[ Tracing functions ]----------------------------------------------------// // Reset the mutable parts of the global state used for tracing. resetTraceState = _ => { state.penPosition = state.center; state.penVelocity = [0, 0]; state.wristPosition = [state.center[0], state.center[1] + state.handLength]; state.wristVelocity = [0, 0]; }, // Moves the pen one step toward the target point. moveToward = point => { // Figure out the wrist position and angle, compared to the ideals. let hand = subtract(state.penPosition, state.wristPosition), targetHand = subtract(point, state.wristPosition), diffRatio = (hand[0] * targetHand[0] + hand[1] * targetHand[1]) / (length(hand) * length(targetHand)), // Calculate the difference in angle between hand and targetHand. angleDiff = p.acos(diffRatio); // Every now and then, diffRatio likes to get too big and causes NaN values. // When this happens, fall back to clamp values. if (Number.isNaN(angleDiff)) angleDiff = (diffRatio < 0) * p.PI; // Account for wrist rotation in the direction the pen tries to move. let path = subtract(point, state.penPosition), pathAngle = p.atan2(path[1], path[0]), // Deflect movement angle to simulate rotation at wrist. moveAngle = pathAngle - Math.sign(path[0]) * angleDiff * state.penDeflection / 2; // Update the pen and wrist velocities. state.penVelocity = add( scale([...state.penVelocity], state.penSmoothing), scale(unit(moveAngle), state.penStep * (1 - state.penSmoothing)) ); state.wristVelocity = add( scale([...state.wristVelocity], state.wristSmoothing), scale( direction(state.wristPosition, [point[0], point[1] + state.handLength]), state.wristStep * (1 - state.wristSmoothing) ) ); // Update the pen and wrist positions. add(state.wristPosition, state.wristVelocity); state.penPosition = add([...state.penPosition], state.penVelocity); return state.penPosition; }, // Returns a point that is "nearly" the provided point. nearly = point => [ point[0] + gaussian(state.penStep / 2), point[1] + gaussian(state.penStep / 2) ], // Traces the given polygon and returns the result. tracePolygon = poly => { let points = [], vertexIndex = 1, vertex = nearly(poly[0]); // Move to the first point in the polygon. while (distSquared(state.penPosition, vertex) > state.thresholdSquared) { moveToward(vertex); } // Trace to every successive point. for (; vertexIndex < poly.length; vertexIndex++) { vertex = nearly(poly[vertexIndex]); let i = 0; while (distSquared(state.penPosition, vertex) > state.thresholdSquared) { points.push(moveToward(vertex)); } } // Wrap back around to the first point. vertex = nearly(poly[0]); while (distSquared(state.penPosition, vertex) > state.thresholdSquared) { points.push(moveToward(vertex)); } return points; }, //-[ Drawing helper functions ]---------------------------------------------// // Converts a polygon into a p5js shape instructions. drawPolygon = (instance, polygon) => { if (!polygon.length) return; instance.beginShape(); polygon.map(vertex => instance.vertex(...vertex.slice(0, 2))); instance.endShape(); }, // Converts Cartesian coordinates into canvas-relative polar coordinates. // Used for computing colors and other styling information. ra = v => { const [x, y] = subtract(v, state.center); return [ 4.84 * (x * x + y * y) / (state.canvasSize * state.canvasSize), p.atan2(y, x) - state.styleAngle ]; }, // Bypasses p5js to create a linear gradient fill. fillLinear = (instance, x1, y1, x2, y2, c1, c2) => { const gradient = instance.drawingContext.createLinearGradient(x1, y1, x2, y2); gradient.addColorStop(0, instance.color(c1).toString()); gradient.addColorStop(1, instance.color(c2).toString()); instance.fill("#DEADC0DE"); // Clear the cached fill value. instance.drawingContext.fillStyle = gradient; }, // Bypasses p5js to create a radial gradient fill. fillRadial = (instance, x, y, radius, inner, outter) => { const gradient = instance.drawingContext.createRadialGradient(x, y, 0, x, y, radius); gradient.addColorStop(0, instance.color(inner).toString()); gradient.addColorStop(1, instance.color(outter).toString()); instance.fill("#DEADC0DE"); // Clear the cached fill value. instance.drawingContext.fillStyle = gradient; }, //-[ Drawing function for "Nexus: Supreme" ]--------------------------------// supreme = texture => { // First draw the subtle background gradient. p.background("#C5C5C2"); texture.clear(); p.noStroke(); texture.noStroke(); p.colorMode(p.RGB); texture.colorMode(p.RGB); fillRadial( texture, ...state.center, state.canvasSize / 2, "#CACAC8", "#CECECC"); texture.circle(...state.center, state.canvasSize); // Roll style-specific random values. const uniform = randomBool(.4), // Precompute values for nodes with Gaussian distrobution. cachedGaussians = state.nodes.map(node => gaussian()), // Fetch a random value for a node. // Based on the value of `uniform` value, this may or may not be the // precomputed value from `cachedGaussians`. nodeGaussian = uniform ? i => cachedGaussians[i] : i => randomBool() ? gaussian() : cachedGaussians[i], // 1 in 4 chance of highlighting the largest node in red. popId = randomBool(.75) ? -1 : state.nodes.reduce( (a, node, i) => a[0] > node[2] ? a : [node[2], i], [0] )[1], // Precompute the node colors. sides = state.nodes.map((node, i) => { const [r, a] = ra(node), offset = 1 - r * p.sin(a); return [ (offset + .45 * nodeGaussian(i)) | 0, (offset + .45 * nodeGaussian(i)) | 0, (offset + .45 * nodeGaussian(i)) | 0, (offset + .45 * nodeGaussian(i)) | 0 ]; }), c = ["#000000", "#222222", "#F2F2F2", "#FFFFFF"], // Alpha value for background colors. // Backgrounds only have transparency when glitched. bg = glitch("Revealed", "", _ => "AA"); // Glitch the dark coloring. c[1] = glitch( "Enlightened", c[1], a => ( a = ["22"], a.splice(p.random(2) | 0, 0, (324 + p.random(35) | 0).toString(16).substr(1)), a.splice(p.random(3) | 0, 0, (290 + p.random(52) | 0).toString(16).substr(1)), "#" + a.join("") ) ); // Record style specific metadata. state.majorMetadata.Emptiness = popId < 0 ? "Dispersed" : "Concentrated"; state.majorMetadata.Polarity = uniform ? "Quiescent" : "Kinetic"; // Finally, draw the background circles. state.nodes.map((node, i) => { p.fill(c[sides[i][0] ? 2 : 0] + bg); p.circle(node[0], node[1], node[2] * 8); const texturePoly = tracePolygon(circle( smear([node[0], node[1], node[2] * 4, node[3]], state.smear * 1.5) )); texture.fill(c[sides[i][0] ? 3 : 1] + bg); drawPolygon(texture, texturePoly); if (uniform) return; texture.fill(sides[i][1] ? c[3] + "22" : c[1] + "44"); drawPolygon(texture, texturePoly); }); // Draw the foreground hexagons. state.hexagons.map((hexagon, i) => { if (popId == i) return; p.fill(c[sides[i][2] ? 0 : 2]); drawPolygon(p, hexagon); }); state.textugons.map((textugon, i) => { if (popId == i) return; texture.fill(c[sides[i][2] ? 1 : 3]); drawPolygon(texture, textugon); if (uniform) return; texture.fill(sides[i][3] ? c[1] + "88" : c[3] + "55"); drawPolygon(texture, textugon); }); // Put the cherry on top. if (popId >= 0) { p.fill("#F22222"); drawPolygon(p, state.hexagons[popId]); texture.fill("#F22"); drawPolygon(texture, state.textugons[popId]); } }, //-[ Drawing function for "Nexus: Celestial" ]------------------------------// celestial = texture => { // Set up colors. let skyColors = ["#182834", "#122632"], bgColors = [ [85, 215, 255], [85, 102, 215], [85, 215, 255], [102, 85, 215], ]; // Glitch the colors. glitch("Radiant", true, _ => { skyColors = skyColors.map(color => "#" + color.substr(5) + color.substr(1, 4)); bgColors = bgColors.map(color => [color[2], color[1] * 1.1, color[0]]); }); // Make the Bezier functions for computing each node's colors. const radialVector = scale(unit(state.styleAngle), state.canvasSize / 2), mainBez = t => bezier3d(bgColors[0], bgColors[1], [34, 17, 85], [34, 34, 34], t), textureBez = t => bezier3d(bgColors[2], bgColors[3], [34, 17, 85], [34, 34, 34], t), hexagonBez = t => bezier3d( [255, 238, 187], [238, 221, 204], [238, 238, 255], [205, 215, 245], 1.6 * t - .3 ); // Now that colors are set up, draw the background. p.clear(); p.noStroke(); p.colorMode(p.RGB); fillLinear( p, ...add(scale([...radialVector], .6), state.center), ...subtract(state.center, radialVector), "#111", skyColors[0] ); p.circle(...state.center, state.canvasSize); // The background on the texture overlay is made by adding two gradients. texture.clear(); texture.noStroke(); texture.colorMode(p.RGB); fillLinear( texture, ...add([...radialVector], state.center), ...subtract(state.center, radialVector), "#0E0E0E", skyColors[1] ); texture.circle(...state.center, state.canvasSize); texture.blendMode(p.ADD); fillRadial( texture, ...state.center, state.canvasSize / 2, "#000", "#060609"); texture.circle(...state.center, state.canvasSize); texture.blendMode(p.BLEND); // Add stars to the background based on node positions. const allStars = glitch("Galactic", false, _ => true), starThreshold = state.smear * 2, stars = state.nodes.map(node => { const [r, a] = ra(node), starCount = (allStars || r * p.cos(a)) * p.random(30), nodeStars = []; for (let i = 0; i++ < starCount;) { const offset = node[2] * (5 + 3.5 * gaussian()), angle = a + p.PI * gaussian(), diameter = p.random(p.random(node[2])) / 4; if (diameter > starThreshold || randomBool(.7)) { nodeStars.push([ node[0] + offset * p.sin(angle), node[1] + offset * p.cos(angle), p.max(diameter, starThreshold) ]); } } return nodeStars; }).flat(); p.fill("#F2F2F2"); texture.fill("#FFF"); stars.map(star => { p.circle(...star); texture.circle(...smear(star, state.smear / 2).slice(0, 3)); }); const hexagonColors = [], showHexagons = glitch("Revealed", true, _ => false); // Draw the background circles and precompute node colors. state.nodes.map(node => { const [r, a] = ra(node), distance = .5 + r / 2 * p.cos(a), alpha = 25 - 18 * distance + 15 * (!showHexagons) - 5 * allStars; hexagonColors.push(hexagonBez(distance)); if (alpha < 0) return; const textureNode = smear([node[0], node[1], node[2] * 4, node[3]], state.smear * 2), hexColor = mainBez(distance), texColor = textureBez(distance); fillRadial( p, ...node.slice(0, 2), node[2] * 4, p.color(...hexColor, alpha), p.color(...hexColor, alpha * .6) ); p.circle(node[0], node[1], node[2] * 8); fillRadial( texture, ...textureNode.slice(0, 2), textureNode[2], p.color(...texColor, alpha), p.color(...texColor, alpha * .6) ); drawPolygon(texture, tracePolygon(circle(textureNode))); }); // Finally, draw foreground hexagons. const alpha = 60 + 5640 / state.nodes.length; state.hexagons.map((hexagon, i) => { if (randomBool(.1) == showHexagons) return; const shine = alpha + 75 * !showHexagons * p.random(); p.fill(...hexagonColors[i], shine); drawPolygon(p, hexagon); texture.fill(...hexagonColors[i], shine + 3); drawPolygon(texture, state.textugons[i]); }); }, //-[ Drawing function for "Nexus: Energy" ]---------------------------------// // Energy stones and their associated color values. stones = [ ["Ruby", 0, 6, 4], ["Garnet", 15, 8, 2.5], ["Topaz", 27, 6, 5], ["Diamond", 42, .5, 5], ["Peridot", 72, 5, 4], ["Emerald", 105, 6, 3], ["Turquoise", 165, 6, 6], ["Aquamarine", 189, 6, 3], ["Sapphire", 234, 6, 4], ["Amethyst", 267, 6, 4], ["Pearl", 294, .75, 6.5], ["Tourmaline", 315, 5, 5] ], energy = texture => { // Start with a black background. p.background(0); p.noStroke(); p.colorMode(p.HSL); texture.background(0); texture.noStroke(); texture.colorMode(p.HSL); // Pick a stone and compute the base alpha value. let hue, sat, brightness, color = p.random(stones.length) | 0, alpha = .04 + p.random(.04) + 4 / state.nodes.length; state.majorMetadata.Stone = stones[color][0]; // Glitch the alpha value. alpha = glitch("Severe", alpha, _ => alpha > .2 ? alpha : .4 + p.random(.3)); const // Sets color values based on the selected stone. setValues = _ => { hue = stones[color][1] + gaussian(2); sat = stones[color][2] + .3; brightness = stones[color][3]; }, // Roll style-specific random values. purity = 7 + gaussian(2), multiply = glitch("Sinister", false, _ => true) ? state.nodes.map(node => randomBool(.7 + .25 * ra(node)[0])) : state.nodes.map(node => randomBool(.25 + .25 * ra(node)[0])), hueShifts = state.nodes.map(node => purity * gaussian()); setValues(); // Draw the backgound gradient. [p, texture].map(instance => { fillRadial( instance, ...state.center, state.canvasSize / 2, instance.color(hue, sat * 15, brightness + 5), instance.color(hue, 100, 2 + (instance == texture)) ); instance.circle(...state.center, state.canvasSize); }); // Draw the background circles. state.nodes.map((node, i) => { const blend = multiply[i] ? p.MULTIPLY : p.ADD, scaled = [node[0], node[1], node[2] * 15, node[3]]; p.blendMode(blend); texture.blendMode(blend); p.fill( multiply[i] ? p.color(0, alpha * 2.5) : p.color(hue + hueShifts[i], sat * 8, brightness * 2, alpha * 2) ); texture.fill(multiply[i] ? p.color(0, alpha * 2.4) : p.color(hue + hueShifts[i], sat * 7.5, brightness * 1.9, alpha * 2)); p.circle(...scaled.slice(0, 2), scaled[2] * 2); drawPolygon( texture, tracePolygon(circle(smear(scaled, state.smear * 3)))); }); // Draw the background hexagons. state.nodes.map((node, i) => { const blend = multiply[i] ? p.MULTIPLY : p.ADD, scaled = [node[0], node[1], node[2] * 5, node[3]]; p.blendMode(blend); texture.blendMode(blend); p.fill( multiply[i] ? p.color(0, alpha * 3.5) : p.color(hue + hueShifts[i], sat * 9, brightness * 4.5, alpha * 3) ); texture.fill( multiply[i] ? p.color(0, alpha * 3.4) : p.color(hue + hueShifts[i], sat * 9, brightness * 4.75, alpha * 3.3) ); drawPolygon(p, hexagon(scaled)); drawPolygon(texture, tracePolygon(hexagon(smear(scaled, state.smear)))); }); // Recolor the background; Bypass p5js since it has no "color" compositing. p.drawingContext.globalCompositeOperation = texture.drawingContext.globalCompositeOperation = "color"; const recolor = p.color(hue, sat * 14, brightness + 5, .35); p.fill(recolor); p.circle(...state.center, state.canvasSize); texture.fill(recolor); texture.circle(...state.center, state.canvasSize); // Reset the cached blend mode. p.blendMode(p.BLEND); texture.blendMode(p.BLEND); // Now that the background is complete, glitch the foreground color. glitch( "Eccentric", color, _ => color = ((color + p.round(gaussian(3))) % stones.length + stones.length) % stones.length, _ => { setValues(); state.majorMetadata.Stone += ", " + stones[color][0]; } ); // Draw the foreground hexagons. state.hexagons.map((hexagon, i) => { p.blendMode(multiply[i] ? p.MULTIPLY : p.ADD); p.fill( multiply[i] ? p.color(hue + hueShifts[i], 100, 5, alpha * 5) : p.color(hue + hueShifts[i], sat * 10, brightness * 10 + 10, alpha * 6) ); drawPolygon(p, hexagon); }); state.textugons.map((textugon, i) => { texture.blendMode(multiply[i] ? p.MULTIPLY : p.ADD); texture.fill( multiply[i] ? p.color(hue + hueShifts[i], 100, 5, alpha * 5) : p.color(hue + hueShifts[i], sat * 9, brightness * 10 + 10, alpha * 6.5) ); drawPolygon(texture, textugon); }); // Recolor the foreground; Bypass p5js since it has no "color" compositing. // Previous mode was MULTIPLY or ADD, and next mode will be BLEND, so no // need for cache busting. p.drawingContext.globalCompositeOperation = texture.drawingContext.globalCompositeOperation = "color"; state.hexagons.map((hexagon, i) => { p.fill(hue + hueShifts[i], sat * 9, brightness * 10, alpha * 3); drawPolygon(p, hexagon); }); state.textugons.map((textugon, i) => { texture.fill(hue + hueShifts[i], sat * 7.5, brightness * 10, alpha * 2.7); drawPolygon(texture, textugon); }); // Set the blend mode back to the default any subsequent draws. p.blendMode(p.BLEND); texture.blendMode(p.BLEND); }; //-[ p5js functions ]---------------------------------------------------------// // Creates the p5js canvas and disables looping. // The rest of the setup is done when the Immutables properties are received. p.setup = _ => { canvas = p.createCanvas(1,1); canvas.style("display", "block"); p.noLoop(); }, // Responds to the properties provided by Immutables. p.myCustomRedrawAccordingToNewPropsHandler = properties => { if (!properties.transactionHash) return; // Check if existing state already matches the new properties. if ( state && state.hash == properties.transactionHash && state.edition == properties.editionId ) { if (state.square != properties.square) { state.square = properties.square; p.windowResized(); } // The state doesn't need updated, so our work here is done. return; } // Pull 32 bits from the transaction hash to seed the RNG. // Pick which bits to pull based on the edition ID to cover the off chance // that someone uses a contract to mint multiple outputs at once. const setupSeed = properties.transactionHash.substr(2 + 8 * (properties.editionId % 8), 8); p.randomSeed(+("0x" + setupSeed)); // Roll values needed for node generation. const layers = (.2 + agaussian(1.2)) | 0, loschianNumber = randomBool() ? 4 : 7, layerRatio = p.sqrt(loschianNumber), layerRotate = loschianNumber == 4 ? 0 : p.atan2(halfRoot3, 2.5), alignment = randomBool() ? 1 : randomBool() ? 0 : 4, ratio = randomBool(.75) ? .01 : randomBool() ? .1 : .3, stutter = !alignment ? .05 : .015, nodeCount = 32 + p.max(8, p.ceil(224 + gaussian(160))), nodes = [], candidates = [], // A list of candidate parents for the next generated node. isDense = randomBool(.2), // Creates a new node. newNode = parent => { let // Random chance of jumping to a new layer. This affects all the rest // of the values. layer = randomBool(.1) && layers ? p.random(layers + 1) | 0 : parent[4], size = parent[2] * 2 ** gaussian(ratio) * layerRatio ** (layer - parent[4]), distance = layer != parent[4] ? 0 : (size + parent[2]) * (1.15 + gaussian(stutter)), angle = parent[3] + (p.PI * isDense) + p.round(gaussian(1.5) % 6) * p.PI / 3 + gaussian(alignment * p.PI / 96) + layerRotate * (parent[4] - layer); let node = [ parent[0] + distance * p.cos(angle), parent[1] + distance * p.sin(angle), size, angle, layer ]; nodes.push(node); return node; }; // Generate starter nodes in every layer. for (let i = layers + 1, layerSize = 20; i--;) { let node = [0, 0, layerSize, i * layerRotate, i, 0]; nodes.push(node); for (let j = 2 + randomBool(); j--;) candidates.push(node, node); // Help smaller layers out by giving them more nodes. for (let j = layers - i; j--;) newNode(node); layerSize /= layerRatio; } // Grow randomly from current nodes to reach the target node count. while (nodes.length < nodeCount) { let pIndex = p.random(candidates.length) | 0, parent = candidates[pIndex]; candidates.splice(pIndex, 1); let node = newNode(parent); while (randomBool() || !candidates.length) candidates.push(node); } const // Compute the canvas center and size based on node locations. frame = enclose(nodes, []), maxRadius = p.max( nodes.map(node => p.sqrt(distSquared(node, frame)) + node[2] * 1.5) ), // Roll the remaining values needed to prepare for drawing. size = p.random(4) | 0, handRatio = 2 ** (1.5 + size / 2), handLength = maxRadius / handRatio, style = p.random(), styleId = (style < .875) + (style < .7125); // Put everything where it can be referenced when drawing and redrawing. state = { square: properties.square, edition: +properties.editionId, hash: properties.transactionHash, center: [frame[0], frame[1]], canvasSize: maxRadius * 2.2, styleAngle: p.random(p.TWO_PI), smear: maxRadius / (handRatio * 256), leftHanded: randomBool(.1), handRatio: handRatio, handLength: handLength, penStep: handLength / 64, wristStep: handLength / 384, penSmoothing: .6, wristSmoothing: .9, penDeflection: .25, // How close the pen has to get to a vertex before having "arrived". thresholdSquared: handLength * handLength / 2048, nodes: nodes, hexagons: nodes.map(node => hexagon(node)), glitch: p.random() * p.random() * .4, glitches: {}, styleDraw: [supreme, celestial, energy][styleId], }; // Add the metadata to state that is known at this point. // It is split into major and minor metadata for ordering purposes. state.majorMetadata = { Nexus: ["Supreme", "Celestial", "Energy"][styleId], Arcana: "" // Reserving the key index. Value is filled during drawing. }; state.minorMetadata = { Adherence: ["Extreme", "Varied", "Uniform"][(ratio < .1) + (ratio < .2)], Growth: ["Rigid", "Loose", "", "", "Chaotic"][alignment], Reach: ["Local", "Regional", "Continental", "Global"][size], Focus: isDense ? "Inward" : "Outward", Centuries: "" + (1 + (nodeCount - 1) / 100 | 0), Degrees: "" + (layers + 1), }; // Only include the Loschian Number in metadata if there are actually layers. if (layers) state.minorMetadata["L\u00F6schian Number"] = "" + loschianNumber; // Add final metadata here that should be last in the list of traits. state.minorMetadata.Handed = state.leftHanded ? "Left" : "Right"; state.minorMetadata.transactionHash = properties.transactionHash; // Consider glitching the trace variables now that the state is set up. glitch("Revelous", true, _ => { state.smear *= 3; state.penSmoothing = .8; state.penDeflection = .875; // Since texture overlay hexagons are based on original nodes, this creates // a nice discrepency between the nodes and their overlay. state.nodes = nodes.map(node => smear(node, state.smear)); }); // Setup the trace state and trace the hexagons on the texture overlay. resetTraceState(); state.textugons = nodes.map(node => tracePolygon(hexagon(smear(node, state.smear)))); // Force a redraw and resize the window if needed. p.windowResized(); }; p.windowResized = _ => { if (!state) return; const minDim = p.min(p.windowWidth, p.windowHeight) * .8 / state.square | 0; p.resizeCanvas(minDim, minDim); }; p.keyTyped = _ => { if (!state || state.square != 1) return; if (p.key == 'S' && !state.save) { state.pixelDensity = p.pixelDensity(); state.save = true; canvas.style("display", "none"); p.pixelDensity(1); p.resizeCanvas(5000,5000); } else if (p.key == 'Z') { state.zoom = !state.zoom; p.redraw(); } } p.draw = _ => { if (!state) return; // Pull 32 bits from the transaction hash to reseed the RNG. // Reseed at the beginning of every draw to keep output consistent. // See the comment on setupSeed to explain the use of the edition ID. const drawSeed = state.hash.substr(2 + 8 * ((state.edition + 1) % 8), 8); p.randomSeed(+("0x" + drawSeed)); // Set up the transformation matrix for centering the nodes. const zoom = state.zoom ? p.sqrt(2) : 1, texture = p.createGraphics(p.width, p.width), scale = p.width / state.canvasSize * zoom, matrix = [ scale, 0, 0, scale, p.width / 2 - state.center[0] * scale, p.width / 2 - state.center[1] * scale ]; p.applyMatrix(...matrix); texture.applyMatrix(...matrix); // Reset the tracing state before drawing to keep output consistent. resetTraceState(); // Call the style-specific draw code. state.styleDraw(texture); // Compile glitches. state.majorMetadata.Arcana = Object.keys(state.glitches).sort().join(", ") || "Unknown"; const fullMetadata = { ...state.majorMetadata, ...state.minorMetadata, } // Report the metadata and log each trait to the console. if (!state.metadataReported) { console.log("metadata: ", fullMetadata); Object.keys(fullMetadata) .map(key => console.log(key, ":", fullMetadata[key])); // Mark as completed so that metadata output can be skipped for redraws. state.metadataReported = true; } // Create the "thread" texture mask. const threadSize = p.width / (state.handRatio * 54), threadLimit = p.width / threadSize + 1, mask = p.createGraphics(p.width, p.width); mask.fill(0); mask.noStroke(); // When zoom is enabled, zoom in just enough to have a full square image. if (state.zoom) { const offset = p.width / 2 * (1 - zoom); mask.applyMatrix(zoom, 0, 0, zoom, offset, offset); } // Draw a grid of threads over the whole mask. for (let x = 0; x < threadLimit; x++) { for (let y = 0; y < threadLimit; y++) { if (x % 2 == y % 2) continue; const w = threadSize * (1 + gaussian(.16)), h = threadSize * (1 + gaussian(.16)); if (w < 0 || h < 0) continue; mask.ellipse(threadSize * x, threadSize * y, w, h); } } // Apply texture mask. const textureImage = texture.get(); textureImage.mask(mask); // Apply border masks. const mainImage = p.get(); if (state.zoom) { // Square mask. const inset = threadSize * p.sqrt(2) / 8; mask.clear(); mask.resetMatrix(); mask.rect(inset, inset, mask.width - inset * 2); mainImage.mask(mask); } else { // Circle mask. mask.clear(); mask.circle(mask.width / 2, mask.width / 2, mask.width * .99); textureImage.mask(mask); mask.clear(); mask.circle(mask.width / 2, mask.width / 2, mask.width * .99 - threadSize / 4); mainImage.mask(mask); } // Copy the masked images to the main canvas. p.clear(); p.resetMatrix(); p.image(mainImage, 0, 0); p.image(textureImage, 0, 0); // Clean up the extra canvases. texture.remove(); mask.remove(); // If a save was initiated, write out the image and reset the canvas. if (state.save) { p.save("Syncret #" + state.edition + ".png"); p.pixelDensity(state.pixelDensity); p.windowResized(); canvas.style("display", "block"); state.save = false; } } ```
Syncret``` "the dream spins outward / slipping from our clenched hands"; let canvas, // p5js canvas. state; // Keep all shared state in one place. const body = document.body, halfRoot3 = p.sqrt(.75), //-[ Geometry functions ]---------------------------------------------------// // v - point or vector - [x, y] // l - line - [a, b, c] where ax + by = c // Returns the line passing through points v1 and v2. line = (v1, v2) => { let a = v2[1] - v1[1], b = v1[0] - v2[0]; return [a, b, a * v1[0] + b * v1[1]]; }, // Adds v2 to v1 and returns the result. // Modifies v1 in place for performance reasons. add = (v1, v2) => (v1[0] += v2[0], v1[1] += v2[1], v1), // Returns the difference between v1 and v2. subtract = (v1, v2) => [v1[0] - v2[0], v1[1] - v2[1]], // Creates a unit vector with angle a. unit = a => [p.cos(a), p.sin(a)], // Scales v by s. // Modifies the vector in place for performance reasons. scale = (v, s) => (v[0] *= s, v[1] *= s, v), // Returns the length of v. length = v => p.sqrt(v[0] * v[0] + v[1] * v[1]), // Returns the unit vector from v1 toward v2. direction = (v1, v2) => { let v3 = subtract(v2, v1); return scale(v3, 1 / length(v3)); }, // Returns the squared distance between v1 and v2. distSquared = (v1, v2) => { let [x, y] = subtract(v1, v2); return x * x + y * y; }, // Returns the line perpendicular to l that passes through point v. perpendicular = (v, l) => [-l[1], l[0], -l[1] * v[0] + l[0] * v[1]], // Returns the midpoint between v1 and v2. midpoint = (v1, v2) => [(v1[0] + v2[0]) / 2, (v1[1] + v2[1]) / 2], // Returns the line that bisects the segment between v1 and v2. bisect = (v1, v2) => perpendicular(midpoint(v1, v2), line(v1, v2)), // Returns the point where l1 and l2 intersect. intersect = (l1, l2) => { let det = l1[0] * l2[1] - l2[0] * l1[1]; // Ignore parallel case where determinate == 0. return [ (l2[1] * l1[2] - l1[1] * l2[2]) / det, (l1[0] * l2[2] - l2[0] * l1[2]) / det ]; }, // Returns the circumscribed circle for up to 3 given points. // The return value is in the format [x, y, r^2]. circumscribe = vs => { if (!vs.length) return [0, 0, 0]; if (vs.length == 1) return [vs[0][0], vs[0][1], 0]; if (vs.length == 2) { return [...midpoint(...vs), distSquared(vs[0], vs[1]) / 4]; } let center = intersect(bisect(vs[0], vs[1]), bisect(vs[1], vs[2])); return [...center, distSquared(center, vs[0])]; }, // Returns the minimal enclosing circle for the given points. // The return value is in the format [x, y, r^2]. enclose = (vs, pBounds) => { if (pBounds.length == 3 || !vs.length) return circumscribe(pBounds); let tailCircle = enclose(vs.slice(1), pBounds), v = vs[0], inside = distSquared(tailCircle, v) < tailCircle[2]; return inside || pBounds.some(vB => vB[0] == v[0] && vB[1] == v[1]) ? tailCircle : enclose(vs.slice(1), [v, ...pBounds]); }, // Returns a point on a Bezier curve in one dimension. bezier = (v0, v1, v2, v3, t) => { let t2 = t * t; let t3 = t2 * t; return v0 * (-t3 + 3 * t2 - 3 * t + 1) + v1 * (3 * t3 - 6 * t2 + 3 * t) + v2 * 3 * (t2 - t3) + v3 * t3; }, // Returns a point on a Bezier curve in three dimensions. bezier3d = (p0, p1, p2, p3, t) => [ bezier(p0[0], p1[0], p2[0], p3[0], t), bezier(p0[1], p1[1], p2[1], p3[1], t), bezier(p0[2], p1[2], p2[2], p3[2], t) ], //-[ Randomness functions ]-------------------------------------------------// gaussian = (sd = 1) => p.randomGaussian(0, sd), agaussian = (sd = 1) => p.abs(gaussian(sd)), randomBool = (t = .5) => p.random() < t, // Allows the provided value to be glitched by using the replace function. glitch = (name, value, replace, post) => { if (!randomBool(state.glitch)) return value; let replacement = replace(); if (replacement != value) { state.glitches[name] = true; // Record the glitch. post && post(); // Execute the post function if provided. } return replacement; }, //-[ Shape functions ]------------------------------------------------------// // Creates an array with length n. Lambda l is used to populate the values. array = (n, l) => Array.from(Array(n), (_, i) => l(i)), // Creates a rounded hexagon as a list of vertices. hexagon = (node, roundRadius = .25, roundPoints = 5) => { let [x, y, r, a] = node; // Given max radius, adjust to min radius. r *= 1 - roundRadius * (1 - halfRoot3); return array(6, i => { let vertexAngle = a + p.PI / 3 * i; return array(roundPoints, j => { let roundAngle = vertexAngle + p.PI / 3 * j / (roundPoints - 1); return [ x + r * (1 - roundRadius) * p.cos(vertexAngle + p.PI / 6) + r * roundRadius * p.cos(roundAngle), y + r * (1 - roundRadius) * p.sin(vertexAngle + p.PI / 6) + r * roundRadius * p.sin(roundAngle) ]; }) }).flat(); // Join the groups of points from each corner into one big array. }, // Creates a circle as a 30-sided polygon. circle = (node, points = 30) => array(points, i => [ node[0] + node[2] * p.cos(node[3] + p.PI / 6 + i / points * p.TWO_PI), node[1] + node[2] * p.sin(node[3] + p.PI / 6 + i / points * p.TWO_PI) ]), // Returns a copy of a node with the values slightly smeared. smear = (node, distance) => { let [x, y, r, a] = node; return [ x + gaussian(distance / 2), y + gaussian(distance / 2), r + agaussian(distance), a + gaussian(distance / r) ]; }, //-[ Tracing functions ]----------------------------------------------------// // Reset the mutable parts of the global state used for tracing. resetTraceState = _ => { state.penPosition = state.center; state.penVelocity = [0, 0]; state.wristPosition = [state.center[0], state.center[1] + state.handLength]; state.wristVelocity = [0, 0]; }, // Moves the pen one step toward the target point. moveToward = point => { // Figure out the wrist position and angle, compared to the ideals. let hand = subtract(state.penPosition, state.wristPosition), targetHand = subtract(point, state.wristPosition), diffRatio = (hand[0] * targetHand[0] + hand[1] * targetHand[1]) / (length(hand) * length(targetHand)), // Calculate the difference in angle between hand and targetHand. angleDiff = p.acos(diffRatio); // Every now and then, diffRatio likes to get too big and causes NaN values. // When this happens, fall back to clamp values. if (Number.isNaN(angleDiff)) angleDiff = (diffRatio < 0) * p.PI; // Account for wrist rotation in the direction the pen tries to move. let path = subtract(point, state.penPosition), pathAngle = p.atan2(path[1], path[0]), // Deflect movement angle to simulate rotation at wrist. moveAngle = pathAngle - Math.sign(path[0]) * angleDiff * state.penDeflection / 2; // Update the pen and wrist velocities. state.penVelocity = add( scale([...state.penVelocity], state.penSmoothing), scale(unit(moveAngle), state.penStep * (1 - state.penSmoothing)) ); state.wristVelocity = add( scale([...state.wristVelocity], state.wristSmoothing), scale( direction(state.wristPosition, [point[0], point[1] + state.handLength]), state.wristStep * (1 - state.wristSmoothing) ) ); // Update the pen and wrist positions. add(state.wristPosition, state.wristVelocity); state.penPosition = add([...state.penPosition], state.penVelocity); return state.penPosition; }, // Returns a point that is "nearly" the provided point. nearly = point => [ point[0] + gaussian(state.penStep / 2), point[1] + gaussian(state.penStep / 2) ], // Traces the given polygon and returns the result. tracePolygon = poly => { let points = [], vertexIndex = 1, vertex = nearly(poly[0]); // Move to the first point in the polygon. while (distSquared(state.penPosition, vertex) > state.thresholdSquared) { moveToward(vertex); } // Trace to every successive point. for (; vertexIndex < poly.length; vertexIndex++) { vertex = nearly(poly[vertexIndex]); let i = 0; while (distSquared(state.penPosition, vertex) > state.thresholdSquared) { points.push(moveToward(vertex)); } } // Wrap back around to the first point. vertex = nearly(poly[0]); while (distSquared(state.penPosition, vertex) > state.thresholdSquared) { points.push(moveToward(vertex)); } return points; }, //-[ Drawing helper functions ]---------------------------------------------// // Converts a polygon into a p5js shape instructions. drawPolygon = (instance, polygon) => { if (!polygon.length) return; instance.beginShape(); polygon.map(vertex => instance.vertex(...vertex.slice(0, 2))); instance.endShape(); }, // Converts Cartesian coordinates into canvas-relative polar coordinates. // Used for computing colors and other styling information. ra = v => { const [x, y] = subtract(v, state.center); return [ 4.84 * (x * x + y * y) / (state.canvasSize * state.canvasSize), p.atan2(y, x) - state.styleAngle ]; }, // Bypasses p5js to create a linear gradient fill. fillLinear = (instance, x1, y1, x2, y2, c1, c2) => { const gradient = instance.drawingContext.createLinearGradient(x1, y1, x2, y2); gradient.addColorStop(0, instance.color(c1).toString()); gradient.addColorStop(1, instance.color(c2).toString()); instance.fill("#DEADC0DE"); // Clear the cached fill value. instance.drawingContext.fillStyle = gradient; }, // Bypasses p5js to create a radial gradient fill. fillRadial = (instance, x, y, radius, inner, outter) => { const gradient = instance.drawingContext.createRadialGradient(x, y, 0, x, y, radius); gradient.addColorStop(0, instance.color(inner).toString()); gradient.addColorStop(1, instance.color(outter).toString()); instance.fill("#DEADC0DE"); // Clear the cached fill value. instance.drawingContext.fillStyle = gradient; }, //-[ Drawing function for "Nexus: Supreme" ]--------------------------------// supreme = texture => { // First draw the subtle background gradient. p.background("#C5C5C2"); texture.clear(); p.noStroke(); texture.noStroke(); p.colorMode(p.RGB); texture.colorMode(p.RGB); fillRadial( texture, ...state.center, state.canvasSize / 2, "#CACAC8", "#CECECC"); texture.circle(...state.center, state.canvasSize); // Roll style-specific random values. const uniform = randomBool(.4), // Precompute values for nodes with Gaussian distrobution. cachedGaussians = state.nodes.map(node => gaussian()), // Fetch a random value for a node. // Based on the value of `uniform` value, this may or may not be the // precomputed value from `cachedGaussians`. nodeGaussian = uniform ? i => cachedGaussians[i] : i => randomBool() ? gaussian() : cachedGaussians[i], // 1 in 4 chance of highlighting the largest node in red. popId = randomBool(.75) ? -1 : state.nodes.reduce( (a, node, i) => a[0] > node[2] ? a : [node[2], i], [0] )[1], // Precompute the node colors. sides = state.nodes.map((node, i) => { const [r, a] = ra(node), offset = 1 - r * p.sin(a); return [ (offset + .45 * nodeGaussian(i)) | 0, (offset + .45 * nodeGaussian(i)) | 0, (offset + .45 * nodeGaussian(i)) | 0, (offset + .45 * nodeGaussian(i)) | 0 ]; }), c = ["#000000", "#222222", "#F2F2F2", "#FFFFFF"], // Alpha value for background colors. // Backgrounds only have transparency when glitched. bg = glitch("Revealed", "", _ => "AA"); // Glitch the dark coloring. c[1] = glitch( "Enlightened", c[1], a => ( a = ["22"], a.splice(p.random(2) | 0, 0, (324 + p.random(35) | 0).toString(16).substr(1)), a.splice(p.random(3) | 0, 0, (290 + p.random(52) | 0).toString(16).substr(1)), "#" + a.join("") ) ); // Record style specific metadata. state.majorMetadata.Emptiness = popId < 0 ? "Dispersed" : "Concentrated"; state.majorMetadata.Polarity = uniform ? "Quiescent" : "Kinetic"; // Finally, draw the background circles. state.nodes.map((node, i) => { p.fill(c[sides[i][0] ? 2 : 0] + bg); p.circle(node[0], node[1], node[2] * 8); const texturePoly = tracePolygon(circle( smear([node[0], node[1], node[2] * 4, node[3]], state.smear * 1.5) )); texture.fill(c[sides[i][0] ? 3 : 1] + bg); drawPolygon(texture, texturePoly); if (uniform) return; texture.fill(sides[i][1] ? c[3] + "22" : c[1] + "44"); drawPolygon(texture, texturePoly); }); // Draw the foreground hexagons. state.hexagons.map((hexagon, i) => { if (popId == i) return; p.fill(c[sides[i][2] ? 0 : 2]); drawPolygon(p, hexagon); }); state.textugons.map((textugon, i) => { if (popId == i) return; texture.fill(c[sides[i][2] ? 1 : 3]); drawPolygon(texture, textugon); if (uniform) return; texture.fill(sides[i][3] ? c[1] + "88" : c[3] + "55"); drawPolygon(texture, textugon); }); // Put the cherry on top. if (popId >= 0) { p.fill("#F22222"); drawPolygon(p, state.hexagons[popId]); texture.fill("#F22"); drawPolygon(texture, state.textugons[popId]); } }, //-[ Drawing function for "Nexus: Celestial" ]------------------------------// celestial = texture => { // Set up colors. let skyColors = ["#182834", "#122632"], bgColors = [ [85, 215, 255], [85, 102, 215], [85, 215, 255], [102, 85, 215], ]; // Glitch the colors. glitch("Radiant", true, _ => { skyColors = skyColors.map(color => "#" + color.substr(5) + color.substr(1, 4)); bgColors = bgColors.map(color => [color[2], color[1] * 1.1, color[0]]); }); // Make the Bezier functions for computing each node's colors. const radialVector = scale(unit(state.styleAngle), state.canvasSize / 2), mainBez = t => bezier3d(bgColors[0], bgColors[1], [34, 17, 85], [34, 34, 34], t), textureBez = t => bezier3d(bgColors[2], bgColors[3], [34, 17, 85], [34, 34, 34], t), hexagonBez = t => bezier3d( [255, 238, 187], [238, 221, 204], [238, 238, 255], [205, 215, 245], 1.6 * t - .3 ); // Now that colors are set up, draw the background. p.clear(); p.noStroke(); p.colorMode(p.RGB); fillLinear( p, ...add(scale([...radialVector], .6), state.center), ...subtract(state.center, radialVector), "#111", skyColors[0] ); p.circle(...state.center, state.canvasSize); // The background on the texture overlay is made by adding two gradients. texture.clear(); texture.noStroke(); texture.colorMode(p.RGB); fillLinear( texture, ...add([...radialVector], state.center), ...subtract(state.center, radialVector), "#0E0E0E", skyColors[1] ); texture.circle(...state.center, state.canvasSize); texture.blendMode(p.ADD); fillRadial( texture, ...state.center, state.canvasSize / 2, "#000", "#060609"); texture.circle(...state.center, state.canvasSize); texture.blendMode(p.BLEND); // Add stars to the background based on node positions. const allStars = glitch("Galactic", false, _ => true), starThreshold = state.smear * 2, stars = state.nodes.map(node => { const [r, a] = ra(node), starCount = (allStars || r * p.cos(a)) * p.random(30), nodeStars = []; for (let i = 0; i++ < starCount;) { const offset = node[2] * (5 + 3.5 * gaussian()), angle = a + p.PI * gaussian(), diameter = p.random(p.random(node[2])) / 4; if (diameter > starThreshold || randomBool(.7)) { nodeStars.push([ node[0] + offset * p.sin(angle), node[1] + offset * p.cos(angle), p.max(diameter, starThreshold) ]); } } return nodeStars; }).flat(); p.fill("#F2F2F2"); texture.fill("#FFF"); stars.map(star => { p.circle(...star); texture.circle(...smear(star, state.smear / 2).slice(0, 3)); }); const hexagonColors = [], showHexagons = glitch("Revealed", true, _ => false); // Draw the background circles and precompute node colors. state.nodes.map(node => { const [r, a] = ra(node), distance = .5 + r / 2 * p.cos(a), alpha = 25 - 18 * distance + 15 * (!showHexagons) - 5 * allStars; hexagonColors.push(hexagonBez(distance)); if (alpha < 0) return; const textureNode = smear([node[0], node[1], node[2] * 4, node[3]], state.smear * 2), hexColor = mainBez(distance), texColor = textureBez(distance); fillRadial( p, ...node.slice(0, 2), node[2] * 4, p.color(...hexColor, alpha), p.color(...hexColor, alpha * .6) ); p.circle(node[0], node[1], node[2] * 8); fillRadial( texture, ...textureNode.slice(0, 2), textureNode[2], p.color(...texColor, alpha), p.color(...texColor, alpha * .6) ); drawPolygon(texture, tracePolygon(circle(textureNode))); }); // Finally, draw foreground hexagons. const alpha = 60 + 5640 / state.nodes.length; state.hexagons.map((hexagon, i) => { if (randomBool(.1) == showHexagons) return; const shine = alpha + 75 * !showHexagons * p.random(); p.fill(...hexagonColors[i], shine); drawPolygon(p, hexagon); texture.fill(...hexagonColors[i], shine + 3); drawPolygon(texture, state.textugons[i]); }); }, //-[ Drawing function for "Nexus: Energy" ]---------------------------------// // Energy stones and their associated color values. stones = [ ["Ruby", 0, 6, 4], ["Garnet", 15, 8, 2.5], ["Topaz", 27, 6, 5], ["Diamond", 42, .5, 5], ["Peridot", 72, 5, 4], ["Emerald", 105, 6, 3], ["Turquoise", 165, 6, 6], ["Aquamarine", 189, 6, 3], ["Sapphire", 234, 6, 4], ["Amethyst", 267, 6, 4], ["Pearl", 294, .75, 6.5], ["Tourmaline", 315, 5, 5] ], energy = texture => { // Start with a black background. p.background(0); p.noStroke(); p.colorMode(p.HSL); texture.background(0); texture.noStroke(); texture.colorMode(p.HSL); // Pick a stone and compute the base alpha value. let hue, sat, brightness, color = p.random(stones.length) | 0, alpha = .04 + p.random(.04) + 4 / state.nodes.length; state.majorMetadata.Stone = stones[color][0]; // Glitch the alpha value. alpha = glitch("Severe", alpha, _ => alpha > .2 ? alpha : .4 + p.random(.3)); const // Sets color values based on the selected stone. setValues = _ => { hue = stones[color][1] + gaussian(2); sat = stones[color][2] + .3; brightness = stones[color][3]; }, // Roll style-specific random values. purity = 7 + gaussian(2), multiply = glitch("Sinister", false, _ => true) ? state.nodes.map(node => randomBool(.7 + .25 * ra(node)[0])) : state.nodes.map(node => randomBool(.25 + .25 * ra(node)[0])), hueShifts = state.nodes.map(node => purity * gaussian()); setValues(); // Draw the backgound gradient. [p, texture].map(instance => { fillRadial( instance, ...state.center, state.canvasSize / 2, instance.color(hue, sat * 15, brightness + 5), instance.color(hue, 100, 2 + (instance == texture)) ); instance.circle(...state.center, state.canvasSize); }); // Draw the background circles. state.nodes.map((node, i) => { const blend = multiply[i] ? p.MULTIPLY : p.ADD, scaled = [node[0], node[1], node[2] * 15, node[3]]; p.blendMode(blend); texture.blendMode(blend); p.fill( multiply[i] ? p.color(0, alpha * 2.5) : p.color(hue + hueShifts[i], sat * 8, brightness * 2, alpha * 2) ); texture.fill(multiply[i] ? p.color(0, alpha * 2.4) : p.color(hue + hueShifts[i], sat * 7.5, brightness * 1.9, alpha * 2)); p.circle(...scaled.slice(0, 2), scaled[2] * 2); drawPolygon( texture, tracePolygon(circle(smear(scaled, state.smear * 3)))); }); // Draw the background hexagons. state.nodes.map((node, i) => { const blend = multiply[i] ? p.MULTIPLY : p.ADD, scaled = [node[0], node[1], node[2] * 5, node[3]]; p.blendMode(blend); texture.blendMode(blend); p.fill( multiply[i] ? p.color(0, alpha * 3.5) : p.color(hue + hueShifts[i], sat * 9, brightness * 4.5, alpha * 3) ); texture.fill( multiply[i] ? p.color(0, alpha * 3.4) : p.color(hue + hueShifts[i], sat * 9, brightness * 4.75, alpha * 3.3) ); drawPolygon(p, hexagon(scaled)); drawPolygon(texture, tracePolygon(hexagon(smear(scaled, state.smear)))); }); // Recolor the background; Bypass p5js since it has no "color" compositing. p.drawingContext.globalCompositeOperation = texture.drawingContext.globalCompositeOperation = "color"; const recolor = p.color(hue, sat * 14, brightness + 5, .35); p.fill(recolor); p.circle(...state.center, state.canvasSize); texture.fill(recolor); texture.circle(...state.center, state.canvasSize); // Reset the cached blend mode. p.blendMode(p.BLEND); texture.blendMode(p.BLEND); // Now that the background is complete, glitch the foreground color. glitch( "Eccentric", color, _ => color = ((color + p.round(gaussian(3))) % stones.length + stones.length) % stones.length, _ => { setValues(); state.majorMetadata.Stone += ", " + stones[color][0]; } ); // Draw the foreground hexagons. state.hexagons.map((hexagon, i) => { p.blendMode(multiply[i] ? p.MULTIPLY : p.ADD); p.fill( multiply[i] ? p.color(hue + hueShifts[i], 100, 5, alpha * 5) : p.color(hue + hueShifts[i], sat * 10, brightness * 10 + 10, alpha * 6) ); drawPolygon(p, hexagon); }); state.textugons.map((textugon, i) => { texture.blendMode(multiply[i] ? p.MULTIPLY : p.ADD); texture.fill( multiply[i] ? p.color(hue + hueShifts[i], 100, 5, alpha * 5) : p.color(hue + hueShifts[i], sat * 9, brightness * 10 + 10, alpha * 6.5) ); drawPolygon(texture, textugon); }); // Recolor the foreground; Bypass p5js since it has no "color" compositing. // Previous mode was MULTIPLY or ADD, and next mode will be BLEND, so no // need for cache busting. p.drawingContext.globalCompositeOperation = texture.drawingContext.globalCompositeOperation = "color"; state.hexagons.map((hexagon, i) => { p.fill(hue + hueShifts[i], sat * 9, brightness * 10, alpha * 3); drawPolygon(p, hexagon); }); state.textugons.map((textugon, i) => { texture.fill(hue + hueShifts[i], sat * 7.5, brightness * 10, alpha * 2.7); drawPolygon(texture, textugon); }); // Set the blend mode back to the default any subsequent draws. p.blendMode(p.BLEND); texture.blendMode(p.BLEND); }; //-[ p5js functions ]---------------------------------------------------------// // Creates the p5js canvas and disables looping. // The rest of the setup is done when the Immutables properties are received. p.setup = _ => { canvas = p.createCanvas(1,1); canvas.style("display", "block"); p.noLoop(); }, // Responds to the properties provided by Immutables. p.myCustomRedrawAccordingToNewPropsHandler = properties => { if (!properties.transactionHash) return; // Check if existing state already matches the new properties. if ( state && state.hash == properties.transactionHash && state.edition == properties.editionId ) { if (state.square != properties.square) { state.square = properties.square; p.windowResized(); } // The state doesn't need updated, so our work here is done. return; } // Pull 32 bits from the transaction hash to seed the RNG. // Pick which bits to pull based on the edition ID to cover the off chance // that someone uses a contract to mint multiple outputs at once. const setupSeed = properties.transactionHash.substr(2 + 8 * (properties.editionId % 8), 8); p.randomSeed(+("0x" + setupSeed)); // Roll values needed for node generation. const layers = (.2 + agaussian(1.2)) | 0, loschianNumber = randomBool() ? 4 : 7, layerRatio = p.sqrt(loschianNumber), layerRotate = loschianNumber == 4 ? 0 : p.atan2(halfRoot3, 2.5), alignment = randomBool() ? 1 : randomBool() ? 0 : 4, ratio = randomBool(.75) ? .01 : randomBool() ? .1 : .3, stutter = !alignment ? .05 : .015, nodeCount = 32 + p.max(8, p.ceil(224 + gaussian(160))), nodes = [], candidates = [], // A list of candidate parents for the next generated node. isDense = randomBool(.2), // Creates a new node. newNode = parent => { let // Random chance of jumping to a new layer. This affects all the rest // of the values. layer = randomBool(.1) && layers ? p.random(layers + 1) | 0 : parent[4], size = parent[2] * 2 ** gaussian(ratio) * layerRatio ** (layer - parent[4]), distance = layer != parent[4] ? 0 : (size + parent[2]) * (1.15 + gaussian(stutter)), angle = parent[3] + (p.PI * isDense) + p.round(gaussian(1.5) % 6) * p.PI / 3 + gaussian(alignment * p.PI / 96) + layerRotate * (parent[4] - layer); let node = [ parent[0] + distance * p.cos(angle), parent[1] + distance * p.sin(angle), size, angle, layer ]; nodes.push(node); return node; }; // Generate starter nodes in every layer. for (let i = layers + 1, layerSize = 20; i--;) { let node = [0, 0, layerSize, i * layerRotate, i, 0]; nodes.push(node); for (let j = 2 + randomBool(); j--;) candidates.push(node, node); // Help smaller layers out by giving them more nodes. for (let j = layers - i; j--;) newNode(node); layerSize /= layerRatio; } // Grow randomly from current nodes to reach the target node count. while (nodes.length < nodeCount) { let pIndex = p.random(candidates.length) | 0, parent = candidates[pIndex]; candidates.splice(pIndex, 1); let node = newNode(parent); while (randomBool() || !candidates.length) candidates.push(node); } const // Compute the canvas center and size based on node locations. frame = enclose(nodes, []), maxRadius = p.max( nodes.map(node => p.sqrt(distSquared(node, frame)) + node[2] * 1.5) ), // Roll the remaining values needed to prepare for drawing. size = p.random(4) | 0, handRatio = 2 ** (1.5 + size / 2), handLength = maxRadius / handRatio, style = p.random(), styleId = (style < .875) + (style < .7125); // Put everything where it can be referenced when drawing and redrawing. state = { square: properties.square, edition: +properties.editionId, hash: properties.transactionHash, center: [frame[0], frame[1]], canvasSize: maxRadius * 2.2, styleAngle: p.random(p.TWO_PI), smear: maxRadius / (handRatio * 256), leftHanded: randomBool(.1), handRatio: handRatio, handLength: handLength, penStep: handLength / 64, wristStep: handLength / 384, penSmoothing: .6, wristSmoothing: .9, penDeflection: .25, // How close the pen has to get to a vertex before having "arrived". thresholdSquared: handLength * handLength / 2048, nodes: nodes, hexagons: nodes.map(node => hexagon(node)), glitch: p.random() * p.random() * .4, glitches: {}, styleDraw: [supreme, celestial, energy][styleId], }; // Add the metadata to state that is known at this point. // It is split into major and minor metadata for ordering purposes. state.majorMetadata = { Nexus: ["Supreme", "Celestial", "Energy"][styleId], Arcana: "" // Reserving the key index. Value is filled during drawing. }; state.minorMetadata = { Adherence: ["Extreme", "Varied", "Uniform"][(ratio < .1) + (ratio < .2)], Growth: ["Rigid", "Loose", "", "", "Chaotic"][alignment], Reach: ["Local", "Regional", "Continental", "Global"][size], Focus: isDense ? "Inward" : "Outward", Centuries: "" + (1 + (nodeCount - 1) / 100 | 0), Degrees: "" + (layers + 1), }; // Only include the Loschian Number in metadata if there are actually layers. if (layers) state.minorMetadata["L\u00F6schian Number"] = "" + loschianNumber; // Add final metadata here that should be last in the list of traits. state.minorMetadata.Handed = state.leftHanded ? "Left" : "Right"; state.minorMetadata.transactionHash = properties.transactionHash; // Consider glitching the trace variables now that the state is set up. glitch("Revelous", true, _ => { state.smear *= 3; state.penSmoothing = .8; state.penDeflection = .875; // Since texture overlay hexagons are based on original nodes, this creates // a nice discrepency between the nodes and their overlay. state.nodes = nodes.map(node => smear(node, state.smear)); }); // Setup the trace state and trace the hexagons on the texture overlay. resetTraceState(); state.textugons = nodes.map(node => tracePolygon(hexagon(smear(node, state.smear)))); // Force a redraw and resize the window if needed. p.windowResized(); }; p.windowResized = _ => { if (!state) return; const minDim = p.min(p.windowWidth, p.windowHeight) * .8 / state.square | 0; p.resizeCanvas(minDim, minDim); }; p.keyTyped = _ => { if (!state || state.square != 1) return; if (p.key == 'S' && !state.save) { state.pixelDensity = p.pixelDensity(); state.save = true; canvas.style("display", "none"); p.pixelDensity(1); p.resizeCanvas(5000,5000); } else if (p.key == 'Z') { state.zoom = !state.zoom; p.redraw(); } } p.draw = _ => { if (!state) return; // Pull 32 bits from the transaction hash to reseed the RNG. // Reseed at the beginning of every draw to keep output consistent. // See the comment on setupSeed to explain the use of the edition ID. const drawSeed = state.hash.substr(2 + 8 * ((state.edition + 1) % 8), 8); p.randomSeed(+("0x" + drawSeed)); // Set up the transformation matrix for centering the nodes. const zoom = state.zoom ? p.sqrt(2) : 1, texture = p.createGraphics(p.width, p.width), scale = p.width / state.canvasSize * zoom, matrix = [ scale, 0, 0, scale, p.width / 2 - state.center[0] * scale, p.width / 2 - state.center[1] * scale ]; p.applyMatrix(...matrix); texture.applyMatrix(...matrix); // Reset the tracing state before drawing to keep output consistent. resetTraceState(); // Call the style-specific draw code. state.styleDraw(texture); // Compile glitches. state.majorMetadata.Arcana = Object.keys(state.glitches).sort().join(", ") || "Unknown"; const fullMetadata = { ...state.majorMetadata, ...state.minorMetadata, } // Report the metadata and log each trait to the console. if (!state.metadataReported) { console.log("metadata: ", fullMetadata); Object.keys(fullMetadata) .map(key => console.log(key, ":", fullMetadata[key])); // Mark as completed so that metadata output can be skipped for redraws. state.metadataReported = true; } // Create the "thread" texture mask. const threadSize = p.width / (state.handRatio * 54), threadLimit = p.width / threadSize + 1, mask = p.createGraphics(p.width, p.width); mask.fill(0); mask.noStroke(); // When zoom is enabled, zoom in just enough to have a full square image. if (state.zoom) { const offset = p.width / 2 * (1 - zoom); mask.applyMatrix(zoom, 0, 0, zoom, offset, offset); } // Draw a grid of threads over the whole mask. for (let x = 0; x < threadLimit; x++) { for (let y = 0; y < threadLimit; y++) { if (x % 2 == y % 2) continue; const w = threadSize * (1 + gaussian(.16)), h = threadSize * (1 + gaussian(.16)); if (w < 0 || h < 0) continue; mask.ellipse(threadSize * x, threadSize * y, w, h); } } // Apply texture mask. const textureImage = texture.get(); textureImage.mask(mask); // Apply border masks. const mainImage = p.get(); if (state.zoom) { // Square mask. const inset = threadSize * p.sqrt(2) / 8; mask.clear(); mask.resetMatrix(); mask.rect(inset, inset, mask.width - inset * 2); mainImage.mask(mask); } else { // Circle mask. mask.clear(); mask.circle(mask.width / 2, mask.width / 2, mask.width * .99); textureImage.mask(mask); mask.clear(); mask.circle(mask.width / 2, mask.width / 2, mask.width * .99 - threadSize / 4); mainImage.mask(mask); } // Copy the masked images to the main canvas. p.clear(); p.resetMatrix(); p.image(mainImage, 0, 0); p.image(textureImage, 0, 0); // Clean up the extra canvases. texture.remove(); mask.remove(); // If a save was initiated, write out the image and reset the canvas. if (state.save) { p.save("Syncret #" + state.edition + ".png"); p.pixelDensity(state.pixelDensity); p.windowResized(); canvas.style("display", "block"); state.save = false; } } ```
unknown sendersent to0x499f4943…3001·#14,119,433·0x097779d6…ea7319
# Syncret _by [Mark Egli]_ Exploring the beauty of harmony and dissonance. <p style="text-align: center;"> <img src="https://ipfs.io/ipfs/bafybeieojujdkmfwevpef4ypymoahyiio7p75m3hiqqv3bk6cbymjtkqm4" alt="Syncret Rinkeby Mint #1" title="Syncret Rinkeby Mint #1" style="width:50%;max-width:512px;" /> </p> While each viewer brings their own understanding to the work, I created Syncret to reflect the ways in which we each embody conflicting motivations and stitch our own inner inconsistencies into a beautiful and cohesive whole. **Code License:** [CC BY-NC-SA 4.0] **Edition License:** [NIFTY] [Mark Egli]: https://markegli.com [CC BY-NC-SA 4.0]: https://creativecommons.org/licenses/by-nc-sa/4.0/ [NIFTY]: https://www.nftlicense.org/ ## Controls | Input | Action | |:----------|:------------------------------------| | Shift + S | Save a 5000&times;5000 pixel image. | | Shift + Z | Toggle square cropping. | ## Traits Traits in italics are only present based on the value of other traits. * Nexus * Arcana * _Emptiness_ * _Polarity_ * _Stone_ * Adherence * Growth * Reach * Focus * Centuries * Degrees * _L&ouml;schian Number_ * Handed
Syncret# Syncret _by [Mark Egli]_ Exploring the beauty of harmony and dissonance. <p style="text-align: center;"> <img src="https://ipfs.io/ipfs/bafybeieojujdkmfwevpef4ypymoahyiio7p75m3hiqqv3bk6cbymjtkqm4" alt="Syncret Rinkeby Mint #1" title="Syncret Rinkeby Mint #1" style="width:50%;max-width:512px;" /> </p> While each viewer brings their own understanding to the work, I created Syncret to reflect the ways in which we each embody conflicting motivations and stitch our own inner inconsistencies into a beautiful and cohesive whole. **Code License:** [CC BY-NC-SA 4.0] **Edition License:** [NIFTY] [Mark Egli]: https://markegli.com [CC BY-NC-SA 4.0]: https://creativecommons.org/licenses/by-nc-sa/4.0/ [NIFTY]: https://www.nftlicense.org/ ## Controls | Input | Action | |:----------|:------------------------------------| | Shift + S | Save a 5000&times;5000 pixel image. | | Shift + Z | Toggle square cropping. | ## Traits Traits in italics are only present based on the value of other traits. * Nexus * Arcana * _Emptiness_ * _Polarity_ * _Stone_ * Adherence * Growth * Reach * Focus * Centuries * Degrees * _L&ouml;schian Number_ * Handed
unknown sendersent to0x499f4943…3001·#13,964,881·0x87737e45…23f801
style.immutables.artbody { color: #606060; background-color: #d9d9d9; } .bg-light { background-color: #d9d9d9!important; } .btn-outline-secondary:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-outline-secondary:focus { box-shadow: none; } .btn:focus { outline: 0; box-shadow: none; } .btn-success { background-color: #323232; border-color: #323232; } .btn-secondary { color: #d9d9d9; background-color: #323232; border-color: #323232; } .btn-secondary:hover { color: #fff; background-color: #323232; border-color: #323232; } .btn-secondary:not(:disabled):not(.disabled):active { color: #fff; background-color: #323232; border-color: #323232; } .btn-outline-warning { color: #ff0000; border-color: #ff0000; } .btn-outline-warning:hover { color: #ff0000; background-color: #d9d9d9; border-color: #ff0000; } .btn-outline-warning:not(:disabled):not(.disabled):active { color: #ff0000; background-color: #d9d9d9; border-color: #ff0000; } .btn-outline-warning:focus { box-shadow: none; } .btn-outline-success { color: #fff; background-color: #28a745; border-color: #28a745; } .row { margin-right: -15px; margin-left: -15px; margin-bottom: -20px; } .center { margin: auto; text-align: center; } .btn-success:focus { color: #fff; background-color: #323232; border-color: #323232; } .btn-secondary:focus { color: #fff; background-color: #323232; border-color: #323232; } .btn-outline-secondary:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn:not(:disabled):not(.disabled) { font-weight: bold; } .modal-header { border-bottom: 0; } .modal-footer { align-items: center; justify-content: center; border-top: 0; } .modal-content { background-color: #222222f7; } .d-flex { color: #b1b1b1; } .table td { border-top: 1px solid #404040; } .table { width: 100%; margin-bottom: 0; color: #a8a8a8; } .btn-warning { color: #606060; background-color: #0000; border-color: #0000; } .btn-warning:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-warning:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-warning:focus { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .form-control { display: block; color: #909090; background-color: #32323200; border: 1px solid #606060; } .form-control:focus { color: #707070; background-color: #32323200; border-color: #808080; outline: 0; box-shadow: none; } .form-group { padding-left: 7.5%; padding-right: 7.5%; } .nav-tabs .nav-link.active { color: #d9d9d9; background-color: #0000; border-color: #d9d9d9 #d9d9d9 #d9d9d9; } a { color: #959595; background-color: transparent; } a:hover { color: #d9d9d9; } b, strong { font-weight: bolder; } p { margin-top: 20px; } .input-group-text { align-items: center; color: #a9a9a9; text-align: center; background-color: #0000; border: 0; } .input-group>.form-control:not(:first-child) { background-color: #0000; } .form-check { color: #606060; } .form-check-input:disabled~.form-check-label, .form-check-input[disabled]~.form-check-label { color: #606060; } .table-bordered td { border: 1px solid #404040; } .table-bordered th { border: 1px solid #404040; } .nav-tabs .nav-link.active { color: #d9d9d9; background-color: #0000; border-color: #d9d9d9 #d9d9d9 #d9d9d9; } .h4 { color: #d9d9d9; } .close { color: #d9d9d9; } .close:hover { color: #fff; } .nav-tabs { border-bottom: 1px solid #666; } .wmde-markdown { color: #606060; } .wmde-markdown a { color: #17a2b8; } .btn-outline-secondary { border-color: #0000; color: #606060 } .btn-info { color: #606060; background-color: #0000; border-color: #0000; } .btn-info:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-info:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-info:focus { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .modal-title { position: absolute; left: 50%; transform: translate(-50%, -50%); margin-top: 2.5%; margin-right: -30%; } .gridTable { margin: 3vh auto 0; } @keyframes grid { from {margin: -197px;} to {margin: 0px;} } @keyframes detail { from {opacity: 0;} to {opacity: 1;} } .cell {padding: 3vmin; animation-name: grid; animation-duration: 1s;} .cell.selected {animation-name: detail; animation-duration: 2s;}
Ethereal Phasestyle.immutables.artbody { color: #606060; background-color: #d9d9d9; } .bg-light { background-color: #d9d9d9!important; } .btn-outline-secondary:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-outline-secondary:focus { box-shadow: none; } .btn:focus { outline: 0; box-shadow: none; } .btn-success { background-color: #323232; border-color: #323232; } .btn-secondary { color: #d9d9d9; background-color: #323232; border-color: #323232; } .btn-secondary:hover { color: #fff; background-color: #323232; border-color: #323232; } .btn-secondary:not(:disabled):not(.disabled):active { color: #fff; background-color: #323232; border-color: #323232; } .btn-outline-warning { color: #ff0000; border-color: #ff0000; } .btn-outline-warning:hover { color: #ff0000; background-color: #d9d9d9; border-color: #ff0000; } .btn-outline-warning:not(:disabled):not(.disabled):active { color: #ff0000; background-color: #d9d9d9; border-color: #ff0000; } .btn-outline-warning:focus { box-shadow: none; } .btn-outline-success { color: #fff; background-color: #28a745; border-color: #28a745; } .row { margin-right: -15px; margin-left: -15px; margin-bottom: -20px; } .center { margin: auto; text-align: center; } .btn-success:focus { color: #fff; background-color: #323232; border-color: #323232; } .btn-secondary:focus { color: #fff; background-color: #323232; border-color: #323232; } .btn-outline-secondary:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn:not(:disabled):not(.disabled) { font-weight: bold; } .modal-header { border-bottom: 0; } .modal-footer { align-items: center; justify-content: center; border-top: 0; } .modal-content { background-color: #222222f7; } .d-flex { color: #b1b1b1; } .table td { border-top: 1px solid #404040; } .table { width: 100%; margin-bottom: 0; color: #a8a8a8; } .btn-warning { color: #606060; background-color: #0000; border-color: #0000; } .btn-warning:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-warning:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-warning:focus { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .form-control { display: block; color: #909090; background-color: #32323200; border: 1px solid #606060; } .form-control:focus { color: #707070; background-color: #32323200; border-color: #808080; outline: 0; box-shadow: none; } .form-group { padding-left: 7.5%; padding-right: 7.5%; } .nav-tabs .nav-link.active { color: #d9d9d9; background-color: #0000; border-color: #d9d9d9 #d9d9d9 #d9d9d9; } a { color: #959595; background-color: transparent; } a:hover { color: #d9d9d9; } b, strong { font-weight: bolder; } p { margin-top: 20px; } .input-group-text { align-items: center; color: #a9a9a9; text-align: center; background-color: #0000; border: 0; } .input-group>.form-control:not(:first-child) { background-color: #0000; } .form-check { color: #606060; } .form-check-input:disabled~.form-check-label, .form-check-input[disabled]~.form-check-label { color: #606060; } .table-bordered td { border: 1px solid #404040; } .table-bordered th { border: 1px solid #404040; } .nav-tabs .nav-link.active { color: #d9d9d9; background-color: #0000; border-color: #d9d9d9 #d9d9d9 #d9d9d9; } .h4 { color: #d9d9d9; } .close { color: #d9d9d9; } .close:hover { color: #fff; } .nav-tabs { border-bottom: 1px solid #666; } .wmde-markdown { color: #606060; } .wmde-markdown a { color: #17a2b8; } .btn-outline-secondary { border-color: #0000; color: #606060 } .btn-info { color: #606060; background-color: #0000; border-color: #0000; } .btn-info:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-info:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-info:focus { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .modal-title { position: absolute; left: 50%; transform: translate(-50%, -50%); margin-top: 2.5%; margin-right: -30%; } .gridTable { margin: 3vh auto 0; } @keyframes grid { from {margin: -197px;} to {margin: 0px;} } @keyframes detail { from {opacity: 0;} to {opacity: 1;} } .cell {padding: 3vmin; animation-name: grid; animation-duration: 1s;} .cell.selected {animation-name: detail; animation-duration: 2s;}
unknown sendersent to0x499f4943…3001·#13,964,643·0xadb5fb20…84fbe0
H0x92c23775f6559d3392562c6bfd4e74c27d098f36b8584553f3716fdf1aa9b5a6# Ethereal Phase An exploration between contrasting polarities and equilibrium inspired by electromagnetic waves. Each 'Ethereal Phase' is unique to the transaction that generated it. ## ![](https://bafkreibmkflzrvjutwgw3tmtqchqpz7foelezjrcwaurw4uuhvxpscqmyi.ipfs.dweb.link/) | Artist | [Audivit](https://audivit.xyz/) | |:------------|:-----------| | **Editions** | 500 | | **Editions License** | [NIFTY](https://www.nftlicense.org/) | | **Code License** | [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) | ## Metadata | Attribute | Possible Values | |:------------|:-----------| | Style | Ethereal, Spectral | | Context | Frame, Marble, Turbine | | Palette | Hero, Smart, Dupont, Funken, Spritz, Decca, Villain, Monochrome | | Crest | 0% to 100% - Amplitude detail | | Frequency | 0% to 100% - Wave cycles | | Flux | 0% to 100% - Wave flow force | | Asymmetry | 0% to 100% - Skew of shadow wave | | Compression | 0% to 100% - Max amplitude and wave border dimension | ## Extra Features | Input | Action | |:------------|:-----------| | Press key [ **s** ] | Save high resolution 5000x5000 pixels file | ## Source Code ``` let decPairs, TX, TXN, EID, DIM, inDIM, WIDTH, HEIGHT, frame, seed, palette, clr, ctx, turble, save; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } } printMetadata = () => { if (decPairs[29] <= 170) { metadataObj.Style = "Ethereal"; } else { metadataObj.Style = "Spectral"; } if (decPairs[20] >= 180 && decPairs[20] < 245 && metadataObj.Style != "Spectral") { metadataObj.Context = "Marble"; } else if (decPairs[20] >= 245) { metadataObj.Context = "Turbine"; } else { metadataObj.Context = "Frame"; } metadataObj.Palette = clr[0]; metadataObj.Crest = p.round(p.map(decPairs[9], 0, 255, 1, 100)) + "%"; metadataObj.Frequency = p.round(p.map(decPairs[15], 0, 255, 1, 100)) + "%"; metadataObj.Flux = p.round(p.map(decPairs[4], 0, 255, 1, 100)) + "%"; metadataObj.Asymmetry = p.round(p.map(decPairs[6], 0, 255, 1, 100)) + "%"; metadataObj.Compression = p.round(p.map(decPairs[7], 0, 255, 1, 100)) + "%"; metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } p.myCustomRedrawAccordingToNewPropsHandler = (props) => { p.keyTyped = () => { if (p.keyCode === 83 && props.square == 1) { save.save("Ethereal Phase #" + EID + ".tif"); } } if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; if (props.square > 1) { WIDTH = p.windowWidth / props.square * 0.7; HEIGHT = p.windowHeight / props.square * 0.7; } else { WIDTH = p.windowWidth / props.square * 0.9; HEIGHT = p.windowHeight / props.square * 0.9; } DIM = Math.min(WIDTH, HEIGHT); inDIM = 1000; getHashData(1); p.randomSeed(+props.transactionHash.substr(0, 10)); seed = p.random(0, 255); p.noiseSeed(seed); p.createCanvas(DIM, DIM); turble = p.createGraphics(inDIM, inDIM, p.WEBGL) turble.smooth(); turble.setAttributes("alpha", true); turble.setAttributes("antialias", true); render = p.createGraphics(inDIM, inDIM); frame = p.createGraphics(inDIM, inDIM, p.WEBGL); frame.setAttributes("alpha", false); frame.setAttributes("antialias", true); frame.smooth(); frame.rectMode(p.CENTER); let crest = p.map(decPairs[9], 0, 255, 1.0, 4.0); let frequency = p.map(decPairs[15], 0, 255, 3.0, 5.0); let flux = p.map(decPairs[4], 0, 255, 1.3, 1.4); let asymmetry = p.map(decPairs[6], 0, 255, 1.0, 1.1); let compression = p.map(decPairs[7], 0, 255, 0.3, 0.6); if (decPairs[29] <= 170) { pal5 = ["Funken", "#4E3D53", "#FFB200", "#FAF9EF", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FAF9EF", "#FF4D6E"]; pal2 = ["Smart", "#FAF9EF", "#00ADB5", "#FAF9EF", "#7DD3D3"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FAF9EF", "#03506F"]; pal4 = ["Spritz", "#FF7869", "#FFC57E", "#FAF9EF", "#FFC57E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FAF9EF", "#FF2442"]; pal7 = ["Villain", "#28FFBF", "#101010", "#28FFBF", "#28FFBF"]; pal8 = ["Monochrome", "#FAF9EF", "#101010", "#FAF9EF", "#FAF9EF"]; } else { pal2 = ["Hero", "#03506F", "#03506F", "#FAF9EF", "#FF2442"]; pal1 = ["Hero", "#03506F", "#03506F", "#FAF9EF", "#FF2442"]; pal4 = ["Dupont", "#6D9598", "#FF2442", "#FAF9EF", "#FF2442"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FAF9EF", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FAF9EF", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FAF9EF", "#FF2442"]; pal7 = ["Funken", "#4E3D53", "#FFB200", "#FAF9EF", "#FFB200"]; pal8 = ["Decca", "#7F616D", "#FF4D6E", "#FAF9EF", "#FF4D6E"];; } let PLT = []; for (let clrArr = 0; clrArr <= 512; clrArr++) { let count = "pal" + p.round(p.random(1, 8)); PLT.push(count); } palette = p.round(p.random(512)); clr = eval(PLT[palette]); printMetadata(); if (props.square > 1) { turble.pixelDensity(0.5); render.pixelDensity(0.5); frame.pixelDensity(0.5); } else if (props.square == 1 && p.displayWidth < p.displayHeight) { turble.pixelDensity(1); render.pixelDensity(1); frame.pixelDensity(1); } else { p.pixelDensity(p.displayDensity() + 1); turble.pixelDensity(5); render.pixelDensity(5); frame.pixelDensity(5); } frame.background(clr[1]); p.noiseDetail(crest); frame.noFill(); frame.strokeWeight(inDIM / 70); frame.rectMode(p.CENTER); if (decPairs[20] < 245 && metadataObj.Context != "Marble") { frame.rect(0, 0, inDIM, inDIM); } frame.translate(-inDIM * 0.35, -inDIM * 0.35, -inDIM / 2); frame.push(); frame.translate(-inDIM * 1.5, 0, 0); frame.beginShape(p.TRIANGLE_STRIP); for (let x = inDIM / 5.5; x < inDIM * 3.5; x += 0.5) { let nx = p.map(x, 100, -inDIM, frequency, 0); let y = inDIM * 0.95 * p.noise(nx / 2); let z = inDIM + p.noise(nx / 2); frame.strokeWeight(inDIM * 0.06); frame.stroke(0, 20); frame.fill(clr[2]); frame.vertex(x, y, 0); if (decPairs[29] <= 170) { if (decPairs[20] >= 245 && metadataObj.Palette == "Monochrome" || metadataObj.Palette == "Smart") { frame.background(clr[2]); } else { frame.background(clr[1]); } frame.stroke(clr[1] + "20"); if (decPairs[20] >= 245) { frame.strokeWeight(1); frame.vertex(x, y * 0.03, 0); frame.vertex(x / (asymmetry * 1.1), y * compression * 3, 0); } else { frame.strokeWeight(1); frame.vertex(x, y * 0.03, 0); frame.vertex(x / (asymmetry * 1.1), y * compression * 2, 0); } } else { frame.noFill(); frame.stroke(clr[4] + "30") frame.strokeWeight(0.5); frame.vertex(x * flux, z / 3, 0); if (decPairs[20] >= 245) { frame.vertex(x, y * 1.5, 0); } else { frame.vertex(x, y * 0.4, 0); } frame.vertex(x / asymmetry, y * compression, 0); } } frame.endShape(); frame.pop(); if (decPairs[20] >= 245 && metadataObj.Palette == "Villain") { frame.fill(clr[2]); } else { frame.fill(clr[3]); } frame.noStroke(); if (decPairs[29] <= 170) { frame.translate(0, inDIM * 0.3, -(inDIM * 0.2)); frame.rect(inDIM / 3, inDIM * 1.75, inDIM * 2, inDIM * 4); frame.fill(clr[2]); frame.rect(inDIM / 3, inDIM * 0.05, inDIM * 2, inDIM * 0.75); } else { frame.translate(0, -2, -(inDIM * 0.2)); frame.rect(inDIM / 3, inDIM * 0.833, inDIM * 2, inDIM); frame.fill(clr[1]); frame.rect(inDIM / 3, inDIM * 0.83, inDIM * 2, inDIM); frame.fill(0, 80); frame.rect(inDIM / 3, inDIM * 0.83, inDIM * 2, inDIM); } } ctx = frame; turble.ortho(-(DIM / 2), DIM / 2, DIM / 2, -(DIM / 2), -(DIM * 6), DIM * 6); turble.camera(DIM, DIM, (DIM / 2) / p.tan(p.PI / 6.8), 0, 0, 0, 0, 1, 0); if (decPairs[20] >= 180 && decPairs[20] < 245 && metadataObj.Style != "Spectral") { ctx = turble; if (metadataObj.Palette == "Hero" && metadataObj.Style == "Spectral") { turble.background(clr[4] + "99"); } else if (metadataObj.Palette == "Smart") { turble.background(clr[4]); } else if (metadataObj.Palette == "Funken" || metadataObj.Palette == "Dupont" || metadataObj.Palette == "Spritz") { turble.background(clr[1] + "99"); } else if (metadataObj.Palette == "Monochrome" || metadataObj.Palette == "Villain") { turble.background(clr[3] + "99"); } else { turble.background(clr[2] + "99"); } turble.noStroke(); turble.texture(frame); turble.rotateX(40); turble.rotateZ(p.random(1, 3)); turble.sphere(DIM / 3, 500, 500); } else if (decPairs[20] >= 245) { ctx = turble; if (metadataObj.Palette == "Smart" || metadataObj.Palette == "Monochrome") { turble.background(clr[2]); turble.stroke(clr[2]); } else { turble.background(clr[1]); turble.stroke(clr[1]); } turble.strokeWeight(10 * turble.pixelDensity()); turble.texture(frame); turble.box(DIM / 2, DIM / 2, DIM / 2); } render.image(ctx, 0, 0, inDIM, inDIM); render.blendMode(p.SOFT_LIGHT); render.background(60); save = render; p.redraw(); } p.draw = () => { p.image(render, 0, 0, DIM, DIM); p.noLoop(); render.remove(); turble.remove(); frame.remove(); ctx.remove(); render = null; turble = null; frame = null; ctx = null; } ```
Ethereal PhaseH0x92c23775f6559d3392562c6bfd4e74c27d098f36b8584553f3716fdf1aa9b5a6# Ethereal Phase An exploration between contrasting polarities and equilibrium inspired by electromagnetic waves. Each 'Ethereal Phase' is unique to the transaction that generated it. ## ![](https://bafkreibmkflzrvjutwgw3tmtqchqpz7foelezjrcwaurw4uuhvxpscqmyi.ipfs.dweb.link/) | Artist | [Audivit](https://audivit.xyz/) | |:------------|:-----------| | **Editions** | 500 | | **Editions License** | [NIFTY](https://www.nftlicense.org/) | | **Code License** | [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) | ## Metadata | Attribute | Possible Values | |:------------|:-----------| | Style | Ethereal, Spectral | | Context | Frame, Marble, Turbine | | Palette | Hero, Smart, Dupont, Funken, Spritz, Decca, Villain, Monochrome | | Crest | 0% to 100% - Amplitude detail | | Frequency | 0% to 100% - Wave cycles | | Flux | 0% to 100% - Wave flow force | | Asymmetry | 0% to 100% - Skew of shadow wave | | Compression | 0% to 100% - Max amplitude and wave border dimension | ## Extra Features | Input | Action | |:------------|:-----------| | Press key [ **s** ] | Save high resolution 5000x5000 pixels file | ## Source Code ``` let decPairs, TX, TXN, EID, DIM, inDIM, WIDTH, HEIGHT, frame, seed, palette, clr, ctx, turble, save; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } } printMetadata = () => { if (decPairs[29] <= 170) { metadataObj.Style = "Ethereal"; } else { metadataObj.Style = "Spectral"; } if (decPairs[20] >= 180 && decPairs[20] < 245 && metadataObj.Style != "Spectral") { metadataObj.Context = "Marble"; } else if (decPairs[20] >= 245) { metadataObj.Context = "Turbine"; } else { metadataObj.Context = "Frame"; } metadataObj.Palette = clr[0]; metadataObj.Crest = p.round(p.map(decPairs[9], 0, 255, 1, 100)) + "%"; metadataObj.Frequency = p.round(p.map(decPairs[15], 0, 255, 1, 100)) + "%"; metadataObj.Flux = p.round(p.map(decPairs[4], 0, 255, 1, 100)) + "%"; metadataObj.Asymmetry = p.round(p.map(decPairs[6], 0, 255, 1, 100)) + "%"; metadataObj.Compression = p.round(p.map(decPairs[7], 0, 255, 1, 100)) + "%"; metadataObj.transactionHash = TX; console.log("metadata: ", metadataObj); } p.myCustomRedrawAccordingToNewPropsHandler = (props) => { p.keyTyped = () => { if (p.keyCode === 83 && props.square == 1) { save.save("Ethereal Phase #" + EID + ".tif"); } } if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; if (props.square > 1) { WIDTH = p.windowWidth / props.square * 0.7; HEIGHT = p.windowHeight / props.square * 0.7; } else { WIDTH = p.windowWidth / props.square * 0.9; HEIGHT = p.windowHeight / props.square * 0.9; } DIM = Math.min(WIDTH, HEIGHT); inDIM = 1000; getHashData(1); p.randomSeed(+props.transactionHash.substr(0, 10)); seed = p.random(0, 255); p.noiseSeed(seed); p.createCanvas(DIM, DIM); turble = p.createGraphics(inDIM, inDIM, p.WEBGL) turble.smooth(); turble.setAttributes("alpha", true); turble.setAttributes("antialias", true); render = p.createGraphics(inDIM, inDIM); frame = p.createGraphics(inDIM, inDIM, p.WEBGL); frame.setAttributes("alpha", false); frame.setAttributes("antialias", true); frame.smooth(); frame.rectMode(p.CENTER); let crest = p.map(decPairs[9], 0, 255, 1.0, 4.0); let frequency = p.map(decPairs[15], 0, 255, 3.0, 5.0); let flux = p.map(decPairs[4], 0, 255, 1.3, 1.4); let asymmetry = p.map(decPairs[6], 0, 255, 1.0, 1.1); let compression = p.map(decPairs[7], 0, 255, 0.3, 0.6); if (decPairs[29] <= 170) { pal5 = ["Funken", "#4E3D53", "#FFB200", "#FAF9EF", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FAF9EF", "#FF4D6E"]; pal2 = ["Smart", "#FAF9EF", "#00ADB5", "#FAF9EF", "#7DD3D3"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FAF9EF", "#03506F"]; pal4 = ["Spritz", "#FF7869", "#FFC57E", "#FAF9EF", "#FFC57E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FAF9EF", "#FF2442"]; pal7 = ["Villain", "#28FFBF", "#101010", "#28FFBF", "#28FFBF"]; pal8 = ["Monochrome", "#FAF9EF", "#101010", "#FAF9EF", "#FAF9EF"]; } else { pal2 = ["Hero", "#03506F", "#03506F", "#FAF9EF", "#FF2442"]; pal1 = ["Hero", "#03506F", "#03506F", "#FAF9EF", "#FF2442"]; pal4 = ["Dupont", "#6D9598", "#FF2442", "#FAF9EF", "#FF2442"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FAF9EF", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FAF9EF", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FAF9EF", "#FF2442"]; pal7 = ["Funken", "#4E3D53", "#FFB200", "#FAF9EF", "#FFB200"]; pal8 = ["Decca", "#7F616D", "#FF4D6E", "#FAF9EF", "#FF4D6E"];; } let PLT = []; for (let clrArr = 0; clrArr <= 512; clrArr++) { let count = "pal" + p.round(p.random(1, 8)); PLT.push(count); } palette = p.round(p.random(512)); clr = eval(PLT[palette]); printMetadata(); if (props.square > 1) { turble.pixelDensity(0.5); render.pixelDensity(0.5); frame.pixelDensity(0.5); } else if (props.square == 1 && p.displayWidth < p.displayHeight) { turble.pixelDensity(1); render.pixelDensity(1); frame.pixelDensity(1); } else { p.pixelDensity(p.displayDensity() + 1); turble.pixelDensity(5); render.pixelDensity(5); frame.pixelDensity(5); } frame.background(clr[1]); p.noiseDetail(crest); frame.noFill(); frame.strokeWeight(inDIM / 70); frame.rectMode(p.CENTER); if (decPairs[20] < 245 && metadataObj.Context != "Marble") { frame.rect(0, 0, inDIM, inDIM); } frame.translate(-inDIM * 0.35, -inDIM * 0.35, -inDIM / 2); frame.push(); frame.translate(-inDIM * 1.5, 0, 0); frame.beginShape(p.TRIANGLE_STRIP); for (let x = inDIM / 5.5; x < inDIM * 3.5; x += 0.5) { let nx = p.map(x, 100, -inDIM, frequency, 0); let y = inDIM * 0.95 * p.noise(nx / 2); let z = inDIM + p.noise(nx / 2); frame.strokeWeight(inDIM * 0.06); frame.stroke(0, 20); frame.fill(clr[2]); frame.vertex(x, y, 0); if (decPairs[29] <= 170) { if (decPairs[20] >= 245 && metadataObj.Palette == "Monochrome" || metadataObj.Palette == "Smart") { frame.background(clr[2]); } else { frame.background(clr[1]); } frame.stroke(clr[1] + "20"); if (decPairs[20] >= 245) { frame.strokeWeight(1); frame.vertex(x, y * 0.03, 0); frame.vertex(x / (asymmetry * 1.1), y * compression * 3, 0); } else { frame.strokeWeight(1); frame.vertex(x, y * 0.03, 0); frame.vertex(x / (asymmetry * 1.1), y * compression * 2, 0); } } else { frame.noFill(); frame.stroke(clr[4] + "30") frame.strokeWeight(0.5); frame.vertex(x * flux, z / 3, 0); if (decPairs[20] >= 245) { frame.vertex(x, y * 1.5, 0); } else { frame.vertex(x, y * 0.4, 0); } frame.vertex(x / asymmetry, y * compression, 0); } } frame.endShape(); frame.pop(); if (decPairs[20] >= 245 && metadataObj.Palette == "Villain") { frame.fill(clr[2]); } else { frame.fill(clr[3]); } frame.noStroke(); if (decPairs[29] <= 170) { frame.translate(0, inDIM * 0.3, -(inDIM * 0.2)); frame.rect(inDIM / 3, inDIM * 1.75, inDIM * 2, inDIM * 4); frame.fill(clr[2]); frame.rect(inDIM / 3, inDIM * 0.05, inDIM * 2, inDIM * 0.75); } else { frame.translate(0, -2, -(inDIM * 0.2)); frame.rect(inDIM / 3, inDIM * 0.833, inDIM * 2, inDIM); frame.fill(clr[1]); frame.rect(inDIM / 3, inDIM * 0.83, inDIM * 2, inDIM); frame.fill(0, 80); frame.rect(inDIM / 3, inDIM * 0.83, inDIM * 2, inDIM); } } ctx = frame; turble.ortho(-(DIM / 2), DIM / 2, DIM / 2, -(DIM / 2), -(DIM * 6), DIM * 6); turble.camera(DIM, DIM, (DIM / 2) / p.tan(p.PI / 6.8), 0, 0, 0, 0, 1, 0); if (decPairs[20] >= 180 && decPairs[20] < 245 && metadataObj.Style != "Spectral") { ctx = turble; if (metadataObj.Palette == "Hero" && metadataObj.Style == "Spectral") { turble.background(clr[4] + "99"); } else if (metadataObj.Palette == "Smart") { turble.background(clr[4]); } else if (metadataObj.Palette == "Funken" || metadataObj.Palette == "Dupont" || metadataObj.Palette == "Spritz") { turble.background(clr[1] + "99"); } else if (metadataObj.Palette == "Monochrome" || metadataObj.Palette == "Villain") { turble.background(clr[3] + "99"); } else { turble.background(clr[2] + "99"); } turble.noStroke(); turble.texture(frame); turble.rotateX(40); turble.rotateZ(p.random(1, 3)); turble.sphere(DIM / 3, 500, 500); } else if (decPairs[20] >= 245) { ctx = turble; if (metadataObj.Palette == "Smart" || metadataObj.Palette == "Monochrome") { turble.background(clr[2]); turble.stroke(clr[2]); } else { turble.background(clr[1]); turble.stroke(clr[1]); } turble.strokeWeight(10 * turble.pixelDensity()); turble.texture(frame); turble.box(DIM / 2, DIM / 2, DIM / 2); } render.image(ctx, 0, 0, inDIM, inDIM); render.blendMode(p.SOFT_LIGHT); render.background(60); save = render; p.redraw(); } p.draw = () => { p.image(render, 0, 0, DIM, DIM); p.noLoop(); render.remove(); turble.remove(); frame.remove(); ctx.remove(); render = null; turble = null; frame = null; ctx = null; } ```
unknown sendersent to0x499f4943…3001·#13,827,914·0x9a92351c…84c321
style.immutables.artbody { color: #606060; background-color: #d9d9d9; } .bg-light { background-color: #d9d9d9!important; } .btn-outline-secondary:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-outline-secondary:focus { box-shadow: none; } .btn:focus { outline: 0; box-shadow: none; } .btn-success { background-color: #323232; border-color: #323232; } .btn-secondary { color: #d9d9d9; background-color: #323232; border-color: #323232; } .btn-secondary:hover { color: #fff; background-color: #323232; border-color: #323232; } .btn-secondary:not(:disabled):not(.disabled):active { color: #fff; background-color: #323232; border-color: #323232; } .btn-outline-warning { color: #ff0000; border-color: #ff0000; } .btn-outline-warning:hover { color: #ff0000; background-color: #d9d9d9; border-color: #ff0000; } .btn-outline-warning:not(:disabled):not(.disabled):active { color: #ff0000; background-color: #d9d9d9; border-color: #ff0000; } .btn-outline-warning:focus { box-shadow: none; } .btn-outline-success { color: #fff; background-color: #28a745; border-color: #28a745; } .row { margin-right: -15px; margin-left: -15px; margin-bottom: -20px; } .center { margin: auto; text-align: center; transform: scale(0.9) translateY(-40px); } .btn-success:focus { color: #fff; background-color: #323232; border-color: #323232; } .btn-secondary:focus { color: #fff; background-color: #323232; border-color: #323232; } .btn-outline-secondary:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn:not(:disabled):not(.disabled) { font-weight: bold; } .modal-header { border-bottom: 0; } .modal-footer { align-items: center; justify-content: center; border-top: 0; } .modal-content { background-color: #222222f7; } .d-flex { color: #b1b1b1; } .table td { border-top: 1px solid #404040; } .table { width: 100%; margin-bottom: 0; color: #a8a8a8; } .btn-warning { color: #606060; background-color: #0000; border-color: #0000; } .btn-warning:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-warning:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-warning:focus { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .form-control { display: block; color: #909090; background-color: #32323200; border: 1px solid #606060; } .form-control:focus { color: #707070; background-color: #32323200; border-color: #808080; outline: 0; box-shadow: none; } .form-group { padding-left: 7.5%; padding-right: 7.5%; } .nav-tabs .nav-link.active { color: #d9d9d9; background-color: #0000; border-color: #d9d9d9 #d9d9d9 #d9d9d9; } a { color: #959595; background-color: transparent; } a:hover { color: #d9d9d9; } b, strong { font-weight: bolder; } p { margin-top: 20px; } .input-group-text { align-items: center; color: #a9a9a9; text-align: center; background-color: #0000; border: 0; } .input-group>.form-control:not(:first-child) { background-color: #0000; } .form-check { color: #606060; } .form-check-input:disabled~.form-check-label, .form-check-input[disabled]~.form-check-label { color: #606060; } .table-bordered td { border: 1px solid #404040; } .table-bordered th { border: 1px solid #404040; } .nav-tabs .nav-link.active { color: #d9d9d9; background-color: #0000; border-color: #d9d9d9 #d9d9d9 #d9d9d9; } .h4 { color: #d9d9d9; } .close { color: #d9d9d9; } .close:hover { color: #fff; } .nav-tabs { border-bottom: 1px solid #666; } .wmde-markdown { color: #606060; } .wmde-markdown a { color: #17a2b8; } .btn-outline-secondary { border-color: #0000; color: #606060 } .btn-info { color: #606060; background-color: #0000; border-color: #0000; } .btn-info:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-info:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-info:focus { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .modal-title { position: absolute; left: 50%; transform: translate(-50%, -50%); margin-top: 2.5%; margin-right: -30%; }
Ethereal Phasestyle.immutables.artbody { color: #606060; background-color: #d9d9d9; } .bg-light { background-color: #d9d9d9!important; } .btn-outline-secondary:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-outline-secondary:focus { box-shadow: none; } .btn:focus { outline: 0; box-shadow: none; } .btn-success { background-color: #323232; border-color: #323232; } .btn-secondary { color: #d9d9d9; background-color: #323232; border-color: #323232; } .btn-secondary:hover { color: #fff; background-color: #323232; border-color: #323232; } .btn-secondary:not(:disabled):not(.disabled):active { color: #fff; background-color: #323232; border-color: #323232; } .btn-outline-warning { color: #ff0000; border-color: #ff0000; } .btn-outline-warning:hover { color: #ff0000; background-color: #d9d9d9; border-color: #ff0000; } .btn-outline-warning:not(:disabled):not(.disabled):active { color: #ff0000; background-color: #d9d9d9; border-color: #ff0000; } .btn-outline-warning:focus { box-shadow: none; } .btn-outline-success { color: #fff; background-color: #28a745; border-color: #28a745; } .row { margin-right: -15px; margin-left: -15px; margin-bottom: -20px; } .center { margin: auto; text-align: center; transform: scale(0.9) translateY(-40px); } .btn-success:focus { color: #fff; background-color: #323232; border-color: #323232; } .btn-secondary:focus { color: #fff; background-color: #323232; border-color: #323232; } .btn-outline-secondary:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn:not(:disabled):not(.disabled) { font-weight: bold; } .modal-header { border-bottom: 0; } .modal-footer { align-items: center; justify-content: center; border-top: 0; } .modal-content { background-color: #222222f7; } .d-flex { color: #b1b1b1; } .table td { border-top: 1px solid #404040; } .table { width: 100%; margin-bottom: 0; color: #a8a8a8; } .btn-warning { color: #606060; background-color: #0000; border-color: #0000; } .btn-warning:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-warning:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-warning:focus { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .form-control { display: block; color: #909090; background-color: #32323200; border: 1px solid #606060; } .form-control:focus { color: #707070; background-color: #32323200; border-color: #808080; outline: 0; box-shadow: none; } .form-group { padding-left: 7.5%; padding-right: 7.5%; } .nav-tabs .nav-link.active { color: #d9d9d9; background-color: #0000; border-color: #d9d9d9 #d9d9d9 #d9d9d9; } a { color: #959595; background-color: transparent; } a:hover { color: #d9d9d9; } b, strong { font-weight: bolder; } p { margin-top: 20px; } .input-group-text { align-items: center; color: #a9a9a9; text-align: center; background-color: #0000; border: 0; } .input-group>.form-control:not(:first-child) { background-color: #0000; } .form-check { color: #606060; } .form-check-input:disabled~.form-check-label, .form-check-input[disabled]~.form-check-label { color: #606060; } .table-bordered td { border: 1px solid #404040; } .table-bordered th { border: 1px solid #404040; } .nav-tabs .nav-link.active { color: #d9d9d9; background-color: #0000; border-color: #d9d9d9 #d9d9d9 #d9d9d9; } .h4 { color: #d9d9d9; } .close { color: #d9d9d9; } .close:hover { color: #fff; } .nav-tabs { border-bottom: 1px solid #666; } .wmde-markdown { color: #606060; } .wmde-markdown a { color: #17a2b8; } .btn-outline-secondary { border-color: #0000; color: #606060 } .btn-info { color: #606060; background-color: #0000; border-color: #0000; } .btn-info:hover { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-info:not(:disabled):not(.disabled):active { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .btn-info:focus { color: #17a2b8; background-color: #0000; border-color: #17a2b8; } .modal-title { position: absolute; left: 50%; transform: translate(-50%, -50%); margin-top: 2.5%; margin-right: -30%; }
unknown sendersent to0x499f4943…3001·#13,827,701·0x92c23775…a9b5a6
# Ethereal Phase An exploration between contrasting polarities and equilibrium inspired by electromagnetic waves. Each 'Ethereal Phase' is unique to the transaction that generated it. ## ![](https://bafkreihnyjputow7ckglqig7nytlupvb6zpq7b7h3fkgdkezwa22gq7mym.ipfs.dweb.link/) | Artist | [Audivit](https://audivit.xyz/) | |:------------|:-----------| | **Editions** | 500 | | **Editions License** | [NIFTY](https://www.nftlicense.org/) | | **Code License** | [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) | ## Metadata | Attribute | Possible Values | |:------------|:-----------| | Style |Ethereal, Glitch, Spectral | | Palette | Hero, Smart, Dupont, Funken, Spritz, Decca, Villain, Monochrome | | Crest | 0% to 100% / Amplitude detail | | Frequency | 0% to 100% / Wave cycles | | Flux | 0% to 100% / Wave flow force | | Asymmetry | 0% to 100% / Skew of shadow wave | Dwell Before Bang | Time delay based on transaction hash | | Compression | 0% to 100% / Max amplitude and wave border dimension | ## Extra Features | Input | Action | |:------------|:-----------| | Press key [ **s** ] | Save high resolution 4000x4000 pixels file | ## Source Code ``` let decPairs, TX, TXN, EID, DIM, inDIM, WIDTH, HEIGHT, render, seed, palette, clr; let pal1, pal2, pal3, pal4, pal5, pal6, pal7, pal8; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } } printMetadata = () => { if (decPairs[29] <= 170) { metadataObj.Style = "Ethereal"; } else if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { metadataObj.Style = "Glitch"; } else { metadataObj.Style = "Spectral"; } metadataObj.Palette = clr[0]; metadataObj.Crest = p.round(p.map(decPairs[9], 0, 255, 1, 100)) + "%"; metadataObj.Frequency = p.round(p.map(decPairs[15], 0, 255, 100, 1)) + "%"; metadataObj.Flux = p.round(p.map(decPairs[4], 0, 255, 1, 100)) + "%"; metadataObj.Asymmetry = p.round(p.map(decPairs[6], 0, 255, 1, 100)) + "%"; metadataObj.Compression = p.round(p.map(decPairs[7], 0, 255, 1, 100)) + "%"; metadataObj.transactionHash = TX; console.log("transaction: ", metadataObj.transactionHash); console.log("metadata: ", metadataObj); } p.keyTyped = () => { if (p.keyCode === 83) { render.save("Ethereal Phase #" + EID + ".tif"); } } p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); inDIM = 1000; getHashData(1); p.randomSeed(+props.transactionHash.substr(0, 10)); seed = p.random(0, 255); p.noiseSeed(seed); p.createCanvas(DIM, DIM); p.pixelDensity(2); render = p.createGraphics(inDIM, inDIM, p.WEBGL); render.setAttributes("alpha", false); render.setAttributes("antialias", true); render.pixelDensity(4); render.smooth(); render.rectMode(p.CENTER); let crest = p.map(decPairs[9], 0, 255, 1.0, 5.0); let frequency = p.map(decPairs[15], 0, 255, 2.0, 5.0); let flux = p.map(decPairs[4], 0, 255, 1.3, 1.5); let asymmetry = p.map(decPairs[6], 0, 255, 1.0, 1.2); let compression = p.map(decPairs[7], 0, 255, 0.3, 0.6); if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { pal2 = ["Villain", "#FFF9F0", "#28FFBF", "#28FFBF", "#030303"]; pal1 = ["Hero", "#03506F", "#FF2442", "#FFF9F0", "#03506F"]; pal4 = ["Villain", "#FFF9F0", "#28FFBF", "#28FFBF", "#030303"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Hero", "#03506F", "#FF2442", "#FFF9F0", "#03506F"]; pal8 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; } else if (decPairs[29] <= 170) { pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal2 = ["Smart", "#FFF9F0", "#00ADB5", "#FFF9F0", "#030303"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal4 = ["Spritz", "#FF7869", "#FFC57E", "#FFF9F0", "#FFC57E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Villain", "#28FFBF", "#030303", "#28FFBF", "#28FFBF"]; pal8 = ["Monochrome", "#FFF9F0", "#101010", "#FFF9F0", "#FFF9F0"]; } else { pal2 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal4 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal8 = ["Monochrome", "#FFF9F0", "#FFF9F0", "#FFF9F0", "#030303"]; } let PLT = [ pal1, pal1, pal1, pal1, pal2, pal2, pal2, pal2, pal3, pal3, pal3, pal3, pal4, pal4, pal4, pal4, pal5, pal5, pal5, pal5, pal6, pal6, pal6, pal6, pal7, pal7, pal7, pal7, pal8, pal8, pal8, pal8, ]; palette = p.round(p.map(decPairs[20], 1, 255, 0, 31)); clr = PLT[palette]; printMetadata(); console.log("noise_seed: ", seed); render.background(clr[1]); p.noiseDetail(crest); render.noFill(); render.strokeWeight(inDIM / 70); render.rectMode(p.CENTER); render.rect(0, 0, inDIM, inDIM); render.translate(-inDIM * 0.35, -inDIM * 0.35, -inDIM / 2); render.push(); render.translate(-inDIM * 0.7, 0, 0); render.beginShape(); for (let x = inDIM/5.5; x < inDIM*2.5; x++) { let nx = p.map(x, 100, -inDIM, frequency, 0); let y = inDIM * 0.95 * p.noise(nx / 2); let z = inDIM + p.noise(nx / 2); render.strokeWeight(inDIM * 0.06); render.stroke(0, 20); render.fill(clr[2]); render.vertex(x, y, 0); if (decPairs[29] <= 170) { render.background(clr[1]); render.strokeWeight(4); render.stroke(clr[1]+"20"); render.vertex(x * flux / 2, y / 3, -1000); render.vertex(x, y * 0.09, 0.0001); render.vertex(x / asymmetry, y * compression * 2, 0.0001); } else if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { render.background(clr[1]); render.vertex(x * flux, z / 3, 0.2); render.fill(p.random(clr)); render.strokeWeight(2); render.vertex(x, y * 0.3, 0.0001); render.vertex(x, y * compression / 1.5, 0.0001); } else { render.noFill(); render.stroke(clr[4] + "30") render.strokeWeight(2); render.vertex(x * flux, z / 3, 0); render.vertex(x, y * 0.4, 0); render.vertex(x / asymmetry, y * compression, 0); } } render.endShape(); render.pop(); render.fill(clr[3]); render.noStroke(); if( decPairs[29] <= 170){ render.translate(0, inDIM*0.3, -200); render.rect(inDIM / 3, inDIM * 1.75, inDIM * 2, inDIM * 4); } else { render.translate(0, -2, -200); render.rect(inDIM / 3, inDIM * 0.833, inDIM * 2, inDIM); } } p.redraw(); } p.draw = () => { p.image(render, 0, 0, DIM, DIM); p.noLoop(); } ```
Ethereal Phase# Ethereal Phase An exploration between contrasting polarities and equilibrium inspired by electromagnetic waves. Each 'Ethereal Phase' is unique to the transaction that generated it. ## ![](https://bafkreihnyjputow7ckglqig7nytlupvb6zpq7b7h3fkgdkezwa22gq7mym.ipfs.dweb.link/) | Artist | [Audivit](https://audivit.xyz/) | |:------------|:-----------| | **Editions** | 500 | | **Editions License** | [NIFTY](https://www.nftlicense.org/) | | **Code License** | [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) | ## Metadata | Attribute | Possible Values | |:------------|:-----------| | Style |Ethereal, Glitch, Spectral | | Palette | Hero, Smart, Dupont, Funken, Spritz, Decca, Villain, Monochrome | | Crest | 0% to 100% / Amplitude detail | | Frequency | 0% to 100% / Wave cycles | | Flux | 0% to 100% / Wave flow force | | Asymmetry | 0% to 100% / Skew of shadow wave | Dwell Before Bang | Time delay based on transaction hash | | Compression | 0% to 100% / Max amplitude and wave border dimension | ## Extra Features | Input | Action | |:------------|:-----------| | Press key [ **s** ] | Save high resolution 4000x4000 pixels file | ## Source Code ``` let decPairs, TX, TXN, EID, DIM, inDIM, WIDTH, HEIGHT, render, seed, palette, clr; let pal1, pal2, pal3, pal4, pal5, pal6, pal7, pal8; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } } printMetadata = () => { if (decPairs[29] <= 170) { metadataObj.Style = "Ethereal"; } else if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { metadataObj.Style = "Glitch"; } else { metadataObj.Style = "Spectral"; } metadataObj.Palette = clr[0]; metadataObj.Crest = p.round(p.map(decPairs[9], 0, 255, 1, 100)) + "%"; metadataObj.Frequency = p.round(p.map(decPairs[15], 0, 255, 100, 1)) + "%"; metadataObj.Flux = p.round(p.map(decPairs[4], 0, 255, 1, 100)) + "%"; metadataObj.Asymmetry = p.round(p.map(decPairs[6], 0, 255, 1, 100)) + "%"; metadataObj.Compression = p.round(p.map(decPairs[7], 0, 255, 1, 100)) + "%"; metadataObj.transactionHash = TX; console.log("transaction: ", metadataObj.transactionHash); console.log("metadata: ", metadataObj); } p.keyTyped = () => { if (p.keyCode === 83) { render.save("Ethereal Phase #" + EID + ".tif"); } } p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); inDIM = 1000; getHashData(1); p.randomSeed(+props.transactionHash.substr(0, 10)); seed = p.random(0, 255); p.noiseSeed(seed); p.createCanvas(DIM, DIM); p.pixelDensity(2); render = p.createGraphics(inDIM, inDIM, p.WEBGL); render.setAttributes("alpha", false); render.setAttributes("antialias", true); render.pixelDensity(4); render.smooth(); render.rectMode(p.CENTER); let crest = p.map(decPairs[9], 0, 255, 1.0, 5.0); let frequency = p.map(decPairs[15], 0, 255, 2.0, 5.0); let flux = p.map(decPairs[4], 0, 255, 1.3, 1.5); let asymmetry = p.map(decPairs[6], 0, 255, 1.0, 1.2); let compression = p.map(decPairs[7], 0, 255, 0.3, 0.6); if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { pal2 = ["Villain", "#FFF9F0", "#28FFBF", "#28FFBF", "#030303"]; pal1 = ["Hero", "#03506F", "#FF2442", "#FFF9F0", "#03506F"]; pal4 = ["Villain", "#FFF9F0", "#28FFBF", "#28FFBF", "#030303"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Hero", "#03506F", "#FF2442", "#FFF9F0", "#03506F"]; pal8 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; } else if (decPairs[29] <= 170) { pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal2 = ["Smart", "#FFF9F0", "#00ADB5", "#FFF9F0", "#030303"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal4 = ["Spritz", "#FF7869", "#FFC57E", "#FFF9F0", "#FFC57E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Villain", "#28FFBF", "#030303", "#28FFBF", "#28FFBF"]; pal8 = ["Monochrome", "#FFF9F0", "#101010", "#FFF9F0", "#FFF9F0"]; } else { pal2 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal4 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal8 = ["Monochrome", "#FFF9F0", "#FFF9F0", "#FFF9F0", "#030303"]; } let PLT = [ pal1, pal1, pal1, pal1, pal2, pal2, pal2, pal2, pal3, pal3, pal3, pal3, pal4, pal4, pal4, pal4, pal5, pal5, pal5, pal5, pal6, pal6, pal6, pal6, pal7, pal7, pal7, pal7, pal8, pal8, pal8, pal8, ]; palette = p.round(p.map(decPairs[20], 1, 255, 0, 31)); clr = PLT[palette]; printMetadata(); console.log("noise_seed: ", seed); render.background(clr[1]); p.noiseDetail(crest); render.noFill(); render.strokeWeight(inDIM / 70); render.rectMode(p.CENTER); render.rect(0, 0, inDIM, inDIM); render.translate(-inDIM * 0.35, -inDIM * 0.35, -inDIM / 2); render.push(); render.translate(-inDIM * 0.7, 0, 0); render.beginShape(); for (let x = inDIM/5.5; x < inDIM*2.5; x++) { let nx = p.map(x, 100, -inDIM, frequency, 0); let y = inDIM * 0.95 * p.noise(nx / 2); let z = inDIM + p.noise(nx / 2); render.strokeWeight(inDIM * 0.06); render.stroke(0, 20); render.fill(clr[2]); render.vertex(x, y, 0); if (decPairs[29] <= 170) { render.background(clr[1]); render.strokeWeight(4); render.stroke(clr[1]+"20"); render.vertex(x * flux / 2, y / 3, -1000); render.vertex(x, y * 0.09, 0.0001); render.vertex(x / asymmetry, y * compression * 2, 0.0001); } else if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { render.background(clr[1]); render.vertex(x * flux, z / 3, 0.2); render.fill(p.random(clr)); render.strokeWeight(2); render.vertex(x, y * 0.3, 0.0001); render.vertex(x, y * compression / 1.5, 0.0001); } else { render.noFill(); render.stroke(clr[4] + "30") render.strokeWeight(2); render.vertex(x * flux, z / 3, 0); render.vertex(x, y * 0.4, 0); render.vertex(x / asymmetry, y * compression, 0); } } render.endShape(); render.pop(); render.fill(clr[3]); render.noStroke(); if( decPairs[29] <= 170){ render.translate(0, inDIM*0.3, -200); render.rect(inDIM / 3, inDIM * 1.75, inDIM * 2, inDIM * 4); } else { render.translate(0, -2, -200); render.rect(inDIM / 3, inDIM * 0.833, inDIM * 2, inDIM); } } p.redraw(); } p.draw = () => { p.image(render, 0, 0, DIM, DIM); p.noLoop(); } ```
unknown sendersent to0x499f4943…3001·#13,822,094·0x16dc3aaf…4a9b4f
# Ethereal Phase An exploration between contrasting polarities and equilibrium inspired by electromagnetic waves. Each 'Ethereal Phase' is unique to the transaction that generated it. ## ![](https://bafkreihnyjputow7ckglqig7nytlupvb6zpq7b7h3fkgdkezwa22gq7mym.ipfs.dweb.link/) | Artist | [Audivit](https://audivit.xyz/) | |:------------|:-----------| | **Editions** | 500 | | **Editions License** | [NIFTY](https://www.nftlicense.org/) | | **Code License** | [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) | ## Metadata | Attribute | Possible Values | |:------------|:-----------| | Style |Ethereal, Glitch, Spectral | | Palette | Hero, Smart, Dupont, Funken, Spritz, Decca, Villain, Monochrome | | Crest | 0% to 100% / Amplitude detail | | Frequency | 0% to 100% / Wave cycles | | Flux | 0% to 100% / Wave flow force | | Asymmetry | 0% to 100% / Skew of shadow wave | Dwell Before Bang | Time delay based on transaction hash | | Compression | 0% to 100% / Max amplitude and wave border dimension | ## Extra Features | Input | Action | |:------------|:-----------| | Press key [ **s** ] | Save high resolution 4000x4000 pixels file | ## Source Code ``` let decPairs, TX, TXN, EID, DIM, inDIM, WIDTH, HEIGHT, render, seed, palette, clr; let pal1, pal2, pal3, pal4, pal5, pal6, pal7, pal8; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } } printMetadata = () => { if (decPairs[29] <= 170) { metadataObj.Style = "Ethereal"; } else if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { metadataObj.Style = "Glitch"; } else { metadataObj.Style = "Spectral"; } metadataObj.Palette = clr[0]; metadataObj.Crest = p.round(p.map(decPairs[9], 0, 255, 1, 100)) + "%"; metadataObj.Frequency = p.round(p.map(decPairs[15], 0, 255, 100, 1)) + "%"; metadataObj.Flux = p.round(p.map(decPairs[4], 0, 255, 1, 100)) + "%"; metadataObj.Asymmetry = p.round(p.map(decPairs[6], 0, 255, 1, 100)) + "%"; metadataObj.Compression = p.round(p.map(decPairs[7], 0, 255, 1, 100)) + "%"; metadataObj.transactionHash = TX; console.log("transaction: ", metadataObj.transactionHash); console.log("metadata: ", metadataObj); } p.keyTyped = () => { if (p.keyCode === 83) { render.save("Ethereal Phase #" + EID + ".tif"); } } p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); inDIM = 1000; getHashData(1); p.randomSeed(+props.transactionHash.substr(0, 10)); seed = p.random(0, 256); p.noiseSeed(seed); p.createCanvas(DIM, DIM); p.pixelDensity(2); render = p.createGraphics(inDIM, inDIM, p.WEBGL); render.setAttributes("alpha", false); render.setAttributes("antialias", true); render.pixelDensity(4); render.smooth(); render.rectMode(p.CENTER); let crest = p.map(decPairs[9], 0, 255, 1.0, 5.0); let frequency = p.map(decPairs[15], 0, 255, 2.0, 5.0); let flux = p.map(decPairs[4], 0, 255, 1.3, 1.5); let asymmetry = p.map(decPairs[6], 0, 255, 1.0, 1.2); let compression = p.map(decPairs[7], 0, 255, 0.3, 0.6); if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { pal2 = ["Villain", "#FFF9F0", "#28FFBF", "#28FFBF", "#030303"]; pal1 = ["Hero", "#03506F", "#FF2442", "#FFF9F0", "#03506F"]; pal4 = ["Villain", "#FFF9F0", "#28FFBF", "#28FFBF", "#030303"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Hero", "#03506F", "#FF2442", "#FFF9F0", "#03506F"]; pal8 = ["Decca", "#FFF9F0", "#FF4D6E", "#7F616D", "#FF4D6E"]; } else if (decPairs[29] <= 170) { pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal2 = ["Smart", "#FFF9F0", "#00ADB5", "#FFF9F0", "#030303"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal4 = ["Spritz", "#FF7869", "#FFC57E", "#FFF9F0", "#FFC57E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Villain", "#28FFBF", "#030303", "#28FFBF", "#28FFBF"]; pal8 = ["Monochrome", "#FFF9F0", "#101010", "#FFF9F0", "#FFF9F0"]; } else { pal2 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal4 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal8 = ["Monochrome", "#FFF9F0", "#FFF9F0", "#FFF9F0", "#030303"]; } let PLT = [ pal1, pal1, pal1, pal1, pal2, pal2, pal2, pal2, pal3, pal3, pal3, pal3, pal4, pal4, pal4, pal4, pal5, pal5, pal5, pal5, pal6, pal6, pal6, pal6, pal7, pal7, pal7, pal7, pal8, pal8, pal8, pal8, ]; palette = p.round(p.map(decPairs[20], 1, 255, 0, 31)); clr = PLT[palette]; printMetadata(); console.log("noise_seed: ", seed); render.background(clr[1]); p.noiseDetail(crest); render.noFill(); render.strokeWeight(inDIM / 70); render.rectMode(p.CENTER); render.rect(0, 0, inDIM, inDIM); render.translate(-inDIM * 0.35, -inDIM * 0.35, -inDIM / 2); render.push(); render.translate(-inDIM * 0.7, 0, 0); render.beginShape(); for (let x = inDIM/5.5; x < inDIM*2.5; x++) { let nx = p.map(x, 100, -inDIM, frequency, 0); let y = inDIM * 0.95 * p.noise(nx / 2); let z = inDIM + p.noise(nx / 2); render.strokeWeight(inDIM * 0.06); render.stroke(0, 20); render.fill(clr[2]); render.vertex(x, y, 0); if (decPairs[29] <= 170) { if (metadataObj.Palette === "Villain") { render.background(clr[3]); } else { render.background(clr[1]); } render.strokeWeight(4); render.stroke(clr[1]+"20"); render.vertex(x * flux / 2, y / 3, -1000); render.vertex(x, y * 0.09, 0.0001); render.vertex(x / asymmetry, y * compression * 2, 0.0001); } else if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { render.background(clr[1]); render.vertex(x * flux, z / 3, 0.2); render.fill(p.random(clr)); render.strokeWeight(2); render.vertex(x, y * 0.3, 0.0001); render.vertex(x, y * compression / 1.5, 0.0001); } else { render.noFill(); render.stroke(clr[4] + "30") render.strokeWeight(2); render.vertex(x * flux, z / 3, 0); render.vertex(x, y * 0.4, 0); render.vertex(x / asymmetry, y * compression, 0); } } render.endShape(); render.pop(); render.fill(clr[3]); render.noStroke(); if( decPairs[29] <= 170){ render.translate(0, inDIM*0.3, -200); render.rect(inDIM / 3, inDIM * 1.75, inDIM * 2, inDIM * 4); } else { render.translate(0, -2, -200); render.rect(inDIM / 3, inDIM * 0.833, inDIM * 2, inDIM); } } p.redraw(); } p.draw = () => { p.image(render, 0, 0, DIM, DIM); p.noLoop(); } ```
Ethereal Phase# Ethereal Phase An exploration between contrasting polarities and equilibrium inspired by electromagnetic waves. Each 'Ethereal Phase' is unique to the transaction that generated it. ## ![](https://bafkreihnyjputow7ckglqig7nytlupvb6zpq7b7h3fkgdkezwa22gq7mym.ipfs.dweb.link/) | Artist | [Audivit](https://audivit.xyz/) | |:------------|:-----------| | **Editions** | 500 | | **Editions License** | [NIFTY](https://www.nftlicense.org/) | | **Code License** | [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) | ## Metadata | Attribute | Possible Values | |:------------|:-----------| | Style |Ethereal, Glitch, Spectral | | Palette | Hero, Smart, Dupont, Funken, Spritz, Decca, Villain, Monochrome | | Crest | 0% to 100% / Amplitude detail | | Frequency | 0% to 100% / Wave cycles | | Flux | 0% to 100% / Wave flow force | | Asymmetry | 0% to 100% / Skew of shadow wave | Dwell Before Bang | Time delay based on transaction hash | | Compression | 0% to 100% / Max amplitude and wave border dimension | ## Extra Features | Input | Action | |:------------|:-----------| | Press key [ **s** ] | Save high resolution 4000x4000 pixels file | ## Source Code ``` let decPairs, TX, TXN, EID, DIM, inDIM, WIDTH, HEIGHT, render, seed, palette, clr; let pal1, pal2, pal3, pal4, pal5, pal6, pal7, pal8; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } } printMetadata = () => { if (decPairs[29] <= 170) { metadataObj.Style = "Ethereal"; } else if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { metadataObj.Style = "Glitch"; } else { metadataObj.Style = "Spectral"; } metadataObj.Palette = clr[0]; metadataObj.Crest = p.round(p.map(decPairs[9], 0, 255, 1, 100)) + "%"; metadataObj.Frequency = p.round(p.map(decPairs[15], 0, 255, 100, 1)) + "%"; metadataObj.Flux = p.round(p.map(decPairs[4], 0, 255, 1, 100)) + "%"; metadataObj.Asymmetry = p.round(p.map(decPairs[6], 0, 255, 1, 100)) + "%"; metadataObj.Compression = p.round(p.map(decPairs[7], 0, 255, 1, 100)) + "%"; metadataObj.transactionHash = TX; console.log("transaction: ", metadataObj.transactionHash); console.log("metadata: ", metadataObj); } p.keyTyped = () => { if (p.keyCode === 83) { render.save("Ethereal Phase #" + EID + ".tif"); } } p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); inDIM = 1000; getHashData(1); p.randomSeed(+props.transactionHash.substr(0, 10)); seed = p.random(0, 256); p.noiseSeed(seed); p.createCanvas(DIM, DIM); p.pixelDensity(2); render = p.createGraphics(inDIM, inDIM, p.WEBGL); render.setAttributes("alpha", false); render.setAttributes("antialias", true); render.pixelDensity(4); render.smooth(); render.rectMode(p.CENTER); let crest = p.map(decPairs[9], 0, 255, 1.0, 5.0); let frequency = p.map(decPairs[15], 0, 255, 2.0, 5.0); let flux = p.map(decPairs[4], 0, 255, 1.3, 1.5); let asymmetry = p.map(decPairs[6], 0, 255, 1.0, 1.2); let compression = p.map(decPairs[7], 0, 255, 0.3, 0.6); if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { pal2 = ["Villain", "#FFF9F0", "#28FFBF", "#28FFBF", "#030303"]; pal1 = ["Hero", "#03506F", "#FF2442", "#FFF9F0", "#03506F"]; pal4 = ["Villain", "#FFF9F0", "#28FFBF", "#28FFBF", "#030303"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Hero", "#03506F", "#FF2442", "#FFF9F0", "#03506F"]; pal8 = ["Decca", "#FFF9F0", "#FF4D6E", "#7F616D", "#FF4D6E"]; } else if (decPairs[29] <= 170) { pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal2 = ["Smart", "#FFF9F0", "#00ADB5", "#FFF9F0", "#030303"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal4 = ["Spritz", "#FF7869", "#FFC57E", "#FFF9F0", "#FFC57E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Villain", "#28FFBF", "#030303", "#28FFBF", "#28FFBF"]; pal8 = ["Monochrome", "#FFF9F0", "#101010", "#FFF9F0", "#FFF9F0"]; } else { pal2 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal4 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal8 = ["Monochrome", "#FFF9F0", "#FFF9F0", "#FFF9F0", "#030303"]; } let PLT = [ pal1, pal1, pal1, pal1, pal2, pal2, pal2, pal2, pal3, pal3, pal3, pal3, pal4, pal4, pal4, pal4, pal5, pal5, pal5, pal5, pal6, pal6, pal6, pal6, pal7, pal7, pal7, pal7, pal8, pal8, pal8, pal8, ]; palette = p.round(p.map(decPairs[20], 1, 255, 0, 31)); clr = PLT[palette]; printMetadata(); console.log("noise_seed: ", seed); render.background(clr[1]); p.noiseDetail(crest); render.noFill(); render.strokeWeight(inDIM / 70); render.rectMode(p.CENTER); render.rect(0, 0, inDIM, inDIM); render.translate(-inDIM * 0.35, -inDIM * 0.35, -inDIM / 2); render.push(); render.translate(-inDIM * 0.7, 0, 0); render.beginShape(); for (let x = inDIM/5.5; x < inDIM*2.5; x++) { let nx = p.map(x, 100, -inDIM, frequency, 0); let y = inDIM * 0.95 * p.noise(nx / 2); let z = inDIM + p.noise(nx / 2); render.strokeWeight(inDIM * 0.06); render.stroke(0, 20); render.fill(clr[2]); render.vertex(x, y, 0); if (decPairs[29] <= 170) { if (metadataObj.Palette === "Villain") { render.background(clr[3]); } else { render.background(clr[1]); } render.strokeWeight(4); render.stroke(clr[1]+"20"); render.vertex(x * flux / 2, y / 3, -1000); render.vertex(x, y * 0.09, 0.0001); render.vertex(x / asymmetry, y * compression * 2, 0.0001); } else if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { render.background(clr[1]); render.vertex(x * flux, z / 3, 0.2); render.fill(p.random(clr)); render.strokeWeight(2); render.vertex(x, y * 0.3, 0.0001); render.vertex(x, y * compression / 1.5, 0.0001); } else { render.noFill(); render.stroke(clr[4] + "30") render.strokeWeight(2); render.vertex(x * flux, z / 3, 0); render.vertex(x, y * 0.4, 0); render.vertex(x / asymmetry, y * compression, 0); } } render.endShape(); render.pop(); render.fill(clr[3]); render.noStroke(); if( decPairs[29] <= 170){ render.translate(0, inDIM*0.3, -200); render.rect(inDIM / 3, inDIM * 1.75, inDIM * 2, inDIM * 4); } else { render.translate(0, -2, -200); render.rect(inDIM / 3, inDIM * 0.833, inDIM * 2, inDIM); } } p.redraw(); } p.draw = () => { p.image(render, 0, 0, DIM, DIM); p.noLoop(); } ```
unknown sendersent to0x499f4943…3001·#13,821,944·0x73c91dc6…12c72d
# Ethereal Phase An exploration between contrasting polarities and equilibrium inspired by electromagnetic waves. Each 'Ethereal Phase' is unique to the transaction that generated it. ## ![](https://bafkreihnyjputow7ckglqig7nytlupvb6zpq7b7h3fkgdkezwa22gq7mym.ipfs.dweb.link/) | Artist | [Audivit](https://audivit.xyz/) | |:------------|:-----------| | **Editions** | 500 | | **Editions License** | [NIFTY](https://www.nftlicense.org/) | | **Code License** | [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) | ## Metadata | Attribute | Possible Values | |:------------|:-----------| | Style |Ethereal, Glitch, Spectral | | Palette | Hero, Smart, Dupont, Funken, Spritz, Decca, Villain, Monochrome | | Crest | 0% to 100% / Amplitude detail | | Frequency | 0% to 100% / Wave cycles | | Flux | 0% to 100% / Wave flow force | | Asymmetry | 0% to 100% / Skew of shadow wave | Dwell Before Bang | Time delay based on transaction hash | | Compression | 0% to 100% / Max amplitude and wave border dimension | ## Extra Features | Input | Action | |:------------|:-----------| | Press key [ **s** ] | Save high resolution 4000x4000 pixels file | ## Source Code ``` let decPairs, TX, TXN, EID, DIM, inDIM, WIDTH, HEIGHT, render, seed, palette, clr; let pal1, pal2, pal3, pal4, pal5, pal6, pal7, pal8; let metadataObj = {}; getHashData = (transactionID) => { let transactions = [TX]; let transactionForTokenId = transactionID - 1; let tokenData = { hash: transactions[transactionForTokenId] }; decPairs = []; for (let i = 0; i < 32; i++) { decPairs.push(parseInt(tokenData.hash.substr(2 * i + 2, 2), 16)); } } printMetadata = () => { if (decPairs[29] <= 150) { metadataObj.Style = "Ethereal"; } else if (decPairs[29] > 200 && decPairs[5] <= 150 && decPairs[10] >= 100) { metadataObj.Style = "Glitch"; } else { metadataObj.Style = "Spectral"; } metadataObj.Palette = clr[0]; metadataObj.Crest = p.round(p.map(decPairs[9], 0, 255, 1, 100)) + "%"; metadataObj.Frequency = p.round(p.map(decPairs[15], 0, 255, 100, 1)) + "%"; metadataObj.Flux = p.round(p.map(decPairs[4], 0, 255, 1, 100)) + "%"; metadataObj.Asymmetry = p.round(p.map(decPairs[6], 0, 255, 1, 100)) + "%"; metadataObj.Compression = p.round(p.map(decPairs[7], 0, 255, 1, 100)) + "%"; metadataObj.transactionHash = TX; console.log("transaction: ", metadataObj.transactionHash); console.log("metadata: ", metadataObj); } p.keyTyped = () => { if (p.keyCode === 83) { render.save("Ethereal Phase #" + EID + ".tif"); } } p.myCustomRedrawAccordingToNewPropsHandler = (props) => { if (props.transactionHash && props.square) { TX = props.transactionHash; TXN = props.tokenId; EID = props.editionId; WIDTH = window.innerWidth / props.square * 0.8; HEIGHT = window.innerHeight / props.square * 0.8; DIM = Math.min(WIDTH, HEIGHT); inDIM = 1000; getHashData(1); p.randomSeed(+props.transactionHash.substr(0, 10)); seed = p.random(0, 256); p.noiseSeed(seed); p.createCanvas(DIM, DIM); p.pixelDensity(2); render = p.createGraphics(inDIM, inDIM, p.WEBGL); render.setAttributes("alpha", false); render.setAttributes("antialias", true); render.pixelDensity(4); render.smooth(); render.rectMode(p.CENTER); let crest = p.map(decPairs[9], 0, 255, 1.0, 5.0); let frequency = p.map(decPairs[15], 0, 255, 2.0, 5.0); let flux = p.map(decPairs[4], 0, 255, 1.3, 1.5); let asymmetry = p.map(decPairs[6], 0, 255, 1.0, 1.2); let compression = p.map(decPairs[7], 0, 255, 0.3, 0.6); if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { pal2 = ["Villain", "#FFF9F0", "#28FFBF", "#28FFBF", "#030303"]; pal1 = ["Hero", "#03506F", "#FF2442", "#FFF9F0", "#03506F"]; pal4 = ["Villain", "#FFF9F0", "#28FFBF", "#28FFBF", "#030303"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Hero", "#03506F", "#FF2442", "#FFF9F0", "#03506F"]; pal8 = ["Decca", "#FFF9F0", "#FF4D6E", "#7F616D", "#FF4D6E"]; } else if (decPairs[29] <= 170) { pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal2 = ["Smart", "#FFF9F0", "#00ADB5", "#FFF9F0", "#030303"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal4 = ["Spritz", "#FF7869", "#FFC57E", "#FFF9F0", "#FFC57E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Villain", "#28FFBF", "#030303", "#28FFBF", "#28FFBF"]; pal8 = ["Monochrome", "#FFF9F0", "#101010", "#FFF9F0", "#FFF9F0"]; } else { pal2 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal1 = ["Hero", "#FF2442", "#03506F", "#FFF9F0", "#03506F"]; pal4 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal5 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal6 = ["Decca", "#7F616D", "#FF4D6E", "#FFF9F0", "#FF4D6E"]; pal3 = ["Dupont", "#6D9598", "#FF2442", "#FFF9F0", "#FF2442"]; pal7 = ["Funken", "#4E3D53", "#FFB200", "#FFF9F0", "#FFB200"]; pal8 = ["Monochrome", "#FFF9F0", "#FFF9F0", "#FFF9F0", "#030303"]; } let PLT = [ pal1, pal1, pal1, pal1, pal2, pal2, pal2, pal2, pal3, pal3, pal3, pal3, pal4, pal4, pal4, pal4, pal5, pal5, pal5, pal5, pal6, pal6, pal6, pal6, pal7, pal7, pal7, pal7, pal8, pal8, pal8, pal8, ]; palette = p.round(p.map(decPairs[20], 1, 255, 0, 31)); clr = PLT[palette]; printMetadata(); console.log("noise_seed: ", seed); render.background(clr[1]); p.noiseDetail(crest); render.noFill(); render.strokeWeight(inDIM / 70); render.rectMode(p.CENTER); render.rect(0, 0, inDIM, inDIM); render.translate(-inDIM * 0.35, -inDIM * 0.35, -inDIM / 2); render.push(); render.translate(-inDIM * 0.7, 0, 0); render.beginShape(); for (let x = inDIM/5.5; x < inDIM*2.5; x++) { let nx = p.map(x, 100, -inDIM, frequency, 0); let y = inDIM * 0.95 * p.noise(nx / 2); let z = inDIM + p.noise(nx / 2); render.strokeWeight(inDIM * 0.06); render.stroke(0, 20); render.fill(clr[2]); render.vertex(x, y, 0); if (decPairs[29] <= 170) { if (metadataObj.Palette === "Villain") { render.background(clr[3]); } else { render.background(clr[1]); } render.strokeWeight(4); render.stroke(clr[1]+"20"); render.vertex(x * flux / 2, y / 3, -1000); render.vertex(x, y * 0.09, 0.0001); render.vertex(x / asymmetry, y * compression * 2, 0.0001); } else if (decPairs[29] > 220 && decPairs[5] <= 150 && decPairs[10] >= 100) { render.background(clr[1]); render.vertex(x * flux, z / 3, 0.2); render.fill(p.random(clr)); render.strokeWeight(2); render.vertex(x, y * 0.3, 0.0001); render.vertex(x, y * compression / 1.5, 0.0001); } else { render.noFill(); render.stroke(clr[4] + "30") render.strokeWeight(2); render.vertex(x * flux, z / 3, 0); render.vertex(x, y * 0.4, 0); render.vertex(x / asymmetry, y * compression, 0); } } render.endShape(); render.pop(); render.fill(clr[3]); render.noStroke(); if( decPairs[29] <= 170){ render.translate(0, inDIM*0.3, -200); render.rect(inDIM / 3, inDIM * 1.75, inDIM * 2, inDIM * 4); } else { render.translate(0, -2, -200); render.rect(inDIM / 3, inDIM * 0.833, inDIM * 2, inDIM); } } p.redraw(); } p.draw = () => { p.image(render, 0, 0, DIM, DIM); p.noLoop(); } ```
1-50 of 57