OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4LandscapeRenderGL Class Referenceabstract

#include <C4LandscapeRender.h>

Inheritance diagram for C4LandscapeRenderGL:
[legend]
Collaboration diagram for C4LandscapeRenderGL:
[legend]

Public Member Functions

 C4LandscapeRenderGL ()
 
 ~C4LandscapeRenderGL () override
 
bool ReInit (int32_t iWidth, int32_t iHeight) override
 
bool Init (int32_t iWidth, int32_t iHeight, C4TextureMap *pMap, C4GroupSet *pGraphics) override
 
void Clear () override
 
C4Rect GetAffectedRect (C4Rect Rect) override
 
void Update (C4Rect Rect, C4Landscape *pSource) override
 
void Draw (const C4TargetFacet &cgo, const C4FoWRegion *Light, uint32_t clrMod) override
 
virtual void Draw (const C4TargetFacet &cgo, const class C4FoWRegion *Light, uint32_t clrMod)=0
 

Protected Attributes

int32_t iWidth {0}
 
int32_t iHeight {0}
 
C4TextureMappTexs {nullptr}
 

Detailed Description

Definition at line 111 of file C4LandscapeRender.h.

Constructor & Destructor Documentation

C4LandscapeRenderGL::C4LandscapeRenderGL ( )

Definition at line 51 of file C4LandscapeRender.cpp.

References ZeroMem().

52 {
53  ZeroMem(Surfaces, sizeof(Surfaces));
54  hMaterialTexture = matMapTexture = 0;
55  hVBO = 0;
56  hVAOIDNoLight = 0;
57  hVAOIDLight = 0;
58 }
std::enable_if< std::is_pod< T >::value >::type ZeroMem(T *lpMem, size_t dwSize)
Definition: Standard.h:60

Here is the call graph for this function:

C4LandscapeRenderGL::~C4LandscapeRenderGL ( )
override

Definition at line 60 of file C4LandscapeRender.cpp.

References Clear().

61 {
62  Clear();
63 }

Here is the call graph for this function:

Member Function Documentation

void C4LandscapeRenderGL::Clear ( )
overridevirtual

Implements C4LandscapeRender.

Definition at line 136 of file C4LandscapeRender.cpp.

References C4LR_SurfaceCount, CStdGL::FreeVAOID(), and pGL.

Referenced by Init(), and ~C4LandscapeRenderGL().

137 {
138  ClearShaders();
139 
140  // free textures
141  int i;
142  for (i = 0; i < C4LR_SurfaceCount; i++)
143  {
144  delete Surfaces[i];
145  Surfaces[i] = nullptr;
146  }
147  if (hMaterialTexture) glDeleteTextures(1, &hMaterialTexture);
148  hMaterialTexture = 0;
149  if (matMapTexture) glDeleteTextures(1, &matMapTexture);
150  matMapTexture = 0;
151 
152  if (hVBO != 0)
153  {
154  glDeleteBuffers(1, &hVBO);
155  hVBO = 0;
156  }
157 
158  if (hVAOIDLight != 0)
159  {
160  pGL->FreeVAOID(hVAOIDLight);
161  hVAOIDLight = 0;
162  }
163 
164  if (hVAOIDNoLight != 0)
165  {
166  pGL->FreeVAOID(hVAOIDNoLight);
167  hVAOIDNoLight = 0;
168  }
169 }
const int C4LR_SurfaceCount
void FreeVAOID(unsigned int vaoid)
Definition: C4DrawGL.cpp:967
CStdGL * pGL
Definition: C4DrawGL.cpp:905

Here is the call graph for this function:

Here is the caller graph for this function:

virtual void C4LandscapeRender::Draw ( const C4TargetFacet cgo,
const class C4FoWRegion Light,
uint32_t  clrMod 
)
pure virtualinherited
void C4LandscapeRenderGL::Draw ( const C4TargetFacet cgo,
const C4FoWRegion Light,
uint32_t  clrMod 
)
override

Definition at line 935 of file C4LandscapeRender.cpp.

