zincjs 1.0.12 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zincjs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "ZincJS (Web-based-Zinc-Visualisation)",
|
|
5
5
|
"main": "build/zinc.js",
|
|
6
6
|
"directories": {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"build/zinc.js",
|
|
14
14
|
"build/zinc.frontend.js",
|
|
15
15
|
"build/zinc.js.map",
|
|
16
|
-
"webpack.config.js"
|
|
16
|
+
"webpack.config.js",
|
|
17
|
+
"src/shaders"
|
|
17
18
|
],
|
|
18
19
|
"scripts": {
|
|
19
20
|
"build-bundle": "webpack --config webpack.frontend.js; webpack --config webpack.backend.js",
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
const THREE = require('three');
|
|
2
|
+
|
|
3
|
+
const glslVersion = null;
|
|
4
|
+
|
|
5
|
+
const fs =
|
|
6
|
+
`
|
|
7
|
+
uniform sampler3D texture0;
|
|
8
|
+
uniform sampler3D texture1;
|
|
9
|
+
uniform vec4 lookup_offsets, lookup_scales;
|
|
10
|
+
uniform vec4 texture_scaling, normal_scaling;
|
|
11
|
+
varying vec4 diffuse, ambientGlobal, ambient;
|
|
12
|
+
|
|
13
|
+
void main()
|
|
14
|
+
{
|
|
15
|
+
vec4 color;
|
|
16
|
+
vec3 n, reflV, viewV, ldir;
|
|
17
|
+
float NdotL, NdotHV, len;
|
|
18
|
+
float att;
|
|
19
|
+
|
|
20
|
+
n = normalize(gl_TexCoord[3].xyz);
|
|
21
|
+
vec3 tex = vec3(texture3D(texture0, vec3(gl_TexCoord[0])));
|
|
22
|
+
color.xyz = tex.xyz;
|
|
23
|
+
color.w = gl_FrontMaterial.diffuse.w;
|
|
24
|
+
//Offset and scale to counteract effect of linear interpolation
|
|
25
|
+
//starting at the middle of the first texel and finishing in the
|
|
26
|
+
//middle of the last texel
|
|
27
|
+
vec4 offsetcolour = color.rgbr * lookup_scales + lookup_offsets;
|
|
28
|
+
vec4 dependentlookup = texture3D(texture1, vec3(offsetcolour));
|
|
29
|
+
color.w = color.w * dependentlookup.r;
|
|
30
|
+
vec4 unlitColour = color;
|
|
31
|
+
//Calculate a finite difference normal based on the magnitude of texture components used.
|
|
32
|
+
vec4 position_up, position_down, tex_up, tex_down;
|
|
33
|
+
vec4 stencil_xup = vec4(1, 0, 0, 0);
|
|
34
|
+
position_up = stencil_xup * texture_scaling + gl_TexCoord[0];
|
|
35
|
+
tex_up = texture3D(texture0, vec3(position_up));
|
|
36
|
+
vec4 stencil_xdown = vec4(-1, 0, 0, 0);
|
|
37
|
+
position_down = stencil_xdown * texture_scaling + gl_TexCoord[0];
|
|
38
|
+
tex_down = texture3D(texture0, vec3(position_down));
|
|
39
|
+
n.x = sqrt(dot(vec3(tex_up - tex_down), vec3(tex_up - tex_down)));
|
|
40
|
+
vec4 stencil_yup = vec4(0, 1, 0, 0);
|
|
41
|
+
position_up = stencil_yup * texture_scaling + gl_TexCoord[0];
|
|
42
|
+
tex_up = texture3D(texture0, vec3(position_up));
|
|
43
|
+
vec4 stencil_ydown = vec4(0, -1, 0, 0);
|
|
44
|
+
position_down = stencil_ydown * texture_scaling + gl_TexCoord[0];
|
|
45
|
+
tex_down = texture3D(texture0, vec3(position_down));
|
|
46
|
+
n.y = sqrt(dot(vec3(tex_up - tex_down), vec3(tex_up - tex_down)));
|
|
47
|
+
vec4 stencil_zup = vec4(0, 0, 1, 0);
|
|
48
|
+
position_up = stencil_zup * texture_scaling + gl_TexCoord[0];
|
|
49
|
+
tex_up = texture3D(texture0, vec3(position_up));
|
|
50
|
+
vec4 stencil_zdown = vec4(0, 0, -1, 0);
|
|
51
|
+
position_down = stencil_zdown * texture_scaling + gl_TexCoord[0];
|
|
52
|
+
tex_down = texture3D(texture0, vec3(position_down));
|
|
53
|
+
n.z = sqrt(dot(vec3(tex_up - tex_down), vec3(tex_up - tex_down)));
|
|
54
|
+
n = n * vec3(normal_scaling);
|
|
55
|
+
vec3 eyeNormal = gl_NormalMatrix * n;
|
|
56
|
+
if (!gl_FrontFacing)
|
|
57
|
+
eyeNormal.z = -1.0 * eyeNormal.z;
|
|
58
|
+
float normalMag = dot (eyeNormal, eyeNormal);
|
|
59
|
+
eyeNormal = normalize(eyeNormal);
|
|
60
|
+
len = length(vec3(gl_TexCoord[1]));
|
|
61
|
+
att = 1.0 / (gl_LightSource[0].constantAttenuation +
|
|
62
|
+
gl_LightSource[0].linearAttenuation * len +
|
|
63
|
+
gl_LightSource[0].quadraticAttenuation * len * len);
|
|
64
|
+
//Calculate attenuation.
|
|
65
|
+
NdotL = (dot(eyeNormal, normalize(gl_TexCoord[1].xyz)));
|
|
66
|
+
if (!gl_FrontFacing)
|
|
67
|
+
NdotL = abs(NdotL);
|
|
68
|
+
color += att * (diffuse *NdotL + ambient);
|
|
69
|
+
reflV = reflect(-normalize(gl_TexCoord[1].xyz), eyeNormal);
|
|
70
|
+
NdotHV = max(dot(reflV, normalize(gl_TexCoord[2].xyz)),0.0);
|
|
71
|
+
color += att * gl_FrontMaterial.specular * gl_LightSource[0].specular *
|
|
72
|
+
pow(NdotHV, gl_FrontMaterial.shininess);
|
|
73
|
+
//Alpha value;
|
|
74
|
+
color.w = unlitColour.w * normalMag;
|
|
75
|
+
gl_FragColor = color;
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
const vs =
|
|
80
|
+
`
|
|
81
|
+
varying vec4 diffuse, ambientGlobal, ambient;
|
|
82
|
+
uniform vec4 texture_scaling;
|
|
83
|
+
|
|
84
|
+
void main()
|
|
85
|
+
{
|
|
86
|
+
vec3 pos;
|
|
87
|
+
diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
|
|
88
|
+
ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
|
|
89
|
+
ambientGlobal = gl_LightModel.ambient * gl_FrontMaterial.ambient;
|
|
90
|
+
vec4 ecPos = gl_ModelViewMatrix * gl_Vertex;
|
|
91
|
+
vec3 aux = gl_LightSource[0].position.xyz - ecPos.xyz;
|
|
92
|
+
gl_TexCoord[0] = texture_scaling * gl_MultiTexCoord0;
|
|
93
|
+
gl_TexCoord[3].xyz = normalize(gl_NormalMatrix * gl_Normal);
|
|
94
|
+
gl_TexCoord[2].xyz = vec3(normalize(-ecPos));
|
|
95
|
+
gl_TexCoord[1].xyz = aux;
|
|
96
|
+
gl_FrontColor = gl_Color;
|
|
97
|
+
gl_BackColor = gl_Color;
|
|
98
|
+
gl_FrontSecondaryColor = vec4(1.0);
|
|
99
|
+
gl_BackSecondaryColor = vec4(0.0);
|
|
100
|
+
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
|
|
104
|
+
const getUniforms = function() {
|
|
105
|
+
return {
|
|
106
|
+
u_size: { value: new THREE.Vector3( 1, 1, 1 ) },
|
|
107
|
+
u_renderstyle: { value: 0 },
|
|
108
|
+
u_renderthreshold: { value: 0.5 },
|
|
109
|
+
u_clim: { value: new THREE.Vector2( 1, 1 ) },
|
|
110
|
+
u_data: { value: null },
|
|
111
|
+
u_cmdata: { value: null },
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
exports.fs = fs;
|
|
116
|
+
exports.vs = vs;
|
|
117
|
+
exports.glslVersion = glslVersion;
|
|
118
|
+
exports.getUniforms = getUniforms;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const THREE = require('three');
|
|
2
|
+
|
|
3
|
+
const glslVersion = THREE.GLSL3;
|
|
4
|
+
|
|
5
|
+
const fs =
|
|
6
|
+
`
|
|
7
|
+
precision highp float;
|
|
8
|
+
precision highp int;
|
|
9
|
+
precision highp sampler2DArray;
|
|
10
|
+
|
|
11
|
+
uniform sampler2DArray diffuse;
|
|
12
|
+
in vec3 vUw;
|
|
13
|
+
|
|
14
|
+
out vec4 outColor;
|
|
15
|
+
|
|
16
|
+
void main() {
|
|
17
|
+
|
|
18
|
+
vec4 color = texture( diffuse, vUw );
|
|
19
|
+
|
|
20
|
+
// lighten a bit
|
|
21
|
+
outColor = vec4( color.rgb + .2, 0.2 );
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
const vs =
|
|
27
|
+
`
|
|
28
|
+
out vec3 vUw;
|
|
29
|
+
uniform float depth;
|
|
30
|
+
|
|
31
|
+
void main() {
|
|
32
|
+
|
|
33
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
34
|
+
|
|
35
|
+
vUw.xyz = vec3(position.x, position.y, position.z * depth);
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
const getUniforms = function() {
|
|
41
|
+
return {
|
|
42
|
+
diffuse: { value: undefined },
|
|
43
|
+
depth: { value: 1 },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
exports.fs = fs;
|
|
49
|
+
exports.vs = vs;
|
|
50
|
+
exports.glslVersion = glslVersion;
|
|
51
|
+
exports.getUniforms = getUniforms;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const THREE = require('three');
|
|
2
|
+
|
|
3
|
+
const glslVersion = THREE.GLSL3;
|
|
4
|
+
|
|
5
|
+
const fs =
|
|
6
|
+
`
|
|
7
|
+
precision highp float;
|
|
8
|
+
precision highp int;
|
|
9
|
+
precision highp sampler2DArray;
|
|
10
|
+
|
|
11
|
+
uniform sampler2DArray diffuse;
|
|
12
|
+
in vec3 vUw;
|
|
13
|
+
|
|
14
|
+
out vec4 outColor;
|
|
15
|
+
|
|
16
|
+
void main() {
|
|
17
|
+
|
|
18
|
+
vec4 color = texture( diffuse, vUw );
|
|
19
|
+
|
|
20
|
+
// lighten a bit
|
|
21
|
+
outColor = vec4( color.rgb + .2, 1.0 );
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
const vs =
|
|
27
|
+
`
|
|
28
|
+
out vec3 vUw;
|
|
29
|
+
uniform float depth;
|
|
30
|
+
uniform vec3 slide;
|
|
31
|
+
|
|
32
|
+
void main() {
|
|
33
|
+
|
|
34
|
+
vec3 slidePos = position.xyz;
|
|
35
|
+
|
|
36
|
+
if (slide.x > 0.0)
|
|
37
|
+
slidePos = vec3(slide.x, position.x, position.y);
|
|
38
|
+
if (slide.y > 0.0)
|
|
39
|
+
slidePos = vec3(position.x, slide.y, position.y);
|
|
40
|
+
if (slide.z > 0.0)
|
|
41
|
+
slidePos = vec3(position.x, position.y, slide.z);
|
|
42
|
+
|
|
43
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( slidePos, 1.0 );
|
|
44
|
+
|
|
45
|
+
vUw.xyz = vec3(slidePos.x, slidePos.y, slidePos.z * depth);
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
49
|
+
|
|
50
|
+
const getUniforms = function() {
|
|
51
|
+
return {
|
|
52
|
+
diffuse: { value: undefined },
|
|
53
|
+
depth: { value: 1 },
|
|
54
|
+
slide: { value: new THREE.Vector3( 0, 0, 1 ) }
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
exports.fs = fs;
|
|
59
|
+
exports.vs = vs;
|
|
60
|
+
exports.glslVersion = glslVersion;
|
|
61
|
+
exports.getUniforms = getUniforms;
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
const THREE = require('three');
|
|
2
|
+
|
|
3
|
+
const glslVersion = null;
|
|
4
|
+
|
|
5
|
+
const fs =
|
|
6
|
+
`
|
|
7
|
+
precision highp float;
|
|
8
|
+
precision highp sampler2DArray;
|
|
9
|
+
precision highp sampler2D;
|
|
10
|
+
|
|
11
|
+
uniform vec3 u_size;
|
|
12
|
+
uniform int u_renderstyle;
|
|
13
|
+
uniform float u_renderthreshold;
|
|
14
|
+
uniform vec2 u_clim;
|
|
15
|
+
|
|
16
|
+
uniform sampler2DArray u_data;
|
|
17
|
+
uniform sampler2D u_cmdata;
|
|
18
|
+
|
|
19
|
+
varying vec3 v_position;
|
|
20
|
+
varying vec4 v_nearpos;
|
|
21
|
+
varying vec4 v_farpos;
|
|
22
|
+
|
|
23
|
+
// The maximum distance through our rendering volume is sqrt(3).
|
|
24
|
+
const int MAX_STEPS = 887; // 887 for 512^3, 1774 for 1024^3
|
|
25
|
+
const int REFINEMENT_STEPS = 4;
|
|
26
|
+
const float relative_step_size = 1.0;
|
|
27
|
+
const vec4 ambient_color = vec4(0.2, 0.4, 0.2, 1.0);
|
|
28
|
+
const vec4 diffuse_color = vec4(0.8, 0.2, 0.2, 1.0);
|
|
29
|
+
const vec4 specular_color = vec4(1.0, 1.0, 1.0, 1.0);
|
|
30
|
+
const float shininess = 40.0;
|
|
31
|
+
|
|
32
|
+
void cast_mip(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray);
|
|
33
|
+
void cast_iso(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray);
|
|
34
|
+
|
|
35
|
+
vec3 sample1(vec3 texcoords);
|
|
36
|
+
vec4 apply_colormap(float val);
|
|
37
|
+
vec4 add_lighting(float val, vec3 loc, vec3 step, vec3 view_ray);
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
void main() {
|
|
41
|
+
// Normalize clipping plane info
|
|
42
|
+
vec3 farpos = v_farpos.xyz / v_farpos.w;
|
|
43
|
+
vec3 nearpos = v_nearpos.xyz / v_nearpos.w;
|
|
44
|
+
|
|
45
|
+
// Calculate unit vector pointing in the view direction through this fragment.
|
|
46
|
+
vec3 view_ray = normalize(nearpos.xyz - farpos.xyz);
|
|
47
|
+
|
|
48
|
+
// Compute the (negative) distance to the front surface or near clipping plane.
|
|
49
|
+
// v_position is the back face of the cuboid, so the initial distance calculated in the dot
|
|
50
|
+
// product below is the distance from near clip plane to the back of the cuboid
|
|
51
|
+
float distance = dot(nearpos - v_position, view_ray);
|
|
52
|
+
distance = max(distance, min((-0.5 - v_position.x) / view_ray.x,
|
|
53
|
+
(u_size.x - 0.5 - v_position.x) / view_ray.x));
|
|
54
|
+
distance = max(distance, min((-0.5 - v_position.y) / view_ray.y,
|
|
55
|
+
(u_size.y - 0.5 - v_position.y) / view_ray.y));
|
|
56
|
+
distance = max(distance, min((-0.5 - v_position.z) / view_ray.z,
|
|
57
|
+
(u_size.z - 0.5 - v_position.z) / view_ray.z));
|
|
58
|
+
|
|
59
|
+
// Now we have the starting position on the front surface
|
|
60
|
+
vec3 front = v_position + view_ray * distance;
|
|
61
|
+
|
|
62
|
+
// Decide how many steps to take
|
|
63
|
+
int nsteps = int(-distance / relative_step_size + 0.5);
|
|
64
|
+
if ( nsteps < 1 )
|
|
65
|
+
discard;
|
|
66
|
+
|
|
67
|
+
// Get starting location and step vector in texture coordinates
|
|
68
|
+
vec3 step = ((v_position - front) / u_size) / float(nsteps);
|
|
69
|
+
vec3 start_loc = front / u_size;
|
|
70
|
+
|
|
71
|
+
// For testing: show the number of steps. This helps to establish
|
|
72
|
+
// whether the rays are correctly oriented
|
|
73
|
+
//gl_FragColor = vec4(0.0, float(nsteps) / 1.0 / u_size.x, 1.0, 1.0);
|
|
74
|
+
//return;
|
|
75
|
+
|
|
76
|
+
if (u_renderstyle == 0)
|
|
77
|
+
cast_mip(start_loc, step, nsteps, view_ray);
|
|
78
|
+
else if (u_renderstyle == 1)
|
|
79
|
+
cast_iso(start_loc, step, nsteps, view_ray);
|
|
80
|
+
|
|
81
|
+
if (gl_FragColor.a < 0.05)
|
|
82
|
+
discard;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
vec3 sample1(vec3 texcoords) {
|
|
87
|
+
/* Sample float value from a 3D texture. Assumes intensity data. */
|
|
88
|
+
return texture(u_data, texcoords.xyz).rgb;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
vec4 apply_colormap(float val) {
|
|
93
|
+
val = (val - u_clim[0]) / (u_clim[1] - u_clim[0]);
|
|
94
|
+
return texture2D(u_cmdata, vec2(val, 0.5));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
void cast_mip(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray) {
|
|
99
|
+
|
|
100
|
+
float max_val = -1e6;
|
|
101
|
+
int max_i = 100;
|
|
102
|
+
vec3 loc = start_loc;
|
|
103
|
+
|
|
104
|
+
// Enter the raycasting loop. In WebGL 1 the loop index cannot be compared with
|
|
105
|
+
// non-constant expression. So we use a hard-coded max, and an additional condition
|
|
106
|
+
// inside the loop.
|
|
107
|
+
for (int iter=0; iter<MAX_STEPS; iter++) {
|
|
108
|
+
if (iter >= nsteps)
|
|
109
|
+
break;
|
|
110
|
+
// Sample from the 3D texture
|
|
111
|
+
vec3 val = sample1(loc);
|
|
112
|
+
float avg = (val.x + val.y + val.z) / 3.0;
|
|
113
|
+
// Apply MIP operation
|
|
114
|
+
if (val > max_val) {
|
|
115
|
+
max_val = val;
|
|
116
|
+
max_i = iter;
|
|
117
|
+
}
|
|
118
|
+
// Advance location deeper into the volume
|
|
119
|
+
loc += step;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Refine location, gives crispier images
|
|
123
|
+
vec3 iloc = start_loc + step * (float(max_i) - 0.5);
|
|
124
|
+
vec3 istep = step / float(REFINEMENT_STEPS);
|
|
125
|
+
for (int i=0; i<REFINEMENT_STEPS; i++) {
|
|
126
|
+
max_val = max(max_val, sample1(iloc));
|
|
127
|
+
iloc += istep;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Resolve final color
|
|
131
|
+
gl_FragColor = apply_colormap(max_val);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
void cast_iso(vec3 start_loc, vec3 step, int nsteps, vec3 view_ray) {
|
|
136
|
+
|
|
137
|
+
gl_FragColor = vec4(0.0); // init transparent
|
|
138
|
+
vec4 color3 = vec4(0.0); // final color
|
|
139
|
+
vec3 dstep = 1.5 / u_size; // step to sample derivative
|
|
140
|
+
vec3 loc = start_loc;
|
|
141
|
+
|
|
142
|
+
float low_threshold = u_renderthreshold - 0.02 * (u_clim[1] - u_clim[0]);
|
|
143
|
+
|
|
144
|
+
// Enter the raycasting loop. In WebGL 1 the loop index cannot be compared with
|
|
145
|
+
// non-constant expression. So we use a hard-coded max, and an additional condition
|
|
146
|
+
// inside the loop.
|
|
147
|
+
for (int iter=0; iter<MAX_STEPS; iter++) {
|
|
148
|
+
if (iter >= nsteps)
|
|
149
|
+
break;
|
|
150
|
+
|
|
151
|
+
// Sample from the 3D texture
|
|
152
|
+
float val = sample1(loc);
|
|
153
|
+
|
|
154
|
+
if (val > low_threshold) {
|
|
155
|
+
// Take the last interval in smaller steps
|
|
156
|
+
vec3 iloc = loc - 0.5 * step;
|
|
157
|
+
vec3 istep = step / float(REFINEMENT_STEPS);
|
|
158
|
+
for (int i=0; i<REFINEMENT_STEPS; i++) {
|
|
159
|
+
val = sample1(iloc);
|
|
160
|
+
if (val > u_renderthreshold) {
|
|
161
|
+
gl_FragColor = add_lighting(val, iloc, dstep, view_ray);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
iloc += istep;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Advance location deeper into the volume
|
|
169
|
+
loc += step;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
vec4 add_lighting(float val, vec3 loc, vec3 step, vec3 view_ray)
|
|
175
|
+
{
|
|
176
|
+
// Calculate color by incorporating lighting
|
|
177
|
+
|
|
178
|
+
// View direction
|
|
179
|
+
vec3 V = normalize(view_ray);
|
|
180
|
+
|
|
181
|
+
// calculate normal vector from gradient
|
|
182
|
+
vec3 N;
|
|
183
|
+
float val1, val2;
|
|
184
|
+
val1 = sample1(loc + vec3(-step[0], 0.0, 0.0));
|
|
185
|
+
val2 = sample1(loc + vec3(+step[0], 0.0, 0.0));
|
|
186
|
+
N[0] = val1 - val2;
|
|
187
|
+
val = max(max(val1, val2), val);
|
|
188
|
+
val1 = sample1(loc + vec3(0.0, -step[1], 0.0));
|
|
189
|
+
val2 = sample1(loc + vec3(0.0, +step[1], 0.0));
|
|
190
|
+
N[1] = val1 - val2;
|
|
191
|
+
val = max(max(val1, val2), val);
|
|
192
|
+
val1 = sample1(loc + vec3(0.0, 0.0, -step[2]));
|
|
193
|
+
val2 = sample1(loc + vec3(0.0, 0.0, +step[2]));
|
|
194
|
+
N[2] = val1 - val2;
|
|
195
|
+
val = max(max(val1, val2), val);
|
|
196
|
+
|
|
197
|
+
float gm = length(N); // gradient magnitude
|
|
198
|
+
N = normalize(N);
|
|
199
|
+
|
|
200
|
+
// Flip normal so it points towards viewer
|
|
201
|
+
float Nselect = float(dot(N, V) > 0.0);
|
|
202
|
+
N = (2.0 * Nselect - 1.0) * N; // == Nselect * N - (1.0-Nselect)*N;
|
|
203
|
+
|
|
204
|
+
// Init colors
|
|
205
|
+
vec4 ambient_color = vec4(0.0, 0.0, 0.0, 0.0);
|
|
206
|
+
vec4 diffuse_color = vec4(0.0, 0.0, 0.0, 0.0);
|
|
207
|
+
vec4 specular_color = vec4(0.0, 0.0, 0.0, 0.0);
|
|
208
|
+
|
|
209
|
+
// note: could allow multiple lights
|
|
210
|
+
for (int i=0; i<1; i++)
|
|
211
|
+
{
|
|
212
|
+
// Get light direction (make sure to prevent zero devision)
|
|
213
|
+
vec3 L = normalize(view_ray); //lightDirs[i];
|
|
214
|
+
float lightEnabled = float( length(L) > 0.0 );
|
|
215
|
+
L = normalize(L + (1.0 - lightEnabled));
|
|
216
|
+
|
|
217
|
+
// Calculate lighting properties
|
|
218
|
+
float lambertTerm = clamp(dot(N, L), 0.0, 1.0);
|
|
219
|
+
vec3 H = normalize(L+V); // Halfway vector
|
|
220
|
+
float specularTerm = pow(max(dot(H, N), 0.0), shininess);
|
|
221
|
+
|
|
222
|
+
// Calculate mask
|
|
223
|
+
float mask1 = lightEnabled;
|
|
224
|
+
|
|
225
|
+
// Calculate colors
|
|
226
|
+
ambient_color += mask1 * ambient_color; // * gl_LightSource[i].ambient;
|
|
227
|
+
diffuse_color += mask1 * lambertTerm;
|
|
228
|
+
specular_color += mask1 * specularTerm * specular_color;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Calculate final color by componing different components
|
|
232
|
+
vec4 final_color;
|
|
233
|
+
vec4 color = apply_colormap(val);
|
|
234
|
+
final_color = color * (ambient_color + diffuse_color) + specular_color;
|
|
235
|
+
final_color.a = color.a;
|
|
236
|
+
return final_color;
|
|
237
|
+
}
|
|
238
|
+
`;
|
|
239
|
+
|
|
240
|
+
const vs =
|
|
241
|
+
`
|
|
242
|
+
varying vec4 v_nearpos;
|
|
243
|
+
varying vec4 v_farpos;
|
|
244
|
+
varying vec3 v_position;
|
|
245
|
+
|
|
246
|
+
void main() {
|
|
247
|
+
// Prepare transforms to map to "camera view". See also:
|
|
248
|
+
// https://threejs.org/docs/#api/renderers/webgl/WebGLProgram
|
|
249
|
+
mat4 viewtransformf = modelViewMatrix;
|
|
250
|
+
mat4 viewtransformi = inverse(modelViewMatrix);
|
|
251
|
+
|
|
252
|
+
// Project local vertex coordinate to camera position. Then do a step
|
|
253
|
+
// backward (in cam coords) to the near clipping plane, and project back. Do
|
|
254
|
+
// the same for the far clipping plane. This gives us all the information we
|
|
255
|
+
// need to calculate the ray and truncate it to the viewing cone.
|
|
256
|
+
vec4 position4 = vec4(position, 1.0);
|
|
257
|
+
vec4 pos_in_cam = viewtransformf * position4;
|
|
258
|
+
|
|
259
|
+
// Intersection of ray and near clipping plane (z = -1 in clip coords)
|
|
260
|
+
pos_in_cam.z = -pos_in_cam.w;
|
|
261
|
+
v_nearpos = viewtransformi * pos_in_cam;
|
|
262
|
+
|
|
263
|
+
// Intersection of ray and far clipping plane (z = +1 in clip coords)
|
|
264
|
+
pos_in_cam.z = pos_in_cam.w;
|
|
265
|
+
v_farpos = viewtransformi * pos_in_cam;
|
|
266
|
+
|
|
267
|
+
// Set varyings and output pos
|
|
268
|
+
v_position = position;
|
|
269
|
+
gl_Position = projectionMatrix * viewMatrix * modelMatrix * position4;
|
|
270
|
+
}
|
|
271
|
+
`;
|
|
272
|
+
|
|
273
|
+
const getUniforms = function() {
|
|
274
|
+
return {
|
|
275
|
+
u_size: { value: new THREE.Vector3( 1, 1, 1 ) },
|
|
276
|
+
u_renderstyle: { value: 0 },
|
|
277
|
+
u_renderthreshold: { value: 0.5 },
|
|
278
|
+
u_clim: { value: new THREE.Vector2( 1, 1 ) },
|
|
279
|
+
u_data: { value: null },
|
|
280
|
+
u_cmdata: { value: null },
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
exports.fs = fs;
|
|
285
|
+
exports.vs = vs;
|
|
286
|
+
exports.glslVersion = glslVersion;
|
|
287
|
+
exports.getUniforms = getUniforms;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const THREE = require('three');
|
|
2
|
+
|
|
3
|
+
const glslVersion = THREE.GLSL3;
|
|
4
|
+
|
|
5
|
+
const fs =
|
|
6
|
+
`
|
|
7
|
+
precision highp float;
|
|
8
|
+
precision highp int;
|
|
9
|
+
precision highp sampler2DArray;
|
|
10
|
+
|
|
11
|
+
uniform sampler2DArray diffuse;
|
|
12
|
+
in vec3 vUw;
|
|
13
|
+
|
|
14
|
+
out vec4 outColor;
|
|
15
|
+
|
|
16
|
+
float boneMag(vec4 color);
|
|
17
|
+
|
|
18
|
+
void main() {
|
|
19
|
+
|
|
20
|
+
vec4 color = texture( diffuse, vUw );
|
|
21
|
+
float noneBone = boneMag(color);
|
|
22
|
+
|
|
23
|
+
float alpha = 1;
|
|
24
|
+
if (noneBone > 0.2)
|
|
25
|
+
alpha = 0.0;
|
|
26
|
+
// lighten a bit
|
|
27
|
+
outColor = vec4( color.rgb + .2, alpha );
|
|
28
|
+
//outColor.rgb = vec3(noneBone);
|
|
29
|
+
//outColor.a = 1.0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
float boneMag(vec4 color) {
|
|
34
|
+
vec3 offsetColor = color.rgb - vec3(0.9, 0.75, 0.6);
|
|
35
|
+
return length(offsetColor);
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
const vs =
|
|
40
|
+
`
|
|
41
|
+
out vec3 vUw;
|
|
42
|
+
uniform float depth;
|
|
43
|
+
|
|
44
|
+
void main() {
|
|
45
|
+
|
|
46
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
47
|
+
|
|
48
|
+
vUw.xyz = vec3(position.x, position.y, position.z * depth);
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
const getUniforms = function() {
|
|
54
|
+
return {
|
|
55
|
+
diffuse: { value: undefined },
|
|
56
|
+
depth: { value: 1 },
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
exports.fs = fs;
|
|
62
|
+
exports.vs = vs;
|
|
63
|
+
exports.glslVersion = glslVersion;
|
|
64
|
+
exports.getUniforms = getUniforms;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const THREE = require('three');
|
|
2
|
+
|
|
3
|
+
const glslVersion = THREE.GLSL3;
|
|
4
|
+
|
|
5
|
+
const fs =
|
|
6
|
+
`
|
|
7
|
+
precision highp int;
|
|
8
|
+
precision highp float;
|
|
9
|
+
|
|
10
|
+
uniform highp sampler2DArray diffuse;
|
|
11
|
+
uniform ivec3 volume_dims;
|
|
12
|
+
uniform float depth;
|
|
13
|
+
|
|
14
|
+
in vec3 vray_dir;
|
|
15
|
+
flat in vec3 transformed_eye;
|
|
16
|
+
|
|
17
|
+
out vec4 color;
|
|
18
|
+
|
|
19
|
+
vec2 intersect_box(vec3 orig, vec3 dir) {
|
|
20
|
+
const vec3 box_min = vec3(0);
|
|
21
|
+
const vec3 box_max = vec3(1);
|
|
22
|
+
vec3 inv_dir = 1.0 / dir;
|
|
23
|
+
vec3 tmin_tmp = (box_min - orig) * inv_dir;
|
|
24
|
+
vec3 tmax_tmp = (box_max - orig) * inv_dir;
|
|
25
|
+
vec3 tmin = min(tmin_tmp, tmax_tmp);
|
|
26
|
+
vec3 tmax = max(tmin_tmp, tmax_tmp);
|
|
27
|
+
float t0 = max(tmin.x, max(tmin.y, tmin.z));
|
|
28
|
+
float t1 = min(tmax.x, min(tmax.y, tmax.z));
|
|
29
|
+
return vec2(t0, t1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
void main(void) {
|
|
33
|
+
// Step 1: Normalize the view ray
|
|
34
|
+
vec3 ray_dir = normalize(vray_dir);
|
|
35
|
+
|
|
36
|
+
// Step 2: Intersect the ray with the volume bounds to find the interval
|
|
37
|
+
// along the ray overlapped by the volume.
|
|
38
|
+
vec2 t_hit = intersect_box(transformed_eye, ray_dir);
|
|
39
|
+
if (t_hit.x > t_hit.y) {
|
|
40
|
+
discard;
|
|
41
|
+
}
|
|
42
|
+
// We don't want to sample voxels behind the eye if it's
|
|
43
|
+
// inside the volume, so keep the starting point at or in front
|
|
44
|
+
// of the eye
|
|
45
|
+
t_hit.x = max(t_hit.x, 0.0);
|
|
46
|
+
|
|
47
|
+
// Step 3: Compute the step size to march through the volume grid
|
|
48
|
+
vec3 dt_vec = 1.0 / (vec3(volume_dims) * abs(ray_dir));
|
|
49
|
+
float dt = min(dt_vec.x, min(dt_vec.y, dt_vec.z));
|
|
50
|
+
|
|
51
|
+
// Step 4: Starting from the entry point, march the ray through the volume
|
|
52
|
+
// and sample it
|
|
53
|
+
vec3 p = transformed_eye + t_hit.x * ray_dir;
|
|
54
|
+
p.z = p.z * depth;
|
|
55
|
+
for (float t = t_hit.x; t < t_hit.y; t += dt) {
|
|
56
|
+
// Step 4.1: Sample the volume, and color it by the transfer function.
|
|
57
|
+
// Note that here we don't use the opacity from the transfer function,
|
|
58
|
+
// and just use the sample value as the opacity
|
|
59
|
+
vec3 tex = texture(diffuse, p).rgb;
|
|
60
|
+
vec4 val_color = vec4(tex.rgb, 0.02);
|
|
61
|
+
|
|
62
|
+
// Step 4.2: Accumulate the color and opacity using the front-to-back
|
|
63
|
+
// compositing equation
|
|
64
|
+
color.rgb += (1.0 - color.a) * val_color.a * val_color.rgb;
|
|
65
|
+
color.a += (1.0 - color.a) * val_color.a;
|
|
66
|
+
|
|
67
|
+
// Optimization: break out of the loop when the color is near opaque
|
|
68
|
+
if (color.a >= 0.95) {
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
p += ray_dir * dt;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
`;
|
|
75
|
+
|
|
76
|
+
const vs =
|
|
77
|
+
`
|
|
78
|
+
uniform vec3 volume_scale;
|
|
79
|
+
|
|
80
|
+
out vec3 vray_dir;
|
|
81
|
+
flat out vec3 transformed_eye;
|
|
82
|
+
|
|
83
|
+
void main(void) {
|
|
84
|
+
// Translate the cube to center it at the origin.
|
|
85
|
+
vec3 volume_translation = vec3(0.5) - volume_scale * 0.5;
|
|
86
|
+
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position * volume_scale + volume_translation, 1);
|
|
87
|
+
|
|
88
|
+
// Compute eye position and ray directions in the unit cube space
|
|
89
|
+
transformed_eye = (cameraPosition - volume_translation) / volume_scale;
|
|
90
|
+
vray_dir = position - transformed_eye;
|
|
91
|
+
}
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
const getUniforms = function() {
|
|
95
|
+
return {
|
|
96
|
+
volume_scale: { value: new THREE.Vector3( 1, 1, 1 ) },
|
|
97
|
+
diffuse: { value: undefined },
|
|
98
|
+
volume_dims: { value: [ 1, 1, 1 ] },
|
|
99
|
+
depth: { value: 1 },
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
exports.fs = fs;
|
|
104
|
+
exports.vs = vs;
|
|
105
|
+
exports.glslVersion = glslVersion;
|
|
106
|
+
exports.getUniforms = getUniforms;
|