00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "video/gl/gl_lightmap.hpp"
00018
00019 #include <SDL_image.h>
00020 #include <algorithm>
00021 #include <assert.h>
00022 #include <functional>
00023 #include <iomanip>
00024 #include <iostream>
00025 #include <math.h>
00026 #include <physfs.h>
00027 #include <sstream>
00028
00029 #include "supertux/gameconfig.hpp"
00030 #include "supertux/globals.hpp"
00031 #include "util/obstackpp.hpp"
00032 #include "video/drawing_context.hpp"
00033 #include "video/drawing_request.hpp"
00034 #include "video/font.hpp"
00035 #include "video/gl/gl_surface_data.hpp"
00036 #include "video/gl/gl_renderer.hpp"
00037 #include "video/gl/gl_texture.hpp"
00038 #include "video/glutil.hpp"
00039 #include "video/lightmap.hpp"
00040 #include "video/renderer.hpp"
00041 #include "video/surface.hpp"
00042 #include "video/texture_manager.hpp"
00043
00044 GLLightmap::GLLightmap() :
00045 screen(),
00046 lightmap(),
00047 lightmap_width(),
00048 lightmap_height(),
00049 lightmap_uv_right(),
00050 lightmap_uv_bottom()
00051 {
00052 screen = SDL_GetVideoSurface();
00053
00054 lightmap_width = SCREEN_WIDTH / LIGHTMAP_DIV;
00055 lightmap_height = SCREEN_HEIGHT / LIGHTMAP_DIV;
00056 unsigned int width = next_po2(lightmap_width);
00057 unsigned int height = next_po2(lightmap_height);
00058
00059 lightmap.reset(new GLTexture(width, height));
00060
00061 lightmap_uv_right = static_cast<float>(lightmap_width) / static_cast<float>(width);
00062 lightmap_uv_bottom = static_cast<float>(lightmap_height) / static_cast<float>(height);
00063 texture_manager->register_texture(lightmap.get());
00064 }
00065
00066 GLLightmap::~GLLightmap()
00067 {
00068 }
00069
00070 void
00071 GLLightmap::start_draw(const Color &ambient_color)
00072 {
00073
00074 glGetFloatv(GL_VIEWPORT, old_viewport);
00075 glViewport(old_viewport[0], SCREEN_HEIGHT - lightmap_height + old_viewport[1], lightmap_width, lightmap_height);
00076 glMatrixMode(GL_PROJECTION);
00077 glLoadIdentity();
00078 #ifdef GL_VERSION_ES_CM_1_0
00079 glOrthof(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
00080 #else
00081 glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
00082 #endif
00083 glMatrixMode(GL_MODELVIEW);
00084 glLoadIdentity();
00085
00086 glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
00087 glClear(GL_COLOR_BUFFER_BIT);
00088 }
00089
00090 void
00091 GLLightmap::end_draw()
00092 {
00093 glDisable(GL_BLEND);
00094 glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
00095 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, old_viewport[0], SCREEN_HEIGHT - lightmap_height + old_viewport[1], lightmap_width, lightmap_height);
00096
00097 glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]);
00098 glMatrixMode(GL_PROJECTION);
00099 glLoadIdentity();
00100 #ifdef GL_VERSION_ES_CM_1_0
00101 glOrthof(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
00102 #else
00103 glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
00104 #endif
00105 glMatrixMode(GL_MODELVIEW);
00106 glLoadIdentity();
00107 glEnable(GL_BLEND);
00108
00109 }
00110
00111 void
00112 GLLightmap::do_draw()
00113 {
00114
00115 glBlendFunc(GL_DST_COLOR, GL_ZERO);
00116
00117 glBindTexture(GL_TEXTURE_2D, lightmap->get_handle());
00118
00119 float vertices[] = {
00120 0, 0,
00121 SCREEN_WIDTH, 0,
00122 SCREEN_WIDTH, SCREEN_HEIGHT,
00123 0, SCREEN_HEIGHT
00124 };
00125 glVertexPointer(2, GL_FLOAT, 0, vertices);
00126
00127 float uvs[] = {
00128 0, lightmap_uv_bottom,
00129 lightmap_uv_right, lightmap_uv_bottom,
00130 lightmap_uv_right, 0,
00131 0, 0
00132 };
00133 glTexCoordPointer(2, GL_FLOAT, 0, uvs);
00134
00135 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
00136
00137 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00138 }
00139
00140 void
00141 GLLightmap::draw_surface(const DrawingRequest& request)
00142 {
00143 const Surface* surface = (const Surface*) request.request_data;
00144 boost::shared_ptr<GLTexture> gltexture = boost::dynamic_pointer_cast<GLTexture>(surface->get_texture());
00145 GLSurfaceData *surface_data = reinterpret_cast<GLSurfaceData *>(surface->get_surface_data());
00146
00147 glBindTexture(GL_TEXTURE_2D, gltexture->get_handle());
00148 intern_draw(request.pos.x, request.pos.y,
00149 request.pos.x + surface->get_width(),
00150 request.pos.y + surface->get_height(),
00151 surface_data->get_uv_left(),
00152 surface_data->get_uv_top(),
00153 surface_data->get_uv_right(),
00154 surface_data->get_uv_bottom(),
00155 request.angle,
00156 request.alpha,
00157 request.color,
00158 request.blend,
00159 request.drawing_effect);
00160 }
00161
00162 void
00163 GLLightmap::draw_surface_part(const DrawingRequest& request)
00164 {
00165 const SurfacePartRequest* surfacepartrequest
00166 = (SurfacePartRequest*) request.request_data;
00167 const Surface* surface = surfacepartrequest->surface;
00168 boost::shared_ptr<GLTexture> gltexture = boost::dynamic_pointer_cast<GLTexture>(surface->get_texture());
00169 GLSurfaceData *surface_data = reinterpret_cast<GLSurfaceData *>(surface->get_surface_data());
00170
00171 float uv_width = surface_data->get_uv_right() - surface_data->get_uv_left();
00172 float uv_height = surface_data->get_uv_bottom() - surface_data->get_uv_top();
00173
00174 float uv_left = surface_data->get_uv_left() + (uv_width * surfacepartrequest->source.x) / surface->get_width();
00175 float uv_top = surface_data->get_uv_top() + (uv_height * surfacepartrequest->source.y) / surface->get_height();
00176 float uv_right = surface_data->get_uv_left() + (uv_width * (surfacepartrequest->source.x + surfacepartrequest->size.x)) / surface->get_width();
00177 float uv_bottom = surface_data->get_uv_top() + (uv_height * (surfacepartrequest->source.y + surfacepartrequest->size.y)) / surface->get_height();
00178
00179 glBindTexture(GL_TEXTURE_2D, gltexture->get_handle());
00180 intern_draw(request.pos.x, request.pos.y,
00181 request.pos.x + surfacepartrequest->size.x,
00182 request.pos.y + surfacepartrequest->size.y,
00183 uv_left,
00184 uv_top,
00185 uv_right,
00186 uv_bottom,
00187 0.0,
00188 request.alpha,
00189 Color(1.0, 1.0, 1.0),
00190 Blend(),
00191 request.drawing_effect);
00192 }
00193
00194 void
00195 GLLightmap::draw_gradient(const DrawingRequest& request)
00196 {
00197 const GradientRequest* gradientrequest
00198 = (GradientRequest*) request.request_data;
00199 const Color& top = gradientrequest->top;
00200 const Color& bottom = gradientrequest->bottom;
00201
00202 glDisable(GL_TEXTURE_2D);
00203 glDisable(GL_TEXTURE_COORD_ARRAY);
00204 glEnable(GL_COLOR_ARRAY);
00205
00206 float vertices[] = {
00207 0, 0,
00208 SCREEN_WIDTH, 0,
00209 SCREEN_WIDTH, SCREEN_HEIGHT,
00210 0, SCREEN_HEIGHT
00211 };
00212 glVertexPointer(2, GL_FLOAT, 0, vertices);
00213
00214 float colors[] = {
00215 top.red, top.green, top.blue, top.alpha,
00216 top.red, top.green, top.blue, top.alpha,
00217 bottom.red, bottom.green, bottom.blue, bottom.alpha,
00218 bottom.red, bottom.green, bottom.blue, bottom.alpha,
00219 };
00220 glColorPointer(4, GL_FLOAT, 0, colors);
00221
00222 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
00223
00224 glDisable(GL_COLOR_ARRAY);
00225 glEnable(GL_TEXTURE_COORD_ARRAY);
00226
00227 glEnable(GL_TEXTURE_2D);
00228 glColor4f(1, 1, 1, 1);
00229 }
00230
00231 void
00232 GLLightmap::draw_filled_rect(const DrawingRequest& request)
00233 {
00234 const FillRectRequest* fillrectrequest
00235 = (FillRectRequest*) request.request_data;
00236
00237 float x = request.pos.x;
00238 float y = request.pos.y;
00239 float w = fillrectrequest->size.x;
00240 float h = fillrectrequest->size.y;
00241
00242 glDisable(GL_TEXTURE_2D);
00243 glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
00244 fillrectrequest->color.blue, fillrectrequest->color.alpha);
00245 glDisable(GL_TEXTURE_COORD_ARRAY);
00246
00247 float vertices[] = {
00248 x, y,
00249 x+w, y,
00250 x+w, y+h,
00251 x, y+h
00252 };
00253 glVertexPointer(2, GL_FLOAT, 0, vertices);
00254
00255 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
00256
00257 glEnable(GL_TEXTURE_COORD_ARRAY);
00258 glEnable(GL_TEXTURE_2D);
00259 glColor4f(1, 1, 1, 1);
00260 }
00261
00262 void
00263 GLLightmap::get_light(const DrawingRequest& request) const
00264 {
00265 const GetLightRequest* getlightrequest
00266 = (GetLightRequest*) request.request_data;
00267
00268 float pixels[3];
00269 for( int i = 0; i<3; i++)
00270 pixels[i] = 0.0f;
00271
00272 float posX = request.pos.x * lightmap_width / SCREEN_WIDTH + old_viewport[0];
00273 float posY = SCREEN_HEIGHT + old_viewport[1] - request.pos.y * lightmap_height / SCREEN_HEIGHT;
00274 glReadPixels((GLint) posX, (GLint) posY , 1, 1, GL_RGB, GL_FLOAT, pixels);
00275 *(getlightrequest->color_ptr) = Color( pixels[0], pixels[1], pixels[2]);
00276 }
00277
00278