Shader 彙整 | Creative Coding TW - 互動程式創作台灣站 https://creativecoding.in/tag/shader/ 蒐集互動設計案例、教學與業界資源,幫助你一起進入互動程式創作的產業 Mon, 28 Nov 2022 00:18:21 +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 Shader 彙整 | Creative Coding TW - 互動程式創作台灣站 https://creativecoding.in/tag/shader/ 32 32 【徵文賞-沉浸式內容】佳作|基於電腦圖學之及時渲染超音波檢測VR遊戲環境 – 林慶佳 https://creativecoding.in/2022/11/24/collection221011-immersive-1/ Thu, 24 Nov 2022 08:33:01 +0000 https://creativecoding.in/?p=3235 透過互動程式創作徵文賞,我們期望讓更多人認識並加入 Creative Coding 這個新奇有趣的領域。此文章為沈浸式內容組佳作,將介紹如何使用電腦圖學知識與工具,開發出如下的及時渲染超音波特效。

這篇文章 【徵文賞-沉浸式內容】佳作|基於電腦圖學之及時渲染超音波檢測VR遊戲環境 – 林慶佳 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
前言

鑒於APIL曾推出過類似的專案,藉由科技教育的方式讓使用者能用更少的成本進行訓練。本文將介紹如何使用電腦圖學知識與工具,開發出如下的及時渲染超音波特效。

APIL製作的模擬遊戲。

內容目錄

超音波原理
透視圖
邊緣高光
強度圖
Radical Blur
上層皮膚模擬
扇型裁切
內臟透視
Stencil masking
雙Pass覆寫深度
用戶操作
額外閱讀
參考文獻

本文章成品效果展示

建議先備知識

  1. Unity 基本操作概念。
  2. Shader lab 或 GLSL 、 HLSL 等渲染語言知識。
  3. 基本線性代數、三角函數知識。

超音波原理

由感測器發出聲波,返回的是該聲波垂直向下的頗面回聲(echo)圖,echo越強的像素越白。 因為器官表面不平,會產生音波漫射(diffuse),所以大部分是灰的。

  • 液體和空氣幾乎沒有回聲,所以是黑的。
  • 組織到另一個組織時,若材質差異大,會產生邊緣高光(specular)反射。
  • 漫射的光會造成雜訊、顆粒感(speckle)。
  • 聲波每經過一層會反射的物質,其強度減弱,產生陰影。
  • 離感測器最近的組織回聲最強,隨著滲透越深,強度衰弱(attenuation)。

透視圖

先準備正常內臟模型,寫個簡單的透明shader並用alpha控制透明度來代表透光程度,讓攝影機最終呈現如圖:

事前準備

可使用任意模型,例如本範例使用Unity Asset store上的Human Organ System PBR模型素材。

https://assetstore.unity.com/packages/3d/characters/humanoids/humans/human-organ-system-pbr-175755

使用Shader渲染模型切面

使用透明混合(blend)技術,可看到方塊內還包含著另一個圓與方塊。

圖源:[1]
Tags { 
            "RenderType" = "Transparent" 
            "Queue" = "Transparent"
            "IgnoreProjector" = "True" }
        LOD 100

        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite Off
				}
				...
				fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                col.a = _Alpha;
                return _Alpha;
            }

混合Shader code

邊緣高光

藉由sample 該uv的顏色與上面一點的uv的顏色,相減後取得顏色變化差距。 (只取上面的顏色變化是因為我們假設聲波來源是上面)

先將頗面圖模糊後取得的線條比較清楚
v2f vert (appdata v)
            {
                v2f o;
                //假設音波來源是上中央
                float2 sourcePosition = float2(0.5, 1);
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                //上緣uv位置
                o.uvabove=v.uv.xy + (sourcePosition - v.uv.xy) * _MainTex_TexelSize.y *_EdgeSize;

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                fixed4 above_col=tex2D(_MainTex, i.uvabove);
                return col * abs(above_col-col)*10 ;
            }
            ENDCG

強度圖

將顏色由貼圖上方往下加,最後反轉後會得到如速度線的效果。

struct v2f {
    float4 pos : SV_POSITION;
    float2 uv : TEXCOORD0;
    float2 toSource : TEXCOORD1;
};

