////////////////////////////////////////////////////////////////////// // // 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 : shader.cpp // Classes : CShader // CShaderInstance // Description : Implementation // //////////////////////////////////////////////////////////////////////// #include #include #include #include "renderer.h" #include "error.h" #include "shader.h" #include "stats.h" #include "shading.h" #include "cache.h" #include "bundles.h" /////////////////////////////////////////////////////////////////////// // Class : CShaderLookup // Method : CShaderLookup // Description : Ctor // Return Value : - // Comments : // Date last edited : 3/10/2001 CShaderLookup::CShaderLookup() { } /////////////////////////////////////////////////////////////////////// // Class : CShaderLookup // Method : ~CShaderLookup // Description : Dtor // Return Value : - // Comments : // Date last edited : 3/10/2001 CShaderLookup::~CShaderLookup() { } /////////////////////////////////////////////////////////////////////// // Class : CFilterLookup // Method : compute // Description : Lookup filter values at discrete intelvals // Return Value : - // Comments : // Date last edited : 3/10/2001 void CFilterLookup::compute() { int i; float val; valStep = 2*width / (NUMFILTERSTEPS-1); val = width; normalizer = 0; for (i=0;i0;i--,src+=3) { CGatherRay *ray = (CGatherRay *) (*r++); movvv((float *) dest + ray->index*3,src); } } /////////////////////////////////////////////////////////////////////// // Class : CShaderVectorVariable // Method : record // Description : // Return Value : - // Comments : // Date last edited : 3/23/2003 void CShaderFloatVariable::record(int nr,CGatherRay **r,float **varying) { int i; float *src = varying[entry]; for (i=nr;i>0;i--) { CGatherRay *ray = (CGatherRay *) (*r++); dest[ray->index].real = *src++; } } /////////////////////////////////////////////////////////////////////// // Class : CShaderVectorVariable // Method : record // Description : // Return Value : - // Comments : // Date last edited : 3/23/2003 void CRayOriginVariable::record(int nr,CGatherRay **r,float **varying) { int i; for (i=nr;i>0;i--) { CGatherRay *ray = (CGatherRay *) (*r++); movvv((float *) dest + ray->index*3,ray->from); } } /////////////////////////////////////////////////////////////////////// // Class : CShaderVectorVariable // Method : record // Description : // Return Value : - // Comments : // Date last edited : 3/23/2003 void CRayDirVariable::record(int nr,CGatherRay **r,float **varying) { int i; for (i=nr;i>0;i--) { CGatherRay *ray = (CGatherRay *) (*r++); movvv((float *) dest + ray->index*3,ray->dir); } } /////////////////////////////////////////////////////////////////////// // Class : CShaderVectorVariable // Method : record // Description : // Return Value : - // Comments : // Date last edited : 3/23/2003 void CRayLengthVariable::record(int nr,CGatherRay **r,float **varying) { int i; for (i=nr;i>0;i--) { CGatherRay *ray = (CGatherRay *) (*r++); dest[ray->index].real = ray->t; } } /////////////////////////////////////////////////////////////////////// // Class : CGatherLookup // Method : CGatherLookup // Description : Ctor // Return Value : - // Comments : // Date last edited : 3/23/2003 CGatherLookup::CGatherLookup() { outputs = NULL; nonShadeOutputs = NULL; } /////////////////////////////////////////////////////////////////////// // Class : CGatherLookup // Method : ~CGatherLookup // Description : Dtor // Return Value : - // Comments : // Date last edited : 3/23/2003 CGatherLookup::~CGatherLookup() { CGatherVariable *cVar; while((cVar=outputs) != NULL) { outputs = cVar->next; if (cVar->destForEachLevel != NULL) delete [] cVar->destForEachLevel; delete cVar; } while((cVar=nonShadeOutputs) != NULL) { nonShadeOutputs = cVar->next; if (cVar->destForEachLevel != NULL) delete [] cVar->destForEachLevel; delete cVar; } } /////////////////////////////////////////////////////////////////////// // Class : CGatherLookup // Method : addOutput // Description : Adds an output // Return Value : - // Comments : // Date last edited : 3/23/2003 void CGatherLookup::addOutput(const char *output,int destIndex) { CGatherVariable *nVar = NULL; if (strncmp(output,"surface:",8) == 0) { CVariable *var = currentRenderer->retrieveVariable(output+8); if (var == NULL) error(CODE_BADTOKEN,"Variable %s not found\n",output); else { if ( (var->type == TYPE_VECTOR) || (var->type == TYPE_POINT) || (var->type == TYPE_COLOR) || (var->type == TYPE_NORMAL)) { CShaderVectorVariable *outVar = new CShaderVectorVariable; outVar->shade = TRUE; outVar->entry = var->entry; outVar->destIndex = destIndex; outVar->next = outputs; outputs = outVar; nVar = outVar; } else if (var->type == TYPE_FLOAT) { CShaderFloatVariable *outVar = new CShaderFloatVariable; outVar->shade = TRUE; outVar->entry = var->entry; outVar->destIndex = destIndex; outVar->next = outputs; outputs = outVar; nVar = outVar; } else { error(CODE_BADTOKEN,"Unknown output variable type for gather\n"); } } } else if (strcmp(output,"ray:origin") == 0) { CRayOriginVariable *outVar = new CRayOriginVariable; outVar->destIndex = destIndex; outVar->next = nonShadeOutputs; nonShadeOutputs = outVar; nVar = outVar; } else if (strcmp(output,"ray:direction") == 0) { CRayDirVariable *outVar = new CRayDirVariable; outVar->destIndex = destIndex; outVar->next = nonShadeOutputs; nonShadeOutputs = outVar; nVar = outVar; } else if (strcmp(output,"ray:length") == 0) { CRayLengthVariable *outVar = new CRayLengthVariable; outVar->destIndex = destIndex; outVar->next = nonShadeOutputs; nonShadeOutputs = outVar; nVar = outVar; } else { error(CODE_BADTOKEN,"Unknown output variable for gather\n"); } if (nVar != NULL) { nVar->destForEachLevel = new TCode*[maxRayDepth+1]; nVar->cDepth = nVar->destForEachLevel; } } /////////////////////////////////////////////////////////////////////// // Class : CGlobalIllumLookup // Method : CGlobalIllumLookup // Description : Ctor // Return Value : - // Comments : // Date last edited : 3/10/2001 CGlobalIllumLookup::CGlobalIllumLookup() { } /////////////////////////////////////////////////////////////////////// // Class : CGlobalIllumLookup // Method : ~CGlobalIllumLookup // Description : Dtor // Return Value : - // Comments : // Date last edited : 3/10/2001 CGlobalIllumLookup::~CGlobalIllumLookup() { if (cache != NULL) cache->finalize(this); } /////////////////////////////////////////////////////////////////////// // Class : CShader // Method : CShader // Description : Constructor // Return Value : - // Comments : // Date last edited : 3/10/2001 CShader::CShader(const char *name) : CFileResource(name) { stats.numShaders++; name = NULL; memory = NULL; codeArea = NULL; parametersArea = NULL; constantsArea = NULL; parameterEntries = NULL; parameterDisplacements = NULL; constantEntries = NULL; varyingSizes = NULL; uniformSizes = NULL; strings = NULL; parameters = NULL; cache = NULL; dirty = FALSE; } /////////////////////////////////////////////////////////////////////// // Class : CShader // Method : ~CShader // Description : Dtor // Return Value : - // Comments : // Date last edited : 3/10/2001 CShader::~CShader() { int i; stats.numShaders--; for (i=0;iattach(); categories = NULL; } /////////////////////////////////////////////////////////////////////// // Class : CShaderInstance // Method : CShaderInstance // Description : Ctor // Return Value : - // Comments : // Date last edited : 3/10/2001 CShaderInstance::~CShaderInstance() { stats.numShaderInstances--; xform->detach(); if (categories != NULL) delete[] categories; } /////////////////////////////////////////////////////////////////////// // Function : getToken // Description : This function implements "strsep" which is non portable // Return Value : // Comments : // Date last edited : 10/1/2005 static char *token(char **str,char *tok) { char *cStr = *str; char *oStr = cStr; int n = strlen(tok); int i; if (cStr == NULL) return NULL; // Walk the string for (;;) { // Did we run out of string ? if (*cStr == '\0') { *str = NULL; break; } // Check for a delimiter for (i=0;igetGlobalID(cCat); } while (tmp != NULL); categories[i++] = 0; // terminate the list free(categoryString); } } /////////////////////////////////////////////////////////////////////// // Class : CProgrammableShaderInstance // Method : CProgrammableShaderInstance // Description : Ctor // Return Value : - // Comments : // Date last edited : 3/10/2001 CProgrammableShaderInstance::CProgrammableShaderInstance(CShader *p,CAttributes *a,CXform *x) : CShaderInstance(a,x) { int i; parent = p; // Create a new place to store the parameters parametersArea = new TCode[parent->totalParameterSize]; parameterEntries = new TCode*[parent->numParameters]; // Copy the default values from parent memcpy(parametersArea,parent->parametersArea,parent->totalParameterSize*sizeof(TCode)); // Set the parameter pointers for (i=0;inumParameters;i++) { parameterEntries[i] = ¶metersArea[parent->parameterDisplacements[i]]; } numStrings = 0; strings = NULL; if (parent->numPLs > 0) { parameterLists = new CShaderLookup*[parent->numPLs]; for (i=0;inumPLs;i++) parameterLists[i] = NULL; } else { parameterLists = NULL; } flags = (parent->usedParameters & PARAMETER_NONAMBIENT) ? SHADERFLAGS_NONAMBIENT : 0; dirty = FALSE; } /////////////////////////////////////////////////////////////////////// // Class : CProgrammableShaderInstance // Method : ~CProgrammableShaderInstance // Description : Dtor // Return Value : - // Comments : // Date last edited : 3/10/2001 CProgrammableShaderInstance::~CProgrammableShaderInstance() { if (parametersArea != parent->parametersArea) delete [] parametersArea; if (parameterEntries != parent->parameterEntries) delete [] parameterEntries; if (strings != NULL) { int i; for (i=0;inumPLs;i++) { assert(parameterLists[i] == NULL); } assert(dirty == FALSE); #endif delete [] parameterLists; } } /////////////////////////////////////////////////////////////////////// // Class : CProgrammableShaderInstance // Method : setParameters // Description : Set the values of the parameters // Return Value : - // Comments : // Date last edited : 3/10/2001 int CProgrammableShaderInstance::setParameter(char *param,void *val) { int j; for (j=0;jnumParameters;j++) { if (strcmp(param,parent->parameters[j].name) == 0) { switch(parent->parameters[j].type) { case TYPE_FLOAT: { const float *src = (const float *) val; float *dest = ¶meterEntries[j]->real; memcpy(dest,src,parent->parameters[j].numItems*sizeof(float)); } break; case TYPE_COLOR: { int p; const float *src = (const float *) val; float *dest = ¶meterEntries[j]->real; for (p=0;pparameters[j].numItems;p++) { movvv(dest,src); dest += 3; src += 3; } } break; case TYPE_VECTOR: { int p; const float *src = (const float *) val; float *dest = ¶meterEntries[j]->real; for (p=0;pparameters[j].numItems;p++) { mulmv(dest,xform->from,src); dest += 3; src += 3; } } break; case TYPE_NORMAL: { int p; const float *src = (const float *) val; float *dest = ¶meterEntries[j]->real; for (p=0;pparameters[j].numItems;p++) { mulmn(dest,xform->to,src); dest += 3; src += 3; } } break; case TYPE_POINT: { int p; const float *src = (const float *) val; float *dest = ¶meterEntries[j]->real; for (p=0;pparameters[j].numItems;p++) { mulmp(dest,xform->from,src); dest += 3; src += 3; } } break; case TYPE_MATRIX: { const float *src = (const float *) val; float *dest = ¶meterEntries[j]->real; memcpy(dest,src,parent->parameters[j].numItems*sizeof(matrix)); } break; case TYPE_QUAD: { const float *src = (const float *) val; float *dest = ¶meterEntries[j]->real; memcpy(dest,src,parent->parameters[j].numItems*sizeof(float)*4); } break; case TYPE_DOUBLE: { const float *src = (const float *) val; float *dest = ¶meterEntries[j]->real; memcpy(dest,src,parent->parameters[j].numItems*sizeof(float)*2); } break; case TYPE_STRING: { const char **src = (const char **) val; const char **dest = ¶meterEntries[j]->string; int t; for (t=0;tparameters[j].numItems;t++) { *dest++ = strings[numStrings++] = strdup(*src++); } } break; case TYPE_INTEGER: case TYPE_BOOLEAN: { const int *src = (int *) val; int *dest = ¶meterEntries[j]->integer; memcpy(dest,src,parent->parameters[j].numItems*sizeof(int)); } break; default: break; } break; } } return j != parent->numParameters; } /////////////////////////////////////////////////////////////////////// // Class : CProgrammableShaderInstance // Method : setParameters // Description : Set the values of the parameters // Return Value : - // Comments : // Date last edited : 3/10/2001 void CProgrammableShaderInstance::setParameters(int np,char **params,void **vals) { int i; // Count the number of new strings that need allocation for (i=0;inumParameters;j++) { if (parent->parameters[j].type == TYPE_STRING) { numStrings += parent->parameters[j].numItems; } } } strings = new char*[numStrings]; numStrings = 0; // Set the parameter defaults for (i=0;inumParameters;i++) { if (strcmp(name,parent->parameters[i].name) == 0) { if (parent->parameters[i].global != NULL) { if ((var == NULL) || (globalIndex == NULL)) continue; *var = parent->parameters[i].global; *globalIndex = globalNumber; return TRUE; } switch(parent->parameters[i].type) { case TYPE_FLOAT: destFloat = (float *) dest; srcFloat = ¶meterEntries[i]->real; for (j=0;jparameters[i].numItems;j++) *destFloat++ = *srcFloat++; break; case TYPE_COLOR: case TYPE_VECTOR: case TYPE_NORMAL: case TYPE_POINT: destFloat = (float *) dest; srcFloat = ¶meterEntries[i]->real; for (j=0;jparameters[i].numItems*3;j++) *destFloat++ = *srcFloat++; break; case TYPE_MATRIX: destFloat = (float *) dest; srcFloat = ¶meterEntries[i]->real; for (j=0;jparameters[i].numItems*16;j++) *destFloat++ = *srcFloat++; break; case TYPE_QUAD: destFloat = (float *) dest; srcFloat = ¶meterEntries[i]->real; for (j=0;jparameters[i].numItems*4;j++) *destFloat++ = *srcFloat++; break; case TYPE_DOUBLE: destFloat = (float *) dest; srcFloat = ¶meterEntries[i]->real; for (j=0;jparameters[i].numItems*2;j++) *destFloat++ = *srcFloat++; break; case TYPE_STRING: destString = (const char **) dest; srcString = ¶meterEntries[i]->string; for (j=0;jparameters[i].numItems;j++) *destString++ = *srcString++; break; case TYPE_INTEGER: case TYPE_BOOLEAN: destInt = (int *) dest; srcInt = ¶meterEntries[i]->integer; for (j=0;jparameters[i].numItems;j++) *destInt++ = *srcInt++; break; default: break; } return TRUE; } else { if (parent->parameters[i].global != NULL) globalNumber++; } } return FALSE; } /////////////////////////////////////////////////////////////////////// // Class : CProgrammableShaderInstance // Method : execute // Description : Actually execute the shader // Return Value : - // Comments : // Date last edited : 3/10/2001 void CProgrammableShaderInstance::execute(CShadingContext *context) { context->execute(this); } /////////////////////////////////////////////////////////////////////// // Class : CProgrammableShaderInstance // Method : requiredParameters // Description : Return the required parameters // Return Value : - // Comments : // Date last edited : 3/10/2001 unsigned int CProgrammableShaderInstance::requiredParameters() { return parent->usedParameters; } /////////////////////////////////////////////////////////////////////// // Class : CProgrammableShaderInstance // Method : registerDefaults // Description : Register the global variables that need to be defaulted // Return Value : - // Comments : // Date last edited : 3/10/2001 void CProgrammableShaderInstance::registerDefaults(CAttributes *cAttributes, CActiveLight *light) { int i; void *data; for (i=0;inumParameters;i++) { if (parent->parameters[i].global != NULL) { switch(parent->parameters[i].type) { case TYPE_FLOAT: case TYPE_COLOR: case TYPE_VECTOR: case TYPE_NORMAL: case TYPE_POINT: case TYPE_MATRIX: case TYPE_QUAD: case TYPE_DOUBLE: data = ¶meterEntries[i]->real; break; case TYPE_STRING: data = ¶meterEntries[i]->string; break; case TYPE_INTEGER: case TYPE_BOOLEAN: data = ¶meterEntries[i]->integer; break; default: error(CODE_BUG,"Unrecognised parameter type in the shader\n"); break; } cAttributes->addDefault(parent->parameters[i].global,data,light); } } } /////////////////////////////////////////////////////////////////////// // Class : CProgrammableShaderInstance // Method : getName // Description : Get the name of the shader // Return Value : - // Comments : // Date last edited : 3/10/2001 const char *CProgrammableShaderInstance::getName() { return parent->name; } /////////////////////////////////////////////////////////////////////// // Class : CProgrammableShaderInstance // Method : illuminate // Description : Illuminate the shading state is a lightsource shader // Return Value : - // Comments : // Date last edited : 3/10/2001 void CProgrammableShaderInstance::illuminate(CShadingContext *context) { // This function should never be called for non-light shaders context->execute(this); } /////////////////////////////////////////////////////////////////////// // Function : debugFunction // Description : This function is used to debugging purposes // Return Value : - // Comments : // Date last edited : 2/4/2003 void debugFunction(float *op) { int i = 1; printf("Debug\n"); }