2 * Copyright (C) 2003 Robert Kooima
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
28 #include "solid_draw.h"
30 /*---------------------------------------------------------------------------*/
32 static const struct tex_env *curr_tex_env;
34 static void tex_env_conf_default(int, int);
35 static void tex_env_conf_shadow(int, int);
37 const struct tex_env tex_env_default = {
41 { GL_TEXTURE0, TEX_STAGE_TEXTURE }
45 const struct tex_env tex_env_shadow = {
49 { GL_TEXTURE0, TEX_STAGE_SHADOW },
50 { GL_TEXTURE1, TEX_STAGE_TEXTURE }
54 const struct tex_env tex_env_shadow_clip = {
58 { GL_TEXTURE0, TEX_STAGE_SHADOW },
59 { GL_TEXTURE1, TEX_STAGE_CLIP },
60 { GL_TEXTURE2, TEX_STAGE_TEXTURE }
64 static void tex_env_conf_default(int stage, int enable)
68 case TEX_STAGE_TEXTURE:
71 glEnable(GL_TEXTURE_2D);
73 /* Modulate is the default mode. */
75 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
77 glMatrixMode(GL_TEXTURE);
79 glMatrixMode(GL_MODELVIEW);
83 glDisable(GL_TEXTURE_2D);
89 static void tex_env_conf_shadow(int stage, int enable)
93 case TEX_STAGE_SHADOW:
96 glDisable(GL_TEXTURE_2D);
98 /* Modulate primary color and shadow alpha. */
100 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
102 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
103 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
104 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
105 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
106 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_ONE_MINUS_SRC_ALPHA);
108 /* Copy incoming alpha. */
110 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
111 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
112 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
114 glMatrixMode(GL_TEXTURE);
116 glMatrixMode(GL_MODELVIEW);
120 glDisable(GL_TEXTURE_2D);
127 glDisable(GL_TEXTURE_2D);
129 /* Interpolate shadowed and non-shadowed primary color. */
131 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
133 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
134 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
135 glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
136 glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE);
137 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
138 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
139 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);
141 /* Copy incoming alpha. */
143 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
144 glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
145 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
147 glMatrixMode(GL_TEXTURE);
149 glMatrixMode(GL_MODELVIEW);
153 glDisable(GL_TEXTURE_2D);
157 case TEX_STAGE_TEXTURE:
158 tex_env_conf_default(TEX_STAGE_TEXTURE, enable);
163 static void tex_env_conf(const struct tex_env *env, int enable)
167 for (i = 0; i < env->count; i++)
169 const struct tex_stage *st = &env->stages[i];
170 glActiveTexture_(st->unit);
171 glClientActiveTexture_(st->unit);
172 env->conf(st->stage, enable);
175 /* Last stage remains selected. */
179 * Set up current texture pipeline.
181 void tex_env_active(const struct tex_env *env)
183 if (curr_tex_env == env)
188 tex_env_conf(curr_tex_env, 0);
192 tex_env_conf(env, 1);
197 * Select stage of the current texture pipeline.
199 int tex_env_stage(int stage)
205 for (i = 0; i < curr_tex_env->count; i++)
207 const struct tex_stage *st = &curr_tex_env->stages[i];
209 if (st->stage == stage)
211 glActiveTexture_(st->unit);
212 glClientActiveTexture_(st->unit);
220 /*---------------------------------------------------------------------------*/
222 static struct s_full beam;
223 static struct s_full jump;
224 static struct s_full goal;
225 static struct s_full flag;
226 static struct s_full mark;
227 static struct s_full vect;
228 static struct s_full back;
230 static int back_state = 0;
232 /*---------------------------------------------------------------------------*/
236 sol_load_full(&beam, "geom/beam/beam.sol", 0);
237 sol_load_full(&jump, "geom/jump/jump.sol", 0);
238 sol_load_full(&goal, "geom/goal/goal.sol", 0);
239 sol_load_full(&flag, "geom/flag/flag.sol", 0);
240 sol_load_full(&mark, "geom/mark/mark.sol", 0);
241 sol_load_full(&vect, "geom/vect/vect.sol", 0);
246 sol_free_full(&vect);
247 sol_free_full(&mark);
248 sol_free_full(&flag);
249 sol_free_full(&goal);
250 sol_free_full(&jump);
251 sol_free_full(&beam);
254 /*---------------------------------------------------------------------------*/
256 void back_init(const char *name)
261 /* Load the background SOL and modify its material in-place to use the */
262 /* named gradient texture. */
264 sol_load_full(&back, "geom/back/back.sol", 0);
265 back.draw.mv[0].o = make_image_from_file(name);
267 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
275 sol_free_full(&back);
280 /*---------------------------------------------------------------------------*/
282 static void jump_part_draw(struct s_rend *rend, GLfloat s, GLfloat a)
284 glMatrixMode(GL_TEXTURE);
285 glTranslatef(s, 0.0f, 0.0f);
286 glMatrixMode(GL_MODELVIEW);
288 glRotatef(a, 0.0f, 1.0f, 0.0f);
289 sol_draw(&jump.draw, rend, 1, 1);
290 glScalef(0.9f, 0.9f, 0.9f);
293 static void goal_part_draw(struct s_rend *rend, GLfloat s)
295 glMatrixMode(GL_TEXTURE);
296 glTranslatef(0.0f, -s, 0.0f);
297 glMatrixMode(GL_MODELVIEW);
299 sol_draw(&goal.draw, rend, 1, 1);
300 glScalef(0.8f, 1.1f, 0.8f);
303 /*---------------------------------------------------------------------------*/
305 void goal_draw(struct s_rend *rend, float t)
309 glScalef(1.0f, 3.0f, 1.0f);
310 glColor4f(1.0f, 1.0f, 0.0f, 0.5f);
312 sol_draw(&beam.draw, rend, 1, 1);
314 goal_part_draw(rend, t * 0.10f);
315 goal_part_draw(rend, t * 0.10f);
316 goal_part_draw(rend, t * 0.10f);
317 goal_part_draw(rend, t * 0.10f);
319 glMatrixMode(GL_TEXTURE);
321 glMatrixMode(GL_MODELVIEW);
323 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
328 void jump_draw(struct s_rend *rend, float t, int h)
330 static GLfloat c[4][4] = {
331 { 0.75f, 0.5f, 1.0f, 0.5f },
332 { 0.75f, 0.5f, 1.0f, 0.8f },
337 glColor4f(c[h][0], c[h][1], c[h][2], c[h][3]);
339 glScalef(1.0f, 2.0f, 1.0f);
341 sol_draw(&beam.draw, rend, 1, 1);
343 jump_part_draw(rend, t * 0.15f, t * 360.0f);
344 jump_part_draw(rend, t * 0.20f, t * 360.0f);
345 jump_part_draw(rend, t * 0.25f, t * 360.0f);
347 glMatrixMode(GL_TEXTURE);
349 glMatrixMode(GL_MODELVIEW);
351 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
356 void swch_draw(struct s_rend *rend, int b, int e)
358 static GLfloat c[4][4] = {
359 { 1.0f, 0.0f, 0.0f, 0.5f }, /* red out */
360 { 1.0f, 0.0f, 0.0f, 0.8f }, /* red in */
361 { 0.0f, 1.0f, 0.0f, 0.5f }, /* green out */
362 { 0.0f, 1.0f, 0.0f, 0.8f }, /* green in */
365 const int h = 2 * b + e;
369 glScalef(1.0f, 2.0f, 1.0f);
371 glColor4f(c[h][0], c[h][1], c[h][2], c[h][3]);
372 sol_draw(&beam.draw, rend, 1, 1);
373 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
378 void flag_draw(struct s_rend *rend)
380 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
381 sol_draw(&flag.draw, rend, 1, 1);
384 void mark_draw(struct s_rend *rend)
386 sol_draw(&mark.draw, rend, 1, 1);
389 void vect_draw(struct s_rend *rend)
391 sol_draw(&vect.draw, rend, 0, 1);
392 sol_draw(&vect.draw, rend, 0, 0);
395 void back_draw(struct s_rend *rend, float t)
399 GLfloat dx = 60.0f * fsinf(t / 10.0f);
400 GLfloat dz = 180.0f * fsinf(t / 12.0f);
402 glDisable(GL_DEPTH_TEST);
403 glDisable(GL_CULL_FACE);
404 glDisable(GL_LIGHTING);
405 glDepthMask(GL_FALSE);
407 glScalef(-BACK_DIST, BACK_DIST, -BACK_DIST);
408 if (t) glRotatef(dz, 0.0f, 0.0f, 1.0f);
409 if (t) glRotatef(dx, 1.0f, 0.0f, 0.0f);
411 sol_draw(&back.draw, rend, 1, 1);
413 glDepthMask(GL_TRUE);
414 glEnable(GL_LIGHTING);
415 glEnable(GL_CULL_FACE);
416 glEnable(GL_DEPTH_TEST);
421 void back_draw_easy(void)
423 struct s_rend rend = { NULL };
425 sol_draw_enable(&rend);
426 back_draw(&rend, 0.0f);
427 sol_draw_disable(&rend);
430 /*---------------------------------------------------------------------------*/
433 * A note about lighting and shadow: technically speaking, it's wrong.
434 * The light position and shadow projection behave as if the
435 * light-source rotates with the floor. However, the skybox does not
436 * rotate, thus the light should also remain stationary.
438 * The correct behavior would eliminate a significant 3D cue: the
439 * shadow of the ball indicates the ball's position relative to the
440 * floor even when the ball is in the air. This was the motivating
441 * idea behind the shadow in the first place, so correct shadow
442 * projection would only magnify the problem.
445 static GLuint shad_text;
446 static GLuint clip_text;
448 static GLubyte clip_data[] = { 0xff, 0xff, 0x0, 0x0 };
452 shad_text = make_image_from_file(IMG_SHAD);
454 if (config_get_d(CONFIG_SHADOW) == 2)
456 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
457 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
460 /* Create the clip texture. */
462 glGenTextures(1, &clip_text);
463 glBindTexture(GL_TEXTURE_2D, clip_text);
465 glTexImage2D(GL_TEXTURE_2D, 0,
466 GL_LUMINANCE_ALPHA, 1, 2, 0,
467 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, clip_data);
469 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
470 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
472 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
473 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
478 glDeleteTextures(1, &shad_text);
479 glDeleteTextures(1, &clip_text);
482 void shad_draw_set(void)
484 if (tex_env_stage(TEX_STAGE_SHADOW))
486 glEnable(GL_TEXTURE_2D);
487 glBindTexture(GL_TEXTURE_2D, shad_text);
489 if (tex_env_stage(TEX_STAGE_CLIP))
491 glBindTexture(GL_TEXTURE_2D, clip_text);
492 glEnable(GL_TEXTURE_2D);
495 tex_env_stage(TEX_STAGE_TEXTURE);
499 void shad_draw_clr(void)
501 if (tex_env_stage(TEX_STAGE_SHADOW))
503 glBindTexture(GL_TEXTURE_2D, 0);
504 glDisable(GL_TEXTURE_2D);
506 if (tex_env_stage(TEX_STAGE_CLIP))
508 glBindTexture(GL_TEXTURE_2D, 0);
509 glDisable(GL_TEXTURE_2D);
512 tex_env_stage(TEX_STAGE_TEXTURE);
516 /*---------------------------------------------------------------------------*/