References C4ShaderCall::AllocTexUnit(), C4FoW::Ambient, C4ScriptUniform::Apply(), C4Draw::ApplyZoom(), FLOAT_RECT::bottom, C4LR_SurfaceCount, C4LRA_LandscapeTexCoord, C4LRA_LightTexCoord, C4LRA_Position, C4LRU_AmbientBrightness, C4LRU_AmbientTex, C4LRU_AmbientTransform, C4LRU_Center, C4LRU_FrameCounter, C4LRU_Gamma, C4LRU_LandscapeTex, C4LRU_LightTex, C4LRU_MaterialDepth, C4LRU_MaterialSize, C4LRU_MaterialTex, C4LRU_MatMapTex, C4LRU_Modulation, C4LRU_ProjectionMatrix, C4LRU_Resolution, C4LRU_ScalerTex, C4LRU_Time, C4Game::C4S, C4ShaderCall::Finish(), C4Game::FrameCounter, Game, C4Draw::gammaOut, C4Shader::GetAttribute(), C4FoWAmbient::GetBrightness(), C4Draw::GetClipRect(), C4FoWRegion::getFoW(), C4FoWAmbient::GetFragTransform(), C4Draw::GetOutRect(), CStdGL::GetProjectionMatrix(), C4FoWRegion::getRegion(), C4FoWRegion::getSurfaceHeight(), C4FoWRegion::getSurfaceName(), C4FoWRegion::getSurfaceWidth(), CStdGL::GetVAO(), C4FoWRegion::getViewportRegion(), C4Shader::HaveUniform(), C4Facet::Hgt, C4Shader::Initialised(), C4Scenario::Landscape, FLOAT_RECT::left, C4SLandscape::MaterialZoom, pDraw, pGL, CStdGL::PrepareRendering(), FLOAT_RECT::right, C4Draw::scriptUniform, C4ShaderCall::SetUniform1f(), C4ShaderCall::SetUniform1i(), C4ShaderCall::SetUniform1iv(), C4ShaderCall::SetUniform2f(), C4ShaderCall::SetUniform3fv(), C4ShaderCall::SetUniform4fv(), C4ShaderCall::SetUniformMatrix2x3fv(), C4ShaderCall::SetUniformMatrix4x4(), C4ShaderCall::Start(), C4Facet::Surface, C4TargetFacet::TargetX, C4TargetFacet::TargetY, C4FoWAmbient::Tex, C4Surface::texture, FLOAT_RECT::top, C4Facet::Wdt, C4Rect::x, C4Facet::X, C4Rect::y, C4Facet::Y, and C4Draw::Zoom.

