1 /** @file h_special.cpp  Special color effects for the game view.
2  *
3  * @authors Copyright (c) 2018 Jaakko Keränen <jaakko.keranen@iki.fi>
4  *
5  * @par License
6  * GPL: http://www.gnu.org/licenses/gpl.html
7  *
8  * <small>This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2 of the License, or (at your
11  * option) any later version. This program is distributed in the hope that it
12  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details. You should have received a copy of the GNU
15  * General Public License along with this program; if not, see:
16  * http://www.gnu.org/licenses</small>
17  */
18 
19 #include "r_special.h"
20 #include "common.h"
21 
22 static float appliedFilter[MAXPLAYERS];
23 
24 #if defined(__JHERETIC__)
25 static byte ringShader = 0;
26 #endif
27 
R_SpecialFilterRegister()28 void R_SpecialFilterRegister()
29 {
30 #if defined(__JHERETIC__)
31     C_VAR_BYTE("rend-ring-effect", &ringShader, 0, 0, 1);
32 #endif
33     R_InitSpecialFilter();
34 }
35 
R_InitSpecialFilter()36 void R_InitSpecialFilter()
37 {
38     for(int i = 0; i < MAXPLAYERS; ++i)
39     {
40         appliedFilter[i] = -1;
41     }
42 }
43 
R_ClearSpecialFilter(int player,float fadeDuration)44 void R_ClearSpecialFilter(int player, float fadeDuration)
45 {
46     if (appliedFilter[player] > 0)
47     {
48         DD_Executef(true, "postfx %i opacity 1; postfx %i none %f", player, player, fadeDuration);
49         appliedFilter[player] = -1;
50     }
51 }
52 
R_UpdateSpecialFilterWithTimeDelta(int player,float delta)53 void R_UpdateSpecialFilterWithTimeDelta(int player, float delta)
54 {
55     const player_t *plr       = players + player;
56     const char *    fxName    = "none";
57     float           intensity = 1.f;
58 
59 #if defined(__JDOOM__)
60     {
61         // In HacX a simple blue shift is used instead.
62         if (gameMode == doom2_hacx) return;
63 
64         fxName = "monochrome.inverted";
65 
66         int filter = plr->powers[PT_INVULNERABILITY];
67         if (!filter)
68         {
69             // Clear the filter.
70             R_ClearSpecialFilter(player, delta);
71             return;
72         }
73         if (filter < 4 * 32 && !(filter & 8))
74         {
75             intensity = 0;
76         }
77     }
78 #endif
79 
80 #if defined(__JHERETIC__)
81     {
82         delta  = 0; // not animated
83         fxName = (ringShader == 0 ? "colorize.gold" : "colorize.inverted.gold");
84 
85         const int filter = plr->powers[PT_INVULNERABILITY];
86         if (!filter)
87         {
88             // Clear the filter.
89             R_ClearSpecialFilter(player, delta);
90             return;
91         }
92         if (filter <= BLINKTHRESHOLD && !(filter & 8))
93         {
94             intensity = 0;
95         }
96     }
97 #endif
98 
99     if (gfw_CurrentGame() == GFW_HEXEN || gfw_CurrentGame() == GFW_DOOM64)
100     {
101         R_ClearSpecialFilter(player, delta);
102         return;
103     }
104 
105     // Activate the filter; load the shader if the effect was previously not in use.
106     if (appliedFilter[player] < 0)
107     {
108         DD_Executef(true, "postfx %i %s %f", player, fxName, delta);
109     }
110 
111     // Update filter opacity.
112     if (!FEQUAL(appliedFilter[player], intensity))
113     {
114         DD_Executef(true, "postfx %i opacity %f", player, intensity);
115         appliedFilter[player] = intensity;
116     }
117 }
118 
R_UpdateSpecialFilter(int player)119 void R_UpdateSpecialFilter(int player)
120 {
121     R_UpdateSpecialFilterWithTimeDelta(player, .3f);
122 }
123