p5.js 彙整 | Creative Coding TW - 互動程式創作台灣站 https://creativecoding.in/tag/p5-js/ 蒐集互動設計案例、教學與業界資源,幫助你一起進入互動程式創作的產業 Wed, 05 Jul 2023 04:48:58 +0000 zh-TW hourly 1 https://wordpress.org/?v=6.2.2 https://creativecoding.in/wp-content/uploads/2022/03/cropped-cct-logo-icon-2-32x32.png p5.js 彙整 | Creative Coding TW - 互動程式創作台灣站 https://creativecoding.in/tag/p5-js/ 32 32 【p5.js 程式創作】Soul Fish 數位永恆生命的靈魂魚 – 製作流程 https://creativecoding.in/2023/03/02/soul-fish-process/ Thu, 02 Mar 2023 08:59:45 +0000 https://creativecoding.in/?p=3510 此篇文章是前陣子發行的作品 - 靈魂魚 - 背後的製作流程,關於如何使用程式來創作一隻夢幻的數位生物!靈魂魚的作品是用理性的程式創造生命感的探索,也融合了互動生成音樂與視覺,是在互動型 NFT 邊界上的探索之作 。

這篇文章 【p5.js 程式創作】Soul Fish 數位永恆生命的靈魂魚 – 製作流程 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
本次內容將會以前陣子發布的作品「靈魂魚」作為主題,分為創作故事製作流程分別介紹,此篇主要是製作流程的分享。靈魂魚的作品是如何使用理性的程式創造生命感的探索,也融合了互動生成音樂與視覺,也是在互動型 NFT 邊界上的探索之作 。

靈魂魚的創作故事:p5.js 程式創作 | Soul Fish 數位永恆生命的靈魂魚 – 創作故事

老闆在直播中分享五月份至美國紐約參加研討會的感想,研討會上有像是 6529 等創作家在研討會上做分享交流。讓老闆想到,最一開始接觸 NFT 是因為創作,從創作上也有看到像是 Pak 這樣藝術家的作品,純粹、好玩卻也附有商業性價值,因此開始接觸區塊鏈,參加像是 Consesus 這樣的區塊鏈相關活動。雖然近期不論國內與國外,對於虛擬世界的交易開始有些反感的聲浪出現,但也因此某些事項反而逆勢而起,像是在 Art Blocks 上購買生成式藝術的趨勢逐漸成長。在創作上,老闆也建議,雖然觀眾在某一期間追求的風格會相似,導致大多創作人會往同風格進行創作,但也不要忘了,走出自己的路線才最有可能被記憶紀錄。

為什麼會選靈魂魚當主題與創作概念?

在準備個展期間,有關看到一部與金魚相關影集,觀察到金魚本身的姿態,因此以此為創作靈感來源。取名自老闆的姓名,靈魂魚誕生於虛空之中,由各式各樣的情緒凝結在深海中誕生,他靜靜的在那邊帶來平靜,自己游著,有些靈魂與全身長滿了亮麗的鱗片,有些則默默地緩緩地飄動,身軀幾乎消逝於深海的光線中。

p5.js 靈魂魚實作示範

創作的初始概念,先以 Shader 呈現(下方圖示參考),使用扭曲線條模擬金魚尾巴線條的流動。 Shader 本來是以點到點之間連成的線條組成,在其後,老闆應用 Sin 波的原理,將 Shader 線條隨著波長座移動變化。

再來進到金魚的輪廓姿態,下方第一版的金魚創作其實可以看出大致上金魚的形狀,以及圖樣上模糊的效果,呈現靈魂的感覺。

將金魚的輪廓以線條構出後,發現從身體上半步到尾巴下半部的線條,呈現 Sin 波的形狀,就以多重 Sin 波線條組成第一版金魚。老闆也實際操作一次供大家參考,首先,由左到右畫出連成一條線。

function setup() {
  createCanvas(windowWidth, windowHeight);

  background(100);
}

function draw() {
  background(255);

  beginShape();

  for (x = 0; x < width; x += 20) {
    stroke(0);

    strokeWeight(5);

    vertex(x, height / 2);
  }

  endShape();
}

當線條畫出來之後,如何形成金魚的輪廓形狀呢?由左到右以及上下的的曲線變化,這時就需要加上 Sin 波,呈現出魚的一半輪廓。

function draw() {
  background(255);

  beginShape();

  for (x = 0; x < width; x += 20) {
    let ang = map(x, 0, width, 0, PI * 1.5);

    let y = height / 2 + (sin(ang) * height) / 5;

    stroke(0);

    strokeWeight(5);

    vertex(x, y);

    circle(x, y, 20);
  }

  endShape();
}

得出單一線條後,以相反方向再繪製出另一條線,將完整金魚的輪廓勾勒出來。

function draw() {
  background(255);

  translate(width / 2, height / 2);

  scale(0.8);

  translate(-width / 2, -height / 2);

  for (direction = -1; direction <= 1; direction += 1) {
    beginShape();

    stroke(0);

    noFill();

    strokeWeight(5);

    for (x = 0; x < width; x += 20) {
      let ang = map(x, 0, width, 0, PI * 1.5);

      let y = height / 2 + ((sin(ang) * height) / 5) * direction;

      vertex(x, y);

      circle(x, y, 20);
    }

    endShape();
  }
}
第一版金魚圖示

上述大略是第一版金魚的組成方式,但老闆認為於本身可以再更活潑的方式做律動,於是進行第二版的製作。第二版的示範操作,著重在呈現魚尾巴,如雨水般的流動感外,也將除了輪廓外的線條作範例,呈現擁有底色與動態的尾巴。

function draw() {
  background(255);

  translate(width / 2, height / 2);

  scale(0.8);

  translate(-width / 2, -height / 2);

  for (direction = -1; direction <= 1; direction += 0.2) {
    beginShape();

    stroke(0);

    noFill();

    strokeWeight(5);

    for (x = 0; x < width; x += 20) {
      let ang = map(x, 0, width, 0, PI * 1.5);

      let y = height / 2 + ((sin(ang) * height) / 5) * direction;

      let xx = x;

      if (ang > PI) {
        xx += (ang - PI) * 50;

        xx += sin(xx / 40 + frameCount / 50) * 50;
      } else {
        if (x % 40) {
          arc(xx, y, 100, 100, -PI / 4, PI / 4);
        }
      }

      noStroke();

      vertex(xx, y);

      fill(255, 0, 0, 90);

      arc(xx, y, 5, 5, -PI / 2, PI / 2);

      circle(x, y, 1);
    }

    endShape();
  }
}
第二版金魚圖示

反覆編輯的過程中,從第一、第二版次的基本輪廓呈現,到了第三版大面積的色彩變化(下方圖示參考),以及最後,第四版層疊了鱗片出現發光發亮的質感(下方圖示參考),再繼續堆疊後,變會呈現帶有霧霧的靈魂感覺。這樣的靈魂質感,是如何執行的呢?

第三版金魚圖示
第四版金魚圖示

在第四版金魚上,主要強調使用 blendMode,並進行疊光 screen,就能發現微發光的質感。而後建議以 shader 再去修飾外型,下方程式與圖片為示範範例。

function draw() {
  push();

  beginShape();

  background(0);

  translate(width / 2, height / 2);

  scale(0.8);

  translate(-width / 2, -height / 2);

  blendMode(SCREEN);

  for (direction = -1; direction <= 1; direction += 0.2) {
    noFill();

    strokeWeight(5);

    for (x = 0; x < width; x += 20) {
      let ang = map(x, 0, width, 0, PI * 1.5);

      let y = height / 2 + ((sin(ang) * height) / 5) * direction;

      let xx = x;

      if (ang > PI) {
        xx += (ang - PI) * 50;

        xx += sin(xx / 40 + frameCount / 50) * 50;
      } else {
        if (x % 40) {
          arc(xx, y, 150, 150, -PI / 4, PI / 4);
        }
      }

      noStroke();

      vertex(xx, y);

      fill(255, x / 2, 0, 100);

      arc(xx, y, 5, 5, -PI / 2, PI / 2);

      circle(xx, y, 5);
    }
  }

  pop();
}
第四版金魚圖示

特殊技法介紹

在完成了基本霧面質感金魚後,老闆進到 shader 技法教學。在這邊使用到 shader 的原因是想呈現發亮的螢光感,以及 shader 特有的毛邊質感。在背景中的流體顏色,也是應用 shader去達到此效果,而這樣的概念從老闆早期作品中,就陸續有不同的變化。像是如同宇宙星河般的效果,堆疊的彩色雲層。這樣雲層的概念,又是取自於老闆本身的創作,純粹使用 p5.js 繪製出的雲層效果(下方圖示)

宇宙星河作品變化

從 p5.js 單點渲染,到 shader 即時動態渲染,後面更進化到會滑動的線條,甚至在線條與線條間也出現反光感的效果,呈現細緻,類似地層沉積剖面的質感,也應用這樣的技法呈現在靈魂魚的背景中。

背景範例

老闆也提到,他認為目前應用 shader 最極致的呈現是如同金屬液態的質感創作(下方圖示)

金屬液態圖示

要呈現這樣的效果,就是將背景進行扭曲。像此圖示最初是一張漸層平面圖(下方圖示),形成原理是以多個點點構成一張圖的基底平面,每個點點會有著大小不同的漩渦,再以每個點點在圖上偏移的角度要是多少,與漩渦的方向還有角度構出。

漸層平面圖

不過老闆也說,雖然 shader 很有趣,作品彈性高,但缺點是每次遇到不同型態的需求都會需要重新造輪子,所以目前實際手寫 shader 的人不多,通常都還是以 3D 軟體執行,或是使用 Unreal、Unity 和 shader note editor 等等。以 node based shader editor 為範例,一樣也是經由不同的部分進行疊加,但不一樣的是,已經進行了模組化,讓使用上更快速簡便。

