Skip to content

Commit

Permalink
Merge pull request #25 from YertleTurtleGit/nodes
Browse files Browse the repository at this point in the history
Nodes
  • Loading branch information
YertleTurtleGit authored Dec 29, 2021
2 parents 93ba728 + 1bbd5ec commit 16f13b2
Show file tree
Hide file tree
Showing 35 changed files with 2,832 additions and 2,063 deletions.
542 changes: 143 additions & 399 deletions index.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"compilerOptions": {
"target": "es2020",
"target": "es2021",
"checkJs": true
},
"ecmaFeatures": {
"modules": false,
"es2020": true
"es2021": true
}
}
50 changes: 50 additions & 0 deletions node-graphs/ambient-occlusion-and-roughness.ng.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* global NodeGraph, ambientOcclusionMap, roughnessMap */

const nodeGraph = new NodeGraph(document.getElementById("nodeGraphDiv"));

const ambientOcclusionMapNode = nodeGraph.registerNodeAsWorker(
ambientOcclusionMap,
"./src/glsl-shader.js",
"./src/ambient-occlusion-map.js"
);
const roughnessMapNode = nodeGraph.registerNodeAsWorker(
roughnessMap,
"./src/glsl-shader.js",
"./src/roughness-map.js"
);

const ambientOcclusionMapNodeA = nodeGraph.placeNode(ambientOcclusionMapNode, {
x: 800,
y: 100,
});
const roughnessMapNodeA = nodeGraph.placeNode(roughnessMapNode, {
x: 800,
y: 500,
});

const normalMapInputNode = nodeGraph.createInputNode("ImageBitmap", {
x: 200,
y: 100,
});
const depthMapInputNode = nodeGraph.createInputNode("ImageBitmap", {
x: 200,
y: 500,
});

nodeGraph.connect(
normalMapInputNode.getOutput(),
ambientOcclusionMapNodeA.getInput("normalMap")
);
nodeGraph.connect(
depthMapInputNode.getOutput(),
ambientOcclusionMapNodeA.getInput("depthMap")
);

nodeGraph.connect(
normalMapInputNode.getOutput(),
roughnessMapNodeA.getInput("normalMap")
);
nodeGraph.connect(
depthMapInputNode.getOutput(),
roughnessMapNodeA.getInput("depthMap")
);
198 changes: 198 additions & 0 deletions node-graphs/photometric-stereo.ng.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/* global NodeGraph, ambientOcclusionMap, roughnessMap, photometricStereoNormalMap, depthMap, albedoMap, PhotometricStereoRenderer */

