我在我的应用程序中使用自定义着色器材质。它是THREE.ShaderLib['phong']
的扩展(并重命名)副本,除了透明度之外,它的效果很好。有时透明对象后面的对象是可见的,但通常会被剔除。为了确保我没有破坏某些东西,我创造了下面的小提琴。
当场景初始化时,一切看起来都应该是 - 三个透明平面,所有透明度都正常工作。即使移动场景,乍一看似乎也能正常工作。但突然间你可能会注意到一些爆裂声。减慢旋转表明,在某些角度,平面相对于彼此简单地停止透明。 (我已经添加了一个方便的" BREAK IT"按钮,将相机移动到一个这样的位置。)
那是怎么回事?我还在/实际上是在破坏什么吗?我已尝试单独初始化材料,但克隆似乎也在克隆材料。或者这只是这个材料如何运作的问题,我必须找到另一种方法来处理它?</ p>
小提琴:http://jsfiddle.net/TheJim01/rwt64fgd/
JS:
// BufferGeometry Tester
var hostDiv, scene, renderer, camera, root, controls, light;
var WIDTH = 500;//window.innerWidth,
HEIGHT = 500;//window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000;
function breakIt(){
camera.position.set(-25.759449580212017, -17.239852126859287, 39.2331270225625);
camera.lookAt(scene.position);
camera.up.set(0.07701484672816412, 0.8931831414880415, 0.44304919494903006);
}
function createBufferGeometryMesh(){
var geo = new THREE.BufferGeometry();
var tl = new THREE.Vector3(-10., 10., 0.),
tr = new THREE.Vector3(10., 10., 0.),
bl = new THREE.Vector3(-10., -10., 0.),
br = new THREE.Vector3(10., -10., 0.);
var n0 = new THREE.Vector3(0., 0., 1.);
var vertices =
[
tl.x, tl.y, tl.z,
tr.x, tr.y, tr.z,
br.x, br.y, br.z,
bl.x, bl.y, bl.z
],
normals =
[
n0.x, n0.y, n0.z,
n0.x, n0.y, n0.z,
n0.x, n0.y, n0.z,
n0.x, n0.y, n0.z
],
indices = [ 0, 2, 1, 0, 3, 2 ];
geo.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
geo.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( normals ), 3 ) );
geo.addAttribute( 'index', new THREE.BufferAttribute( new Uint32Array( indices ), 1 ) );
/*/
var mat = new THREE.MeshPhongMaterial( {
color: 0xffffff,
ambient: 0xffffff,
specular: 0xffffff,
shininess: 50,
side: THREE.DoubleSide
} );
/*/
var shader = THREE.ShaderLib['phong'];
var uniforms = null,
parameters = null;
uniforms = THREE.UniformsUtils.clone(shader.uniforms);
uniforms['diffuse'].value.setHex(0xcccccc);
uniforms['ambient'].value.setHex(0x0);
uniforms['emissive'].value.setHex(0x0);
uniforms['specular'].value.setHex(0xffffff);
uniforms['shininess'].value = 1;
uniforms['opacity'].value = 0.5;
uniforms['ambient'].value.convertGammaToLinear();
parameters = {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: uniforms,
lights: true,
fog: false,
side: THREE.DoubleSide,
blending: THREE.NormalBlending,
transparent: (uniforms['opacity'].value < 1.0)
};
var mat = new THREE.ShaderMaterial(parameters);
var msh = new THREE.Mesh(geo, mat);
return msh;
}
function init() {
hostDiv = document.createElement('div');
document.body.appendChild(hostDiv);
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor( 0x888888, 1 );
hostDiv.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 50;
camera.lookAt(scene.position);
controls = new THREE.TrackballControls(camera, renderer.domElement);
light = new THREE.PointLight(0xffffff, 1, 1000);
light.position.copy(camera.position);
scene.add(camera);
scene.add(light);
var square = createBufferGeometryMesh();
square.material.uniforms['diffuse'].value.setHex(0xff0000);
square.material.needsUpdate = true;
square.translateY(5);
square.translateX(5);
square.translateZ(5);
scene.add(square);
square = createBufferGeometryMesh();
square.material.uniforms['diffuse'].value.setHex(0x00ff00);
square.material.needsUpdate = true;
square.translateY(-5);
square.translateX(-5);
square.translateZ(-5);
scene.add(square);
square = createBufferGeometryMesh();
square.material.uniforms['diffuse'].value.setHex(0x0000ff);
square.material.needsUpdate = true;
square.scale.set(0.5, 0.5, 0.5);
scene.add(square);
animate();
var button = document.createElement('input');
button.setAttribute('type', 'button');
button.setAttribute('value', 'BREAK IT');
button.addEventListener('click', breakIt);
document.body.appendChild(button);
}
function render() {
renderer.render(scene, camera);
}
function animate() {
light.position.copy(camera.position);
requestAnimationFrame(animate);
render();
controls.update();
}
init();
答案 0 :(得分:2)
您看到的透明度工件与您的特定着色器无关。 MeshBasicMaterial
会出现同样的问题。
三个.js中透明对象的Alpha混合是依赖于顺序的。
three.js根据物体与相机的距离对物体进行分类,并按照从最远到最近的顺序渲染透明物体。请参阅this related answer。
因此,您可能会在移动相机时看到瑕疵,并且排序顺序会发生变化。
有一些特定于用例的解决方法可能会有所帮助,例如通过设置renderer.sortObjects = false
或更改材料属性来控制渲染顺序。你必须尝试看看哪些对你有用。
three.js r.69