Created
September 27, 2018 05:04
-
-
Save edom18/b60166c6137953bc0aa778869f99dd31 to your computer and use it in GitHub Desktop.
レイマーチングでAmbient Occlusion ref: https://qiita.com/edo_m18/items/63dbacb57db3b7734483
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// なんちゃってAOを計算する | |
// | |
// +-----------------+--------------------+ | |
// | ro = Ray Origin | rd = Ray Direction | | |
// +-----------------+--------------------+ | |
vec4 genAmbientOcclusion(vec3 ro, vec3 rd) | |
{ | |
vec4 totao = vec4(0.0); | |
float sca = 1.0; | |
for (int aoi = 0; aoi < 5; aoi++) | |
{ | |
float hr = 0.01 + 0.02 * float(aoi * aoi); | |
vec3 aopos = ro + rd * hr; | |
float dd = distFunc(aopos); | |
float ao = clamp(-(dd - hr), 0.0, 1.0); | |
totao += ao * sca * vec4(1.0, 1.0, 1.0, 1.0); | |
sca *= 0.75; | |
} | |
const float aoCoef = 0.5; | |
totao.w = 1.0 - clamp(aoCoef * totao.w, 0.0, 1.0); | |
return totao; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
float distFunc(vec3 pos) | |
{ | |
float d1 = distSphere(pos, size); | |
float d2 = distPlane(pos, vec4(0.0, 1.0, 0.0, 2.0)); | |
float d3 = distTorus(pos, vec2(0.5, 0.2)); | |
return min(d3, min(d1, d2)); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vec3 aopos = ro + rd * hr; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
float hr = 0.01 + 0.02 * float(aoi * aoi); // aoiはイテレーション回数を表すint型。for (int aoi... | |
vec3 aopos = ro + rd * hr; | |
float dd = distFunc(aopos); | |
float ao = clamp(-(dd - hr), 0.0, 1.0); | |
totao += ao * sca * vec4(1.0, 1.0, 1.0, 1.0); | |
sca *= 0.75; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
float hr = 0.01 + 0.02 * float(aoi * aoi); // aoiはイテレーション回数を表すint型。for (int aoi... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vec3 aopos = ro + rd * hr; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
float dd = distFunc(aopos); | |
float ao = clamp(-(dd - hr), 0.0, 1.0); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
totao += ao * sca * vec4(1.0, 1.0, 1.0, 1.0); | |
sca *= 0.75; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vec3 cameraPos = vec3(0.0, -0.5, 1.5); | |
vec3 cameraDir = normalize(vec3(0.0, -0.3, -1.0)); | |
vec3 lightDir = vec3(1.0, 1.0, 1.0); | |
float softShadow = 16.0; | |
float size = 0.5; | |
// sphereの距離関数 | |
float distSphere(vec3 pos, float size) | |
{ | |
vec3 spPos = vec3(1.0, -1.8, -1.0); | |
return length(pos - spPos) - size; | |
} | |
// Planeの距離関数 | |
float distPlane(vec3 pos, vec4 n) | |
{ | |
return dot(pos, n.xyz) + n.w; | |
} | |
// トーラスの距離関数 | |
float distTorus(vec3 p, vec2 t) | |
{ | |
vec2 tPos = vec2(0.0, -2.0); | |
vec2 q = vec2(length(p.xy - tPos) - t.x, p.z); | |
return length(q - tPos) - t.y; | |
} | |
float distFunc(vec3 pos) | |
{ | |
float d1 = distSphere(pos, size); | |
float d2 = distPlane(pos, vec4(0.0, 1.0, 0.0, 2.0)); | |
float d3 = distTorus(pos, vec2(0.5, 0.2)); | |
return min(d3, min(d1, d2)); | |
} | |
vec3 getNormal(vec3 pos) | |
{ | |
const float e = 0.0001; | |
const vec3 dx = vec3(e, 0, 0); | |
const vec3 dy = vec3(0, e, 0); | |
const vec3 dz = vec3(0, 0, e); | |
float d = distFunc(pos); | |
return normalize(vec3( | |
d - distFunc(vec3(pos - dx)), | |
d - distFunc(vec3(pos - dy)), | |
d - distFunc(vec3(pos - dz)) | |
)); | |
} | |
// 影を計算する | |
// オブジェクトの衝突位置からライト方向にレイを飛ばし、 | |
// 遮蔽があったら影とする。 | |
// また、ライトに向かうレイがなにかのオブジェクトに接近した場合は | |
// 最接近情報を保持し、影の影響度として利用する(ソフトシャドウ) | |
// +-----------------+--------------------+ | |
// | ro = Ray Origin | rd = Ray Direction | | |
// +-----------------+--------------------+ | |
float genShadow(vec3 ro, vec3 rd) | |
{ | |
// 距離関数の結果 = 距離 | |
float h = 0.0; | |
// 現在のレイの位置 | |
float c = 0.001; | |
// レイの最接近距離 | |
float r = 1.0; | |
// シャドウ係数(濃さ) | |
float shadowCoef = 0.5; | |
// レイマーチにより影を計算する | |
for (float t = 0.0; t < 50.0; t++) | |
{ | |
h = distFunc(ro + rd * c); | |
if (h < 0.001) | |
{ | |
return shadowCoef; | |
} | |
// 現時点の距離関数の結果と係数を掛けたものを | |
// レイの現時点での位置で割ったものを利用する | |
// 計算結果のうち、もっとも小さいものを採用する | |
r = min(r, h * softShadow / c); | |
c += h; | |
} | |
return 1.0 - shadowCoef + (r * shadowCoef); | |
} | |
// なんちゃってAOを計算する | |
// | |
// +-----------------+--------------------+ | |
// | ro = Ray Origin | rd = Ray Direction | | |
// +-----------------+--------------------+ | |
vec4 genAmbientOcclusion(vec3 ro, vec3 rd) | |
{ | |
vec4 totao = vec4(0.0); | |
float sca = 1.0; | |
for (int aoi = 0; aoi < 5; aoi++) | |
{ | |
float hr = 0.01 + 0.02 * float(aoi * aoi); | |
vec3 aopos = ro + rd * hr; | |
float dd = distFunc(aopos); | |
float ao = clamp(-(dd - hr), 0.0, 1.0); | |
totao += ao * sca * vec4(1.0, 1.0, 1.0, 1.0); | |
sca *= 0.75; | |
} | |
const float aoCoef = 0.5; | |
totao.w = 1.0 - clamp(aoCoef * totao.w, 0.0, 1.0); | |
return totao; | |
} | |
void mainImage(out vec4 fragColor, in vec2 fragCoord) | |
{ | |
vec2 p = (fragCoord.xy * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y); | |
vec4 m = iMouse / iResolution.xxxx; | |
vec3 col = vec3(0.0); | |
vec3 cPos = cameraPos; | |
vec3 cDir = normalize(vec3(m.x, -m.y, -1.0)); | |
vec3 cSide = normalize(cross(cDir, vec3(0, 1, 0))); | |
vec3 cUp = normalize(cross(cSide, cDir)); | |
float targetDepth = 1.3; | |
vec3 ray = normalize(cSide * p.x + cUp * p.y + cDir * targetDepth); | |
float dist, depth; | |
depth = 0.0; | |
vec3 pos; | |
const int maxsteps = 128; | |
const float eps = 0.001; | |
for (int i = 0; i < maxsteps; i++) | |
{ | |
pos = cPos + ray * depth; | |
dist = distFunc(pos); | |
if (dist < eps) | |
{ | |
break; | |
} | |
depth += dist; | |
} | |
float shadow = 1.0; | |
if (dist < eps) | |
{ | |
vec3 n = getNormal(pos); | |
float diff = dot(n, lightDir); | |
shadow = genShadow(pos + n + 0.001, lightDir); | |
vec4 totao = genAmbientOcclusion(pos, n); | |
float u = 1.0 - floor(mod(pos.x, 2.0)); | |
float v = 1.0 - floor(mod(pos.z, 2.0)); | |
if ((u == 1.0 && v < 1.0) || (v == 1.0 && u < 1.0)) | |
{ | |
diff *= 0.7; | |
} | |
col = vec3(diff) + vec3(0.1); | |
col -= totao.xyz * totao.w; | |
} | |
fragColor = vec4(col, 1.0) * exp(-depth * 0.12); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ... 省略 | |
vec4 ao = genAmbientOcclusion(pos, n); | |
// ... 省略(なにがしかの色計算) | |
col -= ao.xyz * ao.w; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment