2014-10-27 24 views
6

渲染我有:分册WebGL的

  1. 要显示
  2. 的4×4矩阵,其限定体积的间距/缩放/取向来显示
  3. 一个不透明度含有3D数据集以3D阵列传递函数
  4. 彩色传输函数

我想用ThreeJS做的体绘制(MIP,光线投射等)这个数据。是否有一些着色器/演示可用?

我应该直接在着色器级别还是在javascript中工作?

任何暗示/代码示例将是非常理解的, 最佳

+1

还有就是移动立方体例如:http://threejs.org/examples/#webgl_marchingcubes – 2014-10-27 19:37:57

+1

mrdoob还链接他在2012年做了一个gihub问题的例子:https://github.com/mrdoob/three.js/issues/1821 – Atrahasis 2015-07-04 21:18:33

回答

1

是否有一些着色器/演示可用?

Leandro R Barbagallo在WebGL中撰写了关于卷呈现的an in-depth blog post

+0

链接已损坏(甚至存档。org) – Kroltan 2017-04-07 13:48:32

+0

@Kroltan嗯,Archive.org链接为我工作 – 2017-04-13 12:30:04

+1

@Kroltan另外,这里是他的GitHub回购:https://github.com/lebarba/WebGLVolumeRendering – 2017-04-13 12:30:59

1

WAVE Client Renderer是一个基于Three.js的库,用于通过Ray Casting进行体绘制。

GPU加速Volume Ray Casting通常是实现多通道渲染。

着色器的第一遍非常简单。它将光线照射到立方体背面的纹理坐标(在对象坐标处)的位置。

你可以找到GLSL着色器的例子,下面有ejs模板。

firstPass.frag

precision mediump int; 

precision mediump float; 



varying vec4 backColor; 



void main(void) 

{ 

    gl_FragColor = backColor; 

} 

firstPass.vert

precision mediump int; 

precision mediump float; 



attribute vec4 vertColor; 



varying vec4 backColor; 

varying vec4 pos; 



void main(void) 

{ 

    backColor = vertColor; 



    pos = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 

    gl_Position = pos; 

} 

第二遍执行数据和最终图像的可视化的实际采样。

secondPass.vert

precision mediump int; 

precision mediump float; 



attribute vec4 vertColor; 



varying vec4 backColor; 

varying vec4 pos; 



void main(void) 

{ 

    backColor = vertColor; 



    pos = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 

    gl_Position = pos; 

} 

secondPass.frag

#ifdef GL_FRAGMENT_PRECISION_HIGH 

// highp is supported 

precision highp int; 

precision highp float; 

#else 

// high is not supported 

precision mediump int; 

precision mediump float; 

#endif 



varying vec4 frontColor; 

varying vec4 pos; 



uniform sampler2D uBackCoord; 

uniform sampler2D uTransferFunction; 

uniform sampler2D uSliceMaps[<%= maxTexturesNumber %>]; 



uniform float uNumberOfSlices; 

uniform float uMinGrayVal; 

uniform float uMaxGrayVal; 

uniform float uOpacityVal; 

uniform float uColorVal; 

uniform float uAbsorptionModeIndex; 

uniform float uSlicesOverX; 

uniform float uSlicesOverY; 

uniform float uSteps; 

// uniform int uAvailable_textures_number; 



//Acts like a texture3D using Z slices and trilinear filtering. 

float getVolumeValue(vec3 volpos) 

{ 

    float s1Original, s2Original, s1, s2; 

    float dx1, dy1; 

    // float dx2, dy2; 

    // float value; 



    vec2 texpos1,texpos2; 



    float slicesPerSprite = uSlicesOverX * uSlicesOverY; 



    s1Original = floor(volpos.z*uNumberOfSlices); 

    // s2Original = min(s1Original + 1.0, uNumberOfSlices); 



    int tex1Index = int(floor(s1Original/slicesPerSprite)); 

    // int tex2Index = int(floor(s2Original/slicesPerSprite)); 



    s1 = mod(s1Original, slicesPerSprite); 

    // s2 = mod(s2Original, slicesPerSprite); 



    dx1 = fract(s1/uSlicesOverX); 

    dy1 = floor(s1/uSlicesOverY)/uSlicesOverY; 



    // dx2 = fract(s2/uSlicesOverX); 

    // dy2 = floor(s2/uSlicesOverY)/uSlicesOverY; 



    texpos1.x = dx1+(volpos.x/uSlicesOverX); 

    texpos1.y = dy1+(volpos.y/uSlicesOverY); 



    // texpos2.x = dx2+(volpos.x/uSlicesOverX); 

    // texpos2.y = dy2+(volpos.y/uSlicesOverY); 



    float value1 = 0.0, value2 = 0.0; 

    // bool value1Set = false, value2Set = false; 



    // int numberOfSlicemaps = int(ceil(uNumberOfSlices/(uSlicesOverX * uSlicesOverY))); 



    <% for(var i=0; i < maxTexturesNumber; i++) { %> 

     if(tex1Index == <%=i%>) 

     { 

      value1 = texture2D(uSliceMaps[<%=i%>],texpos1).x; 

     } 



     <% if(i < maxTexturesNumber-1) { %> 

      else 

     <% } %> 

    <% } %> 



    return value1; 



    // for (int x = 0; x < gl_MaxTextureImageUnits-2; x++) 

    // { 

    //  if(x == numberOfSlicemaps) 

    //  { 

    //   break; 

    //  } 



    //  if(x == tex1Index) { 

    //   value1 = texture2D(uSliceMaps[x],texpos1).x; 

    //   value1Set = true; 

    //  } 



    //  if(x == tex2Index) { 

    //   value2 = texture2D(uSliceMaps[x],texpos2).x; 

    //   value2Set = true; 

    //  } 



    //  if(value1Set && value2Set) { 

    //   break; 

    //  } 



    // } 



    // return mix(value1, value2, fract(volpos.z*uNumberOfSlices)); 



} 