v2f vert(appdata_base v) {
    v2f output;
    // ...
    float2 sourcePosition = float2(0.5, 1);
    output.uv = v.texcoord.xy;
    output.toSource = sourcePosition - v.texcoord.xy;

    return output;
}

half4 frag(v2f input) : SV_Target {
    half4 output = half4(0, 0, 0, 1);
    float2 normalizedToSource = input.toSource / length(input.toSource);
    float2 texelToSource = float2(normalizedToSource * _MainTex_TexelSize.y);

    // _TexelSize.w is automatically assigned by Unity to the texture’s height
    for (int i = 0; i < _MainTex_TexelSize.w; i++) {
        output += tex2D(_MainTex, input.uv + texelToSource * i);
    }

    return output;
}

Radical Blur

原理:根據(x,y)找到對應的( r , θ) 座標,取鄰近像素座標 ( r , Θ) =(r , θ ± l / 2 ) 平均值輸出。

struct v2f
        {
            float4 pos : SV_POSITION;
            float2 uv : TEXCOORD0;
        };

        sampler2D _MainTex;
        float4 _MainTex_TexelSize;
        float4 _MainTex_ST;
        float _BlurSize;
        float2 _BlurCenter;
        float _Iteration
        v2f vert(appdata_img v)
        {
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex);
            o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
            return o;
        }

        float4 frag(v2f i) : SV_TARGET
        {
            float2 blurVector = (_BlurCenter.xy - i.uv.xy) * _BlurSize;
            float r = length((_BlurCenter.xy - i.uv.xy));
            float angle=acos((i.uv.x - _BlurCenter.x )/r);
            angle *=sign(i.uv.y - _BlurCenter.y);

            float4 acumulateColor = float4(0, 0, 0, 0);

            for (int it = -_Iteration; it <= _Iteration; it++)
            {
                float phi = angle + radians(it);
                float2 _arcuv = float2(_BlurCenter.x + r * cos(phi), _BlurCenter.y + r * sin(phi));

                acumulateColor += tex2D(_MainTex, _arcuv);
            }

            return acumulateColor / _Iteration;
        }

這邊使用acos取角度,其性質如下

上層皮膚模擬

超音波圖之所以上面通常都是白白一絲一絲的,因為那是人的表層皮膚、肌肉,容易產生echo,所以偏白。 文獻[1]教了我們基本的超音波效果模擬,為了讓圖更逼真,所以再來多做一些吧。

可以看到超音波上面的皮膚組織偏白。圖源:來自網路

使用tanh取得上層偏白的遮罩,再調整一下參數可得到以下曲線:

float whiteIntensity = 1 - tanh((1 - input.uv.y) * 9);
遮罩效果

搭配雜訊貼圖可得到以下效果:

再調整一下曲線讓他不要太白:

扇型裁切

我們需要的是右邊這種形狀的,需再加點角度範圍判斷。

參考文獻[3],畫出扇型遮罩。
使用兩個圓弧剪裁出扇型。
half4 frag(v2f i) : SV_Target
            {
                //Re-map this now rather than later
                float2 pos = - (i.uv * 2.0 - 1.0);

                //Calculate the angle of our current pixel around the circle
                float theta = degrees(atan2(pos.x, pos.y)) + 180.0;

                //Get circle and sector masks
                float circle = length(pos) <= 1.0 && length(pos) >=_innerDistance;
                float sector = (theta <= _EndAngle) && (theta >= _StartAngle);

                //Return the desired colour masked by the circle and sector
                return _Color * (circle * sector);
            }

結果:

內臟透視

為了讓使用者能知道內臟的位置,本專案提供透視選項,能讓指定內臟顯示於最上層。 這邊嘗試了(1)Stencil masking 與(2)雙Pass覆寫深度 兩種作法。

Stencil masking

利用Stencil 遮罩將特定部位的像素裁剪出來,並指定疊加顯示於畫面上。

來源文獻[4]

在人體等想被穿透的物體shader上加

Stencil
{
    Ref 1 // ReferenceValue = 1
    Comp NotEqual // Only render pixels whose reference value differs from the value in the buffer.
}

能穿透的物件shader加上