(截圖自 node based shader editor

讓我們重新回到作品靈魂魚的技法上吧!

在創作金魚本體時,我們有使用到一個叫做 blendmode 的融合選項,在 blendmode 中其實有兩種不同的方式能呈現疊色。第一個就是上述有提及的 blendmode(SCREEN),這一項變化就是讓疊色時出現螢光的效果,再來第二個就是 blendmode(MULTIPLY),而這線就是將疊色效果呈現墨水的質感。以下使用範例是以多線條的方式,進行 blendmode(MULTIPLY),所呈現出的細緻金魚。

疊色技法金魚(截圖自影片

以魚鰭來舉例,下方圖示可以看到老闆簡單的說明

金魚魚鰭說明(截圖自影片

魚鰭是依據金魚身體上半部的輪廓點延伸,設定在特定距離上做不同點,再依這些點連成一條又一條組合成魚鰭的線。不過,也因為以線條作為主要組成金魚的來源,所以效能上並不是非常理想。在最終完成品上,可以觀察到,除了金魚本身與線條外,內部也有像是生命線般,會在魚擺動時跟著起舞,這個部分是老闆使用物理模擬操作。在 p5.js 中, Example 中有一個系列叫做 Simulation 物理模擬,在這系列裡,像是 chain,此功能就是將特定點與點之間連成線外,也能進行動態移動,除了作品上,老闆也將其運用在官網上面,將視覺衝擊更加優化。

官網應用(截圖自墨雨設計官網

作品在電腦上完成後,老闆也有將靈魂魚藉由台北藝術中心舉辦的活動,大範圍的投影在藝術中心外,最顯眼的位置做展示。

台北藝術中心展示(截圖自老闆推特

生成式音樂

在圖樣不斷變化的過程中,老闆也在本次創作中增加入生成式音樂做襯托,讓音樂配合游動的靈魂魚產生不同音調。不過生程式藝術結合音樂輔助呈現這個部分,目前是 fxhash 才提供可上架的服務,因為生成式音樂本身檔案較大,像是 artblocks 目前無法接收過大的夾帶檔案。靈魂魚的生成式音樂是將每一節的音樂 sample 檔案與空白格做不同的排列組合,使用 tone.sampler 做完整拼接,拼接完再套用 bpm 讓整段旋律有休止或是不同的音樂變化,最後,再以 reverb 營造具有回音的空間感,讓我們在觀看、收聽時,能夠聽到一段又一段的美妙旋律。

生成式音樂撰寫(截圖自影片

如何將作品上架 fxhash

接下來,我們進入統整上 fxhash 的流程,老闆習慣當作品在 openprocessing 修整到一定程度後,就回到 VsCode 上,使用 fxhash 的模板進行整合。 fxhash 的模板會提供一個固定的亂數,引導你如何使用這套亂數,讓導出的結果都是一樣的(參考連結),而 fxrand 就是提供的亂數名稱,只要給它特定的 hash,就會產生特定的 random。在 VsCode 編輯上,老闆就會針對例如說 features 的這個選項進行編輯。為何是 features 呢?在將生成式藝術上架到 fxhash 時,都會需要標記每一個作品產出的相關特徵,而老闆通常會使用 renderfeatureas() 的方式,將特徵全都渲染出來,但也有時候會因為抓取的值與原本創作呈現的值其實是不同的狀況,這時候就會需要再根據一定的規則算出,我們最終要顯示的是什麼。這樣,在告訴收藏家時,也能以較通俗的說明讓藏家了解作品本身,除了意象外的特徵內容。

fxhash 模板介面(截圖自影片
fxhash 模板 feature 介面(截圖自影片

為了應對較複雜的上架流程,老闆製作了一個名為「previewer」的專案,這個專案可以印出所有生成式藝術作品中的渲染結果。當今天一個作品渲染出了一千張圖片後,這個功能會將這一千張圖片綜合在一個小型網頁上,然後可以在此網頁上進行不同種類的過濾,以進行每一張渲染圖片的檢查。在上架方面,老闆分享了他在fxhash上架時遇到的問題,包括價格、數量和最初設定的販售名單和策略之間的差異,因此他建議同學們在這方面要多加注意。此外,他還提到了作品呈現方面的要求,希望之後製作的每一件作品都能具有足夠的精采度。在前置作業完成後,老闆帶領我們稍微講解了白名單處理流程。在NFT世界中,每當我們購買一件項目,都需要鑄造並購買NFT,但通常NFT在販售時會有數量限制,並非所有人都能鑄造,這就是「白名單」的概念。白名單主要是指只有在名單內的購買方才能鑄造項目,因為他們已經預先保留在名單中了。因此,賣方需要在fxhash上設定白名單流程,首先,要去「mint generation token」瀏覽要上傳的解壓縮檔案,然後按照每個步驟的要求進行上傳或選項勾選,最後,確定上架後就完成了。老闆還建議上架最好一次上完,並且數量控制在256到500之間,這樣對於購買單項作品的買家再繼續購入,帶來的後續效益會更大。老闆也順勢舉例近期執行的「FabDAO 百岳山脈計畫 」,此計畫除了老闆外也與多位藝術家合作,執行公益的 NFT 計畫。在計畫中,老闆的作品便是以 Shader 執行,也示範有無 Shader 的差異。作品內容都十分精彩,有興趣的同學都歡迎至官網做更進一步的了解。

新作品介紹

新作品呈現如同粒子搬形成的圖畫,經由 Shader 再去製造出邊緣不規則的狀態。

最初作品構想(參考連結

作品經反覆編輯製作後,以2D 生成3D 的方向勾勒出虛擬世界感。而此項目將會與老闆致英國作展出。展出的地方名為 Outernet London,主要就是在進行生成式藝術展示的展館,那到時至英國後,老闆也會與共同展出的藝術家們合作交流,後續有任何更新也都會開直播影片與大家分享心得。

預計展出的圖片參考(截圖自影片

總結

在最後也觀眾提出有關近期蔚為風潮,MidJourney – AI 生成藝術的相關問題,老闆也對於這個興起的議題提出了一些看法。其實,不論是生成式藝術與 AI 生成藝術都是經由更快速與便利,與傳統手繪不同的數位化方法進行藝術創作,個人特色或是創意能不能持續表現,才是更值得被記錄的,也希望大家都能勇於嘗試不同的方法做各式各樣的藝術創作探索。

如果想要更深入的了解,目前有與李婷婷講師合開針對 Web3的相關課程,也歡迎直接訂閱老闆的 Youtube 頻道,時不時會有直播 live coding或是近期有持續更新像是 Web3相關影片等等,都歡迎加入並進行踴躍發問喔!

以上就是本次影片和文章的介紹啦!別忘了加入互動藝術程式創作入門課程開始學習吧!還有不要忘了追蹤老闆 Twitter 和訂閱老闆,來點寇汀吧。Boss, CODING please. Youtube 頻道隨時補充新媒體藝術的養份,讓我們一起探索這多元的世界吧!下次見~

此篇直播筆記由幫手熊柑協助整理

這篇文章 【p5.js 程式創作】Soul Fish 數位永恆生命的靈魂魚 – 製作流程 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
【p5.js 程式創作】Soul Fish 數位永恆生命的靈魂魚 – 創作故事 https://creativecoding.in/2023/01/30/soul-fish-story/ Mon, 30 Jan 2023 10:42:09 +0000 https://creativecoding.in/?p=3475 在這篇文章中,哲宇想跟大家介紹為什麼會製作靈魂魚,如何透過多重感官觀賞作品,他的完整故事與設計,以及在視覺跟聽覺和互動上的巧思,曾展出的空間形式和未來期待繼續發展的方向!

這篇文章 【p5.js 程式創作】Soul Fish 數位永恆生命的靈魂魚 – 創作故事 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
本次內容將會以前陣子發布的作品「靈魂魚」作為主題,分為創作故事製作流程分別介紹,此篇主要是製作流程的分享。靈魂魚的作品是如何使用理性的程式創造生命感的探索,也融合了互動生成音樂與視覺,也是在互動型 NFT 邊界上的探索之作 。

靈魂魚的製作過程:【p5.js 程式創作】Soul Fish 數位永恆生命的靈魂魚 – 製作過程

SoulFish #183

大家好,我是生成式藝術家吳哲宇,四五年前我開始製作動態的數位藝術,像是互動網站、平面設計等開始對踏入互動設計的領域,後來研究所到了紐約 NYU 互動媒體學系讀書,因此認識了 Creative Coding 這個領域而深深著迷,發現程式也有很多的可能性,不僅是為了設計或是達成目標而存在,而是寫程式的本身即是藝術

在這篇文章中,我想跟大家介紹為什麼會製作靈魂魚,如何透過多重感官觀賞作品,他的完整故事與設計,以及在視覺跟聽覺和互動上的巧思,曾展出的空間形式和未來期待繼續發展的方向!

Soul Fish Fxhash 作品專案連結 ( https://www.fxhash.xyz/generative/slug/soulfish )

我曾製作了很多互動型態的作品,像是 CryptoPochi 或是 Seahams,也曾在 Foundation 平台上嘗試傳統繪畫手法探索美術館質感的作品,我發現我最喜歡的是能夠製造有機的狀態,意味著作品的本身的隨機性除了表現在初始屬性之外,也隨著動態生長讓作品在執行的過程中有一定的隨機度,例如粒子的軌跡是由每個時刻的亂數累積決定的,最後繪製成一個完整的作品,得益於亂數原理與現在的區塊鏈技術,我們能夠確保在同一個數位作品中,完美而精準的重現隨機過程,這是我覺得最迷人的部分。

永恆的生命是什麼樣子?

剛開始想到製作靈魂魚的時候,我的靈感來自於深海生物,他們的形體透明的浮游在水中,通常會有一些自己的發光器官來照亮周圍的環境,我覺得這樣的有機感很迷人,也很喜歡一些像是光暈、觸鬚般物理上的物理模擬動態,因此想來以深海魚作為主題來創作一個作品,我想要創造出深海中精細結構帶有透明狀態的魚的感覺,這些魚像是靈魂似的漂浮在幽暗的水域中,因此取名為「靈魂魚」,這些魚能夠永恆的存在與游動,不跟著時間的進行而逝去。

靈魂魚其實也同時取名自我自己的名字 – 吳哲宇最後一個字,他們靈魂魚誕生於虛空之中,在各式各樣的情緒凝結,在深海中誕生,他靜靜的在那邊帶來平靜,自己游著,有些靈魂與全身長滿了亮麗的鱗片,有些則默默地緩緩地飄動,身軀幾乎消逝於深海的光線中。

如何去繪製魚柔軟有機的形體呢?

在製作初期,我仔細的觀察後發現,魚的形狀類似於一個波(sin/cos)的前半部所有狀態疊加的形狀,所以如果我把一條波的線條擷取出來,上下透過不同的比例複製重複,就能夠繪製出外觀。

Sin / Cos 波構成魚的線條

過程中除了計算一個一個點的精確位置之外,也確保不會死板的加入了不同頻率,也就是不同大小的波來建構形體,如果加上了時間函數讓他們慢慢的交錯移動,就能夠形成魚的動態質感。每一個點都有額外再經過噪聲跟波形處理,來創造靈魂般不穩定的形體跟質感,最後再加上從身體到尾部的波狀動態,產生出空間中尾巴來回擺動的效果。

使用波狀函數、自然噪聲以及物理模擬

我製作的第一個版本看起來像實心的卡通魚,接下來逐漸改的透明、加上shader背景,讓所有的線條跟筆觸在繪製時,能夠帶有透明度的重疊,也逐漸加入細節 像是魚骨頭、鬍鬚、魚鰭、尾巴等設計,為了創造出有機感,我混合了材質、形狀跟很多的結構設計,包括中心的魚骨頭一節一節的可以動、生命線的鬍鬚是由20幾個點透過鎖鏈物理模擬的形式來控制,與尾巴跟魚鰭的薄膜每一條線條,都透過精密的計算擺動隨機性的設計,每一隻魚都會有不同的線條數量、大小跟身體結構。

顏色設計上,我讓魚可以橫跨所有的光譜,並且在每一隻魚中,都會有類似泡泡表面的色偏質感,也讓他們的顏色更為有機,隨機性的產生了所有的顏色數值之後,我讓他們再對應到相對的顏色的名字。顏色上會有兩個主要的顏色過渡來建構一隻魚的形體,來確保能夠產生和諧漂亮的漸層,我想要作品呈現出類似極光般的質感以及擁有漂亮的光暈,因此用不同的顏色模式重疊了幾次混合,模擬用光線作為筆觸來去繪製靈魂般的小生物

光線色偏的效果 Soul Fish #123

另外也有一些魚是白色背景的,小時候的我很喜歡生物科學,不同於黑色背景螢光的效果,白色的背景更像是顏料暈染,也很像小時候在做標本時,會將植物的組織切片染色,在顯微鏡底下看到的狀態。

Soul Fish #302
SoulFish #3

背景中有什麼樣的巧思?

在靈魂魚的系列中,有三款主要的背景 – 虛空、波動跟深海,大部分的魚都是虛空背景,能夠讓你在投影或黑暗的空間感受時,能最直觀的感受到作品的神聖感,會將焦點全部都放在魚的身上。波動的背景來自於以前的另一個作品 – 星雲 (220413 Nebula Drift),是由 GPU計算所有的星星之後,動態的扭曲來創造流動的銀河。最後一種背景深海,是模擬由上照下的一束光線穿進深海的質感,在者三款背景中,都有額外加入一些灰塵跟懸浮物,會緩緩地在水中漂動,並會跟著音樂閃爍。

220413 Nebula Drift

如何搭配視覺產生有機的聲音系統設計?

在靈魂魚的作品中,聲音是很重要的部分,在前幾個作品如 Sliderverse 或是 Soul sea 中,我都有嘗試使用 Web audio api 的方式來合成聲響,而在 Soul Fish 這個作品中,我使用了一組鋼琴的 Sample,並在作品開始執行的時候,確定這個作品的和弦進行和旋律線,因為是動態生成的音樂,每一隻魚的旋律線都是獨一無二的,會搭配較高的弦律線與較低的伴奏聲音來構築曲子,每一隻魚都是旋律自動機,能夠合成屬於他的曲調。

SoulFish #59

就像是 生成式視覺一樣,生成式音樂的概念鮮為人知,是打散一首歌的長度跟制式編曲,不是根據既有的譜面來演奏,而是透過規則來去建構音符和和弦的進行,因此可以產生永不停止可以持續生成而有機的聲音編制,在 開啟基因 (B) 的模式中,你能夠看到每隻魚都有自己對應的和弦,是自己的旋律不斷的重複的自動機,另外泡泡破掉時,也可以聽到他觸發高音的鋼琴音符,這也對應到我當初對於作品的期望,是能夠創造視覺與聽覺的詩意同步,當這些所有的感官整合起來觀賞作品時能夠有最完整的體驗。

在互動設計中有哪些可以玩的元素?

在製作作品的最後,我加入了游動與泡泡的設計讓藏家能夠去控制魚的游動時快時慢,以及使用鍵盤往特定的方向移動,我搜尋了一些真實的魚的影片,發現他們其實魚鰭跟尾巴在高速游動時都比我預期的快跟靈活,因此加上了游動的機制之後變的很生動,更像自然中魚類運動的樣子。

除了魚的互動之外,泡泡會不斷的從下方冒上來,你能夠使用滑鼠戳破泡泡,或泡泡碰到魚的時候,會同時觸發高音的鋼琴聲,跟背景的音樂呼應。

發售的狀況與後續調整

在 2023/1/16 順利鑄造完售!

我在 2022 五月時發行了靈魂魚的作品,原本計畫是500版次,原本預期會有很多 Hamily 來 mint 所以調整成 1000 版,近期調整回 400 版確保作品的獨特性,雖然在過去的一年中沒有馬上 mint out,隨著時間過去,終於在 2023 Jan 16, 02:53:29 PM 鑄造完畢,達成了里程碑!

此外,我也曾受邀在台北表演藝術中心的大圓球建築物上投影靈魂魚,在大街上看到魚在圓球上游泳很像實體世界的巨型魚缸。我於台北101的個展 – 「混沌實驗室」中有展出,投影在沈浸式的空間中,沐浴在像是極光般的靈魂魚質感時很浪漫。

2022/5 月在台北 101 的個展 「Chaos Laboratory

除了單件作品的展示之外,我也很喜歡讓靈魂魚以群體的方式呈現,因此後續希望能夠在線上做一個虛擬的水族箱,一個發光的海底世界,並且結合場域投影讓魚有機會再實體空間持續存在與游動,如果能夠結合實體場域,製作一個全互動式的虛擬投影空間,讓人可以彷彿置於深海的體驗黑暗中的光輝,一定會非常感動。

如果你對更多的創作過程有興趣,可以看之前的靈魂魚製作分享直播!

這篇文章 【p5.js 程式創作】Soul Fish 數位永恆生命的靈魂魚 – 創作故事 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
p5 js互動藝術程式創作 – 初階應用實戰教學!(下篇) https://creativecoding.in/2022/12/26/p5js-workshop-clab-2/ Mon, 26 Dec 2022 03:12:37 +0000 https://creativecoding.in/?p=3435 老闆在第一屆「Processing 臺灣國際社群日」活動中,受邀為設計工作坊擔任講師,針對 p5.js互動藝術程式創作入門的主題進行為期兩天的分享。分別為第一天的基礎練習與第二天的生程式藝術實作,本篇文章內容為第二天的實作練習,希望能讓同學能學習到以基礎的方式,將創意想像以自己的技術實現!

這篇文章 p5 js互動藝術程式創作 – 初階應用實戰教學!(下篇) 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
臺灣當代文化實驗場 C-LAB 在 2021 年 10 月 19 日到 10 月 24 日,邀請全球 Processing 使用者共同參與台灣第一屆「Processing 臺灣國際社群日」,活動中集結不同藝術家及設計師的觀點,帶領大眾以多方的視角,進入未來新媒體藝術的全新想像。
老闆在這一連串的活動中,除了擔任對談講者外(參考文章:創意程式設計:Processing/p5.js教學與趨勢觀察——王連晟、吳哲宇台美連線對談),也受邀為設計工作坊擔任講師,此次就是針對 p5.js互動藝術程式創作入門的主題進行為期兩天的分享,分別為第一天的基礎練習與第二天的生程式藝術實作,希望在兩天的時間內,讓同學能學習到生程式藝術創作的基礎,將自己的創意想像以技術實作呈現!在工作坊正式開始前,老闆提供下列素材讓學員進行課前準備,包含:p5.js 的簡短介紹與 Hahow 上的課程示範。
工作坊會從 p5.js 及工具介紹、p5.js 的開發入門、基本圖形繪製以及變數解說循序漸進。
本篇文章為第二天的生程式藝術實作,依據前一天的基礎練習再更進一階,影片總長兩個小時左右,那我們就事不宜遲開始進入工作坊啦!

上篇這邊走:

課程開始

首先,延續第一天的工作坊進度,老闆先大致瀏覽了昨日有進行創作練習的同學們的作品。有同學提出在創作時的疑問,例如,當設定圖形為筆刷時,雖然圖形是連續性的出現,但當滑鼠動作較快時,圖形就無法連續性的出現,這個問題能如何解決呢?

其實這個問題反向思考來說,就是要讓筆刷連在一起,所以老闆先設定 line(),將已經經過的滑鼠位置,與滑鼠正在進行的位置串起,形成如同在繪圖軟體中,筆刷繪製的效果。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  stroke(255)
  line(pmouseX, pmouseY, mouseX, pmouseY)
}

也可以再依據線條想要調整粗細、顏色變化,或是當滑鼠按下右鍵後再執行筆刷等等變化。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  stroke(255, frameCount%255, 100)
  strokeWeight(10)
  if(mouseIsPressed){
  line(pmouseX, pmouseY, mouseX, pmouseY)
}

第一階段 – 重複迴圈

短暫回顧完第一天的內容後,老闆進行第二天的主要內容的講解,包含以迴圈與互動、增加不同色彩或是複雜圖形的編輯做分享。先從迴圈與互動,建構創作規則上面開始。老闆以知名藝術家,草間彌生的作品說明建構創作規則的原因。草間彌生的知名創作,大多都建立在「觀察事物的形體」、「重複線條的位置」以及「大量的重複」等手法,去構成她的創作系統。或是莫內及梵谷,拆解其創作手法,就會發現使用連續性的線條和錯落的顏色,去重複堆疊出作品。而上述列出的方法,對程式創作來說,是低成本就能執行的技術,也因此我們能藉由這樣的方式去快速獲得一件具有「美術手法」的創作作品。以迴圈來說,可以設計出相同圖形但是不同排列,具有設計感或是抽象感的作品,像臺灣的傳統花磚,就是利用重複圖案,但是利用不同角度的鏡射,排列出具有韻律感的設計作品。

台灣傳統花磚(圖片來源
使用重複技巧的程式作品(作品連結

那我們也開始迴圈實作吧!

老闆先以最單純的圓圈重複做範例,在還沒學習到如何使用重複迴圈技法時,我們可能就是使用重複貼上同一組程式碼,再在位置上做些許變化執行。但這樣並不便利,也因此又能使用迴圈 for() 來解決此項問題,先來說明 for 的基本語法結構。

for (計數變數的起始狀態; 結束條件; 每次結束後變數如何變化) {
  概念相同,需要重複執行的事情
}

實際帶入數字撰寫示範說明:

function setup() {
  createCanvas(windowWidth, windowHeight);
   background(100);
}

function draw() {
  background(0)
  for(let i=0; i<10; i+=1){
    ellipse(width/2+i*50, height/2, 300, 300)
  }
}

在 i 這個變數下,根據前面設定的數字,起始到結束重複執行。

創作過程中,老闆也提供一些設計小技巧,像是顏色選擇。在創作中,顏色佔了很大的一部分,但當我們對於選色上想要有更快速的方式就是應用設計網站。老闆提供一個叫做 COOLORS 的網站給同學做參考,可以選擇自已想要的主要顏色,點按空白鍵就能產生多種配色選項。

COOLORS 網站首頁(網站連結

那要如何經由程式,去排列出不同顏色卻執行重複動作的流程呢?

老闆以陣列舉例,去執行顏色上的排列。在前一天的工作坊中,也有提到陣列以中括號執行即可。我們先列出需要的顏色,再將其存取起來。當形成一個完整陣列後,再套入重複圖形的顏色當中。

let colorList = ["#ffffff","#2e86ab","#d0cdd7","#ffa62b","#273469"]

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(255);
}

function draw() {
  background(0)
  noStroke()
  for(let i=0; i<50; i+=1){
    fill(colorList[i%5])
    circle(width/4+i*(mouseX/10), height/2, 300 -i*6)
  }
}

在程式創作的好處就是能夠快速地進行大量編輯,例如如果要替換配色,只要在陣列中變換色票即可,又或是,想要變化圖形的位置,我們可以從觀察程式中哪裡有重複進行編輯,以下示範:

先設置一個 function() ,將會重複使用到的程式包在裡面,再將設置的代表文字,套入 draw() 中,簡化重複的程式,增加多樣化編輯。

let colorList = ["#ffffff","#2e86ab","#d0cdd7","#ffa62b","#273469"]

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  noStroke()
  drawCircles(random(width), random(height))
}

function drawCircles(posX, posY){
  for(let i=0; i<50; i+=1){
    fill(colorList[i%5])
    circle(posX+i*(mouseX/10), posY, 300 -i*6)
  }
}

不想制式的都從同一個顏色開始,可以在顏色上使用 random,讓顏色隨機出現,也需要 int 套入在設定前,讓出現的數字得以四捨五入為整數。

for(let i=0; i<count; i+=1){
  fill(colorList[int(i+random(10))%colorList.length])
  circle(posX+i*span, posY, 300 -i*(300/count))
}

增加了隨機的亂數,作品是否又多增加了不同的詩意呢?老闆在這邊提出了有趣的看法,他認為,程式雖然可大量重複的行為,但再加入無法預測的亂數後,出其不意的呈現,就會在視覺上趨向傳統所謂的藝術感。

迴圈教學到這邊,休息十分鐘讓同學提問以及練習。有同學提問,為何在此次練習中,老闆使用 let 而不是 var 做函數參數呢?老闆在這邊鼓勵大家,雖然在 javascipt 當中是以 var 做使用,但 let 會更加嚴謹。舉例說明,用在函數定義範圍時,let 就是在大括號的範圍內具有作用。但如果是 var 的話,是以 function 為範圍,所以定義較大,判斷上較不容易。在這十分鐘,老闆也持續的做小技巧教學。例如,要如何隨機對應不同顏色組合,做圖形上的顏色變化,我們必須先設定不同的 colorList 設定顏色組合,再依據需求變更。

延伸閱讀:使用 let / var / const 宣告變數的差異(鐵人賽:ES6 開始的新生活 let, const – 卡斯伯

let ColorList = ["#ffffff","#2e86ab","#d0cdd7","#ffa62b","#273469"]
let ColorList2 =["#c9cba3","#ffe1a8","#e26d5c","#723d46","#472d30"]

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  noStroke()
  drawCircles(random(width), random(height), mouseX/5, 50, ColorList2)
}

function drawCircles(posX, posY, span, count=50){
  for(let i=0;i<count;i+=1){
    // 從清單中選取顏色
    let colorIndex = int(i+random(10))%ColorList2.length
    fill(ColorList2[colorIndex])
    circle(posX+i*span, posY, 300 -i*(300/count))
  }
}

可以依照上方陣列設定,變化要使用 ColorList 或是 ColorList2 執行效果。另外,設定畫布的大小可以讓畫面更接近畫作感覺。

再來進入到使用變數紀錄狀態,如同一個簡化邏輯的過程,就像是假如今天我們設置了三種不同筆刷效果供使用,要如何快速切換這些效果呢?最快的方式又是設定變數。設定筆刷 paintMode,並且設定筆刷在不同模式時的效果,像是隨機大小變化,就能使用 random 進行。

let colorList = "32373b-4a5859-f4d6cc-f4b860-c83e4d".split("-").map(clr=>"#"+clr)
let colorList2 = "0c090d-e01a4f-f15946-f9c22e-53b3cb".split("-").map(clr=>"#"+clr)
let colorList3 = "6622cc-a755c2-b07c9e-b59194-d2a1b8-fff".split("-").map(clr=>"#"+clr)
let colorList4 = "2f2d2e-41292c-792359-d72483-fd3e81-fff".split("-").map(clr=>"#"+clr)

let paintMode = 0

function setup() {
  createCanvas(1000,1000);
  background(0);
  paintMode = int(random(2))
  // print(colorList[2])
}

function draw() {
  // background(0)
  noStroke()
  if (paintMode==0){
    drawCircles(
      random(width),random(height),
      mouseX/5, 50, random([colorList, colorList2])
    )
  } else if (paintMode==1) {
    drawRects(
      random(width), random(height),
      mouseX/5, 50, random([colorList3, colorList4])
    )
  }
}

function mousePressed(){
  paintMode++
  paintMode = paintMode %2
}

function drawCircles(posX, posY, span, count=50, useColorList){
  for(let i=0; i<count; i+=1){
    let colorIndex = int(i+random(10) )%useColorList.length
    fill(useColorList[colorIndex])
    circle(
      posX+i*span, posY,
      300 -i*(300/count)
    )
  }
}

function drawRects(posX, posY, span, count=50, useColorList){
  for (let i=0; i<count; i+=1) {
    let colorIndex = int(i+random(10) )%useColorList.length
    fill(useColorList[colorIndex])
    rectMode(CENTER)
    rect(
      posX+i*span, posY,
      300 -i*(300/count)
    )
  }
}

應用重複的紋理與符號,改變物件的大小、方向或是出現的頻率,讓畫面的效果更加豐富。

第二階段 – 色彩

在 p5.js 裡常用的色彩系統有 RGB 與 HSB 兩種,RGB 是指顏色紅、綠與藍三種交疊後產生,HSB 是由色相、飽和度與亮度三種維度組成。應用 p5.js 的 Color 物件,並填上以像是一個數值、RGB 數值、填入顏色名稱、填入色票號碼或是宣告色彩模式後再填入色碼等多樣化模式都是得以進行的。了解基本設定後,就來進行實際操作示範吧!

先由圖形的顏色變化開始,假設要執行顏色漸變的圓形,可以先設定色彩系統 HSB,再依據可能使用滑鼠讓顏色變化的技巧,進而使顏色做漸進變化。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  colorMode(HSB)
  fill(mouseX%360, 100, 100)
  ellipse(mouseX, mouseY, 500, 500);
}

多方應用 random,使其在顏色或是圖形大小變化上,都能做一定範圍的控制。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  colorMode(HSB)
  noStroke()
  fill(random(0,50), random(50,100), 100)
  circle(mouseX, mouseY, random(300));
}

或者是控制在特定範圍內,即使是 random 的效果也能控制想要的方向,像是指定色相的呈現,顏色偏移在指定的範圍內。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  colorMode(HSB)
  noStroke()
  let startHue =random(0,150)
  for(let i=0; i<20; i++) {
    fill(startHue+i*5, random(50,100), 100)
    circle(mouseX+i*20, mouseY, 200-i*10);
  }
}

另一種常見的顏色使用功能為  blendMode(模式名稱),與 p5.js 當中的疊色模式十分相近, 帶入不同的模式時,疊色的效果就會不同,以 SCREEN 作範例,就是亮系的疊色效果,老闆調整變化速度與圓形顆數示範疊色效果,過程中也可以應由透明度的調整變化出不同的感覺。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
  frameRate(5)
}

function draw() {
  colorMode(HSB)
  noStroke()
  let startHue = random(0, 150)
  blendMode(SCREEN)
  for(let i=0; i<1; i++){
    let currentStartHue = (startHue+mouseY)%360
    fill(currentStartHue+i*5, random(50,100), 100,1)
    circle(mouseX+i*100, mouseY, 200-i*10);
  }
}

或是設定變數,讓在不同位置圖形有指定的顏色,限制色相的範圍,使其在生成時顏色為固定效果,以及加上填塞與單純線條的選項,讓作品更多活潑變化性。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
  // frameRate(5)
}

function draw() {
  colorMode(HSB)
  noStroke()
  let startHue = random(0, 150)
  blendMode(SCREEN)
  // blendMode(MULTIPLY)
  for(let i=0;i<1;i++){
    let xx = random(width) + i*100
        yy= random(height)
    let currentStartHue = (startHue+yy/3)%360
    if(random()<0.5){
      fill(currentStartHue+i*5, random(50,100), 100, 1)
      noStroke()
    } else {
      stroke(currentStartHue+i*5, random(50,100), 100, 1)
      noFill()
    }
    circle(xx, yy, random(100));
  }
}

但,當在使用重複多種圖案顯示時,有些圖案並沒有顯示在畫布上,這時可以應用 pushpop,將圖案分別開來指定顯示,或是設定 frameRate() 圖形的出現速度變化,控制一秒中出現幾次。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
  // frameRate(5)
}

function keyPressed(){
  if (key == "1") {
    frameRate(5)
  } else if (key == "2") {
    frameRate(30)
  } else if (key == "3") {
    frameRate(60)
  } else if (key == "4") {
    frameRate(120)
  }
}

function draw() {
  colorMode(RGB)
  background(0, 1)
  push()
    colorMode(HSB)
    noStroke()
    blendMode(SCREEN)
    let startHue =random(0,50)
    // blendMode(MULTIPLY)
    for(let i=0; i<1; i++){
      let xx = random(width)+i*100
          yy = random(height)
      let currentStartHue = (startHue+yy/3)%360
      if (random() < 0.5) {
        fill(currentStartHue+i*5, random(50,100), 100, 1)
        noStroke()
      } else {
        stroke(currentStartHue+i*5, random(50,100), 100, 1)
        noFill()
      }
      circle(xx,yy, random(50,500));
    }
  pop()
}

練習過程中,老闆也陸續回答同學的發問。

【問題一】請問 Openprocessing Editor 與 p5.js Editor 有所不同嗎?

回答:其實兩者的使用方式以及效能都是大同小異的,皆為提供給創作者即時顯示創作效果的地方。但老闆覺得在整體設計上,openprocessing 對於初學者來說較友善且容易上手,但每個人的感受不一,建議同學都能去嘗試看看自己比較適合哪種應用介面。

【問題二】請問 p5.js 可以做到如同 Team Lab 或是 梵谷光影展那樣的內容嗎?

回答:可以,但在 3D 的呈現上,因為函式庫的內容還沒有那麼完整,在建構呈現效果以及動畫上可能就需要再多加著墨。

【問題三】請問對於每行的分號加或不加有什麼心得或是建議嗎?

回答:老闆在撰寫時習慣不加,因為在 p5.js 撰寫時目前並不是必要的。但是如果同學們擔心的話,在網路上也都能找到自動幫你每行加分號的執行系統。

【問題四】請問 p5.js 有類似於 opencv 進行影像處理或是人臉辨識的進階 library 嗎?

回答:有的,但並不是官方的,名為 ml5.js。在臉部的輪廓或是 pixel 的呈現都是能夠抓到的。

臉部輪廓抓取 api 介面。(截圖自 ml5.js

老闆也有執行過類似的創作,抓取人體位置輪廓,以線條和原點呈現。(作品參考)也建議如果有更多函示庫應用的相關資訊想了解,可以觀看上一篇的影片介紹喔!(影片連結

第三階段 – 畫布操作

此階段以畫布操作,使同學在畫複雜圖形的時候,能以簡化的方式執行,快速且不需多樣計算,重點即是如何簡化繪製圖形的位置。

老闆先以要在畫布上畫多重圓形為舉例,比較先前執行與畫布操作後的差別。這邊應用到三角函數,因為需要使用三角函數去執行圖形的位置,而三角函數的取得需要使用到角度 degree() 功能去計算,今天以要得到一個在中心點圓形的45度角運行的圓形,以下為設定了角度、半徑與函數設定的程式。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  background(0)
  fill(255)
  let r = 200
  let ang =frameCount/100
  let x = r*cos(ang)
  let y = r*sin(ang)
  ellipse(width/2, height/2, 100)
  ellipse(width/2+x, height/2+y, 100)
}

此類的設定模式,會出現兩種問題。一,算式偏多,應該可以更加簡化。二,如果要畫多個圓形,就必須重複設定位置。對於這一系列的設定,老闆先解釋角度後說明如何應用,為何畫布的操作便是可以簡化此應用的方式。

我們在操作時,是為了要設定以一個圖形為中心,並依據此的某個特定角度,使用 translate() 進行其他圖形繪製。假設,今天要為中心的圖形,其實位在左上角,那我們移轉畫布就是讓左上角的圖形變成畫布的中央。(移轉畫布解說參考

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  background(0)
  fill(255)
  let r = 300
  let ang = frameCount/100
  let x = r*cos(ang)
  let y = r*sin(ang)
  translate(mouseX, mouseY)
  ellipse(0, 0, 100)
  ellipse(x, y, 400)
  ellipse(x, y, 300)
  ellipse(x, y, 200)
  ellipse(x, y, 100)
  fill(255, 0, 0)
  rect(200, 200, 50, 50)
}

此種移轉畫布的方式,讓圖形的總體位置相關參數,並不會跟程式邏輯混和在一起。偏移結束後,接下來進到畫布的旋轉。當設定為同種圖形在不同的位置重複出現,使用 translate()roatate() 繪製出多個圖形。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  fill(255)
  let r = 300
  let ang = frameCount/100
  translate(width/2, height/2)
  rotate(ang)
  translate(200, 0)
  rect(0, 0, 200, 200)
  fill(255, 0, 0)
  rect(200, 200, 50, 50)
}

嘗試多做點不同變化,像是旋轉的幅度以及圖形的大小隨著旋轉有所改變。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  push()
    fill(255)
    let r = 300-frameCount/2
    let ang = frameCount/100
    let currentScale = 1-frameCount/500
    translate(width/2, height/2)
    scale(currentScale)
    rotate(ang)
    translate(r, 0)
    rect(0, 0, 200, 200)
  pop()
}

在顏色排列上,除了 random 的隨機排列外,也能使用 noise() 執行持續性的變化。什麼是 noise?其代表著連續性的、可預測性的亂數。依據 perlin 噪聲圖上的不同位置,去影響每個設定,給相同點的時候,出來的結果會是一樣的,所以就可以嘗試將 random 更換成 noise 去觀察結果的差異。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  noStroke()
  push()
    colorMode(HSB)
    fill(noise(frameCount/50)*100,100,100)
    let r = 300-frameCount/2
    let ang = frameCount/20
    let currentScale = 1 - frameCount/500 + random(0.1, 0.5)
    translate(width/2, height/2)
    scale(currentScale)
    rotate(ang)
    translate(r, 0)
    rect(0, 0, 200, 200)
  pop()
}

將 noise 與 random 共同使用,讓顏色變化不死板,有多樣性的呈現。使用 hue 色相作為變數,去引導顏色為漸進的變化。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  push()
    colorMode(HSB)
    let useHue = (random(20)+noise(frameCount/50)*100 +frameCount/3)%360
    fill(useHue,100,100)
    let r = 300-frameCount/2
    let ang = frameCount/20
    let currentScale = 1 -frameCount/500 +random(0.1,0.2) +noise(frameCount/50)/2
    translate(width/2, height/2)
    scale(currentScale)
    rotate(ang)
    translate(r, 0)
    rect(0, 0, 200, 200)
  pop()
}

今日工作坊總結

在本次工作坊的下篇,我們總共學習到了三大項主題,包含迴圈的建構創作規則、變化色彩使用與留下痕跡,到最後的進階應用,畫布的變化。上述這些應用,老闆在做後一個示範中,將上述的功能都包含在裡面。由左到右畫一連串的長方形,這些動作是可以被累加的。先使用 translate 將圖形重複的執行,再設定變數以及出現的規則,將圖形依照滑鼠位置做變化。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(100);
}

function draw() {
  // ellipse(mouseX, mouseY, 20, 20);
  fill(random(255), 200, 200)
  translate(0, height/2)
  rectMode(CENTER)
  for(let i=0; i<50; i++){
    rotate(map(mouseY, 0, height, -0.5, 0.5))
    translate(50,0)
    scale(0.95)
    rect(0, 0, 500, 500)
  }
}

雖然快接近結束,同學們還是十分積極的詢問問題,像是,如果想針對資料進行統計的視覺化呈現,有什麼相關的 lib 或 sample 可以參考嗎?比如地區人口統計?針對此問題,老闆認為目前 p5.js 的函數庫在視覺化上的效果還不是最齊全的,可能會使用其他函數庫如 D3.js 來進行,但也還是可以參考先前的相關課程,針對 p5.js 在視覺化上的 api 應用教學,來嘗試進行(參考文章)。

最後,也不免俗的與同學分享老闆在互動藝術程式創作的其他課程,或是影片推廣給大家。包含 Creative Coding TW – 互動程式創作台灣站 的專業文章網站、社群軟體上的即時資訊分享 老闆 來點寇汀吧。 Boss,CODING please(臉書)、老闆來點寇汀吧 Boss, Coding Please (臉書)、老闆,來點寇汀吧。Boss, CODING please(Youtube 頻道),當然還有想要進一步正式開始創作,歡迎加入 互動藝術程式創作入門課程 開始學習!本次分享就到這邊結束啦,歡迎各位一起踏入程式與藝術交織的世界!

此篇直播筆記由幫手熊柑協助整理

這篇文章 p5 js互動藝術程式創作 – 初階應用實戰教學!(下篇) 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
p5 js互動藝術程式創作 – 初階應用實戰教學!(上篇) https://creativecoding.in/2022/12/26/p5js-workshop-clab-1/ Mon, 26 Dec 2022 03:10:20 +0000 https://creativecoding.in/?p=3403 老闆在第一屆「Processing 臺灣國際社群日」活動中,受邀為設計工作坊擔任講師,針對 p5.js互動藝術程式創作入門的主題進行為期兩天的分享。分別為第一天的基礎練習與第二天的生程式藝術實作,本篇文章內容為第一天的基礎練習,希望能讓同學能學習到以基礎的方式,將創意想像以自己的技術實現!

這篇文章 p5 js互動藝術程式創作 – 初階應用實戰教學!(上篇) 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
臺灣當代文化實驗場 C-LAB 在 2021 年 10 月 19 日到 10 月 24 日,邀請全球 Processing 使用者共同參與台灣第一屆「Processing 臺灣國際社群日」,活動中集結不同藝術家及設計師的觀點,帶領大眾以多方的視角,進入未來新媒體藝術的全新想像。
老闆在這一連串的活動中,除了擔任對談講者外(參考文章:創意程式設計:Processing/p5.js教學與趨勢觀察——王連晟、吳哲宇台美連線對談),也受邀為設計工作坊擔任講師,此次就是針對 p5.js互動藝術程式創作入門的主題進行為期兩天的分享,分別為第一天的基礎練習與第二天的生程式藝術實作,希望在兩天的時間內,讓同學能學習到生程式藝術創作的基礎,將自己的創意想像以技術實作呈現!在工作坊正式開始前,老闆提供下列素材讓學員進行課前準備,包含:p5.js 的簡短介紹與 Hahow 上的課程示範。
工作坊會從 p5.js 及工具介紹、p5.js 的開發入門、基本圖形繪製以及變數解說循序漸進。本篇文章為第一天的基礎練習介紹,影片總長兩個小時左右,那我們就事不宜遲開始進入工作坊啦!

什麼是 Creative Coding ?

老闆以自我介紹作為開場,從大學的電機工程背景到至紐約就讀新媒體藝術相關研究所,而開始了一連串生成式藝術的創作。對於什麼是 Creative Coding,老闆說自己也是在不太理解的狀況下開始的。是用程式創作藝術嗎?那到底程式創作出來的藝術,最終呈現出來的效果又會是如何呢?這些想必是初接觸生成式藝術的人都會提出的問題,因此老闆提供不同的案例分享,作為答覆的參考。
以目前最常看到的例子來說,視覺上,像是原先平面的設計海報以動態的方式呈現增加趣味性,或是模擬傳統媒材(如水墨)等等,藉由制定規則,讓每一次不同互動產生出的作品都有不一樣的呈現,這使每件藝術作品都是獨一無二的,並且在參與度提升的情況下,成為對互動者更特別的藝術存在。還有在互動網頁上,像是老闆成立的墨雨設計工作室,就有許多應用相關技術的案例,例如與台灣啤酒合作的網頁。或是現在有很多網頁,當使用者將滑鼠向下移動要瀏覽整個畫面時,也會有不同的動畫呈現,整個瀏覽體驗就像是一個完整的時間軸。

老闆作品 Slient Sky 參考範例(連結
台灣啤酒合作案例(連結

在執行設計創作時,老闆也提出自己建立規則的範例供大家參考,以下方作品為例,從中心散開的圓心,其規則並不複雜。先從中心設定隨機數量生成的粒子,粒子會向外成長擴散,並且在成長的過程中變化成不同的顏色,以及施加不同的外力讓粒子扭曲變形。綜合以上這四項變化,就會得出每一次都是不同作品的互動創作。

視覺平面的傳達外,像是在美術館裡的互動式藝術,或是在街角呈現的大型裝置都是可以用 p5.js 執行的。

p5.js 是什麼?

Processing 為一種開源式語言,最初的目的是希望能以視覺化的方式幫助非程式設計師學習程式語言,而後演變成在電子藝術或是互動式設計上都能發現其應用。

Processing 網站首頁(截圖自 Processing網站首頁 )

p5.js 即是將 Processing 以 Javascript 語言做應用,使其可在網路瀏覽器上進行直接創作,免費及開放資料庫的特性,降低了學習門檻,也吸引更多人進入創意程式設計 Creative Coding 的領域。

p5.js 網站首頁(截圖自 p5.js網站首頁 )

此外還有像是 MaxMSP,以 Creative Coding 應用在音樂的視覺化效果呈現。其撰寫時與 p5.js 的不同在於,p5.js 一般會以程式碼顯示,但在 MaxMsp 是直接以視覺的圖案的方式做呈現,將語言命令可視化成一塊一塊的圖形,再依位置的安排去創造不一樣的效果,串接出不同的流程,進行音樂的創作。

MaxMSP 網站首頁(取自 MaxMSP 網站首頁)

或是 Sonic Pi,一個使用文字創作音樂的程式設計環境。

Sonic Pi 網站首頁(取自 Sonic Pi 網站首頁 )

Touch Designer 也屬於視覺為基礎的語言,採用圖形化的介面讓使用者創作,實現多媒體特效。

Touch Designer 網站首頁(取自 Touch Designer 網站首頁 )

不同的創作環境,都說明 Creative Coding 不論在視覺上,或是聲音上都有豐富的創作應用。而 p5.js 代表的就是更全面的環境,整合了從3D 到聲音都有涵蓋。有同學提到,既然 p5.js 與 processing 的語法幾乎相容,那還有什麼狀況下選擇 processing 比較好呢?老闆回覆是,其實 processing 在過去的優勢現在幾乎在 p5.js 上都能進行,建議剛入門的同學以好操作上手的 p5.js 開始創作入門,這樣到後面如果真的因為 pocessing 可能在效能上有相對好一些,要回 processing 上進行創作,入門時間也不會過長。歸類以下 p5.js 的優勢,簡化了語法、減少了無程式背景的創作者的入門門檻,以及多項資料庫可使用或是簡易自行建立。

課程開始

首先,登入進 Openprocessing ,直接點擊連結便能開始以創作,或是也可以追蹤老闆及不同的創作者,參考不同的創作概念。進入個人創作頁面後,便能看到 「Create a Sketch」,每建立一個 Sketch 都代表一個新的創作實驗場域。點進去創作介面會先看到基本程式裡分成兩個部分, setupdraw 兩種不同的規則。前者代表在畫布上的設定,一次性的準備動作,後者代表不斷在畫布上重複著畫上新東西的動作。在創作同時,我們也可以在右方欄位做 layout 設定,讓撰寫程式同時在同一版面看到作品呈現。

一、顏色置換示範

推薦使用 Chrome 瀏覽器的擴充功能「 ColorZilla 」,可以挑選想要的顏色並顯示出色票。當有了色票後,便可以依上色元素不同,在 background() 或是 fill() 做更換。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(255,181,35);
}

function draw() {
  circle(mouseX, mouseY, 20);
}

二、繪製圖形、圖形大小與顏色變更示範(筆刷變換)

基本變化像是圖形中不填色 noFill()、去掉圖形外框 noStroke(),或是 strokwWeight() 控制線框粗細。另外,當你要暫停一行程式的功能,請按下 ctrl 鍵與 /,就能看到反灰並且暫停功能的程式碼。

基本圖形控制可以至 p5.js 資料庫中做多方搜尋,以本次範例橢圓形 ellipse 為主,有設定位置是特別指定或是以滑鼠 mouseX、mouseY 代替,與形狀的長寬大小設定。

進入到顏色階段,針對圖形總共有兩個部份可以做編輯,分別是圖形內的顏色以及圖形線條的顏色。fill() 提供圖形內的顏色,stroke()則負責圖形線條的顏色,在顏色選取上,能使用顏色色票、顏色名稱(請記得要加上雙引號,例如:”white”)以及 rgb 顏色(CSS Colors 網站)。如果想要使顏色變化根據互動而有更多元的呈現,可以將 rgb 色彩數值的其中一項更改成滑鼠位置,如此一來顏色就會根據滑鼠位置變化。

滑鼠效果除移動中會有變化外,在 if 與 else 間進行條件判斷,就能在不同情況中呈現不同的效果,下方是根據滑鼠點按之間的效果呈現。

function draw() {
  noStroke()
  fill(mouseX/4,mouseY/4,200)
  print(mouseX/4)
  
  if (mouseIsPressed){
    ellipse(mouseX, mouseY, 100,100);
  } else {
    stroke(255)
    noFill()
    rect(mouseX,mouseY,100,100)
  }
}

如果要增加顏色多樣性,可以使用 random() 設定需要的顏色數值,讓不同的顏色隨機出現。也另外補充個撰寫程式小技巧,可以在選擇多組相同數字時,使用 ctrl 鍵加上 D 進行多重選取減少時間。

上述是由變換位置去進行筆刷的變更,那藉由時間來變更的部分,可以使用 frameCount() 編輯。以示範案例中的橢圓形舉例來說,假使要讓橢圓形的 Y 軸隨著時間來進行筆刷大小的變化,在相對應的 Y 軸編輯位置放上 frameCount 就可以執行,下方範例:

function draw() {
  noStroke()
  fill(mouseX/4,mouseY/4,200)
  print(mouseX/4)

  if (mouseIsPressed){
    ellipse(mouseX, mouseY, 200,frameCount);
  } else {
    stroke(255)
    noFill()
    rectMode(CENTER)
    rect(mouseX,mouseY,100,100)
  }
}

講解到這邊後,老闆給線上參與的同學進行五分鐘的線上練習,題目為:請設計出一個隨機大小為 0 到 50 的圓形筆刷。與此同時,也開放同學在製作時有任何問題能當場詢問,以下問題歡迎參考。

【問題一】 在 p5.js 裡面是否有質感筆刷可以應用或是製作呢?像是油漆筆刷般的效果?

答:有許多方式可以處理,目前先以比較便捷的方式做示範。

先至網路上找尋相關筆刷的圖樣,比如此次是製作油漆類型,那就搜尋相近的筆刷圖案,先下載圖片。

下載其中自己比較喜歡的圖片後,再至 openprocessing 的編輯頁面上傳圖片檔案。便可以開 使進行質感操作啦!

首先,需要先使用 var 宣告與 preload function 預載入,設置質感 texture 的出現,再設置筆刷 image 進行應用,程式與呈現效果如下:

var paintTexture

function preload(){
  paintTexture =loadImage("20190806101953yop172.png")
}

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0);
}

