b5251e07657a81863ed44d137bec68157d769f93
[supertux.git] / src / video / gl / gl_lightmap.cpp
1 //  SuperTux
2 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 #include "video/gl/gl_lightmap.hpp"
18
19 #include <SDL_image.h>
20 #include <algorithm>
21 #include <assert.h>
22 #include <functional>
23 #include <iomanip>
24 #include <iostream>
25 #include <math.h>
26 #include <physfs.h>
27 #include <sstream>
28
29 #include "supertux/gameconfig.hpp"
30 #include "supertux/globals.hpp"
31 #include "util/obstackpp.hpp"
32 #include "video/drawing_context.hpp"
33 #include "video/drawing_request.hpp"
34 #include "video/font.hpp"
35 #include "video/gl/gl_painter.hpp"
36 #include "video/gl/gl_renderer.hpp"
37 #include "video/gl/gl_surface_data.hpp"
38 #include "video/gl/gl_texture.hpp"
39 #include "video/glutil.hpp"
40 #include "video/lightmap.hpp"
41 #include "video/renderer.hpp"
42 #include "video/surface.hpp"
43 #include "video/texture_manager.hpp"
44
45 inline int next_po2(int val)
46 {
47   int result = 1;
48   while(result < val)
49     result *= 2;
50
51   return result;
52 }
53
54 GLLightmap::GLLightmap() :
55   m_lightmap(),
56   m_lightmap_width(),
57   m_lightmap_height(),
58   m_lightmap_uv_right(),
59   m_lightmap_uv_bottom()
60 {
61   m_lightmap_width = SCREEN_WIDTH / s_LIGHTMAP_DIV;
62   m_lightmap_height = SCREEN_HEIGHT / s_LIGHTMAP_DIV;
63   unsigned int width = next_po2(m_lightmap_width);
64   unsigned int height = next_po2(m_lightmap_height);
65
66   m_lightmap.reset(new GLTexture(width, height));
67
68   m_lightmap_uv_right = static_cast<float>(m_lightmap_width) / static_cast<float>(width);
69   m_lightmap_uv_bottom = static_cast<float>(m_lightmap_height) / static_cast<float>(height);
70   TextureManager::current()->register_texture(m_lightmap.get());
71 }
72
73 GLLightmap::~GLLightmap()
74 {
75 }
76
77 void
78 GLLightmap::start_draw(const Color &ambient_color)
79 {
80
81   glGetFloatv(GL_VIEWPORT, m_old_viewport); //save viewport
82   glViewport(m_old_viewport[0], m_old_viewport[3] - m_lightmap_height + m_old_viewport[1], m_lightmap_width, m_lightmap_height);
83   glMatrixMode(GL_PROJECTION);
84   glLoadIdentity();
85 #ifdef GL_VERSION_ES_CM_1_0
86   glOrthof(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
87 #else
88   glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
89 #endif
90   glMatrixMode(GL_MODELVIEW);
91   glLoadIdentity();
92
93   glClearColor( ambient_color.red, ambient_color.green, ambient_color.blue, 1 );
94   glClear(GL_COLOR_BUFFER_BIT);
95 }
96
97 void
98 GLLightmap::end_draw()
99 {
100   glDisable(GL_BLEND);
101   glBindTexture(GL_TEXTURE_2D, m_lightmap->get_handle());
102   glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_old_viewport[0], m_old_viewport[3] - m_lightmap_height + m_old_viewport[1], m_lightmap_width, m_lightmap_height);
103
104   glViewport(m_old_viewport[0], m_old_viewport[1], m_old_viewport[2], m_old_viewport[3]);
105   glMatrixMode(GL_PROJECTION);
106   glLoadIdentity();
107 #ifdef GL_VERSION_ES_CM_1_0
108   glOrthof(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
109 #else
110   glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
111 #endif
112   glMatrixMode(GL_MODELVIEW);
113   glLoadIdentity();
114   glEnable(GL_BLEND);
115
116   glClearColor(0, 0, 0, 1 );
117   glClear(GL_COLOR_BUFFER_BIT);
118 }
119
120 void
121 GLLightmap::do_draw()
122 {
123   // multiple the lightmap with the framebuffer
124   glBlendFunc(GL_DST_COLOR, GL_ZERO);
125
126   glBindTexture(GL_TEXTURE_2D, m_lightmap->get_handle());
127
128   float vertices[] = {
129     0, 0,
130     float(SCREEN_WIDTH), 0,
131     float(SCREEN_WIDTH), float(SCREEN_HEIGHT),
132     0, float(SCREEN_HEIGHT)
133   };
134   glVertexPointer(2, GL_FLOAT, 0, vertices);
135
136   float uvs[] = {
137     0,                 m_lightmap_uv_bottom,
138     m_lightmap_uv_right, m_lightmap_uv_bottom,
139     m_lightmap_uv_right, 0,
140     0, 0
141   };
142   glTexCoordPointer(2, GL_FLOAT, 0, uvs);
143
144   glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
145
146   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
147 }
148
149 void
150 GLLightmap::draw_surface(const DrawingRequest& request)
151 {
152   GLPainter::draw_surface(request);
153 }
154
155 void
156 GLLightmap::draw_surface_part(const DrawingRequest& request)
157 {
158   GLPainter::draw_surface_part(request);
159 }
160
161 void
162 GLLightmap::draw_gradient(const DrawingRequest& request)
163 {
164   GLPainter::draw_gradient(request);
165 }
166
167 void
168 GLLightmap::draw_filled_rect(const DrawingRequest& request)
169 {
170   GLPainter::draw_filled_rect(request);
171 }
172
173 void
174 GLLightmap::draw_inverse_ellipse(const DrawingRequest& request)
175 {
176   GLPainter::draw_inverse_ellipse(request);
177 }
178
179 void
180 GLLightmap::get_light(const DrawingRequest& request) const
181 {
182   const GetLightRequest* getlightrequest
183     = (GetLightRequest*) request.request_data;
184
185   float pixels[3];
186   for( int i = 0; i<3; i++)
187     pixels[i] = 0.0f; //set to black
188
189   float posX = request.pos.x * m_lightmap_width / SCREEN_WIDTH + m_old_viewport[0];
190   float posY = m_old_viewport[3] + m_old_viewport[1] - request.pos.y * m_lightmap_height / SCREEN_HEIGHT;
191   glReadPixels((GLint) posX, (GLint) posY , 1, 1, GL_RGB, GL_FLOAT, pixels);
192   *(getlightrequest->color_ptr) = Color( pixels[0], pixels[1], pixels[2]);
193 }
194
195 /* EOF */