2015-02-06 115 views
1

我试图让我的头绕着使用three.js和ray进行GLSL的体绘制。我有一些数据是从一个numpy数组合成的。体积渲染从另一个方向更透明

数据的立方体被呈现在一侧更不透明,毕业是在另一侧的透明 - 这样的(忽略线框,这只是针对位取向的) enter image description here

然而,当你从更透明的一端看立方体时,透明度似乎“阻挡”了透明度较低的一端(希望这是有道理的)。像这样: enter image description here

我不知道这是否相关,但我也有一个问题,当相机稍微在立方体内时,它会停止正常渲染。它切断离摄像机最近的位,如下所示: enter image description here 这是一个相关问题,还是仅仅是方法的限制。

的代码是在这里 https://github.com/niallrobinson/test-volume-rendering/blob/master/viewer.htmlhttps://github.com/niallrobinson/test-volume-rendering/blob/master/viewer.js https://github.com/niallrobinson/test-volume-rendering/blob/master/viewer.html

和第二遍着色器是这样的:事先大家

<script id="vertexShaderFirstPass" type="x-shader/x-vertex"> 
    varying vec3 worldSpaceCoords; 
    void main(){ 
     //Set the world space coordinates of the back faces vertices as output. 
     worldSpaceCoords = position + vec3(0.5, 0.5, 0.5); //move it from [-0.5;0.5] to [0,1] 
     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 
    } 
</script> 

<script id="fragmentShaderFirstPass" type="x-shader/x-fragment"> 
    varying vec3 worldSpaceCoords; 
    void main(){ 
     //The fragment's world space coordinates as fragment output. 
     gl_FragColor = vec4(worldSpaceCoords.x , worldSpaceCoords.y, worldSpaceCoords.z, 1); 
    } 
</script> 


<!-- second pass shaders --> 
<script id="vertexShaderSecondPass" type="x-shader/x-vertex"> 
    varying vec3 worldSpaceCoords; 
    varying vec4 projectedCoords; 

    void main() 
    { 
     worldSpaceCoords = (modelMatrix * vec4(position + vec3(0.5, 0.5, 0.5), 1.0)).xyz; 
     gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 
     projectedCoords = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 
    } 
</script> 

<script id="fragmentShaderSecondPass" type="x-shader/x-fragment"> 
    varying vec3 worldSpaceCoords; 
    varying vec4 projectedCoords; 

    uniform sampler2D firstPassTexture, dataTexture; //i.e. tex and cubeTex 
    uniform float steps; 
    uniform float alphaCorrection; 
    const int MAX_STEPS = 512; 

    vec3 dataDims = vec3(4, 4, 4); 

    vec4 sampleAs3DTexture(sampler2D tex, vec3 pos) { 
     // pos is in UV coords i.e. 0->1. We also want to interrogate out texture in the range 0->1 
     // however, our 3D dimensions are conceptually 4,4,4 
     float nTiles = dataDims.z; 
     float tileWidth = 1.0/nTiles; 
     float p = pos.y * tileWidth + pos.x/nTiles; 
     float q = pos.z; 

     lowp vec4 sample = texture2D(tex, vec2(p, q)); //I think this fn might convert from 255 range to 0->1 range 
     vec4 returnSample = vec4(0.7, 0., 0., sample.x * alphaCorrection); // alpha is 255 in png so overwrite 
     return returnSample; 
    } 

    // max 2d size is 4096 x 4096 

    void main(void) { 
     //Transform the coordinates it from [-1;1] to [0;1] 
     vec2 firstPassTexCoord = vec2(((projectedCoords.x/projectedCoords.w) + 1.0)/2.0, 
         ((projectedCoords.y/projectedCoords.w) + 1.0)/2.0); 

     //The back position is the world space position stored in the texture. 
     vec3 backPos = texture2D(firstPassTexture, firstPassTexCoord).xyz; 

     //The front position is the world space position of the second render pass. 
     vec3 frontPos = worldSpaceCoords; 

     //The direction from the front position to back position. 
     vec3 dir = backPos - frontPos; 

     float rayLength = length(dir); 

     //Calculate how long to increment in each step. 
     float delta = 1.0/steps; 

     //The increment in each direction for each step. 
     vec3 deltaDirection = normalize(dir) * delta; 
     float deltaDirectionLength = length(deltaDirection); 

     //Start the ray casting from the front position. 
     vec3 currentPosition = frontPos; 

     //The color accumulator. 
     vec4 accumulatedColor = vec4(0.0); 

     //The alpha value accumulated so far. 
     float accumulatedAlpha = 0.0; 

     //How long has the ray travelled so far. 
     float accumulatedLength = 0.0; 

     //vec4 dataSample; 
     vec4 dataSample; 

     float alphaSample; 

     //Perform the ray marching iterations 
     for(int i = 0; i < MAX_STEPS; i++){ 
      //Get the voxel intensity value from the 3D texture.  
      dataSample = sampleAs3DTexture(dataTexture, currentPosition); 

      //Allow the alpha correction customization 
      alphaSample = dataSample.a; 

      //Perform the composition. 
      accumulatedColor += (1.0 - accumulatedAlpha) * dataSample * alphaSample; 
      //accumulatedColor += dataSample; 

      //Store the alpha accumulated so far. 
      accumulatedAlpha += alphaSample; 

      //Advance the ray. 
      currentPosition += deltaDirection; 
      accumulatedLength += deltaDirectionLength; 

      //If the length traversed is more than the ray length, or if the alpha accumulated reaches 1.0 then exit. 
      if(accumulatedLength >= rayLength || accumulatedAlpha >= 1.0) 
       break; 
     } 
     gl_FragColor = accumulatedColor; 
    } 

</script> 

感谢

编辑:有点实验后,似乎问题在于只有多维数据集的外部正在呈现。如果我将一块数据放在多维数据集的中间,您什么也看不到。

编辑: Infact,其在正面上的唯一渲染数据。如果我逆转光线行进方向(即将其更改为朝向相机),则只能在背面观看它

+1

你的第三个画面是简单地在相机上近平面。您可以通过在相机定义中使用较小的数字来最小化效果,但不要将其设置得太小,否则会由于浮点精度错误而产生奇怪的伪像。 – 2015-02-09 12:54:07

+0

谢谢 - 这已经让剪辑的东西消失了 - 好的呼叫。顺便说一句,关于只渲染多维数据集外部的OP上的编辑。 – nrob 2015-02-09 15:15:12

回答

2

认为它已排序!从tex查询返回的数据是vec4。然后这被用来增加accumulatedColor。我改变accumulatedColor到VEC3只有靠.xyz增加它,这似乎这样的伎俩

谢谢大家谁看了看