Simple Water Caustics
Vulkan Ray TracingでWater Causticsを書いてみました。Water Causticsとは水面の底にできる光の模様のことです。正確には光りの屈折でできあがる様々な模様のことのようです。
コースティクス - Wikipedia
水面の波の式
様々な波を試してみましたが、最も綺麗な模様を描けるのは円形波のようでした。
円形波自体は
で表されます。ここで、、です。
上記のプログラムでは
pos.y = -1.5 + sin(time * 5.0f - glm::length(pos - glm::vec3(0, pos.y, 0)) * 8.0f) / 16.0f;
としています。
Caustics描画
アイデアは次のNVIDIAのblogに書かれているものと同じです。
Chapter 2. Rendering Water Caustics | NVIDIA Developer
ただし今回の例だと光源が一つだけなのでlight mapは作成せずに、shaderの中で直接計算しています。
//caustics uint causticFlags = gl_RayFlagsOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT; traceRayEXT(topLevelAS, causticFlags, 0xFF, 1, 0, 1, refractPos, 0.001, vec3(0.0, -1.0, 0.0), tMax, 2); vec3 waterSurface = prd.pos; vec3 waterNormal = prd.normal; vec3 waterV = refract(vec3(0.0, -1.0, 0.0), -waterNormal, nWater/nAir); float t = (pushC.lightPosition.y - waterSurface.y) / waterV.y; vec3 sunMapPoint = waterSurface + t * waterV; float caustics = 1.0 / (1.0 + length(sunMapPoint - pushC.lightPosition)); color += caustics;
図でいうところの
ということになります。
本来ならCausticsは光源から波に当たった光の内、屈折した結果ある点に集まるすべての光をトレースする必要がありますが、それだと難易度が高すぎるので、一番強い光ということで水面に垂直にあたる光のみをトレースしています。
これだけでも、実施例のようにそれなりの結果が得られますね。