function draw() {
  noStroke()
  fill(mouseX/4,mouseY/4,200)
  print(mouseX/4)

  if (mouseIsPressed){
    image(paintTexture,mouseX,mouseY)
  } else {
    stroke(255)
    noFill()
    rectMode(CENTER)
    rect(mouseX,mouseY,100,100)
  }
}

【問題二】 如何分享在 openprocessing 上創作的作品呢?

答:將作品儲存後,可以使用網址直接分享,或是 openprocessing 作品頁面右上方的分享功能都可以使用喔。

接下來進到線上練習的分享時間!

經過五分鐘的練習後,同學應用上述老闆教學說明到的不同應用進行創作。老闆也針對這些分享作品提供不同的建議,或是告訴其他同學這些不同創作是怎麼製作的。例如,有作品使用透明度進行不同編輯,在這邊透明度的應用分為兩種:第一種為圖案顏色的透明度,此類型是在圖案填色 fill() 中,除了 rgb 填寫外,再增加一個代表透明度的數字,變成 rgba 模式,例如 fill(255,255,255,10),代表顏色具有百分之十的透明度;另一種情況為圖形筆刷在背景留下軌跡與否,在 background() 編輯時,設定透明度,讓背景每秒覆蓋的顏色不會完全覆蓋,如此一來就能留下上一秒的軌跡。

