Hey Everyone!
I create my material before running render, but for some reason I can’t update it in the render function directly, the userData.shader
is undefined at first render call, and I need to use an if statement to avoid this issue.
import * as THREE from "three";
import * as dat from "dat.gui";
import Stats from 'three/examples/jsm/libs/stats.module.js'
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
const sizes = {
width: window.innerWidth,
height: window.innerHeight
};
const vertShaderSource = document.getElementById("vertexshader").textContent;
const fragShaderSource = document.getElementById("fragmentshader").textContent;
class App {
constructor() {
this.width = sizes.width;
this.height = sizes.height;
this.container = document.getElementById("app");
this.scene = new THREE.Scene();
this.renderer = new THREE.WebGLRenderer();
this.container.appendChild(this.renderer.domElement);
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
this.renderer.setClearAlpha(0xeeeeee, 1);
this.renderer.setSize(this.width, this.height);
this.stats = Stats()
document.body.appendChild(this.stats.dom)
this.camera = new THREE.PerspectiveCamera(
70,
this.width / this.height,
0.01,
1000
);
this.camera.position.set(0, 0, 2);
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.debug = true;
this.time = 0;
this.clock = new THREE.Clock();
this.init();
}
init() {
this.addObjects();
this.addLights();
this.resize();
this.render();
this.setupResize();
this.setDebug();
}
setupResize() {
window.addEventListener("resize", this.resize.bind(this));
}
resize() {
this.width = this.container.offsetWidth;
this.height = this.container.offsetHeight;
this.renderer.setSize(this.width, this.height);
this.camera.aspect = this.width / this.height;
this.camera.updateProjectionMatrix();
}
addObjects() {
const that = this
this.material = new THREE.MeshStandardMaterial({
onBeforeCompile:(shader) => {
console.log("onBeforeCompile triggered");
shader.uniforms.time = { value: 0 };
that.material.userData.shader = shader;
console.log(this.material); // This should now log properly
},
// side: THREE.DoubleSide,
// uniforms: {
// time: { value: 0 },
// resolution: { value: new THREE.Vector4() },
// progress: { value: 0 }
// },
// vertexShader: vertShaderSource,
// fragmentShader: fragShaderSource,
wireframe: true
});
this.geometry = new THREE.PlaneGeometry(1, 1, 10, 10);
this.plane = new THREE.Mesh(this.geometry, this.material);
this.scene.add(this.plane);
}
addLights() {
const light1 = new THREE.AmbientLight(0xffffff, 0.5);
const light2 = new THREE.DirectionalLight(0xffffff, 0.5);
light2.position.set(0.5, 0, 0.866); // ~60º
this.scene.add(light1);
this.scene.add(light2);
}
render() {
// console.log(this.material.userData);
this.time = this.clock.getDelta();
//if(this.material.userData.shader){
this.material.userData.shader.uniforms.time.value += this.time;
// }
this.renderer.render(this.scene, this.camera);
this.stats.update();
window.requestAnimationFrame(this.render.bind(this));
}
setDebug() {
if (this.debug) {
this.debug = new dat.GUI({ width: 420 });
const main = this.debug.addFolder("main");
main.add(this.material.userData.shader.uniforms.progress, "value", 0, 1);
}
}
}
new App();