936 {
937  // Must have GL and be initialized
938  if(!pGL && !Shader.Initialised() && !ShaderLight.Initialised()) return;
939 
940  // prepare rendering to surface
941  C4Surface *sfcTarget = cgo.Surface;
942  if (!pGL->PrepareRendering(sfcTarget)) return;
943 
944  // Choose the right shader depending on whether we have dynamic lighting or not
945  const C4Shader* shader = &Shader;
946  if (Light) shader = &ShaderLight;
947  if (!shader->Initialised()) return;
948 
949  // Activate shader
950  C4ShaderCall ShaderCall(shader);
951  ShaderCall.Start();
952 
953  // Bind data
954  ShaderCall.SetUniformMatrix4x4(C4LRU_ProjectionMatrix, pGL->GetProjectionMatrix());
955  ShaderCall.SetUniform3fv(C4LRU_Gamma, 1, pGL->gammaOut);
956  ShaderCall.SetUniform2f(C4LRU_Resolution, Surfaces[0]->Wdt, Surfaces[0]->Hgt);
957  float centerX = float(cgo.TargetX)+float(cgo.Wdt)/2,
958  centerY = float(cgo.TargetY)+float(cgo.Hgt)/2;
959  ShaderCall.SetUniform2f(C4LRU_Center,
960  centerX / float(Surfaces[0]->Wdt),
961  centerY / float(Surfaces[0]->Hgt));
962  ShaderCall.SetUniform1f(C4LRU_MaterialDepth, float(iMaterialTextureDepth));
963  ShaderCall.SetUniform2f(C4LRU_MaterialSize,
964  float(iMaterialWidth) / ::Game.C4S.Landscape.MaterialZoom,
965  float(iMaterialHeight) / ::Game.C4S.Landscape.MaterialZoom);
966  const float fMod[4] = {
967  ((clrMod >> 16) & 0xff) / 255.0f,
968  ((clrMod >> 8) & 0xff) / 255.0f,
969  ((clrMod ) & 0xff) / 255.0f,
970  ((clrMod >> 24) & 0xff) / 255.0f
971  };
972  ShaderCall.SetUniform4fv(C4LRU_Modulation, 1, fMod);
973 
974  if (Light)
975  {
976  const FLOAT_RECT ViewportRect = Light->getViewportRegion();
977  const C4Rect ClipRect = pDraw->GetClipRect();
978  const C4Rect OutRect = pDraw->GetOutRect();
979  float ambientTransform[6];
980  Light->getFoW()->Ambient.GetFragTransform(ViewportRect, ClipRect, OutRect, ambientTransform);
981  ShaderCall.SetUniformMatrix2x3fv(C4LRU_AmbientTransform, 1, ambientTransform);
982  ShaderCall.SetUniform1f(C4LRU_AmbientBrightness, Light->getFoW()->Ambient.GetBrightness());
983  }
984 
985  // time information
986  ShaderCall.SetUniform1i(C4LRU_FrameCounter, ::Game.FrameCounter);
987  const auto now = std::chrono::steady_clock::now();
988  const int epoch = std::chrono::duration_cast<std::chrono::milliseconds>(now - TimerStart).count();
989  ShaderCall.SetUniform1i(C4LRU_Time, epoch);
990 
991  pDraw->scriptUniform.Apply(ShaderCall);
992 
993  // Start binding textures
994  if(shader->HaveUniform(C4LRU_LandscapeTex))
995  {
996  GLint iLandscapeUnits[C4LR_SurfaceCount];
997  for(int i = 0; i < C4LR_SurfaceCount; i++)
998  {
999  iLandscapeUnits[i] = ShaderCall.AllocTexUnit(-1) - GL_TEXTURE0;
1000  glBindTexture(GL_TEXTURE_2D, Surfaces[i]->texture->texName);
1001  if (pGL->Zoom != 1.0)
1002  {
1003  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1004  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1005  }
1006  else
1007  {
1008  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1009  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1010  }
1011  }
1012  ShaderCall.SetUniform1iv(C4LRU_LandscapeTex, C4LR_SurfaceCount, iLandscapeUnits);
1013  }
1014  if(Light && ShaderCall.AllocTexUnit(C4LRU_LightTex))
1015  {
1016  glBindTexture(GL_TEXTURE_2D, Light->getSurfaceName());
1017  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1018  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1019  }
1020  if(Light && ShaderCall.AllocTexUnit(C4LRU_AmbientTex))
1021  {
1022  glBindTexture(GL_TEXTURE_2D, Light->getFoW()->Ambient.Tex);
1023  }
1024  if(ShaderCall.AllocTexUnit(C4LRU_ScalerTex))
1025  {
1026  glBindTexture(GL_TEXTURE_2D, fctScaler.Surface->texture->texName);
1027  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1028  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1029  }
1030  if(ShaderCall.AllocTexUnit(C4LRU_MaterialTex))
1031  {
1032  glBindTexture(GL_TEXTURE_2D_ARRAY, hMaterialTexture);
1033  }
1034  if(ShaderCall.AllocTexUnit(C4LRU_MatMapTex))
1035  {
1036  uint32_t MatMap[2*256];
1037  BuildMatMap(MatMap);
1038  glBindTexture(GL_TEXTURE_1D, matMapTexture);
1039  glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA8, 2*256, 0, GL_RGBA, GL_UNSIGNED_BYTE, MatMap);
1040  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1041  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1042  }
1043 
1044  // Calculate coordinates into landscape texture
1045  FLOAT_RECT fTexBlt;
1046  float fx = float(cgo.TargetX), fy = float(cgo.TargetY);
1047  fTexBlt.left = fx / Surfaces[0]->Wdt;
1048  fTexBlt.top = fy / Surfaces[0]->Hgt;
1049  fTexBlt.right = (fx + float(cgo.Wdt)) / Surfaces[0]->Wdt;
1050  fTexBlt.bottom= (fy + float(cgo.Hgt)) / Surfaces[0]->Hgt;
1051 
1052  // Calculate coordinates on screen (zoomed!)
1053  FLOAT_RECT tTexBlt;
1054  float tx = float(cgo.X), ty = float(cgo.Y);
1055  pGL->ApplyZoom(tx, ty);
1056  tTexBlt.left = tx;
1057  tTexBlt.top = ty;
1058  tTexBlt.right = tx + float(cgo.Wdt) * pGL->Zoom;
1059  tTexBlt.bottom= ty + float(cgo.Hgt) * pGL->Zoom;
1060 
1061  // Blend it
1062  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1063 
1064  // Prepare vertex data
1065  float vtxData[24];
1066  float* pos = &vtxData[0];
1067  float* tex = &vtxData[8];
1068  float* lightTex = &vtxData[16];
1069 
1070  pos[0] = tTexBlt.left;
1071  pos[1] = tTexBlt.top;
1072  pos[2] = tTexBlt.right;
1073  pos[3] = tTexBlt.top;
1074  pos[4] = tTexBlt.left;
1075  pos[5] = tTexBlt.bottom;
1076  pos[6] = tTexBlt.right;
1077  pos[7] = tTexBlt.bottom;
1078 
1079  tex[0] = fTexBlt.left;
1080  tex[1] = fTexBlt.top;
1081  tex[2] = fTexBlt.right;
1082  tex[3] = fTexBlt.top;
1083  tex[4] = fTexBlt.left;
1084  tex[5] = fTexBlt.bottom;
1085  tex[6] = fTexBlt.right;
1086  tex[7] = fTexBlt.bottom;
1087 
1088  unsigned int nFloats = 16;
1089  if (Light)
1090  {
1091  FLOAT_RECT lTexBlt;
1092  const C4Rect LightRect = Light->getRegion();
1093  int32_t iLightWdt = Light->getSurfaceWidth(),
1094  iLightHgt = Light->getSurfaceHeight();
1095  lTexBlt.left = (fx - LightRect.x) / iLightWdt;
1096  lTexBlt.top = 1.0 - (fy - LightRect.y) / iLightHgt;
1097  lTexBlt.right = (fx + cgo.Wdt - LightRect.x) / iLightWdt;
1098  lTexBlt.bottom = 1.0 - (fy + cgo.Hgt - LightRect.y) / iLightHgt;
1099 
1100  lightTex[0] = lTexBlt.left;
1101  lightTex[1] = lTexBlt.top;
1102  lightTex[2] = lTexBlt.right;
1103  lightTex[3] = lTexBlt.top;
1104  lightTex[4] = lTexBlt.left;
1105  lightTex[5] = lTexBlt.bottom;
1106  lightTex[6] = lTexBlt.right;
1107  lightTex[7] = lTexBlt.bottom;
1108  nFloats = 24;
1109  }
1110 
1111  // Upload vertex data
1112  glBindBuffer(GL_ARRAY_BUFFER, hVBO);
1113  glBufferSubData(GL_ARRAY_BUFFER, 0, nFloats * sizeof(float), vtxData);
1114 
1115  // Bind VAO
1116  unsigned int vaoid = Light ? hVAOIDLight : hVAOIDNoLight;
1117  GLuint vao;
1118  const bool has_vao = pGL->GetVAO(vaoid, vao);
1119  glBindVertexArray(vao);
1120  if (!has_vao)
1121  {
1122  // Setup state
1123  glEnableVertexAttribArray(shader->GetAttribute(C4LRA_Position));
1124  glEnableVertexAttribArray(shader->GetAttribute(C4LRA_LandscapeTexCoord));
1125  if (Light)
1126  glEnableVertexAttribArray(shader->GetAttribute(C4LRA_LightTexCoord));
1127 
1128  glVertexAttribPointer(shader->GetAttribute(C4LRA_Position), 2, GL_FLOAT, GL_FALSE, 0, nullptr);
1129  glVertexAttribPointer(shader->GetAttribute(C4LRA_LandscapeTexCoord), 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<const uint8_t*>(8 * sizeof(float)));
1130  if (Light)
1131  glVertexAttribPointer(shader->GetAttribute(C4LRA_LightTexCoord), 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<const uint8_t*>(16 * sizeof(float)));
1132  }
1133 
1134  // Do the blit
1135  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1136 
1137  // Reset state
1138  glBindVertexArray(0);
1139  glBindBuffer(GL_ARRAY_BUFFER, 0);
1140 
1141  ShaderCall.Finish();
1142 }
float Y
Definition: C4Facet.h:118
void ApplyZoom(float &X, float &Y)
Definition: C4Draw.cpp:784
const int C4LR_SurfaceCount
int Wdt
Definition: C4Surface.h:65
int32_t MaterialZoom
Definition: C4Scenario.h:185
C4Game Game
Definition: C4Globals.cpp:52
C4ScriptUniform scriptUniform
Definition: C4Draw.h:100
float bottom
Definition: C4Rect.h:25
C4Scenario C4S
Definition: C4Game.h:74
const FLOAT_RECT & getViewportRegion() const
Definition: C4FoWRegion.h:52
float right
Definition: C4Rect.h:25
float left
Definition: C4Rect.h:25
C4SLandscape Landscape
Definition: C4Scenario.h:234
float gammaOut[3]
Definition: C4Draw.h:98
double GetBrightness() const
Definition: C4FoWAmbient.h:56
void Apply(C4ShaderCall &call)
Definition: C4Shader.cpp:826
Definition: C4Rect.h:27
const C4FoW * getFoW() const
Definition: C4FoWRegion.h:50
int Hgt
Definition: C4Surface.h:65
int32_t FrameCounter
Definition: C4Game.h:128
int32_t y
Definition: C4Rect.h:30
int32_t getSurfaceHeight() const
GLuint getSurfaceName() const
C4Draw * pDraw
Definition: C4Draw.cpp:42
bool GetVAO(unsigned int vaoid, GLuint &vao)
Definition: C4DrawGL.cpp:1013
int32_t getSurfaceWidth() const
C4FoWAmbient Ambient
Definition: C4FoW.h:115
bool HaveUniform(int iUniform) const
Definition: C4Shader.h:122
GLint GetAttribute(int iAttribute) const
Definition: C4Shader.h:127
int32_t x
Definition: C4Rect.h:30
float Zoom
Definition: C4Draw.h:116
std::unique_ptr< C4TexRef > texture
Definition: C4Surface.h:78
bool Initialised() const
Definition: C4Shader.h:106
float TargetX
Definition: C4Facet.h:165
float Hgt
Definition: C4Facet.h:118
bool PrepareRendering(C4Surface *sfcToSurface) override
Definition: C4DrawGL.cpp:169
C4Rect GetOutRect() const
Definition: C4Draw.cpp:739
const C4Rect & getRegion() const
Definition: C4FoWRegion.h:51
CStdGL * pGL
Definition: C4DrawGL.cpp:905
C4Rect GetClipRect() const
Definition: C4Draw.cpp:730
const StdProjectionMatrix & GetProjectionMatrix() const
Definition: C4DrawGL.h:251
C4Surface * Surface
Definition: C4Facet.h:117
float TargetY
Definition: C4Facet.h:165
float Wdt
Definition: C4Facet.h:118
float X
Definition: C4Facet.h:118
float top
Definition: C4Rect.h:25
void GetFragTransform(const struct FLOAT_RECT &vpRect, const C4Rect &clipRect, const C4Rect &outRect, float ambientTransform[6]) const