三、變數解說教學

進入應用變數的環節,老闆以設計橢圓形為範例說明。如何快速的將兩個不同的,寬與高等比例放大呢?我們需要設置一個櫃子來存放將這些即將運用到的變數,在需要的時候就可以快速抓取使用。運用 let 設置存放變數,舉例來說 let r=50,後續在 draw 裡面,使用到 r 時程式就會帶入 50 這個數字。

延伸閱讀:使用 let / var / const 宣告變數的差異(鐵人賽:ES6 開始的新生活 let, const – 卡斯伯

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(0,50);
}

function draw() {
  noStroke()
  fill(mouseX/4,mouseY/4,200)
  print(mouseX/4)

  if (mouseIsPressed){
    let r =random(50,200)
    ellipse(mouseX, mouseY, r,r);
    image(paintTexture,mouseX,mouseY)
  } else {
    stroke(255)
    noFill()
    rectMode(CENTER)
    rect(mouseX,mouseY,100,100)
  }
}

四、如何繪製形狀

經由上述的基礎設定、顏色選填、變數教學與基本圖形設定解說後,接下來進行繪製形狀的教學。形狀除了先前提到的圓形或是方形外,還有線條、3/4圓甚至是自己建立的幾何形狀,其實都能應用函數的變化去繪製出。老闆先以線條舉例,函數式為 line(x1,y1,x2,y2),分別代表連成線條的不同點,而線條粗細是以 strokeWeight() 調整。那該如何得知座標呢?可以先透過設定文字,顯示出滑鼠在座標上移動的位置。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(255);
}

function draw() {
  background(255)
  strokeWeight(10)
  line(0,0,500,500)
  textSize(50)
  text(mouseX + "," + mouseY,mouseX,mouseY)
}

老闆也提到如何將圖案融合文字,呈現對話框般的資訊。先設定隨機出現的長方形,並且將方角設定成圓角,使其更具有對話框的設定。並且運用變數設定,使文字與對話框在相同的設定下隨機出現。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(255);
}

function draw() {
  // background(255)
  strokeWeight(2)
  let x = random(width)
      y = random(height)
  rect(x,y,200,50,20)
  text("HELLO",x,y+40)
}

或者使用特定條件呈現更多層次的畫面,像是加上 if()else() 的二元判斷變化,以及使用變數讓不同文字隨機出現在不同的對話框中。執行的同時,老闆也會分享一些在寫程式的快捷鍵和小撇步,假使不想只選取單一文字,而是同行多個文字選取,可以根據游標位置,按下 alt 和 shift 再向右或左按下鍵盤左右鍵。或是因為撰寫項目太多,想要進行分類時,可以將無效文字標註在程式中,以防後續搞混或忘記。另外,建立好形狀繪製的基礎後,我們也可以控制出現的頻率。其中一種作法是使用  frameRate() 來編輯。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(255);
  frameRate(10)
}

function draw() {
  strokeWeight(2)
  let x = random(width)
      y = random(height)

  if(random()<0.5){
    fill(0)
    rect(x,y,200,50,20)
    textSize(30)
    fill(255)
    text(random(["HELLO","TAIWAN","CREATIVE","CODING"]),x+20,y+40)
  } else {
    // 指定文字大小
    textSize(30)
    // 白底黑字
    let myText = random(["CLAB","TAIWAN","當代文化實驗場"])
    let w=textWidth(myText)
    // 對話框
    fill(255)
    rect(x,y,200,50,20)
    fill(0)
    // 文字
    text(myText,x+20,y+40)
  }
}

瞭解圖形與文字的隨機變化後,繼續進行隨機自行繪製形狀的產生,從三角形隨機顏色變化為例,以及自行繪製的圖形示範。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(255);
}

function draw() {
  strokeWeight(random(5))
  line(0,0,width/2,height/2)
  fill(random(0,255),random(0,255),200)
  triangle(0,0,width/2,height/2,mouseX,mouseY)
}

在隨機變化中,老闆習慣設定顏色要在哪種色調或色系間做變化進行設計,建議以這樣的方式進行才比較不易出現奇怪的顏色配置問題。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(255);
}

function draw() {
  strokeWeight(random(5))
  line(0,0,width/2,height/2)
  fill(random(50,100),random(100,150),200)
  triangle(0,0,width/2,height/2,mouseX,mouseY)
}

再來是自行繪製的圖形解說,老闆以王冠繪製示範。多邊形製作需要使用到 beginShape() 代表起始位置、 endShape() 代表終點位置,以及 vertex() 說明在起始與終點間會經過哪些點。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(255);
}

function draw() {
  background(255)
  // strokeWeight(random(5))
  strokeWeight(50)
  line(0,0,width/2,height/2)
  // line(width/2,height/2,mouseX,mouseY)
  // ellipse(mouseX, mouseY, 20,20);
  fill(random(50,100),random(100,150),200)
  // triangle(0,0,width/2,height/2,mouseX,mouseY)
  fill("#ffcc00")
  beginShape()
    vertex(200,200)
    vertex(200,600)
    vertex(750,600)
    vertex(750,200)
    vertex(600,350)
    vertex(470,200)
    vertex(350,350)
  endShape(CLOSE)
  // 繪製座標文字
  fill("red")
  textSize(50)
  text(mouseX+","+mouseY,mouseX,mouseY)
  // circle(mouseX, mouseY, 20);
}

或者是互動式的顏色應用,將王冠與背景顏色或是新增圖形都設定成會依據滑鼠位置的改變進行更動。使用預設函數改變線條粗細、圖案顏色或是模式等等,去繪製圓形、方形,甚至是多邊形,提供作者與互動者不同的作品溝通模式。像是在皇冠上,老闆進行顏色、大小和特別圖形繪製,主要是根據 mouseXmouseY 的設定。

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(255);
}

function draw() {
  background(mouseX/4,100,50)
  strokeWeight(20)
  line(0,0,width/2,height/2)
  fill(random(50,100),random(100,150),200)
  fill(255,mouseX/4,0)
  beginShape()
    vertex(200,200)
    vertex(200,600)
    vertex(750,600)
    vertex(750,200)
    vertex(600,350)
    vertex(470+mouseX/10,200)
    vertex(350,350)
  endShape(CLOSE)
  fill(255)
  circle(325,480,100)
  circle(600,480,100+mouseY/10)
  fill(0)
  circle(325,480,30)
  circle(600,480,30)
  line(355,550,500,520+mouseX/30)
  // 繪製座標文字
  fill(255)
  textSize(50)
  text(mouseX + "," + mouseY, mouseX, mouseY)
}

說明完後,又進到同學們自行練習的時間啦!

那也一樣,老闆趁這時解答同學問題。其中有一位同學詢問到霓虹效果該如何呈現,老闆拿出先前做過類似效果的作品說明示範(作品連結)。主要使用 shadow() 的疊色模式編輯,總體上分為兩個步驟,一個是指定形狀中的顏色,另一個是周圍光暈的 dawingContext() 代表周圍光暈的顏色及顯現的程度。老闆以王冠作品進行實際操作, 將王冠周圍的光暈,從最原始的單一色調設定,進階到隨滑鼠移動改變顏色,到最後是點按滑鼠鍵進行光暈顏色變更,多樣化的創作方式供同學參考。

var lightColor

function setup() {
  createCanvas(windowWidth, windowHeight);
  background(255);
}

function draw() {
  background(mouseX/4,100,50)
  strokeWeight(20)
  line(0,0,width/2,height/2)
  fill(random(50,100),random(100,150),200)

  // 畫王冠
  fill(255,mouseX/4,0)
  drawingContext.shadowColor = lightColor;
  drawingContext.shadowBlur =30;
  beginShape()
    vertex(200,200)
    vertex(200,600)
    vertex(750,600)
    vertex(750,200)
    vertex(600,350)
    vertex(470+mouseX/10,200)
    vertex(350,350)
  endShape(CLOSE)

  // 畫眼睛
  fill(255)
  circle(325,480,100)
  circle(600,480,100+mouseY/10)
  fill(0)
  circle(325,480,30)
  circle(600,480,30)
  line(355,550,500,520+mouseX/30)

  // 繪製座標文字
  fill(255)
  textSize(50)
  text(mouseX + "," + mouseY, mouseX, mouseY)
  // circle(mouseX, mouseY, 20);
}

function mousePressed(){
  lightColor = color(
    random([
      "#F2C400",
      "#F9C784",
      "#8AE1FC"
    ])
  )
}

後續特別應用,例如想讓 frameCount() 的變化是限制在特定範圍內,可以使用 constrain() 限制 frameCount() 隨機大小的範圍,或是使用 sincos 設計。 sin 是指一到負一之間,譬如 sin(frameCount)*50+200,就可以得知是設定在 負五十加兩百到五十加兩百間。或是,如果要設定由左到右的數字大小,使用 map 設定初始範圍與限制範圍進行有意識的創作編輯。

結語

主要實作教學結束後,老闆也傳授了一些編輯使用上的常用事項。例如,openprocessing 封面設定是可以藉由上方編輯按鈕,進行特定封面圖案設定,如下圖圖示,在此頁面按下右上方 edit 編輯即可操作。

也有同學問到,mouse 的座標是否可以連結到外部感應器的點位?可以開啟編輯頁面左方需連結感應的部分,但如何應用就需要後面再多做分享。或是,想要將 p5.js 的效果呈現在網頁上,能如何操作呢?老闆說明,最快的方式是使用 iframe,先至分享區域做壓縮檔下載、直接使用 emded code 程式碼崁入,或是使用 GitHub 將程式碼轉換成 index 檔案後,到 setting 的 GitHub Pages 上傳,並且再選擇 main 之後存檔,就能藉由網址看到自己已 p5.js 創作的互動程式以網頁的方式呈現。上述精彩的課程教學以及同學們多樣化的提問,就是說明互動藝術程式創作還有好多應用面向可以進行探討,與繼續發掘它不同的樣貌。閱讀到這邊,相信你也對互動藝術程式抱持著更高的興趣了吧!就讓我們接續收看下半場的精彩解說吧!

但,如果你已經迫不急待要開始進行創作,加入 互動藝術程式創作入門課程 開始進行深度學習吧!還有不要忘了 追蹤老闆 Twitter 和訂閱 老闆,來點寇汀吧。Boss, CODING please. Youtube頻道隨時補充新媒體藝術的養份,讓我們一起探索這多元的世界!

此篇直播筆記由幫手熊柑協助整理

這篇文章 p5 js互動藝術程式創作 – 初階應用實戰教學!(上篇) 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
【徵文賞-互動藝術】佳作|P5.js學習筆記:時間之隙Time gap – 羅瑋婷 https://creativecoding.in/2022/11/24/collection221110-art-1/ Thu, 24 Nov 2022 14:00:06 +0000 https://creativecoding.in/?p=3301 透過互動程式創作徵文賞,我們期望讓更多人認識並加入 Creative Coding 這個新奇有趣的領域。此作品為互動藝術組佳作,嘗試使用 shader 疊加不同效果,實驗的思路分成兩個方向,一是純粹改變外觀形狀,二是讓其他動態線條追上水流的變化。

這篇文章 【徵文賞-互動藝術】佳作|P5.js學習筆記:時間之隙Time gap – 羅瑋婷 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
裂隙彼方的幻影

之前曾經用shader成功做出夢想中的水流效果,因此之後就開始研究是否能把不同的效果疊加在上面,呈現更多不一樣的變化。實驗的思路分成兩個方向,一是純粹改變外觀形狀,二是讓其他動態線條追上水流的變化。目前雖然只暫時成功了關於形狀的部分,但這也算是一種進度,因此決定作為筆記先記錄下來。

使用的效果有兩種:

  • fbm:水流背景
  • shockwave:形狀變化的定義

fbm的部分,沿用了之前曾做過的雲水,所以重點在控制變形的 shockwave 。濾鏡的參考來源是andras這位作者,原本的效果是有點類似墨漬在紙上暈染開來的感覺,經過加工後把它改成類似在虛空中撕開時間縫隙的視覺感。

將原本的濾鏡拆解後,主要的功能函數基本上可以分成4個部分,依參數的使用層級排序為:

  • rectToPolar
  • effect
  • line
  • sw

首先 rectToPolar 這個函數負責的是「形狀呈現的基礎位置」。

  • p:畫面座標。
  • ms:時間。
  • a + r:配合atan + PI,回傳有固定範圍的擴張圓。
	vec2 rectToPolar(vec2 p, vec2 ms) {
		p -= ms / 1.35;
		const float PI = 3.1415926534;
		float r = length(p);
		float a = ((atan(p.y+0.2, p.x) / PI) * 0.85 + 0.5) * ms.x;
		return vec2(a, r);	
	}

effect接收rectToPolar回傳的參數後,再藉由fbm產生的參數重定義顯示座標。

  • p:rectToPolar處理過的範圍。
  • o:原點,這裡傳入的是float(0.0)。
  • e:透過abs()和sqrt(),緩和變動的範圍。如果想要比較尖銳的形狀,可以省略這段處理。
float effect(vec2 p, float o) {
		p *= 1.5;
		float f1 = fbm(p * vec2(13.0, 1.0) + 100.0 + vec2(0.0, o) );
    
		float e = fbm(p * vec2(15.0, 1.0) + vec2(f1 * 0.85, o));
    e = abs(e) * sqrt(p.y / 5.0);
    
    return e * 0.75;
	}

之後line負責的是「以圓為基礎擴張出去的線條曲化度」。

  • v:畫面座標值。
  • from, to:開始與結束的數值。to的值受effect函數影響。
  • d:搭配傳入的參數(v, from, to),定義最後起點到終點的最大值,讓形狀擴張到一定的距離後自動停下來。
  • smoothstep:WebGL的函數之一,不想啃官方文件的話其實在The Book of Shaders可以找到中文說明。用來將線條平滑曲化,傳入的三個值類似(start, end, value)這樣的定義。
 float line(float v, float from, float to, float f)
	{
		float d = max(from - v, v - to);
		return 1.0 - smoothstep(0.0, f, d);
	}

