Skip to content

Commit

Permalink
adding gimp file, and testing 144 flags
Browse files Browse the repository at this point in the history
  • Loading branch information
idiom-bytes committed Jul 28, 2024
1 parent 27de224 commit cda5306
Show file tree
Hide file tree
Showing 2 changed files with 285 additions and 0 deletions.
Binary file added flag_sim/flag_1.xcf
Binary file not shown.
285 changes: 285 additions & 0 deletions flag_sim/flag_sim_24.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dense Grid of Flags</title>
<style>
body { margin: 0; }
canvas { display: block; position: fixed; top: 0; left: 0; }
#scrollContainer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 300%; /* Adjust based on your needs */
}
#controls {
position: fixed;
top: 10px;
left: 10px;
background: rgba(255,255,255,0.7);
padding: 10px;
z-index: 100;
}
</style>
</head>
<body>
<div id="scrollContainer"></div>
<div id="controls">
<select id="blendMode">
<option value="0">Normal</option>
<option value="1">Adjusted Overlay</option>
<option value="2">Hard Light</option>
<option value="3">Multiply</option>
<option value="4">Screen</option>
</select>
<br>
Blend Strength: <input type="range" id="blendStrength" min="0" max="1" step="0.01" value="0.8">
<br>
Brightness: <input type="range" id="brightness" min="-1" max="1" step="0.01" value="0">
<br>
Contrast: <input type="range" id="contrast" min="0" max="2" step="0.01" value="1">
<br>
Glow Strength: <input type="range" id="glowStrength" min="0" max="1" step="0.01" value="0.5">
<br>
Glow Width: <input type="range" id="glowWidth" min="0" max="0.1" step="0.001" value="0.02">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
let scene, camera, renderer, flags = [];
const NUM_FLAGS = 144;
const FLAGS_PER_ROW = 12;
const FLAG_WIDTH = 0.3;
const FLAG_HEIGHT = 0.9;
const FLAG_SPACING_X = 0.35;
const FLAG_SPACING_Y = 1.0;

function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const loader = new THREE.TextureLoader();
const flagTexture = loader.load('flag_1.png');
const maskTexture = loader.load('flag_1_movement.png');
const profileTexture = loader.load('milady.png');
const flagShapeMask = loader.load('flag_1_glow.png');

const geometry = new THREE.PlaneGeometry(FLAG_WIDTH, FLAG_HEIGHT, 20, 20);

for (let i = 0; i < NUM_FLAGS; i++) {
const material = createFlagMaterial(flagTexture, maskTexture, profileTexture, flagShapeMask);
const flag = new THREE.Mesh(geometry, material);

const row = Math.floor(i / FLAGS_PER_ROW);
const col = i % FLAGS_PER_ROW;

flag.position.x = (col - FLAGS_PER_ROW / 2 + 0.5) * FLAG_SPACING_X;
flag.position.y = 3 + (-row * FLAG_SPACING_Y);

flag.userData.eventId = i;
flags.push(flag);
scene.add(flag);
}

camera.position.z = 5;
camera.position.y = 0.5;

window.addEventListener('resize', onWindowResize, false);
window.addEventListener('scroll', onScroll, false);
renderer.domElement.addEventListener('mousemove', onMouseMove, false);

setupControls();
animate();
}

