Skip to content

Instantly share code, notes, and snippets.

@hideya
Last active August 13, 2025 20:32
Show Gist options
  • Save hideya/228c7e42b1a261f4c7bb868d9c0e66d8 to your computer and use it in GitHub Desktop.
Save hideya/228c7e42b1a261f4c7bb868d9c0e66d8 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG Filter Demo -- Bumpy Metal Surface</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body, html {
height: 100%;
overflow: hidden;
}
body {
background: #000000;
font-family: 'Arial', sans-serif;
position: relative;
overflow: hidden;
}
.metal-panel-container {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 10;
}
.metal-panel {
width: 100%;
height: 100%;
}
@keyframes gradientShift {
/* Removed - no longer needed */
}
</style>
</head>
<body>
<div class="metal-panel-container">
<svg class="metal-panel" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Bump map using turbulence -->
<filter id="bumpMap" x="-50%" y="-50%" width="200%" height="200%">
<!-- Generate noise for surface bumps -->
<feTurbulence baseFrequency="0.5" numOctaves="4" seed="2" result="noise"/>
<!-- Create height map from noise -->
<feColorMatrix in="noise" type="saturate" values="0" result="heightMap"/>
<!-- Generate normal map from height map -->
<feConvolveMatrix in="heightMap" order="3" kernelMatrix="
-1 -1 -1
-1 8 -1
-1 -1 -1" result="normalMap"/>
<!-- Create diffuse lighting -->
<feDiffuseLighting in="normalMap" diffuseConstant="1" lighting-color="#ffffff" result="diffuseOut">
<fePointLight id="diffuseLight" x="0" y="0" z="100"/>
</feDiffuseLighting>
<!-- Combine lighting effects -->
<feComposite in="specularOut" in2="diffuseOut" operator="add" result="lighting"/>
<!-- Apply to just the noise pattern -->
<feComposite in="noise" in2="lighting" operator="multiply" result="lit"/>
<!-- Add specular highlights -->
<feComposite in="lit" in2="specularOut" operator="screen"/>
</filter>
<!-- Shadow filter -->
<filter id="shadow" x="-100%" y="-100%" width="300%" height="300%">
<feDropShadow dx="0" dy="10" stdDeviation="15" flood-color="#000000" flood-opacity="0.3"/>
</filter>
</defs>
<!-- Shadow -->
<rect x="15" y="15" width="170" height="170" fill="#000000" opacity="0.2" filter="url(#shadow)"/>
<!-- Pure bumpy texture rectangle -->
<rect x="15" y="15" width="170" height="170" fill="#C0C0C0" filter="url(#bumpMap)"/>
</svg>
</div>
<script>
let mouseX = 0.3;
let mouseY = 0.3;
function updateLighting() {
// const lightSource = document.getElementById('lightSource');
const diffuseLight = document.getElementById('diffuseLight');
// if (lightSource && diffuseLight) {
if (diffuseLight) {
// Convert mouse position to light coordinates (scaled for full screen)
const lightX = mouseX * 300 - 100;
const lightY = mouseY * 300 - 100;
const lightZ = 100 // - (mouseX * 50); // Vary Z based on X for more dynamic effect
diffuseLight.setAttribute('x', lightX);
diffuseLight.setAttribute('y', lightY);
diffuseLight.setAttribute('z', lightZ * 0.5);
}
}
document.addEventListener('mousemove', (e) => {
// Calculate relative position from entire screen
mouseX = e.clientX / window.innerWidth;
mouseY = e.clientY / window.innerHeight;
updateLighting();
});
// Initialize lighting
updateLighting();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment