OpenClonk
C4FoW.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2014-2016, The OpenClonk Team and contributors
5  *
6  * Distributed under the terms of the ISC license; see accompanying file
7  * "COPYING" for details.
8  *
9  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10  * See accompanying file "TRADEMARK" for details.
11  *
12  * To redistribute this file separately, substitute the full license texts
13  * for the above references.
14  */
15 
16 #include "C4Include.h"
18 #include "landscape/fow/C4FoW.h"
19 #include "graphics/C4Draw.h"
20 
21 #include <cfloat>
22 
23 
24 C4FoW::C4FoW() = default;
25 
27 {
28  if (deleted_lights)
29  {
31  }
32 }
33 
35 {
36 #ifndef USE_CONSOLE
37  // Kill any dead lights
38  while (deleted_lights)
39  {
40  C4FoWLight *light = deleted_lights;
41  deleted_lights = deleted_lights->getNext();
42  delete light;
43  }
44 #endif
45 }
46 
48 {
49 #ifndef USE_CONSOLE
50  // Not created yet?
51  if (!FramebufShader.Initialised())
52  {
53  // Create the frame buffer shader. The details are in C4FoWRegion, but
54  // this is about how to utilise old frame buffer data in the lights texture.
55  // Or put in other words: This shader is responsible for fading lights out.
56  const char* FramebufVertexShader =
57  "in vec2 oc_Position;\n"
58  "in vec2 oc_TexCoord;\n"
59  "out vec2 texcoord;\n"
60  "uniform mat4 projectionMatrix;\n"
61  "\n"
62  "slice(position)\n"
63  "{\n"
64  " gl_Position = projectionMatrix * vec4(oc_Position, 0.0, 1.0);\n"
65  "}\n"
66  "\n"
67  "slice(texcoord)\n"
68  "{\n"
69  " texcoord = oc_TexCoord;\n"
70  "}";
71 
72  const char* FramebufFragmentShader =
73  "in vec2 texcoord;\n"
74  "uniform sampler2D tex;\n"
75  "out vec4 fragColor;\n"
76  "\n"
77  "slice(color)\n"
78  "{\n"
79  " fragColor = texture(tex, texcoord);\n"
80  "}";
81 
82  FramebufShader.AddVertexSlices("built-in FoW framebuf shader", FramebufVertexShader);
83  FramebufShader.AddFragmentSlices("built-in FoW framebuf shader", FramebufFragmentShader);
84 
85  const char *szUniforms[C4FoWFSU_Count + 1];
86  szUniforms[C4FoWFSU_ProjectionMatrix] = "projectionMatrix";
87  szUniforms[C4FoWFSU_Texture] = "tex";
88  szUniforms[C4FoWFSU_Count] = nullptr;
89 
90  const char *szAttributes[C4FoWFSA_Count + 1];
91  szAttributes[C4FoWFSA_Position] = "oc_Position";
92  szAttributes[C4FoWFSA_TexCoord] = "oc_TexCoord";
93  szAttributes[C4FoWFSA_Count] = nullptr;
94 
95  if (!FramebufShader.Init("framebuf", szUniforms, szAttributes)) {
96  FramebufShader.ClearSlices();
97  return nullptr;
98  }
99  }
100  return &FramebufShader;
101 #else
102  return nullptr;
103 #endif
104 }
105 
107 {
108 #ifndef USE_CONSOLE
109  // Not created yet?
110  if (!RenderShader.Initialised())
111  {
112  // Create the render shader. Fairly simple pass-through.
113  const char* RenderVertexShader =
114  "in vec2 oc_Position;\n"
115  "in vec4 oc_Color;\n"
116  "out vec4 vtxColor;\n"
117  "uniform mat4 projectionMatrix;\n"
118  "uniform vec2 vertexOffset;\n"
119  "\n"
120  "slice(position)\n"
121  "{\n"
122  " gl_Position = projectionMatrix * vec4(oc_Position + vertexOffset, 0.0, 1.0);\n"
123  "}\n"
124  "\n"
125  "slice(color)\n"
126  "{\n"
127  " vtxColor = oc_Color;\n"
128  "}";
129 
130  const char* RenderFragmentShader =
131  "in vec4 vtxColor;\n"
132  "out vec4 fragColor;\n"
133  "\n"
134  "slice(color)\n"
135  "{\n"
136  " fragColor = vtxColor;\n"
137  "}";
138 
139  RenderShader.AddVertexSlices("built-in FoW render shader", RenderVertexShader);
140  RenderShader.AddFragmentSlices("built-in FoW render shader", RenderFragmentShader);
141 
142  const char* szUniforms[C4FoWRSU_Count + 1];
143  szUniforms[C4FoWRSU_ProjectionMatrix] = "projectionMatrix";
144  szUniforms[C4FoWRSU_VertexOffset] = "vertexOffset";
145  szUniforms[C4FoWRSU_Count] = nullptr;
146 
147  const char* szAttributes[C4FoWRSA_Count + 1];
148  szAttributes[C4FoWRSA_Position] = "oc_Position";
149  szAttributes[C4FoWRSA_Color] = "oc_Color";
150  szAttributes[C4FoWRSA_Count] = nullptr;
151 
152  if (!RenderShader.Init("fowRender", szUniforms, szAttributes)) {
153  RenderShader.ClearSlices();
154  return nullptr;
155  }
156 
157  }
158  return &RenderShader;
159 #else
160  return nullptr;
161 #endif
162 }
163 
164 
165 void C4FoW::Add(C4Object *pObj)
166 {
167 #ifndef USE_CONSOLE
168  // No view range? Probably want to remove instead
169  if(!pObj->lightRange && !pObj->lightFadeoutRange)
170  {
171  Remove(pObj);
172  return;
173  }
174 
175  // Safety
176  if (!pObj->Status) return;
177 
178  // Look for matching light
179  C4FoWLight *pLight;
180  for (pLight = pLights; pLight; pLight = pLight->getNext())
181  if (pLight->getObj() == pObj)
182  break;
183 
184  if (pLight)
185  {
186 
187  // Update reach and light color
188  pLight->SetReach(pObj->lightRange, pObj->lightFadeoutRange);
189  pLight->SetColor(pObj->lightColor);
190  }
191  else
192  {
193  // Create new light otherwise
194  pLight = new C4FoWLight(pObj);
195  pLight->pNext = pLights;
196  pLights = pLight;
197  }
198 #endif
199 }
200 
202 {
203 #ifndef USE_CONSOLE
204  // Look for matching light
205  C4FoWLight *pPrev = nullptr, *pLight;
206  for (pLight = pLights; pLight; pPrev = pLight, pLight = pLight->getNext())
207  if (pLight->getObj() == pObj)
208  break;
209  if (!pLight)
210  return;
211 
212  // Remove from list
213  (pPrev ? pPrev->pNext : pLights) = pLight->getNext();
214 
215  // Delete on next render pass
216  pLight->pNext = deleted_lights;
217  deleted_lights = pLight;
218 #endif
219 }
220 
222 {
223 #ifndef USE_CONSOLE
224  for (C4FoWLight *pLight = pLights; pLight; pLight = pLight->getNext())
225  pLight->Invalidate(r);
226 #endif
227 }
228 
230 {
231 #ifndef USE_CONSOLE
232  for (C4FoWLight *pLight = pLights; pLight; pLight = pLight->getNext())
233  if (pLight->IsVisibleForPlayer(pPlr))
234  pLight->Update(r);
235 #endif
236 }
237 
238 void C4FoW::Render(C4FoWRegion *pRegion, const C4TargetFacet *pOnScreen, C4Player *pPlr, const StdProjectionMatrix& projectionMatrix)
239 {
240 #ifndef USE_CONSOLE
241  // Delete any dead lights
243  // Set up shader. If this one doesn't work, we're really in trouble.
244  C4Shader *pShader = GetRenderShader();
245  assert(pShader);
246  if (!pShader) return;
247 
248  C4ShaderCall Call(pShader);
249  Call.Start();
250  Call.SetUniformMatrix4x4(C4FoWRSU_ProjectionMatrix, projectionMatrix);
251 
252  for (C4FoWLight *pLight = pLights; pLight; pLight = pLight->getNext())
253  if (pLight->IsVisibleForPlayer(pPlr))
254  pLight->Render(pRegion, pOnScreen, Call);
255 
256  Call.Finish();
257 #endif
258 }
@ C4FoWRSU_ProjectionMatrix
Definition: C4FoW.h:84
@ C4FoWRSU_VertexOffset
Definition: C4FoW.h:85
@ C4FoWRSU_Count
Definition: C4FoW.h:87
@ C4FoWFSU_Texture
Definition: C4FoW.h:71
@ C4FoWFSU_ProjectionMatrix
Definition: C4FoW.h:70
@ C4FoWFSU_Count
Definition: C4FoW.h:73
@ C4FoWRSA_Count
Definition: C4FoW.h:94
@ C4FoWRSA_Color
Definition: C4FoW.h:92
@ C4FoWRSA_Position
Definition: C4FoW.h:91
@ C4FoWFSA_Position
Definition: C4FoW.h:77
@ C4FoWFSA_TexCoord
Definition: C4FoW.h:78
@ C4FoWFSA_Count
Definition: C4FoW.h:80
void Add(C4Object *pObj)
Definition: C4FoW.cpp:165
~C4FoW()
Definition: C4FoW.cpp:26
void Remove(C4Object *pObj)
Definition: C4FoW.cpp:201
C4Shader * GetFramebufShader()
Definition: C4FoW.cpp:47
void ClearDeletedLights()
Definition: C4FoW.cpp:34
C4Shader * GetRenderShader()
Definition: C4FoW.cpp:106
void Render(class C4FoWRegion *pRegion, const C4TargetFacet *pOnScreen, C4Player *pPlr, const StdProjectionMatrix &projectionMatrix)
Definition: C4FoW.cpp:238
void Invalidate(C4Rect r)
Definition: C4FoW.cpp:221
void Update(C4Rect r, C4Player *player)
Definition: C4FoW.cpp:229
void SetReach(int32_t iReach, int32_t iFadeout)
Definition: C4FoWLight.cpp:58
C4Object * getObj() const
Definition: C4FoWLight.h:72
void SetColor(uint32_t iValue)
Definition: C4FoWLight.cpp:81
C4FoWLight * getNext() const
Definition: C4FoWLight.h:71
int32_t lightRange
Definition: C4Object.h:120
int32_t lightFadeoutRange
Definition: C4Object.h:121
uint32_t lightColor
Definition: C4Object.h:122
int32_t Status
Definition: C4PropList.h:173
Definition: C4Rect.h:28
bool Initialised() const
Definition: C4Shader.h:106
void AddVertexSlices(const char *szWhat, const char *szText, const char *szSource="", int iFileTime=0)
Definition: C4Shader.cpp:82
void ClearSlices()
Definition: C4Shader.cpp:324
bool Init(const char *szWhat, const char **szUniforms, const char **szAttributes)
Definition: C4Shader.cpp:348
void AddFragmentSlices(const char *szWhat, const char *szText, const char *szSource="", int iFileTime=0)
Definition: C4Shader.cpp:87