UFO: Alien Invasion
Loading...
Searching...
No Matches
r_program.cpp
Go to the documentation of this file.
1
5
6/*
7* Copyright(c) 1997-2001 Id Software, Inc.
8* Copyright(c) 2002 The Quakeforge Project.
9* Copyright(c) 2006 Quake2World.
10*
11* This program is free software; you can redistribute it and/or
12* modify it under the terms of the GNU General Public License
13* as published by the Free Software Foundation; either version 2
14* of the License, or(at your option) any later version.
15*
16* This program is distributed in the hope that it will be useful,
17* but WITHOUT ANY WARRANTY; without even the implied warranty of
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19*
20* See the GNU General Public License for more details.
21*
22* You should have received a copy of the GNU General Public License
23* along with this program; if not, write to the Free Software
24* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25*/
26
27#include "r_local.h"
28#include "r_error.h"
29#include "r_program.h"
30#include "../../shared/parse.h"
31#include "../../shared/shared.h"
32
33#define SHADER_BUF_SIZE 16384
34
36
38 {"world_low","model_low"},
39 {"world_med","model_med"},
40 {"world_med","model_high"}
41};
42
44{
45 if (!qglUseProgram || r_state.active_program == prog)
46 return;
47
48 if (!r_state.active_program)
49 refdef.FFPToShaderCount++;
50 else if (!prog)
51 refdef.shaderToFFPCount++;
52 else
53 refdef.shaderToShaderCount++;
54
55 r_state.active_program = prog;
56
57 if (prog) {
58 qglUseProgram(prog->id);
59
60 if (prog->use) /* invoke use function */
61 prog->use(prog);
62 } else {
63 qglUseProgram(0);
64 }
65}
66
67static r_progvar_t* R_ProgramVariable (int type, const char* name)
68{
70 int i;
71
72 if (!r_state.active_program) {
73 Com_DPrintf(DEBUG_RENDERER, "R_ProgramVariable: \"%s\" - No program bound.\n", name);
74 return nullptr;
75 }
76
77 /* find the variable */
78 for (i = 0; i < MAX_PROGRAM_VARS; i++) {
79 v = &r_state.active_program->vars[i];
80
81 if (!v->location)
82 break;
83
84 if (v->type == type && Q_streq(v->name, name))
85 return v;
86 }
87
88 if (i == MAX_PROGRAM_VARS) {
89 Com_Printf("R_ProgramVariable: MAX_PROGRAM_VARS reached.\n");
90 return nullptr;
91 }
92
93 /* or query for it */
94 if (type == GL_UNIFORM)
95 v->location = qglGetUniformLocation(r_state.active_program->id, name);
96 else
97 v->location = qglGetAttribLocation(r_state.active_program->id, name);
98
99 if (v->location == -1) {
100 Com_Printf("R_ProgramVariable: Could not find parameter %s in program %s.\n", name, r_state.active_program->name);
101 v->location = 0;
102 return nullptr;
103 }
104
105 v->type = type;
106 Q_strncpyz(v->name, name, sizeof(v->name));
107
108 return v;
109}
110
111void R_ProgramParameter1i (const char* name, GLint value)
112{
113 r_progvar_t* v;
114
116 return;
117
118 qglUniform1i(v->location, value);
119}
120
121void R_ProgramParameter1f (const char* name, GLfloat value)
122{
123 r_progvar_t* v;
124
126 return;
127
128 qglUniform1f(v->location, value);
129}
130
131void R_ProgramParameter1fvs (const char* name, GLint size, GLfloat* value)
132{
133 r_progvar_t* v;
134
136 return;
137
138 qglUniform1fv(v->location, size, value);
139}
140
141void R_ProgramParameter2fv (const char* name, GLfloat* value)
142{
143 r_progvar_t* v;
144
146 return;
147
148 qglUniform2fv(v->location, 1, value);
149}
150
151void R_ProgramParameter2fvs (const char* name, GLint size, GLfloat* value)
152{
153 r_progvar_t* v;
154
156 return;
157
158 qglUniform2fv(v->location, size, value);
159}
160
161void R_ProgramParameter3fv (const char* name, GLfloat* value)
162{
163 r_progvar_t* v;
164
166 return;
167
168 qglUniform3fv(v->location, 1, value);
169}
170
171void R_ProgramParameter3fvs (const char* name, GLint size, GLfloat* value)
172{
173 r_progvar_t* v;
174
176 return;
177
178 qglUniform3fv(v->location, size, value);
179}
180
181void R_ProgramParameter4fv (const char* name, GLfloat* value)
182{
183 r_progvar_t* v;
184
186 return;
187
188 qglUniform4fv(v->location, 1, value);
189}
190
191void R_ProgramParameter4fvs (const char* name, GLint size, GLfloat* value)
192{
193 r_progvar_t* v;
194
196 return;
197
198 qglUniform4fv(v->location, size, value);
199}
200
201void R_ProgramParameterMatrix4fv (const char* name, GLfloat* value)
202{
203 r_progvar_t* v;
204
206 return;
207
208 qglUniformMatrix4fv(v->location, 1, GL_FALSE, value);
209}
210
211void R_AttributePointer (const char* name, GLuint size, const GLvoid* array)
212{
213 r_progvar_t* v;
214
216 return;
217
218 qglVertexAttribPointer(v->location, size, GL_FLOAT, GL_FALSE, 0, array);
219}
220
221void R_EnableAttribute (const char* name)
222{
223 r_progvar_t* v;
224
226 return;
227
228 qglEnableVertexAttribArray(v->location);
229}
230
231void R_DisableAttribute (const char* name)
232{
233 r_progvar_t* v;
234
236 return;
237
238 qglDisableVertexAttribArray(v->location);
239}
240
242{
243 qglDeleteShader(sh->id);
244 OBJZERO(*sh);
245}
246
248{
249 if (prog->v) {
250 qglDetachShader(prog->id, prog->v->id);
251 R_ShutdownShader(prog->v);
252 R_CheckError();
253 }
254 if (prog->f) {
255 qglDetachShader(prog->id, prog->f->id);
256 R_ShutdownShader(prog->f);
257 R_CheckError();
258 }
259
260 qglDeleteProgram(prog->id);
261
262 OBJZERO(*prog);
263}
264
266{
267 if (!qglDeleteProgram)
268 return;
269
270 if (!r_programs->integer)
271 return;
272
273 for (int i = 0; i < MAX_PROGRAMS; i++) {
274 if (!r_state.programs[i].id)
275 continue;
276
277 R_ShutdownProgram(&r_state.programs[i]);
278 }
279}
280
289static size_t R_PreprocessShaderAddToShaderBuf (const char* name, const char* in, char** out, size_t* len)
290{
291 const size_t inLength = strlen(in);
292 strcpy(*out, in);
293 *out += inLength;
294 *len -= inLength;
295 return inLength;
296}
297
309static size_t R_InitializeShader (const GLenum type, const char* name, char* out, size_t len)
310{
311 size_t initialChars = 0;
312 const char* hwHack, *defines;
313 /* in the format GLSL compiler expects it -- e.g. 110 for version 1.10 */
314 const int shaderVersion = (int)(r_glsl_version->value * 100 + 0.1);
315
316 switch (r_config.hardwareType) {
317 case GLHW_ATI:
318 hwHack = "#ifndef ATI\n#define ATI\n#endif\n";
319 break;
320 case GLHW_INTEL:
321 hwHack = "#ifndef INTEL\n#define INTEL\n#endif\n";
322 break;
323 case GLHW_NVIDIA:
324 hwHack = "#ifndef NVIDIA\n#define NVIDIA\n#endif\n";
325 break;
326 case GLHW_MESA:
327 hwHack = "#ifndef MESA\n#define MESA\n#endif\n";
328 break;
329 case GLHW_GENERIC:
330 hwHack = nullptr;
331 break;
332 default:
333 Com_Error(ERR_FATAL, "R_PreprocessShader: Unknown hardwaretype");
334 }
335
336 /*
337 * Prefix "#version xxx" onto shader string.
338 * This causes GLSL compiler to compile to that version.
339 */
340 defines = va("#version %d\n", shaderVersion);
341 initialChars += R_PreprocessShaderAddToShaderBuf(name, defines, &out, &len);
342
343 /*
344 * Prefix "#define glslxxx" onto shader string.
345 * This named constant is used to setup shader code to match the desired GLSL spec.
346 */
347 defines = va("#define glsl%d\n", shaderVersion);
348 initialChars += R_PreprocessShaderAddToShaderBuf(name, defines, &out, &len);
349
350 /* Define r_width.*/
351 defines = va("#ifndef r_width\n#define r_width %f\n#endif\n", (float)viddef.context.width);
352 initialChars += R_PreprocessShaderAddToShaderBuf(name, defines, &out, &len);
353
354 /* Define r_height.*/
355 defines = va("#ifndef r_height\n#define r_height %f\n#endif\n", (float)viddef.context.height);
356 initialChars += R_PreprocessShaderAddToShaderBuf(name, defines, &out, &len);
357
358 if (hwHack) {
359 initialChars += R_PreprocessShaderAddToShaderBuf(name, hwHack, &out, &len);
360 }
361
362 if (GL_VERTEX_SHADER == type) {
363 /* Define 'in_qualifier as 'attribute' & 'out_qualifier' as 'varying' if GLSL v1.10, otherwise define them as 'in' and 'out' respectively.*/
364 initialChars += R_PreprocessShaderAddToShaderBuf(name, "#ifndef glsl110\n#define in_qualifier in\n#define out_qualifier out\n#else\n#define in_qualifier attribute\n#define out_qualifier varying\n#endif\n", &out, &len);
365 } else if (GL_FRAGMENT_SHADER == type) {
366 /* Define 'texture2D' as 'texture', as texture2D was deprecated (replaced with 'texture') as of GLSL v1.30.*/
367 initialChars += R_PreprocessShaderAddToShaderBuf(name, "#ifndef glsl110\n#define texture2D texture\n#endif\n", &out, &len);
368 /* Define 'in_qualifier as 'varying' if GLSL v1.10, otherwise define it as 'in'.*/
369 initialChars += R_PreprocessShaderAddToShaderBuf(name, "#ifndef glsl110\n#define in_qualifier in\n#else\n#define in_qualifier varying\n#endif\n", &out, &len);
370 }
371
372 return initialChars;
373}
374
392static size_t R_PreprocessShaderR (const char* name, const char** inPtr, char* out, long* remainingOutChars, bool nested, bool inElse)
393{
394 const size_t INITIAL_REMAINING_OUT_CHARS = (size_t)*remainingOutChars;
395 /* Keep looping till we reach the end of the shader string, or a parsing error.*/
396 while (**inPtr) {
397 if ('#' == **inPtr) {
398 bool endBlockToken;
399 (*inPtr)++;
400
401 endBlockToken = !strncmp(*inPtr, "endif", 5);
402
403 if (!strncmp(*inPtr, "else", 4)) {
404 if (inElse) {
405 /* Error in shader! Print a message saying our preprocessor failed parsing.*/
406 Com_Error(ERR_DROP, "R_PreprocessShaderR: #else without #if: %s", name);
407 }
408 endBlockToken = true;
409 }
410
411 if (endBlockToken) {
412 if (!nested) {
413 /* Error in shader! Print a message saying our preprocessor failed parsing.*/
414 Com_Error(ERR_DROP, "R_PreprocessShaderR: Unmatched #endif/#else: %s", name);
415 }
416 /* Whoever called us will have to deal with closing the block */
417 return (INITIAL_REMAINING_OUT_CHARS - (size_t)*remainingOutChars);
418 }
419
420 if (!strncmp((*inPtr), "if ", 3)) {
421 /* The line looks like "#if r_postprocess".*/
422 (*inPtr) += 3;
423 /* Get the corresponding cvar value.*/
424 float f = Cvar_GetValue(Com_Parse(inPtr));
425 if (f) { /* Condition is true, recursively preprocess #if block, and skip over #else block, if any */
426 int size = R_PreprocessShaderR(name, inPtr, out, remainingOutChars, true, false);
427 if (out) out += size;
428
429 if (!strncmp((*inPtr), "else", 4)) {/* Preprocess and skip #else block */
430 (*inPtr) +=4 ;
431 R_PreprocessShaderR(name, inPtr, (char*)0, remainingOutChars, true, true);
432 }
433 } else {
434 /* The cvar was false, don't add to out. Lets look and see if we hit a #else, or #endif.*/
435 R_PreprocessShaderR(name, inPtr, (char*)0, remainingOutChars, true, false);
436 if (!strncmp((*inPtr), "else", 4)) {
437 int size;
438 /* All right, we want to add this to out.*/
439 (*inPtr) +=4 ;
440 size = R_PreprocessShaderR(name, inPtr, out, remainingOutChars, true, true);
441 if (out) out += size;
442 }
443 }
444 /* skip #endif, if any (could also get here by unexpected EOF */
445 if (!strncmp((*inPtr), "endif", 5))
446 (*inPtr) +=5 ;
447 } else if (!strncmp((*inPtr), "ifndef", 6) || !strncmp((*inPtr), "ifdef", 5)) { /* leave those for GLSL compiler, but follow #else/#endif nesting */
448 int size;
449 if (out) {
450 if (*remainingOutChars <= 0)
451 Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name);
452 *out++ = '#';
453 (*remainingOutChars)--;
454 }
455
456 size = R_PreprocessShaderR(name, inPtr, out, remainingOutChars, true, false);
457 if (out) out += size;
458
459 if (!strncmp((*inPtr), "else", 4)) {
460 if (out) {
461 if (*remainingOutChars <= 0)
462 Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name);
463 *out++ = '#';
464 (*remainingOutChars)--;
465 }
466 size = R_PreprocessShaderR(name, inPtr, out, remainingOutChars, true, true);
467 if (out) out += size;
468 }
469
470 if (out) {
471 if (*remainingOutChars <= 0)
472 Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name);
473 *out++ = '#';
474 (*remainingOutChars)--;
475 }
476
477 } else if (!strncmp((*inPtr), "include", 7)) {
478 char path[MAX_QPATH];
479 byte* buf = (byte*)0;
480 const char* bufAsChar = (const char*)0;
481 const char** bufAsCharPtr = (const char**)0;
482 (*inPtr) += 8;
483 Com_sprintf(path, sizeof(path), "shaders/%s", Com_Parse(inPtr));
484 if (FS_LoadFile(path, &buf) == -1) {
485 Com_Printf("Failed to resolve #include: %s.\n", path);
486 continue;
487 }
488 bufAsChar = (const char*)buf;
489 bufAsCharPtr = &bufAsChar;
490 if (out) {
491 out += R_PreprocessShaderR(name, bufAsCharPtr, out, remainingOutChars, nested, false);
492 } else {
493 R_PreprocessShaderR(name, bufAsCharPtr, out, remainingOutChars, nested, false);
494 }
496 } else if (!strncmp((*inPtr), "unroll", 6)) {
497 /* loop unrolling */
498 size_t subLength = 0;
499 byte* const buffer = Mem_PoolAllocTypeN(byte, SHADER_BUF_SIZE, vid_imagePool);
500 (*inPtr) += 6;
501 int z = Cvar_GetValue(Com_Parse(inPtr));
502 while (*(*inPtr)) {
503 if (!strncmp((*inPtr), "#endunroll", 10)) {
504 (*inPtr) += 10;
505 break;
506 }
507 buffer[subLength++] = *(*inPtr)++;
508 if (subLength >= SHADER_BUF_SIZE)
509 Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name);
510 }
511 if (out) {
512 for (int j = 0; j < z; j++) {
513 for (int l = 0; l < subLength; l++) {
514 if (buffer[l] == '$') {
515 byte insertedLen = (j / 10) + 1;
516 if (!Com_sprintf(out, (size_t)*remainingOutChars, "%d", j))
517 Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name);
518 out += insertedLen;
519 (*remainingOutChars) -= insertedLen;
520 } else {
521 if (*remainingOutChars <= 0)
522 Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name);
523 *out++ = buffer[l];
524 (*remainingOutChars)--;
525 }
526 }
527 }
528 }
529 Mem_Free(buffer);
530 } else if (!strncmp((*inPtr), "replace", 7)) {
531 int r = 0;
532 (*inPtr) += 8;
533 r = Cvar_GetValue(Com_Parse(inPtr));
534 if (out) {
535 byte insertedLen = 0;
536 if (!Com_sprintf(out, (size_t)*remainingOutChars, "%d", r))
537 Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name);
538 insertedLen = (r / 10) + 1;
539 out += insertedLen;
540 (*remainingOutChars) -= insertedLen;
541 }
542 } else {
543 /* general case is to copy so long as the buffer has room */
544 if (out) {
545 if (*remainingOutChars <= 0)
546 Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name);
547 *out++ = '#';
548 (*remainingOutChars)--;
549 }
550 }
551 } else {
552 /* general case is to copy so long as the buffer has room */
553 if (out) {
554 if (*remainingOutChars <= 0)
555 Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name);
556 *out++ = *(*inPtr);
557 (*remainingOutChars)--;
558 }
559 (*inPtr)++;
560 }
561 }
562 /* Return the number of characters added to the buffer.*/
563 return (INITIAL_REMAINING_OUT_CHARS - *remainingOutChars);
564}
565
581static size_t R_PreprocessShader (const char* name, const char* in, char* out, size_t* remainingOutChars)
582{
583 long remainingOutCharsAsLong = *remainingOutChars;
584 size_t numCharactersAddedToOutBuffer = R_PreprocessShaderR(name, &in, out, &remainingOutCharsAsLong, false, false);
585 *remainingOutChars = remainingOutCharsAsLong;
586 return numCharactersAddedToOutBuffer;
587}
588
595static r_shader_t* R_LoadShader (const GLenum type, const char* name)
596{
597 r_shader_t* sh;
598 char path[MAX_QPATH], *src[1];
599 unsigned e, length[1];
600 char* srcBuf;
601 byte* buf;
602 int i;
603 size_t bufLength = SHADER_BUF_SIZE;
604 size_t initializeLength;
605
606#ifdef DEBUG
607 /* Used to contain result of shader compile.*/
608 char log[MAX_STRING_CHARS];
609#endif
610
611 snprintf(path, sizeof(path), "shaders/%s", name);
612
613 if (FS_LoadFile(path, &buf) == -1) {
614 Com_DPrintf(DEBUG_RENDERER, "R_LoadShader: Failed to load ./base/shaders/%s.\n", name);
615 return nullptr;
616 }
617
618 Com_DPrintf(DEBUG_RENDERER, "R_LoadShader: Loading ./base/shaders/%s.\n", name);
619
620 char* const source = srcBuf = Mem_PoolAllocTypeN(char, bufLength, vid_imagePool);
621
622 initializeLength = R_InitializeShader(type, name, srcBuf, bufLength);
623 srcBuf += initializeLength;
624 bufLength -= initializeLength;
625
626 R_PreprocessShader(name, (const char*)buf, srcBuf, &bufLength);
628
629 src[0] = source;
630 length[0] = strlen(source);
631
632 for (i = 0; i < MAX_SHADERS; i++) {
633 sh = &r_state.shaders[i];
634
635 if (!sh->id)
636 break;
637 }
638
639 if (i == MAX_SHADERS) {
640 Com_Printf("R_LoadShader: MAX_SHADERS reached.\n");
641 Mem_Free(source);
642 return nullptr;
643 }
644
645 Q_strncpyz(sh->name, name, sizeof(sh->name));
646
647 sh->type = type;
648
649 sh->id = qglCreateShader(sh->type);
650 if (!sh->id) {
651 Mem_Free(source);
652 return nullptr;
653 }
654
655 /* upload the shader source */
656 qglShaderSource(sh->id, 1, src, length);
657
658 /* compile it and check for errors */
659 qglCompileShader(sh->id);
660
661 Mem_Free(source);
662
663 qglGetShaderiv(sh->id, GL_COMPILE_STATUS, &e);
664#ifdef DEBUG
665 qglGetShaderInfoLog(sh->id, sizeof(log) - 1, nullptr, log);
666 Com_Printf("R_LoadShader: %s: %s", sh->name, log);
667#endif
668 if (!e) {
669#ifndef DEBUG
670 char log[MAX_STRING_CHARS];
671 qglGetShaderInfoLog(sh->id, sizeof(log) - 1, nullptr, log);
672 Com_Printf("R_LoadShader: %s: %s", sh->name, log);
673#endif
674
675 qglDeleteShader(sh->id);
676 OBJZERO(*sh);
677
678 return nullptr;
679 }
680
681 return sh;
682}
683
685{
686 r_program_t* prog;
687 unsigned e;
688 int i;
689
690 /* shaders are deactivated */
691 if (!r_programs->integer)
692 return nullptr;
693
694 /* search existing one */
695 for (i = 0; i < MAX_PROGRAMS; i++) {
696 prog = &r_state.programs[i];
697
698 if (Q_streq(prog->name, name))
699 return prog;
700 }
701
702 /* search free slot */
703 for (i = 0; i < MAX_PROGRAMS; i++) {
704 prog = &r_state.programs[i];
705
706 if (!prog->id)
707 break;
708 }
709
710 if (i == MAX_PROGRAMS) {
711 Com_Printf("R_LoadProgram: MAX_PROGRAMS reached.\n");
712 return nullptr;
713 }
714
715 Q_strncpyz(prog->name, name, sizeof(prog->name));
716
717 prog->id = qglCreateProgram();
718
719 prog->v = R_LoadShader(GL_VERTEX_SHADER, va("%s_vs.glsl", name));
720 prog->f = R_LoadShader(GL_FRAGMENT_SHADER, va("%s_fs.glsl", name));
721
722 if (prog->v)
723 qglAttachShader(prog->id, prog->v->id);
724 if (prog->f)
725 qglAttachShader(prog->id, prog->f->id);
726
727 qglLinkProgram(prog->id);
728
729 qglGetProgramiv(prog->id, GL_LINK_STATUS, &e);
730 if (!e || !prog->v || !prog->f) {
731 char log[MAX_STRING_CHARS];
732 qglGetProgramInfoLog(prog->id, sizeof(log) - 1, nullptr, log);
733 Com_Printf("R_LoadProgram: %s: %s\n", prog->name, log);
734
735 R_ShutdownProgram(prog);
736 return nullptr;
737 }
738
739 prog->init = init;
740
741 if (prog->init) { /* invoke initialization function */
742 R_UseProgram(prog);
743
744 prog->init(prog);
745
746 R_UseProgram(nullptr);
747 }
748
749 prog->use = use;
750
751 Com_Printf("R_LoadProgram: '%s' loaded.\n", name);
752
753 return prog;
754}
755
756extern vec2_t fogRange;
757
759{
760 R_ProgramParameter1i("SAMPLER_DIFFUSE", 0);
761 R_ProgramParameter1i("SAMPLER_LIGHTMAP", 1);
762 R_ProgramParameter1i("SAMPLER_DELUXEMAP", 2);
763 R_ProgramParameter1i("SAMPLER_NORMALMAP", 3);
764 R_ProgramParameter1i("SAMPLER_GLOWMAP", 4);
765
766 R_ProgramParameter1i("BUMPMAP", 0);
767
768 if (r_programs->integer > 1) {
769 R_ProgramParameter3fv("AMBIENT", refdef.ambientColor);
770
771 R_ProgramParameter1i("SPECULARMAP", 0);
772 R_ProgramParameter1i("SAMPLER_SPECULAR", 5);
773
774 R_ProgramParameter1f("HARDNESS", defaultMaterial.hardness);
775 R_ProgramParameter1f("SPECULAR", defaultMaterial.specular);
776 R_ProgramParameter1f("PARALLAX", defaultMaterial.parallax);
777 }
778
780 R_ProgramParameter1f("GLOWSCALE", defaultMaterial.glowscale);
781
782 if (r_fog->integer) {
783 if (r_state.fog_enabled) {
784 R_ProgramParameter3fv("FOGCOLOR", refdef.fogColor);
785 R_ProgramParameter1f("FOGDENSITY", refdef.fogColor[3]);
786 R_ProgramParameter2fv("FOGRANGE", fogRange);
787 } else {
788 R_ProgramParameter1f("FOGDENSITY", 0.0f);
789 }
790 }
791}
792
794{
795 if (r_programs->integer > 1) {
796 R_ProgramParameter3fv("AMBIENT", refdef.ambientColor);
797 }
798
799 if (r_fog->integer) {
800 if (r_state.fog_enabled) {
801 R_ProgramParameter3fv("FOGCOLOR", refdef.fogColor);
802 R_ProgramParameter1f("FOGDENSITY", refdef.fogColor[3]);
803 R_ProgramParameter2fv("FOGRANGE", fogRange);
804 } else {
805 R_ProgramParameter1f("FOGDENSITY", 0.0f);
806 }
807 }
808}
809
811{
812 vec4_t sunDirection;
813
814 R_ProgramParameter1i("SAMPLER_DIFFUSE", 0);
815 R_ProgramParameter1i("SAMPLER_NORMALMAP", 3);
816 R_ProgramParameter1i("SAMPLER_GLOWMAP", 4);
817
818 R_ProgramParameter1i("BUMPMAP", 0);
819 R_ProgramParameter1i("ANIMATE", 0);
820
822 R_ProgramParameter1f("GLOWSCALE", defaultMaterial.glowscale);
823 R_ProgramParameter1f("OFFSET", 0.0);
824
825 R_ProgramParameter3fv("AMBIENT", refdef.modelAmbientColor);
826 R_ProgramParameter3fv("SUNCOLOR", refdef.sunDiffuseColor);
827
828 GLVectorTransform(r_locals.world_matrix, refdef.sunVector, sunDirection);
829 R_ProgramParameter3fv("SUNDIRECTION", sunDirection); /* last component is not needed */
830
831 if (r_programs->integer > 1) {
832 R_ProgramParameter1i("SAMPLER_SPECULAR", 5);
833 R_ProgramParameter1i("SPECULARMAP", 0);
834 R_ProgramParameter1f("HARDNESS", defaultMaterial.hardness);
835 R_ProgramParameter1f("SPECULAR", defaultMaterial.specular);
836 R_ProgramParameter1f("PARALLAX", defaultMaterial.parallax);
837 if (r_programs->integer > 2) {
838 R_ProgramParameter1i("SAMPLER_ROUGHMAP", 2);
839 R_ProgramParameter1i("ROUGHMAP", 0);
840 }
841 }
842
843 if (r_fog->integer) {
844 if (r_state.fog_enabled) {
845 R_ProgramParameter3fv("FOGCOLOR", refdef.fogColor);
846 R_ProgramParameter1f("FOGDENSITY", refdef.fogColor[3]);
847 R_ProgramParameter2fv("FOGRANGE", fogRange);
848 } else {
849 R_ProgramParameter1f("FOGDENSITY", 0.0f);
850 }
851 }
852}
853
855{
856 vec4_t sunDirection;
857 /*R_ProgramParameter1i("LIGHTS", refdef.numLights);*/
858
859 R_ProgramParameter1f("OFFSET", 0.0);
860 R_ProgramParameter3fv("AMBIENT", refdef.modelAmbientColor);
861 R_ProgramParameter3fv("SUNCOLOR", refdef.sunDiffuseColor);
862
863 GLVectorTransform(r_locals.world_matrix, refdef.sunVector, sunDirection);
864 R_ProgramParameter3fv("SUNDIRECTION", sunDirection); /* last component is not needed */
865
866 if (r_fog->integer) {
867 if (r_state.fog_enabled) {
868 R_ProgramParameter3fv("FOGCOLOR", refdef.fogColor);
869 R_ProgramParameter1f("FOGDENSITY", refdef.fogColor[3]);
870 R_ProgramParameter2fv("FOGRANGE", fogRange);
871 } else {
872 R_ProgramParameter1f("FOGDENSITY", 0.0f);
873 }
874 }
875}
876
878{
879 static vec4_t offset;
880
881 R_ProgramParameter1i("SAMPLER_DIFFUSE", 0);
882 R_ProgramParameter1i("SAMPLER_WARP", 1);
883 R_ProgramParameter1i("SAMPLER_GLOWMAP", 4);
884 R_ProgramParameter1f("GLOWSCALE", 0.0);
885 R_ProgramParameter4fv("OFFSET", offset);
886 if (r_fog->integer) {
887 if (r_state.fog_enabled) {
888 R_ProgramParameter3fv("FOGCOLOR", refdef.fogColor);
889 R_ProgramParameter1f("FOGDENSITY", refdef.fogColor[3]);
890 R_ProgramParameter2fv("FOGRANGE", fogRange);
891 } else {
892 R_ProgramParameter1f("FOGDENSITY", 0.0f);
893 }
894 }
895}
896
897static void R_UseWarpProgram (r_program_t* prog)
898{
899 static vec4_t offset;
900
901 offset[0] = offset[1] = refdef.time / 8.0;
902 R_ProgramParameter4fv("OFFSET", offset);
903 if (r_fog->integer) {
904 if (r_state.fog_enabled) {
905 R_ProgramParameter3fv("FOGCOLOR", refdef.fogColor);
906 R_ProgramParameter1f("FOGDENSITY", refdef.fogColor[3]);
907 R_ProgramParameter2fv("FOGRANGE", fogRange);
908 } else {
909 R_ProgramParameter1f("FOGDENSITY", 0.0f);
910 }
911 }
912}
913
915{
916 static vec4_t defaultColor = {0.0, 0.0, 0.0, 1.0};
917 static vec4_t cityLightColor = {1.0, 1.0, 0.8, 1.0};
918 static vec2_t uvScale = {2.0, 1.0};
919
920 R_ProgramParameter1i("SAMPLER_DIFFUSE", 0);
921 R_ProgramParameter1i("SAMPLER_BLEND", 1);
922 R_ProgramParameter1i("SAMPLER_NORMALMAP", 2);
923
924 R_ProgramParameter4fv("DEFAULTCOLOR", defaultColor);
925 R_ProgramParameter4fv("CITYLIGHTCOLOR", cityLightColor);
926 R_ProgramParameter2fv("UVSCALE", uvScale);
927}
928
933static int R_PascalTriangle (int row, int col)
934{
935 if (row <= 1 || col <= 1 || col >= row)
936 return 1;
937 return R_PascalTriangle(row - 1, col) + R_PascalTriangle(row - 1, col - 1);
938}
939
941#define FILTER_SIZE 3
942
944{
945 float filter[FILTER_SIZE];
946 float sum = 0;
947 int i;
948 const size_t size = lengthof(filter);
949
950 /* approximate a Gaussian by normalizing the Nth row of Pascale's Triangle */
951 for (i = 0; i < size; i++) {
952 filter[i] = (float)R_PascalTriangle(size, i + 1);
953 sum += filter[i];
954 }
955
956 for (i = 0; i < size; i++)
957 filter[i] = (filter[i] / sum);
958
959 R_ProgramParameter1i("SAMPLER0", 0);
960 R_ProgramParameter1fvs("COEFFICIENTS", size, filter);
961}
962
967{
968 const float* userdata= (float*)prog->userdata;
969 float offsets[FILTER_SIZE * 2];
970 const float halfWidth = (FILTER_SIZE - 1) * 0.5;
971 const float offset = 1.2f / userdata[0];
972 const float x = userdata[1] * offset;
973
974 for (int i = 0; i < FILTER_SIZE; i++) {
975 const float y = (float)i - halfWidth;
976 const float z = x * y;
977 offsets[i * 2 + 0] = offset * y - z;
978 offsets[i * 2 + 1] = z;
979 }
980 R_ProgramParameter2fvs("OFFSETS", FILTER_SIZE, offsets);
981}
982
984{
985 GLfloat defaultColor[4] = {0.0, 0.0, 0.0, 0.0};
986
987 R_ProgramParameter1i("SAMPLER0", 0);
988 R_ProgramParameter1i("SAMPLER1", 1);
989
990 R_ProgramParameter4fv("DEFAULTCOLOR", defaultColor);
991}
992
994{
995 static vec4_t defaultColor = {0.0, 0.0, 0.0, 1.0};
996 static vec2_t uvScale = {2.0, 1.0};
997
998 R_ProgramParameter1i("SAMPLER_DIFFUSE", 0);
999 R_ProgramParameter1i("SAMPLER_NORMALMAP", 2);
1000
1001 R_ProgramParameter4fv("DEFAULTCOLOR", defaultColor);
1002 R_ProgramParameter2fv("UVSCALE", uvScale);
1003}
1004
1006{
1007 R_ProgramParameter1i("SAMPLER_DIFFUSE", 0);
1008 R_ProgramParameter1i("SAMPLER_GLOWMAP", 4);
1009 R_ProgramParameter1f("GLOWSCALE", 1.0);
1010}
1011
1013{
1014 R_ProgramParameter1i("SAMPLER0", 0);
1015}
1016
1018{
1019/* ptl_t* ptl = (ptl_t*)prog->userdata;*/
1020}
1021
1023{
1024 if (!qglCreateProgram) {
1025 Com_Printf("not using GLSL shaders\n");
1026 Cvar_Set("r_programs", "0");
1027 r_programs->modified = false;
1028 return;
1029 }
1030
1031 OBJZERO(r_state.shaders);
1032 OBJZERO(r_state.programs);
1033
1034 /* Capable of running shaders, but have got them disabled, so do nothing */
1035 if (!r_programs->integer)
1036 return;
1037
1041 r_state.geoscape_program = R_LoadProgram("geoscape", R_InitGeoscapeProgram, nullptr);
1042 r_state.combine2_program = R_LoadProgram("combine2", R_InitCombine2Program, nullptr);
1044 r_state.atmosphere_program = R_LoadProgram("atmosphere", R_InitAtmosphereProgram, nullptr);
1045 r_state.simple_glow_program = R_LoadProgram("simple_glow", R_InitSimpleGlowProgram, nullptr);
1046
1047 if (!(r_state.world_program && r_state.model_program && r_state.warp_program && r_state.geoscape_program && r_state.combine2_program
1048 && r_state.convolve_program && r_state.atmosphere_program && r_state.simple_glow_program)) {
1049 Com_Printf("disabled shaders because they failed to compile\n");
1050 Cvar_Set("r_programs", "0");
1051 r_programs->modified = false;
1052 }
1053}
1054
1059{
1060 if (r_programs->integer) {
1061 Com_Printf("glsl restart to a version of v%s\n", Cvar_Get("r_glsl_version", nullptr, 0, nullptr)->string);
1062 } else {
1063 Com_Printf("glsl shutdown\n");
1064 }
1065
1069}
memPool_t * vid_imagePool
Definition cl_main.cpp:88
rendererData_t refdef
Definition r_main.cpp:45
viddef_t viddef
Definition cl_video.cpp:34
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition common.cpp:440
void Com_Error(int code, const char *fmt,...)
Definition common.cpp:459
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define ERR_DROP
Definition common.h:211
#define ERR_FATAL
Definition common.h:210
cvar_t * Cvar_Set(const char *varName, const char *value,...)
Sets a cvar value.
Definition cvar.cpp:615
float Cvar_GetValue(const char *varName)
Returns the float value of a cvar.
Definition cvar.cpp:125
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags, const char *desc)
Init or return a cvar.
Definition cvar.cpp:342
#define DEBUG_RENDERER
Definition defines.h:62
#define MAX_STRING_CHARS
Definition defines.h:90
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition files.cpp:384
void FS_FreeFile(void *buffer)
Definition files.cpp:411
#define MAX_QPATH
Definition filesys.h:40
voidpf void uLong size
Definition ioapi.h:42
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
voidpf void * buf
Definition ioapi.h:42
voidpf uLong offset
Definition ioapi.h:45
void GLVectorTransform(const float m[16], const vec4_t in, vec4_t out)
Multiply 4*4 matrix by 4d vector.
Definition mathlib.cpp:366
#define Mem_PoolAllocTypeN(type, n, pool)
Definition mem.h:42
#define Mem_Free(ptr)
Definition mem.h:35
const char * Com_Parse(const char *data_p[], char *target, size_t size, bool replaceWhitespaces)
Parse a token out of a string.
Definition parse.cpp:107
Shared parsing functions.
Error checking function.
#define R_CheckError()
Definition r_error.h:30
void R_InitFBObjects(void)
QGL_EXTERN GLuint GLchar GLuint * len
Definition r_gl.h:99
QGL_EXTERN GLint
Definition r_gl.h:135
QGL_EXTERN int GLboolean GLfloat * v
Definition r_gl.h:120
QGL_EXTERN GLuint GLsizei GLsizei * length
Definition r_gl.h:110
QGL_EXTERN GLfloat f
Definition r_gl.h:114
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLint GLenum type
Definition r_gl.h:94
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
QGL_EXTERN GLuint
Definition r_gl.h:124
QGL_EXTERN const GLuint *QGL_EXTERN GLuint *QGL_EXTERN GLenum
Definition r_gl.h:127
#define GL_FRAGMENT_SHADER
#define GL_COMPILE_STATUS
#define GL_VERTEX_SHADER
#define GL_LINK_STATUS
local graphics definitions
@ GLHW_INTEL
Definition r_local.h:149
@ GLHW_GENERIC
Definition r_local.h:147
@ GLHW_MESA
Definition r_local.h:148
@ GLHW_ATI
Definition r_local.h:150
@ GLHW_NVIDIA
Definition r_local.h:151
cvar_t * r_fog
Definition r_main.cpp:107
cvar_t * r_programs
Definition r_main.cpp:97
rconfig_t r_config
Definition r_main.cpp:47
cvar_t * r_glsl_version
The GLSL version being used (not necessarily a supported version by the OpenGL implementation)....
Definition r_main.cpp:99
rlocals_t r_locals
Definition r_main.cpp:49
rstate_t r_state
Definition r_main.cpp:48
material_t defaultMaterial
void R_InitParticleProgram(r_program_t *prog)
void R_ProgramParameter1fvs(const char *name, GLint size, GLfloat *value)
static void R_UseModelProgram(r_program_t *prog)
static void R_UseWorldProgram(r_program_t *prog)
static void R_InitWarpProgram(r_program_t *prog)
static int R_PascalTriangle(int row, int col)
static void R_InitConvolveProgram(r_program_t *prog)
shaderQualityLevel_t
Definition r_program.cpp:35
@ SHQ_LOW
Definition r_program.cpp:35
@ SHQ_MID
Definition r_program.cpp:35
@ SHQ_HIGH
Definition r_program.cpp:35
@ SHQ_NUM
Definition r_program.cpp:35
vec2_t fogRange
Definition r_state.cpp:584
void R_RestartPrograms_f(void)
Reloads the glsl shaders.
#define FILTER_SIZE
width of convolution filter (for blur/bloom effects)
void R_ProgramParameter1i(const char *name, GLint value)
void R_UseParticleProgram(r_program_t *prog)
static void R_InitAtmosphereProgram(r_program_t *prog)
static r_progvar_t * R_ProgramVariable(int type, const char *name)
Definition r_program.cpp:67
r_program_t * R_LoadProgram(const char *name, programInitFunc_t init, programUseFunc_t use)
static size_t R_InitializeShader(const GLenum type, const char *name, char *out, size_t len)
Prefixes the shader string with user settings and the video hardware manufacturer.
static void R_UseWarpProgram(r_program_t *prog)
static void R_InitWorldProgram(r_program_t *prog)
static void R_InitSimpleGlowProgram(r_program_t *prog)
static size_t R_PreprocessShaderAddToShaderBuf(const char *name, const char *in, char **out, size_t *len)
Prefixes shader string (out) with in.
void R_EnableAttribute(const char *name)
static void R_InitCombine2Program(r_program_t *prog)
void R_ProgramParameterMatrix4fv(const char *name, GLfloat *value)
void R_ProgramParameter2fv(const char *name, GLfloat *value)
void R_ProgramParameter3fvs(const char *name, GLint size, GLfloat *value)
void R_ProgramParameter4fv(const char *name, GLfloat *value)
void R_InitPrograms(void)
static size_t R_PreprocessShaderR(const char *name, const char **inPtr, char *out, long *remainingOutChars, bool nested, bool inElse)
Do our own preprocessing to the shader file, before the GLSL implementation calls it's preprocessor.
void R_ShutdownPrograms(void)
void R_ProgramParameter1f(const char *name, GLfloat value)
static void R_InitModelProgram(r_program_t *prog)
static void R_InitGeoscapeProgram(r_program_t *prog)
void R_ProgramParameter4fvs(const char *name, GLint size, GLfloat *value)
void R_DisableAttribute(const char *name)
static size_t R_PreprocessShader(const char *name, const char *in, char *out, size_t *remainingOutChars)
Do our own preprocessing to the shader file, before the GLSL implementation calls it's preprocessor.
#define SHADER_BUF_SIZE
Definition r_program.cpp:33
void R_AttributePointer(const char *name, GLuint size, const GLvoid *array)
void R_ProgramParameter2fvs(const char *name, GLint size, GLfloat *value)
const char * shaderQualityLevelNames[SHQ_NUM][2]
Definition r_program.cpp:37
void R_UseProgram(r_program_t *prog)
Definition r_program.cpp:43
static void R_UseConvolveProgram(r_program_t *prog)
Use the filter convolution glsl program.
void R_ProgramParameter3fv(const char *name, GLfloat *value)
static r_shader_t * R_LoadShader(const GLenum type, const char *name)
Reads/Preprocesses/Compiles the specified shader into a program.
static void R_ShutdownShader(r_shader_t *sh)
static void R_ShutdownProgram(r_program_t *prog)
void(* programUseFunc_t)(struct r_program_s *prog)
Definition r_program.h:51
#define MAX_PROGRAM_VARS
Definition r_program.h:46
#define MAX_SHADERS
Definition r_program.h:66
void(* programInitFunc_t)(struct r_program_s *prog)
Definition r_program.h:50
#define GL_ATTRIBUTE
Definition r_program.h:36
#define GL_UNIFORM
Definition r_program.h:34
#define MAX_PROGRAMS
Definition r_program.h:65
#define Q_streq(a, b)
Definition shared.h:136
#define DOUBLEQUOTE(x)
Definition shared.h:90
#define OBJZERO(obj)
Definition shared.h:178
#define lengthof(x)
Definition shared.h:105
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition shared.cpp:457
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition shared.cpp:494
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition shared.cpp:410
programUseFunc_t use
Definition r_program.h:61
void * userdata
Definition r_program.h:62
GLuint id
Definition r_program.h:55
programInitFunc_t init
Definition r_program.h:60
r_shader_t * v
Definition r_program.h:57
r_shader_t * f
Definition r_program.h:58
char name[MAX_VAR]
Definition r_program.h:56
GLuint id
Definition r_program.h:29
char name[MAX_QPATH]
Definition r_program.h:30
GLenum type
Definition r_program.h:28
vec_t vec4_t[4]
Definition ufotypes.h:40
vec_t vec2_t[2]
Definition ufotypes.h:38