async function main() {
const nodeGraph = new NodeGraph(document.getElementById("nodeGraphDiv"));

const albedoMapNode = nodeGraph.registerNodeAsWorker(
albedoMap,
"./src/glsl-shader.js",
"./src/albedo-map.js"
);
const normalMapNode = nodeGraph.registerNodeAsWorker(
photometricStereoNormalMap,
"./src/glsl-shader.js",
"./src/normal-map.js"
);
const depthMapNode = nodeGraph.registerNodeAsWorker(
depthMap,
"./src/glsl-shader.js",
"./src/depth-map.js"
);
const ambientOcclusionMapNode = nodeGraph.registerNodeAsWorker(
ambientOcclusionMap,
"./src/glsl-shader.js",
"./src/ambient-occlusion-map.js"
);
const roughnessMapNode = nodeGraph.registerNodeAsWorker(
roughnessMap,
"./src/glsl-shader.js",
"./src/roughness-map.js"
);

const albedoMapNodeA = nodeGraph.placeNode(albedoMapNode, {
x: 750,
y: 500,
});
const normalMapNodeA = nodeGraph.placeNode(normalMapNode, {
x: 750,
y: 150,
});
const depthMapNodeA = nodeGraph.placeNode(depthMapNode, { x: 1025, y: 600 });
const ambientOcclusionMapNodeA = nodeGraph.placeNode(
ambientOcclusionMapNode,
{
x: 1300,
y: 150,
}
);
const roughnessMapNodeA = nodeGraph.placeNode(roughnessMapNode, {
x: 1300,
y: 500,
});

const testImageUrls = [
"./../test-datasets/photometric-stereo/test_000_036.jpg",
"./../test-datasets/photometric-stereo/test_045_036.jpg",
"./../test-datasets/photometric-stereo/test_090_036.jpg",
"./../test-datasets/photometric-stereo/test_135_036.jpg",
"./../test-datasets/photometric-stereo/test_180_036.jpg",
"./../test-datasets/photometric-stereo/test_225_036.jpg",
"./../test-datasets/photometric-stereo/test_270_036.jpg",
"./../test-datasets/photometric-stereo/test_315_036.jpg",
];

/** @type {ImageBitmap[]} */
const testImages = [];

for (let i = 0; i < testImageUrls.length; i++) {
await new Promise((resolve) => {
const htmlImage = new Image();
htmlImage.addEventListener("load", async () => {
const imageBitmap = await createImageBitmap(htmlImage);
testImages.push(imageBitmap);
resolve();
});
htmlImage.src = testImageUrls[i];
});
}

const lightPolarAngleInputNode = nodeGraph.createInputNode(
"number",
{
x: 200,
y: 300,
},
45
);
const cameraDistanceInputNode = nodeGraph.createInputNode(
"number",
{
x: 200,
y: 500,
},
18
);
const lightDistanceInputNode = nodeGraph.createInputNode(
"number",
{
x: 200,
y: 600,
},
18
);
/*const lightImagesInputNode = nodeGraph.createInputNode("ImageBitmap[]", {
x: 200,
y: 400,
});*/

const uiCanvas = document.createElement("canvas");
uiCanvas.width = 250;
uiCanvas.height = 250;
uiCanvas.style.zIndex = "999";
document.body.appendChild(uiCanvas);

new PhotometricStereoRenderer(
uiCanvas,
"./test-datasets/models/mesh_plane.glb",
{
width: 250,
height: 250,
}
);
await PhotometricStereoRenderer.renderLightImages(45, 18, 18);

const lightImagesRenderNode = nodeGraph.registerNode(
PhotometricStereoRenderer.renderLightImages
);
const lightImagesRenderNodeA = nodeGraph.placeNode(lightImagesRenderNode, {
x: 450,
y: 400,
});

const qualityPercentInputNode = nodeGraph.createInputNode(
"number",
{
x: 750,
y: 800,
},
1
);

/*nodeGraph.connect(
lightImagesInputNode.getOutput(),
normalMapNodeA.getInput("lightImages")
);
nodeGraph.connect(
lightImagesInputNode.getOutput(),
albedoMapNodeA.getInput("lightImages")
);*/
nodeGraph.connect(
lightPolarAngleInputNode.getOutput(),
normalMapNodeA.getInput("lightPolarAngleDeg")
);
nodeGraph.connect(
lightPolarAngleInputNode.getOutput(),
lightImagesRenderNodeA.getInput("lightPolarAngleDeg")
);
nodeGraph.connect(
cameraDistanceInputNode.getOutput(),
lightImagesRenderNodeA.getInput("cameraDistance")
);
nodeGraph.connect(
lightDistanceInputNode.getOutput(),
lightImagesRenderNodeA.getInput("lightDistance")
);
nodeGraph.connect(
lightImagesRenderNodeA.getOutput(),
normalMapNodeA.getInput("lightImages")
);
nodeGraph.connect(
lightImagesRenderNodeA.getOutput(),
albedoMapNodeA.getInput("lightImages")
);
nodeGraph.connect(
normalMapNodeA.getOutput(),
depthMapNodeA.getInput("normalMap")
);
nodeGraph.connect(
qualityPercentInputNode.getOutput(),
depthMapNodeA.getInput("qualityPercent")
);
nodeGraph.connect(
normalMapNodeA.getOutput(),
ambientOcclusionMapNodeA.getInput("normalMap")
);
nodeGraph.connect(
depthMapNodeA.getOutput(),
ambientOcclusionMapNodeA.getInput("depthMap")
);
nodeGraph.connect(
normalMapNodeA.getOutput(),
roughnessMapNodeA.getInput("normalMap")
);
nodeGraph.connect(
depthMapNodeA.getOutput(),
roughnessMapNodeA.getInput("depthMap")
);
}
main();
31 changes: 31 additions & 0 deletions src/albedo-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* global GLSL */
/* exported albedoMap */

