渲染我有:分册WebGL的
- 要显示
- 的4×4矩阵,其限定体积的间距/缩放/取向来显示
- 一个不透明度含有3D数据集以3D阵列传递函数
- 彩色传输函数
我想用ThreeJS做的体绘制(MIP,光线投射等)这个数据。是否有一些着色器/演示可用?
我应该直接在着色器级别还是在javascript中工作?
任何暗示/代码示例将是非常理解的, 最佳
渲染我有:分册WebGL的
我想用ThreeJS做的体绘制(MIP,光线投射等)这个数据。是否有一些着色器/演示可用?
我应该直接在着色器级别还是在javascript中工作?
任何暗示/代码示例将是非常理解的, 最佳
是否有一些着色器/演示可用?
Leandro R Barbagallo在WebGL中撰写了关于卷呈现的an in-depth blog post。
链接已损坏(甚至存档。org) – Kroltan 2017-04-07 13:48:32
@Kroltan嗯,Archive.org链接为我工作 – 2017-04-13 12:30:04
@Kroltan另外,这里是他的GitHub回购:https://github.com/lebarba/WebGLVolumeRendering – 2017-04-13 12:30:59
医学成像(DICOM,Nifti,对于现在NRRD支持)在WEBGL光线投射体绘制与AMI/THREEJS
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;
}
现在是更好吗? – 2017-04-07 13:52:17
还有就是移动立方体例如:http://threejs.org/examples/#webgl_marchingcubes – 2014-10-27 19:37:57
mrdoob还链接他在2012年做了一个gihub问题的例子:https://github.com/mrdoob/three.js/issues/1821 – Atrahasis 2015-07-04 21:18:33