Here is the call graph for this function:

C4Rect C4LandscapeRenderGL::GetAffectedRect ( C4Rect  Rect)
overridevirtual

Implements C4LandscapeRender.

Definition at line 350 of file C4LandscapeRender.cpp.

References C4LR_BiasDistanceX, C4LR_BiasDistanceY, and C4Rect::Enlarge().

351 {
353  return Rect;
354 }
const int C4LR_BiasDistanceX
const int C4LR_BiasDistanceY
void Enlarge(int32_t iByX, int32_t iByY)
Definition: C4Rect.h:51

Here is the call graph for this function:

bool C4LandscapeRenderGL::Init ( int32_t  iWidth,
int32_t  iHeight,
C4TextureMap pMap,
C4GroupSet pGraphics 
)
overridevirtual

Implements C4LandscapeRender.

Definition at line 65 of file C4LandscapeRender.cpp.

References Clear(), C4LandscapeRender::iHeight, C4LandscapeRender::iWidth, LogFatal(), and C4LandscapeRender::pTexs.

66 {
67  Clear();
68 
69  // Safe info
70  this->iWidth = iWidth;
71  this->iHeight = iHeight;
72  this->pTexs = pTexs;
73 
74  // Start timer
75  this->TimerStart = std::chrono::steady_clock::now();
76 
77  // Allocate landscape textures
78  if (!InitLandscapeTexture())
79  {
80  LogFatal("[!] Could not initialize landscape texture!");
81  return false;
82  }
83 
84  // Build texture, er, texture
85  if (!InitMaterialTexture(pTexs))
86  {
87  LogFatal("[!] Could not initialize landscape textures for rendering!");
88  return false;
89  }
90 
91  // Load sclaer
92  if (!LoadScaler(pGraphics))
93  {
94  LogFatal("[!] Could not load scaler!");
95  return false;
96  }
97 
98  // Load shader
99  if (!LoadShaders(pGraphics))
100  {
101  LogFatal("[!] Could not initialize landscape shader!");
102  return false;
103  }
104 
105  if (!InitVBO())
106  {
107  LogFatal("[!] Could not initialize landscape VBO!");
108  return false;
109  }
110 
111  return true;
112 }
C4TextureMap * pTexs
bool LogFatal(const char *szMessage)
Definition: C4Log.cpp:237

