0.1 ) f = 1.0 - f; // if i is even m = v * (1.0 - s); n = v * (1.0 - s * f); if( i == 6.0 || i == 0.0 ) return_value = vec4(v, n, m, hsva.a); else if( i == 1.0 ) return_value = vec4(n, v, m, hsva.a); else if( i == 2.0 ) return_value = vec4(m, v, n, hsva.a); else if( i == 3.0 ) return_value = vec4(m, n, v, hsva.a); else if( i == 4.0 ) return_value = vec4(n, m, v, hsva.a); else if( i == 5.0 ) return_value = vec4(v, m, n, hsva.a); // should never happen else return_value = vec4( 0, 0, 0, 1 ); } return return_value; } vec3 HSVToRGBv3( vec3 hsv ) { return HSVToRGBv4( vec4(hsv,1.0) ).rgb; } vec4 normalizedNormalFromTexture(sampler2D normals, vec4 pos) { vec4 n = cTexture3D(normals, pos.xyz); n.xyz = (2.0*n.xyz)-1.0; n.a = length(n.xyz); if( length(n.xyz) > 0.001 ) n.xyz = normalize(n.xyz); return n; } struct RayResult { vec4 color; vec4 zpoint; }; // compute t such that r0+t*dir is the exit point of the [0,1] box float rayexit(vec3 r0, vec3 dir) { vec3 q = 1.0/(dir+1.0e-6); vec3 t0 = -r0*q; vec3 tmax = max(t0,q+t0); return min(tmax.x,min(tmax.y,tmax.z)); } // CartoonVolumeStyle // Notes: void CartoonVolumeStyle( inout vec4 current_color, vec4 pos, vec4 viewdir, bool enabled, vec3 parallelColorHSV, vec3 orthogonalColorHSV, int colorSteps, vec4 normal ) { if( enabled && colorSteps >= 1 ) { if( normal.a > 0.001 ) { float cos_a = dot( normal.xyz, viewdir.xyz ); if( cos_a < 0.0 ) { current_color.rgb = vec3( 0.0, 0.0, 0.0 ); } else { float step = 1.0 / float(colorSteps); float interval = floor( cos_a / step ); if( interval >= float(colorSteps) ) interval = float(colorSteps) - 1.0; float w = interval * step; current_color.rgb = HSVToRGBv3( mix(orthogonalColorHSV, parallelColorHSV,w)); //HSVToRGB( orthogonalColorHSV * w + parallelColorHSV * (1.0-w) ); // 2 -> 0-0.5-1 0.5 // 3 -> 0-0.33-0.66-1 0.33 // 4 -> 0-0.25-0.5-0.75-1 0.25 } } else { current_color.a = 0.0; } } } // traverse ray // Inputs: // r0 - ray start (xyz), ray exit time (w) // dir - ray direction (xyz), step length (-w) // Output: // RayResult.color - the computed RGBA color for this fragment // RayResult.zpoint - the point to use for depth calculations, // if zpoint.x<0, no depth is computed RayResult traverseRay(vec4 r0, vec4 dir) { //useful stuff (hopefully not computed if not needed...?) mat4 view_to_tex = textureMatrix*modelViewMatrixInverse; mat4 tex_to_view = modelViewMatrix*textureMatrixInverse; vec4 viewdir_tex = vec4( -normalize(dir.xyz), 0.0 ); // return value RayResult rr; // initial color of this fragment is black with zero alpha rr.color = vec4(0.0, 0.0, 0.0, 0.0); // initial depth is not defined rr.zpoint = vec4(-1.0, 0.0, 0.0, 0.0); //BEGIN PRE-LOOP vec3 parallelColorHSV_4188f80 = RGBToHSVv3(parallelColor4188f80); vec3 orthogonalColorHSV_4188f80 = RGBToHSVv3(orthogonalColor4188f80); //END PRE-LOOP // compositing loop //while( rr.color.a<0.95 && r0.w>=0.0 ) for (float rayIterator = 0.0; rayIterator < 10.0; rayIterator += 1.0) { vec4 orig_sample_color = cTexture3D(uVolData, r0.xyz); orig_sample_color.a = orig_sample_color.r; vec4 sample_default_normal = normalizedNormalFromTexture( defaultNormals, r0 ); //ORIG_SAMPLE_MANIP // color of this sample vec4 sample_color = orig_sample_color; //BEGIN INSIDE-LOOP CartoonVolumeStyle(sample_color, r0, viewdir_tex, enabled4188f80, parallelColorHSV_4188f80, orthogonalColorHSV_4188f80, colorSteps4188f80, sample_default_normal); //END INSIDE-LOOP //BEGIN COMPOSITING // front-to-back compositing sample_color.rgb *= sample_color.a; rr.color += sample_color*(1.0-rr.color.a); if( rr.zpoint.x < 0.0 && rr.color.a > 0.0 ) { rr.zpoint = vec4( r0.xyz, 1 ); } //END COMPOSITING // step forward along ray r0 += dir; if (!(rr.color.a<0.95 && r0.w>=0.0)) break; } //BEGIN POST-LOOP //END POST-LOOP if( rr.color.a == 0.0 ) discard; // return result return rr; } void main() { textureMatrix = mat4(1.000, 0.000, 0.000, 0.500, 0.000, 1.000, 0.000, 0.500, 0.000, 0.000, 1.000, 0.500, 0.000, 0.000, 0.000, 1.000); textureMatrixInverse = mat4(1.000, 0.000, 0.000, -0.500, 0.000, 1.000, 0.000, -0.500, 0.000, 0.000, 1.000, -0.500, 0.000, 0.000, 0.000, 1.000); // initialize ray vec4 raydir = vec4(normalize(rayDir), -1.0); float texit = rayexit(rayStart,raydir.xyz); raydir = rayStep*raydir; vec4 raypos = vec4(rayStart, texit); // traverse ray RayResult rr = traverseRay(raypos, raydir); // set color gl_FragColor= rr.color; /* // set depth if computed if( rr.zpoint.x>=0.0 ) { // set depth vec4 tmp = modelViewProjectionMatrix*textureMatrixInverse*rr.zpoint; // in window coordinates gl_FragDepth = 0.5*(gl_DepthRange.diff*tmp.z/tmp.w + gl_DepthRange.near+gl_DepthRange.far); } else { gl_FragDepth = gl_FragCoord.z; } */ } ]]>