最後sw把前三個搭配在一起,產生出要在畫面上變動的值:

  1. 首先用rectToPolar產生橢圓的範圍座標p。
  2. 用line產生x軸的偏移曲線。
  3. 將p傳入effect,產生從0到結束位移點兩種不一樣的濾鏡範圍。
  4. 最後混合time的變化,透過line產生y軸的偏移曲線。
  5. 回傳平滑後的形狀。
float sw(vec2 p, vec2 ms) {
		
		p = rectToPolar(p, ms);
		p.x = mod(p.x + 2.95, ms.x);
		
		// Create the seem mask at that offset
		const float b = 0.5;
		const float d = 0.04;
		float seem = line(p.x, -1.0, d, b) + line(p.x, ms.x - d, ms.x + 1.0, b);
		seem = min(seem, 1.0);
		
		float s1 = effect(p, 0.0);
		
		// Create another noise to fade to, but the seem has the be at a different position
		p.x = mod(p.x + 3.6, ms.x);
		float s2 = effect(p, -1020.0);
		
		// Blend them together
		float s = s1;
		s = mix(s1, s2, seem);
		    
    float perc = min( max(abs(sin(u_time * 0.1)), u_time * 0.1), 1.0);
    
    float f1 = perc * 0.25;
    float f2 = perc * 1.;
    
    float m = line(p.y, 0.1, f1 + s * f2 * sin(1.5), 0.2);
		
		return smoothstep(0.31, 0.6, m);
	}

完成以上系列行為,最後要將參數輸出到畫布上。使用fbm的部分略過不看,下面就只列出在main裡引用shockwave相關函數的部分:

  • c:用sw()回傳的函數s加工後的參數。先除後加是為了產生形狀再把顏色疊上去。
  • col:把fbm產生的函數f和c混合,最後再稍微加一點隨機變化。
    vec2 p = gl_FragCoord.xy / u_resolution.xy;
    float m = u_resolution.x / u_resolution.y;
		vec2 ms = vec2(m, 1.5);
     
    float c = .90;
    
    float s = sw(p, ms);
    c /= s;
    c += s;
    float t = random(p * 2.0);
  	
		vec3 pic = vec3(f);
		
   	vec3 col = mix(color, pic, c); 
    
    // Some grain
    col -= (2.0 - s) * t * 0.04;
    
		gl_FragColor = vec4((f*f*f + .26 * f*f + .15 * f) * col,1.0);

成品大概是這種感覺。雖然結果和最初的想像有落差,但意外的看起來還可以⋯⋯?其實一開始是想找有沒有方法能做出把墨滴進水裡的擴散感,後來因為單純相加的效果不好,重複嘗試後才轉向這種呈現方式,也算是另類的收穫。

最後,順便記錄一下自我流派式的學習心得吧。雖然不明白其他人是如何學習的,但我算是「累積式」。在學習路途上,我其實挺常間歇性的陷入某種循環:有想要的效果→搜尋資料→嘗試→做不出來→自我厭惡→loop。從旁觀角度看雖然有些智障,身處其中時還真是笑不出來的狀況。

說到底,擁有藝術和程式兩面性的生成藝術和普通的繪畫創作本就不同,但對我來說要把兩者徹底分開一直都有困難。和直接拿著筆不同,最容易挫折的不是畫不出好東西,而是知道自己畫不出來卻不明白該用什麼方式改進,當自我厭惡積累到某種程度時可能會就此放棄。

所以我現在變成了順其自然的累積式。簡單來說就是看多過做,嘗試時發現看不懂就繼續加長搜尋資料的週期,過段時間回來就會像突然打通任督二脈一樣成功做出來。當然這方式缺點是學習時間超~級長,但每個人的學習狀態各有不同,或許在他人眼中算不上好,如果能讓自己繼續堅持學習,我想那肯定就會是對自己來說的「好方法」了。

這篇文章 【徵文賞-互動藝術】佳作|P5.js學習筆記:時間之隙Time gap – 羅瑋婷 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
科技藝術初階入門看這篇準沒錯!! 新媒體、科技與程式藝術創作入門講座 https://creativecoding.in/2022/10/24/generative-art-basic/ Mon, 24 Oct 2022 03:16:34 +0000 https://creativecoding.in/?p=3001 對科技藝術總是抱著忐忑不安的心情,以至於還不敢踏進來嗎?本篇藉由科技藝術初階入門看這篇準沒錯!! 新媒體、科技與程式藝術創作入門講座直播影片內容作撰寫,藉由跨領域分享與實作教學,讓你跟我們一起安心入門。

這篇文章 科技藝術初階入門看這篇準沒錯!! 新媒體、科技與程式藝術創作入門講座 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
對科技藝術總是抱著忐忑不安的心情,以至於還不敢踏進來嗎?本篇整理自科技藝術初階入門看這篇準沒錯!! 新媒體、科技與程式藝術創作入門講座直播影片,應 ITSA – 教育部智慧創新跨域人才培育計畫的邀請,老闆以新媒體藝術家的角度,分享目前程式藝術界的發展脈絡和創作入門,也藉此引領有興趣的同學們入門。上半場以科技藝術 Creative Coding 做開場介紹,適合初學者快速通盤了解科技藝術目前在市場上面的應用,以及如何使用如 MaxMsp 或是 p5.js 等現有工具進行創作連結,將基本程式使用延伸到創作。下半場以 p5.js和 MaxMsp 的介紹與創作教學為主軸,包括如何應用與未來趨勢分享,如果想要了解更詳細的創作撇步,歡迎至老闆的互動程式藝術創作課程喔!

科技藝術初階入門看這篇準沒錯!! 新媒體、科技與程式藝術創作入門講座

什麼是 Creative Coding?

通常大家比較常將 Coding 認知為解決問題的一種工具,以比較制式的方式去解決設定好的問題。而 Creative Coding 在新媒體藝術領域來說,是結合設計、工程、數學、動態、程式邏輯與硬體的一種創作形式,嘗試在不同事物間建造一座溝通的橋樑。只要擁有程式的基礎概念、能夠靈活運用以及美感具備,就能創作出有趣的作品。以池田亮司,這位來自日本的聲音和視覺新媒體藝術家舉例,其藝術創作多是以資料轉化為視覺藝術模式進行,並投射在物件上,使觀眾在進入藝術展間時,有種身處異空間的錯視感;或是知名沉浸式內容製作公司 TeamLab,以商業型展覽為主,藉由展品與觀眾間的互動模式呈現作品;除了在展覽上的呈現外,像是演唱會或是公共裝置藝術也是現今常被應用的管道。

