-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adding gimp file, and testing 144 flags
- Loading branch information
1 parent
27de224
commit cda5306
Showing
2 changed files
with
285 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |