<script language="javascript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.js"></script>
body {margin:0px; padding:0px; overflow: hidden}
let roughness = 0.0;
function setup() {
createCanvas(windowWidth, windowHeight);
}
function draw() {
const SampleNum = 128;
background(235, 255, 160);
const radius = min(width, height) * 0.4;
const cx = width / 2;
const cy = height / 2;
let nSamples = 0;
noStroke();
fill(0);
for (let i = 0; i < SampleNum; i++) {
const Xi = Hammersley(i, SampleNum);
const N = createVector(0, 0, 1);
const sampleVec = ImportanceSampleGGX(Xi, N, roughness);
circle(sampleVec.x * radius + cx, cy - sampleVec.y * radius, 2);
nSamples ++;
}
drawLabel(8, 32, "Roughness " + roughness.toFixed(3), LEFT);
drawLabel(8, 56, "Number of samples " + nSamples, LEFT);
roughness += 0.001;
if (roughness > 1.0) {roughness = 0;}
}
function ImportanceSampleGGX(Xi, N, roughness)
{
const a = roughness*roughness;
const phi = 2.0 * PI * Xi[0];
const cosTheta = sqrt((1.0 - Xi[1]) / (1.0 + (a*a - 1.0) * Xi[1]));
const sinTheta = sqrt(1.0 - cosTheta*cosTheta);
// from spherical coordinates to cartesian coordinates
const H = createVector();
H.x = cos(phi) * sinTheta;
H.y = sin(phi) * sinTheta;
H.z = cosTheta;
// from tangent-space vector to world-space sample vector
const up = abs(N.z) < 0.999 ? createVector(0.0, 0.0, 1.0) : createVector(1.0, 0.0, 0.0);
const tangent = up.copy().cross(N).normalize();//normalize(cross(up, N));
const bitangent = N.copy().cross(tangent);//cross(N, tangent);
const v0 = p5.Vector.mult(tangent, H.x);
const v1 = p5.Vector.mult(bitangent, H.y);
const v2 = p5.Vector.mult(N, H.z);
const sampleVec = p5.Vector.add(v0, p5.Vector.add(v1, v2));
return sampleVec;
}
function VanDerCorput(n, base)
{
let invBase = 1.0 / base;
let denom = 1.0;
let result = 0.0;
for (let i = 0; i < 32; ++i)
{
if (n > 0)
{
denom = float(n) % 2.0;
result += denom * invBase;
invBase = invBase / 2.0;
n = floor(n / 2.0);
}
}
return result;
}
function Hammersley(i, N) {
return [i / N, VanDerCorput(i, 2)];
}
function drawLabel(x, y, label, align = CENTER) {
push();
strokeWeight(0);
textFont("monospace");
textSize(14);
textAlign(align);
if (align == LEFT) {x += 6;}
if (align == RIGHT) {x -= 6;}
text(label, x, y);
pop();
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.