00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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)
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
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
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)) {
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)) {
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)) {
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
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
00557 qglShaderSource(sh->id, 1, src, length);
00558
00559
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
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
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) {
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
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
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
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
00817
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 }