00001 !!ARBfp1.0
00002 OPTION NV_fragment_program2;
00003
00004 # Copyright (c) 2005 Institute for Visualization and Interactive
00005 # Systems, University of Stuttgart, Germany
00006 #
00007 # This source code is distributed as part of the single-pass volume
00008 # rendering project. Details about this project can be found on the
00009 # project web page at http://www.vis.uni-stuttgart.de/eng/research/
00010 # fields/current/spvolren. This file may be distributed, modified,
00011 # and used free of charge as long as this copyright notice is
00012 # included in its original form. Commercial use is strictly
00013 # prohibited.
00014 #
00015 # Filename: isosurface_scattering_sm3.fp
00016
00017 #! VOLUME = 0
00018 #! TRANSFERFUNCTION = 1
00019 #! BACKGROUND = 2
00020 #! SCATTERING = 3
00021
00022 # r = step
00023 # g = gradient scale
00024 # b = gradient offset
00025 # a = z-value of background plane
00026 PARAM params = program.local[0];
00027
00028 # r = texture coordinate scale
00029 # g = number of iterations
00030 # b = isovalue of isosurface
00031 # a = soft shadow scale
00032 PARAM params2 = program.local[1];
00033 PARAM center = program.local[2];
00034 PARAM texMax = program.local[3];
00035
00036 # r = scattering scale factor
00037 PARAM params3 = program.local[4];
00038
00039 PARAM scaleFactors = program.local[5];
00040
00041 TEMP geomDir;
00042 TEMP geomPos;
00043 TEMP criterion;
00044 TEMP specular;
00045 TEMP lightVec;
00046 TEMP texCoord;
00047 TEMP enterPos;
00048 TEMP ambient;
00049 TEMP diffuse;
00050 TEMP prevPos;
00051 TEMP texblen;
00052 TEMP diffVec;
00053 TEMP halfway;
00054 TEMP scatter;
00055 TEMP eyeVec;
00056 TEMP intens;
00057 TEMP camera;
00058 TEMP normal;
00059 TEMP weight;
00060 TEMP scale;
00061 TEMP temp1;
00062 TEMP temp2;
00063 TEMP temp;
00064 TEMP grad;
00065 TEMP sign;
00066 TEMP pos;
00067 TEMP src;
00068 TEMP dst;
00069 TEMP dir;
00070 TEMP tex;
00071 TEMP tempr;
00072 TEMP scalAct;
00073 TEMP scalPre;
00074
00075 # Compute the ray's starting point
00076 MOV geomPos, fragment.texcoord[0];
00077 MUL pos, geomPos, scaleFactors;
00078 MOV pos.a, 0.0;
00079
00080 # Compute the camera position by translating the origin to the center of the
00081 # volume
00082 MOV camera, state.matrix.modelview.invtrans.row[3];
00083
00084 # Compute the ray direction
00085 SUB geomDir, geomPos, camera;
00086
00087 # Normalize the direction
00088 DP3 geomDir.w, geomDir, geomDir;
00089 RSQ geomDir.w, geomDir.w;
00090 MUL geomDir, geomDir, geomDir.w;
00091 MOV geomDir.w, 0.0;
00092
00093 MUL dir, geomDir, scaleFactors;
00094
00095 # Initialize texture corrdinates
00096 # texcood.a inherits level of detail
00097 MOV texCoord, 0.0;
00098 MOV pos.w, 0.0;
00099
00100 # Initialize the 'previous' intensity
00101 TXL intens, pos, texture[0], 3D;
00102 MOV intens.g, intens.a;
00103
00104 # Initialize destination color
00105 MOV dst, 0.0;
00106 REP params2.g;
00107 REP params2.g;
00108 # Lookup scalar and gradient
00109 TXL tex, pos, texture[0], 3D;
00110
00111 # Component 'b' written to circumvent driver bug
00112 MOV intens.r, tex.a;
00113
00114 # Move one step forward
00115 MAD pos.xyz, dir, params.r, pos;
00116
00117 # Isosurface if differences with past and present
00118 # scalar values and isovalue have different signs
00119 SUB temp.rg, intens, params2.b;
00120 MULC temp.x, temp.r, temp.g;
00121 IF LE.x;
00122 # Isosurface found
00123
00124 # Determine if subsurface scattering refers to scalar
00125 # values below or above the isovalue (1 = greater, 0 = smaller)
00126 SGT criterion, intens.r, intens.g;
00127
00128 # Get scalar value from actual position
00129 MAD pos, -dir, params.r, pos;
00130 TXL scalAct, pos, texture[0], 3D;
00131
00132 # Get scalar value from previous position
00133 MAD prevPos, -dir, params.r, pos;
00134 TXL scalPre, prevPos, texture[0], 3D;
00135
00136 SUB temp.r, params2.b, scalPre.a;
00137 SUB temp.g, scalAct.a, scalPre.a;
00138
00139 # Perform linear interpolation to increase accuracy
00140 DIV_SAT temp.b, temp.r, temp.g;
00141 LRP pos, temp.b, pos, prevPos;
00142
00143 # Look up the color based on the isovalue
00144 MOV texCoord.rgb, params2.b;
00145 TXL src, texCoord, texture[1], 2D;
00146
00147 # We assume that isosurfaces are opaque
00148 MOV src.a, 1.0;
00149 # 'Normalize' color
00150 NRM src, src;
00151
00152 # isosurface hit found
00153 MOV dst.a, 1.0;
00154
00155 # Everything is done, jump out of loop
00156 BRK;
00157 ENDIF;
00158
00159 MOV intens.g, intens.r;
00160
00161 # Set values to zero if outside volume
00162 SGE temp1, pos, 0.0;
00163 SLE temp2, pos, texMax;
00164 DP3 weight.r, temp1, temp2;
00165 SEQC weight.r, weight.r, 3.0;
00166
00167 # Already outside volume, skip the rest
00168 BRK (EQ.x);
00169
00170 ENDREP;
00171
00172 # Already outside volume, skip the rest
00173 BRK (EQ.x);
00174 # isosurface hit?
00175 MOVC temp, dst.a;
00176 BRK (GT.x);
00177
00178 ENDREP;
00179
00180 # -------------- Scattering Code Begin -----------------------
00181
00182 MOV scatter, 0.0;
00183
00184 # Only need to compute scattering if isosurface was hit
00185 MOVC dst.a, dst.a;
00186 IF NE.w;
00187
00188 SUB lightVec.rgb, state.light[0].position, pos;
00189 MOV lightVec.a, 0.0;
00190 NRM lightVec, lightVec;
00191
00192 # Determine gradient at corrected position (same as above)
00193 TXL grad.rgb, pos, texture[0], 3D;
00194
00195 # Determine scale factor for gradient
00196 SNE temp.rgb, grad, 0.0;
00197 DP3_SAT temp.r, temp, 1.0;
00198
00199 # Reconstruct the gradient
00200 MAD_SSAT grad.rgb, tex, 2.0, -1.0;
00201 NRM_SSAT grad.rgb, grad;
00202
00203 # Set gradient to zero if it was zero
00204 MUL grad.rgb, grad, temp.r;
00205
00206 # Re-orient the gradient to get a
00207 # correct surface normal
00208 MOV temp, 0.0;
00209 DP3 temp.r, -geomDir, grad;
00210 NRM temp, temp;
00211 MUL grad.rgb, grad, temp.r;
00212 NRM grad.rgb, grad;
00213
00214 DP3C_SAT temp.r, grad, lightVec;
00215 MOV tempr, temp.r;
00216
00217 # compute diffuse lighting
00218 #Perform the lighting calculation (yes, we know LIT!)
00219
00220 # Ambient term
00221 MUL ambient, state.light[0].ambient, src;
00222
00223 # Diffuse term
00224 TEX diffuse, {0.2, 0.0, 0.0, 0.0}, texture[3], 1D;
00225 # Specular term
00226
00227 # Isosurfaces are opaque
00228 ADD dst.rgb, diffuse, ambient;
00229 MUL_SAT dst.rgb, dst, temp.r;
00230
00231 # Make sure the isosurface is not intersected twice
00232 # in the same location
00233 MAD pos.xyz, dir, params.r, pos;
00234
00235 REP params2.g;
00236 REP params2.g;
00237 # Move one step forward
00238 MAD pos.xyz, lightVec, params.r, pos;
00239
00240 # Exit loop when leaving volume
00241 SGE temp1, pos, 0.0;
00242 SLE temp2, pos, texMax;
00243 DP3 weight.r, temp1, temp2;
00244 SEQC weight.r, weight.r, 3.0;
00245 BRK (EQ.x);
00246
00247 # Determine scalar value
00248 TXL tex, pos, texture[0], 3D;
00249
00250 # Component 'b' written to circumvent driver bug
00251 MOV intens.r, tex.a;
00252
00253 # Adjust scatter value
00254 SUBC temp.x, intens.r, params2.b;
00255 IF LE.x;
00256 # Intensity smaller isovalue
00257 MOVC temp.x, criterion.x;
00258 IF EQ.x;
00259 # Want to sum up intensities less than isovalues
00260 MOV scale, params3.r;
00261 SUB temp.rg, intens, params2.b;
00262 MULC temp, temp.r, temp.g;
00263 IF LE.x;
00264 # Sign change
00265 SUB temp.r, params2.b, intens.r;
00266 SUB temp.g, intens.g, intens.r;
00267 DIV_SAT temp.b, temp.r, temp.g;
00268 MUL scale, scale, temp.b;
00269 ENDIF;
00270 MAD scatter.x, params.r, scale, scatter.x;
00271 ENDIF;
00272 ELSE;
00273 # Scalar greater isovalue
00274 MOVC temp.x, criterion.x;
00275 IF GT.x;
00276 # Want to sum up intensities greater than isovalues
00277 MOV scale, params3.r;
00278 SUB temp.rg, intens, params2.b;
00279 MULC temp, temp.r, temp.g;
00280 IF LE.x;
00281 # Sign change
00282 SUB temp.r, intens.r, params2.b;
00283 SUB temp.g, intens.r, intens.g;
00284 DIV_SAT temp.b, temp.r, temp.g;
00285 MUL scale, scale, temp.b;
00286 ENDIF;
00287 MAD scatter.x, params.r, scale, scatter.x;
00288 ENDIF;
00289 ENDIF;
00290
00291 MOV intens.g, intens.r;
00292 ENDREP;
00293
00294 # Already outside volume, skip the rest
00295 BRK (EQ.x);
00296 ENDREP;
00297
00298 TXL temp.rgb, scatter.x, texture[3], 1D;
00299 #ADD dst.xyz, dst, temp;
00300
00301 LRP dst.rgb, tempr, dst, temp;
00302 ENDIF; # isosurface hit
00303
00304 # -------------- Scattering Code End -------------------------
00305
00306 # Compute the normal of the background plane (this is just the negative view
00307 # direction which initially is (0, 0, -1))
00308 MOV normal, state.matrix.modelview.row[2];
00309
00310 # Compute the plane constant (we want the plane to be located in the volume
00311 # center)
00312 DP3 temp1.r, normal, center;
00313
00314 # Move the plane behind the volume: d' = <n,(x - l n)> = <n, x> - l <n, n>;
00315 # l = 0.71 is chosen since it is greater than half the cube diagonal
00316 DP3 temp1.g, normal, normal;
00317 MAD temp1.r, temp1.g, -.71, temp1.r;
00318
00319 # Compute ray parameter
00320 DP3 temp1.g, normal, geomPos;
00321 SUB temp1.g, temp1.r, temp1.g;
00322 DP3 temp1.b, normal, geomDir;
00323 DIV temp.r, temp1.g, temp1.b;
00324
00325 # Compute ray/plane intersection
00326 MAD temp.rgb, temp.r, geomDir, geomPos;
00327
00328 # Compute the difference vector
00329 SUB diffVec, temp, center;
00330
00331 # Compute the texture coordinates
00332 DP3 temp.r, diffVec, state.matrix.modelview.row[0];
00333 DP3 temp.g, diffVec, state.matrix.modelview.row[1];
00334 MUL temp.rg, temp, params2.r;
00335
00336 # Center background image
00337 ADD temp.rg, temp, .5;
00338
00339 # Look up the texel value
00340 TEX temp.rgb, temp, texture[2], 2D;
00341 MOV temp.a, 1.0;
00342
00343 # Blend the background pixel
00344 SUB texblen, 1.0, dst.a;
00345 MAD dst, temp, texblen.x, dst;
00346
00347 # Write the output color
00348 MOV result.color, dst;
00349
00350 END