2017-10-01 4 views
0

문제 : 회전 된 cubecamera의 그림을 큐브와 함께 투영 할 때 특정 직선 (이 예제에서는 파란색 z 축)이 직선으로 투영되지 않습니다. 쉐이더를 비 큐브 화면에 배치하고 원근 카메라를 사용하여 이상적인 위치에서 화면을 봅니다. 왜? 나는 무엇이 잘못 되었는가?동일한 원점에서 임의의 지오메트리에 대한 GLSL textureCube의 원근 투영은 직선을 유지하지 않습니다.

큐브 카메라에 대한 나의 이해는 fov = 90 및 aspect = 1 인 6 개의 원근 카메라로 구성되어 있으며, 각각은 양수 또는 음수 주축으로 정렬되어 전체 공간 (근거리와 원거리)을 포함합니다. 자유롭게 배치하고 회전시킬 수 있으며 (심지어 크기도 비뚤어 졌을 수도 있습니다.) 생성 된 이미지가 이것을 설명합니다. 이미지는 CubeTexture로 다소 정사각형 인 6 개의 텍스처입니다. 매개 변수의 "큐브 크기"는 정사각형 텍스처의 해상도입니다.

큐브 쉐이더와 텍스쳐 큐브에 대한 나의 이해는 제공된 벡터가 방향으로 만 취급되며 색상은 큐브의 표면과 그 방향 (중심에서)으로 교차하여 얻어지는 것입니다.

원근감있는 카메라를 배치 할 때, 카메라의 위치는 투영면 위치가 아닌 눈 위치임을 이해합니다. 이것을 염두

, I는 기대 : 투영면 형상 큐브 쉐이더 사용 동일한 원점에 위치하는 관찰자 (관점)와 카메라 관찰자 카메라의 전체 뷰를 포함하는 경우, 큐브 카메라가 회전 되더라도, 관찰자 카메라의 사진은 가능한 모든 영사 표면 지오메트리에 대해 동일합니다 (약간의 샘플링/앨리어싱 가공물 제외). 관찰자 카메라 또는 큐브 쉐이더 원점이 이동 한 경우에만 형상에 의한 차이가 발생할 것으로 예상됩니다.

대신 I는 실린더에 돌출 된 회전 CubeCamera의 이미지와 함께얻을 : The blue z axis is broken (presumably on the edge of the cylinder) 주의 푸른 Z 축 (아마도 실린더의 가장자리) "파손"방법. enter image description here

실린더 투영 회전하지 않은 CubeCamera의 이미지와

이 : 큐브 투영 동일한 이미지

enter image description here

및 큐브 투영 동일한 화상이 : enter image description here

자르기는 이미지마다 다릅니다 (수동으로 수행됨). 그러나 관찰자 카메라 설정 및 회전은 동일합니다. 회전되지 않은 CubeCamera는 큐브와 실린더에 대해 동일한 이미지를 제공하는 반면 회전 된 CubeCamera는 매우 다른 이미지를 제공합니다.

문제를 설명하기에 충분한 코드가 아래에 포함되어 있습니다. 또한 실행중인 버전 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> 

답변

0

해결했습니다. 큐브 셰이더는 하늘 큐브를 표시하는 데 특화된 것으로 나타났습니다. 아이러니 컬하게도 솔루션은 단순화되었습니다.난 그냥 대신 transformDirection의 세계 위치를 사용했다 :

이제 내 버텍스 쉐이더가 (일부 매크로, 함수 호출 및 중간 변수 대체 후) 다음과 같습니다 정상화도 제거됩니다

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); 
} 

공지 사항 . textureCube은 정규화되지 않은 벡터를 처리하며 실제로 보간 된 벡터는 일반적으로 어쨌든 정규화되지 않습니다.

이전 조각 쉐이더를 재사용 할 수 있습니다.

관련 문제