Here is the call graph for this function:

bool C4LandscapeRenderGL::ReInit ( int32_t  iWidth,
int32_t  iHeight 
)
overridevirtual

Implements C4LandscapeRender.

Definition at line 114 of file C4LandscapeRender.cpp.

References C4LandscapeRender::iHeight, C4LandscapeRender::iWidth, and LogFatal().

115 {
116  // Safe info
117  this->iWidth = iWidth;
118  this->iHeight = iHeight;
119 
120  // Clear old landscape textures
121  for (auto & Surface : Surfaces)
122  {
123  delete Surface;
124  Surface = nullptr;
125  }
126 
127  // Allocate new landscape textures
128  if (!InitLandscapeTexture())
129  {
130  LogFatal("[!] Could not initialize landscape texture!");
131  return false;
132  }
133  return true;
134 }
bool LogFatal(const char *szMessage)
Definition: C4Log.cpp:237

Here is the call graph for this function:

void C4LandscapeRenderGL::Update ( C4Rect  Rect,
C4Landscape pSource 
)
overridevirtual

Implements C4LandscapeRender.

Definition at line 356 of file C4LandscapeRender.cpp.

References C4Landscape::_GetPix(), C4Landscape::_GetPlacement(), C4LR_BiasDistanceX, C4LR_BiasDistanceY, C4LR_BiasX, C4LR_BiasY, C4LR_Material, C4LR_Place, C4LR_Scaler, C4LR_SurfaceCount, Clamp(), C4Rect::Hgt, C4LandscapeRender::iHeight, C4Rect::Intersect(), C4LandscapeRender::iWidth, RGBA(), C4Rect::Wdt, C4Rect::x, and C4Rect::y.

