Share
Embed
もっと綺麗で写実的な絵作りがしたい!レイマーチング向けのシェーディング技術
レイマーチングで大域照明を実現するための理論と実践を紹介します。
メガデモ勉強会! 2018で発表しました。
https://atnd.org/events/93843
がむ
March 10, 2018
Transcript
44 slides
-
ࣗݾհ • @gam0022 / Sho HOSODA • KLabגࣜձࣾ UnityΤϯδχΞ •
TokyoDemoFest 2017 GLSL Graphics Compo෦ 3Ґೖ 2 -
ൃදͷྲྀΕ • ຊͷલʹ ‣ ϨΠϚʔνϯάͷ͓͞Β͍ • ཧ ‣ େҬর໌ͱԿ͔ •
࣮ફ ‣ ϨΠϚʔνϯάͰେҬর໌Λ࣮ݱ͢Δख๏ͷհ • ͓·͚ ‣ ϨΠϚʔνϯά͚ͷϚςϦΞϧ࣮ͷ ݸਓతϕετϓϥΫςΟεͷհ 3 -
ϨΠϚʔνϯάͷ͓͞Β͍ • ڑؔʢdistance functionʣͱ͍͏ࣜͰܗঢ়Λఆٛ ‣ 3DϞσϧΛ༻ҙ͢Δඞཁ͕ͳ͍ ‣ ݫ͍͠༰ྔͷ੍ͷ͋ΔϝΨσϞͱ૬ੑ͕ྑ͍ • TDFͷ্Ґ࡞ϨΠϚʔνϯάΛར༻
4 Fusioned Bismuth by gam0022 @TDF2017 GLSL Graphics Compo 2nd stage BOSS by 0x4015&YET11 @TDF2016 PC 4K Intro Shift by FMS_Cat @TDF2017 Combined Demo Compo -
ϨΠϚʔνϯάͷ͓͞Β͍ • ڑؔ = p͔Βମද໘ͷ࠷ڑΛฦؔ͢ 5 float sdSphere( vec3 p,
float s ) { return length(p)-s; } float udBox( vec3 p, vec3 b ) { return length(max(abs(p)-b,0.0)); } http://iquilezles.org/www/articles/distfunctions/distfunctions.htm -
ϨΠϚʔνϯάͷ͓͞Β͍ • ૢ࡞ͱͯ୯७ ‣ ࠷ͷڑ͚ͩϨΠΛਐΊΔͷΛ܁Γฦ͚ͩ͢ • Ͱɺ͏·͘ಈ͘ ‣ ަࠩ͢ΔέʔεͳΒɺ࠷ڑͣͭϨΠΛਐΊΕɺ ϨΠͷઌ͕ަࠩʹ͍͔ͭ౸ୡ͢Δ
‣ ࠷ڑͣͭਐΊΔͷͰɺϨΠ͕ମΛಥ͖ൈ͚Δ ͜ͱ͕ͳ͍ 17 -
ϨΠϚʔνϯάͷ͓͞Β͍ • ϨΠτϨͱಉ͡Α͏Α͏ʹγΣʔσΟϯά • ๏ઢڑؔͷޯ͔Βܭࢉ 18 vec3 calcNormal(vec3 p) {
return normalize(vec3( dScene(p + vec3( EPS, 0.0, 0.0)) - dScene(p + vec3( -EPS, 0.0, 0.0)), dScene(p + vec3(0.0, EPS, 0.0)) - dScene(p + vec3(0.0, -EPS, 0.0)), dScene(p + vec3(0.0, 0.0, EPS)) - dScene(p + vec3(0.0, 0.0, -EPS)) )); } ๏ઢ γΣʔσΟϯά -
ؒޫͱ֦ࢄ • ޫମʹিಥ͢Δͱɺόϥόϥʹ֦ࢄ͢Δ • ද໘ͷΒ͔͞ʹΑ֦ͬͯࢄͷ߹͍ҟͳΔ • ؒޫΛͯ͢γϛϡϨʔτ͢Δܭࢉίετߴ͍ 25 Sebastien Lagarde
and Charles de Rousiers, “Moving Frostbite to Physically Based Rendering 2.0”, SIGGRAPH 2014 Course: Physically Based Shading in Theory and Practice, p.8 -
େҬর໌Λ࣮ݱ͢Δख๏ • ΦϑϥΠϯϨϯμϦϯά͚ͳΒ ‣ ύετϨʔγϯά • ޫͷܦ࿏ʢύεʣΛͯͯ͢͠ɺ ؒޫΛܭࢉ • ڀۃͷख๏͕ͩɺ͕͔͔࣌ؒΔ
• ϦΞϧλΠϜϨϯμϦϯά͚ͳΒ ‣ ؒޫΛΞϯϏΤϯτΦΫϧʔδϣϯͰۙࣅ 27 ϝΨσϞͬͪ͜ -
ΞϯϏΤϯτΦΫϧʔδϣϯ • ΞϯϏΤϯτΦΫϧʔδϣϯʢAmbient Occlusion, AOʣ • ःṭʢΦΫϧʔδϣϯʣ͞Ε͍ͯΔ෦Λܭࢉͨ͠ͷ ‣ ΞϯϏΤϯτʢڥޫɺͭ·Γؒޫʣ͕ಧ͘ڧ •
ܭࢉͷख๏λΠϛϯά৭ʑ ‣ Unity • ࣄલܭࢉͨ݁͠ՌΛςΫενϟʹ ম͖ࠐΉEnlighten ‣ Unreal Engine • DepthόοϑΝ͔ΒϦΞϧλΠϜʹ ܭࢉ͢ΔSSAO • ͰɺϨΠϚʔνϯάͰͲ͏Δ͔ʁ 28 ΞϯϏΤϯτΦΫϧʔδϣϯͷΈ http://ambientocclusion.hatenablog.com/entry/2013/10/15/223302 -
• ๏ઢํ n ʹϨΠΛඈͯ͠ɺःṭ occ Λܭࢉ • ϨΠͷઌִؒͰҠಈ AOΛܭࢉ͢ΔGLSLͷίʔυ 31
float calcAo(in vec3 p, in vec3 n){ float k = 1.0, occ = 0.0; for(int i = 0; i < 5; i++){ float len = 0.15 + float(i) * 0.15; float distance = dScene(n * len + p); occ += (len - distance) * k; k *= 0.5; } return saturate(1.0 - occ); } n p -
ःṭoccͷܭࢉ 32 ःณͳ͠ EJTUBODFMFO ःณ͋Γ EJTUBODFMFO len distance len distance
occ += (len - distance) * k; -
ϨΠϚʔνϯά͚ͷϚςϦΞϧ࣮ ృΓ͚͍ͨΦϒδΣΫτຖʹڑؔΛఆٛ 36 float dSphere(vec3 p, float r) { return
length(p) - r; } float dSphereCenter(vec3 p) { return dSphere(p - vec3(0.0, 1.0, -0.5), 1.0); } float dSphereLeft(vec3 p) { return dSphere(p - vec3(2.5, 1.0, 0.0), 1.0); } dSphereLeft dSphereCenter -
ϨΠϚʔνϯά͚ͷϚςϦΞϧ࣮ িಥใͷߏମ Intersection Λఆٛ 37 struct Intersection { bool hit;
vec3 position; float distance; vec3 normal; vec2 uv; float count; vec3 ambient; vec3 diffuse; vec3 specular; float reflectance; vec3 color; }; -
ϨΠϚʔνϯά͚ͷϚςϦΞϧ࣮ • িಥఆΛߦ͏ intersectObjects ؔ • ϨΠϚʔνϯάͰަΛٻΊͨޙ ‣ ΦϒδΣΫτຖͷڑؔΛൺֱ͠ɺͲͷΦϒδΣΫτʹিಥ͔ͨ͠ఆ ‣
Intersection ʹϚςϦΞϧใʢambient/diffuse/specularʣΛηοτ 38 void intersectObjects(inout Intersection intersection, inout Ray ray) { float d; float distance = 0.0; vec3 p = ray.origin; for (float i = 0.0; i < 100.0; i++) { d = dObjects(p); distance += d; p = ray.origin + distance * ray.direction; intersection.count = i; if (abs(d) < EPS || distance > 100.0) break; } if (abs(d) < EPS && distance < intersection.distance) { intersection.distance = distance; intersection.hit = true; intersection.position = p; intersection.normal = calcNormal(p, dScene); if (abs(dSphereLeft(p)) < EPS) { intersection.ambient = vec3(0.0); intersection.diffuse = vec3(0.0); intersection.specular = vec3(0.5); intersection.reflectance = 0.9; } else if (abs(dSphereCenter(p)) < EPS) { intersection.ambient = vec3(0.3, 0.3, 0.6) * 1.2; intersection.diffuse = vec3(0.3, 0.3, 0.6) * 0.5; intersection.specular = vec3(0.3); intersection.reflectance = 0.2; } else if (abs(dMengerSpongeRight(p)) < EPS) { intersection.ambient = vec3(0.1, 0.2, 0.1) * 2.0; intersection.diffuse = vec3(0.1, 0.2, 0.1) * 0.2; intersection.specular = vec3(0.0); intersection.reflectance = 0.0; } } } if (abs(dSphereLeft(p)) < EPS) { intersection.ambient = vec3(0.0); intersection.diffuse = vec3(0.0); intersection.specular = vec3(0.5); intersection.reflectance = 0.9; } else if (abs(dSphereCenter(p)) < EPS) { intersection.ambient = vec3(0.3, 0.3, 0.6) * 1.2; intersection.diffuse = vec3(0.3, 0.3, 0.6) * 0.5; intersection.specular = vec3(0.3); intersection.reflectance = 0.2; } else if (abs(dMengerSpongeRight(p)) < EPS) { intersection.ambient = vec3(0.1, 0.2, 0.1) * 2.0; intersection.diffuse = vec3(0.1, 0.2, 0.1) * 0.2; intersection.specular = vec3(0.0); intersection.reflectance = 0.0; } -
ϨΠϚʔνϯά͚ͷϚςϦΞϧ࣮ • γΣʔσΟϯάΛߦ͏ calcRadiance ؔ • Intersection ͷϚςϦΞϧใΛ༻͍ͯγΣʔσΟϯά • PhongͷࣹϞσϧͷܭࢉྫ
39 void calcRadiance(inout Intersection intersection, inout Ray ray, int bounce) { intersection.hit = false; intersectScene(intersection, ray); if (intersection.hit) { // shading float diffuse = saturate(dot(lightDir, intersection.normal)); float specular = pow(saturate(dot(reflect(lightDir, intersection.normal), ray.direction)), 10.0); float ao = calcAo(intersection.position, intersection.normal); float shadow = calcShadow(intersection.position, lightDir); // mix intersection.color = intersection.ambient * ao + intersection.diffuse * diffuse * shadow + intersection.specular * specular * shadow; // fog intersection.color = mix(intersection.color, vec3(0.8), 1.0 - exp(-0.0001 * intersection.distance * intersection.distance * intersection.distance)); } else { intersection.color = texture(iChannel0, ray.direction).rgb; } } -
ϨΠϚʔνϯά͚ͷϚςϦΞϧ࣮ • PhongͷࣹϞσϧ ‣ ϨϯμϦϯά݁Ռ = ڥޫ+ ֦ࢄࣹ + ڸ໘ࣹ
‣ https://ja.wikipedia.org/wiki/PhongͷࣹϞσϧ 40 intersection.color = intersection.ambient * ao + intersection.diffuse * diffuse * shadow + intersection.specular * specular * shadow; -
ϨΠϚʔνϯά͚ͷϚςϦΞϧ࣮ Intersection ͷఆٛΛม͑ΕɺཧϕʔεͷγΣʔσΟϯάʹରԠͰ͖Δ 41 struct Intersection { bool hit; vec3
position; float distance; vec3 normal; vec2 uv; float count; vec3 ambient; vec3 diffuse; vec3 specular; float reflectance; vec3 color; }; struct Intersection { bool hit; vec3 position; float distance; vec3 normal; vec2 uv; float count; vec3 albedo; vec3 specular; float metalness; float roughness; vec3 color; }; PhongͷࣹϞσϧ༻ ཧϕʔεͷࣹϞσϧ༻ -
ϨΠϚʔνϯά͚ͷϚςϦΞϧ࣮ • ϝϦοτ ‣ ൚༻ੑՄಡੑߴ͍ • σϝϦοτ ‣ ίʔυ͕͘ͳΔ ‣
4K introͷΑ͏ͳ༰ྔ੍ݶͩͱݫ͍͠ 42