OpenProcessing 彙整 | Creative Coding TW - 互動程式創作台灣站 https://creativecoding.in/tag/openprocessing/ 蒐集互動設計案例、教學與業界資源,幫助你一起進入互動程式創作的產業 Sun, 29 May 2022 14:58:46 +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 OpenProcessing 彙整 | Creative Coding TW - 互動程式創作台灣站 https://creativecoding.in/tag/openprocessing/ 32 32 五月社群聚(下):張文瀚教你用數學作畫 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 - 互動程式創作台灣站

]]>
【p5.js創作教學】Dreamy Bird 夢幻鳥 https://creativecoding.in/2021/10/12/p5-js-dreamy-bird/ Tue, 12 Oct 2021 09:12:00 +0000 https://creativecoding.in/?p=1568 本篇記錄創作<夢幻鳥>這件作品的過程,利用p5.js在短短的時間內創作出繽紛多彩、眼睛跟著滑鼠游標轉的夢幻鳥,看著他不斷地動,好像趴著在看水族館裡的魚一樣,心情也會跟著雀躍起來唷!

這篇文章 【p5.js創作教學】Dreamy Bird 夢幻鳥 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>

本文翻自【Coding Vlog | p5.js】200514 Dreamy Bird 夢幻鳥 – 來做彩色又毛毛不知道是魚還是鳥的生物吧!若是想要老闆手把手帶你飛,可以跟著影片進行,這邊也附上成品歡迎大家一起動手做。

這一次分享的內容比較特別,是紀錄老闆創作的過程,起初只是想做金屬色的練習,調整不同屬性以及數值後,慢慢產生了生物的形體,而有了夢幻鳥的誕生。這個作品會利用線上的工具 openprocessing 來進行 p5.js 的創作。完成作品後會發現,其實使用到的 api 就只有那幾個,卻能創作出獨特又有趣的作品,大家了解 api 後,也能勇敢去嘗試調整,說不定會有更意想不到的作品產生。如果想要了解更詳細的製作流程和其他創作內容,可以去支持老闆的互動藝術程式創作課程哦!

這次直播筆記會帶大家學會以下內容:

  • 利用 p5.js 進行創作互動作品
  • 使用 noise 產生自然有序的隨機數
  • 在作品中加入滑鼠互動,讓作品與觀賞者產生連結

事前準備

開發環境

開發會使用 openprocessing 線上撰寫程式碼,如果想知道較詳細的設定,可以到成品看老闆的開發環境設定。

  • openprocessing:提供大家在網頁中直接使用 p5.js 進行開發,只要利用所提供的 api ,就能製作出有趣的效果。想要了解更多相關效果的開發,除了參考網站中其他的p5.js創作教學之外,也歡迎看看老闆的線上課程,跟老闆跟一起進入 processing 的世界。

會使用到的 API:

這次專案會使用以下的 api,先重點整理給大家,不清楚的地方,可以透過後面跟著老闆操作,了解每個 api 使用時機。

  • createCanvas(width, height): 創建畫布,參數中分別傳入寬跟高。
  • background(colorCode): 加上背景色,可依照文件傳入色碼參數。
  • noStroke(): 取消繪製圖形的邊框。
  • colorMode(): 定義顏色的方式,預設為 RGB 顏色,HSB 模式依序要填入的值則為(色相, 飽和度, 明度)。
  • fill(): 選擇填入的顏色,依照 colorMode 選擇的填色模式填入對應的參數。
  • ellipse(posX, posY, width, height): 在 (posX, posY) 上繪製一個寬高(width, height)的橢圓形。
  • rect(x, y, width, height): 以 (x, y) 的位置為左上角的點,畫一個寬度 width 高度 height 的方形(如果要畫正方形的話,即寬度=高度)。
  • random(): 沒有傳參數時,會返回一個隨機浮點數。
  • noise(): 產生自然有序的隨機值,與 random 的概念不一樣。在範例中會使用到 noise,所以建議先稍微理解 noise 的概念,有興趣的同學也可以延伸閱讀相關資訊:2D Noise – Perlin Noise and p5.js Tutorial
  • rotate(angle): 依照傳入的參數進行旋轉。
  • translate(x, y): 將畫筆移到(x,y) 上。
  • push(): 紀錄目前畫筆狀態。
  • pop(): 恢復畫筆狀態。
  • sin(): 正弦,將傳入的數值做為角度值,換算成 1~-1 的值。
  • cos(): 餘弦,將傳入的數值做為角度值,換算成 1~-1 的值。
  • atan2(y, x): 計算從指定點(y,x)到座標原點的角度。

跟著老闆開始動手做

1. 起手式

開啟新的 openprocessing > Create a Sketch,可以看到程式碼頁面已經有一段預設的程式碼,隨著滑鼠的移動,會沿路產生小球,理解這段程式碼後,接著只留下我們需要的部份。

  • setup(): 可以視為環境初始化,只在開始執行的當下會呼叫一次,以下的程式碼使用了兩個 api
    • createCanvas(width, height):創建畫布,參數中分別傳入寬跟高,如果直接寫螢幕的寬高(windowWidth, windowHeight),就會成為滿版的互動區塊。
    • background(colorCode):加上背景色,可依照文件傳入色碼參數。
  • draw(): 會依照時間不停地重跑裡面的程式碼,要製作互動的內容可以在這個 function 中呼叫。
    • ellipse(posX, posY, width, height):在 (posX, posY) 上繪製一個寬高(width, height)的橢圓形。
