1 /*
2 This file is part of Warzone 2100.
3 Copyright (C) 1999-2004 Eidos Interactive
4 Copyright (C) 2005-2020 Warzone 2100 Project
5
6 Warzone 2100 is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 Warzone 2100 is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Warzone 2100; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 /** \file
21 * Renderer setup and state control routines for 3D rendering.
22 */
23 #include "lib/framework/frame.h"
24
25 #include <physfs.h>
26 #include "lib/framework/physfs_ext.h"
27
28 #include "lib/ivis_opengl/pieblitfunc.h"
29 #include "lib/ivis_opengl/piestate.h"
30 #include "lib/ivis_opengl/piedef.h"
31 #include "lib/ivis_opengl/tex.h"
32 #include "lib/ivis_opengl/piepalette.h"
33 #include "screen.h"
34 #include "pieclip.h"
35 #include <glm/gtc/type_ptr.hpp>
36 #ifndef GLM_ENABLE_EXPERIMENTAL
37 #define GLM_ENABLE_EXPERIMENTAL
38 #endif
39 #include <glm/gtx/transform.hpp>
40
41 #include <algorithm>
42
43 /*
44 * Global Variables
45 */
46
47 static gfx_api::gfxFloat shaderStretch = 0;
48 gfx_api::buffer* pie_internal::rectBuffer = nullptr;
49 static RENDER_STATE rendStates;
50 static int32_t ecmState = 0;
51 static gfx_api::gfxFloat timeState = 0.0f;
52
rendStatesRendModeHack()53 void rendStatesRendModeHack()
54 {
55 rendStates.rendMode = REND_ALPHA;
56 }
57
58 /*
59 * Source
60 */
61
pie_SetDefaultStates()62 void pie_SetDefaultStates()//Sets all states
63 {
64 PIELIGHT black;
65
66 //fog off
67 rendStates.fogEnabled = false;// enable fog before renderer
68 rendStates.fog = false;//to force reset to false
69 pie_SetFogStatus(false);
70 black.rgba = 0;
71 black.byte.a = 255;
72 pie_SetFogColour(black);
73
74 rendStates.rendMode = REND_ALPHA; // to force reset to REND_OPAQUE
75 }
76
77 //***************************************************************************
78 //
79 // pie_EnableFog(bool val)
80 //
81 // Global enable/disable fog to allow fog to be turned of ingame
82 //
83 //***************************************************************************
pie_EnableFog(bool val)84 void pie_EnableFog(bool val)
85 {
86 if (rendStates.fogEnabled != val)
87 {
88 debug(LOG_FOG, "pie_EnableFog: Setting fog to %s", val ? "ON" : "OFF");
89 rendStates.fogEnabled = val;
90 if (val)
91 {
92 pie_SetFogColour(WZCOL_FOG);
93 }
94 else
95 {
96 pie_SetFogColour(WZCOL_BLACK); // clear background to black
97 }
98 }
99 }
100
pie_GetFogEnabled()101 bool pie_GetFogEnabled()
102 {
103 return rendStates.fogEnabled;
104 }
105
pie_GetFogStatus()106 bool pie_GetFogStatus()
107 {
108 return rendStates.fog;
109 }
110
pie_SetFogColour(PIELIGHT colour)111 void pie_SetFogColour(PIELIGHT colour)
112 {
113 rendStates.fogColour = colour;
114 }
115
pie_GetFogColour()116 PIELIGHT pie_GetFogColour()
117 {
118 return rendStates.fogColour;
119 }
120
pie_FreeShaders()121 void pie_FreeShaders()
122 {
123 // no-op, currently
124 }
125
126 //static float fogBegin;
127 //static float fogEnd;
128
129 // Run from screen.c on init.
pie_LoadShaders()130 bool pie_LoadShaders()
131 {
132 // note: actual loading of shaders now occurs in gfx_api
133
134 gfx_api::gfxUByte rect[] {
135 0, 255, 0, 255,
136 0, 0, 0, 255,
137 255, 255, 0, 255,
138 255, 0, 0, 255
139 };
140 if (!pie_internal::rectBuffer)
141 pie_internal::rectBuffer = gfx_api::context::get().create_buffer_object(gfx_api::buffer::usage::vertex_buffer);
142 pie_internal::rectBuffer->upload(16 * sizeof(gfx_api::gfxUByte), rect);
143
144 return true;
145 }
146
pie_SetShaderTime(uint32_t shaderTime)147 void pie_SetShaderTime(uint32_t shaderTime)
148 {
149 uint32_t base = shaderTime % 1000;
150 if (base > 500)
151 {
152 base = 1000 - base; // cycle
153 }
154 timeState = (gfx_api::gfxFloat)base / 1000.0f;
155 }
156
pie_GetShaderTime()157 float pie_GetShaderTime()
158 {
159 return timeState;
160 }
161
pie_SetShaderEcmEffect(bool value)162 void pie_SetShaderEcmEffect(bool value)
163 {
164 ecmState = (int)value;
165 }
166
pie_GetShaderEcmEffect()167 int pie_GetShaderEcmEffect()
168 {
169 return ecmState;
170 }
171
pie_SetShaderStretchDepth(float stretch)172 void pie_SetShaderStretchDepth(float stretch)
173 {
174 shaderStretch = stretch;
175 }
176
pie_GetShaderStretchDepth()177 float pie_GetShaderStretchDepth()
178 {
179 return shaderStretch;
180 }
181
182 /// Set the OpenGL fog start and end
pie_UpdateFogDistance(float begin,float end)183 void pie_UpdateFogDistance(float begin, float end)
184 {
185 rendStates.fogBegin = begin;
186 rendStates.fogEnd = end;
187 }
188
pie_SetFogStatus(bool val)189 void pie_SetFogStatus(bool val)
190 {
191 if (rendStates.fogEnabled)
192 {
193 //fog enabled so toggle if required
194 rendStates.fog = val;
195 }
196 else
197 {
198 rendStates.fog = false;
199 }
200 }
201
getCurrentRenderState()202 RENDER_STATE getCurrentRenderState()
203 {
204 return rendStates;
205 }
206
pie_GetMaxAntialiasing()207 int pie_GetMaxAntialiasing()
208 {
209 int32_t maxSamples = gfx_api::context::get().get_context_value(gfx_api::context::context_value::MAX_SAMPLES);
210 return maxSamples;
211 }
212