Stencil
{
    Ref 1 // ReferenceValue = 1
    Comp Always // Comparison Function - Make the stencil test always pass.
    Pass Replace // Write the reference value into the buffer.
}

缺點是只有PC能執行,由於Occulus是安卓系統,礙於該平台不支援,導致只會渲染在一顆眼睛上。

雙Pass覆寫深度

原理:

第一個pass無視深度條件寫入背面,同時也會寫下深度,讓深度能在它之上的只有自己的正面,因此讓第二個pass正常渲染即可。

Cull Front
ZTest Always
Shader "Unlit/OrganOutline"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" { }
        _Color ("outline color", Color) = (1, 0, 0, 1)
        _OutlineWidth ("Outline width", Range(0.0, 1.0)) = .005
    }
    SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 100

        pass
        {
            Cull Front
            ZTest Always
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            float4 _Color;
            float _OutlineWidth = 0.5;

            struct v2f
            {
                float4 pos : SV_POSITION;
            };

            v2f vert(appdata_base v)
            {
                v2f o;
                float3 norm = normalize(v.normal);
                v.vertex.xyz += v.normal * _OutlineWidth;
                o.pos = UnityObjectToClipPos(v.vertex);

                return o;
            }
            fixed4 frag(v2f i) : COLOR
            {
                return _Color;
            }
            ENDCG

        }

        Pass
        {
            Cull Back
            //...... render your texture
        }
    }
}

用戶操作

為了提升VR體驗,所以如影片中的感測器會自動貼合人體表面,防止穿模。

public LayerMask skinMeshLayer;

    [SerializeField]
    private Transform sensorPoint;

    [SerializeField]
    private float rayDistance = 10;

    private float stickLength;

    private void Start() {
        stickLength = (sensorPoint.position - transform.position).magnitude;
    }

    void Update()
    {
        Vector3 alignDir = (sensorPoint.position - transform.position).normalized;
        Vector3 _rayStart = transform.position -  alignDir*rayDistance ; //往後退保留ray空間

        RaycastHit hit;

        if (Physics.Raycast(_rayStart, alignDir, out hit, rayDistance * 2, skinMeshLayer))
        {
            Vector3 _stickPoint = hit.point;
            Vector3 _movePoint = _stickPoint - alignDir * stickLength;
            transform.position = _movePoint;
        }
        else {
            transform.localPosition = Vector3.zero;
        }

    }

總結

製作步驟整理如下:

額外閱讀

[5] 核磁共振是3D立體空間,而超聲波是建立在聲波網格(acoustic grid),渲染比較困難。

[6] 快速剖面演算法。 (因為超音波是取截面)

[7] 更專業的演算法。


參考文獻

  1. Ultrasound simulation with shaders – Avangarde-Software
  2. Barnouin, C., Zara, F., & Jaillet, F. (2020, February). A real-time ultrasound rendering with model-based tissue deformation for needle insertion. In 15th International Conference on Computer Graphics Theory and Applications, GRAPP 2020. [pdf]
  3. How to draw circular sector in RunTime? – Unity Answers
  4. unity – How can I create a “see behind walls” effect? – Game Development Stack Exchange
  5. Chapter 40. Applying Real-Time Shading to 3D Ultrasound Visualization | NVIDIA Developer
  6. https://www.scitepress.org/papers/2017/60972/60972.pdf
  7. GPU Ultrasound Simulation and Volume Reconstruction (tum.de)

這篇文章 【徵文賞-沉浸式內容】佳作|基於電腦圖學之及時渲染超音波檢測VR遊戲環境 – 林慶佳 最早出現於 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第一次社群聚(中)Hoba與叁式的演算視覺邁進之路 https://creativecoding.in/2022/05/07/creative-coding-meetup-202204-hoba/ Sat, 07 May 2022 02:24:00 +0000 https://creativecoding.in/?p=2649 叁式互動新媒體的技術美術Hoba帶來演算視覺在展演和商業上的應用,揭露近年來精彩的作品幕後製作祕辛,文末也帶來社群聚的創作者張文瀚帶來作品Wormhole分享。

