Beispiel #1
0
QString
ShaderFactory::addLighting()
{
  QString shader;

//  shader += " vec3 gx, gy, gz;\n";
//  shader += " gx = vec3(1/vsize.x,0,0);\n";
//  shader += " gy = vec3(0,1/vsize.y,0);\n";
//  shader += " gz = vec3(0,0,1/vsize.z);\n";
//  shader += " float vx = texture3D(dataTex, voxelCoord+gx).x - texture3D(dataTex, voxelCoord-gx).x;\n";
//  shader += " float vy = texture3D(dataTex, voxelCoord+gy).x - texture3D(dataTex, voxelCoord-gy).x;\n";
//  shader += " float vz = texture3D(dataTex, voxelCoord+gz).x - texture3D(dataTex, voxelCoord-gz).x;\n";
//  shader += " vec3 grad = vec3(vx, vy, vz);\n";

  shader += getGrad();
  shader += " if (length(grad) > 0.1)\n";
  shader += "  {\n";
  shader += "    grad = normalize(grad);\n";
  shader += "    vec3 lightVec = viewDir;\n";
  shader += "    float diff = abs(dot(lightVec, grad));\n";
  shader += "    vec3 reflecvec = reflect(lightVec, grad);\n";
  shader += "    float spec = pow(abs(dot(grad, reflecvec)), 512.0);\n";
  shader += "    colorSample.rgb *= (0.6 + 0.4*diff + spec);\n";
  shader += "    if (any(greaterThan(colorSample.rgb,vec3(1.0,1.0,1.0)))) \n";
  shader += "      colorSample.rgb = vec3(1.0,1.0,1.0);\n";
  shader += "  }\n";

  return shader;
}
Beispiel #2
0
// ** Temporary version
int
ClpPdco::pdco( ClpPdcoBase * stuff, Options &options, Info &info, Outfo &outfo)
{
//    D1, D2 are positive-definite diagonal matrices defined from d1, d2.
//           In particular, d2 indicates the accuracy required for
//           satisfying each row of Ax = b.
//
// D1 and D2 (via d1 and d2) provide primal and dual regularization
// respectively.  They ensure that the primal and dual solutions
// (x,r) and (y,z) are unique and bounded.
//
// A scalar d1 is equivalent to d1 = ones(n,1), D1 = diag(d1).
// A scalar d2 is equivalent to d2 = ones(m,1), D2 = diag(d2).
// Typically, d1 = d2 = 1e-4.
// These values perturb phi(x) only slightly  (by about 1e-8) and request
// that A*x = b be satisfied quite accurately (to about 1e-8).
// Set d1 = 1e-4, d2 = 1 for least-squares problems with bound constraints.
// The problem is then
//
//    minimize    phi(x) + 1/2 norm(d1*x)^2 + 1/2 norm(A*x - b)^2
//    subject to  bl <= x <= bu.
//
// More generally, d1 and d2 may be n and m vectors containing any positive
// values (preferably not too small, and typically no larger than 1).
// Bigger elements of d1 and d2 improve the stability of the solver.
//
// At an optimal solution, if x(j) is on its lower or upper bound,
// the corresponding z(j) is positive or negative respectively.
// If x(j) is between its bounds, z(j) = 0.
// If bl(j) = bu(j), x(j) is fixed at that value and z(j) may have
// either sign.
//
// Also, r and y satisfy r = D2 y, so that Ax + D2^2 y = b.
// Thus if d2(i) = 1e-4, the i-th row of Ax = b will be satisfied to
// approximately 1e-8.  This determines how large d2(i) can safely be.
//
//
// EXTERNAL FUNCTIONS:
// options         = pdcoSet;                  provided with pdco.m
// [obj,grad,hess] = pdObj( x );               provided by user
//               y = pdMat( name,mode,m,n,x ); provided by user if pdMat
//                                             is a string, not a matrix
//
// INPUT ARGUMENTS:
// pdObj      is a string containing the name of a function pdObj.m
//            or a function_handle for such a function
//            such that [obj,grad,hess] = pdObj(x) defines
//            obj  = phi(x)              : a scalar,
//            grad = gradient of phi(x)  : an n-vector,
//            hess = diag(Hessian of phi): an n-vector.
//         Examples:
//            If phi(x) is the linear function c"x, pdObj should return
//               [obj,grad,hess] = [c"*x, c, zeros(n,1)].
//            If phi(x) is the entropy function E(x) = sum x(j) log x(j),
//               [obj,grad,hess] = [E(x), log(x)+1, 1./x].
// pdMat      may be an ifexplicit m x n matrix A (preferably sparse!),
//            or a string containing the name of a function pdMat.m
//            or a function_handle for such a function
//            such that y = pdMat( name,mode,m,n,x )
//            returns   y = A*x (mode=1)  or  y = A"*x (mode=2).
//            The input parameter "name" will be the string pdMat.
// b          is an m-vector.
// bl         is an n-vector of lower bounds.  Non-existent bounds
//            may be represented by bl(j) = -Inf or bl(j) <= -1e+20.
// bu         is an n-vector of upper bounds.  Non-existent bounds
//            may be represented by bu(j) =  Inf or bu(j) >=  1e+20.
// d1, d2     may be positive scalars or positive vectors (see above).
// options    is a structure that may be set and altered by pdcoSet
//            (type help pdcoSet).
// x0, y0, z0 provide an initial solution.
// xsize, zsize are estimates of the biggest x and z at the solution.
//            They are used to scale (x,y,z).  Good estimates
//            should improve the performance of the barrier method.
//
//
// OUTPUT ARGUMENTS:
// x          is the primal solution.
// y          is the dual solution associated with Ax + D2 r = b.
// z          is the dual solution associated with bl <= x <= bu.
// inform = 0 if a solution is found;
//        = 1 if too many iterations were required;
//        = 2 if the linesearch failed too often.
// PDitns     is the number of Primal-Dual Barrier iterations required.
// CGitns     is the number of Conjugate-Gradient  iterations required
//            if an iterative solver is used (LSQR).
// time       is the cpu time used.
//----------------------------------------------------------------------

// PRIVATE FUNCTIONS:
//    pdxxxbounds
//    pdxxxdistrib
//    pdxxxlsqr
//    pdxxxlsqrmat
//    pdxxxmat
//    pdxxxmerit
//    pdxxxresid1
//    pdxxxresid2
//    pdxxxstep
//
// GLOBAL VARIABLES:
//    global pdDDD1 pdDDD2 pdDDD3
//
//
// NOTES:
// The matrix A should be reasonably well scaled: norm(A,inf) =~ 1.
// The vector b and objective phi(x) may be of any size, but ensure that
// xsize and zsize are reasonably close to norm(x,inf) and norm(z,inf)
// at the solution.
//
// The files defining pdObj  and pdMat
// must not be called Fname.m or Aname.m!!
//
//
// AUTHOR:
//    Michael Saunders, Systems Optimization Laboratory (SOL),
//    Stanford University, Stanford, California, USA.
//    [email protected]
//
// CONTRIBUTORS:
//    Byunggyoo Kim, SOL, Stanford University.
//    [email protected]
//
// DEVELOPMENT:
// 20 Jun 1997: Original version of pdsco.m derived from pdlp0.m.
// 29 Sep 2002: Original version of pdco.m  derived from pdsco.m.
//              Introduced D1, D2 in place of gamma*I, delta*I
//              and allowed for general bounds bl <= x <= bu.
// 06 Oct 2002: Allowed for fixed variabes: bl(j) = bu(j) for any j.
// 15 Oct 2002: Eliminated some work vectors (since m, n might be LARGE).
//              Modularized residuals, linesearch
// 16 Oct 2002: pdxxx..., pdDDD... names rationalized.
//              pdAAA eliminated (global copy of A).
//              Aname is now used directly as an ifexplicit A or a function.
//              NOTE: If Aname is a function, it now has an extra parameter.
// 23 Oct 2002: Fname and Aname can now be function handles.
// 01 Nov 2002: Bug fixed in feval in pdxxxmat.
//-----------------------------------------------------------------------

//  global pdDDD1 pdDDD2 pdDDD3
     double inf = 1.0e30;
     double eps = 1.0e-15;
     double atolold = -1.0, r3ratio = -1.0, Pinf, Dinf, Cinf, Cinf0;

     printf("\n   --------------------------------------------------------");
     printf("\n   pdco.m                            Version of 01 Nov 2002");
     printf("\n   Primal-dual barrier method to minimize a convex function");
     printf("\n   subject to linear constraints Ax + r = b,  bl <= x <= bu");
     printf("\n   --------------------------------------------------------\n");

     int m = numberRows_;
     int n = numberColumns_;
     bool ifexplicit = true;

     CoinDenseVector<double> b(m, rhs_);
     CoinDenseVector<double> x(n, x_);
     CoinDenseVector<double> y(m, y_);
     CoinDenseVector<double> z(n, dj_);
     //delete old arrays
     delete [] rhs_;
     delete [] x_;
     delete [] y_;
     delete [] dj_;
     rhs_ = NULL;
     x_ = NULL;
     y_ = NULL;
     dj_ = NULL;

     // Save stuff so available elsewhere
     pdcoStuff_ = stuff;

     double normb  = b.infNorm();
     double normx0 = x.infNorm();
     double normy0 = y.infNorm();
     double normz0 = z.infNorm();

     printf("\nmax |b | = %8g     max |x0| = %8g", normb , normx0);
     printf(                "      xsize   = %8g", xsize_);
     printf("\nmax |y0| = %8g     max |z0| = %8g", normy0, normz0);
     printf(                "      zsize   = %8g", zsize_);

     //---------------------------------------------------------------------
     // Initialize.
     //---------------------------------------------------------------------
     //true   = 1;
     //false  = 0;
     //zn     = zeros(n,1);
     //int nb     = n + m;
     int CGitns = 0;
     int inform = 0;
     //---------------------------------------------------------------------
     //  Only allow scalar d1, d2 for now
     //---------------------------------------------------------------------
     /*
     if (d1_->size()==1)
         d1_->resize(n, d1_->getElements()[0]);  // Allow scalar d1, d2
     if (d2_->size()==1)
         d2->resize(m, d2->getElements()[0]);  // to mean dk * unit vector
      */
     assert (stuff->sizeD1() == 1);
     double d1 = stuff->getD1();
     double d2 = stuff->getD2();

     //---------------------------------------------------------------------
     // Grab input options.
     //---------------------------------------------------------------------
     int  maxitn    = options.MaxIter;
     double featol    = options.FeaTol;
     double opttol    = options.OptTol;
     double steptol   = options.StepTol;
     int  stepSame  = 1;  /* options.StepSame;   // 1 means stepx == stepz */
     double x0min     = options.x0min;
     double z0min     = options.z0min;
     double mu0       = options.mu0;
     int  LSproblem = options.LSproblem;  // See below
     int  LSmethod  = options.LSmethod;   // 1=Cholesky    2=QR    3=LSQR
     int  itnlim    = options.LSQRMaxIter * CoinMin(m, n);
     double atol1     = options.LSQRatol1;  // Initial  atol
     double atol2     = options.LSQRatol2;  // Smallest atol,unless atol1 is smaller
     double conlim    = options.LSQRconlim;
     //int  wait      = options.wait;

     // LSproblem:
     //  1 = dy          2 = dy shifted, DLS
     // 11 = s          12 =  s shifted, DLS    (dx = Ds)
     // 21 = dx
     // 31 = 3x3 system, symmetrized by Z^{1/2}
     // 32 = 2x2 system, symmetrized by X^{1/2}

     //---------------------------------------------------------------------
     // Set other parameters.
     //---------------------------------------------------------------------
     int  kminor    = 0;      // 1 stops after each iteration
     double eta       = 1e-4;   // Linesearch tolerance for "sufficient descent"
     double maxf      = 10;     // Linesearch backtrack limit (function evaluations)
     double maxfail   = 1;      // Linesearch failure limit (consecutive iterations)
     double bigcenter = 1e+3;   // mu is reduced if center < bigcenter.

     // Parameters for LSQR.
     double atolmin   = eps;    // Smallest atol if linesearch back-tracks
     double btol      = 0;      // Should be small (zero is ok)
     double show      = false;  // Controls lsqr iteration log
     /*
     double gamma     = d1->infNorm();
     double delta     = d2->infNorm();
     */
     double gamma = d1;
     double delta = d2;

     printf("\n\nx0min    = %8g     featol   = %8.1e", x0min, featol);
     printf(                  "      d1max   = %8.1e", gamma);
     printf(  "\nz0min    = %8g     opttol   = %8.1e", z0min, opttol);
     printf(                  "      d2max   = %8.1e", delta);
     printf(  "\nmu0      = %8.1e     steptol  = %8g", mu0  , steptol);
     printf(                  "     bigcenter= %8g"  , bigcenter);

     printf("\n\nLSQR:");
     printf("\natol1    = %8.1e     atol2    = %8.1e", atol1 , atol2 );
     printf(                  "      btol    = %8.1e", btol );
     printf("\nconlim   = %8.1e     itnlim   = %8d"  , conlim, itnlim);
     printf(                  "      show    = %8g"  , show );

// LSmethod  = 3;  ////// Hardwire LSQR
// LSproblem = 1;  ////// and LS problem defining "dy".
     /*
       if wait
         printf("\n\nReview parameters... then type "return"\n")
         keyboard
       end
     */
     if (eta < 0)
          printf("\n\nLinesearch disabled by eta < 0");

     //---------------------------------------------------------------------
     // All parameters have now been set.
     //---------------------------------------------------------------------
     double time    = CoinCpuTime();
     //bool useChol = (LSmethod == 1);
     //bool useQR   = (LSmethod == 2);
     bool direct  = (LSmethod <= 2 && ifexplicit);
     char solver[7];
     strncpy(solver, "  LSQR", 7);

     //---------------------------------------------------------------------
     // Categorize bounds and allow for fixed variables by modifying b.
     //---------------------------------------------------------------------

     int nlow, nupp, nfix;
     int *bptrs[3] = {0};
     getBoundTypes(&nlow, &nupp, &nfix, bptrs );
     int *low = bptrs[0];
     int *upp = bptrs[1];
     int *fix = bptrs[2];

     int nU = n;
     if (nupp == 0) nU = 1;  //Make dummy vectors if no Upper bounds

     //---------------------------------------------------------------------
     //  Get pointers to local copy of model bounds
     //---------------------------------------------------------------------

     CoinDenseVector<double> bl(n, columnLower_);
     double *bl_elts = bl.getElements();
     CoinDenseVector<double> bu(nU, columnUpper_);  // this is dummy if no UB
     double *bu_elts = bu.getElements();

     CoinDenseVector<double> r1(m, 0.0);
     double *r1_elts = r1.getElements();
     CoinDenseVector<double> x1(n, 0.0);
     double *x1_elts = x1.getElements();

     if (nfix > 0) {
          for (int k = 0; k < nfix; k++)
               x1_elts[fix[k]] = bl[fix[k]];
          matVecMult(1, r1, x1);
          b = b - r1;
          // At some stage, might want to look at normfix = norm(r1,inf);
     }

     //---------------------------------------------------------------------
     // Scale the input data.
     // The scaled variables are
     //    xbar     = x/beta,
     //    ybar     = y/zeta,
     //    zbar     = z/zeta.
     // Define
     //    theta    = beta*zeta;
     // The scaled function is
     //    phibar   = ( 1   /theta) fbar(beta*xbar),
     //    gradient = (beta /theta) grad,
     //    Hessian  = (beta2/theta) hess.
     //---------------------------------------------------------------------
     double beta = xsize_;
     if (beta == 0) beta = 1; // beta scales b, x.
     double zeta = zsize_;
     if (zeta == 0) zeta = 1; // zeta scales y, z.
     double theta  = beta * zeta;                          // theta scales obj.
     // (theta could be anything, but theta = beta*zeta makes
     // scaled grad = grad/zeta = 1 approximately if zeta is chosen right.)

     for (int k = 0; k < nlow; k++)
          bl_elts[low[k]] = bl_elts[low[k]] / beta;
     for (int k = 0; k < nupp; k++)
          bu_elts[upp[k]] = bu_elts[upp[k]] / beta;
     d1     = d1 * ( beta / sqrt(theta) );
     d2     = d2 * ( sqrt(theta) / beta );

     double beta2  = beta * beta;
     b.scale( (1.0 / beta) );
     y.scale( (1.0 / zeta) );
     x.scale( (1.0 / beta) );
     z.scale( (1.0 / zeta) );

     //---------------------------------------------------------------------
     // Initialize vectors that are not fully used if bounds are missing.
     //---------------------------------------------------------------------
     CoinDenseVector<double> rL(n, 0.0);
     CoinDenseVector<double> cL(n, 0.0);
     CoinDenseVector<double> z1(n, 0.0);
     CoinDenseVector<double> dx1(n, 0.0);
     CoinDenseVector<double> dz1(n, 0.0);
     CoinDenseVector<double> r2(n, 0.0);

     // Assign upper bd regions (dummy if no UBs)

     CoinDenseVector<double> rU(nU, 0.0);
     CoinDenseVector<double> cU(nU, 0.0);
     CoinDenseVector<double> x2(nU, 0.0);
     CoinDenseVector<double> z2(nU, 0.0);
     CoinDenseVector<double> dx2(nU, 0.0);
     CoinDenseVector<double> dz2(nU, 0.0);

     //---------------------------------------------------------------------
     // Initialize x, y, z, objective, etc.
     //---------------------------------------------------------------------
     CoinDenseVector<double> dx(n, 0.0);
     CoinDenseVector<double> dy(m, 0.0);
     CoinDenseVector<double> Pr(m);
     CoinDenseVector<double> D(n);
     double *D_elts = D.getElements();
     CoinDenseVector<double> w(n);
     double *w_elts = w.getElements();
     CoinDenseVector<double> rhs(m + n);


     //---------------------------------------------------------------------
     // Pull out the element array pointers for efficiency
     //---------------------------------------------------------------------
     double *x_elts  = x.getElements();
     double *x2_elts = x2.getElements();
     double *z_elts  = z.getElements();
     double *z1_elts = z1.getElements();
     double *z2_elts = z2.getElements();

     for (int k = 0; k < nlow; k++) {
          x_elts[low[k]]  = CoinMax( x_elts[low[k]], bl[low[k]]);
          x1_elts[low[k]] = CoinMax( x_elts[low[k]] - bl[low[k]], x0min  );
          z1_elts[low[k]] = CoinMax( z_elts[low[k]], z0min  );
     }
     for (int k = 0; k < nupp; k++) {
          x_elts[upp[k]]  = CoinMin( x_elts[upp[k]], bu[upp[k]]);
          x2_elts[upp[k]] = CoinMax(bu[upp[k]] -  x_elts[upp[k]], x0min  );
          z2_elts[upp[k]] = CoinMax(-z_elts[upp[k]], z0min  );
     }
     //////////////////// Assume hessian is diagonal. //////////////////////

//  [obj,grad,hess] = feval( Fname, (x*beta) );
     x.scale(beta);
     double obj = getObj(x);
     CoinDenseVector<double> grad(n);
     getGrad(x, grad);
     CoinDenseVector<double> H(n);
     getHessian(x , H);
     x.scale((1.0 / beta));

     //double * g_elts = grad.getElements();
     double * H_elts = H.getElements();

     obj /= theta;                       // Scaled obj.
     grad = grad * (beta / theta) + (d1 * d1) * x; // grad includes x regularization.
     H  = H * (beta2 / theta) + (d1 * d1)      ; // H    includes x regularization.


     /*---------------------------------------------------------------------
     // Compute primal and dual residuals:
     // r1 =  b - Aprod(x) - d2*d2*y;
     // r2 =  grad - Atprod(y) + z2 - z1;
     //  rL =  bl - x + x1;
     //  rU =  x + x2 - bu; */
     //---------------------------------------------------------------------
     //  [r1,r2,rL,rU,Pinf,Dinf] = ...
     //      pdxxxresid1( Aname,fix,low,upp, ...
     //                   b,bl,bu,d1,d2,grad,rL,rU,x,x1,x2,y,z1,z2 );
     pdxxxresid1( this, nlow, nupp, nfix, low, upp, fix,
                  b, bl_elts, bu_elts, d1, d2, grad, rL, rU, x, x1, x2, y, z1, z2,
                  r1, r2, &Pinf, &Dinf);
     //---------------------------------------------------------------------
     // Initialize mu and complementarity residuals:
     //    cL   = mu*e - X1*z1.
     //    cU   = mu*e - X2*z2.
     //
     // 25 Jan 2001: Now that b and obj are scaled (and hence x,y,z),
     //              we should be able to use mufirst = mu0 (absolute value).
     //              0.1 worked poorly on StarTest1 with x0min = z0min = 0.1.
     // 29 Jan 2001: We might as well use mu0 = x0min * z0min;
     //              so that most variables are centered after a warm start.
     // 29 Sep 2002: Use mufirst = mu0*(x0min * z0min),
     //              regarding mu0 as a scaling of the initial center.
     //---------------------------------------------------------------------
     //  double mufirst = mu0*(x0min * z0min);
     double mufirst = mu0;   // revert to absolute value
     double mulast  = 0.1 * opttol;
     mulast  = CoinMin( mulast, mufirst );
     double mu      = mufirst;
     double center,  fmerit;
     pdxxxresid2( mu, nlow, nupp, low, upp, cL, cU, x1, x2,
                  z1, z2, &center, &Cinf, &Cinf0 );
     fmerit = pdxxxmerit(nlow, nupp, low, upp, r1, r2, rL, rU, cL, cU );

     // Initialize other things.

     bool  precon   = true;
     double PDitns    = 0;
     //bool converged = false;
     double atol      = atol1;
     atol2     = CoinMax( atol2, atolmin );
     atolmin   = atol2;
     //  pdDDD2    = d2;    // Global vector for diagonal matrix D2

     //  Iteration log.

     int nf      = 0;
     int itncg   = 0;
     int nfail   = 0;

     printf("\n\nItn   mu   stepx   stepz  Pinf  Dinf");
     printf("  Cinf   Objective    nf  center");
     if (direct) {
          printf("\n");
     } else {
          printf("  atol   solver   Inexact\n");
     }

     double regx = (d1 * x).twoNorm();
     double regy = (d2 * y).twoNorm();
     //  regterm = twoNorm(d1.*x)^2  +  norm(d2.*y)^2;
     double regterm = regx * regx + regy * regy;
     double objreg  = obj  +  0.5 * regterm;
     double objtrue = objreg * theta;

     printf("\n%3g                     ", PDitns        );
     printf("%6.1f%6.1f" , log10(Pinf ), log10(Dinf));
     printf("%6.1f%15.7e", log10(Cinf0), objtrue    );
     printf("   %8.1f\n"   , center                   );
     /*
     if kminor
       printf("\n\nStart of first minor itn...\n");
       keyboard
     end
     */
     //---------------------------------------------------------------------
     // Main loop.
     //---------------------------------------------------------------------
     // Lsqr
     ClpLsqr  thisLsqr(this);
     //  while (converged) {
     while(PDitns < maxitn) {
          PDitns = PDitns + 1;

          // 31 Jan 2001: Set atol according to progress, a la Inexact Newton.
          // 07 Feb 2001: 0.1 not small enough for Satellite problem.  Try 0.01.
          // 25 Apr 2001: 0.01 seems wasteful for Star problem.
          //              Now that starting conditions are better, go back to 0.1.

          double r3norm = CoinMax(Pinf,   CoinMax(Dinf,  Cinf));
          atol   = CoinMin(atol,  r3norm * 0.1);
          atol   = CoinMax(atol,  atolmin   );
          info.r3norm = r3norm;

          //-------------------------------------------------------------------
          //  Define a damped Newton iteration for solving f = 0,
          //  keeping  x1, x2, z1, z2 > 0.  We eliminate dx1, dx2, dz1, dz2
          //  to obtain the system
          //
          //     [-H2  A"  ] [ dx ] = [ w ],   H2 = H + D1^2 + X1inv Z1 + X2inv Z2,
          //     [ A   D2^2] [ dy ] = [ r1]    w  = r2 - X1inv(cL + Z1 rL)
          //                                           + X2inv(cU + Z2 rU),
          //
          //  which is equivalent to the least-squares problem
          //
          //     min || [ D A"]dy  -  [  D w   ] ||,   D = H2^{-1/2}.         (*)
          //         || [  D2 ]       [D2inv r1] ||
          //-------------------------------------------------------------------
          for (int k = 0; k < nlow; k++)
               H_elts[low[k]]  = H_elts[low[k]] + z1[low[k]] / x1[low[k]];
          for (int k = 0; k < nupp; k++)
               H[upp[k]]  = H[upp[k]] + z2[upp[k]] / x2[upp[k]];
          w = r2;
          for (int k = 0; k < nlow; k++)
               w[low[k]]  = w[low[k]] - (cL[low[k]] + z1[low[k]] * rL[low[k]]) / x1[low[k]];
          for (int k = 0; k < nupp; k++)
               w[upp[k]]  = w[upp[k]] + (cU[upp[k]] + z2[upp[k]] * rU[upp[k]]) / x2[upp[k]];

          if (LSproblem == 1) {
               //-----------------------------------------------------------------
               //  Solve (*) for dy.
               //-----------------------------------------------------------------
               H      = 1.0 / H;  // H is now Hinv (NOTE!)
               for (int k = 0; k < nfix; k++)
                    H[fix[k]] = 0;
               for (int k = 0; k < n; k++)
                    D_elts[k] = sqrt(H_elts[k]);
               thisLsqr.borrowDiag1(D_elts);
               thisLsqr.diag2_ = d2;

               if (direct) {
                    // Omit direct option for now
               } else {// Iterative solve using LSQR.
                    //rhs     = [ D.*w; r1./d2 ];
                    for (int k = 0; k < n; k++)
                         rhs[k] = D_elts[k] * w_elts[k];
                    for (int k = 0; k < m; k++)
                         rhs[n+k] = r1_elts[k] * (1.0 / d2);
                    double damp    = 0;

                    if (precon) {   // Construct diagonal preconditioner for LSQR
                         matPrecon(d2, Pr, D);
                    }
                    /*
                    	rw(7)        = precon;
                            info.atolmin = atolmin;
                            info.r3norm  = fmerit;  // Must be the 2-norm here.

                            [ dy, istop, itncg, outfo ] = ...
                       pdxxxlsqr( nb,m,"pdxxxlsqrmat",Aname,rw,rhs,damp, ...
                                  atol,btol,conlim,itnlim,show,info );


                    	thisLsqr.input->rhs_vec = &rhs;
                    	thisLsqr.input->sol_vec = &dy;
                    	thisLsqr.input->rel_mat_err = atol;
                    	thisLsqr.do_lsqr(this);
                    	*/
                    //  New version of lsqr

                    int istop;
                    dy.clear();
                    show = false;
                    info.atolmin = atolmin;
                    info.r3norm  = fmerit;  // Must be the 2-norm here.

                    thisLsqr.do_lsqr( rhs, damp, atol, btol, conlim, itnlim,
                                      show, info, dy , &istop, &itncg, &outfo, precon, Pr);
                    if (precon)
                         dy = dy * Pr;

                    if (!precon && itncg > 999999)
                         precon = true;

                    if (istop == 3  ||  istop == 7 )  // conlim or itnlim
                         printf("\n    LSQR stopped early:  istop = //%d", istop);


                    atolold   = outfo.atolold;
                    atol      = outfo.atolnew;
                    r3ratio   = outfo.r3ratio;
               }// LSproblem 1

               //      grad      = pdxxxmat( Aname,2,m,n,dy );   // grad = A"dy
               grad.clear();
               matVecMult(2, grad, dy);
               for (int k = 0; k < nfix; k++)
                    grad[fix[k]] = 0;                            // grad is a work vector
               dx = H * (grad - w);

          } else {
               perror( "This LSproblem not yet implemented\n" );
          }
          //-------------------------------------------------------------------

          CGitns += itncg;

          //-------------------------------------------------------------------
          // dx and dy are now known.  Get dx1, dx2, dz1, dz2.
          //-------------------------------------------------------------------
          for (int k = 0; k < nlow; k++) {
               dx1[low[k]] = - rL[low[k]] + dx[low[k]];
               dz1[low[k]] =  (cL[low[k]] - z1[low[k]] * dx1[low[k]]) / x1[low[k]];
          }
          for (int k = 0; k < nupp; k++) {
               dx2[upp[k]] = - rU[upp[k]] - dx[upp[k]];
               dz2[upp[k]] =  (cU[upp[k]] - z2[upp[k]] * dx2[upp[k]]) / x2[upp[k]];
          }
          //-------------------------------------------------------------------
          // Find the maximum step.
          //--------------------------------------------------------------------
          double stepx1 = pdxxxstep(nlow, low, x1, dx1 );
          double stepx2 = inf;
          if (nupp > 0)
               stepx2 = pdxxxstep(nupp, upp, x2, dx2 );
          double stepz1 = pdxxxstep( z1     , dz1      );
          double stepz2 = inf;
          if (nupp > 0)
               stepz2 = pdxxxstep( z2     , dz2      );
          double stepx  = CoinMin( stepx1, stepx2 );
          double stepz  = CoinMin( stepz1, stepz2 );
          stepx  = CoinMin( steptol * stepx, 1.0 );
          stepz  = CoinMin( steptol * stepz, 1.0 );
          if (stepSame) {                  // For NLPs, force same step
               stepx = CoinMin( stepx, stepz );   // (true Newton method)
               stepz = stepx;
          }

          //-------------------------------------------------------------------
          // Backtracking linesearch.
          //-------------------------------------------------------------------
          bool fail     =  true;
          nf       =  0;

          while (nf < maxf) {
               nf      = nf + 1;
               x       = x        +  stepx * dx;
               y       = y        +  stepz * dy;
               for (int k = 0; k < nlow; k++) {
                    x1[low[k]] = x1[low[k]]  +  stepx * dx1[low[k]];
                    z1[low[k]] = z1[low[k]]  +  stepz * dz1[low[k]];
               }
               for (int k = 0; k < nupp; k++) {
                    x2[upp[k]] = x2[upp[k]]  +  stepx * dx2[upp[k]];
                    z2[upp[k]] = z2[upp[k]]  +  stepz * dz2[upp[k]];
               }
               //      [obj,grad,hess] = feval( Fname, (x*beta) );
               x.scale(beta);
               obj = getObj(x);
               getGrad(x, grad);
               getHessian(x, H);
               x.scale((1.0 / beta));

               obj        /= theta;
               grad       = grad * (beta / theta)  +  d1 * d1 * x;
               H          = H * (beta2 / theta)  +  d1 * d1;

               //      [r1,r2,rL,rU,Pinf,Dinf] = ...
               pdxxxresid1( this, nlow, nupp, nfix, low, upp, fix,
                            b, bl_elts, bu_elts, d1, d2, grad, rL, rU, x, x1, x2,
                            y, z1, z2, r1, r2, &Pinf, &Dinf );
               //double center, Cinf, Cinf0;
               //      [cL,cU,center,Cinf,Cinf0] = ...
               pdxxxresid2( mu, nlow, nupp, low, upp, cL, cU, x1, x2, z1, z2,
                            &center, &Cinf, &Cinf0);
               double fmeritnew = pdxxxmerit(nlow, nupp, low, upp, r1, r2, rL, rU, cL, cU );
               double step      = CoinMin( stepx, stepz );

               if (fmeritnew <= (1 - eta * step)*fmerit) {
                    fail = false;
                    break;
               }

               // Merit function didn"t decrease.
               // Restore variables to previous values.
               // (This introduces a little error, but save lots of space.)

               x       = x        -  stepx * dx;
               y       = y        -  stepz * dy;
               for (int k = 0; k < nlow; k++) {
                    x1[low[k]] = x1[low[k]]  -  stepx * dx1[low[k]];
                    z1[low[k]] = z1[low[k]]  -  stepz * dz1[low[k]];
               }
               for (int k = 0; k < nupp; k++) {
                    x2[upp[k]] = x2[upp[k]]  -  stepx * dx2[upp[k]];
                    z2[upp[k]] = z2[upp[k]]  -  stepz * dz2[upp[k]];
               }
               // Back-track.
               // If it"s the first time,
               // make stepx and stepz the same.

               if (nf == 1 && stepx != stepz) {
                    stepx = step;
               } else if (nf < maxf) {
                    stepx = stepx / 2;
               }
               stepz = stepx;
          }

          if (fail) {
               printf("\n     Linesearch failed (nf too big)");
               nfail += 1;
          } else {
               nfail = 0;
          }

          //-------------------------------------------------------------------
          // Set convergence measures.
          //--------------------------------------------------------------------
          regx = (d1 * x).twoNorm();
          regy = (d2 * y).twoNorm();
          regterm = regx * regx + regy * regy;
          objreg  = obj  +  0.5 * regterm;
          objtrue = objreg * theta;

          bool primalfeas    = Pinf  <=  featol;
          bool dualfeas      = Dinf  <=  featol;
          bool complementary = Cinf0 <=  opttol;
          bool enough        = PDitns >=       4; // Prevent premature termination.
          bool converged     = primalfeas  &  dualfeas  &  complementary  &  enough;

          //-------------------------------------------------------------------
          // Iteration log.
          //-------------------------------------------------------------------
          char str1[100], str2[100], str3[100], str4[100], str5[100];
          sprintf(str1, "\n%3g%5.1f" , PDitns      , log10(mu)   );
          sprintf(str2, "%8.5f%8.5f" , stepx       , stepz       );
          if (stepx < 0.0001 || stepz < 0.0001) {
               sprintf(str2, " %6.1e %6.1e" , stepx       , stepz       );
          }

          sprintf(str3, "%6.1f%6.1f" , log10(Pinf) , log10(Dinf));
          sprintf(str4, "%6.1f%15.7e", log10(Cinf0), objtrue     );
          sprintf(str5, "%3d%8.1f"   , nf          , center      );
          if (center > 99999) {
               sprintf(str5, "%3d%8.1e"   , nf          , center      );
          }
          printf("%s%s%s%s%s", str1, str2, str3, str4, str5);
          if (direct) {
               // relax
          } else {
               printf(" %5.1f%7d%7.3f", log10(atolold), itncg, r3ratio);
          }
          //-------------------------------------------------------------------
          // Test for termination.
          //-------------------------------------------------------------------
          if (kminor) {
               printf( "\nStart of next minor itn...\n");
               //      keyboard;
          }

          if (converged) {
               printf("\n   Converged");
               break;
          } else if (PDitns >= maxitn) {
               printf("\n   Too many iterations");
               inform = 1;
               break;
          } else if (nfail  >= maxfail) {
               printf("\n   Too many linesearch failures");
               inform = 2;
               break;
          } else {

               // Reduce mu, and reset certain residuals.

               double stepmu  = CoinMin( stepx , stepz   );
               stepmu  = CoinMin( stepmu, steptol );
               double muold   = mu;
               mu      = mu   -  stepmu * mu;
               if (center >= bigcenter)
                    mu = muold;

               // mutrad = mu0*(sum(Xz)/n); // 24 May 1998: Traditional value, but
               // mu     = CoinMin(mu,mutrad ); // it seemed to decrease mu too much.

               mu      = CoinMax(mu, mulast); // 13 Jun 1998: No need for smaller mu.
               //      [cL,cU,center,Cinf,Cinf0] = ...
               pdxxxresid2( mu, nlow, nupp, low, upp, cL, cU, x1, x2, z1, z2,
                            &center, &Cinf, &Cinf0 );
               fmerit = pdxxxmerit( nlow, nupp, low, upp, r1, r2, rL, rU, cL, cU );

               // Reduce atol for LSQR (and SYMMLQ).
               // NOW DONE AT TOP OF LOOP.

               atolold = atol;
               // if atol > atol2
               //   atolfac = (mu/mufirst)^0.25;
               //   atol    = CoinMax( atol*atolfac, atol2 );
               // end

               // atol = CoinMin( atol, mu );     // 22 Jan 2001: a la Inexact Newton.
               // atol = CoinMin( atol, 0.5*mu ); // 30 Jan 2001: A bit tighter

               // If the linesearch took more than one function (nf > 1),
               // we assume the search direction needed more accuracy
               // (though this may be true only for LPs).
               // 12 Jun 1998: Ask for more accuracy if nf > 2.
               // 24 Nov 2000: Also if the steps are small.
               // 30 Jan 2001: Small steps might be ok with warm start.
               // 06 Feb 2001: Not necessarily.  Reinstated tests in next line.

               if (nf > 2  ||  CoinMin( stepx, stepz ) <= 0.01)
                    atol = atolold * 0.1;
          }
          //---------------------------------------------------------------------
          // End of main loop.
          //---------------------------------------------------------------------
     }


     for (int k = 0; k < nfix; k++)
          x[fix[k]] = bl[fix[k]];
     z      = z1;
     if (nupp > 0)
          z = z - z2;
     printf("\n\nmax |x| =%10.3f", x.infNorm() );
     printf("    max |y| =%10.3f", y.infNorm() );
     printf("    max |z| =%10.3f", z.infNorm() );
     printf("   scaled");

     x.scale(beta);
     y.scale(zeta);
     z.scale(zeta);   // Unscale x, y, z.

     printf(  "\nmax |x| =%10.3f", x.infNorm() );
     printf("    max |y| =%10.3f", y.infNorm() );
     printf("    max |z| =%10.3f", z.infNorm() );
     printf(" unscaled\n");

     time   = CoinCpuTime() - time;
     char str1[100], str2[100];
     sprintf(str1, "\nPDitns  =%10g", PDitns );
     sprintf(str2, "itns =%10d", CGitns );
     //  printf( [str1 " " solver str2] );
     printf("    time    =%10.1f\n", time);
     /*
     pdxxxdistrib( abs(x),abs(z) );   // Private function

     if (wait)
       keyboard;
     */
//-----------------------------------------------------------------------
// End function pdco.m
//-----------------------------------------------------------------------
     /*  printf("Solution x values:\n\n");
       for (int k=0; k<n; k++)
         printf(" %d   %e\n", k, x[k]);
     */
// Print distribution
     double thresh[9] = { 0.00000001, 0.0000001, 0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1.00001};
     int counts[9] = {0};
     for (int ij = 0; ij < n; ij++) {
          for (int j = 0; j < 9; j++) {
               if(x[ij] < thresh[j]) {
                    counts[j] += 1;
                    break;
               }
          }
     }
     printf ("Distribution of Solution Values\n");
     for (int j = 8; j > 1; j--)
          printf(" %g  to  %g %d\n", thresh[j-1], thresh[j], counts[j]);
     printf("   Less than   %g %d\n", thresh[2], counts[0]);

     return inform;
}
Beispiel #3
0
QString
ShaderFactory::genXRayShader(int maxSteps, bool firstHit, bool nearest, bool useMask)
{
  QString shader;

  shader =  "#extension GL_ARB_texture_rectangle : enable\n";
  shader += "uniform sampler3D maskTex;\n";
  shader += "uniform sampler1D tagTex;\n";
  shader += "uniform sampler3D dataTex;\n";
  shader += "uniform sampler2D lutTex;\n";
  shader += "uniform sampler2DRect exitTex;\n";
  shader += "uniform float stepSize;\n";
  shader += "uniform vec3 eyepos;\n";
  shader += "uniform vec3 viewDir;\n";
  shader += "uniform vec3 vcorner;\n";
  shader += "uniform vec3 vsize;\n";
  shader += "uniform float minZ;\n";
  shader += "uniform float maxZ;\n";  
  shader += "uniform bool saveCoord;\n";
  shader += "uniform int skipLayers;\n";
  shader += "uniform sampler2DRect entryTex;\n";
  shader += "uniform vec3 bgcolor;\n";

  shader += "void main(void)\n";
  shader += "{\n";


  shader += "vec4 exP = texture2DRect(exitTex, gl_FragCoord.st);\n";
  shader += "vec4 enP = texture2DRect(entryTex, gl_FragCoord.st);\n";

  shader += "if (exP.a < 0.001 || enP.a < 0.001) discard;\n";

  shader += "vec3 exitPoint = exP.rgb;\n";
  shader += "vec3 entryPoint = enP.rgb;\n";

  shader += "vec3 dir = (exitPoint-entryPoint);\n";
  shader += "float len = length(dir);\n";
  shader += "if (len < 0.001) discard;\n";

  shader += "vec3 normDir = normalize(dir);\n";
  shader += "vec3 deltaDir = normalize(dir)*stepSize;\n";
  shader += "float deltaDirLen = length(deltaDir);\n";

  shader += "vec3 voxelCoord = entryPoint;\n";
  shader += "vec4 colorAcum = vec4(0.0);\n"; // The dest color
  shader += "float lengthAcum = 0.0;\n";

  // backgroundColor
  shader += "vec4 bgColor = vec4(0.0, 0.0, 0.0, 0.0);\n";
  
  shader += "bool gotFirstHit = false;\n";
  shader += "int nskipped = 0;\n"; 
  shader += "bool solid = false;\n";
  shader += QString("for(int i=0; i<%1; i++)\n").arg(maxSteps);
  shader += "{\n";

  // -- get exact texture coordinate so we don't get tag interpolation --
  shader += "  vec3 vC = voxelCoord*vsize;\n";
  shader += "  bvec3 vclt = lessThan(floor(vC+0.5), vC);\n";
  shader += "  vC += vec3(vclt)*vec3(0.5);\n";
  shader += "  vC -= vec3(not(vclt))*vec3(0.5);\n";
  shader += "  vC /= vsize;\n";

  if (nearest)
    shader += "  float val = texture3D(dataTex, vC).x;\n";
  else
    shader += "  float val = texture3D(dataTex, voxelCoord).x;\n";

  shader += "  vec4 colorSample = texture2D(lutTex, vec2(val,0.0));\n";

  if (useMask)
    {
      shader += "  float tag = texture3D(maskTex, vC).x;\n";
      shader += "  vec4 tagcolor = texture1D(tagTex, tag);\n";
      shader += "  if (tag < 0.001) tagcolor.rgb = colorSample.rgb;\n";

      shader += "  colorSample.rgb = mix(colorSample.rgb, tagcolor.rgb, 0.5);\n";

      // so that we can use tag opacity to hide certain tagged regions
      // tagcolor.a should either 0 or 1
      shader += "  colorSample *= tagcolor.a;\n";
    }
  else
    shader += "  float tag = 0;\n";


  shader += "  if (!gotFirstHit && colorSample.a > 0.001) gotFirstHit = true;\n";  

  shader += "  if (gotFirstHit && nskipped > skipLayers)\n";
  shader += "  {\n";

  shader += "    if (saveCoord && colorSample.a > 0.001)";
  shader += "      {\n";
  shader += "        gl_FragColor = vec4(vC,1.0);\n";
  shader += "        return;\n";
  shader += "      }\n";

  if (firstHit)
    {
      shader += "  if (colorSample.a > 0.001 )\n";
      shader += "    {\n";  
      shader += "      vec3 voxpos = vcorner + voxelCoord*vsize;";
      shader += "      vec3 I = voxpos - eyepos;\n";
      shader += "      float z = dot(I, normalize(dir));\n";
      shader += "      z = (z-minZ)/(maxZ-minZ);\n";
      shader += "      z = clamp(z, 0.0, 1.0);\n";
      shader += "      gl_FragColor = vec4(z,val,tag,1.0);\n";
      shader += "      return;\n";
      shader += "    }\n";
    }

  // modulate opacity by angle wrt view direction
  shader += getGrad();
  shader += "if (length(grad) > 0.1)\n";
  shader += "  {\n";
  shader += "    grad = normalize(grad);\n";
  shader += "    colorSample.a *= (0.3+0.9*(1.0-abs(dot(grad,normDir))));\n";
  shader += "  }\n";
  shader += "else\n";
  shader += "  colorSample.a *= 0.2;\n";

  // reduce the opacity
  shader += "    colorSample.a *= 0.1;\n";
  shader += "    colorSample.rgb *= colorSample.a;\n";

  // just add up, don't composite
  shader += "    colorAcum += colorSample;\n";

  shader += "  }\n"; // gotfirsthit && nskipped > skipLayers

  shader += "  if (lengthAcum >= len )\n";
  shader += "    {\n";
  shader += "      colorAcum.rgb = colorAcum.rgb*colorAcum.a + (1.0 - colorAcum.a)*bgColor.rgb;\n";
  shader += "      break;\n";  // terminate if opacity > 1 or the ray is outside the volume	
  shader += "    }\n";
  shader += "  else if (colorAcum.a > 1.0)\n";
  shader += "    {\n";
  shader += "      colorAcum.a = 1.0;\n";
  shader += "      break;\n";
  shader += "    }\n";

  shader += "  voxelCoord += deltaDir;\n";
  shader += "  lengthAcum += deltaDirLen;\n";

  shader += "  if (gotFirstHit) \n";
  shader += "   {\n";
  shader += "     if (colorSample.a > 0.001)\n";
  shader += "      {\n";  
  shader += "         if (!solid)\n";
  shader += "           {\n";    
  shader += "             solid = true;\n";
  shader += "             nskipped++;\n";  
  shader += "           }\n";  
  shader += "      }\n";
  shader += "     else\n";
  shader += "      {\n";  
  shader += "         if (solid)\n";
  shader += "           {\n";    
  shader += "             solid = false;\n";
  shader += "           }\n";  
  shader += "      }\n";
  shader += "   }\n";

  shader += "}\n";

  //shader += "gl_FragColor = colorAcum;\n";    
  shader += "gl_FragColor = mix(colorAcum, vec4(bgcolor,1.0), 1.0-colorAcum.a);\n";

  shader += "}\n";

  return shader;
}
Beispiel #4
0
QString
RcShaderFactory::genXRayShader(bool nearest, float raylenFrac)
{
  QString shader;

  shader =  "#extension GL_ARB_texture_rectangle : enable\n";
  shader += "uniform sampler3D dataTex;\n";
  shader += "uniform sampler2D lutTex;\n";
  shader += "uniform sampler2DRect exitTex;\n";
  shader += "uniform float stepSize;\n";
  shader += "uniform vec3 eyepos;\n";
  shader += "uniform vec3 viewDir;\n";
  shader += "uniform vec3 vcorner;\n";
  shader += "uniform vec3 vsize;\n";
  shader += "uniform float minZ;\n";
  shader += "uniform float maxZ;\n";  
  shader += "uniform bool saveCoord;\n";
  shader += "uniform int skipLayers;\n";
  shader += "uniform sampler2DRect entryTex;\n";
  shader += "uniform vec3 bgcolor;\n";

  shader += "void main(void)\n";
  shader += "{\n";


  shader += "vec4 exP = texture2DRect(exitTex, gl_FragCoord.st);\n";
  shader += "vec4 enP = texture2DRect(entryTex, gl_FragCoord.st);\n";

  shader += "if (exP.a < 0.001 || enP.a < 0.001) discard;\n";

  shader += "vec3 exitPoint = exP.rgb;\n";
  shader += "vec3 entryPoint = enP.rgb;\n";

  shader += "vec3 dir = (exitPoint-entryPoint);\n";
  shader += "float len = length(dir);\n";
  shader += "if (len < 0.001) discard;\n";

  shader += "vec3 normDir = normalize(dir);\n";
  shader += "vec3 deltaDir = normalize(dir)*stepSize;\n";
  shader += "float deltaDirLen = length(deltaDir);\n";

  shader += "vec3 voxelCoord = entryPoint;\n";
  shader += "vec4 colorAcum = vec4(0.0);\n"; // The dest color
  shader += "float lengthAcum = 0.0;\n";

  // backgroundColor
  shader += "vec4 bgColor = vec4(0.0, 0.0, 0.0, 0.0);\n";
  
  shader += "bool gotFirstHit = false;\n";
  shader += "int nskipped = 0;\n"; 
  shader += "bool solid = false;\n";

  shader += QString("for(int i=0; i<max(10,int(%1*length(exitPoint-entryPoint)/stepSize)); i++)\n").arg(raylenFrac);

  shader += "{\n";

  // -- get exact texture coordinate so we don't get tag interpolation --
  shader += "  vec3 vC = voxelCoord*vsize;\n";
  shader += "  bvec3 vclt = lessThan(floor(vC+0.5), vC);\n";
  shader += "  vC += vec3(vclt)*vec3(0.5);\n";
  shader += "  vC -= vec3(not(vclt))*vec3(0.5);\n";
  shader += "  vC /= vsize;\n";

  if (nearest)
    shader += "  float val = texture3D(dataTex, vC).x;\n";
  else
    shader += "  float val = texture3D(dataTex, voxelCoord).x;\n";


  shader += getGrad();
  shader += "  vec4 colorSample = texture2D(lutTex, vec2(val,length(grad)));\n";

  shader += "  if (!gotFirstHit && colorSample.a > 0.001) gotFirstHit = true;\n";  

  shader += "  if (gotFirstHit && nskipped > skipLayers)\n";
  shader += "  {\n";

  shader += "    if (saveCoord && colorSample.a > 0.001)";
  shader += "      {\n";
  shader += "        gl_FragColor = vec4(vC,1.0);\n";
  shader += "        return;\n";
  shader += "      }\n";

  // modulate opacity by angle wrt view direction
  shader += "if (length(grad) > 0.1)\n";
  shader += "  {\n";
  shader += "    grad = normalize(grad);\n";
  shader += "    colorSample.a *= (0.3+0.9*(1.0-abs(dot(grad,normDir))));\n";
  shader += "  }\n";
  shader += "else\n";
  shader += "  colorSample.a *= 0.2;\n";

  // reduce the opacity
  shader += "    colorSample.a *= 0.1;\n";
  shader += "    colorSample.rgb *= colorSample.a;\n";

  // just add up, don't composite
  shader += "    colorAcum += colorSample;\n";

  shader += "  }\n"; // gotfirsthit && nskipped > skipLayers

  shader += "  if (lengthAcum >= len )\n";
  shader += "    {\n";
  shader += "      colorAcum.rgb = colorAcum.rgb*colorAcum.a + (1.0 - colorAcum.a)*bgColor.rgb;\n";
  shader += "      break;\n";  // terminate if opacity > 1 or the ray is outside the volume	
  shader += "    }\n";
  shader += "  else if (colorAcum.a > 1.0)\n";
  shader += "    {\n";
  shader += "      colorAcum.a = 1.0;\n";
  shader += "      break;\n";
  shader += "    }\n";

  shader += "  voxelCoord += deltaDir;\n";
  shader += "  lengthAcum += deltaDirLen;\n";

  shader += "  if (gotFirstHit) \n";
  shader += "   {\n";
  shader += "     if (colorSample.a > 0.001)\n";
  shader += "      {\n";  
  shader += "         if (!solid)\n";
  shader += "           {\n";    
  shader += "             solid = true;\n";
  shader += "             nskipped++;\n";  
  shader += "           }\n";  
  shader += "      }\n";
  shader += "     else\n";
  shader += "      {\n";  
  shader += "         if (solid)\n";
  shader += "           {\n";    
  shader += "             solid = false;\n";
  shader += "           }\n";  
  shader += "      }\n";
  shader += "   }\n";

  shader += "}\n";

  shader += "gl_FragColor = mix(colorAcum, vec4(bgcolor,1.0), 1.0-colorAcum.a);\n";

  shader += "}\n";

  return shader;
}
Beispiel #5
0
QString
RcShaderFactory::genIsoRaycastShader(bool nearest)
{
  QString shader;

  shader =  "#extension GL_ARB_texture_rectangle : enable\n";
  shader += "uniform sampler3D dataTex;\n";
  shader += "uniform sampler2D lutTex;\n";
  shader += "uniform sampler2DRect exitTex;\n";
  shader += "uniform float stepSize;\n";
  shader += "uniform vec3 eyepos;\n";
  shader += "uniform vec3 viewDir;\n";
  shader += "uniform vec3 vcorner;\n";
  shader += "uniform vec3 vsize;\n";
  shader += "uniform float minZ;\n";
  shader += "uniform float maxZ;\n";  
  shader += "uniform bool saveCoord;\n";
  shader += "uniform int skipLayers;\n";
  shader += "uniform sampler2DRect entryTex;\n";
  shader += "uniform vec3 bgcolor;\n";

  shader += "void main(void)\n";
  shader += "{\n";

  shader += "vec4 exP = texture2DRect(exitTex, gl_FragCoord.st);\n";
  shader += "vec4 enP = texture2DRect(entryTex, gl_FragCoord.st);\n";

  shader += "gl_FragData[0] = vec4(0.0);\n";
  shader += "gl_FragData[1] = vec4(0.0);\n";

  shader += "if (exP.a < 0.001 || enP.a < 0.001) discard;\n";

  shader += "vec3 exitPoint = exP.rgb;\n";
  shader += "vec3 entryPoint = enP.rgb;\n";

  shader += "vec3 dir = (exitPoint-entryPoint);\n";
  shader += "float len = length(dir);\n";
  shader += "if (len < 0.001) discard;\n";

  shader += "vec3 deltaDir = normalize(dir)*stepSize;\n";
  shader += "float deltaDirLen = length(deltaDir);\n";

  shader += "vec3 voxelCoord = entryPoint;\n";
//  shader += "vec4 colorAcum = vec4(0.0);\n"; // The dest color
  shader += "float lengthAcum = 0.0;\n";

  // backgroundColor
  shader += "vec4 bgColor = vec4(0.0, 0.0, 0.0, 0.0);\n";
  
  shader += "bool gotFirstHit = false;\n";
  shader += "int nskipped = 0;\n"; 
  shader += "bool solid = false;\n";
 
  shader += "for(int i=0; i<int(length(exitPoint-entryPoint)/stepSize); i++)\n";

  shader += "{\n";

  // -- get exact texture coordinate so we don't get tag interpolation --
  shader += "  vec3 vC = voxelCoord*vsize;\n";
  shader += "  bvec3 vclt = lessThan(floor(vC+0.5), vC);\n";
  shader += "  vC += vec3(vclt)*vec3(0.5);\n";
  shader += "  vC -= vec3(not(vclt))*vec3(0.5);\n";
  shader += "  vC /= vsize;\n";

  if (nearest)
    shader += "  float val = texture3D(dataTex, vC).x;\n";
  else
    shader += "  float val = texture3D(dataTex, voxelCoord).x;\n";

  shader += "  vec4 colorSample = vec4(1.0);\n";

  shader += getGrad();
  shader += "  float gradlen = length(grad);\n";
  shader += "  colorSample = texture2D(lutTex, vec2(val,gradlen));\n";

  shader += "  if (!gotFirstHit && colorSample.a > 0.001) gotFirstHit = true;\n";  

  shader += "  if (gotFirstHit && nskipped > skipLayers)\n";
  shader += "  {\n";

  shader += "  if (saveCoord && colorSample.a > 0.001)";
  shader += "    {\n";
  shader += "      gl_FragData[0] = vec4(vC,1.0);\n";
  shader += "      return;\n";
  shader += "    }\n";

  shader += "  if (colorSample.a > 0.001 )\n";
  shader += "    {\n";  
  shader += "      vec3 voxpos = vcorner + voxelCoord*vsize;";
  shader += "      vec3 I = voxpos - eyepos;\n";
  shader += "      float z = dot(I, normalize(viewDir));\n";
  shader += "      z = (z-minZ)/(maxZ-minZ);\n";
  shader += "      z = clamp(z, 0.0, 1.0);\n";
  shader += "      gl_FragData[0] = vec4(z,val,gradlen,1.0);\n";
  shader += "      if (gradlen > 0.2)\n";
  shader += "        {\n";
  shader += "           grad = normalize(grad);\n";
  shader += "           vec3 lightVec = viewDir;\n";
  shader += "           float diff = abs(dot(lightVec, grad));\n";
  shader += "           vec3 reflecvec = reflect(lightVec, grad);\n";
  shader += "           float spec = pow(abs(dot(grad, reflecvec)), 512.0);\n";
  shader += "           gl_FragData[1] = vec4(1.0,diff,spec,1.0);\n";
  shader += "        }\n";
  shader += "      else\n";
  shader += "        gl_FragData[1] = vec4(1.0,0.0,0.0,1.0);\n";
  shader += "      return;\n";
  shader += "    }\n";

  shader += "    colorSample.rgb *= colorSample.a;\n";

  shader += "  }\n"; // gotfirsthit && nskipped > skipLayers

  shader += "  if (lengthAcum >= len )\n";
  shader += "      break;\n";  // terminate if opacity > 1 or the ray is outside the volume	

  shader += "  voxelCoord += deltaDir;\n";
  shader += "  lengthAcum += deltaDirLen;\n";

  shader += "  if (gotFirstHit) \n";
  shader += "   {\n";
  shader += "     if (colorSample.a > 0.001)\n";
  shader += "      {\n";  
  shader += "         if (!solid)\n";
  shader += "           {\n";    
  shader += "             solid = true;\n";
  shader += "             nskipped++;\n";  
  shader += "           }\n";  
  shader += "      }\n";
  shader += "     else\n";
  shader += "      {\n";  
  shader += "         if (solid)\n";
  shader += "           {\n";    
  shader += "             solid = false;\n";
  shader += "           }\n";  
  shader += "      }\n";
  shader += "   }\n";

  shader += "}\n";

  shader += "}\n";

  return shader;
}
Beispiel #6
0
QString
RcShaderFactory::genFirstHitShader(bool nearest)
{
  QString shader;

  shader =  "#extension GL_ARB_texture_rectangle : enable\n";
  shader += "uniform sampler3D dataTex;\n";
  shader += "uniform sampler2D lutTex;\n";
  shader += "uniform sampler2DRect exitTex;\n";
  shader += "uniform sampler2DRect entryTex;\n";
  shader += "uniform float stepSize;\n";
  shader += "uniform vec3 vsize;\n";
  shader += "uniform int skipLayers;\n";

  shader += "void main(void)\n";
  shader += "{\n";

  shader += "vec4 exP = texture2DRect(exitTex, gl_FragCoord.st);\n";
  shader += "vec4 enP = texture2DRect(entryTex, gl_FragCoord.st);\n";

  shader += "gl_FragColor = vec4(0.0);\n";
  shader += "if (exP.a < 0.001 || enP.a < 0.001) discard;\n";

  shader += "vec3 exitPoint = exP.rgb;\n";
  shader += "vec3 entryPoint = enP.rgb;\n";

  shader += "vec3 dir = (exitPoint-entryPoint);\n";
  shader += "float len = length(dir);\n";
  shader += "if (len < 0.001) discard;\n";

  shader += "vec3 deltaDir = normalize(dir)*stepSize;\n";
  shader += "float deltaDirLen = length(deltaDir);\n";

  shader += "vec3 voxelCoord = entryPoint;\n";
  shader += "vec4 colorAcum = vec4(0.0);\n"; // The dest color
  shader += "float lengthAcum = 0.0;\n";

  shader += "bool gotFirstHit = false;\n";
  shader += "int nskipped = 0;\n"; 
  shader += "bool solid = false;\n";
  shader += "for(int i=0; i<int(length(exitPoint-entryPoint)/stepSize); i++)\n";
  //shader += QString("for(int i=0; i<%1; i++)\n").arg(maxSteps);
  shader += "{\n";

  // -- get exact texture coordinate so we don't get tag interpolation --
  if (nearest)
    {
      shader += "  vec3 vC = voxelCoord*vsize;\n";
      shader += "  bvec3 vclt = lessThan(floor(vC+0.5), vC);\n";
      shader += "  vC += vec3(vclt)*vec3(0.5);\n";
      shader += "  vC -= vec3(not(vclt))*vec3(0.5);\n";
      shader += "  vC /= vsize;\n";
      shader += "  float val = texture3D(dataTex, vC).x;\n";
    }
  else
    shader += "  float val = texture3D(dataTex, voxelCoord).x;\n";

  shader += "  vec4 colorSample = vec4(1.0);\n";

  shader += getGrad();
  shader += "  float gradlen = length(grad);\n";
  shader += "  colorSample = texture2D(lutTex, vec2(val,gradlen));\n";

  shader += "  if (!gotFirstHit && colorSample.a > 0.001) gotFirstHit = true;\n";  

  shader += "  if (gotFirstHit && nskipped > skipLayers)\n";
  shader += "  {\n";
  shader += "    if (colorSample.a > 0.001 )\n";
  shader += "      {\n";  
  shader += "        gl_FragColor = vec4(voxelCoord,1.0);\n";
  shader += "        return;\n";
  shader += "      }\n";
  shader += "  }\n"; // gotfirsthit && nskipped > skipLayers

  shader += "  if (lengthAcum >= len )\n";
  shader += "    return;\n";  // terminate if opacity > 1 or the ray is outside the volume	

  shader += "  voxelCoord += deltaDir;\n";
  shader += "  lengthAcum += deltaDirLen;\n";	         

  shader += "  if (gotFirstHit) \n";
  shader += "   {\n";
  shader += "     if (colorSample.a > 0.001)\n";
  shader += "      {\n";  
  shader += "         if (!solid)\n";
  shader += "           {\n";    
  shader += "             solid = true;\n";
  shader += "             nskipped++;\n";  
  shader += "           }\n";  
  shader += "      }\n";
  shader += "     else\n";
  shader += "      {\n";  
  shader += "         if (solid)\n";
  shader += "           solid = false;\n";
  shader += "      }\n";
  shader += "   }\n"; // got first hit

  shader += " }\n"; // loop over maxSteps

  shader += "}\n";

  return shader;
}
/* ******************************************************************************** */
int CalcConc(double *x, int **A, double *G, double *x0, int numSS, int numTotal, 
	     int MaxIters, double tol, double deltaBar, double eta, double kT, 
	     int MaxNoStep, int MaxTrial, double PerturbScale, int quiet, 
	     int WriteLogFile, char *logFile, double MolesWaterPerLiter,
	     unsigned long seed) {
  /*
    Computes the equilbrium mole fractions of species in dilute
    solution using a trust region algorithm on the dual problem.
    Discussion of the method is in Dirks, et al., Thermodynamic
    analysis of interacting nucleic acid strands, SIAM Review, (2006),
    in press.  The trust region algorithm for solving the dual problem
    is that in Nocedal and Wright, Numerical Optimization, 1999, page
    68, with the dogleg method on page 71.

    Returns 1 if converged and 0 otherwise.
  */

  int i,j; // Counters, i is over single-species and j is over all complexes
  int iters; // Number of iterations
  double *AbsTol; // The absolute tolerance on all values of gradient
  double rho; // Ratio of actual to predicted reduction in trust region method
  double delta; // Radius of trust region
  double *Grad; // The gradient of -g(lambda)
  double *lambda; // Lagrange multipliers (dual variables),x[j] = Q[j]*exp(lambda[j])
                  // for j \in \Psi^0
  double *p; // The step we take toward minimization
  double **Hes; // The Hessian
  double FreeEnergy; // The free energy of the solution
  unsigned long rand_seed = 0; // Random number seed
  int nNoStep; // Number of iterations without taking a step
  int nTrial; // Number of times we've perturbed lambda
  int **AT; // Transpose of A
  int RunStats[6]; // Statistics on results from getSearchDir (see comments below)
  FILE *fplog; // Log file

  // Initialize iters just so compiler doesn't give a warning when optimization is on
  iters = 0;

  // Allocate memory
  AT = (int **) malloc(numTotal * sizeof(int *));
  for (j = 0; j < numTotal; j++) {
    AT[j] = (int *) malloc(numSS * sizeof(int));
  }
  Hes = (double **) malloc(numSS * sizeof(double *));
  for (i = 0; i < numSS; i++) {
    Hes[i] = (double *) malloc(numSS * sizeof(double));
  }

  AbsTol = (double *) malloc(numSS * sizeof(double));
  Grad = (double *) malloc(numSS * sizeof(double));
  lambda = (double *) malloc(numSS * sizeof(double));
  p = (double *) malloc(numSS * sizeof(double));

  // The absolute tolerance is a percentage of the entries in x0
  for (i = 0; i < numSS; i++) {
    AbsTol[i] = tol * x0[i];
  }

  // Compute AT (transpose of A), useful to have around.
  IntTranspose(AT,A,numSS,numTotal);

  nTrial = 0;
  for (i = 0; i < numSS; i++) {
    Grad[i] = AbsTol[i] + 1.0; // Initialize just to get started.
  }
  while (CheckTol(Grad,AbsTol,numSS) == 0 && nTrial < MaxTrial) {

    if (nTrial == 1) {
      // Seed the random number generator if necessary
      rand_seed = GetRandSeed(seed);
      init_genrand(rand_seed);
    }

    // Set initial guess
    getInitialGuess(x0,lambda,G,AT,A,numSS,numTotal,PerturbScale,rand_seed);

    // Calculate the counts of the species based on lambda
    if (getx(x,lambda,G,AT,numSS,numTotal) == 0) { // Should be fine; checked prev.
      if (quiet == 0) {
	printf("Overflow error in calcution of mole fractions.\n\n");
	printf("Exiting....\n");
      }
      exit(ERR_OVERFLOW);
    }

    // Calculate the gradient
    getGrad(Grad,x0,x,A,numSS,numTotal);
    
    // Initialize delta to be just less than deltaBar
    delta = 0.99 * deltaBar;
    
    // Initializations
    iters = 0;
    nNoStep = 0;
    RunStats[0] = 0; // Number of pure Newton steps (didn't hit trust region boundary)
    RunStats[1] = 0; // Number of pure Cauchy steps (hit trust region boundary)
    RunStats[2] = 0; // Number of dogleg steps (part Newton and part Cauchy)
    RunStats[3] = 0; // Number of steps with Cholesky failure forcing Cauchy step
    RunStats[4] = 0; // Number of steps with irrelevant Cholesky failures
    RunStats[5] = 0; // Number of failed dogleg calculations
    
    // Run trust region with these initial conditions
    while (iters < MaxIters && CheckTol(Grad,AbsTol,numSS) == 0 
	   && nNoStep < MaxNoStep) {
      

      // Compute the Hessian (symmetric, positive, positive definite)
      getHes(Hes,x,A,numSS,numTotal);

      // Solve for the search direction
      (RunStats[getSearchDir(p,Grad,Hes,delta,numSS) - 1])++;

      // Calculate rho, ratio of actual to predicted reduction
      rho = getRho(lambda,p,Grad,x,Hes,x0,G,AT,numSS,numTotal);
      
      // Adjust delta and make step based on rho
      if (rho < 0.25) {
	delta /= 4.0;
      }
      else if (rho > 0.75 && fabs(norm(p,numSS) - delta) < NUM_PRECISION) {
	delta = min2(2.0*delta,deltaBar);
      }
      if (rho > eta) {
	for (i = 0; i < numSS; i++) {
	  lambda[i] += p[i];
	}
	nNoStep = 0;	
      }
      else {
	nNoStep++;
      }
      
      // Calculate the mole fractions of the complexes based on lambda
      if (getx(x,lambda,G,AT,numSS,numTotal) == 0) {// Should be fine;checked prev.
	if (quiet == 0) {
	  printf("Overflow error in calcution of mole fractions.\n\n");
	  printf("Exiting....\n");
	}
	exit(ERR_OVERFLOW);
      }
      
      // Calculate the gradient
      getGrad(Grad,x0,x,A,numSS,numTotal);
      
      // Advance the iterations count
      iters++;
    }

    // Advance the number of perturbations we've tried
    nTrial++;
  }

  // Compute the free energy
  FreeEnergy = 0;
  // First the reference free energy
  for (i = 0; i < numSS; i++) {
    FreeEnergy += x0[i]*(1.0 - log(x0[i]));
  }
  // Now the free energy
  for (j = 0; j < numTotal; j++) {
    if (x[j] > 0) {
      FreeEnergy += x[j]*(log(x[j]) + G[j] - 1.0);
    }
  }
  // Convert to kcal/liter of solution
  FreeEnergy *= kT*MolesWaterPerLiter;

  /* **************** WRITE OUT RESULTS ********************************* */
  if ( nTrial == MaxTrial  && quiet == 0) {
    printf("\n\n   TRUST REGION METHOD DID NOT CONVERGE DUE TO PRECISION ISSUES\n\n");
  }

  // Report errors in conservation of mass to screen
  if (quiet == 0) {
    // Print out values of the gradient, which is the error in cons. of mass
    printf("Error in conservation of mass:\n");
    for (i = 0; i < numSS; i++) {
      printf("   %8.6e Molar\n",Grad[i]*MolesWaterPerLiter);
    }
    printf("\n");

    // Print out the free energy of the solution
    printf("Free energy = %8.6e kcal/litre of solution\n",FreeEnergy);
   }

  // Write out details of calculation to outfile
  if (WriteLogFile) {
    if ((fplog = fopen(logFile,"a")) == NULL) {
      if (quiet == 0) {
	printf("Error opening %s.\n\nExiting....\n",logFile);
      }
      exit(ERR_LOG);
    }
    if (nTrial == MaxTrial) {
      fprintf(fplog,"TRUST REGION DID NOT CONVERGE DUE TO PRECISION ISSUES\n\n");
    }
    fprintf(fplog,"   --Trust region results:\n");
    fprintf(fplog,"       No. of initial conditions tried: %d\n",nTrial);
    fprintf(fplog,"       Results from succesful trial:\n");
    fprintf(fplog,"         No. of iterations: %d\n",iters);
    fprintf(fplog,"         No. of Newton steps: %d\n",RunStats[0]);
    fprintf(fplog,"         No. of Cauchy steps: %d\n",RunStats[1]);
    fprintf(fplog,"         No. of dogleg steps: %d\n",RunStats[2]);
    fprintf(fplog,"         No. of Cholesky failures resulting in Cauchy steps: %d\n"
	    ,RunStats[3]);
    fprintf(fplog,"         No. of inconsequential Cholesky failures: %d\n",
	    RunStats[4]);
    fprintf(fplog,"         No. of dogleg failures: %d\n",RunStats[5]);
    fprintf(fplog,"         Error in conservation of mass (units of molarity):\n");
    fprintf(fplog,"              Error\tTolerance\n");
    for (i = 0; i < numSS; i++) {
      fprintf(fplog, "           %.14e\t%.14e\n",Grad[i]*MolesWaterPerLiter,
	      AbsTol[i]*MolesWaterPerLiter);
    }
    fprintf(fplog,"   --Free energy of solution = %.14e kcal/litre of solution\n",
	    FreeEnergy);
    fclose(fplog);
  }
  /* **************** END OF WRITING OUT RESULTS **************************** */

   // Free memory
  for (j = 0; j < numTotal; j++) {
    free(AT[j]);
  }
  for (i = 0; i < numSS; i++) {
    free(Hes[i]);
  }
  free(AbsTol);
  free(AT);
  free(Hes);
  free(Grad);
  free(p);
  free(lambda);

  // Return convergence
  if (nTrial == MaxTrial) {
    return 0;
  }
  else {
    return 1;
  }

}
Beispiel #8
0
QString
ShaderFactory::genRaycastShader(int maxSteps, bool firstHit, bool nearest, bool useMask,
				bool bit16)
{
  QString shader;

  shader =  "#extension GL_ARB_texture_rectangle : enable\n";
  shader += "uniform sampler3D maskTex;\n";
  shader += "uniform sampler1D tagTex;\n";
  shader += "uniform sampler3D dataTex;\n";
  shader += "uniform sampler2D lutTex;\n";
  shader += "uniform sampler2DRect exitTex;\n";
  shader += "uniform float stepSize;\n";
  shader += "uniform vec3 eyepos;\n";
  shader += "uniform vec3 viewDir;\n";
  shader += "uniform vec3 vcorner;\n";
  shader += "uniform vec3 vsize;\n";
  shader += "uniform float minZ;\n";
  shader += "uniform float maxZ;\n";  
  shader += "uniform bool saveCoord;\n";
  shader += "uniform int skipLayers;\n";
  shader += "uniform sampler2DRect entryTex;\n";
  shader += "uniform vec3 bgcolor;\n";

  shader += "void main(void)\n";
  shader += "{\n";

  shader += "vec4 exP = texture2DRect(exitTex, gl_FragCoord.st);\n";
  shader += "vec4 enP = texture2DRect(entryTex, gl_FragCoord.st);\n";

  shader += "if (exP.a < 0.001 || enP.a < 0.001) discard;\n";

  shader += "vec3 exitPoint = exP.rgb;\n";
  shader += "vec3 entryPoint = enP.rgb;\n";

  shader += "vec3 dir = (exitPoint-entryPoint);\n";
  shader += "float len = length(dir);\n";
  shader += "if (len < 0.001) discard;\n";

  //shader += "vec3 normDir = normalize(dir);\n";
  shader += "vec3 deltaDir = normalize(dir)*stepSize;\n";
  shader += "float deltaDirLen = length(deltaDir);\n";

  shader += "vec3 voxelCoord = entryPoint;\n";
  shader += "vec4 colorAcum = vec4(0.0);\n"; // The dest color
  shader += "float lengthAcum = 0.0;\n";

  // backgroundColor
  shader += "vec4 bgColor = vec4(0.0, 0.0, 0.0, 0.0);\n";
  
  shader += "bool gotFirstHit = false;\n";
  shader += "int nskipped = 0;\n"; 
  shader += "bool solid = false;\n";
  shader += QString("for(int i=0; i<%1; i++)\n").arg(maxSteps);
  shader += "{\n";

  // -- get exact texture coordinate so we don't get tag interpolation --
  shader += "  vec3 vC = voxelCoord*vsize;\n";
  shader += "  bvec3 vclt = lessThan(floor(vC+0.5), vC);\n";
  shader += "  vC += vec3(vclt)*vec3(0.5);\n";
  shader += "  vC -= vec3(not(vclt))*vec3(0.5);\n";
  shader += "  vC /= vsize;\n";

  if (nearest)
    shader += "  float val = texture3D(dataTex, vC).x;\n";
  else
    shader += "  float val = texture3D(dataTex, voxelCoord).x;\n";

  shader += "  vec4 colorSample = vec4(0.0);\n";

  if (!bit16)
    shader += "  colorSample = texture2D(lutTex, vec2(val,0.0));\n";
  else
    {
      shader += "  int h0 = int(65535.0*val);\n";
      shader += "  int h1 = h0 / 256;\n";
      shader += "  h0 = int(mod(float(h0),256.0));\n";
      shader += "  float fh0 = float(h0)/256.0;\n";
      shader += "  float fh1 = float(h1)/256.0;\n";
      shader += "  colorSample = texture2D(lutTex, vec2(fh0,fh1));\n";
    }


  if (useMask)
    {
      shader += "  float tag = texture3D(maskTex, vC).x;\n";
      shader += "  vec4 tagcolor = texture1D(tagTex, tag);\n";
      shader += "  if (tag < 0.001) tagcolor.rgb = colorSample.rgb;\n";

      shader += "  colorSample.rgb = mix(colorSample.rgb, tagcolor.rgb, 0.5);\n";

      // so that we can use tag opacity to hide certain tagged regions
      // tagcolor.a should either 0 or 1
      shader += "  colorSample *= tagcolor.a;\n";
    }
  else
    shader += "  float tag = 0;\n";


  shader += "  if (!gotFirstHit && colorSample.a > 0.001) gotFirstHit = true;\n";  

  shader += "  if (gotFirstHit && nskipped > skipLayers)\n";
  shader += "  {\n";

  if (firstHit)
    {
      shader += "  if (saveCoord && colorSample.a > 0.001)";
      shader += "    {\n";
      shader += "      gl_FragData[0] = vec4(vC,1.0);\n";
      shader += "      return;\n";
      shader += "    }\n";

      shader += "  if (colorSample.a > 0.001 )\n";
      shader += "    {\n";  
      shader += "      vec3 voxpos = vcorner + voxelCoord*vsize;";
      shader += "      vec3 I = voxpos - eyepos;\n";
      shader += "      float z = dot(I, normalize(viewDir));\n";
      shader += "      z = (z-minZ)/(maxZ-minZ);\n";
      shader += "      z = clamp(z, 0.0, 1.0);\n";
      shader += "      gl_FragData[0] = vec4(z,val,tag,1.0);\n";
      shader += getGrad();
      shader += "      if (length(grad) > 0.2)\n";
      shader += "        {\n";
      shader += "           grad = normalize(grad);\n";
      shader += "           vec3 lightVec = viewDir;\n";
      shader += "           float diff = abs(dot(lightVec, grad));\n";
      shader += "           vec3 reflecvec = reflect(lightVec, grad);\n";
      shader += "           float spec = pow(abs(dot(grad, reflecvec)), 512.0);\n";
      shader += "           gl_FragData[1] = vec4(1.0,diff,spec,1.0);\n";
      shader += "        }\n";
      shader += "      else\n";
      shader += "        gl_FragData[1] = vec4(1.0,0.0,0.0,1.0);\n";
      shader += "      return;\n";
      shader += "    }\n";
    }
  else
    {
      shader += "    if (saveCoord && colorSample.a > 0.001)";
      shader += "      {\n";
      shader += "        gl_FragColor = vec4(vC,1.0);\n";
      shader += "        return;\n";
      shader += "      }\n";
    }

  shader += getGrad();
  shader += addLighting();

  shader += "    colorSample.rgb *= colorSample.a;\n";

  shader += "    colorAcum += (1.0 - colorAcum.a) * colorSample;\n";

  shader += "  }\n"; // gotfirsthit && nskipped > skipLayers

  shader += "  if (lengthAcum >= len )\n";
  shader += "    {\n";
  shader += "      colorAcum.rgb = colorAcum.rgb*colorAcum.a + (1.0 - colorAcum.a)*bgColor.rgb;\n";
  shader += "      break;\n";  // terminate if opacity > 1 or the ray is outside the volume	
  shader += "    }\n";
  shader += "  else if (colorAcum.a > 1.0)\n";
  shader += "    {\n";
  shader += "      colorAcum.a = 1.0;\n";
  shader += "      break;\n";
  shader += "    }\n";

////------
//  shader += " if (colorSample.a < 0.001)\n"; // skip a few steps
//  shader += "    {\n";
//  shader += "      voxelCoord += 2*deltaDir;\n";
//  shader += "      lengthAcum += 2*deltaDirLen;\n";
//  shader += "    }\n";
////------

  shader += "  voxelCoord += deltaDir;\n";
  shader += "  lengthAcum += deltaDirLen;\n";

  shader += "  if (gotFirstHit) \n";
  shader += "   {\n";
//  shader += "     phaseChanged = false;\n";
  shader += "     if (colorSample.a > 0.001)\n";
  shader += "      {\n";  
  shader += "         if (!solid)\n";
  shader += "           {\n";    
  shader += "             solid = true;\n";
  shader += "             nskipped++;\n";  
//  shader += "             phaseChanged = true;\n";
  shader += "           }\n";  
  shader += "      }\n";
  shader += "     else\n";
  shader += "      {\n";  
  shader += "         if (solid)\n";
  shader += "           {\n";    
//  shader += "             phaseChanged = true;\n";
  shader += "             solid = false;\n";
  shader += "           }\n";  
  shader += "      }\n";
  shader += "   }\n";

  shader += "}\n";

  if (!firstHit)
    //shader += "gl_FragColor = colorAcum;\n";
    shader += "gl_FragColor = mix(colorAcum, vec4(bgcolor,1.0), 1.0-colorAcum.a);\n";
  else
    {
      shader += "gl_FragData[0] = colorAcum;\n";
      shader += "gl_FragData[1] = vec4(0.0,0.0,0.0,1.0);\n";
    }

  shader += "}\n";

  return shader;
}