Aqoole_Hateenaの技術日記

vulkan+raytraceで色々描いてます

compute shaderでanimation部分を計算してみた

compute shaderでanimation部分の計算

vertex shaderとfragment shaderを用いるのであれば、vertex shaderでanimation後の位置に更新した後fragment shaderで色を付ければよいと思うが、raytracing pipelineでレンダリングする場合にはどの時点で位置を計算するのが良いのかわからなったので、compute shaderで計算するようにした。
もしかすれば、raytracing pipelineの中で頂点座標の位置を更新する方法もあるかもしれないが、rayがヒットするタイミングがどうなんだろうと思ったので、raytracing pipelineに入る前にcompute pipelineを動かし、compute pipelineの計算が終わった後にraytracing pipelineの処理を行うようにした。

compute shader部分

簡単に紹介

layout(binding = 1, set = 0, scalar) buffer VerticesobjDst {Vertex3DObj vobjDst[];} verticesobjDst[];
:
      vec3 v1 = w * (mats[0].m[jj] * vec4(v0, 1.0)).xyz;
      vec3 v2 = w * (matsNext[0].m[jj] * vec4(v0, 1.0)).xyz;
      if (animNum.a == 4){
        v3 += v1 + ((v2 - v1) * (1.0 - time.t));
      } else {
        v3 += v1 + ((v2 - v1) * (time.t - KeyFrames[animNum.a]));
      }
:
    verticesobjDst[0].vobjDst[ii].pos = v3;

mats:今のkey frameのanimation matrix
matsNext:次のkey frameのanimation matrix
今のkey frameと次のkey frameの位置を計算し、今の時間分だけ線形に補間している。
compute shader内ではraytracing pipelineでも用いるstorage bufferを共有しているので、storage bufferの値を直接更新することで、device(GPU)側のメモリだけで処理が完結できていると思っている。

個人的な反省

今回は別のところで、間違ったことをしており時間がかかってしまった。
bufferのアップデートの処理でindexを間違えており、animation matrixを更新するはずがずっとjointの重み付けのbufferをanimation matrixの値で更新していた。
そのせいでbufferの値が滅茶苦茶になっていたが、まさか更新先のbufferが間違えているとは思わず、調査にすごく時間がかかってしまった。
気づいてしまえばindexを間違えていただけなのだが、同期処理のタイミングを疑ってみたり、shader内でのstorage bufferの更新処理を疑ってみたり、メモリアラインメントを疑ってみたりetc...
凡ミスをしないようなアーキテクチャが必要なんだろうと思うが、今回で言えばバッファーをindexで管理せずに名前などで管理するなどになるか。