function setup() {
  createCanvas(windowWidth, windowHeight);
  background(100);
}

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

2. 繪製基礎噪聲

在 draw 中,我們先調整顏色模式改成 HSB,後續與填色有關的 api 就會改成依序填入(色相, 飽和度, 明度),

  • noStroke() 將每次繪製圖形的邊框取消掉,每個方塊間就不會有 stroke。
  • colorMode():定義顏色的方式,預設為 RGB 顏色,HSB 模式依序要填入的值為(色相, 飽和度, 明度)。

接下來我們可以看到有兩個 for 迴圈,第一個 for 迴圈會每隔高度 20 ,再進行一次第二個 for 迴圈的內容,重新從左至右繪製一長串的方形。

  • rotate(angle): 依照傳入的參數進行旋轉。
  • fill():選擇填入的顏色,由於前面選擇了 HSB ,所以這邊要改使用 HSB 的方式填色。
  • sin():將傳入的數值做為角度值,換算成 1~-1 的值。
  • noise():躁聲,隨機序列生成器。跟 random 相比,可以利用多維的座標產生自然有序的序列,產出的值介於 0~1之間。
  • rect(x, y, width):在 (x, y) 的位置畫一個寬度 width 的方形。

經過調整後,讓呈現的顏色有時偏白,有時飽和度不會那麼高。在 sin 或 noise 中代入的值,老闆會多除上一些數字,目的是為了讓呈現的顏色變化不要太快,但這沒有正確答案,同學可以在了解每個 api 的操作方式後,依照自己的經歷或感受,去嘗試自己喜歡的氛圍。

最後一步驟,老闆希望能讓每一個橫條看起來都不同進度,所以在每一條橫條繪製前,都旋轉一下,就完成繪製基礎噪聲階段了,產生類似彩虹的畫面。

function setup() {
  createCanvas(800, 800);
  background(100);
}

function draw() {
  colorMode(HSB)
  noStroke()
  for(var o = 0; o<height; o+=20) {
    rotate(PI/1000)
    for(var i = 0; i<width; i++) {
      fill(sin(i/100)*300, noise(i/50, o/1000)*100, sin(i/40,o/1000)*30+80)
      rect(i, o, 30)
    }
  }
}
【p5.js創作教學】 夢幻鳥-步驟二:繪製基礎噪聲
【p5.js創作教學】 夢幻鳥-步驟二:繪製基礎噪聲

3. 依據噪聲橫列的影響色彩分佈跟變化

這個階段,老闆對每一行的波進行尺寸與填色的微調,也進行了波型的嘗試:

  • 讓每一橫列產生偏移:填色位置加入 o ,隨著每一行 o 的值逐漸增加,使得每一橫列的波產生偏移。
  • 讓波跟著時間動起來:填色位置加入時間因子 frameCount,讓整幅跟著時間的前進而動起來。
  • 更豐富的顏色:希望每一行波使用了 o 之後,不是只有偏移效果,所以在 noise 中又加入了 noise。
  • 降低波顏色變化速度:希望顏色變化的速度能更慢一點,針對 fill 內色相位置的值,除上更小的數字。
  • 加上插畫材質:為了讓作品更有質感,所以我們為作品加上插畫材質,材質製作方式這邊不詳細介紹,同學可以將程式碼貼到對應的地方直接使用。
let overAllTexture
function setup() {
  createCanvas(800, 800);
  background(0);
	
  // 插畫材質
  overAllTexture=createGraphics(width,height)
  overAllTexture.loadPixels()
  for(var i=0;i<width+50;i++){
    for(var o=0;o<height+50;o++){
      overAllTexture.set(i,o,color(100,noise(i/3,o/3,i*o/50)*random([0,40,80])))
    }
  }
  overAllTexture.updatePixels()
}
function draw() {
  colorMode(HSB)
  noStroke()
  for(var o = 0; o<height; o+=100) {
    for(var i = 0; i<width; i++) {
      fill(
        noise(i/400, o/400, noise(frameCount/150) + frameCount/50)*600%360,
        noise(i/50, o/1000, frameCount/100)*100,
        noise(i/40, o/1000, frameCount/100)*30+80
      )
      rect(i, o, 80)
    }
  }

  // 加上插畫材質
  push()
    blendMode(MULTIPLY)
    image(overAllTexture,0,0)
  pop()
}
【p5.js創作教學】 夢幻鳥-步驟三:依據噪聲橫列的影響色彩分佈跟變化
【p5.js創作教學】 夢幻鳥-步驟三:依據噪聲橫列的影響色彩分佈跟變化,隨著時間前進具有插畫材質的波

4. 修飾幾何形狀與加入隨機大小