這篇文章 初次見面請多指教!Creative Coding第一次社群聚(中)Hoba與叁式的演算視覺邁進之路 最早出現於 Creative Coding TW - 互動程式創作台灣站

]]>
上一篇 初次見面請多指教!Creative Coding第一次社群聚(上)吳哲宇的生成式藝術宇宙 我們聊了Creative Coding,還有藝術家吳哲宇從 p5.js 到 Shader 的生成式藝術(Generative art)創作之路。

本篇文章則是由叁式互動新媒體的技術美術Hoba帶來演算視覺的應用,不藏私揭露叁式近年來精彩的作品幕後祕辛(影片從這裡開始看),以及另一位與會的創作者張文瀚帶來作品 <Wormhole>分享(看看作者的詮釋及解析)。

叁式互動新媒體 Hoba <演算視覺的應用>

這次邀請到叁式互動新媒體的技術美術Hoba,以個人角度、發展歷程,觀看叁式近年來的作品。技術美術的工作內容從視覺到程式,包含 Photoshop、Illustrator、After Effects、Unity…等。

最早接觸 p5.js 是大二的時候,畢製時也用 p5.js 做了一個互動的吧檯桌,桌上酒杯利用桌下的投影產生互動影像。原本以為畢業之後不會再寫程式了,因為第一份工作是在展場設計公司做空間設計,主要就是不停設計及畫 3D 示意圖。 後來在獨自接案及因緣際會之下,來到叁式,才真正又開始寫程式。 在叁式的最早期是用 openFrameworks,去繪製各種東西。那時候學了各種不同的 shader (fragment、geometry、compute),來控制粒子(particle)的點、形狀及運動方式,也做出一些測試用的作品,像是一些比較混亂的形狀或水墨的效果。

不同shader製作出的視覺效果都不同
不同shader製作出的視覺效果都不同

叁式其實用了很多不同的感應器(sensor)及各式各樣的演算法去結合視覺來創作。以此作品為例, openFrameworks 加上 NVIDIA 的 Flex 物理引擎(現已停止維護),就可以模擬出水的波紋或煙的視覺(參考影片),像這樣可以讓粒子像水一樣在空間中流動,甚至可以改變空間中的重力,讓這些粒子朝不同方向去運動。

叁式也做了一些藝術案,常見的是跟安娜琪的合作,像是 Seventh Sense 跟 Second Body等舞蹈表演,結合叁式擅長的視覺動態特效技術。

安娜琪舞團:Seventh Sense
安娜琪舞團:Seventh Sense
安娜琪舞團:Second Body
安娜琪舞團:Second Body

以 Seventh Sense 來說,把舞台當成一個盒子,除了觀眾這面外,其他全部都打投影,在某一些特定的觀眾視角,會是一個完美透視的狀態。也包括舞者在裡面移動表演,裡面的粒子和線條都是用程式即時去畫的。

而Second Body,是用四面台,各四台 Kinect 及投影機的組合,利用 Kinect 感應器捕捉現場舞者的身體樣態,將這些捕捉到的點雲(point cloud)資料即時建成一個360度完整的 3D mesh,再將動畫準確地投影在舞者身上及地面上,完成現場表演的即時動態投影。

海尼根的時空旅人
海尼根的時空旅人
陳綺貞展出作品
陳綺貞展出作品

其他還有一些商業案,如海尼根的時空旅人是用 leap motion 感測手部動作,去擾動牆上的麥田或撥動水流;陳綺貞的展覽,使用她手寫的字體組合成她的臉,且會根據遠近變化做出顏色及大小的改變。像這樣要同時運算很多字元件是非常耗費效能的,所以必須透過 shader 的方式,在這些 geometry 裡面畫出正確的 UV 及大小。

NYX 彩妝品牌照片互動效果
NYX 彩妝品牌照片互動效果
利用shader製作的SONY網站
利用shader製作的SONY網站

為 NYX 這個彩妝品牌創造的互動作品,是利用客人發布在 IG 上的 hashtag 找出當天活動的照片,利用程式分析粗糙及平滑的地方,再疊加 NYX 的彩妝,最後用動態的方式將大小不一的多層彩妝疊合起來。

網頁形式的話,是跟SONY合作,主要是做轉場的特效。 另外如果想學習 Shader 的話,有個很好的參考學習網站叫 Shadertoy,裡面有非常多人單純用 fragment shader 去創造出各式各樣,不管是常見的濾鏡或具體的像蝸牛之類的。

