////////////////////////////////////////////////////////////////////// // // Pixie // // Copyright © 1999 - 2003, Okan Arikan // // Contact: okan@cs.berkeley.edu // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // // File : executeMisc.cpp // Classes : - // Description : This file implements the main shader execution // //////////////////////////////////////////////////////////////////////// #include #include #include "common/global.h" #include "bundles.h" #include "executeMisc.h" #include "memory.h" #include "attributes.h" /////////////////////////////////////////////////////////////////////////////////////////////////// // // Misc. derivative functions // /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Class : CShadingContext // Method : duFloat // Description : Compute the u derivative // Return Value : - // Comments : // Date last edited : 2/4/2003 void CShadingContext::duFloat(float *dest,const float *src) { switch(currentShadingState->shadingDim) { // Du executing on Points or Curves (note that curves are defined along v) case SHADING_0D: case SHADING_1D_GRID: case SHADING_1D: { int i; for (i=currentShadingState->numVertices;i>0;i--) { *dest++ = 0; } } break; // Du executing on a 2D grid case SHADING_2D_GRID: { int uVertices = currentShadingState->numUvertices; int vVertices = currentShadingState->numVvertices; int i,j; const float *u = currentShadingState->varying[VARIABLE_U]; for (j=vVertices;j>0;j--) { *dest++ = (src[1] - src[0]) / (u[1] - u[0]); src++; u++; for (i=uVertices-2;i>0;i--) { *dest++ = (src[1] - src[-1]) / (u[1] - u[-1]); src++; u++; } *dest++ = (src[0] - src[-1]) / (u[0] - u[-1]); src++; u++; } } break; // Du executing on a 2D raytraced surface case SHADING_2D: { int numVertices = currentShadingState->numVertices; int numRealVertices = currentShadingState->numRealVertices; const float *dsrc = src + numRealVertices; float *ddest = dest + numRealVertices; const float *du = currentShadingState->varying[VARIABLE_DU]; int i; for (i=numRealVertices;i>0;i--) { const float val = (dsrc[0] - src[0]) / (*du++); ddest[0] = val; ddest[1] = val; dest[0] = val; dest++; src++; ddest += 2; dsrc += 2; } } break; } } /////////////////////////////////////////////////////////////////////// // Class : CShadingContext // Method : dvFloat // Description : Compute the v derivative // Return Value : - // Comments : // Date last edited : 2/4/2003 void CShadingContext::dvFloat(float *dest,const float *src) { switch(currentShadingState->shadingDim) { // Dv executing on Points case SHADING_0D: { for (int i=currentShadingState->numVertices;i>0;i--) { *dest++ = 0; } } break; // Dv executing on Curves case SHADING_1D_GRID: { int vVertices = currentShadingState->numVvertices; int i; const float *v = currentShadingState->varying[VARIABLE_V]; *dest++ = (src[1] - src[0]) / (v[1] - v[0]); src++; v++; for (i=vVertices-2;i>0;i--) { *dest++ = (src[1] - src[-1]) / (v[1] - v[-1]); src++; v++; } *dest = (src[0] - src[-1]) / (v[0] - v[-1]); } break; // Dv executing on Curves case SHADING_1D: { int numVertices = currentShadingState->numVertices; int numRealVertices = currentShadingState->numRealVertices; const float *dsrc = src + numRealVertices; float *ddest = dest + numRealVertices; const float *dv = currentShadingState->varying[VARIABLE_DV]; int i; assert(numVertices == numRealVertices*3); for (i=numRealVertices;i>0;i--) { const float val = (dsrc[0] - src[0]) / (*dv++); ddest[0] = val; ddest[1] = val; dest[0] = val; dest++; src++; ddest += 2; dsrc += 2; } } break; // Dv executing on a 2D grid case SHADING_2D_GRID: { int uVertices = currentShadingState->numUvertices; int vVertices = currentShadingState->numVvertices; int i,j; const float *v = currentShadingState->varying[VARIABLE_V]; for (j=0;j0;i--) { cRes[0] = (cOp[uVertices] - cOp[-uVertices]) / (cv[uVertices] - cv[-uVertices]); cRes += uVertices; cOp += uVertices; cv += uVertices; } cRes[0] = (cOp[0] - cOp[-uVertices]) / (cv[0] - cv[-uVertices]); } } break; // Dv executing on a 2D raytraced surface case SHADING_2D: { int numVertices = currentShadingState->numVertices; int numRealVertices = currentShadingState->numRealVertices; const float *dsrc = src + numRealVertices; float *ddest = dest + numRealVertices; const float *dv = currentShadingState->varying[VARIABLE_DV]; assert(numVertices == numRealVertices*3); for (int i=numRealVertices;i>0;i--) { const float val = (dsrc[1] - src[0]) / (*dv++); ddest[0] = val; ddest[1] = val; dest[0] = val; dest++; src++; ddest += 2; dsrc += 2; } } break; } } /////////////////////////////////////////////////////////////////////// // Class : CShadingContext // Method : duVector // Description : Compute the u derivative // Return Value : - // Comments : // Date last edited : 2/4/2003 void CShadingContext::duVector(float *dest,const float *src) { switch(currentShadingState->shadingDim) { // Du executing on Points or Curves (note that curves are defined along v) case SHADING_0D: case SHADING_1D_GRID: case SHADING_1D: { int i; for (i=currentShadingState->numVertices;i>0;i--) { *dest++ = 0; } } break; // Du executing on a 2D grid case SHADING_2D_GRID: { int uVertices = currentShadingState->numUvertices; int vVertices = currentShadingState->numVvertices; int i,j; const float *u = currentShadingState->varying[VARIABLE_U]; for (j=vVertices;j>0;j--) { float invDu = 1 / (u[1] - u[0]); *dest++ = (src[3] - src[0]) * invDu; *dest++ = (src[4] - src[1]) * invDu; *dest++ = (src[5] - src[2]) * invDu; src += 3; u++; for (i=uVertices-2;i>0;i--) { invDu = 1 / (u[1] - u[-1]); *dest++ = (src[3] - src[-3]) * invDu; *dest++ = (src[4] - src[-2]) * invDu; *dest++ = (src[5] - src[-1]) * invDu; src += 3; u++; } invDu = 1 / (u[0] - u[-1]); *dest++ = (src[0] - src[-3]) * invDu; *dest++ = (src[1] - src[-2]) * invDu; *dest++ = (src[2] - src[-1]) * invDu; src += 3; u++; } } break; // Du executing on a 2D raytraced surface case SHADING_2D: { int numVertices = currentShadingState->numVertices; int numRealVertices = currentShadingState->numRealVertices; const float *dsrc = src + numRealVertices*3; float *ddest = dest + numRealVertices*3; const float *du = currentShadingState->varying[VARIABLE_DU]; int i; for (i=numRealVertices;i>0;i--) { const float invDu = 1 / (*du++); const float val0 = (dsrc[0] - src[0]) * invDu; const float val1 = (dsrc[1] - src[1]) * invDu; const float val2 = (dsrc[2] - src[2]) * invDu; ddest[0] = val0; ddest[1] = val1; ddest[2] = val2; ddest[3] = val0; ddest[4] = val1; ddest[5] = val2; dest[0] = val0; dest[1] = val1; dest[2] = val2; assert(dotvv(dest,dest) >= 0); dest += 3; src += 3; ddest += 6; dsrc += 6; } } break; } } /////////////////////////////////////////////////////////////////////// // Class : CShadingContext // Method : dvVector // Description : Compute the v derivative // Return Value : - // Comments : // Date last edited : 2/4/2003 void CShadingContext::dvVector(float *dest,const float *src) { switch(currentShadingState->shadingDim) { // Dv executing on Points case SHADING_0D: { for (int i=currentShadingState->numVertices;i>0;i--) { *dest++ = 0; } } break; // Dv executing on Curves case SHADING_1D_GRID: { int vVertices = currentShadingState->numVvertices; int i; const float *v = currentShadingState->varying[VARIABLE_V]; float invDv; assert(currentShadingState->numUvertices == 1); assert(vVertices > 0); invDv = 1 / (v[1] - v[0]); *dest++ = (src[3] - src[0]) * invDv; *dest++ = (src[4] - src[1]) * invDv; *dest++ = (src[5] - src[2]) * invDv; src += 3; v++; for (i=vVertices-2;i>0;i--) { invDv = 1 / (v[1] - v[-1]); *dest++ = (src[3] - src[-3]) * invDv; *dest++ = (src[4] - src[-2]) * invDv; *dest++ = (src[5] - src[-1]) * invDv; src += 3; v++; } invDv = 1 / (v[0] - v[-1]); *dest++ = (src[0] - src[-3]) * invDv; *dest++ = (src[1] - src[-2]) * invDv; *dest++ = (src[2] - src[-1]) * invDv; } break; // Dv executing on Curves case SHADING_1D: { int numVertices = currentShadingState->numVertices; int numRealVertices = currentShadingState->numRealVertices; const float *dsrc = src + numRealVertices*3; float *ddest = dest + numRealVertices*3; const float *dv = currentShadingState->varying[VARIABLE_DV]; int i; assert(numVertices == numRealVertices*3); for (i=numRealVertices;i>0;i--) { const float invDv = 1 / (*dv++); const float val0 = (dsrc[3] - src[0]) * invDv; const float val1 = (dsrc[4] - src[1]) * invDv; const float val2 = (dsrc[5] - src[2]) * invDv; ddest[0] = val0; ddest[1] = val1; ddest[2] = val2; ddest[3] = val0; ddest[4] = val1; ddest[5] = val2; dest[0] = val0; dest[1] = val1; dest[2] = val2; dest += 3; src += 3; ddest += 6; dsrc += 6; } } break; // Dv executing on a 2D grid case SHADING_2D_GRID: { int uVertices = currentShadingState->numUvertices; int vVertices = currentShadingState->numVvertices; int i,j; const float *v = currentShadingState->varying[VARIABLE_V]; for (j=0;j0;i--) { invDv = 1 / (cv[uVertices] - cv[-uVertices]); cRes[0] = (cOp[uVertices*3+0] - cOp[-uVertices*3+0]) * invDv; cRes[1] = (cOp[uVertices*3+1] - cOp[-uVertices*3+1]) * invDv; cRes[2] = (cOp[uVertices*3+2] - cOp[-uVertices*3+2]) * invDv; cRes += uVertices*3; cOp += uVertices*3; cv += uVertices; } invDv = 1 / (cv[0] - cv[-uVertices]); cRes[0] = (cOp[0] - cOp[-uVertices*3+0]) * invDv; cRes[1] = (cOp[1] - cOp[-uVertices*3+1]) * invDv; cRes[2] = (cOp[2] - cOp[-uVertices*3+2]) * invDv; } } break; // Dv executing on a 2D raytraced surface case SHADING_2D: { int numVertices = currentShadingState->numVertices; int numRealVertices = currentShadingState->numRealVertices; const float *dsrc = src + numRealVertices*3; float *ddest = dest + numRealVertices*3; const float *dv = currentShadingState->varying[VARIABLE_DV]; int i; assert(numVertices == numRealVertices*3); for (i=numRealVertices;i>0;i--) { const float invDv = 1 / (*dv++); const float val0 = (dsrc[3] - src[0]) * invDv; const float val1 = (dsrc[4] - src[1]) * invDv; const float val2 = (dsrc[5] - src[2]) * invDv; ddest[0] = val0; ddest[1] = val1; ddest[2] = val2; ddest[3] = val0; ddest[4] = val1; ddest[5] = val2; dest[0] = val0; dest[1] = val1; dest[2] = val2; dest += 3; src += 3; ddest += 6; dsrc += 6; } } break; } } /////////////////////////////////////////////////////////////////////// // Class : CShadingContext // Method : traceTransmission // Description : Trace transmission rays // Return Value : - // Comments : // Date last edited : 3/23/2003 void CShadingContext::traceTransmission(float *dest,const float *from,const float *L,int numVertices,int *tags,CTextureLookup *lookup) { CTransmissionRay *rayBase; CTransmissionRay **raysBase; CTransmissionRay *cRay,**cRays; const int numSamples = lookup->numSamples; const float bias = lookup->shadowBias; const int shootStep = min(this->shootStep,numVertices*numSamples); const float coneAngle = lookup->coneAngle; const float maxDist = lookup->maxDist; int numRemaining = shootStep; const float multiplier = 1 / (float) lookup->numSamples; int currentSample; int i; CTransmissionBundle bundle; vector dir; if (lookup->label == NULL) bundle.label = rayLabelTransmission; else bundle.label = lookup->label; // Allocate the memory for the transmission rays cRay = rayBase = (CTransmissionRay *) ralloc(shootStep*sizeof(CTransmissionRay)); cRays = raysBase = (CTransmissionRay **) ralloc(shootStep*sizeof(CTransmissionRay*)); inShadow = TRUE; // We're in shadow // Create the rays for (i=currentShadingState->numRealVertices;i>0;i--,tags++) { if (*tags == 0) { const float d = lengthv(L); mulvf(dir,L,-1/d); initv(dest,0,0,0); // Clear the transmission // Create the samples for (currentSample=numSamples;currentSample>0;currentSample--) { // Sample a point in the cone sampleHemisphere(cRay->dir,dir,coneAngle,transmissionGenerator); movvv(cRay->from,from); cRay->t = min(maxDist,d) - bias; cRay->tmin = bias; cRay->time = urand(); cRay->flags = ATTRIBUTES_FLAGS_TRANSMISSION_VISIBLE; cRay->dest = dest; cRay->multiplier = multiplier; *cRays++ = cRay++; if (--numRemaining == 0) { bundle.numRays = shootStep; bundle.rays = (CRay **) raysBase; bundle.depth = 0; bundle.last = 0; bundle.postShader = NULL; traceEx(&bundle); cRay = rayBase; cRays = raysBase; numRemaining = shootStep; } } } dest += 3; from += 3; L += 3; } if (numRemaining != shootStep) { bundle.numRays = shootStep-numRemaining; bundle.rays = (CRay **) raysBase; bundle.depth = 0; bundle.last = 0; bundle.postShader = NULL; traceEx(&bundle); } inShadow = FALSE; } /////////////////////////////////////////////////////////////////////// // Class : CShadingContext // Method : traceReflection // Description : Trace reflection rays // Return Value : - // Comments : // Date last edited : 3/23/2003 void CShadingContext::traceReflection(float *dest,const float *from,const float *dir,int numVertices,int *tags,CTextureLookup *lookup) { CTraceRay *rayBase; CTraceRay **raysBase; CTraceRay *cRay,**cRays; const int numSamples = lookup->numSamples; const float bias = lookup->shadowBias; const int shootStep = min(this->shootStep,numVertices*numSamples); const float coneAngle = lookup->coneAngle; const float maxDist = lookup->maxDist; int numRemaining = shootStep; const float multiplier = 1 / (float) lookup->numSamples; int currentSample; int i; CTraceBundle bundle; vector D; if (lookup->label == NULL) bundle.label = rayLabelTransmission; else bundle.label = lookup->label; cRay = rayBase = (CTraceRay *) ralloc(shootStep*sizeof(CTraceRay)); cRays = raysBase = (CTraceRay **) ralloc(shootStep*sizeof(CTraceRay*)); for (i=currentShadingState->numRealVertices;i>0;i--,tags++) { if (*tags == 0) { normalizev(D,dir); initv(dest,0,0,0); for (currentSample=numSamples;currentSample>0;currentSample--) { sampleHemisphere(cRay->dir,D,coneAngle,traceGenerator); movvv(cRay->from,from); cRay->time = urand(); cRay->t = C_INFINITY; cRay->tmin = bias; cRay->flags = ATTRIBUTES_FLAGS_TRACE_VISIBLE; cRay->dest = dest; cRay->multiplier = multiplier; *cRays++ = cRay++; if (--numRemaining == 0) { bundle.numRays = shootStep; bundle.rays = (CRay **) raysBase; bundle.depth = 0; bundle.last = 0; bundle.postShader = NULL; traceEx(&bundle); cRay = rayBase; cRays = raysBase; numRemaining = shootStep; } } } dest += 3; from += 3; dir += 3; } if (numRemaining != shootStep) { bundle.numRays = shootStep-numRemaining; bundle.rays = (CRay **) raysBase; bundle.depth = 0; bundle.last = 0; bundle.postShader = NULL; traceEx(&bundle); } } /////////////////////////////////////////////////////////////////////// // Class : CShadingContext // Method : traceTransmission // Description : Trace transmission rays // Return Value : - // Comments : // Date last edited : 3/23/2003 void CShadingContext::traceTransmission(int numVertices,CRaySample *samples,CTextureLookup *lookup) { CTransmissionRay *rayBase; CTransmissionRay **raysBase; CTransmissionRay *cRay,**cRays; const int numSamples = lookup->numSamples; const float bias = lookup->shadowBias; const int shootStep = min(this->shootStep,numVertices*numSamples); const float coneAngle = lookup->coneAngle; const float maxDist = lookup->maxDist; int numRemaining = shootStep; const float multiplier = 1 / (float) lookup->numSamples; int currentSample; int i; CTransmissionBundle bundle; vector L,D; // Set the label if (lookup->label == NULL) bundle.label = rayLabelTransmission; else bundle.label = lookup->label; // Allocate the memory for the transmission rays cRay = rayBase = (CTransmissionRay *) ralloc(shootStep*sizeof(CTransmissionRay)); cRays = raysBase = (CTransmissionRay **) ralloc(shootStep*sizeof(CTransmissionRay*)); // We're in shadow inShadow = TRUE; // Create the rays for (i=numVertices;i>0;i--,samples++) { subvv(L,samples->to,samples->from); const float d = lengthv(L); mulvf(D,L,1/d); // Clear the transmission initv(samples->res,0,0,0); // Create the samples for (currentSample=numSamples;currentSample>0;currentSample--) { // Sample a point in the cone sampleCosineHemisphere(cRay->dir,D,coneAngle,transmissionGenerator); movvv(cRay->from,samples->from); cRay->t = min(maxDist,d) - bias; cRay->tmin = bias; cRay->time = urand(); cRay->flags = ATTRIBUTES_FLAGS_TRANSMISSION_VISIBLE; cRay->dest = samples->res; cRay->multiplier = multiplier; *cRays++ = cRay++; if (--numRemaining == 0) { bundle.numRays = shootStep; bundle.rays = (CRay **) raysBase; bundle.depth = 0; bundle.last = 0; bundle.postShader = NULL; traceEx(&bundle); cRay = rayBase; cRays = raysBase; numRemaining = shootStep; } } } // Shoot the remaining rays if (numRemaining != shootStep) { bundle.numRays = shootStep-numRemaining; bundle.rays = (CRay **) raysBase; bundle.depth = 0; bundle.last = 0; bundle.postShader = NULL; traceEx(&bundle); } // We're not in shadow anymore inShadow = FALSE; } /////////////////////////////////////////////////////////////////////// // Class : CShadingContext // Method : traceReflection // Description : Trace reflection rays // Return Value : - // Comments : // Date last edited : 3/23/2003 void CShadingContext::traceReflection(int numVertices,CRaySample *samples,CTextureLookup *lookup) { CTraceRay *rayBase; CTraceRay **raysBase; CTraceRay *cRay,**cRays; const int numSamples = lookup->numSamples; const float bias = lookup->shadowBias; const int shootStep = min(this->shootStep,numVertices*numSamples); const float coneAngle = lookup->coneAngle; const float maxDist = lookup->maxDist; int numRemaining = shootStep; const float multiplier = 1 / (float) lookup->numSamples; int currentSample; int i; CTraceBundle bundle; vector D; // Set the label if (lookup->label == NULL) bundle.label = rayLabelTransmission; else bundle.label = lookup->label; // Allocate the memory cRay = rayBase = (CTraceRay *) ralloc(shootStep*sizeof(CTraceRay)); cRays = raysBase = (CTraceRay **) ralloc(shootStep*sizeof(CTraceRay*)); // Shoot the rays for (i=numVertices;i>0;i--,samples++) { subvv(D,samples->to,samples->from); normalizev(D); initv(samples->res,0); for (currentSample=numSamples;currentSample>0;currentSample--) { sampleCosineHemisphere(cRay->dir,D,coneAngle,traceGenerator); movvv(cRay->from,samples->from); cRay->time = urand(); cRay->t = C_INFINITY; cRay->tmin = bias; cRay->flags = ATTRIBUTES_FLAGS_TRACE_VISIBLE; cRay->dest = samples->res; cRay->multiplier = multiplier; *cRays++ = cRay++; if (--numRemaining == 0) { bundle.numRays = shootStep; bundle.rays = (CRay **) raysBase; bundle.depth = 0; bundle.last = 0; bundle.postShader = NULL; traceEx(&bundle); cRay = rayBase; cRays = raysBase; numRemaining = shootStep; } } } // Shoot any remaining rays if (numRemaining != shootStep) { bundle.numRays = shootStep-numRemaining; bundle.rays = (CRay **) raysBase; bundle.depth = 0; bundle.last = 0; bundle.postShader = NULL; traceEx(&bundle); } }