「Floating in the sky – VR experience」- 吳哲宇(取自吳哲宇個人網站

老闆以「Floating in the sky – VR experience」介紹其創作理念,藉由個人的想法作為出發點,使用了 UNREAL 遊戲引擎、MaxMsp和自行製作的音樂, 結合軟體與硬體間的互動所呈現的有趣 VR實境作品。還有像是「Net Device – The Gambling Lamp」及「Explode – Motion Capture Performance」這幾項作品,帶出不同事物之間,皆能以程式來進行對話,甚至最終變成視覺化的藝術創作。

Creative Coding 對概念的視覺化,強調用不同領域及不同的觀點將自身的角度陳述出來,像詩意運算就是早期在做 Creative Coding 的藝術家所提出來的概念,藉由程式撰寫所表現出的質感、顏色或是律動的模式,如 Tyler Hobbs高偉俊介 或是 Matt Deslauriers,這些具有燈光藝術與裝置藝術背景的創作者作品,在與藝術創作時所提到的「心流」有極大的相似之處。

現在 Creative Coding 最主要的發展方向強調的是,所有人皆能上手的程式語言撰寫,建立現有的程式資料庫,讓沒有程式背景的人在有足夠認知的能力下,也能快速反應的應用方式。而在創作時還是建議,作品本身觀看時,可以不用解釋也能理解其想表達的事物。

從網頁教學到 Creative Coding 教學

HaHow好學校的網頁設計課程
〈動畫互動網頁程式入門 (HTML / CSS / JS)〉
HaHow好學校的網頁設計課程
〈動畫互動網頁程式入門 (HTML / CSS / JS)〉

最初,老闆是以視覺平面設計師的角度教授動畫互動網頁程式入門 (HTML/CSS/JS),在課程中使用 Codepen 或是 OpenProcessing,希望引導設計師們不只是使用程式,更希望能創造出想要的網頁視覺樣貌。以 Vue.js 舉例,一般具工程背景的同學大部分拿它做出網頁的資料框架,但老闆將其應用,做出互動式網頁鋼琴作品

為了將互動式網頁進階與特效做結合,老闆開設了第二門課程,動畫互動網頁特效入門(JS/CANVAS)。在網頁設計的教學歷程中,發現從顏色、平面設計或是為了動態設計而應用到的三角函數等數學(延伸閱讀 : 來用可怕的三角函數做網頁吧! -Part 2科幻時鐘(直播筆記)),這些其實也都是 Creative Coding 應用內容。

其實,使用 Coding 的邏輯也能套用在不同的傳統藝術作品上,舉例來說,許多印象派的畫作皆由不同的筆觸重複堆疊而成,而 Creative Coding 也能使用相同的概念去創作,再應不同的創作設計出不同想法,將客觀物體經由本身的主觀認知詮釋成新的作品。也因此開設了第三門〈互動藝術程式創作入門 (Creative Coding)〉,使作品不限於視覺、聲音、投影或裝置藝術等等,是跨足所有互動相關開發的核心概念。(延伸閱讀 : 章節一 Creative Coding程式創作是甚麼

目前老闆仍持續應用 p5.js 和  OpenProcessing 做創作及教學,前期也有在 C-LAB 工作坊作做分享(延伸閱讀:創意程式設計:Processing/p5.js教學與趨勢觀察——王連晟、吳哲宇台美連線對談)。

p5.js網站首頁(取自p5.js網站首頁)

p5.js 的由來是一位在紐約新媒體藝術家, Lauren Lee McCarthy 所建立的,將開源式語言 Processing 以 Javascript 語言做應用,只要能夠跑瀏覽器就能創作,像是現今流行的 Sketch 和 Figma 等設計工具,就是應用了瀏覽器虛擬化的特點,不用再多安裝任何軟體,在網頁上即可進行。而 p5.js 也藉由其免費及開放資料庫的特性,降低了學習門檻,吸引更多人進入 Creative Coding 的領域。

在上半場的分享中有許多踴躍發言,以下為紀錄同學與老闆的問答:

Q:如何在實作上使用 UNREAL,操作以上所提到的效果並搭配音樂?
A:可以在每節旋律上擷取重拍的位置做效果,或是依據旋律的大小聲做變化。

Q:如何調適創作時的低潮?
A:在創作時必然有自己或他人不喜歡的作品,但還是鼓勵可以從每一次不同的產出中獲得不同的養分,變成下一個的創作靈感。老闆提供自身經驗說到創作的想法來自將日常所發生的點滴記錄下來,或者是平日感興趣的問題也能作為深入探討的目標。

Q:如何使用硬體 EYESY 來做生成式藝術?
A:藉由音樂的輸入,與程式的應用,傳導出生成式藝術。

接續上半場的應用介紹,下半場老闆二話不說實際展示了 Live coding 線上 Demo 給同學們。

p5.js 線上 Demo

本次 Demo 為介紹基礎應用,以下介紹會使用到的 API 及創作成果,使用 Openprocessing 做撰寫,各位直接點擊連結便能開始創作。

應用 API 介紹

  • createCanvas(width, height):創建畫布,參數中分別輸入寬跟高的大小。
  • background(colorCode):制定背景色,可依照文件輸入色碼參數或是基本顏色英文名稱。
  • ellipse(x, y, width, height):在 (x, y) 上繪製一個寬高 (width, height) 的橢圓形。
  • circle(x,y,d):在 (x, y) 上繪製 d 大小的圓形。
  • mouseX():滑鼠沿著左右移動。
  • mouseY():滑鼠沿著上下移動。
  • frameCount():控制每一秒產生的 frame 格數。
  • random():亂數,沒有傳參數時,會來回的隨機浮點數。
  • fill():填入圖形顏色,依照 colorMode 選擇的填色模式填入對應的參數。
  • stroke():圖形邊框顏色,依照 colorMode 選擇的填色模式填入對應的參數。
  • strokeWeight():邊框粗細,依照填入的數字大小。
  • if-else:判斷多種不同條件執行。

基本程式裡分成兩個部分,setup 與 draw。前者代表在畫布上的設定,後者代表不斷在畫布上重複著畫上新東西的動作。而 function 則是指動作的集合。以下先依序講解如何應用基本 API 設定。

一、背景顏色置換示範
function setup() {
  createCanvas(windowWidth, windowHeight);
  background(100); //色碼
}

function setup() {
  createCanvas(windowWidth, windowHeight);
  background("red"); //顏色名稱
}

第一步,先建置畫布,設定畫布的大小及顏色。尺寸使用 createCanvas(width, height) 在參數中分別輸入寬跟高的大小。而畫布顏色使用 background(),並在括號裡依照文件填入色碼(上)或是基本顏色名稱(下)。

二、繪製圖形、圖形大小與顏色變更示範
function draw() {
  fill('black')
  if(mouseIsPressed){
    fill('red')
  }
  stroke('white')
  strokeWeight(2)
  circle(mouseX,mouseY,mouseX+random(50))
}

第二步,畫布上的圖形建置。圓形隨著滑鼠的位置出現,大小會隨著滑鼠在 X 軸上的移動加上到50間的亂數做變化,圓形外框為白色的並且粗細設定為2。在按下滑鼠鍵時,圓形將會被填上紅色,如沒有便是黑色。

三、示範成果
function setup() {
  createCanvas(windowWidth, windowHeight);
  background('black');
}

function draw() {
  fill('black');

  if(random()<0.2){
    fill('white')
  }

  if(mouseIsPressed){
    fill('red')
  }

  stroke('white')
  strokeWeight(2)
  rect(mouseX,mouseY,mouseX/2+random(50))}
}

在這邊,我們先設置一個與視窗長寬相符的黑色畫布,並且在上方生成在不同情況下會有不同外觀改變的長方形,正常情況下,為黑色方形,外框為白色的並且粗細設定為2,而大小會隨著滑鼠在 X 軸上的移動除以2加上到50間的亂數做變化。在亂數小於0.2時,就會變換為白色方形,當按下滑鼠鍵時,則會是紅色方形。將上述 API 整合使用,便會出現以下的Demo範例。

Demo

應用以上基本教學,加上自己思索想要的圖樣,開始小試身手看看!

什麼是 MaxMsp?

MaxMsp 網站首頁(取自 MaxMsp 網站首頁)

MaxMsp 本身具有程式語言的概念,以 Creative Coding 應用在音樂的視覺化效果呈現。其撰寫與 p5.js 的不同在於,一般會以程式碼顯示,但在 MaxMsp 是直接以視覺的圖案的方式做呈現,將語言命令可視化成一塊一塊的圖形,再依位置的安排去創造不一樣的效果,串接出不同的流程。

MaxMsp 實際應用(截圖自本講座影片)

如何開始撰寫呢?在打開版面後,我們能運用兩側及上下方的按鈕來做指令,或是在空白處左鍵點擊兩下叫出長方形空白格,並在空白格內打入文字指令。

以下為本次示範有使用到之按鈕與指令名稱:

  • delay:接收訊號與要延遲多久,假設在delay處設定1000,等於在觸發第一個動作之後,隔一秒才會觸發接在delay後的動作。
  • cycle:在這邊就代表著數學中三角函數的 sin,代表正弦曲線。
  • toggle:控制物件或是介面的開與關
  • scope:類似於製波器
  • dac:將數位的訊號變成類比的訊號
  • ~ :代表輸出時是類比的訊號,為一連串的音訊作呈現
  • saw:鋸齒波
  • tri:三角波
  • slider:藉由在slider上面的滑動製造出聲音
  • kslider:虛擬鋼琴鍵盤
  • mtof:轉換音符對應到的頻率
  • function:設定 ADSR
  • metro:節拍控制
  • sub patch:子函數
  • midiinfo:可讓 midi 裝置在 Maxmsp 裡呈現
  • polyin:可一次取得多個聲音輸入

如何製造出音符?

藉由訊息傳遞數字的不同,連結上 slider 後,再藉由觸發的時間點差異去形成一顆音符。再音高上面,則可以使用虛擬鋼琴鍵盤 kslider,將鍵盤上的音符轉換成頻率,透過視波器去看再圖形上面的呈現。

對於聲音的控制,最主要的兩點為音高與音量大小,傳統在音樂合成上有 ADSR 作為進行的代表。ADSR 字母分別代表了四個不同意思,分別是Attack 、Decay 、Sustain、Release,中文意思為起音、衰減、延音、釋放。

ADSR 圖像(取自維基百科

起音:從無聲音開始上升到最大音量所用的時間。

衰減:最大音量下降到指定的維持音量所需的時間。

延音:主要聲音持續的時間。

釋放:延音到無聲音所需時間。

經由 function 撰寫 ADSR 後,我們得以此控制音量的大小,再加上節拍的控制及前面的波長頻率設定,就完成了基礎 MaxMsp 範例,將音符呈現。

MaxMsp 實際應用(截圖自本講座影片)

再更進階要取得多個音符一次輸入的話,將上述一個音符所應用到的程式函數化,使用 sub patch 濃縮至一個圖形中。如要外接 MIDI 音樂數位介面,且多個音符同時呈現,只要設置 midiinfo 讓 MIDI 音符輸入,再以 polyin 取得同個模組多個聲音,就能製造出好玩的音樂。老闆也分享自身經驗,在前期街觸到 MaxMsp 的 noise 功能後,發現與節拍還有音符的結合創造出非常有趣的東西,因此也鼓勵同學能多方嘗試,玩出興趣也激盪出不同的火花。

新媒體藝術家與新媒體藝術未來趨勢發展

來到講座的最後,老闆分享對於新媒體藝術的未來觀點,新媒體藝術在之後還是會持續存在,不過重點是應用的軟體或平台可能會有所改變,而身為創作者,我們要如何去融會貫通各種不同的應用,以及背後的創作理念呈現的思考方式,都是可以多加著墨以應變未來變化。

例如,元宇宙,將所有3D物件都無資料庫化,以類區塊鏈的方式,將所有人的東西都在網路世界做一個副本,虛實整合,所以不論是虛擬世界及現實世界都能執行交易。也帶領傳統藝術家經由生成式藝術觸發更多不同的靈感。老闆建議,如果要嘗試開始進入新媒體藝術的同學可以從 p5.js 開始下手,或是經由觀看多位不同新媒體藝術家的作品了解應用。

Q. 數位的東西得以快速實踐以及被改變,何以說明所謂的原創?
A. NFT 其實就是以數位正本的概念去運做的,所有人在網路上的交易紀錄都能被認得與證明,清楚的說明所有權的歸屬,這也才造就價值,以限量性和稀有性。

建議從最終想要達到甚麼樣的目標,去開始思考,能從何種媒材下手運用,再來進入到可以使用哪些資源開始學習與實踐。

結語

看完影片和文章後也對科技藝術躍躍欲試了嗎?加入互動藝術程式創作入門課程開始學習吧!還有不要忘了追蹤老闆 Twitter 和訂閱老闆,來點寇汀吧。Boss, CODING please. Youtube 頻道隨時補充新媒體藝術的養份,讓我們一起探索這多元的世界!

此篇直播筆記由幫手熊柑協助整理

這篇文章 科技藝術初階入門看這篇準沒錯!! 新媒體、科技與程式藝術創作入門講座 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
圓圓圈圈:利用迴圈呈現重覆的美 https://creativecoding.in/2022/07/28/cc-ch5-circle/ Thu, 28 Jul 2022 11:32:00 +0000 https://creativecoding.in/?p=2951 「重複」,在藝術表現或日常中很常見的概念,在Creative Coding的領域內更是大量被使用的表現手法,跟大家分享如何在程式創作內加入「重複」概念及實作。

這篇文章 圓圓圈圈:利用迴圈呈現重覆的美 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
在進入正題之前,先請大家觀察下方的圖片。花磚雖然不是台灣傳統建築的「專屬記憶」,但飄洋過海以後落地生根,逐漸在這裡發展出自己的特色。在單一磚片上設計出花紋,透過大量且重複地排列,形成獨特的空間氛圍,也連結成我們小時候的回憶。

「重複」──在藝術表現或日常中很常見的概念,或存在於大自然的晶體結構中、或存在於阿嬤家的廁所廚房內。以音樂而言,在同一首曲子中常可聽到反覆出現的旋律;以文學而言,詩歌中也常出現反覆的句子或單字等;以視覺而言,經由單一的圖案或形體,上下左右不斷的重複予人單純、規律的感受。

在Creative Coding的領域內重複更是大量被使用的表現手法,像是改變物件大小、方向、時間、頻率,或是重複粒子、文字、符號、紋理、以及動作等,善用重複可以讓畫面看起來有整體感。今天就要跟大家分享如何在程式創作內加入重複的概念,以及如何用利用「迴圈」快速製造相同的物件。

各式各樣的汽水罐整齊排列,形成一個奇妙的汽水秩序世界。 
Soda Fantasy @ Che-Yu wu
各式各樣的汽水罐整齊排列,形成一個奇妙的汽水秩序世界。
Soda Fantasy @ Che-Yu wu

目標介紹

  1. 瞭解程式中達成重複的「for 迴圈」概念與常見的應用方式
  2. 瞭解如何在重複中套用規則與創造變化
  3. 嘗試不同的重複概念應用與變化
  4. 結合變數、使用者操作創作重複的作品

迴圈可以重複執行同一組程式碼,幫我們處理不斷重複的事情。 for 迴圈 – 需要以程式碼執行次數作為迴圈的條件。

// for 的基本語法結構
for(計數變數的起始狀態; 結束條件; 每次結束後變數如何變化)
  {
    概念相同,需要重複執行的事件
  }

// 舉例
for(var i=0 ; i < 3 ; i++){
  console.log(i)
}

根據上面的概念,如果我們要在畫布上每 100px水平間隔畫一個圓且重複三次,可以有下面兩種寫法:

// 寫法一:手動複製貼上=人工迴圈
ellipse(0,100,30,30)
  ellipse(100,100,30,30) // 相較於上面,右移動了 100 px
  ellipse(200,100,30,30) // 相較於上面,又右移動了 100 px

// 寫法二:使用程式語言的 for 迴圈
for(var i=0; i<3 ; i++){
  ellipse(100*i, 100, 30, 30)  // 計數變數 i 只要小於 3 時都會做這件事,直到不滿足條件則停下並跳出該程式區塊
}

俗話說的好,能交給別人做的事就不要自己做,善用迴圈可以幫助我們快速處理類似的事件。除了單層的for迴圈以外還有巢狀個for迴圈結構:

for(var i=0; i<2; i++){
  for(var j=0; j<2; j++){    // 在每一個 i 中,都會這層迴圈完再跳往下一個 i
    ellipse(50*i, 50*j, 40)  // 分別於 (50*i, 0) 和 (50*i, 50) 畫圓,畫完之後再往下一個 i 繼續重複
  }
}

在上述的例子中,可以把巢狀迴圈想像成時鐘的分針跟秒針,秒針要跑完一圈,分針才會前進一格。同樣地,外層迴圈i要等內層迴圈j全部跑完才會再+1,所以當j是0和1的時候,分別在(50i, 0) 和 (50i, 50) 的地方畫圓,接著j又會從0開始印,直到外層迴圈結束。(延伸閱讀:[JS] 迴圈筆記

以上了解迴圈的概念後,我們試著用迴圈來創作屬於自己的作品吧。由於Ju編最近去了一個有趣的音樂表演活動Rangeselector,由台灣另類電子搖滾樂團眠腦主演,串連影像、空間動態感測技術所編製的新型態live session,除了隨著節奏跳動的幾何粒子等動態畫面外,觀眾也可以透過移動位置來和展場的視覺產生互動。聽完這場很不一樣的live現場後,覺得或許也可以將自己喜歡的音樂當成主題,來進行Creative Coding的創作。

這次的靈感來源為台灣樂團The Fur. – Friday Love,復古的曲風配上輕快活潑的歌詞,行版的節奏讓人忍不住想跳起舞來,就像一顆又一顆的彩球。藉著這首甜蜜的歌曲,來個類專輯封面的創作吧!

首先我們挑選一組具有復古感的色票,這邊選用的以粉色、紅色系為主,配上米白和橘咖等輔色。既然是專輯封面,那歌名是一大重點,為了凸顯歌名我們試試看在Illustrator製作標準字並輸出,所以在規劃作品草稿時可分為靜態的標準字圖片和動態生成的彩球兩個部分。

復古的配色常以暗濁的暖色調為主,明度和純度都比較低。

如何在OpenProcessing導入圖片呢?我們可以把圖片上傳到第三方平台Imgur,然後把圖片當作背景來使用。

接著來準備下方空白處的彩球,定義一個陣列colors把挑選好的色票放進去,再準備一個circles的空陣列。我們要做一組4*4共16顆的彩球,這邊定義5個變數x, y, d, num, col,分別代表彩球在x軸和y軸的產生位置、彩球的大小、個數和顏色,利用巢狀迴圈的結構產生共16顆:

function setup() {
  createCanvas(600,600);
    let seg = 4;
    let w = width / seg;
    for (let i = 0; i < seg; i++) {
      for (let j = 0; j < seg; j++) {
        let x = i * w + w / 2; //x軸產生位置
        let y = j * w + w / 2; //y軸產生位置
        let d = random(0.5, 1) * w; //彩球大小
        let num = int(random(1, 4)); //彩球個數
        let col = random(colors); //彩球顏色
        for (let k = 0; k < num; k++) {
          circles.push({
          x: x,
          y: y,
          d: d * 0.7,
          c: col
        });
        movers.push(new Mover(x, y, d * 0.5));
      }
    }
  }
}

把準備好的彩球畫出來,注意圖層的順序必須畫在background上方,為了避免跟畫面上的其他元素重疊,位置和大小也要稍微調整一下。

function draw() {
  background(img);
  translate(width / 2, height / 2); // 定位在畫布中間
  scale(0.5); //範圍大小
  translate(-width / 2, -height / 4); // 定位在畫布偏下

  for (let c of circles) {
    fill(c.c); // 用變數c的顏色來填充
    circle(c.x, c.y, c.d); // 畫在變數x,y的位置、變數d的大小
  }
  noStroke();
}

現在我們有一顆又一顆的基本彩球了,看起來是不是很像糖果呢?為了替畫面增加一些動態性,我們在彩球旁邊增加幾顆移動的小彩球,這邊需要分為三種function:定義小彩球參數的constructor、畫小彩球的show、移動小彩球的move。在OpenProcessing的語法庫中,有一些常見的數學常數可以做使用,比如下方用到的PI,可以很快速地引入使用。

let movers = [];

class Mover {
  constructor(x, y, r) {
    this.x = x;
    this.y = y;
    this.r = r;
    this.cs = this.r * 0.4; //第一種大小 
    this.cs0 = this.r * 0.4; //第二種大小
    this.t = random(100);
    this.off = 0;
    this.tStep = random(0.01, 0.05);
    this.ang = random(PI); 
    this.aStep = random(-1, 1) * 0.01;
    this.col1 = random(colors); //第一種顏色
    this.col2 = random(colors); //第二種顏色
    while (this.col1 == this.col2) {
      this.col1 = random(colors);
    }
  }

  show() {
    push();
    translate(this.x, this.y);
    rotate(this.ang); //旋轉的角度
    stroke(255); //加上白色邊框以凸顯小球
    fill(this.col1); //
    if (this.cs0 * 0.15 < this.cs) {
      fill(this.col2); 
      circle(this.off, 0, this.cs);
    } //錯開大球和小球的顏色
    pop();
  }

  move() {
    this.off = map(sin(this.t), -1, 1, -1, 1) * this.r; //彩球正面的角度
    this.cs = map(cos(this.t), -1, 1, this.cs0, 0); //彩球背面的角度
    this.t += this.tStep; //彩球的速度 
    this.ang += this.aStep; //彩球的圓周速率
  }
}

記得在 setup 的地方把 movers 推入 Mover,這樣我們就有移動的小彩球囉!

movers.push(new Mover(x, y, d * 0.5));

這樣就完成啦,希望大家喜歡這次的分享唷,一起試試看如何利用迴圈創作吧!

成品請往這邊走 👉🏻 https://openprocessing.org/sketch/1560267

歡迎加入互動藝術程式創作入門(Creative Coding)線上課程,課程中你可以認識程式與互動藝術產業應用,開啟對工程跟設計的想像,學會使用 p5.js 開發互動介面,整合繪圖、音訊、視訊、文字、3D、互動與機器創作完整的作品,並將創作輸出應用在個人品牌或網站、主視覺或海報,甚至互動裝置、遊戲與教材製作等場景,讓你對進修的資源與路線更有方向。

有興趣的朋友歡迎加入我們的臉書社團,第一時間接收活動報名消息,希望不久的將來,就能看到你跟大家分享你的生成式藝術創作囉!

此篇文章由 Jeudi Kuo 撰寫

這篇文章 圓圓圈圈:利用迴圈呈現重覆的美 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
外星圖像渲染語言?如何應用 Shader 跟 WebGL 達成絢麗視覺效果 https://creativecoding.in/2022/07/07/shader-webgl-intro/ Thu, 07 Jul 2022 08:32:00 +0000 https://creativecoding.in/?p=2909 想要在網頁中快速渲染出驚人的 3D 視覺效果和互動嗎?本篇文章老闆帶你快速入門了解 Shader、分享實作在專案中的經驗,就讓我們開始玩玩看 Shader 吧!

這篇文章 外星圖像渲染語言?如何應用 Shader 跟 WebGL 達成絢麗視覺效果 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
本篇文章老闆要來聊聊什麼是 Shader 、把 Shader 實作在專案中的經驗、以及如何開始玩玩看 Shader。 3D 技術逐漸應用於網頁上,瞭解 Shader 就可以透過 GPU ,以更快的速度渲染出各式各樣有趣的視覺效果和互動,快跟著老闆看下去吧!

吳哲宇的創作 Spike Mountains

閱讀完此篇文章,你會知道:

  • 什麼是 Shader
  • Shader 應用案例
  • 如何開始學習 Shader

相關資源

Shader 作品和必追蹤的藝術家


Shader

老闆第一次接觸 Shader,是在 Codrops 看到的 WebGL Distortion Hover Effects 這篇文章,第一印象覺得它根本就像是外星語言,因為它是非常底層的、類似 C++ 的程式語言。

滑鼠滑過物件的互動,對網頁工程師來說,大概就是簡單地在 css 寫上 &hover 然後可能換個背景圖片和顏色,再加上 transition 。但這篇文章中的 Demo 卻做出了各種讓人為之驚艷的效果,像是類似液體那樣 ㄍㄡˊ ㄍㄡˊ 的感覺、三角形漸層、稜鏡感、刷色感、鋸齒狀…等等。老闆原本想說,這大概需要研究個兩三天用很多行的程式碼才寫得出來,殊不知點開它的 code ,發現做出這麼酷炫視覺效果的程式碼,嚴格上來說只有短短的六行!

大概就是這個部分:

// hover-effect.js
void main() {
  vec4 disp = texture2D(disp, vUv);
  vec2 dispVec = vec2(disp.r, disp.g);

  vec2 uv = 0.5 * gl_FragCoord.xy / (res.xy) ;
  vec2 myUV = (uv - vec2(0.5))*res.zw + vec2(0.5);

  vec2 distortedPosition1 = myUV + getRotM(angle1) * dispVec * intensity1 * dispFactor;
  vec2 distortedPosition2 = myUV + getRotM(angle2) * dispVec * intensity2 * (1.0 - dispFactor);
  vec4 _texture1 = texture2D(texture1, distortedPosition1);
  vec4 _texture2 = texture2D(texture2, distortedPosition2);
  gl_FragColor = mix(_texture1, _texture2, dispFactor);
}
`;

為了瞭解他如何運作,老闆接觸到 Shadertoy 這個網站,裡面有類似剛剛那種 hover 效果的超級進階版應用,像是用 200 行左右的程式碼做出 超逼真海水 ,或者像這樣利用造點圖片加上扭曲旋轉效果即完成的 銀河 Galaxy

Shadertoy 上的範例作品銀河 Galaxy
Shadertoy 上的範例作品銀河 Galaxy

什麼是 Shader ?

What is a fragment shader?

Shaders are a set of instructions, but the instructions are executed all at once for every single pixel on the screen. That means the code you write has to behave differently depending on the position of the pixel on the screen. Like a type press, your program will work as a function that receives a position and returns a color, and when it’s compiled it will run extraordinarily fast. - The Book of Shaders

Shader 是繪製螢幕上內容的著色器,最重要的特性在於它是以每顆像素個別做渲染的方式運作,可以想像成活字印刷機,透過定義每顆像素在每個位置的表現組成一個完整畫面。

為什麼 Shader 渲染可以這麼快?

因為它不是用 CPU ,而是用 GPU 來運算。 CPU (中央處理器)通常被大家理解為是電腦的大腦,負責執行作業系統所需的指令與程序,它是線性的加工廠,一次可以處理一個工作。而 GPU (繪圖處理器)則是由許多更小也更專業的核心組成,所以我們就可以一次性地送出我們想處理的像素,一次性地處理完之後,再渲染出來。

用水管來比喻的話, CPU 就像一根大水管,但它一次只能處理一顆像素,而我們有堆積如山的像素等著被處理; GPU 則像是很多個水管並列,所以我們可以讓很多顆像素同時通過不同的小水管。

圖片來源:The Book of Shaders
圖片來源:The Book of Shaders

但是問題來了,我們要怎麼告訴這些不同的小水管,每顆像素該如何做處理呢?

在撰寫 Shaders 時使用的語言是 GLSL (OpenGL Shading Language) ,也稱做 GLslang ,是一個以 C 語言為基礎的高階著色語言。它讓我們可以跟 GPU 溝通,安排每個小水管該負責什麼工作。

這也是讓 Shaders 看起來不是很平易近人的原因。

首先,為了讓每根小水管能夠同時獨立運作,它們彼此之間的資料會是單向且無法溝通的,就像上方圖片示意那樣,資料處理的方向必須是相同的,而且每根水管都沒有辦法知道彼此處理完的像素變成什麼樣子。此外,因為 GPU 會讓工作接踵而至,換句話說會一直塞東西進水管,所以這些水管也就忙到沒辦法記得它們自己上一個工作的內容。

Each thread is not just blind but also memoryless. Besides the abstraction required to code a general function that changes the result pixel by pixel depending on its position, the blind and memoryless constraints make shaders not very popular among beginning programmers. - The Book of Shaders

Hello World

讓瀏覽器顯示 Hello World 通常是學新語言時會做的第一個練習,但是要在 GPU 領域渲染文字是件相對困難的事情,所以這個範例就用色塊來說明:

#ifdef GL_ES
precision mediump float;
#endif

uniform float u_time;

void main() {
  gl_FragColor = vec4(0,0,0,0); // red, green, blue, alpha
}

接著也可以嘗試代入變數uniform

我們可以透過 uniform 從 CPU 發送資料到 GPU ,且透過 uniform 宣告的變數會是全域且獨特的,可以在所有的 Shaders 中讀取。

#ifdef GL_ES
precision mediump float;
#endif

uniform float u_time;

void main() {
  gl_FragColor = vec4(abs(sin(u_time)),0.0,0.0,1.0);

  // gl_FragColor = vec4(abs(sin(mod(u_time, 0.5))),0.0,0.0,1.0); // 例如這樣寫可以讓閃爍變快
}

在 GLSL 中有提供許多計算數值的 functions ,像是 sin(), cos(), tan(), asin(), acos(), atan(), pow(), exp(), log(), sqrt(), abs(), sign(), floor(), ceil(), fract(), mod(), min(), max() and clamp() 等等,我們可以用這些函式搭配時間做出會不斷變動的圖形。

gl_FragCoord

除了像上面的範例那樣,用 uniform 宣告同樣的 input ,再用 default output vec4 gl_FragColor 呈現結果的做法外, GLSL 也給了我們 default input vec4 gl_FragCoord ,其中儲存了每個水管正在處理的 pixel 或 screen fragment 的座標,有了這個資訊,我們就可以針對每個座標做個別的處理,而這個情況下所使用的變數就不會叫做 uniform ,而會稱作 varying 。

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
  vec2 st = gl_FragCoord.xy/u_resolution;
  // vec2 st = gl_FragCoord.xy/u_mouse; // 例如這樣可以用滑鼠改變漸層的位置

  gl_FragColor = vec4(st.x,st.y,0.0,1.0);
}

在 Shader 裡面畫圖形是很困難的事情

因為用「點」連成「面」是一個相對高階的概念,在 GLSL 中如果要做出形狀,就得把每個邊的位置都計算出來之後再組合起來,才可以變成圖形。所以就會需要很多角度、三角函數、指數等等的數學計算。


Shader 可以做什麼?

把 Shader 做為材質來使用

可以用圖層的概念來想: 基礎圖形 + 一些 filter + 扭轉座標 = 看起來就會像有躁點的漩渦。

把 Shader 用在 3D 的模型上

用 Shaders 渲染一顆 3D 的球,也可以根據滑鼠位置做變化。

綜合應用

用 p5.js 畫一張動態圖片 + 把 Shaders 做成扭曲 filter。

如果註解掉 frag 標籤下, void main(){} 裡面的這三行程式碼,就可以得到沒有經過 shader 濾鏡的原始 p5.js 動態畫面:

distorted_st.x+=cnoise(vec3(st.x*5000.,st.y*3000.,u_time))/(1.+(sin(sqrt(st.y+u_time/20.)*50.)+1.)*500.)/2.; // 電視雜訊 1
distorted_st.y+=cnoise(vec3(st.x*5000.,st.y*3000.,u_time))/(1.+(sin(sqrt(st.y+u_time/10.)*50.)+1.)*1000.)/2.; // 電視雜訊 2
distorted_st.x += sin(distorted_st.y*(50.+sin(st.x)*20.)+u_time)*distorted_st.y*distorted_st.y/10.; // X方向的扭曲

Shader 就像是非常高功能的透鏡,但困難的點在於,我們要定義每個像素經過這個透鏡的行為。

與 3D 整合:Three.js – Displacement map

3D 軟體的渲染,像是 Unreal、Vray、Octane 等等軟體內的材質編輯器,跟 Shader 運用的概念都一樣,所以如果沒有要做到更底層的應用,使用 Shader 就像是在自討苦吃。因為把 Shader 做為 3D 環境的材質來使用,勢必得考慮光影的渲染,例如光打到某個點上,材質會如何變化、入射方向、反光效果等等,會更加複雜。

例如要做出像磁磚獲木紋那樣凹凸的效果,除了貼上紋理之外,還需要告訴軟體根據這個紋理渲染對應的陰影。 Shader 的 displacement map 就是透過指定一個畫面,算出對應的陰影和光線反射,讓整個畫面看起來更真實。

應用案例

日本藝術家 Sayama 的創作

日本藝術家 Sayama – 200426

實務應用

所有技術最重要的還是要能夠應用,譬如工作室願意把它用到上線的專案中,它才有意義。

實務上老闆把 Shader 拿來畫 OUTERNETS 的 Home 和 About us ,做出光暈和躁點效果,還有非常繽紛科幻可以跟滑鼠互動的旋轉球球。

Outernets

Outernets
Outernets

Outernets – About us

Outernets - About us
Outernets – About us

墨雨工作室也嘗試把 Shader 應用在 跟18天台灣生啤酒1起吃飯8! 這個活動網頁上,做出啤酒噴灑出來的動態扭曲效果。

跟18天台灣生啤酒1起吃飯8!
跟18天台灣生啤酒1起吃飯8!

如何開始學習 Shader ?

The Book of Shaders

這個網站用深入淺出的說明加上可以操作的範例,也提供了一個好用的 編輯器 (從網站首頁點選 Examples Gallery ,再點擊 “Hello World” 下面的色塊),可以先從這邊熟悉 Shader ,之後再嘗試放到自己的專案中。

Touch Designer

探索 Shader 也可以從 Touch Designer 開始,它幫我們把各種模組都寫好,讓我們不用寫任何程式碼,只要載入不同的圖片和效果就可以玩出各式各樣的變化。

Banana Test

例如老闆之前在嘗試的時候,把香蕉經過 transform 再合成到背景上面。

Banana test
Banana test

題外話:各位如果對 3D 有興趣的話,可以去玩玩看 Blender ,它是開源的免費軟體。

在 p5 裡面玩 Shader

ITP – p5js shaders 介紹了如何把 p5 和 Shader 結合使用,把 Shader 當成材質或者影像的即時處理。

老闆也在 OpenProcessing 製作了 Shader template ,基礎的架設都已經完成了,歡迎 fork 之後自己玩玩看囉!

簡單的 Demo

雜訊效果:可以用 rand() 給原本位置的像素一個隨機的位置資訊,就會讓畫面有看起來霧霧的效果。

// frag 標籤中的第 20 行開始
void main(){
  vec2 st = var_vertTexCoord.xy /u_resolution.xy;

  st.x += rand(st); // 霧霧的效果
  st.x += rand(st) / (1.+st.y*10.); // 上面會霧霧的,但越下面會越平滑

  vec3 color = vec3(st.x,st.y,1.0);
  float d = distance(u_mouse,st);
  color*=1.-d;
  gl_FragColor= vec4(color,1.0);
}

扭曲效果:用 sin() 給 y 位置的資訊(但因為底圖沒有東西所以看不太出來效果)

// frag 標籤中的第 20 行開始
void main(){
  vec2 st = var_vertTexCoord.xy /u_resolution.xy;

  st.y += sin(st.x/10.)/10.; // 像這樣

  vec3 color = vec3(st.x,st.y,1.0);
  float d = distance(u_mouse,st);
  color*=1.-d;
  gl_FragColor= vec4(color,1.0);
}

範例 test bubble 根據左側的底圖,做完扭曲效果後就變成右側:

void main(){
  vec2 st = var_vertTexCoord.xy /u_resolution.x;

  st.x += rand(st)/5.; // 模糊效果
  st.y += sin(st.x * 50.) /10. ; // 扭曲效果

  vec3 color = vec3(0.);
  float ang = atan(st.y-0.55,st.x-0.5) ;
  float r = sin(ang*5.+u_time*2.+u_mouse.y*3. +u_mouse.x*3.);
  vec2 displacemenetMap = vec2(cos(ang),sin(ang))*r /150. ;
  vec3 spray = texture2D(tex0,st + displacemenetMap -vec2(0.,0.2) ).rgb;

  if (!u_mouse_pressed){
    color += spray;
  }else{
    color = vec3(displacemenetMap,0.5)*500.;
  }

  gl_FragColor= vec4(color,1.0);
}

也可以拿上一格留下的畫面做扭曲,看起來就會像液體效果


結語

老闆覺得現在 3D 的趨勢應該會越來越往網頁發展,像 Autodesk 也出了 Fusion360 可以在網頁上製作 3D 物件,如果可以把這些效果應用在案子的網頁上,想必可以創作出更加吸睛的視覺。

五分鐘問答時間

Q. 會開 Shader 課程嗎?

感覺有點難募資達標,有點太小眾了😂

Q. 最近有看到什麼用 Shader 做的酷案例嗎?

可以在 awwwards 上找到很多厲害的範例!搭配 p5.js 或是 three.js 就可以用在像是 carousel (輪播)或是其他扭曲的效果。

Q. Node Editor 怎麼做?

可以使用現成函式庫 Rete.js ,把自己的 function 做成可以給前端使用的介面。但技術尚未非常成熟,用在實務要自己注意一下囉。

小範例:胎死腹中的 文章產生器 原本想說可以做一份教材,用模組編輯的方式組裝成 A, B, C… 多種不同的教材,就可以因材施教。但發現沒有特別方便,而且概念其實也蠻類似現在的筆記工具 Notion 。

老闆貼心提示: CodePen 不是工程師實務上會使用的

使用 CodePen 或者 OpenProcessing 等平台,主要是為了讓學生快速上手,不需要自己架設開發環境,如果想實作到 production ,還需要再去更進階了解 JavaScript 的模組化概念,以及使用 Webpack 或者 Rollup 之類的打包工具。


工商時間

互動藝術程式創作入門
互動藝術程式創作入門

《互動藝術程式創作入門》課程學生作品分享

Hahow 課程作業成果

課程加碼單元

此篇直播筆記由幫手 Yuan 協助整理

墨雨設計banner

這篇文章 外星圖像渲染語言?如何應用 Shader 跟 WebGL 達成絢麗視覺效果 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
五月社群聚(下):張文瀚教你用數學作畫 GLSL fragment shader https://creativecoding.in/2022/06/02/creative-coding-meetup-202205-changwenhan-shader/ Thu, 02 Jun 2022 02:21:00 +0000 https://creativecoding.in/?p=2837 第二次的 Creative Coding 社群聚,我們邀請到了聲音藝術家吳秉聖,以及 Team9 技術長、黑洞創造前端工程師及國立清華大學藝術學院的兼任教師張文瀚,下集由張文瀚介紹如何用數學作畫:fragment shader 的入門與應用。

這篇文章 五月社群聚(下):張文瀚教你用數學作畫 GLSL fragment shader 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
第二次的 Creative Coding 社群聚,上集由聲音藝術家、同時也是噪咖藝術的音樂統籌吳秉聖帶來聲音、光、裝置與創意程式的互動關係,本篇下集則是由張文瀚分享 fragment shader 的有趣創作思維。

張文瀚曾是清大藝術學院的兼任教師,教虛擬實境藝術,也是黑洞創造的前端工程師,自己開了一間 Team9 工作室擔任技術長,主要是在做遊戲,像是「文字遊戲」是只用文字做出來的一個解謎遊戲。

上一位講者吳秉聖分享的是如何用視覺化程式語言、軟體結合實體裝置,製作出互動的裝置作品(想閱讀上集的這邊請)。當大家談到 Creative Coding 通常都會直覺想到 p5.js 等等,叫電腦幫你畫出東西,慢慢組成漂亮的畫面,張文瀚介紹的則是 Creative Coding 的另一個面向、另一種 Creative Coding 的工具: GLSL 的 fragment shader,以及他跟 p5.js 相較之下的優劣勢。

如何叫電腦畫出一個圓?

先從圓的定義開始:「由距離特定座標 500px 以內的所有點集合而成的圖形」在這個畫面中的所有像素,若是離圓心 500px 以內的為黑色,不是的則維持白色。 在 p5.js 內甚至不用懂這個,只要跟 p5.js 說:「在畫布中央用黑色畫一個半徑為500的圓!」他就會幫你畫好了。

下一個問題,如何畫出一個圓,而圓內每個像素都是從黑到白的隨機顏色?

p5.js 畫不出來。

這就是 shader 派上用場的時候了!

像素等級的上色就交給 fragment shader (片段著色器),前提是要親自處理這些運算,了解數學、座標及空間的關係。 需要一些陣痛期才能轉換成 shader 的邏輯和思路,一旦上手之後就可以很順地做出細緻的作品。

為什麼會需要用到片段著色器?

如何用shader快速完成混合漸層效果

想像要做出如左圖這般混合漸層的效果,他的上色規則是甚麼?

對每個像素說,「你在越上面,就越綠;你在越右邊,就越紅。」 用程式替像素上色則變成:

for (var y=0; y < height; y++){
  for (var x=0; x < width; x++){
    var r = (x / width)*255;
    var g = (y / height)*255;
    var b = 0;
    pixels[y][x] = [r,g,b];
  }
}

如果一個畫布的長寬為 1920×1080,總共就有 2,073,600 個像素要著色,也就是為了要完成這一個漸層,這個迴圈程式碼總共要跑兩百萬次!如果只是畫一次,就算多花一點時間也沒關係,何況現在的硬體越來越強大,說久也其實不需要多久。

如果現在規則再加上一條「時間越推移,你就越藍」,而且要及時處理還能跑 60fps,1920 寬 x 1080 高 x 60 fps,每秒鐘得做1.2億次的著色指令!

CPU單執行緒,一次處理一件事
CPU單執行緒,一次處理一件事
CPU單執行緒,事情一多就塞車
CPU單執行緒,事情一多就塞車

像這樣的迴圈程式指令就像一個個的生產線,CPU的單執行緒邏輯,一次只能處理一件事情,東西一多,就會向右邊的圖一樣塞車。我們需要GPU圖形處理器的多執行緒邏輯,同時有無數跟管子並行處理。

Fragment Shader 片段著色器

片段著色器的著色工廠利用上千萬工人迅速完成圖案
片段著色器的著色工廠利用上千萬工人迅速完成圖案

片段著色器就像是一個著色工廠,用你制定好的統一規則,決定畫布裡每個像素的顏色,工廠裡的幾百萬個工人,每一個工人負責一個像素,只要工人依據規則(各種參數)對各自負責的像素著色,每人只要畫一筆,一幅畫就瞬間完成了。

優點:由於利用 GPU 並行處理,可以快速做出複雜的像素操作,某些複雜的數學運算可以直接使用硬體運算,跟電流一樣快速。

兩個最大的限制,第一個是盲視,每一個線程(工人)都是完全獨立的,無從得知其他線程的運算結果,更無法干預;第二個是無記憶,每一個線程只會知道此刻的狀況,不會記得上一刻的自己在做甚麼,每一幀都是完全獨立的。

回到原本的畫布問題,我們需要用 fragment shader ,對每個像素說:「你的紅與綠的程度是由你的 uv 所決定,而藍的程度則由時間推移所決定。」

uniform vec2 u_resolution;
uniform float u_time;

void main(){
  vec2 uv = gl_FragCoord.xy/u_resolution.xy;
  gl_FragColor = vec4(uv.x, uv.y, sin(u_time)*0.5*0.5, 1.);
}

你的每一個上色程度都是用 uv 決定,就像是每個像素的座標或是工人的名牌一樣,每個像素都有一個自己的 uv ,就可以指定它改變顏色。

Fragment shader 可以算是比較類似C語言的程式語言,撰寫著色器程式的思考模式要從單個像素的角度出發,而非畫布的整體。

以右邊的例子來說,就是對著每個像素說:

「你在畫布左半邊就是白色,右半邊就是黑色;但你跟滑鼠的距離若是在畫布大小 5% 內就是紅色。」

用 shader 寫出跟隨滑鼠移動的紅點
用 shader 寫出跟隨滑鼠移動的紅點
uniform vec2 u_resolution;
uniform vec2 u_mouse;

void main(){
  vec2 uv = gl_FragCoord.xy/u_resolution.xy;
  vec2 dist = uv - u_mouse.xy/u_resolution.xy;
  vec3 color = mix(
    vec3(step(uv.x, 0.5)),
    vec3(1,0,0),
    step(length(dist), 0.05)
  );
  gl_FragColor = vec4(color, 1.);
}

Shader 不可思議之最:空間折疊

若要在畫布上畫出一百個圓,最直覺的想法是用迴圈,但要畫的圓越多,指令要執行的次數越多,有沒有其他不用迴圈卻能達成同樣效果的方法?

利用簡單數學運算完成2x2的四個圓
利用簡單數學運算完成2×2的四個圓
利用簡單數學運算完成2x2的四個圓
利用簡單數學運算完成2×2的四個圓

在畫布中心畫一個圓形(上方左圖),並將水平與垂直線分別均分十等份,做 0.0 到 1.0 標號,接下來只需要一個數學運算 uv = fract(uv * 2.0 ); 取餘數的小數點(捨去整是數1),瞬間就能變成四個圓形(上方右圖),每一個方塊其實都是原本完整的 0.0 到 1.0 , 1.0 改成 0.0、1.2 變成 0.2,以此類推,x 和 y 都是相同邏輯。

我們只用了一個數學運算式便把一個圓形變成 2×2 四個,舉一反三,不費吹灰之力就可以變成 5×5、10×10、100×100 的畫面,無論在這個圖上渲染多少個圓,都不會消耗額外資源,僅僅改變數學運算裡的一個參數!效能的高低只要是看指令執行的多寡,像這個例子只有一行運算,完全不會有效能上的差異,連在手機上也可以跑,很多 shader 吃效能是因為畫面的細緻要求和大量的運算。

理論上,你可以擁有無線長寬、無限縮放的畫布,極限僅在於你的像素多寡而已。這個感覺像是你先看一個圓, zoom out 將攝影機往外拉,看到一百個,再往外拉,看到上萬個,用極少量的運算做到複雜的視覺效果。

但,如果只能在每個空間複製一模一樣的圖案,那就太單調了。讓每個小空間內都出現不同的變化需要另一個數學的運算:取 floor 把小數點去掉,進而得到他的 ID 身分證明,再依據該圓圈 ID 的 x 值做出圓形半徑改變。

live coding 一下:

首先在畫布中寫出一個圓,並製作出方才提到的空間折疊效果,然後再把圓的半徑拉出來指定,這個半徑會隨著 ID 的 x 值的不同而改變。如果把 uv 縮放得更誇張就可以看出差異,縮放 30 倍(下圖左)和 100 倍(下圖中)的效果已經明顯不同,可以利用這個方式製作許多不同的效果。若圓圈的大小還受 y 軸的影響,相乘會出現更不一樣的 pattern ;加上時間的參數,就變成了動態。

依據x值改變圓半徑,再縮放30倍
依據x值改變圓半徑,再縮放30倍
依據x值改變圓半徑,再縮放100倍
依據x值改變圓半徑,再縮放100倍
依據x值改變圓半徑,再加上y值參數
依據x值改變圓半徑,再加上y值參數

Shader 除了從全白的畫布開始畫之外,也可以當作濾鏡使用,一個範例是這個網站http://filters.pixijs.download/dev/demo/index.html,可以靠右側的控制器改變顏色、曝光、模糊、風格化等,這是 shader 實務上最常用到的應用方式。

Pixi JS 網站範例截圖
Pixi JS 網站範例截圖

如果想用 shader 創作,可以從哪個裡找到學習資源呢?

第一個是 Shadertoy 老牌的創作平台,使用純粹的 fragment shader 而無法結合其他語法,所有神人都在這裡,你在這裡會看到很多匪夷所思到無法想像是怎麼做出來的作品,尤其又以 3D 為大宗,主要也可能是因為 Ray Marching 這個技術特別流行,大家嘗試了很多在 2D 畫布中渲染 3D 物體。

另一個創作平台是大家更熟悉的 OpenProcessing,可以用 p5.js 結合 shader 作創作,也可以使用 vertex shader + fragment shader,可以自由上傳或讀取自己的素材,達到更多不同的效果,但要小心沒有 GLSL 的語法上色,因 WebGL 版本較舊,不支援部分語法,手機支援度也較差,有視覺顯示或是無法運算等問題。 因為可以結合 p5.js ,張文瀚近期也開始改在這個平台上創作和發表作品,也做了他的 shader template 可以直接 fork 一版來做你的創作。

張文瀚<Out of bounds>作品截圖
張文瀚<Out of bounds>作品截圖,https://openprocessing.org/sketch/1540595

有參加第一次社群聚的人看到這件作品應該不陌生,這件是張文瀚上次的共創主題「宇宙」的作品。後來張文瀚也製作了一篇如何從零開始做出這件作品的教學,歡迎大家參考! 看似複雜但程式碼其實很少,只有 37 行,即使是初學者也可以透過教學文章慢慢踏入 shader 領域。對張文瀚來說,撰寫 shader 的成就感最主要來自於「僅用少少的 code 跟簡單的數學運算就可以達到絢麗的視覺效果」。

Shader 學習資源

台灣目前沒有太多中文的 shader 學習資源,不過 The Book of Shaders 即是針對入門者打造的教學網站,有翻譯成簡體中文的版本,且可以即時做範例,是最推薦的學習管道。

The Art of Code:從初學實作到進階理論都有的 Youtube 頻道,也主要針對 shadertoy 上作品的實作,全英文

Inigo Quilez 頻道:Shader 界宗師,以前貌似在皮克斯工作,動畫裡用到大量的 shader, Youtube 頻道裡多數為進階理論和 live coding,全英文

Inigo Quilez 網站:更深奧的理論與實作文章,全英文

 Inigo Quilez 在 Shadertoy 上的頻道截圖
Inigo Quilez 在 Shadertoy 上的頻道截圖

讓大家看一下 Inigo Quilez 在 Shadertoy 上的頻道,乍看真的無法相信這些細緻五官的人、風景、蝸牛等等都是用一行行的程式碼製作而成的,對於也還算初學的張文瀚在研究程式碼的時候,真的看不懂任何一行 code ,但這些作品真真確確是透過這些加減和數學運算組合而成的。

張文瀚個人作品分享

互動動態網站<體感溫差>
互動動態網站<體感溫差>截圖

第一件是替藝術家展覽製作的互動動態網站<體感溫差>,核心概念是使用 shader 當作濾鏡製作出熱像儀的效果以及熱像軌跡,左上角顯示滑過軌跡上的顏色所對應的溫度。

字畫產生器成果截圖
字畫產生器成果截圖

第二件則是文字遊戲延伸出來的字畫產生器,用純文字組成畫面,也另外開發一個小工具,方便大家做宣傳圖和素材。這個網站可以非常即時地將影片、影像轉換成文字,顯示的內文、字型、模式等都可以自由調整。

其他的作品歡迎來張文瀚的 Shadertoy 頁面 以及 Open Processing 頁面 觀看玩耍。

張文瀚的個人網頁>>https://changwenhan.com/

五月社群聚共創主題:<山>

張文瀚<And As The Sun Goes Down>

是一個靜態 shader 作品,使用到先前提到的 Ray Marching 的技術,這個山坡是用數學式所描述出來的 3D 物體,讀一張影像素材,用素材上的像素決定他的突起程度,去掉這一個步驟的話就是很一般、很光滑的 mapping,由素材本身的複雜度去決定成品最終的樣貌。 因為本身並不擅長顏色搭配,通常一件作品就保守用兩到三個顏色決定色調。

Jennifer

Jennifer共創作品

自由接案 js 工程師,「山」這個主題想到Open Processing上水墨畫的山,齊柏林在淡水的看見台灣展覽,有很多台灣的照片,所以決定做台灣的地形,月世界。

從沒有真正創作過,一開始想到是用遞迴樹(recursive tree)的方法,從稜線開始畫,但線條會相互重疊,變得很不自然,不是山稜線該有的樣子,所以認為需要改用面而非線去畫;接著在搜尋其他更好的製作方法時,找到主打資料處理、數據視覺化的 Observable 平台,參考了其中網友發表模擬珊瑚碎形的作法(網頁連結),回頭調整作品。

哲宇<Mountain & water>

吳哲宇 <Mountain & Water>
吳哲宇 <Mountain & Water> https://openprocessing.org/sketch/1519323

使用 noise 做不同層次的疊加,有一個 x 從左到右,在 y 上疊很多不同的sin 及 cos;一個大的perlin noise再乘上一個波,增加疏密的變化;另外一個比較有趣的手法,山脈往下長的這個效果是使用 mainGraphics.image(mainGraphics,0,2) 把祝張圖往下畫,上面再多疊一條又一條的線,整體畫面就呈現一直往下長的動態效果。

2022年5月也是第二次的 Creative Coding 社群聚就在這邊到一個段落了,如果還沒有看過上集由聲音藝術家吳秉聖帶來聲音、光、裝置與創意程式的人趕快點擊閱讀,這次因為疫情飆升、台北又下大雨而沒有太多的人來現場交流實在可惜,希望下一次有機會能夠在現場見到喜愛用 Creative Coding 創作的你們!

還不知道如何開始踏入 Creative Coding 嗎?那 Hahow 課程 <互動藝術創作程式入門>再適合你不過了,快加入2000位同學的行列,一起學習互動藝術創作吧!

墨雨設計banner

整理編輯:Chia 編

這篇文章 五月社群聚(下):張文瀚教你用數學作畫 GLSL fragment shader 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
初次見面請多指教!Creative Coding第一次社群聚(上)吳哲宇的生成式藝術宇宙 https://creativecoding.in/2022/05/06/creative-coding-meetup-202204-cheyu-wu/ Fri, 06 May 2022 02:59:00 +0000 https://creativecoding.in/?p=2639 第一次的社群聚,召集人吳哲宇破題開講 Creative Coding 以及 Shader 在生成式藝術領域的相關應用,分享他經典的NFT作品,最後也帶來他為這次的共創主題<宇宙>的新作

這篇文章 初次見面請多指教!Creative Coding第一次社群聚(上)吳哲宇的生成式藝術宇宙 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
2022年4月14日這個重要的日子必須紀念一下,因為喜愛生成式藝術的 Creative Coding Taiwan 社群,大家終於在臺北實體見面啦!

Creative Coding Taiwan 社群大合照
Creative Coding Taiwan 社群大合照

Creative Coding Taiwan 是由墨雨互動設計所發起與支持的社群,旨在台灣推廣互動程式設計以及任何由程式創作衍生出來的藝術作品及行為。之前一直都是在線上直播、線上課程,接下來我們希望藉由每個月的固定聚會,舉辦各種不同類型的活動,讓喜歡寇汀的大家互相交流,分享自己的創作與想法,技術上有任何不懂的,現場說不定也會有很多大神出沒可以討教哦!

什麼是 Creative Coding?

Creative Coding 顧名思義是結合程式加創意,狹義上是用程式寫一些看起來很有藝術感的圖形,廣義上是可以用程式,將世界上的各種事物賦予互動跟連結起來,創造出新的現象、關聯與有趣的呈現。用程式偵測走在路上的人群,轉換成五線譜之後播放成音樂,或是比較商業的演唱會背景,擷取歌手的影像做後製,結合動態設計,變成即時的互動背景,跟著聲音的大小、人的位置、時間等做變化,這些都是程式創作能應用的範疇。近期由於 NFT 生成藝術平台 Art Blocks 的興起,也讓更多人注意到了生成藝術與 Creative Coding 的魅力與各種可能性!

因為篇幅關係,此次的內容將這次將近兩小時的直播影片拆成上、中、下三篇,首先由吳哲宇破題開講 Creative Coding 以及生成式藝術的相關應用,最後也帶來他為這次的共創主題<宇宙>的新作(影片同時服用);中篇由叁式互動新媒體的技術美術Hoba帶來演算視覺的應用,不藏私揭露叁式近年來精彩的作品幕後祕辛(影片從這裡開始看),以及另一位與會的創作者張文瀚帶來作品 <Wormhole>分享(看看作者的詮釋及解析);下篇則是由 FAB DAO 的黃豆泥讓大家一窺<沒有市場的靈魂綁定NFT>又是怎麼一回事(影片從這裡開始看),以及第三位創作者 Mizok 帶來他的<Universe-alpha>及<Universe-beta>(作者展示)。

延伸閱讀:
初次見面請多指教!Creative Coding第一次社群聚(中)Hoba與叁式的演算視覺邁進之路
初次見面請多指教!Creative Coding第一次社群聚(下)黃豆泥:沒有市場的靈魂綁定NFT

墨雨設計創辦人 吳哲宇 <Creative Coding 是甚麼?Shader與Generative Art 應用>

對藝術家吳哲宇,也是我們口中的老闆來說, Creative Coding 程式創作是結合設計、工程、數學、動態、程式邏輯甚至是硬體的一種藝術創作形式,把程式當作畫筆,搜尋喜歡的主題,利用一行行的程式碼將世界上的各種事物連結起來、賦予互動,以邏輯思維創造出新的現象、關聯,編織成有趣互動的成果呈現。例如下方這一個神祕的生物,僅僅是用不到二十行的程式碼寫成。

哲宇用簡單算式程式碼完成的神祕生物
哲宇用簡單算式程式碼完成的神祕生物

很多人都會說你視覺要看起來有藝術感才能算是藝術。但哲宇覺得, Creative Coding 本身程式的運作以及邏輯概念是藝術的展現,Creative Coding 的魅力也正在此。

進入程式創作的世界,常使用的軟體包括 Unreal 以及 Unity 兩套3D遊戲開發軟體及引擎,MaxMSP 是一款圖形化編程語言的軟體工具,還有主流創作的 Open Frameworks 和 Touch Designer,有興趣的都可以玩玩看。

想必有許多人都是透過 p5.js 生成式藝術創作認識哲宇以及 Creative Coding 的,2020年因為疫情,哲宇而開啟了一天一 p5.js 創作的計畫,最初的起點其實都很簡單,利用三角形、圓形、線條、色彩等不同的主題,從生活中取材,隨意實驗,慢慢發展出有趣的圖像以及互動小品。包括用物理模擬做成軟軟的生物、魚鉤釣魚,或是童趣的蝸牛、用 shader 寫 DNA 等。

常使用的平台是 Open Processing 這個線上編輯器,修改程式碼能即時看到成果。 p5.js 是個入門好上手的程式語言,只要花個一週左右的時間就可以做出有趣的作品,尤其是即時視覺回饋的有趣,足以沖淡一些學習或是撰寫程式的痛苦。

p5.js 生成式藝術創作的過程其實跟一般藝術創作的過程相似,從最初始的動機,也許是個視覺想法(波浪?)或是某個靈感開始,想像不同的可能性(大小、顏色、樣態、互動等等)將草圖逐步建置成形,中途來回不停修改,像調配藥水一樣嘗試各種排列組合、疊加變形,甚至有時會有一些意料之外的驚喜,最後完成作品。

生成式藝術的核心

常看哲宇直播的人,或是 Creative Coding 台灣站的忠實讀者大概可以發現,其實生成式藝術,或說用程式創作藝術,重要的概念可大致分為以下:

  • 規則:大自然中有法則,透過探索、模仿,建立規則而非框架。
  • 限制:有限制才能激發更多的創意以及自由。
  • 核心概念及故事:也是創作的動機,賦予作品更多意義。
  • 視覺呈現:加上材質、小動態,用心雕琢細節是畫龍點睛的關鍵。
  • 變化:一成不變讓人無趣,無論是透過時間、
  • 隨機性:加入一點 random 一點 noise,讓人摸不透規則更好奇。
  • 輸入/輸出:輸入包含了影像、音像,滑鼠點擊或移動,其他外部資料或是時間;輸出則是以視覺、聲音及動態(也可能是硬體)為三個主要的方向。

像是哲宇之前利用骰子骰出來的數字控制檯燈的作品;或是將 Unreal 結合動態捕捉系統,即時接收舞者(也就是哲宇本人)的動作並顯示在四周的投影牆上,再加上物理引擎模擬,碰撞、擾動虛擬世界中的圖像,所完成的現場即時表演,這些都算是互動藝術。無論是在 p5.js 或是 Unreal 等平台,程式創作和互動的邏輯都是可以互通的。

NFT作品分享:SoulSea 以及 CryptoPochi

如果對於哲宇在 NFT 的心路歷程有興趣,歡迎右轉閱讀【老闆週六來聊聊】我開始賣NFT作品啦!生成式藝術在NFT的價值,這邊就不再多述,僅挑出兩件特別喜歡的作品跟大家分享。

哲宇在fxhash上發行的SoulSea系列作品
哲宇在fxhash上發行的SoulSea系列作品

第一件是發布在 fxhash 的 SoulSea 系列作品,其實是在做商業案子的時候,哲宇發現太漂亮到捨不得給別人,所以就自己上架。作品使用 p5.js 製作出噪聲和波形,模擬海洋的質感,從一條波浪,在多個地方疊加上 noise 產生連續且自然的波紋,加上材質等小元素,其中牽涉到了對數學、形狀的掌握度,製造出接近生活體驗、有機體的東西。

哲宇在OpenSea上發布的互動型NFT <CryptoPochi>
哲宇在OpenSea上發布的互動型NFT <CryptoPochi>

第二件是發布在 OpenSea 的 CryptoPochi ,也是一個互動型的 NFT,結合區塊鏈以及網頁的技術,以網頁的形式呈現,並使用物理模擬引擎與 Artblocks 製作互動,隨時都可以透過滑鼠去玩他,甚至製作了 On Chain Event 觸發同步事件,可以讓不同作品內的 Pochi 互相互動。

如果你是工程師,鼓勵你多看一些作品,會有一些想法和創意開始踏出利用程式碼創作的第一步;如果你是設計師,便可以從熟悉 p5.js 語法開始,慢慢地往生成式藝術的方向邁進。

在這裡也要推薦一下在HaHow好學校的〈互動藝術程式創作入門〉課程。大約兩年前開這堂線上課程時,還沒有很多人知道 Creative Coding 這個領域,如今隨著元宇宙、NFT成為夯字,也越來越多人投入。

哲宇不藏私,分享他在創作的同時,也持續思考作品商業的潛力,除了持續創作、賣 NFT 之外,另外跟很多品牌合作,從品牌的角度出發,例如跟漢堡店合作,將漢堡層層拆分,以程式藝術手法詮釋。未來硬體也會越來越強大、跑得動複雜的程式碼,之後許多公司品牌可能都會開始發展動態或是 3D 的視覺以及衍伸行銷,大家也可以想想看新媒體藝術有哪些商業應用。哲宇也趁機苦口婆心地以過來人身分勸大家不要賣自己作品的授權,因為哲宇之前曾遇過,授權給對方使用他的畫作,對方還反寄律師函回來告的情形。

Shader 與 Generative Art 的應用

哲宇用Shader創作出來的生成式藝術
哲宇用Shader創作出來的生成式藝術

Shader 就是執行在GPU上的電腦程式,控制著GPU渲染管線,處理開發者給他的各種繪圖相關的資料,即使是畫一個點、一個顏色、一個向量,也要透過 Shader 渲染。 Shader 就像是 Creative Coding 的進階版,將原本在 3D 軟體內才能看到的材質,運用 Shader 做出來。

GLSL(OpenGL Shading Language) 全稱 OpenGL 著色語言,是一個以C語言為基礎的高階著色語言,用來在OpenGL 中著色編程,這個語言的好處是因在 shader 裡面全部的東西以像素為單位做運算,若你的 GPU 越強,就能渲染出越精細漂亮的畫面,而且效能也很好。如果有興趣的話,也可以參考一些哲宇之前使用相關語言做的作品:

哲宇的作品 The Soul
哲宇的作品 The Soul

舉一件自己的作品當例子,看起來像瞳孔的這幅作品 The Soul,程式碼就非常單純,計算離中心的角度,算出像是類似山脈的偏移效果,再把顏色畫出來,從內到外,紅色是離中心距離的兩倍、綠色是離中心距離的三倍,就可以呈現這種類似極光、光譜分散的效果。

大家有興趣都可以去 fork 哲宇的 shader template (連結這裡走,不可商用、需標記來源),裡面已經準備好 shader 裡基礎的東西,從這個環境開始,可以快速完成你自己的 shader 作品.或是你可以從改一些範本中的不同參數,看會製造出甚麼樣的效果開始。

另外也想跟大家介紹一個很酷的學/寫程式的好用工具 VSCode,你可以去申請 Copilot 的功能,他可以解釋程式碼在做些甚麼,假設我這邊有一串 shader 或是任何其他語言的程式碼,選取後點選 Ask Copilot 就會出現解釋,他甚至會去猜你的變數在幹嘛,譬如說這個 p 可能是位置等。在撰寫程式碼的時候也會有一個自動輸入功能,你只要起頭,他就會幫忙填完 function 和 name 甚至是後面的程式碼,也可以把寫好的程式碼轉換成各式各樣的語言。

若想了解更多有關 shader 的知識,可以參考 TheBook of Shaders https://thebookofshaders.com/,一步步帶你了解如何使用 Fragment Shaders 開始做幾何圖形,從像素開始建構圖像、 3D 等。

Q:整包 HTML 如何上傳變成 NFT?

A:可以用 fxhash 這個平台,將你的程式碼打包成一個 zip 檔案丟上去就可以了,需要注意的是要使用官方提供的 fxhash-snippet 把每個 NFT 獨立的序號生成一個 random object(fxrand),這個 random 就能夠自行產生你在作品中所需要用到的亂數,只要作品序號相同,亂數就是一樣的。把這個部分丟進去、順利跟 fxrand 對接之後,就可以產生很多獨一無二的 NFT 了。

參考:Guide to mint a token

截圖自Guide to mint a token

Lightning talk 2 – 吳哲宇

社群聚當天,最後的一個小環節是 Lightning Talk,每一次的 Creative Coding Taiwan 聚會都會事先提供一個主題,邀請大家趁著這個機會創作出一件互動藝術作品並與大家分享。在一次又一次的共創過程中,激盪出更多更有趣的火花。

哲宇為這次的共創主題<宇宙>所作的創作 <Nebula Shift>
哲宇為這次的共創主題<宇宙>所作的創作 <Nebula Shift>

作品連結:https://openprocessing.org/sketch/1543928

用 Shader 寫的作品,移動鼠標不只有星雲飄動,還有星星閃爍。將粒子的資料輸入進 Shader 裡使用,透過 p5.js 使用多層 perlin noise 與一般的 noise 兩種不同的躁聲做扭曲,呈現出線條流動之感,另外也須計算點跟星星的距離,完成不同明暗程度的閃爍以及穿透霧氣的感覺,將 RGB 分層處理,因為光譜頻率偏差,便會有如色散的效果呈現。

由哲宇創辦的墨雨設計也持續地經營 Creative Coding Taiwan 互動程式藝術創作台灣站,無論是 p5.js 的實作教學,或是你該怎麼入門、去哪裡找資源,都可以從這邊看起。歡迎各方好手加入,一齊充實內容!


最後小小工商時間,我們第一次的社群聚會現場也請到了 AWS Activate Taiwan 的 Alex Cheng 帶著最正宗的韓式炸雞來到現場,以及分享給新創公司的好康,無論你是剛起步的小團隊,或是已經加入育成中心、新創加速器的新創公司,使用 AWS 升級服務可以獲得 US$1,000 的免費積分!有興趣的人歡迎掃瞄下方 QR Code 了解更多。

這次 Creative Coding Taiwan 四月社群聚,每位講者都帶著滿滿的知識和熱忱分享,若是你對哲宇的生成式藝術感到意猶未盡,那你一定要繼續看下去:
初次見面請多指教!Creative Coding第一次社群聚(中)Hoba與叁式的演算視覺邁進之路
初次見面請多指教!Creative Coding第一次社群聚(下)黃豆泥:沒有市場的靈魂綁定NFT

五月的社群已經開放報名囉,有興趣的朋友歡迎加入我們的臉書社團,第一時間接收活動報名消息,希望不久的將來,就能看到你跟大家分享你的生成式藝術創作囉!

整理編輯:Chia 編

墨雨設計banner

訂閱 Creative Coding Taiwan 電子報:

這篇文章 初次見面請多指教!Creative Coding第一次社群聚(上)吳哲宇的生成式藝術宇宙 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>