Preview
precision highp float;
uniform vec2 resolution;
uniform vec2 mouse;
uniform float time;
uniform sampler2D backbuffer;
out vec4 outColor;
#define FC gl_FragCoord
#define o outColor
// vðPI/4.¾¯ñ]
#define rotpi4(v) (vec2((v).x + (v).y, -(v).x + (v).y) / sqrt(2.))
// IuWFNgÌíÞ
#define FLOOR 1
#define WALL 2
#define CEILING 3
#define SYOBON 4
// ÇÌzui}bvjÍAÎpüÌTruchet tilesðx[XƵĢé
// ·×ÄÌÇÌ@üxNgÍ(}1, 0, }1)ÌSíÞ
// ¦~j}bvÍ45X¢Ä¨èAÎßEºªx²Ì³ûüAÎ߶ºªz²Ì³ûüÆÈÁÄ¢é
// Çi^CjÌíÞ
// l÷ÌÝ
#define FOURCORNERS 11.0
// l÷ÆÎpü(½Êx=z)
#define DIAGPLUS 12.0
// l÷ÆÎpü(½Êx=-z)
#define DIAGMINUS 13.0
//---------------GPU×Ìèvö--------------------------
const int numSamples = 50; // pXg[VOÌTv
//----------------------------------------------------------
const int maxDepth = 3; // CÌoHÌ[³ÌÅåli½Ëñ+1Ìlj
const float sceneTime1 = 5.; // æÊmCYÌI¹Ô
const float sceneTime2 = 8.; // Ob`ÌI¹Ô
const float sceneTime3 = 10.; // HUDÌJnÔ
const float sceneTime4 = 11.; // ^C}[AvC[iJjÌÚ®ÌJnÔ
const float sceneTime5 = 14.; // V{ÌÇÕÌJnÔ
const float PI = acos(-1.); // ~ü¦
const float PI2 = acos(-1.) * 2.;
const float EPS = 0.0001; // Cg[XÈÇÉg¤÷¬Ê
const float FOV = 60. / 360. * PI; // ìp(WA) ÍÍF(0./360.*PI, 180./360.*PI)
const float wallRate = 0.7; // ÇÌ@ÍÍF[0., 1.]
const float wallWidth = 0.1; // ÇÌú³@ÍÍF(0., 0.5)
const float mapSeed = 5.; // }bv¶¬Ég¤ÌV[h
const float ceilHeight = 0.5; // Vä̳
const float damageRate = 0.01; // 1t[ ½èÌ_[WÊ
const float enemySize = 0.2; // V{iGjÌ嫳i
̼aj
vec3 enemyPos; // V{ÌÊu
float enemyDirA; // V{Ìü«(WA)
float pathSeed = 0.; // pXg[VOÅg¤ÌV[h
// 1DÌ
float hash11(float p)
{
return fract(sin(p) * 43758.5453);
}
// 2DÌ
float hash12(vec2 p)
{
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
}
// 1DÌ(V[hðXV)
float random() {
return hash11(pathSeed++);
}
// 2³Ìñ]sñ
mat2 rotate2D(float a) {
float s = sin(a), c = cos(a);
return mat2(c, s, -s, c);
}
const float segScale = 0.03; // ZOgÌ嫳
// ÌZOgÌ£Ö
float sdSeg(vec2 p) {
p = abs(p);
return max(p.x - segScale / 3., p.x + p.y - segScale);
}
// "0"Ì£Ö
float sd0(vec2 p) {
p = abs(p);
p.y -= segScale;
p = p.y > p.x ? p.yx : p;
p.x -= segScale;
return sdSeg(p);
}
// "1"Ì£Ö
float sd1(vec2 p) {
p.y = abs(p.y);
p -= segScale;
return sdSeg(p);
}
// "2"Ì£Ö
float sd2(vec2 p) {
p = p.y < 0. ? -p : p;
p.y = abs(p.y - segScale);
p = p.y > p.x ? p.yx : p;
p.x -= segScale;
return sdSeg(p);
}
// "3"Ì£Ö
float sd3(vec2 p) {
p.y = abs(abs(p.y) - segScale);
p = p.y > p.x ? p.yx : p;
p.x -= segScale;
return sdSeg(p);
}
// "4"Ì£Ö
float sd4(vec2 p) {
float d = sdSeg(p - vec2(-segScale, segScale));
p.y = abs(p.y) - segScale;
p = p.y < -p.x ? -p.yx : p;
p.x -= segScale;
return min(d, sdSeg(p));
}
// "5"Ì£Ö
float sd5(vec2 p) {
p = p.y < 0. ? -p : p;
p.y = abs(p.y - segScale);
p = p.y > -p.x ? -p.yx : p;
p.x += segScale;
return sdSeg(p);
}
// "6"Ì£Ö
float sd6(vec2 p) {
float d = sdSeg(p - vec2(segScale, -segScale));
p.y = abs(abs(p.y) - segScale);
p = p.y > -p.x ? -p.yx : p;
p.x += segScale;
return min(d, sdSeg(p));
}
// "7"Ì£Ö
float sd7(vec2 p) {
float d = sdSeg(p - vec2(segScale, -segScale));
p.y -= segScale;
p = p.y > p.x ? p.yx : p;
p.x -= segScale;
return min(d, sdSeg(p));
}
// "8"Ì£Ö
float sd8(vec2 p) {
p = abs(p);
p.y = abs(p.y - segScale);
p = p.y > p.x ? p.yx : p;
p.x -= segScale;
return sdSeg(p);
}
// "9"Ì£Ö
float sd9(vec2 p) {
float d = sdSeg(p - vec2(-segScale, segScale));
p.y = abs(abs(p.y) - segScale);
p = p.y > p.x ? p.yx : p;
p.x -= segScale;
return min(d, sdSeg(p));
}
// Ni0`9jÌ£Ö
float sdDigit(vec2 p, int N) {
if(N == 0) return sd0(p);
if(N == 1) return sd1(p);
if(N == 2) return sd2(p);
if(N == 3) return sd3(p);
if(N == 4) return sd4(p);
if(N == 5) return sd5(p);
if(N == 6) return sd6(p);
if(N == 7) return sd7(p);
if(N == 8) return sd8(p);
if(N == 9) return sd9(p);
return 1e5;
}
// ^C}[ÌF
vec3 colTimer(vec3 col, vec2 uv, vec2 pos, float size, float Time) {
uv -= pos;
uv /= size;
vec2 uvp = uv;
uv.x -= uv.y * 0.2;
float segGap = 0.002;
float interval = 0.09;
float interval2 = interval * 1.3;
float ra = 0.01;
float hundredths = fract(Time) * 100.;
float seconds = mod(Time, 60.);
float minutes = mod(Time / 60., 60.);
float hours = mod(Time / 3600., 100.);
int digit1 = int(mod(hundredths, 10.));
int digit2 = int(hundredths / 10.);
int digit3 = int(mod(seconds, 10.));
int digit4 = int(seconds / 10.);
int digit5 = int(mod(minutes, 10.));
int digit6 = int(minutes / 10.);
int digit7 = int(mod(hours, 10.));
int digit8 = int(hours / 10.);
float d = length(uvp - vec2(-0.159, -0.06)) - ra; // sIh
uvp -= vec2(-interval * 5.1, 0);
uvp.x -= sign(uvp.y) * 0.007;
uvp = abs(uvp) - vec2(interval * 1.15, 0.035);
d = min(d, length(uvp) - ra); // R
vec2 uv12 = (uv - vec2(-0.036, -0.021)) * 1.5;
d = min(d, sdDigit(uv12, digit1));
uv.x += interval;
uv12.x += interval;
d = min(d, sdDigit(uv12, digit2));
uv.x += interval2;
d = min(d, sdDigit(uv, digit3));
uv.x += interval;
d = min(d, sdDigit(uv, digit4));
uv.x += interval2;
d = min(d, sdDigit(uv, digit5));
uv.x += interval;
d = min(d, sdDigit(uv, digit6));
uv.x += interval2;
d = min(d, sdDigit(uv, digit7));
uv.x += interval;
d = min(d, sdDigit(uv, digit8));
col = mix(vec3(0.2), col, smoothstep(0.009, 0.0091, d + segGap)); // g
col += smoothstep(0.001, 0., d + segGap);
return col;
}
const float serifThin = 4.; // ¶ÌZtÌ׳
// ¶ÌZtÌ£Ö
float sdSerif(vec2 p, vec2 pos, float width, float height) {
p -= pos;
p.x = abs(p.x);
float d = p.x - exp(-p.y * p.y * serifThin) - width;
d = max(d, -p.y);
return max(d, p.y - height);
}
// "Y"Ì£Ö
float sdCY(vec2 p) {
float d = sdSerif(p, vec2(0, -5.), 0.7, 4.5);
p.y = -p.y;
vec2 q = p;
q.x += q.y * 0.6 - 0.8;
d = min(d, sdSerif(q, vec2(0, -5.), 0.45, 6.));
q = p;
q.x -= q.y * 0.6 - 0.5;
return min(d, sdSerif(q, vec2(0, -5.), 0.7, 5.8));
}
// "O"Ì£Ö
float sdCO(vec2 p) {
p.x *= 1.1;
float d = length(p) - 5.;
p.x *= 1.4;
return max(d, 4.5 - length(p));
}
// "U"Ì£Ö
float sdCU(vec2 p) {
vec2 q = p;
q.y += 2.2;
q.y *= 1.2;
float r1 = 3.7;
float r2 = 2.6;
float of = 0.25;
q.y -= max(q.y, 0.);
float d = length(q) - r1;
q.x -= of;
d = max(d, r2 - length(q));
d = max(d, p.y - 5.);
q = p;
q.y = 5. - q.y;
float temp = of - r2;
d = min(d, sdSerif(q, vec2((temp - r1) * 0.5, 0), (temp + r1) * 0.5, 3.));
temp = of + r2;
return min(d, sdSerif(q, vec2((r1 + temp) * 0.5, 0), (r1 - temp) * 0.5, 3.));
}
// "D"Ì£Ö
float sdCD(vec2 p) {
p.y = abs(p.y);
vec2 q = p;
q.x -= min(q.x, 0.2);
float d = length(q) - 5.;
d = max(d, -p.x - 2.5);
q = p;
q.x += 1.;
d = max(d, 4.5 - length(q));
q.y = 5. - q.y;
return min(d, sdSerif(q, vec2(-1.7, 0), 0.7, 6.));
}
// "I"Ì£Ö
float sdCI(vec2 p) {
p.y = 5. - abs(p.y);
return sdSerif(p, vec2(0, 0), 0.7, 6.);
}
// "E"Ì£Ö
float sdCE(vec2 p) {
vec2 q = vec2(p.y, -p.x);
float d = sdSerif(q, vec2(0.5, -4.), 0.42, 6.);
q = p;
q.y = 5. - abs(q.y);
d = min(d, sdSerif(q, vec2(-1.5, 0), 0.7, 6.));
q = vec2(p.y - 5., 4.5 - p.x);
q.y -= q.x *.1;
d = min(d, sdSerif(q, vec2(0, 0), 0.7, 6.));
q = vec2(p.y + 5., 4.5 - p.x);
q.y += q.x *.3;
d = min(d, sdSerif(q, vec2(0, 0), 0.7, 6.));
return max(d, abs(p.y) - 5.);
}
// SÌbZ[WÌF
vec3 colDeathMsg(vec3 col, vec2 uv, vec2 pos, float size) {
uv -= pos;
uv /= size * 0.05;
uv.x += 30.;
float d = sdCY(uv); // Y
uv.x -= 10.;
d = min(d, sdCO(uv)); // O
uv.x -= 10.5;
d = min(d, sdCU(uv)); // U
uv.x -= 14.5;
d = min(d, sdCD(uv)); // D
uv.x -= 8.5;
d = min(d, sdCI(uv)); // I
uv.x -= 6.5;
d = min(d, sdCE(uv)); // E
uv.x -= 11.;
d = min(d, sdCD(uv)); // D
col *= mix(0.2, 1., smoothstep(5., 14., abs(uv.y)));
col = mix(vec3(0.7,0.,0.) + col, col, smoothstep(0., 0.01, d));
return col;
}
// ÇÌíÞ
vec2 wallType(vec2 ID) {
float hash = hash12(ID + mapSeed * PI);
if(hash > wallRate) {
return vec2(FOURCORNERS, 1.);
}
if(hash > wallRate * 0.5) {
return vec2(DIAGPLUS, 1.);
}
return vec2(DIAGMINUS, -1.);
}
// ÇÌ£Öi2³j
// ÎpüÌTruchet tilesðx[XƵĢé
float sdWall(vec2 p) {
vec2 ID = floor(p);
vec2 q = fract(p) - 0.5;
vec2 wType = wallType(ID);
q.y *= wType.y;
if(wType.x != FOURCORNERS) {
// DIAGMINUS or DIAGPLUS
return (0.5 - wallWidth - abs(fract(q.y - q.x) - 0.5)) / sqrt(2.);
}
// FOURCORNERS
q = abs(q);
return (1. - q.x - q.y - wallWidth) / sqrt(2.);
}
// ÇÌ@üxNgi2³j
vec2 wallNormal(vec2 p) {
vec2 e = vec2(0, 0.1);
return normalize(vec2(sdWall(p + e.yx) - sdWall(p - e.yx),
sdWall(p + e.xy) - sdWall(p - e.xy)));
}
// æÊãÌ~j}bvÌF
vec3 colMiniMap(vec3 col, vec2 uv, vec2 pos, float size, vec2 ro, float dirA) {
uv -= pos;
uv /= size;
float L = length(uv);
float R = 0.4;
col = mix(vec3(0.5), col, smoothstep(0., 0.02, abs(L - R))); // Û¢g
if(L < R) {
vec3 mapCol = vec3(0.7, 0.7, 0.9);
uv.y = -uv.y;
uv = rotpi4(uv); // PI/4.¾¯ñ]
uv *= 15.;
col = mix(vec3(1.), col * mapCol, smoothstep(0., 0.01, sdWall(uv + ro))); // Ç
col = mix(vec3(1, 1, 0), col, smoothstep(0.2, 0.25, length(uv))); // vC[
vec2 q = uv * rotate2D(dirA);
float width = 0.02;
float a = abs(atan(q.y, q.x));
if(a < FOV + width && col.x < 0.99) {
float cFOV = smoothstep(1., 6., length(q)) * smoothstep(0., width, abs(a - FOV));
col = mix(vec3(0.6, 0.6, 0), col, cFOV); // E
}
}
return col;
}
// HPo[ÌF
vec3 colHPBar(vec3 col, vec2 uv, vec2 pos, vec2 size, float HP) {
uv -= pos;
vec2 uvb = uv;
uv = abs(uv) - size;
uvb /= size * 2.;
uvb += 0.5;
float d = max(uv.x, uv.y);
if(d < 0.) {
col = mix(vec3(0), col, 0.4);
if(uvb.x < HP) {
col = vec3(1, .0, .0);
col += uvb.y * 1.5 - 0.75;
}
}
col = mix(vec3(0.8), col, smoothstep(0., 0.01, abs(d))); // g
return col;
}
// HUDÌF
vec3 colHUD(vec3 col, vec2 uv, vec2 ro, float dirA, float HP) {
col = colMiniMap(col, uv, vec2(0.8, -0.55), 1., ro, dirA); // ~j}bvð\¦
col = colHPBar(col, uv, vec2(0, 0.85), vec2(0.8, 0.05), HP); // HPo[ð\¦
float Time = max(time - sceneTime4, 0.);
col = colTimer(col, uv, vec2(1.18, -0.03), 1., Time); // ^C}[ð\¦
if(HP >= damageRate) { // ¶«Ä¢éÔÍSÌbZ[Wð\¦µÈ¢
return col;
}
return colDeathMsg(col, uv, vec2(0, 0.4), 0.6); // SÌbZ[Wð\¦
}
// ¨ÌÌ\ÊãÌÀWrpɨ¯é@üxNg
vec3 objNormal(vec3 rp, out int objType) {
vec3 n = vec3(0, 1, 0);
if(rp.y > ceilHeight - EPS) {
objType = CEILING;
return vec3(0, -1, 0);
}
if(rp.y < EPS) {
objType = FLOOR;
return vec3(0, 1, 0);
}
vec3 ep = rp - enemyPos;
if(dot(ep, ep) < (enemySize + EPS) * (enemySize + EPS)) {
objType = SYOBON;
return ep / enemySize; //
ÌÈÌżaÅéÆ@üxNgÉÈé
}
vec2 frp = fract(rp.xz) - 0.5;
vec2 ID = floor(rp.xz);
vec2 wType = wallType(ID);
objType = WALL;
n.y = 0.;
n.xz = -sign(frp) / sqrt(2.);
if(wType.x == FOURCORNERS) {
return n;
}
// DIAGMINUS or DIAGPLUS
float temp = frp.y - wType.y * frp.x;
float signNormal = sign(temp);
n.xz = (abs(temp) < wallWidth + EPS) ? vec2(-wType.y * signNormal, signNormal) / sqrt(2.) : n.xz;
return n;
}
// CÆ
Ì\ÊÌð·»èÖ
// ref: sphIntersect() by iq
// https://iquilezles.org/articles/intersectors/
float sphIntersect(vec3 ro, vec3 rd, vec3 ce, float ra) {
vec3 oc = ro - ce;
float e = dot(oc, rd);
float c = dot(oc, oc) - ra * ra;
float h = e * e - c;
if(h < 0.) return -1.0;
return -e - sqrt(h);
}
// G~bVÌF
vec3 emission(vec3 rp, int objType, out float ceilPattern) {
if(objType != CEILING) { // õ¹ÍVäÌÝ
return vec3(0);
}
// õ¹Ì^CÌ[ðÇÉí¹é
vec2 uv = rp.xz;
uv /= wallWidth * sqrt(2.);
uv = rotpi4(uv);
uv -= 0.5;
float hash = hash12(floor(uv));
uv = abs(fract(uv) - 0.5);
ceilPattern = smoothstep(0.5, 0.43, max(uv.x, uv.y));
if(fract(hash + time * 0.05) < 0.05) { // _Å
return vec3(ceilPattern * 10.);
}
return vec3(0);
}
// V{ÌÚÌ£Ö
float sdSyobonEye(vec2 p, vec2 pos, float radius) {
p.x = abs(p.x);
return length(p - pos) - radius;
}
// V{ÌûÑÌ£Ö
float sdSyobonEyebrow(vec2 p, vec2 pos, float L, float angle) {
p.x = abs(p.x);
p -= pos;
p *= rotate2D(angle);
p.x -= clamp(p.x, -L, L);
return length(p);
}
// V{ÌûÌ£Ö
// reference: "Arc - exact" by iq
// https://iquilezles.org/articles/distfunctions2d/
float sdSyobonMouth(vec2 p, float posY, float radius) {
p.x = abs(p.x);
p.y -= posY;
p *= rotate2D(0.5);
float a = 1.1;
float s = sin(a);
float c = cos(a);
vec2 cp = vec2(s, c) * radius;
p -= vec2(cp.x, -cp.y);
p.x = abs(p.x);
if(p.y * s > p.x * c) {
return length(p - cp);
}
return abs(length(p) - radius);
}
// V{ÌçÌ£Ö
float sdSyobon(vec2 p) {
float d;
d = sdSyobonEye(p, vec2(0.5, 0), 0.06);
d = min(d, sdSyobonEyebrow(p, vec2(0.8, 0.3), 0.13, -0.5));
return min(d, sdSyobonMouth(p, -0.3, 0.1));
}
// ¨ÌÌF
vec3 objColor(vec3 rp, int objType, float ceilPattern) {
if(objType == FLOOR) { // °
return vec3(0.7, 0.4, 0.2);
}
if(objType == CEILING) { // Vä
return vec3(mix(0.5, 1.0, ceilPattern));
}
if(objType == WALL) { // Ç
if(abs(rp.y - ceilHeight * 0.5) > ceilHeight * 0.47) {
return vec3(1.0);
}
rp.x = abs(fract(rp.x / wallWidth * 5. - 0.5) - 0.5); // cÌÈÍlÉ·é
return mix(vec3(0.95), vec3(0.1, 0.6, 0.3), smoothstep(0., 0.2, rp.x));
}
vec3 p = rp - enemyPos;
if(objType == SYOBON) { // V{
p.xz *= rotate2D(enemyDirA);
if(p.x < 0.) {
return vec3(1);
}
vec2 uv = p.zy;
uv *= 1.3 / enemySize;
float d = sdSyobon(uv);
return vec3(smoothstep(0.05, 0.1, d));
}
return vec3(0);
}
// vðV¸ÆµÄÉÀWphi, theta¾¯ñ]³¹½xNg
// ¦øvÍ·³1ÌxNgÅ éKv è
vec3 jitter(vec3 v, float phi, float sinTheta, float cosTheta) {
vec3 xAxis = normalize(cross(v.yzx, v));
vec3 yAxis = cross(v, xAxis);
vec3 zAxis = v;
return (xAxis * cos(phi) + yAxis * sin(phi)) * sinTheta + zAxis * cosTheta;
}
// ro©ç¨Ì\ÊÜÅòε½CÌ·³
// 2DÌVoxel Traversalðx[XƵĢé
float castRay(vec3 ro, vec3 rd, const int itr) {
float t = 0.; // CÌ·³
vec2 ri = 1.0 / rd.xz;
vec2 rs = sign(rd.xz);
// Çð³µ½CÌ·³
float tLimit = (rd.y > 0.) ? (ceilHeight - ro.y) : -ro.y;
tLimit = (rd.y == 0.) ? 1e5 : tLimit / rd.y; // VäܽͰÜÅÌCÌ·³
// V{ÜÅÌCÌ·³
float tEnemy = sphIntersect(ro, rd, enemyPos, enemySize);
tLimit = (tEnemy > 0.) ? min(tLimit, tEnemy) : tLimit; // CªV{ÉÕ˵½çtLimitðXV
vec2 ID = floor(ro.xz); // ZÌIDiCÌÀWÌ®ªj
for(int i = 0; i < itr; i++) {
vec2 rp = ro.xz + rd.xz * t; // CÌæ[ÌÀW
vec2 wType = wallType(ID); // ÇÌíÞ
vec2 frp = rp - ID - 0.5; // CÌæ[ÌÀW̬ª-0.5
float tWall = 1e5; // ÌÇÜÅÌCÌ·³
vec2 v = (0.5 * rs - frp) * ri; // ÌZÌ«EÜÅÌCÌ·³(XûüÆZûü)
vec2 vCell = vec2(step(v.x, v.y), step(v.y, v.x)); // XûüÆZûṳ̈¿AÇ¿çÌZÉiÞ©
float tCell = dot(v, vCell); // ÌZÌ«EÜÅÌCÌ·³iv.x or v.yj
vec2 normal = -sign(frp + tCell * rd.xz); // ·³ðvZ®É½fÏÝ̽ßnormalize()Ísv
float tWallFourCorners = (wallWidth - 1. - dot(frp, normal)) / dot(rd.xz, normal); // l÷ÌÇÜÅÌCÌ·³
tWall = (tWallFourCorners > 0.) ? tWallFourCorners : tWall; // tWallðXV·é
float signNormal = sign(frp.y - wType.y * frp.x);
normal = vec2(-wType.y * signNormal, signNormal); // ·³ðvZ®É½fÏÝ̽ßnormalize()Ísv
float tWallDiag = (wallWidth - dot(frp, normal)) / dot(rd.xz, normal); // ÎpüÌÇÜÅÌCÌ·³
tWall = (tWallDiag > 0. && wType.x != FOURCORNERS) ? min(tWall, tWallDiag) : tWall; // ÇÌíÞªÎpÌêÍtWallðXV·é
if(tWall < tCell) { // ÌZÌ«EæèàAÇÌûªß¢
return min(t + tWall, tLimit);
}
// ÌZÌ«EÉiÞ
t += tCell;
ID += vCell * rs;
if(t >= tLimit) { // ÌZÌ«EæèàAVä or ° or V{Ìûªß¢
return tLimit;
}
}
return -1.0;
}
// ref: "pXg[VO - Computer Graphics - memoRANDOM" by Shocker_0x15
// (Japanese article)
// https://rayspace.xyz/CG/contents/path_tracing/
// ref: "GLSL smallpt" by Zavie
// https://www.shadertoy.com/view/4sfGDB
// ¦QlÉ͵ĢéªR[hÍåÉÙÈé
// pXg[VOžçêéF
vec3 pathTrace(vec3 ro, vec3 rd) {
vec3 acc = vec3(0);
vec3 mask = vec3(1);
// ÅÉJ©çCðòη
float t = castRay(ro, rd, 20);
if(t < 0.) { // Cª¨ÌÉÕ˵ȩÁ½
return vec3(0.1, 0.6, 0.3) * 0.1;
}
ro += t * rd; // CÌ´_ð¨Ì\ÊÜÅißé
int objType;
float ceilPattern;
vec3 n = objNormal(ro, objType);
// ¦{ÍTv̪¾¯J©çCðòη½ßAnumSamplesð©¯é
acc += mask * emission(ro, objType, ceilPattern) * float(numSamples);
mask *= objColor(ro, objType, ceilPattern);
// ÉA¨Ì\Ê©ç_ÉCðòη
vec3 ro0 = ro + n * EPS;
vec3 n0 = n;
vec3 mask0 = mask;
for(int i = 0; i < numSamples; i++) {
ro = ro0;
n = n0;
mask = mask0;
for(int depth = 1; depth < maxDepth; depth++) {
float ur = random(); // êl
// d_ITvOðs¤½ßA¼
Êàcosªzðgp·é
rd = jitter(n, random() * PI2, sqrt(1. - ur), sqrt(ur)); // ÌCÌûü
t = castRay(ro, rd, 4);
if(t < 0.) { // Cª¨ÌÉÕ˵ȩÁ½
break;
}
ro += t * rd;
n = objNormal(ro, objType);
acc += mask * emission(ro, objType, ceilPattern);
mask *= objColor(ro, objType, ceilPattern);
ro += n * EPS; // »Ý̨Ì\Êðð¯é½ßÉAµ©¹é
}
}
acc /= float(numSamples);
acc = clamp(acc, 0., 1.);
return acc;
}
// JÌÊuÆü«ðú»EXV·é
void doCamera(in vec2 uv, out vec3 ro, out float dirA, out vec3 dir, out vec3 rd) {
// JÌÀWðú»
ro = vec3(wallWidth + 0.2, ceilHeight * 0.5, 0.);
// JÌü«ðú»
dir.y = 0.;
dirA = 0.;
dir.xz = vec2(cos(dirA), sin(dirA));
if(time > sceneTime4) {
// JÌü«ð}EXÅϦé
dir.y = (mouse.y - 0.5) * 2.;
dirA = mouse.x * PI2 * 4.;
dir.xz = vec2(cos(dirA), sin(dirA));
dir = normalize(dir);
// Ot[ÌJÌÊuðæ¾
ro.xz = texture(backbuffer, vec2(0.5, 0.5) / resolution).rg;
// JðÚ®³¹é
vec2 v = dir.xz;
vec2 n = wallNormal(ro.xz);
float d = sdWall(ro.xz);
if(d < 0.) { // ÇÉÜÁÄ¢éÌÅ@üûüÉiñŲ¯o·
v = n;
} else if(d < 0.15 && dot(v, n) < 0.) { // ÇÉߢêAÇƽsɵ©ißÈ¢æ¤É·é
vec2 nv = vec2(n.y, -n.x);
v = nv * dot(nv, v);
}
ro.xz += v * 0.01;
ro.y += abs(sin(fract(time * 4.) * PI) * 0.01); // vC[ªÁÄ¢éæ¤ÉAJðãºÉhç·
}
// æÊÌuvÀWÆJÌü«©çCxNgðßé
vec3 side = normalize(cross(dir, vec3(0, 1, 0)));
vec3 up = cross(side, dir);
rd = normalize(vec3(uv.x * side + uv.y * up + dir / tan(FOV)));
}
// V{ÌÊuÆü«ðú»EXV·é
void doEnemy() {
enemyPos.y = abs(sin(time * 3.)) * 0.1 + enemySize; // °ÌãŵËé
enemyPos.xz = vec2(1e5);
enemyDirA = 0.;
if(time > sceneTime5) { // vC[ðÇÕ
vec3 texE = texture(backbuffer, vec2(200.5, 0.5) / resolution).rgb; // vC[ÌßÌÊuEü«ðæ¾
enemyPos.xz = texE.rg;
enemyDirA = texE.b;
}
}
// uvð¸çµÄOb`
vec2 glitch(vec2 uv, float rate) {
float T = fract(time / 10.) * 10.;
float vx = hash12(vec2(floor(uv.y * 20.), T));
float vy = hash12(vec2(floor(uv.y * 20.), T + 500.));
float v = floor(hash12(vec2(floor(uv.y * 6. - T * 3.))) * 6.) - 2.5;
vec2 shift = vec2(vx, vy) * v / 2.5;
uv -= shift * rate;
return uv;
}
void main(){
vec2 uv = (FC.xy * 2. - resolution) / min(resolution.x, resolution.y); // ÀW̳K»
// HPª0ÉÈÁ½çæÊðâ~µÄASÄÌðI¹·é
float HP = 1.; // HPðú»
if(time > sceneTime5) {
//HP = texture2D(backbuffer, vec2(0.5, 1.5) / resolution).a;
HP = texture(backbuffer, (resolution / 2. + 0.5) / resolution).a;
if(HP < damageRate) {
outColor = texture(backbuffer, FC.xy / resolution);
return;
}
}
float T = fract(time / 10.) * 500.;
// ÅÌÔÍæÊÉmCYð\¦·é
if(time + hash11(T) * 2.5 < sceneTime1) {
vec2 i = floor(uv * 100.);
i += hash12(i) * 500.;
o = vec4(vec3(hash12(i + T)), 1.);
return;
}
// Ob`ÌGtFNgð©¯é
uv = glitch(uv, smoothstep(sceneTime2 + EPS, sceneTime1, time));
vec3 ro; // JÌÊuiCÌ´_j
vec3 rd; // CÌü«
vec3 dir; // JÌü«
float dirA; // JÌü«iXZ½ÊàÅÌpxiWAjj
doCamera(uv, ro, dirA, dir, rd); // JÌÊuEü«ðú»EXV·é
doEnemy(); // V{ÌÊuEü«ðú»EXV·é
// pXg[VOÅg¤ÌV[hðú»·é
pathSeed = hash12(FC.xy * PI) * 500.;
pathSeed += hash12(FC.xy + pathSeed + T) * 500.;
// pXg[VOð·é
vec3 col = vec3(0);
col = pathTrace(ro, rd);
col = pow(col, vec3(1. / 2.2)); // K}â³
// pXg[VOžçê½F̪Uðḷé½ßÉOÌt[ÌFð¬·é
float tex = 0.7;
col *= 1. - tex;
col += texture(backbuffer, FC.xy / resolution).rgb * tex;
// _[WÌ
if(time > sceneTime5) {
// GÉÚß·éÆ_[Wðó¯é
if(length(enemyPos - ro) < enemySize + 0.2) {
HP = max(HP - damageRate, 0.); // HP¸
col = mix(col, vec3(1, 0, 0), 0.15); // _[WGtFNg
}
}
// HUDð\¦
if(time > sceneTime3) {
col = colHUD(col, uv, ro.xz, dirA, HP);
}
col = clamp(col, 0., 1.);
o.rgb = col;
// vC[iJjÌÊuEü«EHPðÛ¶
if(FC.y < 0.6) {
if(FC.x < 0.6) {
o.rgb = vec3(ro.xz, dirA); // vC[ÌÊuÆü«ðÛ¶
} else {
// vC[ÌßÌóÔðV{ÌóÔƵÄg¤½ßA¸çµÄßÌóÔðÛ·é
o.rgb = texture(backbuffer, vec2(FC.x - 1., 0.5) / resolution).rgb;
}
}
//if(FC.x < 0.6 && FC.y > 0.6 && FC.y < 1.6) {
o.a = HP; // HPðÛ¶
//}
}