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