接下來,我們只會動到 draw 裡面的內容,老闆在這個階段做了以下嘗試:

  • 貓毛效果:畫方塊的時候,利用變數 glitchAmount ,在 x, y 座標加上隨機偏移值。
  • 隨著滑鼠位置改變的貓毛:將隨機偏移的值加上滑鼠的值,使作品與滑鼠產生了互動。
  • 微調樣式,將外層的 for 迴圈 o 從 10 開始,讓作品與上下邊界的距離一樣

老闆也有嘗試加入隨機的黑線在波形中,產生類似現代藝術的感覺,但實際做出來的效果不好(下圖左),大家想要嘗試,可以將以下程式碼斜線的部分恢復。

let glitchAmount = 20
function draw() {
  colorMode(HSB)
  noStroke()
  glitchAmount = mouseX/10 // 隨著滑鼠變更數字的貓毛
  for(var o = 10; o<height; o+=100) {
    for(var i = 0; i<width; i++) {
      fill(
        noise(i/400, o/400, noise(frameCount/150) + frameCount/50)*600%360,
        noise(i/90, o/1000, frameCount/100)*100,
        noise(i/80, o/1000, frameCount/100)*30+80
      )
      rect(// 繪製方塊時,繪製的座標結合隨機的值
        i + random(-glitchAmount, glitchAmount), 
        o + random(-glitchAmount, glitchAmount),
        80
      )
      // if(noise(i, o, frameCount/100) < 0.1){
      //   push()
      //     stroke(0)
      //     strokeWeight(20)
      //     rect(i, o, 80)
      //   pop()
      // }
    }
  }
	
  push()
    blendMode(MULTIPLY)
    image(overAllTexture,0,0)
  pop()
}
【p5.js創作教學】 夢幻鳥-步驟四:加入隨機的黑線
【p5.js創作教學】 夢幻鳥-步驟四:加入隨機的黑線
【p5.js創作教學】 夢幻鳥-步驟四:隨著滑鼠產生不同波形尺寸
【p5.js創作教學】 夢幻鳥-步驟四:隨著滑鼠產生不同波形尺寸

5. 使用三角函數繪製波型

接下來老闆想做出類似極光的效果,一系列的調整與操作後,慢慢地變成一塊一塊的物體往前移動中,過程中做了以下嘗試,大家也能跟著老闆一起嘗試:

  • 由上到下、粗到細:極光從上到下粗到細,改變 rect 的第三個參數來實現改變波的大小
  • 結合 sin 產生波形:使用 sin 來繪製方形所產生波形,比較像極光或海浪,
  • 將波形結合時間因子 frameCount,讓波動起來
  • 改變 rectMode 為 CENTER,讓波上下同時變大
let glitchAmount = 5
function draw() {
  colorMode(HSB)
  noStroke()
  glitchAmount = mouseX/10
  rectMode(CENTER) // 調整繪製方形的模式
  for(var o = 50; o<height; o+=100) {
    for(var i = 0; i<width; i++) {
      fill(
        noise(i/400, o/400, noise(frameCount/150) + frameCount/50)*600%360,
        noise(i/90, o/1000, frameCount/100)*100,
        noise(i/80, o/1000, frameCount/100)*30+80
      )
      rect(
        i + random(0, glitchAmount),
        o + random(-glitchAmount, glitchAmount),
        (sin(i/40 + frameCount/20+o*50)+1)*30+20 // 結合 sin 繪製波形,加上 frameCount 讓波能跟著時間動起來
      )
    }
  }
	
  push()
    blendMode(MULTIPLY)
    image(overAllTexture,0,0)
  pop()
}
【p5.js創作教學】 夢幻鳥-步驟五:結合三角函數,產生向前的波形物體

6. 加上眼睛與調整生物外觀

老闆認為一塊一塊向前的波形很像生物的身體,雖然還沒確定是魚還是鳥,但是老闆決定賦予每一個區塊眼睛。這階段老闆將一些值整理成變數,大家可以來回參照上一階段與這個階段的程式碼比較,在加上眼睛與生物外觀的調整過程做了以下嘗試:

  • push 與 pop:因為老闆將眼睛位置統一記錄在 eyes 中,所以程式碼會先將所有生物的身體繪製完畢後,再繪製所有生物的眼睛,這邊就會需要把畫筆位置移到對的地方,所以使用了 translate。要注意的是,做畫筆的移動或是旋轉畫布時,我們會使用 push 將原本的狀態記錄著,當完成位置時再搭配 pop 去恢復原本畫筆的狀態。
    • translate(x,y):將畫筆移動到 x, y 的位置
  • 以波形的進度 (progAng) 作為眼球的位置:將每個完整波形的長度百分之 3 的位置存進陣列中,同學要記得使用餘數,因為隨著時間增加,frameCount 是一直增加的,利用 PI * 2 去處理餘數,就能取得每個波形進度。
  • 生物的位置與滑鼠關聯:除了讓方塊的位置隨著時間去改變,這邊也做了滑鼠的互動,讓波形進度的值結合滑鼠位置。
  • 繪製生物的方塊:生物的身體,是依不同時間點來決定出不同大小的方塊所組成,老闆將原本的方大小作為 progAng 變數的值,再由 hh 變數來組合使用 progAng。
  • 區塊的大小更加生動:原本的區塊大小只是隨著滑鼠位置去變化,在 hh 的值中,除了利用 sin 之外,也加入 cos ,讓這個生物的外觀更有趣,產生毛邊金魚的感覺。
  • 繪製眼睛:眼睛陣列(eyes)裡的物件,是所有符合條件的眼睛 x 座標,結合 ellipse,繪製眼白與眼珠。
