////////////////////////////////////////////////////////////////////// // This file is part of Remere's Map Editor ////////////////////////////////////////////////////////////////////// // Remere's Map Editor is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Remere's Map Editor is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . ////////////////////////////////////////////////////////////////////// #include "main.h" #include "light_drawer.h" #include "gl_renderer.h" #include "gl_compat.h" LightDrawer::LightDrawer() { texture = 0; buffer.resize(static_cast(rme::ClientMapWidth * rme::ClientMapHeight * rme::PixelFormatRGBA)); global_color = wxColor(50, 50, 50, 255); } LightDrawer::~LightDrawer() { unloadGLTexture(); lights.clear(); } void LightDrawer::draw(int map_x, int map_y, int end_x, int end_y, int scroll_x, int scroll_y, GLRenderer* renderer) { if (texture == 0) { createGLTexture(); } int w = end_x - map_x; int h = end_y - map_y; buffer.resize(static_cast(w * h * rme::PixelFormatRGBA)); for (int x = 0; x < w; ++x) { for (int y = 0; y < h; ++y) { int mx = (map_x + x); int my = (map_y + y); int index = (y * w + x); int color_index = index * rme::PixelFormatRGBA; buffer[color_index] = global_color.Red(); buffer[color_index + 1] = global_color.Green(); buffer[color_index + 2] = global_color.Blue(); buffer[color_index + 3] = global_color.Alpha(); for (auto &light : lights) { float intensity = calculateIntensity(mx, my, light); if (intensity == 0.f) { continue; } wxColor light_color = colorFromEightBit(light.color); uint8_t red = static_cast(light_color.Red() * intensity); uint8_t green = static_cast(light_color.Green() * intensity); uint8_t blue = static_cast(light_color.Blue() * intensity); buffer[color_index] = std::max(buffer[color_index], red); buffer[color_index + 1] = std::max(buffer[color_index + 1], green); buffer[color_index + 2] = std::max(buffer[color_index + 2], blue); } } } const int draw_x = map_x * rme::TileSize - scroll_x; const int draw_y = map_y * rme::TileSize - scroll_y; int draw_width = w * rme::TileSize; int draw_height = h * rme::TileSize; glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data()); renderer->flush(); renderer->setBlendMode(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); renderer->drawTexturedQuad(static_cast(draw_x), static_cast(draw_y), static_cast(draw_width), static_cast(draw_height), texture, { 255, 255, 255, 255 }); renderer->flush(); renderer->resetBlendMode(); } void LightDrawer::setGlobalLightColor(uint8_t color) { global_color = colorFromEightBit(color); } void LightDrawer::addLight(int map_x, int map_y, int map_z, const SpriteLight &light) { if (map_z <= rme::MapGroundLayer) { map_x -= (rme::MapGroundLayer - map_z); map_y -= (rme::MapGroundLayer - map_z); } if (map_x <= 0 || map_x >= rme::MapMaxWidth || map_y <= 0 || map_y >= rme::MapMaxHeight) { return; } uint8_t intensity = std::min(light.intensity, static_cast(rme::MaxLightIntensity)); if (!lights.empty()) { Light &previous = lights.back(); if (previous.map_x == map_x && previous.map_y == map_y && previous.color == light.color) { previous.intensity = std::max(previous.intensity, intensity); return; } } lights.push_back(Light { static_cast(map_x), static_cast(map_y), light.color, intensity }); } void LightDrawer::clear() noexcept { lights.clear(); } void LightDrawer::createGLTexture() { glGenTextures(1, &texture); } void LightDrawer::unloadGLTexture() { if (texture != 0) { GLRenderer::invalidateTexture(texture); glDeleteTextures(1, &texture); } }