Skip to content

Commit a5d41e9

Browse files
committed
refactoring renderer out into js file. switched to ortho camera, centering model, removing camera and light contols for now
1 parent e942547 commit a5d41e9

File tree

7 files changed

+487
-236
lines changed

7 files changed

+487
-236
lines changed

src/assets/scad.bloomRenderer.js

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import * as THREE from "three";
2+
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
3+
import { STLLoader } from "three/addons/loaders/STLLoader.js";
4+
import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
5+
import { RenderPass } from "three/addons/postprocessing/RenderPass.js";
6+
import { UnrealBloomPass } from "three/addons/postprocessing/UnrealBloomPass.js";
7+
import GUI from "https://cdn.jsdelivr.net/npm/lil-gui@0.21/+esm";
8+
9+
const loader = new STLLoader();
10+
const container = document.getElementById("viewer");
11+
const deg2rad = (degrees) => degrees * (Math.PI / 180);
12+
13+
let renderer, camera, scene, controls, spotLight;
14+
let composer, bloomPass;
15+
16+
function setupRenderer() {
17+
renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
18+
renderer.setSize(container.clientWidth, container.clientHeight);
19+
renderer.setClearColor(0xffffff, 0);
20+
21+
renderer.physicallyCorrectLights = true;
22+
renderer.outputColorSpace = THREE.SRGBColorSpace;
23+
renderer.toneMapping = THREE.ACESFilmicToneMapping;
24+
renderer.toneMappingExposure = 1.0;
25+
26+
container.appendChild(renderer.domElement);
27+
}
28+
29+
function setupCameraAndControls({ x, y, z }) {
30+
camera = new THREE.PerspectiveCamera(
31+
60,
32+
container.clientWidth / container.clientHeight,
33+
0.1,
34+
1000
35+
);
36+
camera.position.set(x, y, z);
37+
controls = new OrbitControls(camera, renderer.domElement);
38+
}
39+
40+
function setupScene({ x, y, z }) {
41+
scene = new THREE.Scene();
42+
43+
scene.add(new THREE.AmbientLight(0x888888));
44+
45+
spotLight = new THREE.DirectionalLight(0xffffff, 1);
46+
spotLight.position.set(x, y, z);
47+
scene.add(spotLight);
48+
}
49+
50+
function setupPostProcessing() {
51+
composer = new EffectComposer(renderer);
52+
53+
const renderPass = new RenderPass(scene, camera);
54+
composer.addPass(renderPass);
55+
56+
bloomPass = new UnrealBloomPass(
57+
new THREE.Vector2(container.clientWidth, container.clientHeight),
58+
1.2,
59+
0.4,
60+
0.85
61+
);
62+
63+
composer.addPass(bloomPass);
64+
}
65+
66+
function loadSTL(url) {
67+
const material = new THREE.MeshStandardMaterial({
68+
color: 0x5588ff,
69+
emissive: 0x3366ff,
70+
emissiveIntensity: 0.6,
71+
metalness: 0.3,
72+
roughness: 0.2
73+
});
74+
75+
loader.load(url, (geometry) => {
76+
const center = new THREE.Vector3();
77+
geometry.computeBoundingBox();
78+
geometry.boundingBox.getCenter(center).negate();
79+
geometry.translate(center.x, center.y, center.z);
80+
81+
const mesh = new THREE.Mesh(geometry, material);
82+
mesh.rotateX(deg2rad(-90));
83+
scene.add(mesh);
84+
});
85+
}
86+
87+
function setupResizeHandler() {
88+
window.addEventListener("resize", () => {
89+
const w = container.clientWidth;
90+
const h = container.clientHeight;
91+
92+
renderer.setSize(w, h);
93+
composer.setSize(w, h);
94+
95+
camera.aspect = w / h;
96+
camera.updateProjectionMatrix();
97+
});
98+
}
99+
100+
function animate() {
101+
requestAnimationFrame(animate);
102+
controls.update();
103+
composer.render();
104+
}
105+
106+
function setupGUI(state) {
107+
const gui = new GUI();
108+
109+
const light = gui.addFolder("Light");
110+
light.add(state.lightPos, "x", -500, 500).onChange(v => {
111+
spotLight.position.x = v;
112+
});
113+
light.add(state.lightPos, "y", -500, 500).onChange(v => {
114+
spotLight.position.y = v;
115+
});
116+
light.add(state.lightPos, "z", -500, 500).onChange(v => {
117+
spotLight.position.z = v;
118+
});
119+
120+
const bloom = gui.addFolder("Bloom");
121+
bloom.add(bloomPass, "strength", 0, 3, 0.01);
122+
bloom.add(bloomPass, "radius", 0, 1, 0.01);
123+
bloom.add(bloomPass, "threshold", 0, 1, 0.01);
124+
}
125+
126+
function init() {
127+
const initialState = {
128+
lightPos: { x: 20, y: 50, z: 200 },
129+
cameraPos: { x: 45, y: 45, z: 45 }
130+
};
131+
132+
setupRenderer();
133+
setupScene(initialState.lightPos);
134+
setupCameraAndControls(initialState.cameraPos);
135+
setupPostProcessing();
136+
setupGUI(initialState);
137+
loadSTL(window.STL_URL);
138+
setupResizeHandler();
139+
animate();
140+
}
141+
142+
init();

