I used Hugo to create my blog website. To render 3D models in the pages generated by Hugo, I used three.js. To make it easy to use, I wrapped the code into a shortcode (saved as layouts\shortcodes\model3d.html).
The short code “model3d" has four parameters:
- src:GLTF model path
- ratio:Aspect ratio of the view port, default to 1.7778
- grid:Whether to show the grid or not, default to false
- back_light:Whether to add the back light, default to false
{{ $_hugo_config := `{ "version": 1 }` }}
{{ $modelPath := .Get "src" }}
{{ $aspectRatio := .Get "ratio" | default 1.7778 }}
{{ $withGrid := .Get "grid" | default false }}
{{ $withBackLight := .Get "back_light" | default false }}
<div id="container_model3d">
</div>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.161.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.161.0/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';
import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader'
import { RectAreaLightHelper } from 'three/addons/helpers/RectAreaLightHelper.js';
import { RectAreaLightUniformsLib } from 'three/addons/lights/RectAreaLightUniformsLib.js';
let camera, scene, renderer, containerParent;
init();
render();
function init() {
const container = document.getElementById('container_model3d');
container.onload = () => {
onWindowResize();
}
// Get aspect ratio of the canvas
const aspectRatio = {{ $aspectRatio }}
// Get path of the 3d model
const model_path = {{ $modelPath }};
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(container.clientWidth, container.clientWidth / aspectRatio);
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(45, aspectRatio, 2, 100);
camera.position.set(-4, 3, 6);
const environment = new RoomEnvironment(renderer);
const pmremGenerator = new THREE.PMREMGenerator(renderer);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xbbbbbb);
scene.environment = pmremGenerator.fromScene(environment).texture;
environment.dispose();
const withGrid = {{ $withGrid }};
if (withGrid) {
const grid = new THREE.GridHelper(10, 10, 0xffffff, 0xffffff);
grid.material.opacity = 0.4;
grid.material.depthWrite = false;
grid.material.transparent = true;
scene.add(grid);
}
const withBackLight = {{ $withBackLight }};
if (withBackLight) {
RectAreaLightUniformsLib.init();
const rectLight = new THREE.RectAreaLight(0xffffff, 25, 5, 5);
rectLight.position.set(-6, 6, -10);
rectLight.lookAt( 0, 0, 0 );
scene.add( rectLight );
scene.add( new RectAreaLightHelper( rectLight ) );
}
const ktx2Loader = new KTX2Loader()
.setTranscoderPath('https://unpkg.com/three@0.161.0/examples/jsm/libs/basis/')
.detectSupport(renderer);
const loader = new GLTFLoader();
loader.setKTX2Loader(ktx2Loader);
loader.setMeshoptDecoder(MeshoptDecoder);
loader.setDRACOLoader(DRACOLoader)
loader.load(model_path, function (gltf) {
gltf.scene.position.y = 0;
scene.add(gltf.scene);
render();
});
const controls = new OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', render); // use if there is no animation loop
controls.minDistance = 4;
controls.maxDistance = 15;
controls.target.set(0, 0, 0);
controls.update();
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
camera.aspect = aspectRatio;
camera.updateProjectionMatrix();
renderer.setSize(container.clientWidth, container.clientWidth / aspectRatio);
render();
}
function render() {
renderer.render(scene, camera);
}
</script>
Example to use the shortcode in the markdown file:
{{< model3d src="/path/to/model.glb" back_light="true" ratio="1.3333" grid="true" >}}
Just like the model in article Blender Exercises Set 7:
I will open source this shortcode in github after I test it.