From: Ingo Ruhnke Date: Thu, 31 Jul 2014 01:02:19 +0000 (+0200) Subject: Implemented basic lightmap rendering, still a bit of an incomplete hack job, drawing... X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=417c6a1cac6d6d8a3c5831662e5189e8415218a3;p=supertux.git Implemented basic lightmap rendering, still a bit of an incomplete hack job, drawing code should be merged with SDLRenderer --- diff --git a/src/video/sdl/sdl_lightmap.cpp b/src/video/sdl/sdl_lightmap.cpp index bb1284bcb..09a8343b7 100644 --- a/src/video/sdl/sdl_lightmap.cpp +++ b/src/video/sdl/sdl_lightmap.cpp @@ -19,588 +19,143 @@ #include "video/sdl/sdl_lightmap.hpp" #include "video/sdl/sdl_surface_data.hpp" #include "video/sdl/sdl_texture.hpp" +#include "video/sdl/sdl_renderer.hpp" SDLLightmap::SDLLightmap() : - red_channel(), - blue_channel(), - green_channel(), + renderer(static_cast(Renderer::instance())->get_sdl_renderer()), width(), height(), - numerator(), - denominator(), LIGHTMAP_DIV() { - //float xfactor = 1.0f; // FIXME: (float) config->screenwidth / SCREEN_WIDTH; - //float yfactor = 1.0f; // FIXME: (float) config->screenheight / SCREEN_HEIGHT; + LIGHTMAP_DIV = 8; - numerator = 1; - denominator = 1; + width = 800; //screen->w / LIGHTMAP_DIV; + height = 600; //screen->h / LIGHTMAP_DIV; - /* FIXME: - if(xfactor < yfactor) - { - numerator = config->screenwidth; - denominator = SCREEN_WIDTH; - } - else - { - numerator = config->screenheight; - denominator = SCREEN_HEIGHT; - } - */ - -#ifdef OLD_SDL1 - LIGHTMAP_DIV = 8 * numerator / denominator; - - width = screen->w / LIGHTMAP_DIV; - height = screen->h / LIGHTMAP_DIV; - - red_channel = (Uint8 *)malloc(width * height * sizeof(Uint8)); - green_channel = (Uint8 *)malloc(width * height * sizeof(Uint8)); - blue_channel = (Uint8 *)malloc(width * height * sizeof(Uint8)); -#endif + SDL_Renderer* renderer = static_cast(Renderer::instance())->get_sdl_renderer(); + texture = SDL_CreateTexture(renderer, + SDL_PIXELFORMAT_RGB888, + SDL_TEXTUREACCESS_TARGET, + width, height); + if (!texture) + { + std::stringstream msg; + msg << "Couldn't create lightmap texture: " << SDL_GetError(); + throw std::runtime_error(msg.str()); + } } SDLLightmap::~SDLLightmap() { - free(red_channel); - free(green_channel); - free(blue_channel); + SDL_DestroyTexture(texture); } void SDLLightmap::start_draw(const Color &ambient_color) { - memset(red_channel, (Uint8) (ambient_color.red * 255), width * height * sizeof(Uint8)); - memset(green_channel, (Uint8) (ambient_color.green * 255), width * height * sizeof(Uint8)); - memset(blue_channel, (Uint8) (ambient_color.blue * 255), width * height * sizeof(Uint8)); + SDL_SetRenderTarget(renderer, texture); + + Uint8 r = static_cast(ambient_color.red * 255); + Uint8 g = static_cast(ambient_color.green * 255); + Uint8 b = static_cast(ambient_color.blue * 255); + + SDL_SetRenderDrawColor(renderer, r, g, b, 255); + SDL_RenderClear(renderer); } void SDLLightmap::end_draw() { + SDL_SetRenderTarget(renderer, NULL); } -//#define BILINEAR - -#ifdef BILINEAR -namespace { - -void merge(Uint8 color[3], Uint8 color0[3], Uint8 color1[3], int rem, int total) -{ - color[0] = (color0[0] * (total - rem) + color1[0] * rem) / total; - color[1] = (color0[1] * (total - rem) + color1[1] * rem) / total; - color[2] = (color0[2] * (total - rem) + color1[2] * rem) / total; -} - -} // namespace -#endif - void SDLLightmap::do_draw() { -#ifdef OLD_SDL1 - // FIXME: This is really slow - if(LIGHTMAP_DIV == 1) - { - int bpp = screen->format->BytesPerPixel; - if(SDL_MUSTLOCK(screen)) - { - SDL_LockSurface(screen); - } - Uint8 *pixel = (Uint8 *) screen->pixels; - int loc = 0; - for(int y = 0;y < height;y++) { - for(int x = 0;x < width;x++, pixel += bpp, loc++) { - if(red_channel[loc] == 0xff && green_channel[loc] == 0xff && blue_channel[loc] == 0xff) - { - continue; - } - Uint32 mapped = 0; - switch(bpp) { - case 1: - mapped = *pixel; - break; - case 2: - mapped = *(Uint16 *)pixel; - break; - case 3: -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - mapped |= pixel[0] << 16; - mapped |= pixel[1] << 8; - mapped |= pixel[2] << 0; -#else - mapped |= pixel[0] << 0; - mapped |= pixel[1] << 8; - mapped |= pixel[2] << 16; -#endif - break; - case 4: - mapped = *(Uint32 *)pixel; - break; - } - Uint8 red, green, blue, alpha; - SDL_GetRGBA(mapped, screen->format, &red, &green, &blue, &alpha); - red = (red * red_channel[loc]) >> 8; - green = (green * green_channel[loc]) >> 8; - blue = (blue * blue_channel[loc]) >> 8; - mapped = SDL_MapRGBA(screen->format, red, green, blue, alpha); - switch(bpp) { - case 1: - *pixel = mapped; - break; - case 2: - *(Uint16 *)pixel = mapped; - break; - case 3: -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - pixel[0] = (mapped >> 16) & 0xff; - pixel[1] = (mapped >> 8) & 0xff; - pixel[2] = (mapped >> 0) & 0xff; -#else - pixel[0] = (mapped >> 0) & 0xff; - pixel[1] = (mapped >> 8) & 0xff; - pixel[2] = (mapped >> 16) & 0xff; -#endif - break; - case 4: - *(Uint32 *)pixel = mapped; - break; - } - } - pixel += screen->pitch - width * bpp; - } - if(SDL_MUSTLOCK(screen)) - { - SDL_UnlockSurface(screen); - } - } - else - { - int bpp = screen->format->BytesPerPixel; - if(SDL_MUSTLOCK(screen)) - { - SDL_LockSurface(screen); - } - Uint8 *div_pixel = (Uint8 *) screen->pixels; - int loc = 0; - for(int y = 0;y < height;y++) { - for(int x = 0;x < width;x++, div_pixel += bpp * LIGHTMAP_DIV, loc++) { - if(red_channel[loc] == 0xff && green_channel[loc] == 0xff && blue_channel[loc] == 0xff) - { - continue; - } - Uint8 *pixel = div_pixel; - for(int div_y = 0;div_y < LIGHTMAP_DIV;div_y++) { - for(int div_x = 0;div_x < LIGHTMAP_DIV;pixel += bpp, div_x++) { - Uint32 mapped = 0; - switch(bpp) { - case 1: - mapped = *pixel; - break; - case 2: - mapped = *(Uint16 *)pixel; - break; - case 3: -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - mapped |= pixel[0] << 16; - mapped |= pixel[1] << 8; - mapped |= pixel[2] << 0; -#else - mapped |= pixel[0] << 0; - mapped |= pixel[1] << 8; - mapped |= pixel[2] << 16; -#endif - break; - case 4: - mapped = *(Uint32 *)pixel; - break; - } - Uint8 red, green, blue, alpha; - SDL_GetRGBA(mapped, screen->format, &red, &green, &blue, &alpha); + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_MOD); -#ifdef BILINEAR - int xinc = (x + 1 != width ? 1 : 0); - int yinc = (y + 1 != height ? width : 0); - Uint8 color00[3], color01[3], color10[3], color11[3]; - { - color00[0] = red_channel[loc]; - color00[1] = green_channel[loc]; - color00[2] = blue_channel[loc]; - } - { - color01[0] = red_channel[loc + xinc]; - color01[1] = green_channel[loc + xinc]; - color01[2] = blue_channel[loc + xinc]; - } - { - color10[0] = red_channel[loc + yinc]; - color10[1] = green_channel[loc + yinc]; - color10[2] = blue_channel[loc + yinc]; - } - { - color11[0] = red_channel[loc + yinc + xinc]; - color11[1] = green_channel[loc + yinc + xinc]; - color11[2] = blue_channel[loc + yinc + xinc]; - } - Uint8 color0[3], color1[3], color[3]; - merge(color0, color00, color01, div_x, LIGHTMAP_DIV); - merge(color1, color10, color11, div_x, LIGHTMAP_DIV); - merge(color, color0, color1, div_y, LIGHTMAP_DIV); - red = (red * color[0]) >> 8; - green = (green * color[1]) >> 8; - blue = (blue * color[2]) >> 8; -#else - red = (red * red_channel[loc]) >> 8; - green = (green * green_channel[loc]) >> 8; - blue = (blue * blue_channel[loc]) >> 8; -#endif + SDL_Rect dst_rect; + dst_rect.x = 0; + dst_rect.y = 0; + dst_rect.w = width; + dst_rect.h = height; - mapped = SDL_MapRGBA(screen->format, red, green, blue, alpha); - switch(bpp) { - case 1: - *pixel = mapped; - break; - case 2: - *(Uint16 *)pixel = mapped; - break; - case 3: -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - pixel[0] = (mapped >> 16) & 0xff; - pixel[1] = (mapped >> 8) & 0xff; - pixel[2] = (mapped >> 0) & 0xff; -#else - pixel[0] = (mapped >> 0) & 0xff; - pixel[1] = (mapped >> 8) & 0xff; - pixel[2] = (mapped >> 16) & 0xff; -#endif - break; - case 4: - *(Uint32 *)pixel = mapped; - break; - } - } - pixel += screen->pitch - LIGHTMAP_DIV * bpp; - } - } - div_pixel += (screen->pitch - width * bpp) * LIGHTMAP_DIV; - } - if(SDL_MUSTLOCK(screen)) - { - SDL_UnlockSurface(screen); - } - } -#endif -} - -void -SDLLightmap::light_blit(SDL_Surface *src, SDL_Rect *src_rect, int dstx, int dsty) -{ - dstx /= LIGHTMAP_DIV; - dsty /= LIGHTMAP_DIV; - int srcx = src_rect->x / LIGHTMAP_DIV; - int srcy = src_rect->y / LIGHTMAP_DIV; - int blit_width = src_rect->w / LIGHTMAP_DIV; - int blit_height = src_rect->h / LIGHTMAP_DIV; - int bpp = src->format->BytesPerPixel; - if(SDL_MUSTLOCK(src)) - { - SDL_LockSurface(src); - } - Uint8 *pixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp; - int loc = dsty * width + dstx; - for(int y = 0;y < blit_height;y++) { - for(int x = 0;x < blit_width;x++, pixel += bpp * LIGHTMAP_DIV, loc++) { - if(x + dstx < 0 || y + dsty < 0 || x + dstx >= width || y + dsty >= height) - { - continue; - } - if(red_channel[loc] == 0xff && green_channel[loc] == 0xff && blue_channel[loc] == 0xff) - { - continue; - } - - Uint32 mapped = 0; - switch(bpp) { - case 1: - mapped = *pixel; - break; - case 2: - mapped = *(Uint16 *)pixel; - break; - case 3: -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - mapped |= pixel[0] << 16; - mapped |= pixel[1] << 8; - mapped |= pixel[2] << 0; -#else - mapped |= pixel[0] << 0; - mapped |= pixel[1] << 8; - mapped |= pixel[2] << 16; -#endif - break; - case 4: - mapped = *(Uint32 *)pixel; - break; - } - Uint8 red, green, blue, alpha; - SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); - - if(red != 0) - { - int redsum = red_channel[loc] + (red * alpha >> 8); - red_channel[loc] = redsum & ~0xff ? 0xff : redsum; - } - if(green != 0) - { - int greensum = green_channel[loc] + (green * alpha >> 8); - green_channel[loc] = greensum & ~0xff ? 0xff : greensum; - } - if(blue != 0) - { - int bluesum = blue_channel[loc] + (blue * alpha >> 8); - blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum; - } - } - pixel += (src->pitch - blit_width * bpp) * LIGHTMAP_DIV; - loc += width - blit_width; - } - if(SDL_MUSTLOCK(src)) - { - SDL_UnlockSurface(src); - } + SDL_RenderCopy(renderer, texture, NULL, &dst_rect); } -/*void Lightmap::light_blit(SDL_Surface *src, SDL_Rect *src_rect, int dstx, int dsty) - { - int bpp = src->format->BytesPerPixel; - if(SDL_MUSTLOCK(src)) - { - SDL_LockSurface(src); - } - Uint8 *pixel = (Uint8 *) src->pixels + src_rect->y * src->pitch + src_rect->x * bpp; - int loc = dsty * width + dstx; - for(int y = 0;y < src_rect->h;y++) { - for(int x = 0;x < src_rect->w;x++, pixel += bpp, loc++) { - if(x + dstx < 0 || y + dsty < 0 || x + dstx >= width || y + dsty >= height) - { - continue; - } - if(red_channel[loc] == 0xff && green_channel[loc] == 0xff && blue_channel[loc] == 0xff) - { - continue; - } - - Uint32 mapped = 0; - switch(bpp) { - case 1: - mapped = *pixel; - break; - case 2: - mapped = *(Uint16 *)pixel; - break; - case 3: - #if SDL_BYTEORDER == SDL_BIG_ENDIAN - mapped |= pixel[0] << 16; - mapped |= pixel[1] << 8; - mapped |= pixel[2] << 0; - #else - mapped |= pixel[0] << 0; - mapped |= pixel[1] << 8; - mapped |= pixel[2] << 16; - #endif - break; - case 4: - mapped = *(Uint32 *)pixel; - break; - } - Uint8 red, green, blue, alpha; - SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); - - if(red != 0) - { - int redsum = red_channel[loc] + (red * alpha >> 8); - red_channel[loc] = redsum & ~0xff ? 0xff : redsum; - } - if(green != 0) - { - int greensum = green_channel[loc] + (green * alpha >> 8); - green_channel[loc] = greensum & ~0xff ? 0xff : greensum; - } - if(blue != 0) - { - int bluesum = blue_channel[loc] + (blue * alpha >> 8); - blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum; - } - } - pixel += src->pitch - src_rect->w * bpp; - loc += width - src_rect->w; - } - if(SDL_MUSTLOCK(src)) - { - SDL_UnlockSurface(src); - } - }*/ - void SDLLightmap::draw_surface(const DrawingRequest& request) { -#ifdef OLD_SDL1 - if((request.color.red == 0.0 && request.color.green == 0.0 && request.color.blue == 0.0) || request.color.alpha == 0.0 || request.alpha == 0.0) - { - return; - } //FIXME: support parameters request.alpha, request.angle, request.blend - const Surface* surface = (const Surface*) request.request_data; boost::shared_ptr sdltexture = boost::dynamic_pointer_cast(surface->get_texture()); - SDLSurfaceData *surface_data = reinterpret_cast(surface->get_surface_data()); - - DrawingEffect effect = request.drawing_effect; - if (surface->get_flipx()) effect = HORIZONTAL_FLIP; - SDL_Surface *transform = sdltexture->get_transform(request.color, effect); + SDL_Rect dst_rect; + dst_rect.x = request.pos.x; + dst_rect.y = request.pos.y; + dst_rect.w = sdltexture->get_image_width(); + dst_rect.h = sdltexture->get_image_height(); - // get and check SDL_Surface - if (transform == 0) { - std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl; - return; - } - - SDL_Rect *src_rect = surface_data->get_src_rect(effect); - int dstx = (int) request.pos.x * numerator / denominator; - int dsty = (int) request.pos.y * numerator / denominator; - light_blit(transform, src_rect, dstx, dsty); -#endif + SDL_SetTextureBlendMode(sdltexture->get_texture(), SDL_BLENDMODE_ADD); + SDL_RenderCopy(renderer, sdltexture->get_texture(), NULL, &dst_rect); } void SDLLightmap::draw_surface_part(const DrawingRequest& request) { -#ifdef OLD_SDL1 - const SurfacePartRequest* surfacepartrequest - = (SurfacePartRequest*) request.request_data; - - const Surface* surface = surfacepartrequest->surface; + //FIXME: support parameters request.alpha, request.angle, request.blend + const Surface* surface = (const Surface*) request.request_data; boost::shared_ptr sdltexture = boost::dynamic_pointer_cast(surface->get_texture()); - DrawingEffect effect = request.drawing_effect; - if (surface->get_flipx()) effect = HORIZONTAL_FLIP; + SDL_Rect dst_rect; + dst_rect.x = request.pos.x; + dst_rect.y = request.pos.y; + dst_rect.w = sdltexture->get_image_width(); + dst_rect.h = sdltexture->get_image_height(); - SDL_Surface *transform = sdltexture->get_transform(Color(1.0, 1.0, 1.0), effect); - - // get and check SDL_Surface - if (transform == 0) { - std::cerr << "Warning: Tried to draw NULL surface, skipped draw" << std::endl; - return; - } - - int ox, oy; - if (effect == HORIZONTAL_FLIP) - { - ox = sdltexture->get_texture_width() - surface->get_x() - (int) surfacepartrequest->size.x; - } - else - { - ox = surface->get_x(); - } - if (effect == VERTICAL_FLIP) - { - oy = sdltexture->get_texture_height() - surface->get_y() - (int) surfacepartrequest->size.y; - } - else - { - oy = surface->get_y(); - } - - SDL_Rect src_rect; - src_rect.x = (ox + (int) surfacepartrequest->source.x) * numerator / denominator; - src_rect.y = (oy + (int) surfacepartrequest->source.y) * numerator / denominator; - src_rect.w = (int) surfacepartrequest->size.x * numerator / denominator; - src_rect.h = (int) surfacepartrequest->size.y * numerator / denominator; - int dstx = (int) request.pos.x * numerator / denominator; - int dsty = (int) request.pos.y * numerator / denominator; - light_blit(transform, &src_rect, dstx, dsty); -#endif + SDL_SetTextureBlendMode(sdltexture->get_texture(), SDL_BLENDMODE_ADD); + SDL_RenderCopy(renderer, sdltexture->get_texture(), NULL, &dst_rect); } void SDLLightmap::draw_gradient(const DrawingRequest& request) { - const GradientRequest* gradientrequest - = (GradientRequest*) request.request_data; - const Color& top = gradientrequest->top; - const Color& bottom = gradientrequest->bottom; - - int loc = 0; - for(int y = 0;y < height;++y) - { - Uint8 red = (Uint8)((((float)(top.red-bottom.red)/(0-height)) * y + top.red) * 255); - Uint8 green = (Uint8)((((float)(top.green-bottom.green)/(0-height)) * y + top.green) * 255); - Uint8 blue = (Uint8)((((float)(top.blue-bottom.blue)/(0-height)) * y + top.blue) * 255); - Uint8 alpha = (Uint8)((((float)(top.alpha-bottom.alpha)/(0-height)) * y + top.alpha) * 255); - for(int x = 0;x < width;x++, loc++) { - if(red != 0) - { - int redsum = red_channel[loc] + (red * alpha >> 8); - red_channel[loc] = redsum & ~0xff ? 0xff : redsum; - } - if(green != 0) - { - int greensum = green_channel[loc] + (green * alpha >> 8); - green_channel[loc] = greensum & ~0xff ? 0xff : greensum; - } - if(blue != 0) - { - int bluesum = blue_channel[loc] + (blue * alpha >> 8); - blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum; - } - } - } + log_info << "draw_gradient" << std::endl; } void SDLLightmap::draw_filled_rect(const DrawingRequest& request) { + log_info << "draw_filled_rect" << std::endl; + const FillRectRequest* fillrectrequest = (FillRectRequest*) request.request_data; - int rect_x = (int) (request.pos.x * width / SCREEN_WIDTH); - int rect_y = (int) (request.pos.y * height / SCREEN_HEIGHT); - int rect_w = (int) (fillrectrequest->size.x * width / SCREEN_WIDTH); - int rect_h = (int) (fillrectrequest->size.y * height / SCREEN_HEIGHT); - Uint8 red = (Uint8) (fillrectrequest->color.red * fillrectrequest->color.alpha * 255); - Uint8 green = (Uint8) (fillrectrequest->color.green * fillrectrequest->color.alpha * 255); - Uint8 blue = (Uint8) (fillrectrequest->color.blue * fillrectrequest->color.alpha * 255); - if(red == 0 && green == 0 && blue == 0) + SDL_Rect rect; + rect.x = request.pos.x; + rect.y = request.pos.y; + rect.w = fillrectrequest->size.x; + rect.h = fillrectrequest->size.y; + + Uint8 r = static_cast(fillrectrequest->color.red * 255); + Uint8 g = static_cast(fillrectrequest->color.green * 255); + Uint8 b = static_cast(fillrectrequest->color.blue * 255); + Uint8 a = static_cast(fillrectrequest->color.alpha * 255); + + log_info << fillrectrequest->color.red << " " << fillrectrequest->color.green << std::endl; + + if((rect.w != 0) && (rect.h != 0)) { - return; - } - for(int y = rect_y;y < rect_y + rect_h;y++) { - for(int x = rect_x;x < rect_x + rect_w;x++) { - int loc = y * width + x; - if(red != 0) - { - int redsum = red_channel[loc] + red; - red_channel[loc] = redsum & ~0xff ? 0xff : redsum; - } - if(green != 0) - { - int greensum = green_channel[loc] + green; - green_channel[loc] = greensum & ~0xff ? 0xff : greensum; - } - if(blue != 0) - { - int bluesum = blue_channel[loc] + blue; - blue_channel[loc] = bluesum & ~0xff ? 0xff : bluesum; - } - } + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_ADD); + SDL_SetRenderDrawColor(renderer, r, g, b, a); + SDL_RenderFillRect(renderer, &rect); } } void SDLLightmap::get_light(const DrawingRequest& request) const { +#if OLD_SDL1 const GetLightRequest* getlightrequest = (GetLightRequest*) request.request_data; @@ -608,6 +163,7 @@ SDLLightmap::get_light(const DrawingRequest& request) const int y = (int) (request.pos.y * height / SCREEN_HEIGHT); int loc = y * width + x; *(getlightrequest->color_ptr) = Color(((float)red_channel[loc])/255, ((float)green_channel[loc])/255, ((float)blue_channel[loc])/255); +#endif } /* EOF */ diff --git a/src/video/sdl/sdl_lightmap.hpp b/src/video/sdl/sdl_lightmap.hpp index 7dd1d56d4..df451be4a 100644 --- a/src/video/sdl/sdl_lightmap.hpp +++ b/src/video/sdl/sdl_lightmap.hpp @@ -19,6 +19,8 @@ #include "video/lightmap.hpp" +#include "SDL.h" + class Color; struct DrawingRequest; @@ -31,24 +33,21 @@ public: void start_draw(const Color &ambient_color); void end_draw(); void do_draw(); + void draw_surface(const DrawingRequest& request); void draw_surface_part(const DrawingRequest& request); void draw_gradient(const DrawingRequest& request); void draw_filled_rect(const DrawingRequest& request); + void get_light(const DrawingRequest& request) const; private: - Uint8 *red_channel; - Uint8 *blue_channel; - Uint8 *green_channel; + SDL_Renderer* renderer; + SDL_Texture* texture; int width; int height; - int numerator; - int denominator; int LIGHTMAP_DIV; - void light_blit(SDL_Surface *src, SDL_Rect *src_rect, int dstx, int dsty); - private: SDLLightmap(const SDLLightmap&); SDLLightmap& operator=(const SDLLightmap&);