25 template<
typename LightMap>
26 double AmbientForPix(
int x0,
int y0,
double R,
const LightMap& light_map)
30 const int Ri =
static_cast<int>(R);
31 for(
int y = 1; y <= Ri; ++y)
34 int max_x =
static_cast<int>(sqrt(R * R - y * y));
35 for(
int x = 1; x <= max_x; ++x)
37 const double l = sqrt(x*x + y*y);
40 if(light_map(x0 + x, y0 + y)) d += 1. / l;
41 if(light_map(x0 + x, y0 - y)) d += 1. / l;
42 if(light_map(x0 - x, y0 - y)) d += 1. / l;
43 if(light_map(x0 - x, y0 + y)) d += 1. / l;
47 const double l =
static_cast<double>(y);
48 if(light_map(x0 + y, y0)) d += 1. / l;
49 if(light_map(x0 - y, y0)) d += 1. / l;
50 if(light_map(x0, y0 + y)) d += 1. / l;
51 if(light_map(x0, y0 - y)) d += 1. / l;
55 if(light_map(x0, y0)) d += 2 * sqrt(M_PI);
63 LightMapFull() =
default;
64 bool operator()(
int x,
int y)
const {
return true; }
68 LightMapZoom(
const C4Landscape& landscape,
double sx,
double sy):
72 bool operator()(
int x,
int y)
const
98 if(
Tex != 0) glDeleteTextures(1, &
Tex);
101 Resolution = Radius = FullCoverage = 0.;
103 LandscapeX = LandscapeY = 0;
109 assert(resolution >= 1.);
110 assert(radius >= 1.);
111 assert(full_coverage > 0 && full_coverage <= 1.);
116 Resolution = resolution;
118 FullCoverage = full_coverage;
123 SizeX = std::min<unsigned int>(
static_cast<unsigned int>(ceil(LandscapeX / resolution)),
pDraw->
MaxTexSize);
124 SizeY = std::min<unsigned int>(
static_cast<unsigned int>(ceil(LandscapeY / resolution)),
pDraw->
MaxTexSize);
127 glGenTextures(1, &
Tex);
128 glBindTexture(GL_TEXTURE_2D,
Tex);
129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
132 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
133 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, SizeX, SizeY, 0, GL_RED, GL_FLOAT,
nullptr);
138 LogF(
"Created %ux%u ambient map in %g secs", SizeX, SizeY, dt / 1000.);
146 if(update.
Wdt == 0 || update.
Hgt == 0)
return;
154 const unsigned int left = std::max(
static_cast<int>( (update.
x - Radius) / zoom_x), 0);
155 const unsigned int right = std::min(
static_cast<unsigned int>( (update.
x + update.
Wdt + Radius) / zoom_x), SizeX - 1) + 1;
156 const unsigned int top = std::max(
static_cast<int>( (update.
y - Radius) / zoom_y), 0);
157 const unsigned int bottom = std::min(
static_cast<unsigned int>( (update.
y + update.
Hgt + Radius) / zoom_y), SizeY - 1) + 1;
161 const double R = Radius / sqrt(zoom_x * zoom_y);
164 const double norm = AmbientForPix(0, 0, R, LightMapFull()) * FullCoverage;
166 LightMapZoom light_mapZoom(landscape, zoom_x, zoom_y);
168 for(
unsigned int y =
top; y <
bottom; ++y)
170 for(
unsigned int x =
left; x <
right; ++x)
172 ambient[(y -
top) * (
right -
left) + (x -
left)] = std::min(AmbientForPix(x, y, R, light_mapZoom) / norm, 1.0);
178 for(
unsigned int y = 0; y < SizeY; ++y)
180 for(
unsigned int x = 0; x < SizeX; ++x)
182 debug.
SetPix(x, y,
int(ambient[y * SizeX + x] * 255. + 0.5));
187 for(
int i = 0; i < 256; ++i)
188 pal.
Colors[i] = i + (i << 8) + (i << 16);
189 debug.
Save(
"Ambient.bmp", &pal);
193 glBindTexture(GL_TEXTURE_2D,
Tex);
208 trans.
Scale(1.0f / clipRect.
Wdt, 1.0f / clipRect.
Hgt);
214 trans.
Scale(1.0f / LandscapeX, 1.0f / LandscapeY);
217 trans.
Get2x3(ambientTransform);
bool LogF(const char *strMessage,...)
T Clamp(T bval, T lbound, T rbound)
void UpdateFromLandscape(const C4Landscape &landscape, const C4Rect &update)
void GetFragTransform(const struct FLOAT_RECT &vpRect, const C4Rect &clipRect, const C4Rect &outRect, float ambientTransform[6]) const
void CreateFromLandscape(const C4Landscape &landscape, double resolution, double radius, double full_coverage)
int32_t GetHeight() const
bool _GetLight(int32_t x, int32_t y)
static C4TimeMilliseconds Now()
bool Save(const char *szFilename, CStdPalette *=nullptr)
void SetPix(int iX, int iY, BYTE byCol)