Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CEDEC+KYUSHU2019 Toon Rendering by Directx Raytracing

orangesuzuki
November 23, 2019

CEDEC+KYUSHU2019 Toon Rendering by Directx Raytracing

DirectX リアルタイムレイトレーシングによるトゥーンレンダリング表現の可能性
http://cedec-kyushu.jp/2019/session/15.html

Microsoft DirectX Raytracing(以下DXR)によるリアルタイムトゥーンレンダリング表現について解説します。レイトレーシングシェーダーを用いることで、トゥーン風な表現をどのように実装したか、具体的なシェーダーとその描画結果を交えながら解説します。
レイトレーシングの特徴である正確なシャドウ表現にドット柄やハッチングなどのパターン模様を施す手法も紹介します。

orangesuzuki

November 23, 2019
Tweet

More Decks by orangesuzuki

Other Decks in Technology

Transcript

  1. Copyright 2019 DELiGHTWORKS. ディライトワークス株式会社 研究開発部 Real Time Computingユニット リードリサーチャー 鈴木

    克史 リアルタイムレイトレーシングによる トゥーンレンダリング表現の可能性 DirectX
  2. Copyright 2019 DELiGHTWORKS. 2 “最高にエキサイティングなグラフィック”を! リアルタイムレイトレーシングの表現力と可能性に関して、 研究開発部と DELiGHT Graphic Works

    が共同で取り組みました。 機能を最大限に引き出し、見る人に訴えかけるグラフィックスを DELiGHTWORKS は目指します!
  3. Copyright 2019 DELiGHTWORKS. 16 Menu 2 ドットシェーダー 4 アウトラインシェーダー 5

    AOとアニメーション 3 1 DXRのきほん レンダリングフロー(DXR × Compute)
  4. Copyright 2019 DELiGHTWORKS. 32 DXR ディレクショナルライト ポイントライト AO リフレクション Compute

    コントラスト補正 カラー補正 カラーオーバーレイ なじませ効果 木の色で2次反射を近似
  5. Copyright 2019 DELiGHTWORKS. DXR 33 ディレクショナルライト ポイントライト AO リフレクション Compute

    コントラスト補正 カラー補正 カラーオーバーレイ アウトライン 輪郭の強調
  6. Copyright 2019 DELiGHTWORKS. 34 DXR レンダリングフロー全体 ディレクショナルライト ポイントライト AO リフレクション

    コントラスト補正 カラー補正 カラーオーバーレイ アウトライン +Compute Compute
  7. Copyright 2019 DELiGHTWORKS. 39 レイトレーシングの原理 Scratchapixel 2.0 Rasterization: a Practical

    Implementation https://www.scratchapixel.com/lessons/3d-basic-rendering/ rasterization-practical-implementation
  8. Copyright 2019 DELiGHTWORKS. 40 レイトレーシングのパイプライン RayGenerationシェーダー ClosestHitシェーダー Missシェーダー 交点あり 交点なし

    シーンの走査 レイの生成 レイを飛ばす(TraceRay関数) 三角形に交差し た? RayGeneration、ClosestHit、Missの 3つのシェーダーをまずおさえよう はい いいえ
  9. Copyright 2019 DELiGHTWORKS. 41 レイトレースシャドウの原理 視点 スクリーン スクリーンレイ シャドウレイ シャドウレイ

    スクリーンレイ スクリーンレイを飛ばした後、 さらに光源に向かってレイを飛ばす。 遮蔽されているかどうかを判定する
  10. Copyright 2019 DELiGHTWORKS. シャドウレイ関数(TraceShadowRay) 43 スクリーンレイを飛ばす オブジェクトと交差あり シーンの走査 RayGenerationシェーダー ClosestHitシェーダー

    他のオブジェク トに交差した? shadowPayload を返す いいえ 遮蔽なし shadowPayload.hit = false Missシェー ダー シャドウレイを飛ばす RayGenerationシェーダー はい 遮蔽あり shadowPayload.hit = true ClosestHit シェーダー 遮蔽情報を使ってシェーディン グ シャドウのアルゴリズムは2ステップ レイトレースシャドウのアルゴリズム
  11. Copyright 2019 DELiGHTWORKS. 61 2Dドットの描き方 画面のUV値をとる UV値をもとに図形を描画 明るさによって図形を変形させる // レイのインデックス

    (0,1,2,3,・・・ float2 pixIdx = float2(DispatchRaysIndex().xy); // 画面解像度 (1920, 1080) float2 numPix = float2(DispatchRaysDimensions().xy); // 正方形化 numPix = float2(min(numPix.x, numPix.y), min(numPix.x, numPix.y)); // UV化 (0~1) float2 uv = pixIdx / numPix * scale; // パターン化 float color = getPattern(uv, shade, mode); // 2値化 color = round(color);
  12. Copyright 2019 DELiGHTWORKS. 62 2Dドットの描き方 画面のUV値をとる UV値をもとに図形を描画 明るさによって図形を変形させる float getPattern(float2

    uv, float shade = 1) { float roughness = 0.175; float scale = 5.7; // 大きさの調整 uv *= scale; // 0~1に変換 uv = fmod(uv, 2) * 0.5; // ドット模様化 float dot = length(float2(0.5, 0.5) - uv); //シャープ化 dot = pow(dot, roughness * 4); // くりぬき(ドットの反転) dot = pow(dot, pow(saturate(1 - shade), roughness * 2)); return dot; }
  13. Copyright 2019 DELiGHTWORKS. 64 3Dドットの描き方 画面の位置(X,Y,Z)をとる 位置をもとに図形の形を描画 明るさによって図形を変形させる // ピクセルの明るさ(ライティングの結果値)

    float luminosity = 1.0; // ピクセルの空間座標 float3 hitPosition = HitWorldPosition(); // ドット化された明るさ float color = getTriPlanarPattern(position, N, luminosity);
  14. Copyright 2019 DELiGHTWORKS. 65 3Dドットの描き方 画面の位置(X,Y,Z)をとる 位置をもとに図形の形を描画 明るさによって図形を変形させる // ----------------------------------------------------

    // 3D Tri-Planar Texture Mapping // ---------------------------------------------------- float getTriPlanarPattern(float3 pos, float3 normal, float shade) { float3 blending = abs(normal); blending = normalize(max(blending, 0.00001)); // 法線の合計値を1になるようにさらに正規化 float b = (blending.x + blending.y + blending.z); blending /= b; // 各座標軸方向から見たパターンを取得 float xaxis = getPattern(pos.yz, shade, mode); float yaxis = getPattern(pos.xz, shade, mode); float zaxis = getPattern(pos.xy, shade, mode); // XYZ軸方向の結果を、法線の各成分を係数としてかけて合算する float color = xaxis * blending.x + yaxis * blending.y + zaxis * blending.z; // シャープ化 color = round(color); return color; }
  15. Copyright 2019 DELiGHTWORKS. 68 3Dチェック模様の描き方 画面の位置(X,Y,Z)をとる 位置をもとに図形の形を描画 明るさによって図形を変形させる float getCheckerPattern(float2

    uv, float shade = 1) { // 符号保持 Float2 uv2 = uv; // 0-1化、大きさ調整 float scale = 1; uv *= scale; uv = fmod(uv, 2) * 0.5; uv = round(uv); uv = abs(uv); // チェック化 float pattern = abs(uv.x - uv.y); // 明るさでくりぬき pattern *= (1-shade); pattern = 1 - pattern; return pattern; }
  16. Copyright 2019 DELiGHTWORKS. 77 ハッチング模様の描き方 画面のUV値をとる UVをもとに図形の形を描画 明るさによって図形を変形させる float getSlashPattern(float2

    uv, float shade, float scaleUV = 90) { // ななめ化 float pattern = uv.x + uv.y; // 小数部のみにする pattern = frac(pattern); // 例:ななめの交差網 { // float pattern2 = uv.x - uv.y; // pattern2 *= scaleUV; // pattern2 = frac(pattern2); // pattern = max(pattern, pattern2); } // 例:ななめ✕水平 { // float pattern3 = uv.y; // pattern3 *= scaleUV; // pattern3 = frac(pattern3); // pattern = max(pattern, pattern3); } return pattern; }
  17. Copyright 2019 DELiGHTWORKS. 84 [shader("closesthit")] void MyClosestHitShader (inout RayPayload rayPayload,

    in Attributes attr) { // 1回目のレイの衝突時のみノーマルバッファに描画する → 反射材質中の輪郭線を描画させない if (rayPayload.rayRecursionDepth <= 1) { rayPayload.normal = normal; } } シェーダーコード例
  18. Copyright 2019 DELiGHTWORKS. 86 各ピクセルの法線ベクトルの内積をとる (①と②、①と③でチェック) 1 2 3 同じ向きを向いていたら

    (内積が0.1より大きければ)、 アウトラインを描画しない ①のピクセルに対するアウトライン判定を取りたい Computeシェーダーでの輪郭線の検出
  19. Copyright 2019 DELiGHTWORKS. 87 アウトラインシェーダー // 法線バッファから輪郭線を検出する float4 drawLine(float2 dispatchID)

    { float2 center = dispatchID + float2(0, 0); float2 right = dispatchID + float2(1, 0); float2 bottom = dispatchID + float2(0, 1); float4 centerN = getNormal(center); float4 rightN = getNormal(left); float4 bottomN = getNormal(bottom); float param0 = 0.1; bool noLine = param0 < dot(centerN.xyz, rightN.xyz) && param0 < dot(centerN.xyz, bottomN.xyz); if (noLine) { return float4(0, 0, 0, 0); } return float4(1, 1, 1, 0); }