Skip to content

Instantly share code, notes, and snippets.

@jpgreth
Created June 16, 2023 11:52
Show Gist options
  • Save jpgreth/6ce1cb1a451c0866257135e3619ed5bb to your computer and use it in GitHub Desktop.
Save jpgreth/6ce1cb1a451c0866257135e3619ed5bb to your computer and use it in GitHub Desktop.
Static Gradient
<script async src="https://ga.jspm.io/npm:es-module-shims@1.6.3/dist/es-module-shims.js" crossorigin="anonymous"></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.153.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.153.0/examples/jsm/"
}
}
</script>
<canvas id="grd" width="512" height="10"></canvas>
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { mergeGeometries } from "three/addons/utils/BufferGeometryUtils.js";
import { GUI } from "three/addons/libs/lil-gui.module.min.js";
console.clear();
let scene = new THREE.Scene();
scene.background = new THREE.Color(0x202020);
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 4, 10);
camera.lookAt(scene.position);
let renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
//renderer.setClearColor(0x404040);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", (event) => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
});
let controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 4, 0);
controls.enableDamping = true;
let light = new THREE.DirectionalLight(0xffffff, 0.8);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xff8888, 0.2));
//scene.add(new THREE.GridHelper());
let gu = {
time: {value: 0}
}
// model
let loader = new GLTFLoader();
let result = await loader.loadAsync("https://threejs.org/examples/models/gltf/Xbot.glb");
let model = result.scene;
let colors = ['#FF0089', '#CFC91E', '#02E91E', '#00DAFF'];
let gradTexture = getGradientTexture(colors);
let u = {
gradTexture: {value: gradTexture},
box: {
min: {value: new THREE.Vector3(-2, 0, -3)},
max: {value: new THREE.Vector3(2, 8.75, 3)}
}
}
scene.add(new THREE.Box3Helper(new THREE.Box3(u.box.min.value, u.box.max.value)));
model.traverse(child => {
if(child.isMesh){
child.material.onBeforeCompile = shader => {
shader.uniforms.gradTexture = u.gradTexture;
shader.uniforms.boxMin = u.box.min;
shader.uniforms.boxMax = u.box.max;
shader.vertexShader = `
varying vec3 wPos;
${shader.vertexShader}
`.replace(
`#include <project_vertex>`,
`
wPos = vec3(modelMatrix * vec4(transformed, 1.));
#include <project_vertex>
`
);
console.log(shader.vertexShader);
shader.fragmentShader = `
uniform sampler2D gradTexture;
uniform vec3 boxMin;
uniform vec3 boxMax;
varying vec3 wPos;
${shader.fragmentShader}
`.replace(
`#include <color_fragment>`,
`#include <color_fragment>
vec3 diag = boxMax - boxMin;
float diagDist = length(diag);
vec3 diagN = normalize(diag);
vec3 boundPos = wPos - boxMin;
float dotted = dot(diagN, boundPos);
float dottedN = clamp(dotted / diagDist, 0., 1.);
//dottedN = fract(dottedN * 10.);
vec3 gradColor = texture(gradTexture, vec2(dottedN, 0.5)).rgb;
diffuseColor.rgb = gradColor;
`
);
console.log(shader.fragmentShader);
}
}
})
model.scale.setScalar(5);
model.frustumCulled = false;
let mixer = new THREE.AnimationMixer(model);
let action = mixer.clipAction(result.animations[3]);
action.play();
//console.log(result)
scene.add(model);
let clock = new THREE.Clock();
let time = 0;
renderer.setAnimationLoop((_) => {
let t = clock.getDelta();
time += t;
gu.time.value = time;
mixer.update(t);
controls.update();
renderer.render(scene, camera);
});
function getGradientTexture(colors){
let c = document.getElementById("grd")
let ctx = c.getContext("2d");
let grd = ctx.createLinearGradient(0, 0, c.width, 0);
let clrStep = 1 / (colors.length - 1);
colors.forEach((clr, clrIdx) => {
grd.addColorStop(clrIdx * clrStep, clr)
});
ctx.fillStyle = grd;
ctx.fillRect(0, 0, c.width, c.height);
let ct = new THREE.CanvasTexture(c);
ct.colorSpace = THREE.SRGBColorSpace
return ct;
}
body{
overflow: hidden;
margin: 0;
background-color: black;
}
#grd{
position: absolute;
margin: 10px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment