Skip to content

Commit

Permalink
fractional spp
Browse files Browse the repository at this point in the history
  • Loading branch information
harry7557558 committed Mar 10, 2024
1 parent bed81d7 commit e73cf58
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 36 deletions.
32 changes: 24 additions & 8 deletions implicit3-rt/frag-render.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ out vec4 fragColor;

uniform float iSeed;
uniform vec2 iResolution;
uniform float iNFrame;
uniform float iSpp;
uniform float sSamples;

uniform mat4 transformMatrix;
uniform float uScale;
Expand Down Expand Up @@ -523,6 +524,8 @@ float sampleHeight(float h, vec3 w) {
return 0.0;
}

#define RANDOM_WALK_DEPTH 8.0

vec3 ggxSampleNormal(float alpha) {
float r1 = randf(), r2 = randf();
float su = 2.0*PI*r2;
Expand Down Expand Up @@ -552,7 +555,7 @@ vec4 sampleBsdfConductor(Material m, vec3 wi) {
float h = 5.*STDEV;
float e = 1.;
vec3 w0, w = -wi;
for (int r = 0; r < 16; r++) {
for (float r = ZERO; r < RANDOM_WALK_DEPTH; r++) {
h = sampleHeight(h, w);
if(abs(h) > 5.*STDEV)
break;
Expand All @@ -569,7 +572,7 @@ float evalBsdfConductor(Material m, vec3 wi, vec3 wo) {
float e = 1.;
vec3 w = -wi;
float total = 0.0;
for (int r = 0; r < 16; r++) {
for (float r = ZERO; r < RANDOM_WALK_DEPTH; r++) {
h = sampleHeight(h, w);
if(abs(h) > 5.*STDEV)
break;
Expand Down Expand Up @@ -598,7 +601,7 @@ vec4 sampleBsdfDielectric(Material m, vec3 wi) {
float h = 5.*STDEV;
vec3 w = -wi;
float transmit = 1.0;
for (int r = 0; r < 16; r++) {
for (float r = ZERO; r < RANDOM_WALK_DEPTH; r++) {
h = sampleHeight(h, w*transmit);
if(abs(h) > 5.*STDEV)
break;
Expand All @@ -619,7 +622,7 @@ float evalBsdfDielectric(Material m, vec3 wi, vec3 wo) {
vec3 w = -wi;
float transmit = 1.0;
float total = 0.0;
for (int r = 0; r < 16; r++) {
for (float r = ZERO; r < RANDOM_WALK_DEPTH; r++) {
h = sampleHeight(h, w*transmit);
if(abs(h) > 5.*STDEV)
break;
Expand Down Expand Up @@ -1264,11 +1267,24 @@ void main(void) {

vec4 totcol = vec4(0);
totcol = texelFetch(accumBuffer, ivec2(gl_FragCoord.xy), 0);
for (float fi=ZERO; fi<iNFrame; fi++) {
for (float fi=ZERO; fi<sSamples; fi++) {
// random number seed
seed0 = hash13(vec3(gl_FragCoord.xy/iResolution.xy, sin(iSeed+fi/iNFrame)));
seed0 = hash13(vec3(gl_FragCoord.xy/iResolution.xy, sin(iSeed+fi/sSamples)));
seed = round(65537.*seed0);

// frame skipping
// to-do: some way without increasing variance
const float tile_size = 16.0;
vec2 tile_uv = mod(floor(gl_FragCoord.xy), tile_size);
vec2 tile_ij = floor(gl_FragCoord.xy/tile_size);
float tile_ij_hash = floor(hash13(vec3(tile_ij,tile_size))*tile_size*tile_size);
float tile_i = tile_uv.y*tile_size + tile_uv.x;
tile_i = mod(37.0*tile_i+tile_ij_hash, tile_size*tile_size);
float tile_f = tile_i / (tile_size*tile_size);
float tile_offset = mod(iSpp, 1.0);
if (mod(tile_f+tile_offset, 1.0) > sSamples)
continue;

vec2 ro_s = vXy;
ro_s += (-1.0+2.0*vec2(randf(), randf())) / iResolution.xy;
vec2 ro_sc = worldToScreen(vec3(0)).xy;
Expand All @@ -1293,7 +1309,7 @@ void main(void) {
float u = dot(col, ru), v = dot(col, rv), w = dot(col, rd);
totcol = vec4(u, v, w, u*u+v*v);
}
else totcol += vec4(col, 1) / iNFrame;
else totcol += vec4(col, 1) / sSamples;
}
}
fragColor = totcol;
Expand Down
17 changes: 13 additions & 4 deletions implicit3-rt/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<option value="0.004">high</option>
<option value="0.001">ultra high</option>
</select>precision</span>&ensp;
<span><select id="select-spp" title="Maximum samples per pixel">
<span title="Maximum samples per pixel"><select id="select-spp">
<option value="1">2⁰</option>
<option value="4"></option>
<option value="16">2⁴</option>
Expand All @@ -67,8 +67,8 @@
<option value="4096">2¹²</option>
<option value="16384">2¹⁴</option>
</select>spp</span>
<br />
<span><select id="select-light-path-depth" title="Maximum light path depth">
<br/>
<span title="Maximum light path depth"><select id="select-light-path-depth">
<option value="8">8</option>
<option value="16">16</option>
<option value="32">32</option>
Expand All @@ -78,7 +78,16 @@
<option value="512">512</option>
<option value="1024">1024</option>
</select>path depth</span>&ensp;
<span title="Enable experimental Multiple Importance Sampling (MIS) for high-variance scenes"><input type="checkbox"
<span title="Number of samples per frame per pixel"><select id="select-samples">
<option value="0.015625">2⁻⁶</option>
<option value="0.0625">2⁻⁴</option>
<option value="0.25">2⁻²</option>
<option value="1" selected>2⁰</option>
<option value="4"></option>
<option value="16">2⁴</option>
<option value="64">2⁶</option>
</select>samples</span>
<span style="display:none" title="Enable experimental Multiple Importance Sampling (MIS) for high-variance scenes"><input type="checkbox"
id="checkbox-mis" />MIS (beta)</span>&ensp;
<br />
<span title="Shape clipping boundary"><select id="select-clip">
Expand Down
3 changes: 3 additions & 0 deletions implicit3-rt/script.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 23 additions & 18 deletions scripts/render-rt.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ var renderer = {
denoiseTarget: null,
tonemapProgram: null,
tonemapTarget: null,
iNFrame: 1,
timerExt: null,
uOutput: 0,
requireAlbedo: false,
Expand All @@ -32,7 +31,7 @@ var trainingData = {
width: 256,
height: 256,
spp: 0,
iNFrame: 64,
sSamples: 64,
frames: [],
};

Expand Down Expand Up @@ -110,7 +109,8 @@ async function drawScene(state, transformMatrix, lightDir) {
gl.uniform2f(gl.getUniformLocation(renderer.renderProgram, "iResolution"),
state.width, state.height);
gl.uniform1i(gl.getUniformLocation(renderer.renderProgram, "uOutput"), renderer.uOutput);
gl.uniform1f(gl.getUniformLocation(renderer.renderProgram, "iNFrame"), renderer.iNFrame);
gl.uniform1f(gl.getUniformLocation(renderer.renderProgram, "iSpp"), state.iSpp);
gl.uniform1f(gl.getUniformLocation(renderer.renderProgram, "sSamples"), Number(state.sSamples));
gl.uniform1f(gl.getUniformLocation(renderer.renderProgram, "iSeed"), Math.random());
gl.uniformMatrix4fv(
gl.getUniformLocation(renderer.renderProgram, "transformMatrix"),
Expand Down Expand Up @@ -163,6 +163,8 @@ async function drawScene(state, transformMatrix, lightDir) {
gl.uniform1i(gl.getUniformLocation(renderer.postProgram, "iChannel1"), 1);
gl.uniform1i(gl.getUniformLocation(renderer.postProgram, "denoise"),
renderer.denoiser !== null);
gl.uniform1f(gl.getUniformLocation(renderer.postProgram, "iSpp"),
state.iSpp+state.sSamples);
renderPass();

// denoising
Expand Down Expand Up @@ -198,7 +200,7 @@ async function drawScene(state, transformMatrix, lightDir) {
for (var i = 0; i < timerQueries.length; i++)
gl.deleteQuery(timerQueries[i]);
fpsDisplay.innerHTML = state.iTime >= 0.0 ? state.iTime.toFixed(2) + " s" :
state.iFrame + " spp";
(Math.round(state.iSpp*100)/100) + " spp";
return;
}
if (timerQueries.length == 0) return;
Expand All @@ -220,7 +222,7 @@ async function drawScene(state, transformMatrix, lightDir) {
if (countIndividualTime) console.log(indivTime.join(' '));
fpsDisplay.innerHTML = (
state.iTime >= 0.0 ? state.iTime.toFixed(2) + " s - " :
(state.iFrame*renderer.iNFrame) + " spp - ") +
(Math.round(state.iSpp*100)/100) + " spp - ") +
(1000.0 / totTime).toFixed(1) + " fps";
}
setTimeout(checkTime, 100);
Expand All @@ -232,6 +234,8 @@ async function drawScene(state, transformMatrix, lightDir) {
var state = {
name: "",
iFrame: 0,
sSamples: 1,
iSpp: 0.0,
width: window.innerWidth,
height: window.innerHeight,
screenCenter: { x: 0.5, y: 0.5 },
Expand Down Expand Up @@ -395,8 +399,8 @@ function initRenderer() {
state.renderNeeded = true;
// if (state.renderNeeded)
if (state.renderNeeded && !trainingData.recording)
state.iFrame = 0;
if (state.iFrame < Number(state.sSpp)) {
state.iFrame = 0, state.iSpp = 0.0;
if (state.iSpp < Number(state.sSpp)) {
if (trainingData.recording) {
state.width = canvas.width = trainingData.width;
state.height = canvas.height = canvas.style.height = trainingData.height;
Expand Down Expand Up @@ -428,6 +432,7 @@ function initRenderer() {
state.iTime = -1.0;
}
state.iFrame += 1;
state.iSpp += Number(state.sSamples);
}
oldScreenCenter = screenCenter;
requestAnimationFrame(render);
Expand Down Expand Up @@ -611,15 +616,15 @@ function recordTrainingData(spp) {
trainingData.frames = [];
trainingData.spp = spp;
state.sSpp = trainingData.spp;
renderer.iNFrame = Math.min(state.sSpp, trainingData.iNFrame);
state.sSpp /= renderer.iNFrame;
state.iFrame = 0;
state.sSamples = Math.min(state.sSpp, trainingData.sSamples);
state.sSpp /= state.sSamples;
state.iFrame = 0, state.iSpp = 0.0;
trainingData.state = "wait";
setTimeout(recordTrainingData, 100);
}

else if (trainingData.state == "wait") {
if (state.iFrame * renderer.iNFrame < trainingData.spp) {
if (state.iSpp < trainingData.spp) {
setTimeout(recordTrainingData, 100);
return;
}
Expand Down Expand Up @@ -657,32 +662,32 @@ function recordTrainingData(spp) {
}
if (renderer.uOutput != 0) {
renderer.uOutput += 1;
state.iFrame = 0;
state.iFrame = 0, state.iSpp = 0.0;
setTimeout(recordTrainingData, 1);
return;
}
if (renderer.uOutput == 0 && trainingData.spp == 1) {
trainingData.spp = 1;
state.sSpp = 1;
renderer.iNFrame = 1;
state.sSamples = 1;
renderer.uOutput = 1;
state.iFrame = 0;
state.iFrame = 0, state.iSpp = 0.0;
setTimeout(recordTrainingData, 1);
return;
}
trainingData.spp /= 2;
state.sSpp = trainingData.spp;
renderer.iNFrame = Math.min(state.sSpp, trainingData.iNFrame);
state.sSpp /= renderer.iNFrame;
state.iFrame = 0;
state.sSamples = Math.min(state.sSpp, trainingData.sSamples);
state.sSpp /= state.sSamples;
state.iFrame = 0, state.iSpp = 0.0;
setTimeout(recordTrainingData, 1);
}

else if (trainingData.state == "finished") {
trainingData.recording = false;
trainingData.state = "unstarted";
updateBuffers();
renderer.iNFrame = 1;
state.sSamples = 1;
state.renderNeeded = true;

let n = trainingData.frames.length;
Expand Down
5 changes: 3 additions & 2 deletions shaders/frag-rt-post.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ uniform sampler2D iChannel1;
out vec4 fragColor;

uniform bool denoise;
uniform float iSpp;

void main(void) {
vec4 pixel0 = texelFetch(iChannel0, ivec2(gl_FragCoord.xy), 0);
vec4 pixel1 = texelFetch(iChannel1, ivec2(gl_FragCoord.xy), 0);
vec4 pixel = pixel0 + pixel1;
vec3 col = max(pixel.xyz/pixel.w, 0.0);
fragColor = denoise ?
vec4(log(pow(col, vec3(1.0/2.2))+1.0), 0.0) :
vec4(col, 1.0);
vec4(log(pow(col/min(iSpp,1.0), vec3(1.0/2.2))+1.0), 0.0) :
vec4(col, 1.0) * pixel.w;
}
23 changes: 19 additions & 4 deletions shaders/frag-tonemap.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,27 @@ vec3 tonemapUncharted2(vec3 x) {
}

void main(void) {
vec3 x = texelFetch(iChannel0, ivec2(gl_FragCoord.xy), 0).xyz;

x = tonemap{%TONEMAP%}(x);
vec4 x = vec4(0);
for (float s = 0.; s < 16.; s++) {
mat2 m = mat2(1);
for (float r = 0.; r < 4.; r++) {
for (float l = 0.; l < 2.*s; l++) {
vec2 p = gl_FragCoord.xy + m * vec2(s, s-l);
x = texelFetch(iChannel0, ivec2(p), 0);
if (x.w > 0.0) break;
}
if (x.w > 0.0) break;
m = mat2(1,1,-1,1) * m;
}
if (x.w > 0.0) break;
}
x /= x.w;

x.xyz = tonemap{%TONEMAP%}(x.xyz);

if (isnan(x.x+x.y+x.z))
x = vec3(1,0,0);
x.xyz = vec3(1,0,0);

fragColor = vec4(x,1);
fragColor = vec4(x.xyz,1);
}

0 comments on commit e73cf58

Please sign in to comment.