r_program.c

Go to the documentation of this file.
00001 
00006 /*
00007 * Copyright(c) 1997-2001 Id Software, Inc.
00008 * Copyright(c) 2002 The Quakeforge Project.
00009 * Copyright(c) 2006 Quake2World.
00010 *
00011 * This program is free software; you can redistribute it and/or
00012 * modify it under the terms of the GNU General Public License
00013 * as published by the Free Software Foundation; either version 2
00014 * of the License, or(at your option) any later version.
00015 *
00016 * This program is distributed in the hope that it will be useful,
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00019 *
00020 * See the GNU General Public License for more details.
00021 *
00022 * You should have received a copy of the GNU General Public License
00023 * along with this program; if not, write to the Free Software
00024 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00025 */
00026 
00027 #include "r_local.h"
00028 #include "r_error.h"
00029 #include "../../shared/parse.h"
00030 #include "../../shared/shared.h"
00031 
00032 
00033 #define SHADER_BUF_SIZE 16384
00034 
00035 void R_UseProgram  (r_program_t *prog)
00036 {
00037     if (!qglUseProgram || r_state.active_program == prog)
00038         return;
00039 
00040     r_state.active_program = prog;
00041 
00042     if (prog) {
00043         qglUseProgram(prog->id);
00044 
00045         if (prog->use)  /* invoke use function */
00046             prog->use(prog);
00047     } else {
00048         qglUseProgram(0);
00049     }
00050 }
00051 
00052 #ifdef DEBUG
00053 #define R_ProgramVariable(x, y) R_ProgramVariable_Debug(x, y, file, line)
00054 static r_progvar_t *R_ProgramVariable_Debug (int type, const char *name, const char *file, int line)
00055 #else
00056 static r_progvar_t *R_ProgramVariable (int type, const char *name)
00057 #endif
00058 {
00059     r_progvar_t *v;
00060     int i;
00061 
00062     if (!r_state.active_program) {
00063 #ifdef DEBUG
00064         Com_DPrintf(DEBUG_RENDERER, "R_ProgramVariable: \"%s\" - No program bound. (%s: line %d)\n", name, file, line);
00065 #else
00066         Com_DPrintf(DEBUG_RENDERER, "R_ProgramVariable: \"%s\" - No program bound.\n", name);
00067 #endif
00068         return NULL;
00069     }
00070 
00071     /* find the variable */
00072     for (i = 0; i < MAX_PROGRAM_VARS; i++) {
00073         v = &r_state.active_program->vars[i];
00074 
00075         if (!v->location)
00076             break;
00077 
00078         if (v->type == type && !strcmp(v->name, name))
00079             return v;
00080     }
00081 
00082     if (i == MAX_PROGRAM_VARS) {
00083         Com_Printf("R_ProgramVariable: MAX_PROGRAM_VARS reached.\n");
00084         return NULL;
00085     }
00086 
00087     /* or query for it */
00088     if (type == GL_UNIFORM)
00089         v->location = qglGetUniformLocation(r_state.active_program->id, name);
00090     else
00091         v->location = qglGetAttribLocation(r_state.active_program->id, name);
00092 
00093     if (v->location == -1) {
00094 #ifdef DEBUG
00095         Com_Printf("R_ProgramVariable: Could not find %s in program %s. (%s: line %d)\n",
00096             name, r_state.active_program->name, file, line);
00097 #else
00098         Com_Printf("R_ProgramVariable: Could not find parameter in program.\n");
00099 #endif
00100         v->location = 0;
00101         return NULL;
00102     }
00103 
00104     v->type = type;
00105     Q_strncpyz(v->name, name, sizeof(v->name));
00106 
00107     return v;
00108 }
00109 
00110 #ifdef DEBUG
00111 void R_ProgramParameter1i_Debug (const char *name, GLint value , const char *file, int line)
00112 #else
00113 void R_ProgramParameter1i (const char *name, GLint value)
00114 #endif
00115 {
00116     r_progvar_t *v;
00117 
00118     if (!(v = R_ProgramVariable(GL_UNIFORM, name)))
00119         return;
00120 
00121     qglUniform1i(v->location, value);
00122 }
00123 
00124 #ifdef DEBUG
00125 void R_ProgramParameter1f_Debug (const char *name, GLfloat value , const char *file, int line)
00126 #else
00127 void R_ProgramParameter1f (const char *name, GLfloat value)
00128 #endif
00129 {
00130     r_progvar_t *v;
00131 
00132     if (!(v = R_ProgramVariable(GL_UNIFORM, name)))
00133         return;
00134 
00135     qglUniform1f(v->location, value);
00136 }
00137 
00138 #ifdef DEBUG
00139 void R_ProgramParameter1fvs_Debug (const char *name, GLint size, GLfloat *value , const char *file, int line)
00140 #else
00141 void R_ProgramParameter1fvs (const char *name, GLint size, GLfloat *value)
00142 #endif
00143 {
00144     r_progvar_t *v;
00145 
00146     if (!(v = R_ProgramVariable(GL_UNIFORM, name)))
00147         return;
00148 
00149     qglUniform1fv(v->location, size, value);
00150 }
00151 
00152 #ifdef DEBUG
00153 void R_ProgramParameter2fv_Debug (const char *name, GLfloat *value , const char *file, int line)
00154 #else
00155 void R_ProgramParameter2fv (const char *name, GLfloat *value)
00156 #endif
00157 {
00158     r_progvar_t *v;
00159 
00160     if (!(v = R_ProgramVariable(GL_UNIFORM, name)))
00161         return;
00162 
00163     qglUniform2fv(v->location, 1, value);
00164 }
00165 
00166 #ifdef DEBUG
00167 void R_ProgramParameter2fvs_Debug (const char *name, GLint size, GLfloat *value , const char *file, int line)
00168 #else
00169 void R_ProgramParameter2fvs (const char *name, GLint size, GLfloat *value)
00170 #endif
00171 {
00172     r_progvar_t *v;
00173 
00174     if (!(v = R_ProgramVariable(GL_UNIFORM, name)))
00175         return;
00176 
00177     qglUniform2fv(v->location, size, value);
00178 }
00179 
00180 #ifdef DEBUG
00181 void R_ProgramParameter3fv_Debug (const char *name, GLfloat *value , const char *file, int line)
00182 #else
00183 void R_ProgramParameter3fv (const char *name, GLfloat *value)
00184 #endif
00185 {
00186     r_progvar_t *v;
00187 
00188     if (!(v = R_ProgramVariable(GL_UNIFORM, name)))
00189         return;
00190 
00191     qglUniform3fv(v->location, 1, value);
00192 }
00193 
00194 #ifdef DEBUG
00195 void R_ProgramParameter4fv_Debug (const char *name, GLfloat *value , const char *file, int line)
00196 #else
00197 void R_ProgramParameter4fv (const char *name, GLfloat *value)
00198 #endif
00199 {
00200     r_progvar_t *v;
00201 
00202     if (!(v = R_ProgramVariable(GL_UNIFORM, name)))
00203         return;
00204 
00205     qglUniform4fv(v->location, 1, value);
00206 }
00207 
00208 #ifdef DEBUG
00209 void R_AttributePointer_Debug (const char *name, GLuint size, const GLvoid *array , const char *file, int line)
00210 #else
00211 void R_AttributePointer (const char *name, GLuint size, const GLvoid *array)
00212 #endif
00213 {
00214     r_progvar_t *v;
00215 
00216     if (!(v = R_ProgramVariable(GL_ATTRIBUTE, name)))
00217         return;
00218 
00219     qglVertexAttribPointer(v->location, size, GL_FLOAT, GL_FALSE, 0, array);
00220 }
00221 
00222 #ifdef DEBUG
00223 void R_EnableAttribute_Debug (const char *name , const char *file, int line)
00224 #else
00225 void R_EnableAttribute (const char *name)
00226 #endif
00227 {
00228     r_progvar_t *v;
00229 
00230     if (!(v = R_ProgramVariable(GL_ATTRIBUTE, name)))
00231         return;
00232 
00233     qglEnableVertexAttribArray(v->location);
00234 }
00235 
00236 #ifdef DEBUG
00237 void R_DisableAttribute_Debug (const char *name , const char *file, int line)
00238 #else
00239 void R_DisableAttribute (const char *name)
00240 #endif
00241 {
00242     r_progvar_t *v;
00243 
00244     if (!(v = R_ProgramVariable(GL_ATTRIBUTE, name)))
00245         return;
00246 
00247     qglDisableVertexAttribArray(v->location);
00248 }
00249 
00250 static void R_ShutdownShader (r_shader_t *sh)
00251 {
00252     qglDeleteShader(sh->id);
00253     memset(sh, 0, sizeof(*sh));
00254 }
00255 
00256 static void R_ShutdownProgram (r_program_t *prog)
00257 {
00258     if (prog->v) {
00259         qglDetachShader(prog->id, prog->v->id);
00260         R_ShutdownShader(prog->v);
00261         R_CheckError();
00262     }
00263     if (prog->f) {
00264         qglDetachShader(prog->id, prog->f->id);
00265         R_ShutdownShader(prog->f);
00266         R_CheckError();
00267     }
00268 
00269     qglDeleteProgram(prog->id);
00270 
00271     memset(prog, 0, sizeof(*prog));
00272 }
00273 
00274 void R_ShutdownPrograms (void)
00275 {
00276     int i;
00277 
00278     if (!qglDeleteProgram)
00279         return;
00280 
00281     if (!r_programs->integer)
00282         return;
00283 
00284     for (i = 0; i < MAX_PROGRAMS; i++) {
00285         if (!r_state.programs[i].id)
00286             continue;
00287 
00288         R_ShutdownProgram(&r_state.programs[i]);
00289     }
00290 }
00291 
00292 static size_t R_PreprocessShaderAddToShaderBuf (const char *name, const char *in, char **out, size_t *len)
00293 {
00294     const size_t inLength = strlen(in);
00295     strcpy(*out, in);
00296     *out += inLength;
00297     *len -= inLength;
00298     return inLength;
00299 }
00300 
00301 static size_t R_InitializeShader (const char *name, char *out, size_t len)
00302 {
00303     size_t i;
00304     const char *hwHack, *defines;
00305 
00306     switch (r_config.hardwareType) {
00307     case GLHW_ATI:
00308         hwHack = "#ifndef ATI\n#define ATI\n#endif\n";
00309         break;
00310     case GLHW_INTEL:
00311         hwHack = "#ifndef INTEL\n#define INTEL\n#endif\n";
00312         break;
00313     case GLHW_NVIDIA:
00314         hwHack = "#ifndef NVIDIA\n#define NVIDIA\n#endif\n";
00315         break;
00316     case GLHW_GENERIC:
00317     case GLHW_MESA:
00318         hwHack = NULL;
00319         break;
00320     default:
00321         Com_Error(ERR_FATAL, "R_PreprocessShader: Unknown hardwaretype");
00322     }
00323 
00324     i = 0;
00325 
00326     defines = "#version 110\n";
00327     i += R_PreprocessShaderAddToShaderBuf(name, defines, &out, &len);
00328     defines = va("#ifndef r_width\n#define r_width %f\n#endif\n", (float)viddef.width);
00329     i += R_PreprocessShaderAddToShaderBuf(name, defines, &out, &len);
00330     defines = va("#ifndef r_height\n#define r_height %f\n#endif\n", (float)viddef.height);
00331     i += R_PreprocessShaderAddToShaderBuf(name, defines, &out, &len);
00332 
00333     if (hwHack)
00334         i += R_PreprocessShaderAddToShaderBuf(name, hwHack, &out, &len);
00335 
00336     return i;
00337 }
00338 
00339 static size_t R_PreprocessShader (const char *name, const char *in, char *out, int len)
00340 {
00341     byte *buffer;
00342     size_t i = 0;
00343 
00345     while (*in) {
00346         if (!strncmp(in, "#include", 8)) {
00347             char path[MAX_QPATH];
00348             byte *buf;
00349             size_t inc_len;
00350             in += 8;
00351             Com_sprintf(path, sizeof(path), "shaders/%s", Com_Parse(&in));
00352 
00353             if (FS_LoadFile(path, &buf) == -1) {
00354                 Com_Printf("Failed to resolve #include: %s.\n", path);
00355                 continue;
00356             }
00357 
00358             inc_len = R_PreprocessShader(name, (const char *)buf, out, len);
00359             len -= inc_len;
00360             out += inc_len;
00361             FS_FreeFile(buf);
00362         }
00363 
00364         if (!strncmp(in, "#if", 3)) {  /* conditionals */
00365             float f;
00366             qboolean elseclause = qfalse;
00367 
00368             in += 3;
00369 
00370             f = Cvar_GetValue(Com_Parse(&in));
00371 
00372             while (*in) {
00373                 if (!strncmp(in, "#endif", 6)) {
00374                     in += 6;
00375                     break;
00376                 }
00377 
00378                 if (!strncmp(in, "#else", 5)) {
00379                     in += 5;
00380                     elseclause = qtrue;
00381                 }
00382 
00383                 len--;
00384                 if (len < 0) {
00385                     Com_Error(ERR_DROP, "R_PreprocessShader: Overflow: %s", name);
00386                 }
00387 
00388                 if ((f && !elseclause) || (!f && elseclause)) {
00389                     if (!strncmp(in, "#unroll", 7)) {  /* loop unrolling */
00390                         int j, z;
00391                         size_t subLength = 0;
00392 
00393                         buffer = Mem_PoolAlloc(SHADER_BUF_SIZE, vid_imagePool, 0);
00394 
00395                         in += 7;
00396                         z = Cvar_GetValue(Com_Parse(&in));
00397 
00398                         while (*in) {
00399                             if (!strncmp(in, "#endunroll", 10)) {
00400                                 in += 10;
00401                                 break;
00402                             }
00403 
00404                             buffer[subLength++] = *in++;
00405 
00406                             if (subLength >= SHADER_BUF_SIZE)
00407                                 Com_Error(ERR_FATAL, "R_PreprocessShader: Overflow in shader loading '%s'", name);
00408                         }
00409 
00410                         for (j = 0; j < z; j++) {
00411                             int l;
00412                             for (l = 0; l < subLength; l++) {
00413                                 if (buffer[l] == '$') {
00414                                     Com_sprintf(out, subLength - l, "%d", j);
00415                                     out += (j / 10) + 1;
00416                                     i += (j / 10) + 1;
00417                                     len -= (j / 10) + 1;
00418                                 } else {
00419                                     *out++ = buffer[l];
00420                                     i++;
00421                                     len--;
00422                                 }
00423                                 if (len < 0)
00424                                     Com_Error(ERR_FATAL, "R_PreprocessShader: Overflow in shader loading '%s'", name);
00425                             }
00426                         }
00427 
00428                         Mem_Free(buffer);
00429                     } else {
00430                         *out++ = *in++;
00431                         i++;
00432                     }
00433                 } else
00434                     in++;
00435             }
00436 
00437             if (!*in) {
00438                 Com_Error(ERR_DROP, "R_PreprocessShader: Unterminated conditional: %s", name);
00439             }
00440         }
00441 
00442 
00443         if (!strncmp(in, "#unroll", 7)) {  /* loop unrolling */
00444             int j, z;
00445             size_t subLength = 0;
00446 
00447             buffer = Mem_PoolAlloc(SHADER_BUF_SIZE, vid_imagePool, 0);
00448 
00449             in += 7;
00450             z = Cvar_GetValue(Com_Parse(&in));
00451 
00452             while (*in) {
00453                 if (!strncmp(in, "#endunroll", 10)) {
00454                     in += 10;
00455                     break;
00456                 }
00457 
00458                 buffer[subLength++] = *in++;
00459                 if (subLength >= SHADER_BUF_SIZE)
00460                     Com_Error(ERR_FATAL, "R_PreprocessShader: Overflow in shader loading '%s'", name);
00461             }
00462 
00463             for (j = 0; j < z; j++) {
00464                 int l;
00465                 for (l = 0; l < subLength; l++) {
00466                     if (buffer[l] == '$') {
00467                         Com_sprintf(out, subLength - l, "%d", j);
00468                         out += (j / 10) + 1;
00469                         i += (j / 10) + 1;
00470                         len -= (j / 10) + 1;
00471                     } else {
00472                         *out++ = buffer[l];
00473                         i++;
00474                         len--;
00475                     }
00476                     if (len < 0)
00477                         Com_Error(ERR_FATAL, "R_PreprocessShader: Overflow in shader loading '%s'", name);
00478                 }
00479             }
00480 
00481             Mem_Free(buffer);
00482         }
00483 
00484         if (!strncmp(in, "#replace", 8)) {
00485             int r;
00486             in += 8;
00487             r = Cvar_GetValue(Com_Parse(&in));
00488             Com_sprintf(out, len, "%d", r);
00489             out += (r / 10) + 1;
00490             len -= (r / 10) + 1;
00491         }
00492 
00493         /* general case is to copy so long as the buffer has room */
00494 
00495         len--;
00496         if (len < 0)
00497             Com_Error(ERR_FATAL, "R_PreprocessShader: Overflow in shader loading '%s'", name);
00498         *out++ = *in++;
00499         i++;
00500     }
00501     return i;
00502 }
00503 
00504 
00505 static r_shader_t *R_LoadShader (GLenum type, const char *name)
00506 {
00507     r_shader_t *sh;
00508     char path[MAX_QPATH], *src[1];
00509     unsigned e, len, length[1];
00510     char *source, *srcBuf;
00511     byte *buf;
00512     int i;
00513     size_t bufLength = SHADER_BUF_SIZE;
00514     size_t initializeLength;
00515 
00516     snprintf(path, sizeof(path), "shaders/%s", name);
00517 
00518     if ((len = FS_LoadFile(path, &buf)) == -1) {
00519         Com_DPrintf(DEBUG_RENDERER, "R_LoadShader: Failed to load %s.\n", name);
00520         return NULL;
00521     }
00522 
00523     srcBuf = source = Mem_PoolAlloc(bufLength, vid_imagePool, 0);
00524 
00525     initializeLength = R_InitializeShader(name, srcBuf, bufLength);
00526     srcBuf += initializeLength;
00527     bufLength -= initializeLength;
00528 
00529     R_PreprocessShader(name, (const char *)buf, srcBuf, bufLength);
00530     FS_FreeFile(buf);
00531 
00532     src[0] = source;
00533     length[0] = strlen(source);
00534 
00535     for (i = 0; i < MAX_SHADERS; i++) {
00536         sh = &r_state.shaders[i];
00537 
00538         if (!sh->id)
00539             break;
00540     }
00541 
00542     if (i == MAX_SHADERS) {
00543         Com_Printf("R_LoadShader: MAX_SHADERS reached.\n");
00544         Mem_Free(source);
00545         return NULL;
00546     }
00547 
00548     Q_strncpyz(sh->name, name, sizeof(sh->name));
00549 
00550     sh->type = type;
00551 
00552     sh->id = qglCreateShader(sh->type);
00553     if (!sh->id)
00554         return NULL;
00555 
00556     /* upload the shader source */
00557     qglShaderSource(sh->id, 1, src, length);
00558 
00559     /* compile it and check for errors */
00560     qglCompileShader(sh->id);
00561 
00562     Mem_Free(source);
00563 
00564     qglGetShaderiv(sh->id, GL_COMPILE_STATUS, &e);
00565     if (!e) {
00566         char log[MAX_STRING_CHARS];
00567         qglGetShaderInfoLog(sh->id, sizeof(log) - 1, NULL, log);
00568         Com_Printf("R_LoadShader: %s: %s\n", sh->name, log);
00569 
00570         qglDeleteShader(sh->id);
00571         memset(sh, 0, sizeof(*sh));
00572 
00573         return NULL;
00574     }
00575 
00576     return sh;
00577 }
00578 
00579 r_program_t *R_LoadProgram (const char *name, void *init, void *use)
00580 {
00581     r_program_t *prog;
00582     unsigned e;
00583     int i;
00584 
00585     /* search existing one */
00586     for (i = 0; i < MAX_PROGRAMS; i++) {
00587         prog = &r_state.programs[i];
00588 
00589         if (!strcmp(prog->name, name))
00590             return prog;
00591     }
00592 
00593     /* search free slot */
00594     for (i = 0; i < MAX_PROGRAMS; i++) {
00595         prog = &r_state.programs[i];
00596 
00597         if (!prog->id)
00598             break;
00599     }
00600 
00601     if (i == MAX_PROGRAMS) {
00602         Com_Printf("R_LoadProgram: MAX_PROGRAMS reached.\n");
00603         return NULL;
00604     }
00605 
00606     Q_strncpyz(prog->name, name, sizeof(prog->name));
00607 
00608     prog->id = qglCreateProgram();
00609 
00610     prog->v = R_LoadShader(GL_VERTEX_SHADER, va("%s_vs.glsl", name));
00611     prog->f = R_LoadShader(GL_FRAGMENT_SHADER, va("%s_fs.glsl", name));
00612 
00613     if (prog->v)
00614         qglAttachShader(prog->id, prog->v->id);
00615     if (prog->f)
00616         qglAttachShader(prog->id, prog->f->id);
00617 
00618     qglLinkProgram(prog->id);
00619 
00620     qglGetProgramiv(prog->id, GL_LINK_STATUS, &e);
00621     if (!e || !prog->v || !prog->f) {
00622         char log[MAX_STRING_CHARS];
00623         qglGetProgramInfoLog(prog->id, sizeof(log) - 1, NULL, log);
00624         Com_Printf("R_LoadProgram: %s: %s\n", prog->name, log);
00625 
00626         R_ShutdownProgram(prog);
00627         return NULL;
00628     }
00629 
00630     prog->init = init;
00631 
00632     if (prog->init) {  /* invoke initialization function */
00633         R_UseProgram(prog);
00634 
00635         prog->init(prog);
00636 
00637         R_UseProgram(NULL);
00638     }
00639 
00640     prog->use = use;
00641 
00642     Com_Printf("R_LoadProgram: '%s' loaded.\n", name);
00643 
00644     return prog;
00645 }
00646 
00647 static void R_InitWorldProgram (r_program_t *prog)
00648 {
00649     R_ProgramParameter1i("SAMPLER0", 0);
00650     R_ProgramParameter1i("SAMPLER1", 1);
00651     R_ProgramParameter1i("SAMPLER2", 2);
00652     R_ProgramParameter1i("SAMPLER3", 3);
00653     if (r_postprocess->integer)
00654         R_ProgramParameter1i("SAMPLER4", 4);
00655 
00656     R_ProgramParameter1i("BUMPMAP", 0);
00657     R_ProgramParameter1i("ROUGHMAP", 0);
00658     R_ProgramParameter1i("SPECULARMAP", 0);
00659     R_ProgramParameter1i("ANIMATE", 0);
00660 
00661     R_ProgramParameter1f("BUMP", 1.0);
00662     R_ProgramParameter1f("PARALLAX", 1.0);
00663     R_ProgramParameter1f("HARDNESS", 0.2);
00664     R_ProgramParameter1f("SPECULAR", 1.0);
00665     if (r_postprocess->integer)
00666         R_ProgramParameter1f("GLOWSCALE", 1.0);
00667 }
00668 
00669 static void R_UseWorldProgram (r_program_t *prog)
00670 {
00671     /*R_ProgramParameter1i("LIGHTS", refdef.numLights);*/
00672 }
00673 
00674 static void R_InitWarpProgram (r_program_t *prog)
00675 {
00676     static vec4_t offset;
00677 
00678     R_ProgramParameter1i("SAMPLER0", 0);
00679     R_ProgramParameter1i("SAMPLER1", 1);
00680     if (r_postprocess->integer) {
00681         R_ProgramParameter1i("SAMPLER4", 4);
00682         R_ProgramParameter1f("GLOWSCALE", 0.0);
00683     }
00684     R_ProgramParameter4fv("OFFSET", offset);
00685 }
00686 
00687 static void R_UseWarpProgram (r_program_t *prog)
00688 {
00689     static vec4_t offset;
00690 
00691     offset[0] = offset[1] = refdef.time / 8.0;
00692     R_ProgramParameter4fv("OFFSET", offset);
00693 }
00694 
00695 static void R_InitGeoscapeProgram (r_program_t *prog)
00696 {
00697     static vec4_t defaultColor = {0.0, 0.0, 0.0, 1.0};
00698     static vec4_t cityLightColor = {1.0, 1.0, 0.8, 1.0};
00699     static vec2_t uvScale = {2.0, 1.0};
00700 
00701     R_ProgramParameter1i("SAMPLER0", 0);
00702     R_ProgramParameter1i("SAMPLER1", 1);
00703     R_ProgramParameter1i("SAMPLER2", 2);
00704 
00705     R_ProgramParameter4fv("DEFAULTCOLOR", defaultColor);
00706     R_ProgramParameter4fv("CITYLIGHTCOLOR", cityLightColor);
00707     R_ProgramParameter2fv("UVSCALE", uvScale);
00708 }
00709 
00714 static int R_PascalTriangle (int row, int col)
00715 {
00716     if (row <= 1 || col <= 1 || col >= row)
00717         return 1;
00718     return R_PascalTriangle(row - 1, col) + R_PascalTriangle(row - 1, col - 1);
00719 }
00720 
00722 #define FILTER_SIZE 3
00723 
00724 static void R_InitConvolveProgram (r_program_t *prog)
00725 {
00726     float filter[FILTER_SIZE];
00727     float sum = 0;
00728     int i;
00729     const size_t size = lengthof(filter);
00730 
00731     /* approximate a Gaussian by normalizing the Nth row of Pascale's Triangle */
00732     for (i = 0; i < size; i++) {
00733         filter[i] = (float)R_PascalTriangle(size, i + 1);
00734         sum += filter[i];
00735     }
00736 
00737     for (i = 0; i < size; i++)
00738         filter[i] = (filter[i] / sum);
00739 
00740     R_ProgramParameter1i("SAMPLER0", 0);
00741     R_ProgramParameter1fvs("COEFFICIENTS", size, filter);
00742 }
00743 
00747 static void R_UseConvolveProgram (r_program_t *prog)
00748 {
00749     int i;
00750     const float *userdata= (float *)prog->userdata;
00751     float offsets[FILTER_SIZE * 2];
00752     const float halfWidth = (FILTER_SIZE - 1) * 0.5;
00753     const float offset = 1.2f / userdata[0];
00754     const float x = userdata[1] * offset;
00755 
00756     for (i = 0; i < FILTER_SIZE; i++) {
00757         const float y = (float)i - halfWidth;
00758         const float z = x * y;
00759         offsets[i * 2 + 0] = offset * y - z;
00760         offsets[i * 2 + 1] = z;
00761     }
00762     R_ProgramParameter2fvs("OFFSETS", FILTER_SIZE, offsets);
00763 }
00764 
00765 static void R_InitCombine2Program (r_program_t *prog)
00766 {
00767     GLfloat defaultColor[4] = {0.0, 0.0, 0.0, 0.0};
00768 
00769     R_ProgramParameter1i("SAMPLER0", 0);
00770     R_ProgramParameter1i("SAMPLER1", 1);
00771 
00772     R_ProgramParameter4fv("DEFAULTCOLOR", defaultColor);
00773 }
00774 
00775 static void R_InitAtmosphereProgram (r_program_t *prog)
00776 {
00777     static vec4_t defaultColor = {0.0, 0.0, 0.0, 1.0};
00778     static vec2_t uvScale = {2.0, 1.0};
00779 
00780     R_ProgramParameter1i("SAMPLER0", 0);
00781     R_ProgramParameter1i("SAMPLER2", 2);
00782 
00783     R_ProgramParameter4fv("DEFAULTCOLOR", defaultColor);
00784     R_ProgramParameter2fv("UVSCALE", uvScale);
00785 }
00786 
00787 static void R_InitSimpleGlowProgram (r_program_t *prog)
00788 {
00789     R_ProgramParameter1i("SAMPLER0", 0);
00790     R_ProgramParameter1i("SAMPLER1", 4);
00791     R_ProgramParameter1f("GLOWSCALE", 1.0);
00792 }
00793 
00794 void R_InitParticleProgram (r_program_t *prog)
00795 {
00796     R_ProgramParameter1i("SAMPLER0", 0);
00797 }
00798 
00799 void R_UseParticleProgram (r_program_t *prog)
00800 {
00801 /*  ptl_t *ptl = (ptl_t *)prog->userdata;*/
00802 }
00803 
00804 void R_InitPrograms (void)
00805 {
00806     if (!qglCreateProgram) {
00807         Com_Printf("not using GLSL shaders\n");
00808         Cvar_Set("r_programs", "0");
00809         r_programs->modified = qfalse;
00810         return;
00811     }
00812 
00813     memset(r_state.shaders, 0, sizeof(r_state.shaders));
00814     memset(r_state.programs, 0, sizeof(r_state.programs));
00815 
00816     /* shaders are deactivated - don't try to load them - some cards
00817      * even have problems with this */
00818     if (!r_programs->integer)
00819         return;
00820 
00821     r_state.world_program = R_LoadProgram("world", R_InitWorldProgram, R_UseWorldProgram);
00822     r_state.warp_program = R_LoadProgram("warp", R_InitWarpProgram, R_UseWarpProgram);
00823     r_state.geoscape_program = R_LoadProgram("geoscape", R_InitGeoscapeProgram, NULL);
00824     r_state.combine2_program = R_LoadProgram("combine2", R_InitCombine2Program, NULL);
00825     r_state.convolve_program = R_LoadProgram("convolve" DOUBLEQUOTE(FILTER_SIZE), R_InitConvolveProgram, R_UseConvolveProgram);
00826     r_state.atmosphere_program = R_LoadProgram("atmosphere", R_InitAtmosphereProgram, NULL);
00827     r_state.simple_glow_program = R_LoadProgram("simple_glow", R_InitSimpleGlowProgram, NULL);
00828 }
00829 
00833 void R_RestartPrograms_f (void)
00834 {
00835     Com_Printf("glsl restart\n");
00836 
00837     R_ShutdownPrograms();
00838     R_InitPrograms();
00839 }

Generated by  doxygen 1.6.2