蔡健雅 列穆尼亞演唱會:粒子化地景
蔡健雅 列穆尼亞演唱會:粒子化地景
蔡健雅 列穆尼亞演唱會:
蔡健雅 列穆尼亞演唱會

蔡健雅 列穆尼亞演唱會合作,叁式製作了開場前三首電子風格的歌曲〈異類的同類〉、〈失語者〉、〈菲林〉的影像視覺,以及〈空白格〉中LED矩陣的即時影像,主要是用粒子去做,運用點雲做為視覺主軸,可模擬煙、風、碎形等特效,再擷取表演者的即時動作,疊加在配合當時滿流行的攝影測量法 photogrammetry 後,經過粒子化處理的地景影像之上。

為台中花博製作的作品<0-3886>將地板打造為一個具即時互動性的演算視覺,觀眾的位置與動態成為了畫面中的一部分,走在地板上可以和粒子和線條有互動。視覺動態請見這部影片

台中花博展出的作品<0-3886>
台中花博展出的作品<0-3886>

以上較前期的作品都是用 OpenFramworks 做,後來我們較常用的轉換工具是 Unity。要如何判斷什麼時候使用哪種工具呢?叁式的切分依據大概是看得到的東西用 Unity,較看不到的東西用 OpenFramworks 做。有在用 Unity 的人應該知道,後來有出像 Visual Graph 這樣的工具,所以我們現在也會用 Visual Graph 或 Shader Graph 來做類似的創作。像剛剛提到的 Second Body,就是用 kinect 的點雲把它們建成 mesh。同樣的作品在 Unity,也可以透過 geometry shader,建成 Unity 裡面的 mesh,就可以跟環境做反射。

長榮飛安影片合作,利用 OpenCV 中的光流(optical flow)技術,一般來說是偵測 2D 影像中像素 (pixel) 的流動,像是人往前移動或揮手的向量。如何將 2D 結合到 3D 呢?例如將 kinect 偵測出來的深度圖畫面轉譯成 3D 的 position,再對他做 optical flow 技術後,便會成為 3D optical flow 檔案,就能在空間中結合煙霧的模擬,讓粒子隨著舞者的動作產生變化。這些包括像模擬都會透過一連串 fragment shader 去做運算,粒子的話就是用 compute 或 geometry 來做。

光流(optical flow):陌生的名詞,但其實每天都能看到。光流指的是我們在這個不停運轉著的世界裡,感覺到的明顯視覺運動,像是在移動的交通工具上看著樹、建築等景物呼嘯而過,我們能通過不同物件的運動速度判斷它們與我們的距離。

五月天-玫瑰少的年合作,視覺都是用Unity製作
五月天-玫瑰少年合作,利用 Unity 的 Particle system 去做地板及牆面的影像。以及上方這些圖像,也都是透過unity製作
2021台北時裝週互動投影視覺效果
2021台北時裝週合作,在台北101双融域展示,投影的背景視覺畫面也是透過unity製作大量的線條,舞者走過時,會隨著音樂及舞者肢體動作造成擾動變化。
模擬鄧紫棋 GMA30 的舞台 LED
模擬鄧紫棋 GMA30 的舞台 LED

除了視覺之外,我們也時常把unity拿來做模擬器,因為時常有一些展演活動,需要在進場前預測、模擬活動現場該長什麼樣子,才最符合我們的想像和設計。像鄧紫棋 GMA30 的舞台 LED 是由很多小波浪組成的。就視覺來說這樣做是很困難的,必須要出很多很破碎的影像。叁式利用 Unity 模擬器,讓視覺可以在 After Effects 裡面去呈現一整大片的影像,再透過 UV 轉換在 Unity 裡面做即時的預覽。

Gogoro VIVA MIX新車發表會模擬
Gogoro VIVA MIX新車發表會模擬

Gogoro VIVA MIX新車發表會合作,會場裡有非常多 AGB 的台車移動,一樣是用模擬器先知道到時候的陣型會怎麼變化。現場表演也是用一模一樣的程式同時間去跑,也就是說模擬器呈現的樣子跟現場的樣子幾乎同步。