void main(void) 

{ 

vec2 texC = ((pos.xy/pos.w) + 1.0)/2.0; 



vec4 backColor = texture2D(uBackCoord,texC); 



vec3 dir = backColor.rgb - frontColor.rgb; 

//dir /= length(dir); 



vec4 vpos = frontColor; 



//  vec3 Step = dir/uSteps; 

vec3 Step = dir/uSteps; 



vec4 accum = vec4(0, 0, 0, 0); 

vec4 sample = vec4(0.0, 0.0, 0.0, 0.0); 

vec4 colorValue = vec4(0, 0, 0, 0); 

float biggest_gray_value = 0.0; 



float opacityFactor = uOpacityVal; 

float lightFactor = uColorVal; 



// const 4095 - just example of big number 

// It because expression i > uSteps impossible 

for(float i = 0.0; i < 4095.0; i+=1.0) 

{ 

// It because expression i > uSteps impossible 

    if(i == uSteps) { 

     break; 

    } 



    float gray_val = getVolumeValue(vpos.xyz); 



    if(gray_val < uMinGrayVal || gray_val > uMaxGrayVal) { 

     colorValue = vec4(0.0); 

    } else { 

     if(biggest_gray_value < gray_val) { 

      biggest_gray_value = gray_val; 

     } 



     if(uAbsorptionModeIndex == 0.0) 

     { 

      vec2 tf_pos; 

      tf_pos.x = (gray_val - uMinGrayVal)/(uMaxGrayVal - uMinGrayVal); 

      tf_pos.y = 0.5; 



      colorValue = texture2D(uTransferFunction,tf_pos); 

      //colorValue = vec4(tf_pos.x, tf_pos.x, tf_pos.x, 1.0); 



      sample.a = colorValue.a * opacityFactor; 

      sample.rgb = colorValue.rgb * uColorVal; 

      accum += sample; 



      if(accum.a>=1.0) 

       break; 



     } 



     if(uAbsorptionModeIndex == 1.0) 

     { 

      vec2 tf_pos; 

      tf_pos.x = (gray_val - uMinGrayVal)/(uMaxGrayVal - uMinGrayVal); 

      tf_pos.y = 0.5; 



      colorValue = texture2D(uTransferFunction,tf_pos); 

      //colorValue = vec4(tf_pos.x, tf_pos.x, tf_pos.x, 1.0); 



      sample.a = colorValue.a * opacityFactor * (1.0/uSteps); 

      sample.rgb = (1.0 - accum.a) * colorValue.rgb * sample.a * lightFactor; 

      accum += sample; 



      if(accum.a>=1.0) 

       break; 



     } 



     if(uAbsorptionModeIndex == 2.0) 

     { 

      vec2 tf_pos; 

      tf_pos.x = (biggest_gray_value - uMinGrayVal)/(uMaxGrayVal - uMinGrayVal); 

      tf_pos.y = 0.5; 



      colorValue = texture2D(uTransferFunction,tf_pos); 

      //colorValue = vec4(tf_pos.x, tf_pos.x, tf_pos.x, 1.0); 

      sample.a = colorValue.a * opacityFactor; 

      sample.rgb = colorValue.rgb * uColorVal; 



      accum = sample; 



     } 



    } 



    //advance the current position 

    vpos.xyz += Step; 



    //break if the position is greater than <1, 1, 1> 

    if(vpos.x > 1.0 || vpos.y > 1.0 || vpos.z > 1.0 || vpos.x < 0.0 || vpos.y < 0.0 || vpos.z < 0.0) 

    { 

     break; 

    } 



} 



gl_FragColor = accum; 



} 
+0

现在是更好吗? – 2017-04-07 13:52:17