Обрезать том в Three.Js, давая черную область вместо внутреннего материала - PullRequest
1 голос
/ 09 мая 2019

Я пытаюсь обрезать том из всех трех плоскостей в ThreeJS, чтобы заглянуть во внутреннюю структуру.

Обрезка выполняется во вдохновенном виде и реализуется во фрагментном шейдере, отбрасывая рисунок пикселя, если он выходит за пределы ограничения:

gl_FragColor  = accumulatedColor;

if(worldSpaceCoords.x < xClippingPlaneMin) discard;
if(worldSpaceCoords.x < xClippingPlaneMin) discard;
if(worldSpaceCoords.z < zClippingPlaneMin) discard;
if(worldSpaceCoords.z > zClippingPlaneMax) discard;
if(worldSpaceCoords.y < yClippingPlaneMin) discard;
if(worldSpaceCoords.y > yClippingPlaneMax) discard;

И передали вышеуказанную информацию, пройдя через шейдерный материал (двухпроходная визуализация томов), как показано в приведенном ниже коде.

var materialFirstPass = new THREE.ShaderMaterial( {
                vertexShader: document.getElementById( 'vertexShaderFirstPass' ).textContent,
                fragmentShader: document.getElementById( 'fragmentShaderFirstPass' ).textContent,
                side: THREE.BackSide,

            } );
materialSecondPass = new THREE.ShaderMaterial( {
                vertexShader: document.getElementById( 'vertexShaderSecondPass' ).textContent,
                fragmentShader: document.getElementById( 'fragmentShaderSecondPass' ).textContent,
                side: THREE.FrontSide,
                depthWrite: false,



uniforms: { tex:  { type: "t", value: rtTexture },
                            cubeTex:  { type: "t", value: cubeTextures['bonsai'] },
                            transferTex:  { type: "t", value: transferTexture },
                            steps : {type: "1f" , value: guiControls.steps },
                            alphaCorrection : {type: "1f" , value: guiControls.alphaCorrection },
                            xClippingPlaneMin : {type: "1f" , value: guiControls.xClippingPlaneMin },
                            xClippingPlaneMax : {type: "1f" , value: guiControls.xClippingPlaneMax },
                            yClippingPlaneMin : {type: "1f" , value: guiControls.yClippingPlaneMin },
                            yClippingPlaneMax : {type: "1f" , value: guiControls.yClippingPlaneMax },
                            zClippingPlaneMin : {type: "1f" , value: guiControls.zClippingPlaneMin },
                            zClippingPlaneMax : {type: "1f" , value: guiControls.zClippingPlaneMax }
                        },
             });

sceneFirstPass = new THREE.Scene();
sceneSecondPass = new THREE.Scene();

var boxGeometry = new THREE.BoxGeometry(1.0, 1.0, 1.0);
boxGeometry.doubleSided = true;

var meshFirstPass = new THREE.Mesh( boxGeometry, materialFirstPass );
var meshSecondPass = new THREE.Mesh( boxGeometry, materialSecondPass );

sceneFirstPass.add( meshFirstPass );
sceneSecondPass.add( meshSecondPass );

Это выглядит чем-то вроде черной границы, которой я хочу быть на визуализированной поверхности. enter image description here enter image description here

Обновление : Мой мотив - заглянуть внутрь отсечения громкости со всех трех направлений X, Y и Z соответственно. Вы также можете думать о нарезке, как будто я хочу заглянуть в том или ином срезе.

Я смотрел на эти примеры Отсечение , Предварительное отсечение и Пересечение пересечения , но они не были особенно полезными, поэтому использовали метод отбрасывания и отсечения на основе координат чтобы достичь моей цели.

1 Ответ

1 голос
/ 16 мая 2019

Как обсуждалось в Three.js Discourse , проблема вашего подхода заключается в том, что, отбрасывая пиксель на фрагментном шейдере, вы вообще не допускаете его рендеринга.

Правильный подход состоял бы в том, чтобы предотвратить накапливание лучей марша цвета и альфа, если положение луча находится за пределами вашего отсечения. Координаты поля отсечения должны быть в пределах [0,1] пробела.

bool withinBoundaries( vec3 pos ) {
    if (
        pos.x < xClippingPlaneMin ||
        pos.y < yClippingPlaneMin ||
        pos.z < zClippingPlaneMin ||
        pos.x > xClippingPlaneMax ||
        pos.y > yClippingPlaneMax ||
        pos.z > zClippingPlaneMax
    ) return false;
    return true;
}

// ...

//Perform the ray marching iterations
for( int i = 0; i < MAX_STEPS; i++) {
    // ...
    if ( withinBoundaries( currentPosition ) ) {
        //Perform the composition.
        accumulatedColor += colorSample * alphaSample;
        //Store the alpha accumulated so far.
        accumulatedAlpha += alphaSample;
    }
    // ...
}

enter image description hereenter image description here

...