2017-10-01 12 views
0

shader sur un écran sans cube et visualiser l'écran à partir de la position idéale en utilisant une caméra en perspective. Pourquoi? Qu'est-ce que je me trompe? Ma compréhension de la caméra cube est qu'elle se compose de 6 caméras en perspective avec fov = 90 et aspect = 1, chacune alignée sur un axe principal positif ou négatif, pour couvrir tout l'espace (entre le proche et le lointain). Il peut être positionné et pivoté librement (et même redimensionné et incliné, je suppose), et les images générées en tiendront compte. Les images sont une CubeTexture, qui est plus ou moins juste 6 textures carrées. La "taille de cube" dans les paramètres est la résolution des textures carrées. Ma compréhension du cube shader et de textureCube est que le vecteur fourni est traité comme une direction seulement, et que la couleur est obtenue en croisant un rayon dans cette direction (du centre) avec la surface du cube. Lors du positionnement d'une caméra en perspective, je crois comprendre que la position de la caméra est la position de l'œil, pas la position du plan de projection ou autre chose.La projection en perspective de GLSL textureCube sur une géométrie arbitraire de même origine ne conserve pas les lignes droites

Dans cet esprit, je attendre que: Si la géométrie de la surface de projection couvre toute la vue de la caméra d'observation (perspective) et la caméra d'observation est positionné dans la même origine que le shader cube utilise, alors même si la caméra de cube est tournée, l'image de la caméra de l'observateur sera la même pour toutes les géométries de surface de projection possibles (à l'exception de quelques artefacts d'échantillonnage/aliasing mineurs). Ce n'est que lorsque la caméra de l'observateur ou l'origine du cube shader ont été déplacées que je m'attendrais à des différences causées par la géométrie.

Au lieu de cela je reçois ce avec l'image d'une CubeCamera pivotée projetée sur un cylindre: The blue z axis is broken (presumably on the edge of the cylinder) Remarquez comment l'axe z bleu est « cassé » (probablement sur le bord du cylindre).

ce avec la même image projetée sur un cube: enter image description here

ceci avec l'image d'un CubeCamera sans rotation projetée sur un cylindre: enter image description here

et ce avec la même image projetée sur un cube: Le recadrage est différent pour chaque image (effectuée manuellement), mais les réglages et la rotation de la caméra de l'observateur sont les mêmes. On dirait que le CubeCamera sans rotation donne la même image pour le cube et le cylindre, tandis que le CubeCamera tourné donne des images très différentes.

Un code suffisant pour illustrer le problème est joint ci-dessous. J'ai également téléchargé une version en cours here.

<html> 
<head> 
    <title>Projectors problem test</title> 
    <script src="three.js-master/build/three.js"></script> 
</head> 

<body> 
<script> 
"use strict"; 

//Globals 
var renderer, simulatedScene, simulationCubeCamera, idealSimulatorScene, camera; 

(function main() { 
    //Renderer setup 
    document.body.style = "overflow: hidden;"; 
    var container = document.createElement("div"); 
    container.style = "position: absolute; top: 0; left: 0;" 
    document.body.appendChild(container); 
    renderer = new THREE.WebGLRenderer({antialias: true}); 
    renderer.setSize(window.innerWidth, window.innerHeight); 
    container.appendChild(renderer.domElement); 

    //Setup of simulated scene: 
    simulatedScene = new THREE.Scene(); 

    simulatedScene.add(new THREE.AxisHelper(500)); 

    //Cubecamera setup 
    simulationCubeCamera = new THREE.CubeCamera(5, 1000, 2048); 
    simulationCubeCamera.position.set(0,50,0); 
    //Comment out CubeCamera rotation to see the difference: 
    simulationCubeCamera.rotation.z = -0.25*Math.PI; 
    simulatedScene.add(simulationCubeCamera); 
    simulationCubeCamera.update(renderer, simulatedScene); 

    //Define (arbitrary mesh-based) projector screen geometry: 
    //Box geometry seems to work. Cylinder geometry works(?) for non-rotated  CubeCamera: 
    var screenGeometry = /*new THREE.BoxBufferGeometry(5,5,5, 1,1,1);*/new  THREE.CylinderBufferGeometry(5,5,5, 12288, 1); 

    //Make "ideal" projection on the screen geometry using cube shader: 
    idealSimulatorScene = new THREE.Scene(); 
    let cubeShader = THREE.ShaderLib.cube; 
    cubeShader.uniforms.tCube.value =  simulationCubeCamera.renderTarget.texture; 
    let idealScreenMat = new THREE.ShaderMaterial({ 
     uniforms: cubeShader.uniforms, 
     vertexShader: cubeShader.vertexShader, 
     fragmentShader: cubeShader.fragmentShader, 
     //depthWrite: false, 
     side: THREE.BackSide}); 

    var idealProjectorScreen = new THREE.Mesh(
     screenGeometry, 
     idealScreenMat 
    ); 
    idealSimulatorScene.add(idealProjectorScreen); 

    //Observer camera setup: 
    camera = new THREE.PerspectiveCamera(90, window.innerWidth/ window.innerHeight, 0.01, 15); 
    camera.lookAt(new THREE.Vector3(5,-50,35)); 

    renderer.render(idealSimulatorScene, camera); 
})(); 

</script> 
</body> 
</html> 

Répondre

0

Je l'ai résolu. Il s'avère que le cube shader est spécialisé pour l'affichage d'un cube de ciel. Ironiquement, la solution était une simplification.Je devais utiliser la position du monde au lieu de transformDirection:

Maintenant, mon vertex shader ressemble à ceci (après avoir remplacé des macros, des appels de fonction et les variables intermédiaires):

varying vec3 vWorldPosition; 

void main() { 
    //With transformDirection: 
    //vWorldPosition = normalize((modelMatrix * vec4(position, 0.0)).xyz); 
    //With just the world position (interpreted by the textureCube as a direction) 
    vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz; 

    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 
} 

Notez que la normalisation est retiré trop . textureCube gère les vecteurs non normalisés, et en fait les vecteurs interpolés ne seraient généralement pas normalisés de toute façon.

Je peux réutiliser l'ancien fragment shader.