Я использую собственный шейдерный материал в своем приложении. Это расширенная (и переименованная) копия THREE.ShaderLib['phong']
, и она отлично работает, за исключением прозрачности, которая является хитом или пропуском. Иногда объекты за прозрачным объектом видны, но часто их отбирают. Чтобы я не сломал что-то, я создал скрипку ниже.ShaderMaterial transparent
Когда сцена инициализируется, все выглядит как должно - три прозрачные плоскости, вся прозрачность работает правильно. Даже перемещение сцены вокруг кажется правильным, на первый взгляд. Но внезапно вы заметите, что некоторые выскакивают. Замедление вращения показывает, что под определенными углами плоскости просто перестают быть прозрачными относительно друг друга. (Я добавил удобную кнопку «BREAK IT», чтобы переместить камеру в такое положение.)
Так что же происходит? Я все-таки/что-то сломал? Я пробовал инициализировать материалы по отдельности, но клон, похоже, выполняет клонирование материалов. Или это просто вопрос о том, как этот материал работает, и мне нужно найти другой способ приблизиться к нему?
Fiddle: 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();
1. Поздравляем с проведением небольших экспериментов по оплодотворению. Это единственный способ, которым вы действительно поймете webgl и three.js. 2. Вы видите ту же проблему, когда используете прозрачный 'MeshPhongMaterial' вместо своего пользовательского материала? – WestLangley
1. Я учитель, поэтому мне это подходит лучше всего и помогает проиллюстрировать мою мысль, когда мне нужно обратиться за помощью. :) 2. Да. Версия 7 моей скрипки сворачивает «ShaderMaterial» для аналогично настроенного «MeshPhongMaterial». – TheJim01
Было больше копания, попытка и т. Д. Я нашел http://stackoverflow.com/questions/15994944/transparent-objects-in-threejs, которые (хотя и на основе r57) указывают, что прозрачность основана на позиции объекта. Были некоторые тесты на это, и это правда. С некоторыми настройками, я получил камеру в положение, где - с плоскостями, уложенными таким же образом - синяя плоскость была самой близкой, но красный самолет все еще находился перед синим планом. Чудовищные результаты. – TheJim01