357 {
358  // clip to landscape size
359  To.Intersect(C4Rect(0,0,iWidth,iHeight));
360  // everything clipped?
361  if (To.Wdt<=0 || To.Hgt<=0) return;
362 
363  // Lock surfaces
364  // We clear the affected region here because ClearBoxDw allocates the
365  // main memory buffer for the box, so that only that box needs to be
366  // sent to the gpu, and not the whole texture, or every pixel
367  // separately. It's an important optimization.
368  for (auto & Surface : Surfaces)
369  {
370  if (!Surface->Lock()) return;
371  Surface->ClearBoxDw(To.x, To.y, To.Wdt, To.Hgt);
372  }
373 
374  // Initialize up & down placement arrays. These arrays are always updated
375  // so that they contain the placement sums of C4LR_BiasDistanceY pixels
376  // above and below the current row.
377  int x, y;
378  int placementSumsWidth = C4LR_BiasDistanceX * 2 + To.Wdt;
379  int *placementSumsUp = new int [placementSumsWidth * 2];
380  int *placementSumsDown = placementSumsUp + placementSumsWidth;
381  for(x = 0; x < placementSumsWidth; x++)
382  {
383  placementSumsUp[x] = 0;
384  placementSumsDown[x] = 0;
385  if (To.x + x - C4LR_BiasDistanceX < 0 || To.x + x - C4LR_BiasDistanceX >= iWidth) continue;
386  for(y = 1; y <= std::min(C4LR_BiasDistanceY, To.y); y++)
387  placementSumsUp[x] += pSource->_GetPlacement(To.x+x-C4LR_BiasDistanceX, To.y-y);
388  for(y = 1; y <= std::min(C4LR_BiasDistanceY, iHeight - 1 - To.y); y++)
389  placementSumsDown[x] += pSource->_GetPlacement(To.x+x-C4LR_BiasDistanceX, To.y+y);
390  }
391 
392  // Get tex refs (shortcut, we will use them quite heavily)
393  C4TexRef *texture[C4LR_SurfaceCount];
394  x = y = 0;
395  for(int i = 0; i < C4LR_SurfaceCount; i++)
396  texture[i] = Surfaces[i]->texture.get();
397 
398  // Go through it from top to bottom
399  for(y = 0; y < To.Hgt; y++)
400  {
401  // Initialize left & right placement sums. These are meant to contain
402  // the placement sum of a (C4LR_BiasDistanceX, 2*C4LR_BiasDistanceY+1)
403  // rectangle left/right of the current pixel. So we initialise it to
404  // be correct at x=0. Note that the placementSum arrays don't contain
405  // information about the current row, therefore we need a special case
406  // for those pixels.
407  int sumLeft = 0, sumRight = 0;
408  for(x = 1; x <= std::min(C4LR_BiasDistanceX, To.x); x++)
409  sumLeft += pSource->_GetPlacement(To.x-x,To.y+y);
410  for(x = 1; x <= std::min(C4LR_BiasDistanceX, iWidth - 1 - To.x ); x++)
411  sumRight += pSource->_GetPlacement(To.x+x,To.y+y);
412  for (int i = 1; i <= C4LR_BiasDistanceX; i++) {
413  sumLeft += placementSumsUp[C4LR_BiasDistanceX - i];
414  sumLeft += placementSumsDown[C4LR_BiasDistanceX - i];
415  sumRight += placementSumsUp[C4LR_BiasDistanceX + i];
416  sumRight += placementSumsDown[C4LR_BiasDistanceX + i];
417  }
418 
419  // Initialise up & down sums. Same principle as above, but slightly
420  // easier as we do not miss pixels if we just use the placement sums.
421  int sumUp = 0, sumDown = 0;
422  for (int i = -C4LR_BiasDistanceX; i <= C4LR_BiasDistanceX; i++) {
423  sumUp += placementSumsUp[C4LR_BiasDistanceX + i];
424  sumDown += placementSumsDown[C4LR_BiasDistanceX + i];
425  }
426 
427  for(x = 0; x < To.Wdt; x++)
428  {
429  int pixel = pSource->_GetPix(To.x+x, To.y+y);
430  int placement = pSource->_GetPlacement(To.x+x, To.y+y);
431 
432  // Calculate bias. The scale here is the size of the rectangle (see above)
433  const int horizontalFactor = C4LR_BiasDistanceX * (2 * C4LR_BiasDistanceY + 1);
434  int horizontalBias = std::max(0, placement * horizontalFactor - sumRight) -
435  std::max(0, placement * horizontalFactor - sumLeft);
436  const int verticalFactor = C4LR_BiasDistanceY * (2 * C4LR_BiasDistanceX + 1);
437  int verticalBias = std::max(0, placement * verticalFactor - sumDown) -
438  std::max(0, placement * verticalFactor - sumUp);
439 
440  // Maximum placement differences that make a difference in the result, after which we are at the limits of
441  // what can be packed into a byte
442  const int maximumPlacementDifference = 40;
443  int horizontalBiasScaled = Clamp(horizontalBias * 127 / maximumPlacementDifference / horizontalFactor + 128, 0, 255);
444  int verticalBiasScaled = Clamp(verticalBias * 127 / maximumPlacementDifference / verticalFactor + 128, 0, 255);
445 
446  // Collect data to save per pixel
447  unsigned char data[C4LR_SurfaceCount * 4];
448  memset(data, 0, sizeof(data));
449 
450  data[C4LR_Material] = pixel;
451  data[C4LR_BiasX] = horizontalBiasScaled;
452  data[C4LR_BiasY] = verticalBiasScaled;
453  data[C4LR_Scaler] = CalculateScalerBitmask(x, y, To, pSource);
454  data[C4LR_Place] = placement;
455 
456  for(int i = 0; i < C4LR_SurfaceCount; i++)
457  texture[i]->SetPix(To.x+x, To.y+y,
458  RGBA(data[i*4+0], data[i*4+1], data[i*4+2], data[i*4+3]));
459 
460  // Update sums (last column would be out-of-bounds, and not
461  // necessary as we will re-initialise it for the next row)
462  if (x < To.Wdt - 1) {
463  sumLeft -= placementSumsUp[x] + placementSumsDown[x];
464  sumLeft += placementSumsUp[x + C4LR_BiasDistanceX] + placementSumsDown[x + C4LR_BiasDistanceX];
465  sumRight -= placementSumsUp[x + C4LR_BiasDistanceX + 1] + placementSumsDown[x + C4LR_BiasDistanceX + 1];
466  sumUp -= placementSumsUp[x];
467  sumDown -= placementSumsDown[x];
468  sumRight += placementSumsUp[x + 2 * C4LR_BiasDistanceX + 1] + placementSumsDown[x + 2 * C4LR_BiasDistanceX + 1];
469  sumUp += placementSumsUp[x + 2 * C4LR_BiasDistanceX + 1];
470  sumDown += placementSumsDown[x + 2 * C4LR_BiasDistanceX + 1];
471  }
472 
473  // Update left & right for next pixel in line
474  if(x + To.x + 1 < iWidth)
475  sumRight -= pSource->_GetPlacement(To.x+x + 1, To.y+y);
476  if(To.x+x + C4LR_BiasDistanceX + 1 < iWidth)
477  sumRight += pSource->_GetPlacement(To.x+x + C4LR_BiasDistanceX + 1, To.y+y);
478  sumLeft += placement;
479  if(To.x+x - C4LR_BiasDistanceX >= 0)
480  sumLeft -= pSource->_GetPlacement(To.x+x - C4LR_BiasDistanceX, To.y+y);
481 
482  // Update up & down arrays (for next line already)
483  if (To.x + x >= C4LR_BiasDistanceX) {
484  if (To.y + y + 1 < iHeight)
485  placementSumsDown[x] -= pSource->_GetPlacement(To.x + x - C4LR_BiasDistanceX, To.y + y + 1);
486  if (To.y + y + C4LR_BiasDistanceY + 1 < iHeight)
487  placementSumsDown[x] += pSource->_GetPlacement(To.x + x - C4LR_BiasDistanceX, To.y + y + C4LR_BiasDistanceY + 1);
488  if (To.y + y - C4LR_BiasDistanceY >= 0)
489  placementSumsUp[x] -= pSource->_GetPlacement(To.x + x - C4LR_BiasDistanceX, To.y + y - C4LR_BiasDistanceY);
490  placementSumsUp[x] += pSource->_GetPlacement(To.x + x - C4LR_BiasDistanceX, To.y + y);
491  }
492  }
493 
494  // Finish updating up & down arrays for the next line
495  if (To.x + x >= C4LR_BiasDistanceX)
496  {
497  for (; x < std::min(placementSumsWidth, iWidth - To.x + C4LR_BiasDistanceX); x++) {
498  if (To.y + y + 1 < iHeight)
499  placementSumsDown[x] -= pSource->_GetPlacement(To.x + x - C4LR_BiasDistanceX, To.y + y + 1);
500  if (To.y + y + C4LR_BiasDistanceY + 1 < iHeight)
501  placementSumsDown[x] += pSource->_GetPlacement(To.x + x - C4LR_BiasDistanceX, To.y + y + C4LR_BiasDistanceY + 1);
502  if (To.y + y - C4LR_BiasDistanceY >= 0)
503  placementSumsUp[x] -= pSource->_GetPlacement(To.x + x - C4LR_BiasDistanceX, To.y + y - C4LR_BiasDistanceY);
504  placementSumsUp[x] += pSource->_GetPlacement(To.x + x - C4LR_BiasDistanceX, To.y + y);
505  }
506  }
507  }
508 
509  // done
510  delete[] placementSumsUp;
511  for (auto & Surface : Surfaces)
512  Surface->Unlock();
513 }
BYTE _GetPix(int32_t x, int32_t y) const
const int C4LR_SurfaceCount
const int C4LR_BiasDistanceX
const int C4LR_BiasDistanceY
Definition: C4Rect.h:27
T Clamp(T bval, T lbound, T rbound)
Definition: Standard.h:44
int32_t _GetPlacement(int32_t x, int32_t y) const
uint32_t RGBA(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
Definition: StdColors.h:22

Here is the call graph for this function:

Member Data Documentation

int32_t C4LandscapeRender::iHeight {0}
protectedinherited

Definition at line 91 of file C4LandscapeRender.h.

Referenced by Init(), ReInit(), and Update().

int32_t C4LandscapeRender::iWidth {0}
protectedinherited

Definition at line 91 of file C4LandscapeRender.h.

Referenced by Init(), ReInit(), and Update().

C4TextureMap* C4LandscapeRender::pTexs {nullptr}
protectedinherited

Definition at line 92 of file C4LandscapeRender.h.

Referenced by Init().


The documentation for this class was generated from the following files: