2014-12-17 2 views
0

Я использую собственный шейдерный материал в своем приложении. Это расширенная (и переименованная) копия 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(); 
+0

1. Поздравляем с проведением небольших экспериментов по оплодотворению. Это единственный способ, которым вы действительно поймете webgl и three.js. 2. Вы видите ту же проблему, когда используете прозрачный 'MeshPhongMaterial' вместо своего пользовательского материала? – WestLangley

+0

1. Я учитель, поэтому мне это подходит лучше всего и помогает проиллюстрировать мою мысль, когда мне нужно обратиться за помощью. :) 2. Да. Версия 7 моей скрипки сворачивает «ShaderMaterial» для аналогично настроенного «MeshPhongMaterial». – TheJim01

+1

Было больше копания, попытка и т. Д. Я нашел http://stackoverflow.com/questions/15994944/transparent-objects-in-threejs, которые (хотя и на основе r57) указывают, что прозрачность основана на позиции объекта. Были некоторые тесты на это, и это правда. С некоторыми настройками, я получил камеру в положение, где - с плоскостями, уложенными таким же образом - синяя плоскость была самой близкой, но красный самолет все еще находился перед синим планом. Чудовищные результаты. – TheJim01

ответ

2

прозрачности артефакты, что вы видите не имеет ничего общего с вашим затенением. Такая же проблема будет возникать с MeshBasicMaterial.

Альфа-смешение прозрачных объектов в three.js зависит от заказа.

three.js сортирует объекты на основе их расстояния от камеры и визуализирует прозрачные объекты в порядке от дальнего до ближайшего. См. this related answer.

Следовательно, вы можете видеть артефакты при перемещении камеры и изменение порядка сортировки.

Возможны некоторые рабочие условия для конкретного случая, такие как управление порядком рендеринга, установка renderer.sortObjects = false или изменение свойств материала. Вам нужно поэкспериментировать, чтобы увидеть, что работает для вас.

three.js r.69

Смежные вопросы