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