很多案子的細節礙於時間關係無法一一介紹,這個notion可以分享給大家,如果有興趣可以點進連結來看。每個案例都有 hashtag 一些關鍵字,想知道這些視覺效果是用什麼方式做出來的,都可以點連結(有些案例直接放官網案例連結)及影片,或是透過關鍵字去搜尋。

接著就來實際放一些 demo,都先以 OpenFrameworks 來做示範:

1. 分子流動,這個是 OpenFrameworks 加上 flex 的物理引擎,讓這些粒子在空間中隨著物體的重力流動,中間有一個球會吸附這些粒子,讓這些液體經過這些球時被吸附到這上面去,有些水花流動的感覺。

2. 測試超越粒子的極限,當時想測試電腦的極限可以跑幾顆粒子,這件作品大概有一百還是兩百萬顆。現在電腦效能更好,Unity 的話就可以跑個七八百萬甚至到一千萬顆。

3. 墨汁暈染效果,這個是想做不同的嘗試,想說能不能把粒子做出像墨汁或顏料在紙張上暈開的感覺。像這個效果不錯,但可惜一直沒辦法用在商案中。

4. SONY互動網站,跟SONY合作網站轉場的效果,因為 OpenFlow 的 GLSL (OpenGL Shader Language) 跟網頁用的是一模一樣,所以其實我都是在 OpenFrameworks 寫完後無痛轉移到 GLSL,雖然網頁的 webGL 版本需要更低,但大概可以做到接近的模擬,網站從一頁進到下一頁時透過 shader 讓畫面做流動、背景再做一些轉場效果後到下一頁的畫面。

Q:GLSL轉換的過程 A:當時的分工,因為客戶公司有很多自己的前端工程師,所以前端輪不到我寫,我記得他們前端是用JS (canvas) 寫的,將 canvas 傳進來的每一個像素,在轉換的同時過一個由我撰寫的 Shader,達成最後的效果。這支 Shader 的程式,最基礎的演算法是從 Shadertoy 來的,這邊也直接附上當初參考的連結。當然因為業主需求會有不一樣,所以需要自己完全理解這些程式碼在寫什麼,才能更進一步將程式碼修改成想要的樣子。但 Shadertoy 確實是非常好參考、拿素材的地方。


Lightning talk 2 – 張文瀚

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

<Wormhole>

張文瀚<Wormhole>
張文瀚<Wormhole>

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

本來就常在做數位藝術的創作,尤以 Shader 為主,本業在做 2D 遊戲,因緣際會回來使用 Processing 創作。這件作品<Wormhole>是無限的圓延伸至盡頭,每一個圓都是前一個瞬間,把前一針的整個畫面複製、縮小再放進這一針畫面裡,如果我們將 frameRate 改為 1 (一秒一針)就可以立即了解。其他在 Shader裡面,像是圓的半徑等變數都可以玩玩看,會有完全不一樣的效果。

<Out of bounds>

張文瀚<Out of bounds>
張文瀚<Out of bounds>

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

這是一件無互動的作品,想要做出銀河系之外的飄浮感覺。最後呈現的這個效果也是在創作的過程中一個美麗的意外,主要是加上了 uv.y /= uv.x * 2.; 這行數學運算的程式碼,少了他,只是一個同心圓的圖案;加上他,把整個畫布增添了詭異的扭曲,造就出這有趣的空間感,感覺就像在銀河系以外能夠看到的景象。

追蹤創作者:https://openprocessing.org/user/322254?view=sketches


若你還沒有看過上篇,必不能錯過:
初次見面請多指教!Creative Coding第一次社群聚(上)吳哲宇的生成式藝術宇宙

想知道你的 NFT 究竟有沒有市場?下篇讓黃豆泥為你解惑:
初次見面請多指教!Creative Coding第一次社群聚(下)黃豆泥:沒有市場的靈魂綁定NFT

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

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


整理編輯:Chia 編

墨雨設計banner

訂閱 Creative Coding Taiwan 電子報:

這篇文章 初次見面請多指教!Creative Coding第一次社群聚(中)Hoba與叁式的演算視覺邁進之路 最早出現於 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 - 互動程式創作台灣站

]]>