let glitchAmount = 5
function draw() {
  colorMode(HSB)
  noStroke()
  glitchAmount = mouseX/100
  rectMode(CENTER)
  for(var o = 50; o<height; o+=100) {
    let eyes = []
    push() // 記錄當下初始畫筆的狀態
      translate(0, o) // 移動畫筆到 (0, o) 的位置
      for(var i = 0; i<width; i++) {
        push() // 再次紀錄當下畫筆狀態
          translate(i,0) // 移動畫筆到(i, 0) 的位置
          fill(
            noise(i/500, o/400, noise(frameCount/150) + frameCount/50)*600%360,
            noise(i/90, o/1000, frameCount/100)*100,
            noise(i/80, o/1000, frameCount/100)*30+80
          )
          let progAng = (i/40 + frameCount/20+o*50 + mouseY/100 + mouseX*noise(o)/100) % (PI*2) // 結合餘數計算,讓值介於 0~100 之間
          let hh = (sin(progAng) + 1 + cos(progAng/2))*30 +20  // 結合波的進度作為每次繪製方塊的大小
          rotate(sin(i/10))
          rect(
            random(0, glitchAmount),
            random(-glitchAmount, glitchAmount),
            hh
          )
          if( int(progAng/PI/2*100 ) == 2) { // 符合進度條件則儲存 x 座標
            eyes.push(i)
          }
        pop() // 釋放畫筆位置
      }
      eyes.forEach( eyeX => { // 將陣列內的物件全部拿出來繪製眼睛
        fill('white')
        ellipse(eyeX, 0, 25)
        fill('#333')
        ellipse(eyeX, 0, 10)
      })
    pop() // 釋放畫筆位置
  }
	
  push()
    blendMode(MULTIPLY)
    image(overAllTexture,0,0)
  pop()
}
【p5.js創作教學】 夢幻鳥-步驟六:加上眼睛呆呆前進
【p5.js創作教學】 夢幻鳥-步驟六:加上眼睛呆呆前進

7. 眼睛看向滑鼠、細調樣式