/**
* @public
* @param {ImageBitmap[]} lightImages
* @returns {Promise<ImageBitmap>}
*/
async function albedoMap(lightImages) {
const albedoShader = new GLSL.Shader({
width: lightImages[0].width,
height: lightImages[0].height,
});
albedoShader.bind();

/** @type {GLSL.Vector4[]} */
const glslLightImageColor = [];

lightImages.forEach((lightImage) => {
const glslLightImage = new GLSL.Image(lightImage);
glslLightImageColor.push(glslLightImage.getPixelColor());
});

const albedoColor = glslLightImageColor[0].maximum(...glslLightImageColor);

const albedoMap = GLSL.render(albedoColor).getImageBitmap();

albedoShader.purge();

return albedoMap;
}
95 changes: 95 additions & 0 deletions src/ambient-occlusion-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/* global GLSL */
/* exported ambientOcclusionMap */

/**
* @public
* @param {ImageBitmap} normalMap
* @param {ImageBitmap} depthMap
* @returns {Promise<ImageBitmap>}
*/
async function ambientOcclusionMap(normalMap, depthMap) {
const ambientOcclusionShader = new GLSL.Shader({
width: normalMap.width,
height: normalMap.height,
});
ambientOcclusionShader.bind();

const glslNormalMap = new GLSL.Image(normalMap);

const r = glslNormalMap.getNeighborPixel(1, 0).normalize();
const rb = glslNormalMap.getNeighborPixel(1, 1).normalize();
const b = glslNormalMap.getNeighborPixel(0, 1).normalize();
const lb = glslNormalMap.getNeighborPixel(-1, 1).normalize();
const l = glslNormalMap.getNeighborPixel(-1, 0).normalize();
const lt = glslNormalMap.getNeighborPixel(-1, -1).normalize();
const t = glslNormalMap.getNeighborPixel(0, -1).normalize();
const rt = glslNormalMap.getNeighborPixel(1, -1).normalize();

let normalMapOcclusion = new GLSL.Float(1);

normalMapOcclusion = normalMapOcclusion
.subtractFloat(r.dot(l).acos().abs())
.minimum(new GLSL.Float(1));
normalMapOcclusion = normalMapOcclusion
.subtractFloat(rb.dot(lt).acos().abs())
.minimum(new GLSL.Float(1));
normalMapOcclusion = normalMapOcclusion
.subtractFloat(b.dot(t).acos().abs())
.minimum(new GLSL.Float(1));
normalMapOcclusion = normalMapOcclusion
.subtractFloat(lb.dot(rt).acos().abs())
.minimum(new GLSL.Float(1));

const glslDepthMap = new GLSL.Image(depthMap);

const kernelPadding = 5;
const neighborhood = [];

for (let xOffset = 0; xOffset < kernelPadding + 1; xOffset++) {
for (let yOffset = 0; yOffset < kernelPadding + 1; yOffset++) {
neighborhood.push(
glslDepthMap.getNeighborPixel(xOffset, yOffset).channel(0)
);
}
}

const depth = glslDepthMap.getPixelColor().channel(0);
let depthMapOcclusion = new GLSL.Float(0);

neighborhood.forEach((neighbor) => {
const neighborOcclusion = neighbor
.subtractFloat(depth)
.addFloat(new GLSL.Float(1));
depthMapOcclusion = depthMapOcclusion.addFloat(neighborOcclusion);
});

depthMapOcclusion = depthMapOcclusion
.divideFloat(new GLSL.Float(neighborhood.length * 0.25))
.subtractFloat(new GLSL.Float(3.05));

let result = normalMapOcclusion
.addFloat(depthMapOcclusion)
.subtractFloat(new GLSL.Float(0.6));

const c = new GLSL.Float(0.5);

const ccf = new GLSL.Float(1)
.multiplyFloat(c.addFloat(new GLSL.Float(1)))
.divideFloat(new GLSL.Float(1))
.multiplyFloat(new GLSL.Float(1).subtractFloat(c));

result = ccf
.multiplyFloat(result.subtractFloat(new GLSL.Float(0.5)))
.addFloat(new GLSL.Float(0.5));

result = new GLSL.Float(1).subtractFloat(result);
result = result.multiplyFloat(new GLSL.Float(1.2));
result = new GLSL.Float(1).subtractFloat(result);

const ambientOcclusionMap = GLSL.render(
new GLSL.Vector4([result, result, result, new GLSL.Float(1)])
).getImageBitmap();

ambientOcclusionShader.purge();
return ambientOcclusionMap;
}
Loading

0 comments on commit 16f13b2

Please sign in to comment.