mirror of
https://github.com/TomHodson/tomhodson.github.com.git
synced 2025-06-26 10:01:18 +02:00
Update model renderer
This commit is contained in:
parent
41d622805a
commit
a692d07ed1
@ -15,7 +15,7 @@ model: /assets/projects/bathroom_shelf/models/ikea.glb
|
||||
---
|
||||
{% include mastodon_post.html post_id = "111822564173512216" %}
|
||||
|
||||
<outline-model-viewer model = "/assets/projects/bathroom_shelf/models/ikea.glb">
|
||||
<outline-model-viewer model = "/assets/projects/bathroom_shelf/models/ikea.glb" camera='{"position":[-10.52,2.5,2.313],"rotation":[-0.8243,-1.258,-0.7995],"zoom":436.67440926643843,"target":[0,0,0]}'>
|
||||
<img class="outline-model-poster no-wc" src = "/assets/projects/bike_lights/thumbnail.svg">
|
||||
<p class="has-wc">Loading model...</p>
|
||||
</outline-model-viewer>
|
||||
|
@ -17,7 +17,7 @@ model: /assets/projects/ceramics/scan.glb
|
||||
<p class="has-wc">Loading model...</p>
|
||||
</outline-model-viewer> -->
|
||||
|
||||
<outline-model-viewer model = "/assets/projects/ceramics/scan_2.glb" materials=keep outlines=false camera='{"position":[-5.155,2.5,-9.456],"rotation":[-2.883,-0.4851,-3.019],"zoom":268,"target":[0,0,0]}'>
|
||||
<outline-model-viewer model = "/assets/projects/ceramics/scan_2.glb" materials=keep mode=1 camera='{"position":[-5.155,2.5,-9.456],"rotation":[-2.883,-0.4851,-3.019],"zoom":268,"target":[0,0,0]}' ambient-light="6" directional-light="0.8">
|
||||
<img class="outline-model-poster no-wc" src = "{{page.img.src}}">
|
||||
<p class="has-wc">Loading model...</p>
|
||||
</outline-model-viewer>
|
@ -1,9 +1,7 @@
|
||||
import * as THREE from "three";
|
||||
import { Pass } from "three/addons/postprocessing/Pass.js";
|
||||
import { FullScreenQuad } from "three/addons/postprocessing/Pass.js";
|
||||
import {
|
||||
getSurfaceIdMaterial,
|
||||
} from "./FindSurfaces.js";
|
||||
import { getSurfaceIdMaterial } from "./FindSurfaces.js";
|
||||
|
||||
// Follows the structure of
|
||||
// https://github.com/mrdoob/three.js/blob/master/examples/jsm/postprocessing/OutlinePass.js
|
||||
@ -19,8 +17,7 @@ class CustomOutlinePass extends Pass {
|
||||
this.fsQuad = new FullScreenQuad(null);
|
||||
this.fsQuad.material = this.createOutlinePostProcessMaterial();
|
||||
|
||||
// Create a buffer to store the normals of the scene onto
|
||||
// or store the "surface IDs"
|
||||
// Create a buffer to surface ids
|
||||
const surfaceBuffer = new THREE.WebGLRenderTarget(
|
||||
this.resolution.x,
|
||||
this.resolution.y
|
||||
@ -117,7 +114,7 @@ class CustomOutlinePass extends Pass {
|
||||
uniform float cameraFar;
|
||||
uniform vec4 screenSize;
|
||||
uniform vec3 outlineColor;
|
||||
uniform vec2 multiplierParameters;
|
||||
uniform vec3 multiplierParameters;
|
||||
uniform int debugVisualize;
|
||||
|
||||
varying vec2 vUv;
|
||||
@ -152,19 +149,36 @@ class CustomOutlinePass extends Pass {
|
||||
return clamp(num, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float getSufaceIdDiff(vec3 surfaceValue) {
|
||||
float surfaceIdDiff = 0.0;
|
||||
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(1, 0));
|
||||
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(0, 1));
|
||||
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(0, 1));
|
||||
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(0, -1));
|
||||
|
||||
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(1, 1));
|
||||
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(1, -1));
|
||||
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(-1, 1));
|
||||
surfaceIdDiff += distance(surfaceValue, getSurfaceValue(-1, -1));
|
||||
return surfaceIdDiff;
|
||||
}
|
||||
float getSurfaceIdDiff(vec3 surfaceValue) {
|
||||
float surfaceIdDiff = 0.0;
|
||||
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(1, 0))) ? 1.0 : 0.0;
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(0, 1))) ? 1.0 : 0.0;
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(-1, 0))) ? 1.0 : 0.0;
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(0, -1))) ? 1.0 : 0.0;
|
||||
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(1, 1))) ? 1.0 : 0.0;
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(1, -1))) ? 1.0 : 0.0;
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(-1, 1))) ? 1.0 : 0.0;
|
||||
surfaceIdDiff += any(notEqual(surfaceValue, getSurfaceValue(-1, -1))) ? 1.0 : 0.0;
|
||||
|
||||
return surfaceIdDiff;
|
||||
}
|
||||
|
||||
float getDepthDiff(float depth) {
|
||||
float depthDiff = 0.0;
|
||||
depthDiff += abs(depth - getPixelDepth(1, 0));
|
||||
depthDiff += abs(depth - getPixelDepth(-1, 0));
|
||||
depthDiff += abs(depth - getPixelDepth(0, 1));
|
||||
depthDiff += abs(depth - getPixelDepth(0, -1));
|
||||
|
||||
depthDiff += abs(depth - getPixelDepth(1, 1));
|
||||
depthDiff += abs(depth - getPixelDepth(1, -1));
|
||||
depthDiff += abs(depth - getPixelDepth(-1, 1));
|
||||
depthDiff += abs(depth - getPixelDepth(-1, -1));
|
||||
return depthDiff;
|
||||
}
|
||||
|
||||
|
||||
const uint k = 1103515245U; // GLIB C
|
||||
@ -184,34 +198,44 @@ class CustomOutlinePass extends Pass {
|
||||
vec3 surfaceValue = getSurfaceValue(0, 0);
|
||||
|
||||
// Get the difference between depth of neighboring pixels and current.
|
||||
float depthDiff = 0.0;
|
||||
depthDiff += abs(depth - getPixelDepth(1, 0));
|
||||
depthDiff += abs(depth - getPixelDepth(-1, 0));
|
||||
depthDiff += abs(depth - getPixelDepth(0, 1));
|
||||
depthDiff += abs(depth - getPixelDepth(0, -1));
|
||||
float depthDiff = getDepthDiff(depth);
|
||||
|
||||
// Get the difference between surface values of neighboring pixels
|
||||
// and current
|
||||
float surfaceValueDiff = getSufaceIdDiff(surfaceValue);
|
||||
float surfaceValueDiff = getSurfaceIdDiff(surfaceValue);
|
||||
|
||||
// Apply multiplier & bias to each
|
||||
float depthBias = multiplierParameters.x;
|
||||
float depthMultiplier = multiplierParameters.y;
|
||||
float lerp = multiplierParameters.z;
|
||||
|
||||
depthDiff = depthDiff * depthMultiplier;
|
||||
depthDiff = saturateValue(depthDiff);
|
||||
depthDiff = saturateValue(depthDiff * depthMultiplier);
|
||||
depthDiff = pow(depthDiff, depthBias);
|
||||
|
||||
if (debugVisualize == 7) {
|
||||
// Surface ID difference
|
||||
gl_FragColor = vec4(vec3(surfaceValueDiff), 1.0);
|
||||
}
|
||||
|
||||
if (surfaceValueDiff != 0.0) surfaceValueDiff = 1.0;
|
||||
|
||||
float outline = saturateValue(surfaceValueDiff + depthDiff);
|
||||
float outline;
|
||||
vec4 outlineColor = vec4(outlineColor, 1.0);;
|
||||
|
||||
// Combine outline with scene color.
|
||||
vec4 outlineColor = vec4(outlineColor, 1.0);
|
||||
gl_FragColor = vec4(mix(sceneColor, outlineColor, outline));
|
||||
// Normal mode, use the surface ids to draw outlines and add the shaded scene in too
|
||||
if (debugVisualize == 0) {
|
||||
outline = saturateValue(surfaceValueDiff);
|
||||
gl_FragColor = vec4(mix(sceneColor, outlineColor, outline));
|
||||
}
|
||||
|
||||
//// For debug visualization of the different inputs to this shader.
|
||||
if (debugVisualize == 2) {
|
||||
// Depth mode, use the depth to draw outlines only at the outside
|
||||
if (debugVisualize == 1) {
|
||||
outline = saturateValue(depthDiff);
|
||||
gl_FragColor = vec4(mix(sceneColor, outlineColor, outline));
|
||||
}
|
||||
|
||||
//Scene color no outline
|
||||
if (debugVisualize == 2) {
|
||||
gl_FragColor = sceneColor;
|
||||
}
|
||||
if (debugVisualize == 3) {
|
||||
@ -223,8 +247,14 @@ class CustomOutlinePass extends Pass {
|
||||
}
|
||||
if (debugVisualize == 5) {
|
||||
// Outlines only
|
||||
outline = mix(surfaceValueDiff, depthDiff, lerp);
|
||||
outline = saturateValue(outline);
|
||||
gl_FragColor = mix(vec4(0,0,0,0), outlineColor, outline);
|
||||
}
|
||||
if (debugVisualize == 6) {
|
||||
// Depth difference
|
||||
gl_FragColor = vec4(vec3(depthDiff), 1.0);
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
@ -237,10 +267,8 @@ class CustomOutlinePass extends Pass {
|
||||
depthBuffer: {},
|
||||
surfaceBuffer: {},
|
||||
outlineColor: { value: new THREE.Color(this.outlineColor) },
|
||||
//4 scalar values packed in one uniform:
|
||||
// depth multiplier, depth bias
|
||||
multiplierParameters: {
|
||||
value: new THREE.Vector2(0.9, 20),
|
||||
value: new THREE.Vector3(0.9, 20, 0.5),
|
||||
},
|
||||
cameraNear: { value: this.renderCamera.near },
|
||||
cameraFar: { value: this.renderCamera.far },
|
||||
|
@ -12,6 +12,7 @@ class FindSurfaces {
|
||||
constructor() {
|
||||
// This identifier, must be globally unique for each surface
|
||||
// across all geometry rendered on screen
|
||||
// reserve 10 special ids for various purposes
|
||||
this.surfaceId = 10;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,6 @@ export class OutlineModelViewer extends HTMLElement {
|
||||
const canvas = this.shadow.querySelector("canvas");
|
||||
|
||||
let canvas_rect = canvas.getBoundingClientRect();
|
||||
console.log(canvas_rect);
|
||||
|
||||
// determine the outline and bg colors
|
||||
const body = document.getElementsByTagName("body")[0];
|
||||
@ -138,11 +137,18 @@ export class OutlineModelViewer extends HTMLElement {
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.setSize(canvas_rect.width, canvas_rect.height, false);
|
||||
|
||||
const light = new THREE.DirectionalLight(0xffffff, 2);
|
||||
scene.add(light);
|
||||
light.position.set(1.7, 1, -1);
|
||||
const directionalLight = new THREE.DirectionalLight(
|
||||
0xffffff,
|
||||
this.getAttribute("directional-light") || 2
|
||||
);
|
||||
scene.add(directionalLight);
|
||||
directionalLight.position.set(1.7, 1, -1);
|
||||
|
||||
scene.add(new THREE.AmbientLight(0xffffff, 5));
|
||||
const ambientLight = new THREE.AmbientLight(
|
||||
0xffffff,
|
||||
this.getAttribute("ambient-light") || 0.5
|
||||
);
|
||||
scene.add(ambientLight);
|
||||
|
||||
// Set up post processing
|
||||
// Create a render target that holds a depthTexture so we can use it in the outline pass
|
||||
@ -180,6 +186,7 @@ export class OutlineModelViewer extends HTMLElement {
|
||||
composer.addPass(effectFXAA);
|
||||
|
||||
const surfaceFinder = new FindSurfaces();
|
||||
|
||||
// Load model
|
||||
const loader = new GLTFLoader();
|
||||
const dracoLoader = new DRACOLoader();
|
||||
@ -189,7 +196,6 @@ export class OutlineModelViewer extends HTMLElement {
|
||||
|
||||
loader.load(model_path, (gltf) => {
|
||||
scene.add(gltf.scene);
|
||||
surfaceFinder.surfaceId = 0;
|
||||
|
||||
// Compute bounding box
|
||||
let box = new THREE.Box3().setFromObject(gltf.scene);
|
||||
@ -212,6 +218,7 @@ export class OutlineModelViewer extends HTMLElement {
|
||||
if (node.type == "Mesh") {
|
||||
// Add surface ID attribute to the geometry
|
||||
const colorsTypedArray = surfaceFinder.getSurfaceIdAttribute(node);
|
||||
node.surfaceId = colorsTypedArray;
|
||||
node.geometry.setAttribute(
|
||||
"color",
|
||||
new THREE.BufferAttribute(colorsTypedArray, 4)
|
||||
@ -293,7 +300,9 @@ export class OutlineModelViewer extends HTMLElement {
|
||||
);
|
||||
}
|
||||
|
||||
shadow.querySelector("#clicked-item").innerText = object.name;
|
||||
shadow.querySelector(
|
||||
"#clicked-item"
|
||||
).innerText = `${object.name} - ${object.type}`;
|
||||
}
|
||||
} else if (this.intersectedObject) {
|
||||
this.intersectedObject = null;
|
||||
@ -359,22 +368,23 @@ export class OutlineModelViewer extends HTMLElement {
|
||||
injectStyles: false,
|
||||
closeFolders: true,
|
||||
});
|
||||
gui.close();
|
||||
|
||||
if ((this.getAttribute("model") || "closed") === "closed") gui.close();
|
||||
|
||||
const uniforms = customOutline.fsQuad.material.uniforms;
|
||||
uniforms.debugVisualize.value =
|
||||
this.getAttribute("outlines") === "false" ? 2 : 0;
|
||||
uniforms.debugVisualize.value = parseInt(this.getAttribute("mode")) || 0;
|
||||
|
||||
const params = {
|
||||
selectedObject: "None",
|
||||
spin: controls.autoRotate,
|
||||
mode: uniforms.debugVisualize.value,
|
||||
// depthBias: uniforms.multiplierParameters.value.x,
|
||||
// depthMult: uniforms.multiplierParameters.value.y,
|
||||
ambientLight: parseFloat(ambientLight.intensity),
|
||||
directionalLight: parseFloat(directionalLight.intensity),
|
||||
mode: { Mode: uniforms.debugVisualize.value },
|
||||
depthBias: uniforms.multiplierParameters.value.x,
|
||||
depthMult: uniforms.multiplierParameters.value.y,
|
||||
lerp: uniforms.multiplierParameters.value.z,
|
||||
printCamera: () => console.log(serialiseCamera(camera, controls)),
|
||||
};
|
||||
|
||||
gui.add(params, "selectedObject").listen();
|
||||
gui.add(params, "spin").onChange((value) => {
|
||||
controls.autoRotate = value;
|
||||
});
|
||||
@ -383,21 +393,34 @@ export class OutlineModelViewer extends HTMLElement {
|
||||
gui
|
||||
.add(params.mode, "Mode", {
|
||||
"Outlines + Shaded (default)": 0,
|
||||
"Only outer outlines + shading": 1,
|
||||
Shaded: 2,
|
||||
"Depth buffer": 3,
|
||||
"SurfaceID buffer": 4,
|
||||
Outlines: 5,
|
||||
"Depth Difference": 6,
|
||||
"SurfaceID Difference": 7,
|
||||
})
|
||||
.onChange(function (value) {
|
||||
uniforms.debugVisualize.value = value;
|
||||
});
|
||||
|
||||
// gui.add(params, "depthBias", 0.0, 5).onChange(function (value) {
|
||||
// uniforms.multiplierParameters.value.x = value;
|
||||
// });
|
||||
// gui.add(params, "depthMult", 0.0, 20).onChange(function (value) {
|
||||
// uniforms.multiplierParameters.value.y = value;
|
||||
// });
|
||||
gui.add(params, "ambientLight", 0.0, 10.0).onChange(function (value) {
|
||||
ambientLight.intensity = value;
|
||||
});
|
||||
gui.add(params, "directionalLight", 0.0, 10.0).onChange(function (value) {
|
||||
directionalLight.intensity = value;
|
||||
});
|
||||
|
||||
gui.add(params, "depthBias", 0.0, 5).onChange(function (value) {
|
||||
uniforms.multiplierParameters.value.x = value;
|
||||
});
|
||||
gui.add(params, "depthMult", 0.0, 40.0).onChange(function (value) {
|
||||
uniforms.multiplierParameters.value.y = value;
|
||||
});
|
||||
gui.add(params, "lerp", 0.0, 1.0).onChange(function (value) {
|
||||
uniforms.multiplierParameters.value.z = value;
|
||||
});
|
||||
|
||||
// Toggle fullscreen mode
|
||||
const shadow = this.shadow;
|
||||
|
Loading…
x
Reference in New Issue
Block a user