大致的生物形體告一段落後,除了細調樣式外,老闆也開始在作品中嘗試加入更多的互動性,例如讓眼睛看向滑鼠的位置,做了以下的操作:

  • 讓眼球看向滑鼠位置:這邊需要先取得滑鼠與眼球的角度,再利用 cos, sin 讓眼球能擺放到對的位置。使用到了新的 api – atan2
    • atan2(y2-y1, x2-x1):以弧度為單位,計算從指定的點 (y2,x2) 到 (y1,x1) 的角度,要注意這邊的 api 參數,第一個是 y 座標的計算,第二個才是 x 座標的計算。(https://p5js.org/reference/#/p5/atan2)
  • 清掉雜訊:因為 p5 是不停的地繪製新的畫面,畫面出現了許多雜點,是因為沒有在每次繪製前,先將畫面清空,這邊只要在繪製前,在畫布上蓋上一個滿版的方形就能達成。需要注意的是,利用覆蓋滿版方塊來清除雜點時,由於我們前面使用的 rectMode(CENTER),除了調整繪製的座標外,也可以先改回使用 rectMode(CORNER),等清除畫面完成後,再繼續原本的程式碼。
  • 微調生物的身體大小:微調的數值可以參考以下的程式碼,大家也可以嘗試看看不同的數值,看看會有什麼有趣的效果。
  • 取消毛邊與滑鼠的互動:固定生物毛邊的程度。
  • 調整背景色:老闆試著改變背景色,希望不要每個作品背景都是黑色。因為生物的顏色比較鮮豔,所以最後老闆挑了較深的顏色,來對比出作品的主角。
let glitchAmount = 5
function draw() {
  noStroke()
  // glitchAmount = mouseX/100 // 取消毛邊與滑鼠的互動
  rectMode(CORNER) // 改變繪製方塊的模式
  colorMode(RGB) // 使用 RGB 作為填色模式
  fill(156, 104, 104, 200) // 每次重新繪製時加上底色
  rect(0, 0, width, height)

  rectMode(CENTER)
  colorMode(HSB)
	
  for(var o = 50; o<height; o+=100) {
    let eyes = []
    push()
      translate(0, o)
      for(var i = 0; i<width; i++) {
        push()
          translate(i,0)
          fill(
            noise(i/500, o/400, noise(frameCount/150) + frameCount/50)*600%360,
            noise(i/90, o/1000, frameCount/100)*100,
            noise(i/80, o/1000, frameCount/100)*30+80
          )
          let progAng = (i/40 + frameCount/20+o*50 + mouseY/100 + mouseX*noise(o)/100) % (PI*2)
          let hh = (sin(progAng) + cos(progAng/2) + cos(progAng/5)/3 +1)*30 // 微調毛邊樣式
          rotate(sin(i/10))
          rect(
            random(0, glitchAmount),
            random(-glitchAmount, glitchAmount),
            +hh
          )
          if( int(progAng/PI/2*100 ) == 2) {
            eyes.push(i)
          }
        pop()
      }
      eyes.forEach( eyeX => {
        let mAng = atan2(mouseY - o, mouseX - eyeX) // 取得滑鼠與眼珠的相對位置
        fill('white')
        ellipse(eyeX, 0, 25)
        fill('#333')
        ellipse(eyeX + cos(mAng)*5, sin(mAng)*5, 10) // 利用 cos, sin 將眼珠放置在對的位置
      })
    pop()
  }
	
  push()
    blendMode(MULTIPLY)
    image(overAllTexture,0,0)
  pop()
}
【p5.js創作教學】 夢幻鳥-步驟七:用滑鼠和眼睛互動,並調整整體畫面及顏色
【p5.js創作教學】 夢幻鳥-步驟七:用滑鼠和眼睛互動,並調整整體畫面及顏色

8. 加入魚鰭與最後修飾

創作到尾聲,其實老闆還沒決定他是什麼樣的生物,看起來類似尖嘴巴的魚,為了讓作品更完整,在這裡我們賦予生物們魚鰭,並做最後的微調:

  • 加上魚鰭:前面我們有記錄所有眼睛的位置,利用這個 for 迴圈,去繪製旋轉的三角形,讓它成為生物的鰭。這邊要記得使用 push 及 pop,不然會導致你下一次在繪製眼睛時出錯。
  • 調整背景色:最後老闆選擇了深藍色的背景作為定調。
  • 扭動的身體:繪製身體前的畫筆移動,在 y 參數的位置加上 sin ,可以繪製出魚移動時身體扭動的感覺。
let glitchAmount = 5
function draw() {
  noStroke()
  rectMode(CORNER)
  colorMode(RGB)
  fill(0, 0, 80, 180)
  rect(0, 0, width, height)
  rectMode(CENTER)
  colorMode(HSB)

  for(var o = 50; o<height; o+=100) {
    let eyes = []
    push()
      translate(0, o)
      for(var i = 0; i<width; i++) {
        push()
          translate(i, sin(i/30)*20) // 利用畫筆的位移,讓鳥在往前時,身體也有了變化
          fill(
            noise(i/500, o/400, noise(frameCount/150) + frameCount/50)*600%360,
            noise(i/90, o/1000, frameCount/100)*100,
            noise(i/80, o/1000, frameCount/100)*30+80
          )
          let progAng = (i/40 + frameCount/20+o*50 + mouseY/100 + mouseX*noise(o)/100) % (PI*2)
          let hh = (sin(progAng) + cos(progAng/2) + cos(progAng/5)/3 +1)*30
          rotate(sin(i/10))
          rect(
            random(0, glitchAmount),
            random(-glitchAmount, glitchAmount),
            +hh
          )
          if( int(progAng/PI/2*100 ) == 2) {
            eyes.push(i)
          }
        pop()
      }
      eyes.forEach( eyeX => {
        let mAng = atan2(mouseY - o, mouseX - eyeX)
        fill('white')
        ellipse(eyeX, 0, 25)
        fill('#333')
        ellipse(eyeX + cos(mAng)*5, sin(mAng)*5, 10)

        push() // 繪製魚鰭時,記得使用 push, pop 來記錄與釋放畫筆狀態
          stroke(0)
          noFill()
          translate(eyeX+50, 0)
          rotate(sin(eyeX/2+o/10)/2) // 畫筆進行旋轉,畫面會呈現魚鰭擺動的效果
          triangle(
            0, 0,
            50, -20,
            50, 20
          )
            pop()
        })
    pop()
  }

  push()
    blendMode(MULTIPLY)
    image(overAllTexture,0,0)
  pop()
}
【p5.js創作教學】 夢幻鳥-步驟八:加上魚鰭之後完成成品

老闆來結語

這次的創作一開始是老闆想要練習金屬色,一系列的調整與操作,最後才產出夢幻鳥這個作品,讓我們快速回顧一下夢幻鳥的創作過程:

  1. 了解 openprocessing 創作的起手式 – setup 與 draw
  2. 利用噪聲 noise 決定方塊的顏色
  3. 利用 for 迴圈的變數、噪聲與時間變數 frameCount,影響每一橫列的色彩分佈與變化
  4. 調整繪製方塊的形狀與大小
  5. 結合三角函數繪製出波形
  6. 為生物加上眼睛,並微調生物外觀
  7. 讓眼睛與滑鼠產生互動
  8. 加上魚鰭與最後修飾

萬事起頭難,一個作品不可能一步到位,將最終目標拆分成不同階段任務,從一開始的雛型慢慢開發出每個區塊,最後組裝在一起,也可以加上個人的創意去實現其他功能,讓作品更豐富。

由於這部影片比較特別,是紀錄老闆在練習與發想後,老闆回頭解說製作過程,所以中間會不停地去微調數值。創作的過程一定會有這種狀況發生,在創作時沒有所謂的正確答案,大家在了解工具之後,就勇敢地去嘗試吧!再附上這次範例的成品<夢幻鳥>,讓大家在開發時參考。

如果你喜歡老闆的教學,歡迎支持老闆,讓老闆在《互動藝術程式創作入門》課程中帶你一起學習。課程裡會帶你看看不一樣的作品,並引導大家一步步完成作品,透過每次的賞析、實作到修正作品,讓寫 code 不再是這麼困難的一件事情,將這個過程想像成,拿一隻比較難的畫筆在進行創作,如果有機會使用它,便能夠在網頁上做出與眾不同的創作。

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

墨雨設計banner

這篇文章 【p5.js創作教學】Dreamy Bird 夢幻鳥 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
圖形繪製與色彩:從點線面開始的世界(互動藝術創作分享教學) https://creativecoding.in/2021/04/21/%e5%9c%96%e5%bd%a2%e7%b9%aa%e8%a3%bd%e8%88%87%e8%89%b2%e5%bd%a9%ef%bc%9a%e5%be%9e%e9%bb%9e%e7%b7%9a%e9%9d%a2%e9%96%8b%e5%a7%8b%e7%9a%84%e4%b8%96%e7%95%8c%ef%bc%88%e5%89%b5%e4%bd%9c%e5%88%86%e4%ba%ab/ Wed, 21 Apr 2021 01:45:00 +0000 https://creativecoding.in/?p=644 如果你跟我(Ju編)一樣是Creative Coding這個領域的菜逼八,可能本身從網頁設計起家、或是從視覺設計半路轉行、甚至只是不小心點到這個網站,對概念還有些模糊但有興趣想多留下來逛一下,那從這篇…

這篇文章 圖形繪製與色彩:從點線面開始的世界(互動藝術創作分享教學) 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
如果你跟我(Ju編)一樣是Creative Coding這個領域的菜逼八,可能本身從網頁設計起家、或是從視覺設計半路轉行、甚至只是不小心點到這個網站,對概念還有些模糊但有興趣想多留下來逛一下,那從這篇文章開始或許是個不錯的選擇。

Creative Coding是什麼?

在程式設計這片汪洋大海中,Creative Coding對台灣來說算是相對較新的概念,網站內右上角的關於入門資源提供了一些輪廓,這邊幫大家節錄一些重點:

Creative Coding一種透過程式創作來表達的藝術形式,表現方式包含但不限於視覺、聲音、投影與裝置藝術等…。
顧名思義是結合程式加創意,狹義上看起來是用程式寫一些看起來很有藝術感的圖形,廣義上是可以用程式,將世界上的各種事物賦予互動跟連結起來,創造出新的現象、關聯與有趣的呈現。

由此可見這個領域且深且廣,舉凡美術館展品到路邊的互動式廣告,可以說是包山包海。當然要馬上變成像那些藝術家大大們一樣厲害可能不是那麼容易,但經過不斷地練習與累積,相信有一天我們可以做出自己也覺得很滿意的作品!

既然是從點線面開始的Creative Coding世界,就讓我們時光回溯一下,回到剛開始學畫畫的小時候,懞懂地拿著蠟筆畫著圓形、長方形、三角形,再以這些基礎圖形為出發點,組成各式各樣的圖像作品。創作的題材選擇上可以先從身邊的事物開始,例如:高樓大廈、喜歡的角色、自然景色等,不一定要馬上挑戰構造複雜的圖面。

在本篇文章中選擇的主題是天外奇蹟(UP),藉著最近剛重溫這部電影替他做個極簡主義的電影海報redesign,另外再添加一些滑鼠小互動,那就讓我們開始動手吧!

圖片來源:Wikipedia

今天要使用的是OpenProcessing搭配p5.js函式庫的大禮包組合,如果對這兩個工具還不太熟悉在這篇文章可以看到更多介紹 👉🏻 p5.js 快速上手

首先,在開始設計前可以先打個草稿,既然是電影海報又要是極簡主義(minimalism),那放置在海報上的元素就必須簡單且具有代表性,選用的當然就是貫穿整部電影的繽紛氣球啦 🎈。

在OpenProcessing裡面建立新的專案,可以看到系統預設的專案內容。(如果想要調整成code跟畫布的分割版面,可以在右邊Editor裡的Layout找到)

互動海報製作的基本設定

由於目標是做出直向的海報,所以將setup()中的createCanvas()寬高設定成寬600、高700。接下來我們需要一片台北冬天很少見的藍色天空,在draw()中的background()設定天空藍的色票。在p5.js中顏色的設定可以分為以下五種:

  1. RGB – rgba(88, 178, 220, 1) 第四個值為設定透明度,1為最深0為最淺。
  2. HSB – hsba(160, 100, 50, 0.5)
  3. HSL – hsla(160, 100, 50, 0.5)
  4. 灰階 – color(65)
  5. HEX – #58B2DC

注意因為這些色票或數值在p5.js中不是一個function,所以記得要在顏色外加上單引號,可以搭配fill()、和background()使用,簡單來說就是background(‘你想要的顏色’)。

利用幾何圖形組合出背景雲朵及主角氣球

接著來畫背景的雲朵,我們把大塊的雲朵用基礎圖形切割分析,可以發現它是由五個圓形+一個長方形組成的。這邊要介紹幾個p5.js畫基礎圖型的語法:

  1. ellipse() – 橢圓形,ellipse( 畫布座標x, 畫布座標y, 橢圓的寬, 橢圓的高), 有時會加上第五個值detail,表示線條之間的間距。
  1. circle() – 圓形,circle( 畫布座標x, 畫布座標y, 圓的半徑)。
  2. rect() – 方形,rect(畫布座標x, 畫布座標y, 方形的寬, 方形的高)。

注意圓形和方形在座標定位點上的不同,圓形預設是用圓心、方形預設是用左上第一個角為定位點。可以用rectMode()ellipdeMode()來解決起定位點不一樣的問題。

在畫圖的時候我們可以把當前滑鼠所在的位置顯示在畫布上來幫助我們定位。使用text()裡面填入mouseX和mouseY,把它定位在畫布x距離20、y距離30的左上角,因為只需要大概的位置所以把數值用int()轉換成整數比較好讀,記得分隔用的逗號要加上雙引號。

再加上大大小小、顏色不一樣的氣球,添加一些透明度,模仿氣球的微透明感。

接下來把一顆顆的氣球綁成一束,用line()來畫出線條,用法為line(x1, y1, x2, y2),告訴p5.js兩個定位讓他幫忙連連看。注意程式撰寫後蓋前的特性,前面畫雲和氣球時我們用noStorke()取消了外框線,記得再用storke()把畫筆線條叫回來,粗細可以用strokeWeight()調整。

加上電影的標題和電影台詞,利用textAlign() 的CENTER置中對齊主標題和副標題,一張簡單的海報就完成啦。

再加一點點互動效果

如果覺得靜態的海報有點單調,想要加入滑鼠往下,氣球變大往上飛、雲層往下的幫浦打氣互動效果,可以在參數的地方加入mouseY來讓元素跟著滑鼠做動態的變化。適當加入一些互動效果可以更抓住使用者的目光唷!這邊提供code給大家參考~

// cloud
  fill(255);
  noStroke();
  circle(30, 510+mouseY/20, 200);
  rect(30, 700+mouseY/20, 600, 80);
  circle(120, 600+mouseY/20, 250);
  circle(250, 600+mouseY/20, 100);
  circle(380, 640+mouseY/20, 250);
  circle(556, 680+mouseY/20, 150);

// balloonYellow
fill('rgba(249, 191, 69, 0.95)');
circle(400, 150, 220+mouseY/10);
// balloonGreen1
fill('rgba(27, 129, 62, 0.95)');
circle(180, 240, 110+mouseY/10);
// balloonRed
fill('rgba(203, 64, 66, 0.95)');
circle(270, 210, 180+mouseY/10);
// balloonGreen2
fill('rgba(27, 129, 62, 0.95)');
circle(350, 270, 110+mouseY/10);

// lineGreen1
stroke('Black');
strokeWeight(1.5);
line(208, 287+mouseY/18, 300, 400);
// lineRed
line(281, 300+mouseY/18, 300, 400);
// lineGreen2
line(327, 320+mouseY/18, 300, 400);
// lineYellow
line(345, 325+mouseY/18, 300, 400);
// lineBottom
strokeWeight(1.5);
line(300, 400, 300, 500);

我們就完成了一個天外奇蹟的互動式海報redesign啦~希望大家喜歡這個簡單的小教學,可以試著用p5.js來畫畫看身邊的靜物、喜歡的角色,然後加上有趣的互動效果。我們下次再見啦 🙌🏻

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

https://imgur.com/Yy3fZoL.gif

語法統整大補帖

圖形相關語法:ellipse()、circle()、rect()
填色相關語法:fill()、background()
線條相關語法:line()、stroke()、noStroke()、strokeWeight()
文字相關語法:text()、textAlign()

下一篇讓我們利用變數概念與程式完成簡單的彩色互動畫作。

想學習更多程式創作嗎?那你必不可以錯過哲宇老師的【互動藝術程式創作入門】課程,快跟著其他一千多名同學開始發揮你無限的創意吧!

作者:Ju編 Jeudi Kuo

墨雨設計banner

訂閱 Creative Coding Taiwan 電子報:

這篇文章 圖形繪製與色彩:從點線面開始的世界(互動藝術創作分享教學) 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
p5.js 快速上手:互動網頁教學 https://creativecoding.in/2020/04/24/p5-js-%e5%bf%ab%e9%80%9f%e4%b8%8a%e6%89%8b/ Fri, 24 Apr 2020 10:47:22 +0000 https://creativecoding.in/?p=325 什麼是 p5.js? 當我們想要在網頁上繪圖,最常用的除了 CSS 之外,就是 HTML5 提供的 Canvas 了,Canvas 的 API 接口讓我們可以實現有效率、高靈活性在網頁上繪圖的夢想,C…

這篇文章 p5.js 快速上手:互動網頁教學 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
什麼是 p5.js?

當我們想要在網頁上繪圖,最常用的除了 CSS 之外,就是 HTML5 提供的 Canvas 了,Canvas 的 API 接口讓我們可以實現有效率、高靈活性在網頁上繪圖的夢想,Canvas 的許多基礎都在 動畫互動網頁特效入門(JS/CANVAS)中提到,讓你可以從頭開始,完成豐富的網頁互動創作。

但是對於想要快速開始互動網站、藝術創作的人來說,Canvas 上像是繪圖、形狀、物理模擬或是常用的數學公式等功能都需要自己從頭處理。有沒有更快的方式呢?

答案是有的,就是今天要介紹的 p5.js,p5 是由 Processing 延伸而成的 JavaScript 函式庫,Processing 是設計給沒有程式基礎的人快速進行創作的平台,而 p5.js 可以理解為 Processing 的 JavaScript 版本。它將許多繪圖、數學、物理模擬等函式封裝好讓我們可以直接使用,如此一來我們可以在享受 Canvas 繪圖的同時不用費心思處理瑣碎的工具!

範例分享

在本篇文章中我們將會實作一個簡單的畫布,把滑鼠當作筆刷,滑鼠經過的路徑會留下彩色的軌跡,點擊的狀況下軌跡則變成方形的圖案,增加繪製的多樣性。

想要跟著影片一起看也沒問題,請從這邊走 👉

我們將以 OpenProcessing 作為本次範例的平台,這是一個像是 Code Pen 的線上程式碼編輯器,可以在創作的同時即時看到程式碼運做的狀況,十分方便!

p5.js 創作環境

如果我們在 OpenProcessing 創立一個新的專案,會看到一個預設的專案長這樣子:

介面非常簡單,左邊是程式碼的區塊,右邊是目前程式繪圖的結果。我們在左邊輸入的程式碼在按下上方的執行或是(cmd + Enter)之後就會即時更新在畫面上。

畫布設定 setup() 與 draw()

p5.js 的專案由兩個主要的函式構成,setup() 與 draw()。setup() 負責程式的初始化,只會執行一次;而 draw() 則會持續更新,我們也可以透過 print(frameCount) 把禎數這個內建的變數打印出來,在 console 中看到當下畫面更新了多少次。

我們通常會在 setup() 中設定一些通用的初始值,例如畫布的大小、背景、繪製型態(2D 或是 3D)之類,在 draw() 中撰寫會時時更新的程式碼,像是筆刷的更新、物件的移動、滑鼠位置、感測器的資料更新等。就算我們不懂 p5 的函式,也可以從 OpenProcessing 的範例中猜出 createCanvas(windowWidth, windowHeight); 是創建畫布,background() 是設定顏色;ellipse(mouseX, mouseY, 20, 20) 是用滑鼠的位置繪製一個寬高各 20 的圓形。

圖形繪製

如同一開始所說,在 p5 要繪製圖形非常容易,以方形來說,我們只要使用 rect() 函數,輸入要繪製的 x, y 座標以及長寬,就可以變出一個方形,圓形也是同理,使用 ellipse() 函數就可以變出來。如果想要知道更多內建的圖形函式,也可以參考文件中的 2D Primitives 部分。

這邊要注意 rectMode() 的設定,如果將他設定為 rectMode(CENTER) 的話繪製方形就會把左標訂定在方形的中間,否則就是方形的左上角喔!

動態改變顏色與線條

能夠繪製形狀之後我們可以試著給圖形一些顏色,在 p5 裡面,設定的函式是 fill() ,裡面就像是 background() 一樣,可以填入 HEX、RGB 等色碼、顏色的英文等參數。要設定顏色也很簡單,在繪製圖形之前加上 fill(‘你要的顏色或是色號’) 就行了。

此外我們也能用 stroke() 與 strokeWeight() 設定圖形邊線粗細或是顏色 noStroke() 則是不加任何的邊框。合併在一起看看吧:

加上判斷式

p5 當中提供了不少可以直接運用的狀態,像是 mouseIsPressed 就是當下滑鼠是否有點擊事件,或是 keyIsPressed 判斷使否有點擊鍵盤事件,甚至是行動裝置的感測器也有 accelerationX, Y, Z 等事件。讓偵測事件變得十分方便。

我們希望在點擊的當下,繪製出不同的形狀,只要在隨時更新的 draw() 當中加上判斷式 if(mouseIsPressed){繪製我要的圖形} 就可以了。

將上述的功能組合在一起

做點有趣的組合,讓作品隨著 frameCount 改變筆刷顏色、增加滑鼠點擊出現不同繪圖的互動,最後再使用隨機改變圖形大小,就完成一個有趣的互動作品了!是不是比自己用 Canvas 土砲慢慢做來的方便多了?來看看我們的成品吧:

以上就是這次的 p5.js 快速上手,p5 的文件寫得很完整,如果有遇到不懂的問題查閱一下,說不定就可以馬上解決,文件中更有互動的範例,簡直是無痛上手程式創作的最佳利器!

希望這個介紹對大家有幫助,如果想要學習更多程式創作的手法與內容,歡迎來看看墨雨設計最新開設的「互動藝術程式創作入門 Creative Coding」 課程,會從頭介紹程式創作的概念與手法,讓你快速做出生動豐富的互動作品喔!

等不及想用p5.js創作嗎?
【p5.js創作教學】電波電路Wave Circuit – 來做個逼哩逼哩送訊號的電路吧!(直播筆記)
【p5.js 創作教學】 色散海葵(直播筆記)

墨雨設計banner

訂閱 Creative Coding Taiwan 電子報:

這篇文章 p5.js 快速上手:互動網頁教學 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>