1 // GL_ARB_vertex_program, GL_ARB_fragment_program 2 extern PFNGLGENPROGRAMSARBPROC glGenPrograms_; 3 extern PFNGLDELETEPROGRAMSARBPROC glDeletePrograms_; 4 extern PFNGLBINDPROGRAMARBPROC glBindProgram_; 5 extern PFNGLPROGRAMSTRINGARBPROC glProgramString_; 6 extern PFNGLGETPROGRAMIVARBPROC glGetProgramiv_; 7 extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4f_; 8 extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fv_; 9 extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArray_; 10 extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArray_; 11 extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointer_; 12 13 // GL_EXT_gpu_program_parameters 14 #ifndef GL_EXT_gpu_program_parameters 15 #define GL_EXT_gpu_program_parameters 1 16 typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params); 17 typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params); 18 #endif 19 20 extern PFNGLPROGRAMENVPARAMETERS4FVEXTPROC glProgramEnvParameters4fv_; 21 extern PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC glProgramLocalParameters4fv_; 22 23 // GL_ARB_shading_language_100, GL_ARB_shader_objects, GL_ARB_fragment_shader, GL_ARB_vertex_shader 24 extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObject_; 25 extern PFNGLDELETEOBJECTARBPROC glDeleteObject_; 26 extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObject_; 27 extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObject_; 28 extern PFNGLSHADERSOURCEARBPROC glShaderSource_; 29 extern PFNGLCOMPILESHADERARBPROC glCompileShader_; 30 extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameteriv_; 31 extern PFNGLATTACHOBJECTARBPROC glAttachObject_; 32 extern PFNGLGETINFOLOGARBPROC glGetInfoLog_; 33 extern PFNGLLINKPROGRAMARBPROC glLinkProgram_; 34 extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocation_; 35 extern PFNGLUNIFORM4FVARBPROC glUniform4fv_; 36 extern PFNGLUNIFORM1IARBPROC glUniform1i_; 37 38 extern int renderpath; 39 40 enum { R_FIXEDFUNCTION = 0, R_ASMSHADER, R_GLSLANG }; 41 42 enum { SHPARAM_LOOKUP = 0, SHPARAM_VERTEX, SHPARAM_PIXEL, SHPARAM_UNIFORM }; 43 44 #define RESERVEDSHADERPARAMS 16 45 #define MAXSHADERPARAMS 8 46 47 struct ShaderParam 48 { 49 const char *name; 50 int type, index, loc; 51 float val[4]; 52 }; 53 54 struct LocalShaderParamState : ShaderParam 55 { 56 float curval[4]; 57 LocalShaderParamStateLocalShaderParamState58 LocalShaderParamState() 59 { 60 memset(curval, -1, sizeof(curval)); 61 } LocalShaderParamStateLocalShaderParamState62 LocalShaderParamState(const ShaderParam &p) : ShaderParam(p) 63 { 64 memset(curval, -1, sizeof(curval)); 65 } 66 }; 67 68 struct ShaderParamState 69 { 70 enum 71 { 72 CLEAN = 0, 73 INVALID, 74 DIRTY 75 }; 76 77 const char *name; 78 float val[4]; 79 bool local; 80 int dirty; 81 ShaderParamStateShaderParamState82 ShaderParamState() 83 : name(NULL), local(false), dirty(INVALID) 84 { 85 memset(val, -1, sizeof(val)); 86 } 87 }; 88 89 enum 90 { 91 SHADER_DEFAULT = 0, 92 SHADER_NORMALSLMS = 1<<0, 93 SHADER_ENVMAP = 1<<1, 94 SHADER_GLSLANG = 1<<2, 95 SHADER_OPTION = 1<<3, 96 SHADER_INVALID = 1<<4, 97 SHADER_DEFERRED = 1<<5 98 }; 99 100 #define MAXSHADERDETAIL 3 101 #define MAXVARIANTROWS 5 102 103 extern int shaderdetail; 104 105 struct Slot; 106 107 struct Shader 108 { 109 static Shader *lastshader; 110 111 char *name, *vsstr, *psstr, *defer; 112 int type; 113 GLuint vs, ps; 114 GLhandleARB program, vsobj, psobj; 115 vector<LocalShaderParamState> defaultparams; 116 Shader *detailshader, *variantshader, *altshader, *fastshader[MAXSHADERDETAIL]; 117 vector<Shader *> variants[MAXVARIANTROWS]; 118 bool standard, forced, used, native; 119 Shader *reusevs, *reuseps; 120 int numextparams; 121 LocalShaderParamState *extparams; 122 uchar *extvertparams, *extpixparams; 123 ShaderShader124 Shader() : name(NULL), vsstr(NULL), psstr(NULL), defer(NULL), type(SHADER_DEFAULT), vs(0), ps(0), program(0), vsobj(0), psobj(0), detailshader(NULL), variantshader(NULL), altshader(NULL), standard(false), forced(false), used(false), native(true), reusevs(NULL), reuseps(NULL), numextparams(0), extparams(NULL), extvertparams(NULL), extpixparams(NULL) 125 { 126 loopi(MAXSHADERDETAIL) fastshader[i] = this; 127 } 128 ~ShaderShader129 ~Shader() 130 { 131 DELETEA(name); 132 DELETEA(vsstr); 133 DELETEA(psstr); 134 DELETEA(defer); 135 DELETEA(extparams); 136 DELETEA(extvertparams); 137 extpixparams = NULL; 138 } 139 140 void fixdetailshader(bool force = true, bool recurse = true); 141 void allocenvparams(Slot *slot = NULL); 142 void flushenvparams(Slot *slot = NULL); 143 void setslotparams(Slot &slot); 144 void bindprograms(); 145 hasoptionShader146 bool hasoption(int row) 147 { 148 if(!detailshader || detailshader->variants[row].empty()) return false; 149 return (detailshader->variants[row][0]->type&SHADER_OPTION)!=0; 150 } 151 setvariantShader152 void setvariant(int col, int row, Slot *slot, Shader *fallbackshader) 153 { 154 if(!this || !detailshader || renderpath==R_FIXEDFUNCTION) return; 155 int len = detailshader->variants[row].length(); 156 if(col >= len) col = len-1; 157 Shader *s = fallbackshader; 158 while(col >= 0) if(!(detailshader->variants[row][col]->type&SHADER_INVALID)) { s = detailshader->variants[row][col]; break; } 159 if(lastshader!=s) s->bindprograms(); 160 lastshader->flushenvparams(slot); 161 if(slot) lastshader->setslotparams(*slot); 162 } 163 164 void setvariant(int col, int row = 0, Slot *slot = NULL) 165 { 166 setvariant(col, row, slot, detailshader); 167 } 168 169 void set(Slot *slot = NULL) 170 { 171 if(!this || !detailshader || renderpath==R_FIXEDFUNCTION) return; 172 if(lastshader!=detailshader) detailshader->bindprograms(); 173 lastshader->flushenvparams(slot); 174 if(slot) lastshader->setslotparams(*slot); 175 } 176 177 bool compile(); 178 void cleanup(bool invalid = false); 179 }; 180 181 #define SETSHADER(name) \ 182 do { \ 183 static Shader *name##shader = NULL; \ 184 if(!name##shader) name##shader = lookupshaderbyname(#name); \ 185 name##shader->set(); \ 186 } while(0) 187 188 struct ImageData 189 { 190 int w, h, bpp, levels, align, pitch; 191 GLenum compressed; 192 uchar *data; 193 void *owner; 194 void (*freefunc)(void *); 195 ImageDataImageData196 ImageData() 197 : data(NULL), owner(NULL), freefunc(NULL) 198 {} 199 200 201 ImageData(int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE) 202 { 203 setdata(NULL, nw, nh, nbpp, nlevels, nalign, ncompressed); 204 } 205 ImageDataImageData206 ImageData(int nw, int nh, int nbpp, uchar *data) 207 : owner(NULL), freefunc(NULL) 208 { 209 setdata(data, nw, nh, nbpp); 210 } 211 ImageDataImageData212 ImageData(SDL_Surface *s) { wrap(s); } ~ImageDataImageData213 ~ImageData() { cleanup(); } 214 215 void setdata(uchar *ndata, int nw, int nh, int nbpp, int nlevels = 1, int nalign = 0, GLenum ncompressed = GL_FALSE) 216 { 217 w = nw; 218 h = nh; 219 bpp = nbpp; 220 levels = nlevels; 221 align = nalign; 222 pitch = align ? 0 : w*bpp; 223 compressed = ncompressed; 224 data = ndata ? ndata : new uchar[calcsize()]; 225 if(!ndata) { owner = this; freefunc = NULL; } 226 } 227 calclevelsizeImageData228 int calclevelsize(int level) const { return ((max(w>>level, 1)+align-1)/align)*((max(h>>level, 1)+align-1)/align)*bpp; } 229 calcsizeImageData230 int calcsize() const 231 { 232 if(!align) return w*h*bpp; 233 int lw = w, lh = h, 234 size = 0; 235 loopi(levels) 236 { 237 if(lw<=0) lw = 1; 238 if(lh<=0) lh = 1; 239 size += ((lw+align-1)/align)*((lh+align-1)/align)*bpp; 240 if(lw*lh==1) break; 241 lw >>= 1; 242 lh >>= 1; 243 } 244 return size; 245 } 246 disownImageData247 void disown() 248 { 249 data = NULL; 250 owner = NULL; 251 freefunc = NULL; 252 } 253 cleanupImageData254 void cleanup() 255 { 256 if(owner==this) delete[] data; 257 else if(freefunc) (*freefunc)(owner); 258 disown(); 259 } 260 replaceImageData261 void replace(ImageData &d) 262 { 263 cleanup(); 264 *this = d; 265 if(owner == &d) owner = this; 266 d.disown(); 267 } 268 wrapImageData269 void wrap(SDL_Surface *s) 270 { 271 setdata((uchar *)s->pixels, s->w, s->h, s->format->BytesPerPixel); 272 pitch = s->pitch; 273 owner = s; 274 freefunc = (void (*)(void *))SDL_FreeSurface; 275 } 276 }; 277 278 // management of texture slots 279 // each texture slot can have multiple texture frames, of which currently only the first is used 280 // additional frames can be used for various shaders 281 282 struct TextureAnim 283 { 284 int count, delay, x, y, w, h; 285 TextureAnimTextureAnim286 TextureAnim() : count(0), delay(0) {} 287 }; 288 289 290 struct Texture 291 { 292 enum 293 { 294 IMAGE = 0, 295 CUBEMAP = 1, 296 TYPE = 0xFF, 297 298 STUB = 1<<8, 299 TRANSIENT = 1<<9, 300 FLAGS = 0xF0 301 }; 302 303 char *name; 304 int type, w, h, xs, ys, bpp, clamp, frame, delay, last; 305 bool mipmap, canreduce; 306 vector<GLuint> frames; 307 GLuint id; 308 uchar *alphamask; 309 310 TextureTexture311 Texture() : frame(0), delay(0), last(0), alphamask(NULL) 312 { 313 frames.setsize(0); 314 } 315 idframeTexture316 GLuint idframe(int id) 317 { 318 if(!frames.empty()) 319 return frames[clamp(id, 0, frames.length()-1)]; 320 return id; 321 } 322 getframeTexture323 GLuint getframe(float amt) 324 { 325 if(!frames.empty()) 326 return frames[clamp(int((frames.length()-1)*amt), 0, frames.length()-1)]; 327 return id; 328 } 329 retframeTexture330 GLuint retframe(int cur, int total) 331 { 332 if(!frames.empty()) 333 return frames[clamp((frames.length()-1)*cur/total, 0, frames.length()-1)]; 334 return id; 335 } 336 }; 337 338 enum 339 { 340 TEX_DIFFUSE = 0, 341 TEX_UNKNOWN, 342 TEX_DECAL, 343 TEX_NORMAL, 344 TEX_GLOW, 345 TEX_SPEC, 346 TEX_DEPTH, 347 TEX_ENVMAP, 348 TEX_MAX 349 }; 350 351 struct Slot 352 { 353 struct Tex 354 { 355 int type; 356 Texture *t; 357 string lname, name; 358 int combined; 359 }; 360 361 vector<Tex> sts; 362 Shader *shader; 363 vector<ShaderParam> params; 364 float scale; 365 int rotation, xoffset, yoffset; 366 float scrollS, scrollT; 367 int layer; 368 vec glowcolor, pulseglowcolor; 369 float pulseglowspeed; 370 bool mtglowed, loaded; 371 uint texmask; 372 char *autograss; 373 Texture *grasstex, *thumbnail; 374 char *layermaskname; 375 int layermaskmode; 376 float layermaskscale; 377 ImageData *layermask; 378 SlotSlot379 Slot() : autograss(NULL), layermaskname(NULL), layermask(NULL) { reset(); } 380 resetSlot381 void reset() 382 { 383 sts.setsize(0); 384 shader = NULL; 385 params.setsize(0); 386 scale = 1; 387 rotation = xoffset = yoffset = 0; 388 scrollS = scrollT = 0; 389 layer = 0; 390 glowcolor = vec(1, 1, 1); 391 pulseglowcolor = vec(0, 0, 0); 392 pulseglowspeed = 0; 393 loaded = false; 394 texmask = 0; 395 DELETEA(autograss); 396 grasstex = NULL; 397 thumbnail = NULL; 398 DELETEA(layermaskname); 399 layermaskmode = 0; 400 layermaskscale = 1; 401 if(layermask) DELETEP(layermask); 402 } 403 cleanupSlot404 void cleanup() 405 { 406 loaded = false; 407 grasstex = NULL; 408 thumbnail = NULL; 409 if(layermask) DELETEP(layermask); 410 loopv(sts) 411 { 412 Tex &t = sts[i]; 413 t.t = NULL; 414 t.combined = -1; 415 } 416 } 417 }; 418 419 extern vector<Slot> slots; 420 extern Slot materialslots[MATF_VOLUME+1]; 421 422 extern void scaleimage(ImageData &s, int w, int h); 423 424 enum 425 { 426 IFMT_NONE = 0, 427 IFMT_BMP, 428 IFMT_PNG, 429 IFMT_TGA, 430 IFMT_MAX, 431 }; 432 extern const char *ifmtexts[IFMT_MAX]; 433 extern int imageformat; 434 435 extern void savepng(const char *filename, ImageData &image, int compress = 9, bool flip = false); 436 extern void savetga(const char *filename, ImageData &image, int compress = 1, bool flip = false); 437 extern void saveimage(const char *name, ImageData &image, int format = IFMT_NONE, int compress = 9, bool flip = false, bool skip = false); 438 extern SDL_Surface *loadsurface(const char *name); 439 extern bool loadimage(const char *name, ImageData &image); 440 extern bool loaddds(const char *filename, ImageData &image); 441 442 extern void resetmaterials(); 443 extern void resettextures(); 444 extern void setshader(char *name); 445 extern void setshaderparam(const char *name, int type, int n, float x, float y, float z, float w); 446 extern int findtexturetype(char *name, bool tryint = false); 447 extern const char *findtexturename(int type); 448 extern void texture(char *type, char *name, int *rot, int *xoffet, int *yoffset, float *scale); 449 extern void updatetextures(); 450 extern void preloadtextures(); 451 452 struct cubemapside 453 { 454 GLenum target; 455 const char *name; 456 bool flipx, flipy, swapxy; 457 }; 458 459 extern cubemapside cubemapsides[6]; 460 extern Texture *notexture, *blanktexture; 461 extern Shader *defaultshader, *rectshader, *notextureshader, *nocolorshader, *foggedshader, *foggednotextureshader, *stdworldshader; 462 extern int reservevpparams, maxvpenvparams, maxvplocalparams, maxfpenvparams, maxfplocalparams; 463 464 extern Shader *lookupshaderbyname(const char *name); 465 extern Shader *useshaderbyname(const char *name); 466 extern Texture *loadthumbnail(Slot &slot); 467 extern void resetslotshader(); 468 extern void setslotshader(Slot &s); 469 extern void linkslotshader(Slot &s, bool load = true); 470 extern void linkslotshaders(); 471 extern void setenvparamf(const char *name, int type, int index, float x = 0, float y = 0, float z = 0, float w = 0); 472 extern void setenvparamfv(const char *name, int type, int index, const float *v); 473 extern void flushenvparamf(const char *name, int type, int index, float x = 0, float y = 0, float z = 0, float w = 0); 474 extern void flushenvparamfv(const char *name, int type, int index, const float *v); 475 extern void setlocalparamf(const char *name, int type, int index, float x = 0, float y = 0, float z = 0, float w = 0); 476 extern void setlocalparamfv(const char *name, int type, int index, const float *v); 477 extern void invalidateenvparams(int type, int start, int count); 478 extern ShaderParam *findshaderparam(Slot &s, const char *name, int type, int index); 479 480 extern int maxtmus, nolights, nowater, nomasks; 481 482 extern void inittmus(); 483 extern void resettmu(int n); 484 extern void scaletmu(int n, int rgbscale, int alphascale = 0); 485 extern void colortmu(int n, float r = 0, float g = 0, float b = 0, float a = 0); 486 extern void setuptmu(int n, const char *rgbfunc = NULL, const char *alphafunc = NULL); 487 488 #define MAXDYNLIGHTS 5 489 #define DYNLIGHTBITS 6 490 #define DYNLIGHTMASK ((1<<DYNLIGHTBITS)-1) 491 492 #define MAXBLURRADIUS 7 493 494 extern void setupblurkernel(int radius, float sigma, float *weights, float *offsets); 495 extern void setblurshader(int pass, int size, int radius, float *weights, float *offsets, GLenum target = GL_TEXTURE_2D); 496 497 #define _TVAR(n, c, m, p) _SVARF(n, n, c, { if(n[0]) textureload(n, m, true); }, p) 498 #define TVAR(n, c, m) _TVAR(n, c, m, IDF_PERSIST|IDF_COMPLETE|IDF_TEXTURE) 499 #define TVARW(n, c, m) _TVAR(n, c, m, IDF_WORLD|IDF_COMPLETE|IDF_TEXTURE) 500 #define _TVARN(n, c, t, m, p) _SVARF(n, n, c, { t = n[0] ? textureload(n, m, true) : notexture; }, p) 501 #define TVARN(n, c, t, m) _TVARN(n, c, t, m, IDF_PERSIST|IDF_COMPLETE|IDF_TEXTURE) 502 #define TVARC(n, c, t, m) Texture *##t; _TVARN(n, c, t, m, IDF_PERSIST|IDF_COMPLETE|IDF_TEXTURE) 503 504 #define _ITVAR(n, c, m, p) _ISVAR(n, c, void changed() { if(*val.s) textureload(val.s, m, true); }, p) 505 #define ITVAR(n, c, m) _ITVAR(n, c, m, IDF_PERSIST|IDF_COMPLETE|IDF_TEXTURE) 506 #define ITVARW(n, c, m) _ITVAR(n, c, m, IDF_WORLD|IDF_COMPLETE|IDF_TEXTURE) 507