Closed slackermorris closed 1 year ago
In adding support for ThreeJS I also realise that it would make sense to review the best practices associated with Astro
.
This is precisely what I want to do for the landing page.
I'm going to have to properly extract this somehow. And I should reach out to Ksenia and thank them.
I would really like to make use of this animated SVG logo as well:
And this font:
And emojis:
DON'T FORGET ABOUT PARTYTOWN.
I should probably read this before sinking my teeth in too much:
This would be good to read, it is a comparison between the different frameworks:
SOME CONFUSION ABOUT BUNDLERS
I am really fucking confused.
Astro
offers support for Vite
plugins to manage advanced configuration options that Astro
currently does not support: https://docs.astro.build/en/reference/configuration-reference/#vite.
Astro
uses Turbo
under the hood: a webpack
successor.
Vite
uses Rollup
as its bundler under the hood. Vite
is part bundler part dev server.
So, why are we using Vite
instead of just grabbing Rollup
?
Because they are obviously different. Turbopack and Vite.
This helped me understand. A little.
SO, DOES ASTRO USE TURBOPACK OR VITE?
Because this would decide what would be best used in terms of plugin support. So strange.
☝️ adding vite or rollup
plugins:
Fuck it. I should just install the dep and not worry about it. Yeah, I've just installed vite-plugin-glsl
.
I think as I am implementing the flower effect I can clean up the way threeJS
has been implemented.
This is the JS implementation of the ThreeJS Flower Animation:
let pointer = {
x: 0.65,
y: 0.3,
clicked: true,
};
// only for codepen preview
let isStart = true;
let isRendering = true;
let renderer, shaderScene, mainScene, sceneTest, renderTargets, camera, clock;
let basicMaterial, shaderMaterial;
const backgroundColor = new THREE.Color(0xffffff);
initScene();
updateSize();
window.addEventListener("resize", updateSize);
function handleClickOrTouch(e) {
e.preventDefault(); // Prevent default touch behavior
let clientX, clientY;
if (e.type === "click") {
clientX = e.clientX;
clientY = e.clientY;
} else if (e.type === "touchstart") {
const touch = e.touches[0];
clientX = touch.clientX;
clientY = touch.clientY;
}
pointer.x = clientX / window.innerWidth;
pointer.y = clientY / window.innerHeight;
pointer.clicked = true;
isRendering = true;
}
window.addEventListener("click", handleClickOrTouch);
window.addEventListener("touchstart", handleClickOrTouch);
render();
function initScene() {
renderer = new THREE.WebGLRenderer({
canvas: canvasEl,
alpha: true,
});
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
shaderScene = new THREE.Scene();
mainScene = new THREE.Scene();
sceneTest = new THREE.Scene();
camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
clock = new THREE.Clock();
renderTargets = [
new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight),
new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight),
];
const planeGeometry = new THREE.PlaneGeometry(2, 2);
shaderMaterial = new THREE.ShaderMaterial({
uniforms: {
u_ratio: { type: "f", value: window.innerWidth / window.innerHeight },
u_point: { type: "v2", value: new THREE.Vector2(pointer.x, pointer.y) },
u_time: { type: "f", value: 0 },
u_stop_time: { type: "f", value: 0 },
u_stop_randomizer: { type: "v3", value: new THREE.Vector2(0, 0, 0) },
u_texture: { type: "t", value: null },
u_background_color: { type: "v3", value: backgroundColor },
},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
transparent: true,
});
basicMaterial = new THREE.MeshBasicMaterial({
transparent: true,
});
const backgroundColorMaterial = new THREE.MeshBasicMaterial({
color: backgroundColor,
transparent: true,
});
const planeBasic = new THREE.Mesh(planeGeometry, basicMaterial);
const planeShader = new THREE.Mesh(planeGeometry, shaderMaterial);
const coloredPlane = new THREE.Mesh(planeGeometry, backgroundColorMaterial);
shaderScene.add(planeShader);
mainScene.add(coloredPlane);
renderer.setRenderTarget(renderTargets[0]);
renderer.render(mainScene, camera);
mainScene.remove(coloredPlane);
mainScene.add(planeBasic);
}
function render() {
requestAnimationFrame(render);
const delta = clock.getDelta();
if (isRendering) {
shaderMaterial.uniforms.u_texture.value = renderTargets[0].texture;
shaderMaterial.uniforms.u_time.value = clock.getElapsedTime() + 0.9; // offset for 1st flower color
if (pointer.clicked) {
shaderMaterial.uniforms.u_point.value = new THREE.Vector2(
pointer.x,
1 - pointer.y
);
shaderMaterial.uniforms.u_stop_randomizer.value = new THREE.Vector3(
Math.random(),
Math.random(),
Math.random()
);
if (isStart) {
shaderMaterial.uniforms.u_stop_randomizer.value = new THREE.Vector3(
0.5,
1,
1
);
isStart = false;
}
shaderMaterial.uniforms.u_stop_time.value = 0;
pointer.clicked = false;
}
shaderMaterial.uniforms.u_stop_time.value += delta;
renderer.setRenderTarget(renderTargets[1]);
renderer.render(shaderScene, camera);
basicMaterial.map = renderTargets[1].texture;
renderer.setRenderTarget(null);
renderer.render(mainScene, camera);
let tmp = renderTargets[0];
renderTargets[0] = renderTargets[1];
renderTargets[1] = tmp;
}
}
function updateSize() {
shaderMaterial.uniforms.u_ratio.value =
window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
}
Could this at all be useful in better boilerplating my project?
This is helpful in refactoring what I have:
O.K. I pretty much have the branch where I want it: the flower animation has been integrated and works.
The styling is borked.
I think before I proceed that I should introduce React to the project. This way I can write the flower animation as a React Component.
Yeah, so I stripped out a lot of the initial boilerplate for the flower animation stuff.
I'm wondering whether the webgl
stuff should be in the scripts directory or not.
https://www.blackspike.com/blog/why-we-chose-astro-over-nuxt/