src/assets/scad.collection.njk

Lines changed: 67 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,80 @@
11
<!doctype html>
2-
<html lang="fr">
3-
<head>
4-
<title>{{ title }}</title>
5-
{% w3_theme theme %}
6-
<style>
7-
.cards {
8-
display: grid;
9-
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
10-
gap: 1em;
11-
padding: 1em 0;
12-
}
2+
<html lang="en">
3+
<head>
4+
<title>{{ title }}</title>
5+
<meta charset="UTF-8"/>
6+
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
7+
{% w3_theme theme %}
8+
<style>
9+
.cards {
10+
display: grid;
11+
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
12+
gap: 1em;
13+
padding: 1em 0;
14+
}
1315
14-
.card {
15-
display: flex;
16-
flex-direction: column;
17-
gap: 0.75em;
18-
padding: 0.5em 1em 1em;
19-
border: 1px solid #ccc;
20-
border-radius: 8px;
21-
backdrop-filter: blur(16px) saturate(180%);
22-
-webkit-backdrop-filter: blur(16px) saturate(180%);
23-
}
16+
.card {
17+
display: flex;
18+
flex-direction: column;
19+
gap: 0.75em;
20+
padding: 0.5em 1em 1em;
21+
border: 1px solid #ccc;
22+
border-radius: 8px;
23+
backdrop-filter: blur(16px) saturate(180%);
24+
-webkit-backdrop-filter: blur(16px) saturate(180%);
25+
}
2426
25-
.card a {
26-
background: inherit;
27-
}
27+
.card a {
28+
background: inherit;
29+
}
2830
29-
.card img {
30-
width: 100%;
31-
height: auto;
32-
border-radius: 4px;
33-
}
31+
.card img {
32+
width: 100%;
33+
height: auto;
34+
border-radius: 4px;
35+
}
3436
35-
.card-title {
36-
font-weight: bold;
37-
font-size: 1.1em;
38-
text-decoration: none;
39-
display: block;
40-
}
37+
.card-title {
38+
font-weight: bold;
39+
font-size: 1.1em;
40+
text-decoration: none;
41+
display: block;
42+
}
4143
42-
.card-footer {
43-
margin-top: auto;
44-
font-size: 0.9em;
45-
opacity: 0.7;
46-
}
44+
.card-footer {
45+
margin-top: auto;
46+
font-size: 0.9em;
47+
opacity: 0.7;
48+
}
4749
48-
.block {
49-
display: block;
50-
}
51-
</style>
52-
</head>
50+
.block {
51+
display: block;
52+
}
53+
</style>
54+
</head>
5355

54-
<body>
55-
<header>
56-
<h1>{{ title }}</h1>
57-
</header>
56+
<body>
57+
<header>
58+
<h1>{{ title }}</h1>
59+
</header>
5860

59-
<section class="cards">
60-
{% for item in collections.scad %}
61-
{% set thumb = [item.data.page.url, item.data.page.fileSlug, ".png"] | join %}
62-
<a href="{{ item.data.page.url | url }}" class="card-title">
63-
<div class="card">
64-
<span>
65-
{{ item.data.title }}
66-
</span>
67-
<img
61+
<section class="cards">
62+
{% for item in collections.scad %}
63+
{% set thumb = [item.data.page.url, item.data.page.fileSlug, ".png"] | join %}
64+
<a href="{{ item.data.page.url | url }}" class="card-title">
65+
<div class="card">
66+
<span>
67+
{{ item.data.title }}
68+
</span>
69+
<img
6870
src="{{ thumb | url }}"
6971
title="Thumbnail image of {{ item.data.page.fileSlug }}.scad"/>
70-
{# <span class="card-footer block">📁 {{ item.data.page.url }}</span> #}
71-
</div>
72-
</a>
73-
{% endfor %}
74-
</section>
72+
{# <span class="card-footer block">📁 {{ item.data.page.url }}</span> #}
73+
</div>
74+
</a>
75+
{% endfor %}
76+
</section>
7577

76-
<footer>{{ content | safe }}</footer>
77-
</body>
78+
<footer>{{ content | safe }}</footer>
79+
</body>
7880
</html>

0 commit comments

Comments
 (0)