3 * (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 static uint8_t *legacy_rgb = NULL;
30 static uint8_t *benson_rgb = NULL;
31 static GLuint legacy_name;
32 static GLuint benson_name;
33 static int screen_width, screen_height;
34 static int image_width, image_height;
35 static int texture_size;
37 /* alloc and init an image texture with size that is greater than the power of two */
38 int init_opengl(int _image_width, int _image_height)
42 image_width = _image_width;
43 image_height = _image_height;
45 /* generate texture */
46 for (texture_size = 1; texture_size <= image_width || texture_size <= image_height; texture_size *= 2)
49 legacy_rgb = calloc(texture_size * texture_size, 3);
51 print_error("Failed to allocate texture\n");
55 glShadeModel(GL_FLAT);
56 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* bytes */
57 glGenTextures(1, &legacy_name);
58 glBindTexture(GL_TEXTURE_2D, legacy_name);
59 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
60 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
61 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_size, texture_size, 0, GL_RGB, GL_UNSIGNED_BYTE, legacy_rgb);
63 benson_rgb = calloc(texture_size * texture_size, 3);
65 print_error("Failed to allocate texture\n");
70 glShadeModel(GL_FLAT);
71 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* bytes */
72 glGenTextures(1, &benson_name);
73 glBindTexture(GL_TEXTURE_2D, benson_name);
74 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
75 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
76 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_size, texture_size, 0, GL_RGB, GL_UNSIGNED_BYTE, benson_rgb);
85 /* set clip planes so that the image portion of the image texture is centered and pixels are rectengular */
86 void resize_opengl(int _screen_width, int _screen_height)
88 screen_width = _screen_width;
89 screen_height = _screen_height;
93 void opengl_clear(void)
95 glClearColor(0.0, 0.0, 0.0, 1.0);
96 glClear(GL_COLOR_BUFFER_BIT);
99 /* set viewport for legacy image */
100 void opengl_viewport_legacy(int split)
103 int view_width, view_height;
104 int new_width, new_height;
109 view_width = screen_width;
110 view_height = screen_height;
113 view_y = screen_height / 2;
114 view_width = screen_width;
115 view_height = screen_height / 2;
118 /* avoid division by zero, if one dimension is too small */
119 if (view_width < 1 || view_height < 1)
122 /* calculate a viewport that has apect of image_width:image_height */
123 if (view_height * image_width > view_width * image_height) {
124 new_height = view_width * image_height / image_width;
125 view_y = view_y + view_height / 2 - new_height / 2;
126 view_height = new_height;
127 } else if (view_height * image_width < view_width * image_height) {
128 new_width = view_height * image_width / image_height;
129 view_x = view_x + view_width / 2 - new_width / 2;
130 view_width = new_width;
133 /* avoid views that are too small */
134 if (view_width < 1 || view_height < 1)
137 /* viewport and projection matrix */
138 glViewport((GLsizei)view_x, (GLsizei)view_y, (GLsizei)view_width, (GLsizei)view_height);
139 glMatrixMode(GL_PROJECTION);
141 glOrtho(0.0, 1.0, 1.0, 0.0, -1.0, 1.0);
142 glMatrixMode(GL_MODELVIEW);
145 /* render legacy image texture */
146 void opengl_render_legacy(uint8_t *rgb, int filter)
148 double width = (double)image_width / (double)texture_size;
149 double height = (double)image_height / (double)texture_size;
151 glEnable(GL_TEXTURE_2D);
152 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); /* no modulation with color */
153 glBindTexture(GL_TEXTURE_2D, legacy_name);
154 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (filter) ? GL_LINEAR : GL_NEAREST);
155 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (filter) ? GL_LINEAR : GL_NEAREST);
156 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image_width, image_height, GL_RGB, GL_UNSIGNED_BYTE, rgb);
158 glTexCoord2f(0.0, 0.0);
159 glVertex3f(0.0, 0.0, 0.0);
160 glTexCoord2f(width, 0.0);
161 glVertex3f(1.0, 0.0, 0.0);
162 glTexCoord2f(width, height);
163 glVertex3f(1.0, 1.0, 0.0);
164 glTexCoord2f(0.0, height);
165 glVertex3f(0.0, 1.0, 0.0);
167 glDisable(GL_TEXTURE_2D);
170 static double fov = 64.0;
172 /* set viewport for improved rendering */
173 void opengl_viewport_improved(int split, int benson_at_line)
176 int view_width, view_height;
177 int new_width, new_height;
179 /* center view, or put it in the top half of the window */
183 view_width = screen_width;
184 view_height = screen_height;
188 view_width = screen_width;
189 view_height = screen_height / 2;
192 /* avoid division by zero, if one dimension is too small */
193 if (view_width < 1 || view_height < 1)
196 /* calculate a viewport that has apect of image_width:image_height */
197 if (view_height * image_width > view_width * image_height) {
198 new_height = view_width * image_height / image_width;
199 view_y = view_y + view_height / 2 - new_height / 2;
200 view_height = new_height;
201 } else if (view_height * image_width < view_width * image_height) {
202 new_width = view_height * image_width / image_height;
203 view_x = view_x + view_width / 2 - new_width / 2;
204 view_width = new_width;
207 /* avoid views that are too small */
208 if (view_width < 1 || view_height < 1)
211 /* viewport and projection matrix */
212 glViewport((GLsizei)view_x, (GLsizei)view_y, (GLsizei)view_width, (GLsizei)view_height);
213 glMatrixMode(GL_PROJECTION);
216 /* calculate field-of-view */
217 double slope = tan(fov / 360 * M_PI);
218 /* make frustum to center the view in the game view above benson */
219 double left = -slope;
220 double right = slope;
221 double top = slope * (double)benson_at_line / (double)image_width;
222 double bottom = -slope * ((double)image_height * 2.0 - (double)benson_at_line) / (double)image_width;
223 glFrustum(left, right, bottom, top, 1.0, 5000000000.0);
224 glMatrixMode(GL_MODELVIEW);
228 glColor3d(0.5, 0.4, 0.4);
230 glVertex3f(-1.0, -1.0, -1.0);
231 glVertex3f(1.0, -1.0, -1.0);
232 glVertex3f(1.0, 1.0, -1.0);
233 glVertex3f(-1.0, 1.0, -1.0);
238 /* render only benson */
239 void opengl_render_benson(uint8_t *rgb, int filter, int benson_at_line)
241 double texture_left = 0.0;
242 double texture_right = (double)image_width / (double)texture_size;
243 double texture_top = (double)benson_at_line / (double)texture_size;
244 double texture_bottom = (double)image_height / (double)texture_size;
245 double benson_top = -(double)benson_at_line / (double)image_width;
246 double benson_bottom = -((double)image_height * 2.0 - (double)benson_at_line) / (double)image_width;
248 /* calculate field-of-view */
249 double slope = tan(fov / 360 * M_PI);
252 rgb += image_width * benson_at_line * 3;
253 glEnable(GL_TEXTURE_2D);
254 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); /* no modulation with color */
255 glBindTexture(GL_TEXTURE_2D, benson_name);
256 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (filter) ? GL_LINEAR : GL_NEAREST);
257 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (filter) ? GL_LINEAR : GL_NEAREST);
258 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, benson_at_line, image_width, image_height - benson_at_line, GL_RGB, GL_UNSIGNED_BYTE, rgb);
260 glTexCoord2f(texture_left, texture_bottom);
261 glVertex3f(-2.0, 2.0 * benson_bottom, -2.0 / slope);
262 glTexCoord2f(texture_right, texture_bottom);
263 glVertex3f(2.0, 2.0 * benson_bottom, -2.0 / slope);
264 glTexCoord2f(texture_right, texture_top);
265 glVertex3f(2.0, 2.0 * benson_top, -2.0 / slope);
266 glTexCoord2f(texture_left, texture_top);
267 glVertex3f(-2.0, 2.0 * benson_top, -2.0 / slope);
269 glDisable(GL_TEXTURE_2D);
272 /* free image texture */
273 void exit_opengl(void)