python-mastery-academy / visualizer.html
mb672038's picture
در این فایلی که اتخاب کردم کی خوام یک سایت بنویسی برای تست گرافیک که سطحش بالا باشه و نتیجه هم بده
46428fd verified
Raw
History Blame Contribute Delete
16.4 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Visualizer | GraphicsLab</title>
<link rel="icon" type="image/x-icon" href="https://static.photos/technology/32x32/3">
<link rel="stylesheet" href="style.css">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
</head>
<body class="bg-gray-50 text-gray-900">
<custom-navbar></custom-navbar>
<main class="container mx-auto px-4 py-8">
<div class="mb-10">
<h1 class="text-4xl font-bold mb-4">Interactive 3D Visualizer</h1>
<p class="text-gray-600">Load, manipulate, and visualize 3D models with real‑time lighting and effects.</p>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div class="lg:col-span-2">
<div class="card p-0 overflow-hidden">
<div class="bg-gray-900 p-4 flex justify-between items-center">
<h2 class="text-xl font-bold text-white">WebGL Canvas</h2>
<div class="flex gap-2">
<button id="playBtn" class="btn-small bg-green-600">
<i class="fas fa-play mr-1"></i> Play
</button>
<button id="resetBtn" class="btn-small bg-gray-700">
<i class="fas fa-redo mr-1"></i> Reset
</button>
</div>
</div>
<div id="canvasContainer" class="relative w-full h-96 bg-gradient-to-br from-gray-900 to-black">
<canvas id="threeCanvas" class="w-full h-full"></canvas>
<div id="loading" class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-75 text-white text-xl">
<div class="text-center">
<i class="fas fa-spinner fa-spin text-4xl mb-4"></i>
<p>Loading WebGL scene...</p>
</div>
</div>
</div>
<div class="p-4 bg-gray-100 flex justify-between items-center">
<div class="text-sm text-gray-700">
<span id="fpsCounter">FPS: 60</span> |
<span id="triangleCount">Triangles: 0</span> |
<span id="renderTime">Render: 0ms</span>
</div>
<div class="flex gap-2">
<button class="text-sm bg-gray-300 hover:bg-gray-400 px-3 py-1 rounded" onclick="toggleWireframe()">
<i class="fas fa-th"></i> Wireframe
</button>
<button class="text-sm bg-gray-300 hover:bg-gray-400 px-3 py-1 rounded" onclick="toggleShadows()">
<i class="fas fa-sun"></i> Shadows
</button>
</div>
</div>
</div>
<div class="card mt-8">
<h2 class="text-2xl font-bold mb-4">Model Library</h2>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div class="model-card p-4 border border-gray-300 rounded-lg text-center cursor-pointer hover:bg-gray-50" onclick="loadModel('sphere')">
<div class="text-4xl text-blue-500 mb-2">
<i class="fas fa-globe-americas"></i>
</div>
<div class="font-semibold">Sphere</div>
<div class="text-sm text-gray-500">1,280 triangles</div>
</div>
<div class="model-card p-4 border border-gray-300 rounded-lg text-center cursor-pointer hover:bg-gray-50" onclick="loadModel('cube')">
<div class="text-4xl text-purple-500 mb-2">
<i class="fas fa-cube"></i>
</div>
<div class="font-semibold">Cube</div>
<div class="text-sm text-gray-500">12 triangles</div>
</div>
<div class="model-card p-4 border border-gray-300 rounded-lg text-center cursor-pointer hover:bg-gray-50" onclick="loadModel('torus')">
<div class="text-4xl text-green-500 mb-2">
<i class="fas fa-ring"></i>
</div>
<div class="font-semibold">Torus</div>
<div class="text-sm text-gray-500">4,800 triangles</div>
</div>
<div class="model-card p-4 border border-gray-300 rounded-lg text-center cursor-pointer hover:bg-gray-50" onclick="loadModel('teapot')">
<div class="text-4xl text-red-500 mb-2">
<i class="fas fa-mug-hot"></i>
</div>
<div class="font-semibold">Teapot</div>
<div class="text-sm text-gray-500">6,324 triangles</div>
</div>
</div>
</div>
</div>
<div>
<div class="card mb-8">
<h2 class="text-2xl font-bold mb-4">Controls</h2>
<div class="space-y-6">
<div>
<label class="block text-gray-700 mb-2">Rotation Speed</label>
<input type="range" min="0" max="10" value="2" class="w-full" id="rotationSpeed" oninput="updateRotation(this.value)">
<div class="flex justify-between text-sm text-gray-500">
<span>Slow</span>
<span id="speedValue">2</span>
<span>Fast</span>
</div>
</div>
<div>
<label class="block text-gray-700 mb-2">Light Intensity</label>
<input type="range" min="0" max="5" step="0.1" value="1.5" class="w-full" id="lightIntensity" oninput="updateLight(this.value)">
<div class="flex justify-between text-sm text-gray-500">
<span>Dim</span>
<span id="lightValue">1.5</span>
<span>Bright</span>
</div>
</div>
<div>
<label class="block text-gray-700 mb-2">Background Color</label>
<div class="flex gap-2">
<button class="flex-1 py-2 rounded bg-gray-800 text-white" onclick="setBackground('#1f2937')">Dark</button>
<button class="flex-1 py-2 rounded bg-gray-300" onclick="setBackground('#f3f4f6')">Light</button>
<button class="flex-1 py-2 rounded bg-blue-900 text-white" onclick="setBackground('#1e3a8a')">Blue</button>
</div>
</div>
<div>
<label class="block text-gray-700 mb-2">Post‑Processing</label>
<div class="space-y-2">
<label class="flex items-center">
<input type="checkbox" class="mr-2" id="bloom" onchange="toggleEffect('bloom')">
<span>Bloom</span>
</label>
<label class="flex items-center">
<input type="checkbox" class="mr-2" id="vignette" onchange="toggleEffect('vignette')">
<span>Vignette</span>
</label>
<label class="flex items-center">
<input type="checkbox" class="mr-2" id="ssao" onchange="toggleEffect('ssao')">
<span>SSAO</span>
</label>
</div>
</div>
</div>
</div>
<div class="card">
<h2 class="text-2xl font-bold mb-4">Scene Info</h2>
<div class="space-y-3">
<div class="flex justify-between">
<span class="text-gray-600">Renderer</span>
<span class="font-semibold" id="rendererInfo">WebGL 2</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Draw Calls</span>
<span class="font-semibold" id="drawCalls">1</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Textures</span>
<span class="font-semibold" id="textureCount">3</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Lights</span>
<span class="font-semibold" id="lightCount">2</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">VRAM Usage</span>
<span class="font-semibold" id="vramUsage">~120 MB</span>
</div>
</div>
<button class="btn-primary w-full mt-6" onclick="exportScene()">
<i class="fas fa-download mr-2"></i> Export as GLB
</button>
</div>
</div>
</div>
</main>
<custom-footer></custom-footer>
<script src="components/navbar.js"></script>
<script src="components/footer.js"></script>
<script src="script.js"></script>
<script>
// Three.js scene variables
let scene, camera, renderer, controls, cube;
let rotationSpeed = 2;
let lightIntensity = 1.5;
let frameCount = 0;
let lastTime = performance.now();
let fps = 60;
// Initialize Three.js scene
function initScene() {
const canvas = document.getElementById('threeCanvas');
const container = document.getElementById('canvasContainer');
scene = new THREE.Scene();
scene.background = new THREE.Color(0x1f2937);
camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);
camera.position.z = 5;
renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.setSize(container.clientWidth, container.clientHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// OrbitControls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// Lighting
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, lightIntensity);
directionalLight.position.set(5, 5, 5);
directionalLight.castShadow = true;
scene.add(directionalLight);
// Add a default cube
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshStandardMaterial({ color: 0x3b82f6, roughness: 0.3, metalness: 0.8 });
cube = new THREE.Mesh(geometry, material);
cube.castShadow = true;
cube.receiveShadow = true;
scene.add(cube);
// Add a ground plane
const planeGeometry = new THREE.PlaneGeometry(10, 10);
const planeMaterial = new THREE.MeshStandardMaterial({ color: 0x374151, side: THREE.DoubleSide });
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = Math.PI / 2;
plane.position.y = -2;
plane.receiveShadow = true;
scene.add(plane);
// Hide loading
document.getElementById('loading').style.display = 'none';
// Start animation loop
animate();
// Update info
updateInfo();
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01 * rotationSpeed;
cube.rotation.y += 0.01 * rotationSpeed;
controls.update();
renderer.render(scene, camera);
// FPS calculation
frameCount++;
const now = performance.now();
if (now >= lastTime + 1000) {
fps = Math.round((frameCount * 1000) / (now - lastTime));
frameCount = 0;
lastTime = now;
document.getElementById('fpsCounter').textContent = `FPS: ${fps}`;
}
}
// UI functions
function updateRotation(val) {
rotationSpeed = parseFloat(val);
document.getElementById('speedValue').textContent = val;
}
function updateLight(val) {
lightIntensity = parseFloat(val);
scene.children.forEach(child => {
if (child.isLight) child.intensity = lightIntensity;
});
document.getElementById('lightValue').textContent = val;
}
function setBackground(color) {
scene.background = new THREE.Color(color);
}
function toggleWireframe() {
cube.material.wireframe = !cube.material.wireframe;
}
function toggleShadows() {
renderer.shadowMap.enabled = !renderer.shadowMap.enabled;
}
function toggleEffect(effect) {
alert(`Effect ${effect} toggled (simulated)`);
}
function loadModel(model) {
alert(`Loading ${model} model (simulated)`);
// In a real app, load GLTF/OBJ here
document.getElementById('triangleCount').textContent = `Triangles: ${{
sphere: 1280,
cube: 12,
torus: 4800,
teapot: 6324
}[model]}`;
}
function exportScene() {
alert('Scene exported as GLB (simulated)');
}
function updateInfo() {
document.getElementById('rendererInfo').textContent = renderer.capabilities.isWebGL2 ? 'WebGL 2' : 'WebGL 1';
document.getElementById('drawCalls').textContent = renderer.info.render.calls;
document.getElementById('textureCount').textContent = renderer.info.memory.textures;
document.getElementById('lightCount').textContent = scene.children.filter(c => c.isLight).length;
}
// Resize handler
window.addEventListener('resize', () => {
const container = document.getElementById('canvasContainer');
camera.aspect = container.clientWidth / container.clientHeight;
camera.updateProjectionMatrix();
renderer.setSize(container.clientWidth, container.clientHeight);
});
// Initialize on load
window.addEventListener('DOMContentLoaded', () => {
initScene();
});
</script>
</body>
</html>