function createFlagMaterial(flagTexture, maskTexture, profileTexture, flagShapeMask) {
return new THREE.ShaderMaterial({
uniforms: {
time: { value: 1.0 },
flagTexture: { value: flagTexture },
maskTexture: { value: maskTexture },
profileTexture: { value: profileTexture },
flagShapeMask: { value: flagShapeMask },
profileSize: { value: new THREE.Vector2(0.4, 0.175) },
profilePosition: { value: new THREE.Vector2(0.5, 0.55) },
blendMode: { value: 0 },
blendStrength: { value: 0.8 },
brightness: { value: 0.0 },
contrast: { value: 1.0 },
glowStrength: { value: 0.5 },
glowWidth: { value: 0.02 },
isHovered: { value: 0 },
mirrorProfile: { value: 0 }
},
vertexShader: `
uniform float time;
uniform sampler2D maskTexture;
varying vec2 vUv;
void main() {
vUv = uv;
vec3 pos = position;
float mask = texture2D(maskTexture, uv).r;
float wave = sin(pos.y * 10.0 + time * 2.0) * 0.05 * pos.y;
pos.z += wave * mask;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
uniform sampler2D flagTexture;
uniform sampler2D profileTexture;
uniform sampler2D flagShapeMask;
uniform vec2 profileSize;
uniform vec2 profilePosition;
uniform int blendMode;
uniform float blendStrength;
uniform float brightness;
uniform float contrast;
uniform float glowStrength;
uniform float glowWidth;
uniform float isHovered;
uniform float mirrorProfile;
varying vec2 vUv;
vec3 blendNormal(vec3 base, vec3 blend) {
return blend;
}
vec3 blendAdjustedOverlay(vec3 base, vec3 blend) {
return mix(
2.0 * base * blend,
1.0 - 2.0 * (1.0 - base) * (1.0 - blend),
step(0.5, blend)
);
}
vec3 blendHardLight(vec3 base, vec3 blend) {
return mix(
2.0 * base * blend,
1.0 - 2.0 * (1.0 - base) * (1.0 - blend),
step(0.5, base)
);
}
vec3 blendMultiply(vec3 base, vec3 blend) {
return base * blend;
}
vec3 blendScreen(vec3 base, vec3 blend) {
return 1.0 - (1.0 - base) * (1.0 - blend);
}
vec3 adjustBrightnessContrast(vec3 color, float brightness, float contrast) {
return (color - 0.5) * contrast + 0.5 + brightness;
}
void main() {
vec4 flagColor = texture2D(flagTexture, vUv);
float flagShape = texture2D(flagShapeMask, vUv).r;
vec2 profileUv = (vUv - profilePosition) / profileSize + 0.5;
if (mirrorProfile > 0.5) profileUv.x = 1.0 - profileUv.x;
if (profileUv.x >= 0.0 && profileUv.x <= 1.0 &&
profileUv.y >= 0.0 && profileUv.y <= 1.0) {
vec4 profileColor = texture2D(profileTexture, profileUv);
vec3 blendedColor;
if (blendMode == 0) blendedColor = blendNormal(flagColor.rgb, profileColor.rgb);
else if (blendMode == 1) blendedColor = blendAdjustedOverlay(flagColor.rgb, profileColor.rgb);
else if (blendMode == 2) blendedColor = blendHardLight(flagColor.rgb, profileColor.rgb);
else if (blendMode == 3) blendedColor = blendMultiply(flagColor.rgb, profileColor.rgb);
else if (blendMode == 4) blendedColor = blendScreen(flagColor.rgb, profileColor.rgb);
blendedColor = adjustBrightnessContrast(blendedColor, brightness, contrast);
float distFromCenter = length((profileUv - 0.5) * 2.0);
float blendFactor = profileColor.a * (1.0 - smoothstep(0.8, 1.0, distFromCenter)) * blendStrength;
flagColor.rgb = mix(flagColor.rgb, blendedColor, blendFactor);
}
if (isHovered > 0.5) {
float glow = 0.0;
for (float x = -glowWidth; x <= glowWidth; x += 0.001) {
for (float y = -glowWidth; y <= glowWidth; y += 0.001) {
vec2 sampleUv = vUv + vec2(x, y);
float sampleShape = texture2D(flagShapeMask, sampleUv).r;
if (sampleShape > 0.5 && flagShape < 0.5) {
float dist = length(vec2(x, y));
glow += smoothstep(glowWidth, 0.0, dist);
}
}
}
glow *= glowStrength / (glowWidth * 2000.0);
flagColor.rgb += vec3(1.0, 0.7, 0.3) * glow * (1.0 - flagShape);
}
gl_FragColor = flagColor;
}
`,
side: THREE.DoubleSide
});
}

function onScroll() {
const scrollY = window.scrollY;
camera.position.y = 0.5 - scrollY / window.innerHeight * FLAG_SPACING_Y;
}

function onMouseMove(event) {
const mouse = new THREE.Vector2(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1
);

const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);

const intersects = raycaster.intersectObjects(flags);

flags.forEach(flag => {
flag.material.uniforms.isHovered.value = 0;
});

if (intersects.length > 0) {
intersects[0].object.material.uniforms.isHovered.value = 1;
}
}

function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}

function setupControls() {
const controls = ['blendMode', 'blendStrength', 'brightness', 'contrast', 'glowStrength', 'glowWidth'];
controls.forEach(control => {
document.getElementById(control).addEventListener('change', updateUniforms);
document.getElementById(control).addEventListener('input', updateUniforms);
});
}

function updateUniforms(e) {
const value = e.target.type === 'range' ? parseFloat(e.target.value) : parseInt(e.target.value);
flags.forEach(flag => {
flag.material.uniforms[e.target.id].value = value;
});
}

function animate() {
requestAnimationFrame(animate);
flags.forEach(flag => {
flag.material.uniforms.time.value += 0.05;
});
renderer.render(scene, camera);
}

init();
</script>
</body>
</html>

0 comments on commit cda5306

Please sign in to comment.