4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NCCAdvent Calendar 2018

Day 5

MetalとSwiftで遊ぶ「エフェクトとKoara」

Last updated at Posted at 2018-12-05

この記事はNCC Advent Calendar 2018の5日目の記事です.

アドベントカレンダー内で勝手にやってるMetalの連載も5日目です.

勝手にやってるMetal連載

最近Metalを初めて楽しくなっちゃったのでたくさんoutputしてみる会です.

  1. Rendererを作る
  2. プロシージャルモデリング的な何か
  3. フラグメントシェーダで遊ぶ
  4. テクスチャで遊ぶ
  5. エフェクトで遊ぶ ← イマココ

(そろそろしんどくなってきた)

Koaraにエフェクトをかけて遊ぶぞ!

フラグメントシェーダしか使いません.
他のソースコードはgithubのリポジトリ前回のTextureの記事を参考にしてください

RGBディストーション

やること

  • 赤色成分をx方向にずらす
  • 緑色成分をy方向にずらす
  • ずらす方向はそれぞれ,スクリーンの中心からの距離に比例する

出来上がり

コード

shades.cpp
fragment half4 fragmentDay5(VertexOut vertexIn [[stage_in]],
                            texture2d<float, access::sample> koaraTexture [[texture(0)]]) {
    // 座標変換とそのまま用いたテクスチャ座標
    float4 p = (vertexIn.screenCoord+1.0)/2.0;
    p.y = 1.0-p.y;
    // uniforms
    float2 touch = vertexIn.touch;
    float time = vertexIn.time;
    constexpr sampler nearestSampler(coord::normalized, filter:: nearest);
    float4 koara = koaraTexture.sample(nearestSampler, p.xy);
    // return half4(koara) // ここからスタート
    
    // RGBディストーション用のコード
    // x方向とy方向にずらした座標でサンプリング
    float2 d = vertexIn.screenCoord.xy*0.03;
    float2 distortion_x = float2(p.x+d.x, p.y);
    float2 distortion_y = float2(p.x, p.y+d.y);
    float4 koara = koaraTexture.sample(nearestSampler, p.xy);
    float4 Koara_distortion_x = koaraTexture.sample(nearestSampler, distortion_x);
    float4 Koara_distortion_y = koaraTexture.sample(nearestSampler, distortion_y);
    // 合わせて描画
    return half4(Koara_distortion_x.x ,Koara_distortion_y.y, koara.z, 1.0);
}

ホワイトノイズ

やること

ノイズを生成して,サンプルした色と掛け合わせます.
使用するノイズは,コピペ伝承のfract-sinノイズです.

出来上がり

コード

shaders.cpp
float rnd(float2 n) {
    return fract(sin(dot(n, float2(12.9898,4.1414)))*43758.5453);
}

fragment half4 fragmentDay5(VertexOut vertexIn [[stage_in]],
                            texture2d<float, access::sample> koaraTexture [[texture(0)]]) {
    // 座標変換とそのまま用いたテクスチャ座標
    float4 p = (vertexIn.screenCoord+1.0)/2.0;
    p.y = 1.0-p.y;
    // uniforms
    float2 touch = vertexIn.touch;
    float time = vertexIn.time;
    constexpr sampler nearestSampler(coord::normalized, filter:: nearest);
    float4 koara = koaraTexture.sample(nearestSampler, p.xy);

    // ホワイトノイズ
//    return half4(half3(koara.xyz*rnd(p.xy)),1.0);
    
    // ホワイトノイズで2値化
    return half4(half3(koara.xyz*step(0.5, rnd(p.xy))),1.0);
    
    // 砂嵐化
//    return half4(half3(koara.xyz*step(0.5, rnd(p.xy+time))),1.0);
}

横にずらす(エフェクトの名前がわからない)

ホワイトノイズで使ったrnd関数を利用して,各textureのrowを同じだけ横にずらします.
説明分かりづらいので,画像を見て

出来上がり

shaders.cpp

float rnd(float2 n) {
    return fract(sin(dot(n, float2(12.9898,4.1414)))*43758.5453);
}

fragment half4 fragmentDay5(VertexOut vertexIn [[stage_in]],
                            texture2d<float, access::sample> koaraTexture [[texture(0)]]) {
    // 座標変換とそのまま用いたテクスチャ座標
    float4 p = (vertexIn.screenCoord+1.0)/2.0;
    p.y = 1.0-p.y;
    // uniforms
    float2 touch = vertexIn.touch;
    float time = vertexIn.time;
    constexpr sampler nearestSampler(coord::normalized, filter:: nearest);
    float4 koara = koaraTexture.sample(nearestSampler, p.xy);
    float2 dx_p = float2(p.x+0.03*(rnd(float2(p.y))*2-1), p.y);
    float4 dx_Koara = koaraTexture.sample(nearestSampler, dx_p);
    
    return half4(dx_Koara);
}

ポスタリゼーション

やること

それぞれの画素で赤色成分,緑色成分,青色成分をn段階に分けます.
まあ見ればわかるはず

出来上がり

コード

shaders.cpp
half3 posterization(float3 c, int n) {
    return half3(ceil(c.x / (1.0/n)) / n,
                 ceil(c.y / (1.0/n)) / n,
                 ceil(c.z / (1.0/n)) / n);
}

fragment half4 fragmentDay5(VertexOut vertexIn [[stage_in]],
                            texture2d<float, access::sample> koaraTexture [[texture(0)]]) {
    // 座標変換とそのまま用いたテクスチャ座標
    float4 p = (vertexIn.screenCoord+1.0)/2.0;
    p.y = 1.0-p.y;
    // uniforms
    float2 touch = vertexIn.touch;
    float time = vertexIn.time;
    constexpr sampler nearestSampler(coord::normalized, filter:: nearest);
    float4 koara = koaraTexture.sample(nearestSampler, p.xy);

    return half4(posterization(koara.xyz,4),1.0);
}

ソラリゼーション

やること

ソラリゼーションは,トーンカーブを色々したものです.
白黒画像ではなく,赤色成分,緑色成分,青色成分それぞれ独立にソラリゼーションしました,
こんな感じに,部分的に反転します.

出来上がり

こちらからスクショしました.
画像処理検定の参考書にもこのような図がありましたね.

コード

shaders.cpp
half3 solarisation(float3 c) {
    return half3((1-cos(3*3.14*c.x))/2,
                 (1-cos(3*3.14*c.y))/2,
                 (1-cos(3*3.14*c.z))/2);
}

fragment half4 fragmentDay5(VertexOut vertexIn [[stage_in]],
                            texture2d<float, access::sample> koaraTexture [[texture(0)]]) {
    // 座標変換とそのまま用いたテクスチャ座標
    float4 p = (vertexIn.screenCoord+1.0)/2.0;
    p.y = 1.0-p.y;
    // uniforms
    float2 touch = vertexIn.touch;
    float time = vertexIn.time;
    constexpr sampler nearestSampler(coord::normalized, filter:: nearest);
    float4 koara = koaraTexture.sample(nearestSampler, p.xy);

    // ソラリゼーション
    return half4(solarisation(koara.xyz),1.0);
}


コードはこちら

githubにあります.

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?