Anonymous
Объект выглядит полупрозрачным, хотя непрозрачность равна 1 из трех js
Сообщение
Anonymous » 17 янв 2025, 21:30
Почему мой куб Three.js выглядит полупрозрачным, когда я меняю металличность, шероховатость и цвет, хотя непрозрачность остается равной 1.
Прозрачность появляется только при прямоугольном освещении, а не точечный источник света.
Посмотрите демонстрационное видео , и вы увидите, что свет появляется снаружи, как если бы коробка была полупрозрачной.
Код: Выделить всё
Simple Rectangle Light
body { margin: 0; }
canvas { display: block; }
#controls {
position: fixed;
top: 10px;
left: 10px;
background: rgba(0,0,0,0.7);
padding: 10px;
border-radius: 5px;
color: white;
font-family: Arial;
}
Rectangle Light
Point Light
Rectangle Light Position:
X:
Y:
Z:
Rectangle Light Rotation:
X:
Y:
Z:
Rectangle Light Size:
Width:
Height:
Material Properties:
Color:
Roughness:
Metalness:
{
"imports": {
"three": "https://unpkg.com/three@0.160.0/build/three.module.js",
"three/examples/jsm/controls/OrbitControls.js": "https://unpkg.com/three@0.160.0/examples/jsm/controls/OrbitControls.js",
"three/examples/jsm/lights/RectAreaLightUniformsLib.js": "https://unpkg.com/three@0.160.0/examples/jsm/lights/RectAreaLightUniformsLib.js",
"three/examples/jsm/helpers/RectAreaLightHelper.js": "https://unpkg.com/three@0.160.0/examples/jsm/helpers/RectAreaLightHelper.js"
}
}
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js';
import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js';
// Scene setup
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);
// Camera setup
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
// Renderer setup
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Initialize rect area light uniforms
RectAreaLightUniformsLib.init();
// Controls
const controls = new OrbitControls(camera, renderer.domElement);
// Comment out texture loading
// const textureLoader = new THREE.TextureLoader();
// const skinTexture = textureLoader.load('skin-image.png');
// Add material definition before box creation
const material = new THREE.MeshStandardMaterial({
color: 0x333333,
roughness: 0.9,
metalness: 0.0,
opacity: 1.0,
transparent: false
});
// Create box
const outerSize = 2;
const thickness = 0.2; // Back to original thickness
const box = new THREE.Group();
// Bottom
const bottom = new THREE.Mesh(
new THREE.BoxGeometry(outerSize, thickness, outerSize),
material
);
bottom.position.y = -outerSize/2;
box.add(bottom);
// Front wall
const front = new THREE.Mesh(
new THREE.BoxGeometry(outerSize, outerSize, thickness),
material
);
front.position.z = outerSize/2 - thickness/2;
front.position.y = -thickness/2;
box.add(front);
// Back wall
const back = new THREE.Mesh(
new THREE.BoxGeometry(outerSize, outerSize, thickness),
material
);
back.position.z = -outerSize/2 + thickness/2;
back.position.y = -thickness/2;
box.add(back);
// Left wall
const left = new THREE.Mesh(
new THREE.BoxGeometry(thickness, outerSize, outerSize),
material
);
left.position.x = -outerSize/2 + thickness/2;
left.position.y = -thickness/2;
box.add(left);
// Right wall
const right = new THREE.Mesh(
new THREE.BoxGeometry(thickness, outerSize, outerSize),
material
);
right.position.x = outerSize/2 - thickness/2;
right.position.y = -thickness/2;
box.add(right);
scene.add(box);
// Rectangle light at bottom
const width = 1.0; // Smaller than inner width (was 1.8)
const height = 1.0; // Make it square like the box (was 1.8)
const intensity = 10;
const rectLight = new THREE.RectAreaLight(0xff0000, intensity, width, height);
rectLight.position.set(0, -0.9 + 0.01, 0); // Keep it just above bottom
rectLight.rotation.x = Math.PI / 2; // Face up
scene.add(rectLight);
// Add visible helper for the light
const helper = new RectAreaLightHelper(rectLight);
rectLight.add(helper);
// Move ambient light before PMREM setup
const ambientLight = new THREE.AmbientLight(0xffffff, 2.0);
scene.add(ambientLight);
// Add point light inside box
const pointLight = new THREE.PointLight(0xff0000, 10.0);
pointLight.position.set(0, -0.5, 0);
pointLight.distance = 3; // How far the light reaches
pointLight.decay = 1; // How quickly it fades with distance
scene.add(pointLight);
// Make the visualization sphere bigger
const sphereGeometry = new THREE.SphereGeometry(0.2, 16, 16); // Increase from 0.05 to 0.2
const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const lightSphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
lightSphere.position.copy(pointLight.position);
scene.add(lightSphere);
// Animation
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
// Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
document.getElementById('rectLight').addEventListener('change', (e) => {
rectLight.visible = e.target.checked;
helper.visible = e.target.checked;
});
document.getElementById('pointLight').addEventListener('change', (e) => {
pointLight.visible = e.target.checked;
lightSphere.visible = e.target.checked;
});
document.getElementById('rectX').addEventListener('input', (e) => {
rectLight.position.x = parseFloat(e.target.value);
updateURL();
});
document.getElementById('rectY').addEventListener('input', (e) => {
rectLight.position.y = parseFloat(e.target.value) + 0.01; // Keep slight offset from bottom
});
document.getElementById('rectZ').addEventListener('input', (e) => {
rectLight.position.z = parseFloat(e.target.value);
});
document.getElementById('rectRotX').addEventListener('input', (e) => {
rectLight.rotation.x = parseFloat(e.target.value);
});
document.getElementById('rectRotY').addEventListener('input', (e) => {
rectLight.rotation.y = parseFloat(e.target.value);
});
document.getElementById('rectRotZ').addEventListener('input', (e) => {
rectLight.rotation.z = parseFloat(e.target.value);
});
document.getElementById('rectWidth').addEventListener('input', (e) => {
rectLight.width = parseFloat(e.target.value);
helper.update(); // Update the helper to show new size
});
document.getElementById('rectHeight').addEventListener('input', (e) => {
rectLight.height = parseFloat(e.target.value);
helper.update(); // Update the helper to show new size
});
document.getElementById('matColor').addEventListener('input', (e) => {
const value = parseInt(e.target.value);
material.color.setRGB(value/255, value/255, value/255);
updateURL();
});
document.getElementById('matRough').addEventListener('input', (e) => {
material.roughness = parseFloat(e.target.value);
});
document.getElementById('matMetal').addEventListener('input', (e) => {
material.metalness = parseFloat(e.target.value);
});
// Add function to update URL with current settings
function updateURL() {
const params = new URLSearchParams();
// Material settings
params.set('color', document.getElementById('matColor').value);
params.set('rough', document.getElementById('matRough').value);
params.set('metal', document.getElementById('matMetal').value);
// Light visibility
params.set('rectVisible', document.getElementById('rectLight').checked);
params.set('pointVisible', document.getElementById('pointLight').checked);
// Rectangle light settings
params.set('rectX', document.getElementById('rectX').value);
params.set('rectY', document.getElementById('rectY').value);
params.set('rectZ', document.getElementById('rectZ').value);
params.set('rectRotX', document.getElementById('rectRotX').value);
params.set('rectRotY', document.getElementById('rectRotY').value);
params.set('rectRotZ', document.getElementById('rectRotZ').value);
params.set('rectWidth', document.getElementById('rectWidth').value);
params.set('rectHeight', document.getElementById('rectHeight').value);
window.history.replaceState({}, '', `${window.location.pathname}?${params.toString()}`);
}
// Also add function to load settings from URL on page load
function loadFromURL() {
const params = new URLSearchParams(window.location.search);
// Helper function to load a parameter
function loadParam(id, prop, obj, converter = parseFloat) {
if(params.has(id)) {
const value = converter(params.get(id));
document.getElementById(id).value = value;
if(obj && prop) obj[prop] = value;
}
}
// Load all parameters
loadParam('color', null, null, value => {
const v = parseInt(value);
material.color.setRGB(v/255, v/255, v/255);
return v;
});
loadParam('rough', 'roughness', material);
loadParam('metal', 'metalness', material);
loadParam('rectX', 'x', rectLight.position);
// ... etc for all parameters
}
// Call on page load
loadFromURL();
Подробнее здесь:
https://stackoverflow.com/questions/793 ... n-three-js
1737138600
Anonymous
Почему мой куб Three.js выглядит полупрозрачным, когда я меняю металличность, шероховатость и цвет, хотя непрозрачность остается равной 1. Прозрачность появляется только при прямоугольном освещении, а не точечный источник света. [b]Посмотрите демонстрационное видео[/b], и вы увидите, что свет появляется снаружи, как если бы коробка была полупрозрачной. [code] Simple Rectangle Light body { margin: 0; } canvas { display: block; } #controls { position: fixed; top: 10px; left: 10px; background: rgba(0,0,0,0.7); padding: 10px; border-radius: 5px; color: white; font-family: Arial; } Rectangle Light Point Light Rectangle Light Position: X: Y: Z: Rectangle Light Rotation: X: Y: Z: Rectangle Light Size: Width: Height: Material Properties: Color: Roughness: Metalness: { "imports": { "three": "https://unpkg.com/three@0.160.0/build/three.module.js", "three/examples/jsm/controls/OrbitControls.js": "https://unpkg.com/three@0.160.0/examples/jsm/controls/OrbitControls.js", "three/examples/jsm/lights/RectAreaLightUniformsLib.js": "https://unpkg.com/three@0.160.0/examples/jsm/lights/RectAreaLightUniformsLib.js", "three/examples/jsm/helpers/RectAreaLightHelper.js": "https://unpkg.com/three@0.160.0/examples/jsm/helpers/RectAreaLightHelper.js" } } import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js'; import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js'; // Scene setup const scene = new THREE.Scene(); scene.background = new THREE.Color(0x000000); // Camera setup const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = 5; // Renderer setup const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // Initialize rect area light uniforms RectAreaLightUniformsLib.init(); // Controls const controls = new OrbitControls(camera, renderer.domElement); // Comment out texture loading // const textureLoader = new THREE.TextureLoader(); // const skinTexture = textureLoader.load('skin-image.png'); // Add material definition before box creation const material = new THREE.MeshStandardMaterial({ color: 0x333333, roughness: 0.9, metalness: 0.0, opacity: 1.0, transparent: false }); // Create box const outerSize = 2; const thickness = 0.2; // Back to original thickness const box = new THREE.Group(); // Bottom const bottom = new THREE.Mesh( new THREE.BoxGeometry(outerSize, thickness, outerSize), material ); bottom.position.y = -outerSize/2; box.add(bottom); // Front wall const front = new THREE.Mesh( new THREE.BoxGeometry(outerSize, outerSize, thickness), material ); front.position.z = outerSize/2 - thickness/2; front.position.y = -thickness/2; box.add(front); // Back wall const back = new THREE.Mesh( new THREE.BoxGeometry(outerSize, outerSize, thickness), material ); back.position.z = -outerSize/2 + thickness/2; back.position.y = -thickness/2; box.add(back); // Left wall const left = new THREE.Mesh( new THREE.BoxGeometry(thickness, outerSize, outerSize), material ); left.position.x = -outerSize/2 + thickness/2; left.position.y = -thickness/2; box.add(left); // Right wall const right = new THREE.Mesh( new THREE.BoxGeometry(thickness, outerSize, outerSize), material ); right.position.x = outerSize/2 - thickness/2; right.position.y = -thickness/2; box.add(right); scene.add(box); // Rectangle light at bottom const width = 1.0; // Smaller than inner width (was 1.8) const height = 1.0; // Make it square like the box (was 1.8) const intensity = 10; const rectLight = new THREE.RectAreaLight(0xff0000, intensity, width, height); rectLight.position.set(0, -0.9 + 0.01, 0); // Keep it just above bottom rectLight.rotation.x = Math.PI / 2; // Face up scene.add(rectLight); // Add visible helper for the light const helper = new RectAreaLightHelper(rectLight); rectLight.add(helper); // Move ambient light before PMREM setup const ambientLight = new THREE.AmbientLight(0xffffff, 2.0); scene.add(ambientLight); // Add point light inside box const pointLight = new THREE.PointLight(0xff0000, 10.0); pointLight.position.set(0, -0.5, 0); pointLight.distance = 3; // How far the light reaches pointLight.decay = 1; // How quickly it fades with distance scene.add(pointLight); // Make the visualization sphere bigger const sphereGeometry = new THREE.SphereGeometry(0.2, 16, 16); // Increase from 0.05 to 0.2 const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const lightSphere = new THREE.Mesh(sphereGeometry, sphereMaterial); lightSphere.position.copy(pointLight.position); scene.add(lightSphere); // Animation function animate() { requestAnimationFrame(animate); controls.update(); renderer.render(scene, camera); } animate(); // Handle window resize window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }); document.getElementById('rectLight').addEventListener('change', (e) => { rectLight.visible = e.target.checked; helper.visible = e.target.checked; }); document.getElementById('pointLight').addEventListener('change', (e) => { pointLight.visible = e.target.checked; lightSphere.visible = e.target.checked; }); document.getElementById('rectX').addEventListener('input', (e) => { rectLight.position.x = parseFloat(e.target.value); updateURL(); }); document.getElementById('rectY').addEventListener('input', (e) => { rectLight.position.y = parseFloat(e.target.value) + 0.01; // Keep slight offset from bottom }); document.getElementById('rectZ').addEventListener('input', (e) => { rectLight.position.z = parseFloat(e.target.value); }); document.getElementById('rectRotX').addEventListener('input', (e) => { rectLight.rotation.x = parseFloat(e.target.value); }); document.getElementById('rectRotY').addEventListener('input', (e) => { rectLight.rotation.y = parseFloat(e.target.value); }); document.getElementById('rectRotZ').addEventListener('input', (e) => { rectLight.rotation.z = parseFloat(e.target.value); }); document.getElementById('rectWidth').addEventListener('input', (e) => { rectLight.width = parseFloat(e.target.value); helper.update(); // Update the helper to show new size }); document.getElementById('rectHeight').addEventListener('input', (e) => { rectLight.height = parseFloat(e.target.value); helper.update(); // Update the helper to show new size }); document.getElementById('matColor').addEventListener('input', (e) => { const value = parseInt(e.target.value); material.color.setRGB(value/255, value/255, value/255); updateURL(); }); document.getElementById('matRough').addEventListener('input', (e) => { material.roughness = parseFloat(e.target.value); }); document.getElementById('matMetal').addEventListener('input', (e) => { material.metalness = parseFloat(e.target.value); }); // Add function to update URL with current settings function updateURL() { const params = new URLSearchParams(); // Material settings params.set('color', document.getElementById('matColor').value); params.set('rough', document.getElementById('matRough').value); params.set('metal', document.getElementById('matMetal').value); // Light visibility params.set('rectVisible', document.getElementById('rectLight').checked); params.set('pointVisible', document.getElementById('pointLight').checked); // Rectangle light settings params.set('rectX', document.getElementById('rectX').value); params.set('rectY', document.getElementById('rectY').value); params.set('rectZ', document.getElementById('rectZ').value); params.set('rectRotX', document.getElementById('rectRotX').value); params.set('rectRotY', document.getElementById('rectRotY').value); params.set('rectRotZ', document.getElementById('rectRotZ').value); params.set('rectWidth', document.getElementById('rectWidth').value); params.set('rectHeight', document.getElementById('rectHeight').value); window.history.replaceState({}, '', `${window.location.pathname}?${params.toString()}`); } // Also add function to load settings from URL on page load function loadFromURL() { const params = new URLSearchParams(window.location.search); // Helper function to load a parameter function loadParam(id, prop, obj, converter = parseFloat) { if(params.has(id)) { const value = converter(params.get(id)); document.getElementById(id).value = value; if(obj && prop) obj[prop] = value; } } // Load all parameters loadParam('color', null, null, value => { const v = parseInt(value); material.color.setRGB(v/255, v/255, v/255); return v; }); loadParam('rough', 'roughness', material); loadParam('metal', 'metalness', material); loadParam('rectX', 'x', rectLight.position); // ... etc for all parameters } // Call on page load loadFromURL(); [/code] Подробнее здесь: [url]https://stackoverflow.com/questions/79365787/object-looks-translucent-even-though-opacity-is-1-in-three-js[/url]