1 /*
2 * RenderRasterize_Shader.cpp
3 * Created by Clemens Unterkofler on 1/20/09.
4 * for Aleph One
5 *
6 * http://www.gnu.org/licenses/gpl.html
7 */
8
9 #include "OGL_Headers.h"
10
11 #include <iostream>
12
13 #include "RenderRasterize_Shader.h"
14
15 #include "lightsource.h"
16 #include "media.h"
17 #include "player.h"
18 #include "weapons.h"
19 #include "AnimatedTextures.h"
20 #include "OGL_Faders.h"
21 #include "OGL_Textures.h"
22 #include "OGL_Shader.h"
23 #include "ChaseCam.h"
24 #include "preferences.h"
25 #include "screen.h"
26
27 #define MAXIMUM_VERTICES_PER_WORLD_POLYGON (MAXIMUM_VERTICES_PER_POLYGON+4)
28
29 inline bool FogActive();
30
31 class Blur {
32
33 private:
34 FBOSwapper _swapper;
35 Shader *_shader_blur;
36 Shader *_shader_bloom;
37 GLuint _width;
38 GLuint _height;
39
40 public:
41
Blur(GLuint w,GLuint h,Shader * s_blur,Shader * s_bloom)42 Blur(GLuint w, GLuint h, Shader* s_blur, Shader* s_bloom)
43 : _swapper(w, h, Bloom_sRGB), _shader_blur(s_blur), _shader_bloom(s_bloom), _width(w), _height(h) {}
44
width()45 GLuint width() { return _width; }
height()46 GLuint height() { return _height; }
47
begin()48 void begin() {
49 _swapper.activate();
50 glDisable(GL_FRAMEBUFFER_SRGB_EXT); // don't blend for initial
51 }
52
end()53 void end() {
54 _swapper.swap();
55 }
56
draw(FBOSwapper & dest)57 void draw(FBOSwapper& dest) {
58
59 int passes = _shader_bloom->passes();
60 if (passes < 0)
61 passes = 5;
62
63 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
64 for (int i = 0; i < passes; i++) {
65 _shader_blur->enable();
66 _shader_blur->setFloat(Shader::U_OffsetX, 1);
67 _shader_blur->setFloat(Shader::U_OffsetY, 0);
68 _shader_blur->setFloat(Shader::U_Pass, i + 1);
69 _swapper.filter(false);
70
71 _shader_blur->setFloat(Shader::U_OffsetX, 0);
72 _shader_blur->setFloat(Shader::U_OffsetY, 1);
73 _shader_blur->setFloat(Shader::U_Pass, i + 1);
74 _swapper.filter(false);
75
76 _shader_bloom->enable();
77 _shader_bloom->setFloat(Shader::U_Pass, i + 1);
78 // if (Bloom_sRGB)
79 // dest.blend(_swapper.current_contents(), true);
80 // else
81 dest.blend_multisample(_swapper.current_contents());
82
83 Shader::disable();
84 }
85
86 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
87 }
88 };
89
90
91 RenderRasterize_Shader::RenderRasterize_Shader() = default;
92 RenderRasterize_Shader::~RenderRasterize_Shader() = default;
93
94 /*
95 * initialize some stuff
96 * happens once after opengl, shaders and textures are setup
97 */
setupGL(Rasterizer_Shader_Class & Rasterizer)98 void RenderRasterize_Shader::setupGL(Rasterizer_Shader_Class& Rasterizer) {
99
100 RasPtr = &Rasterizer;
101
102 Shader::loadAll();
103
104 Shader* s_blur = Shader::get(Shader::S_Blur);
105 Shader* s_bloom = Shader::get(Shader::S_Bloom);
106
107 blur.reset();
108 if(TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_Blur)) {
109 if(s_blur && s_bloom) {
110 blur.reset(new Blur(640., 640. * graphics_preferences->screen_mode.height / graphics_preferences->screen_mode.width, s_blur, s_bloom));
111 }
112 }
113
114 // glDisable(GL_CULL_FACE);
115 // glDisable(GL_LIGHTING);
116 }
117
118 /*
119 * override for RenderRasterizerClass::render_tree()
120 *
121 * with multiple rendering passes for glow effect
122 */
123 const double TWO_PI = 8*atan(1.0);
124 const float FixedAngleToRadians = TWO_PI/(float(FIXED_ONE)*float(FULL_CIRCLE));
125 const float FixedAngleToDegrees = 360.0/(float(FIXED_ONE)*float(FULL_CIRCLE));
126
render_tree()127 void RenderRasterize_Shader::render_tree() {
128
129 weaponFlare = PIN(view->maximum_depth_intensity - NATURAL_LIGHT_INTENSITY, 0, FIXED_ONE)/float(FIXED_ONE);
130 selfLuminosity = PIN(NATURAL_LIGHT_INTENSITY, 0, FIXED_ONE)/float(FIXED_ONE);
131
132 Shader* s = Shader::get(Shader::S_Invincible);
133 s->enable();
134 s->setFloat(Shader::U_Time, view->tick_count);
135 s->setFloat(Shader::U_LogicalWidth, view->screen_width);
136 s->setFloat(Shader::U_LogicalHeight, view->screen_height);
137 s->setFloat(Shader::U_PixelWidth, view->screen_width * MainScreenPixelScale());
138 s->setFloat(Shader::U_PixelHeight, view->screen_height * MainScreenPixelScale());
139 if (blur.get()) {
140 s = Shader::get(Shader::S_InvincibleBloom);
141 s->enable();
142 s->setFloat(Shader::U_Time, view->tick_count);
143 s->setFloat(Shader::U_LogicalWidth, view->screen_width);
144 s->setFloat(Shader::U_LogicalHeight, view->screen_height);
145 s->setFloat(Shader::U_PixelWidth, blur->width());
146 s->setFloat(Shader::U_PixelHeight, blur->height());
147 }
148
149 short leftmost = INT16_MAX;
150 short rightmost = INT16_MIN;
151 vector<clipping_window_data>& windows = RSPtr->RVPtr->ClippingWindows;
152 for (vector<clipping_window_data>::const_iterator it = windows.begin(); it != windows.end(); ++it) {
153 if (it->x0 < leftmost) {
154 leftmost = it->x0;
155 leftmost_clip = it->left;
156 }
157 if (it->x1 > rightmost) {
158 rightmost = it->x1;
159 rightmost_clip = it->right;
160 }
161 }
162
163 bool usefog = false;
164 int fogtype;
165 OGL_FogData *fogdata;
166 if (TEST_FLAG(Get_OGL_ConfigureData().Flags,OGL_Flag_Fog))
167 {
168 fogtype = (current_player->variables.flags&_HEAD_BELOW_MEDIA_BIT) ?
169 OGL_Fog_BelowLiquid : OGL_Fog_AboveLiquid;
170 fogdata = OGL_GetFogData(fogtype);
171 if (fogdata && fogdata->IsPresent && fogdata->AffectsLandscapes) {
172 usefog = true;
173 }
174 }
175 const float virtual_yaw = view->virtual_yaw * FixedAngleToRadians;
176 const float virtual_pitch = view->virtual_pitch * FixedAngleToRadians;
177 s = Shader::get(Shader::S_Landscape);
178 s->enable();
179 s->setFloat(Shader::U_UseFog, usefog ? 1.0 : 0.0);
180 s->setFloat(Shader::U_Yaw, virtual_yaw);
181 s->setFloat(Shader::U_Pitch, view->mimic_sw_perspective ? 0.0 : virtual_pitch);
182 s = Shader::get(Shader::S_LandscapeBloom);
183 s->enable();
184 s->setFloat(Shader::U_UseFog, usefog ? 1.0 : 0.0);
185 s->setFloat(Shader::U_Yaw, virtual_yaw);
186 s->setFloat(Shader::U_Pitch, view->mimic_sw_perspective ? 0.0 : virtual_pitch);
187 Shader::disable();
188
189 RenderRasterizerClass::render_tree(kDiffuse);
190 render_viewer_sprite_layer(kDiffuse);
191
192 if (TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_Blur) && blur.get()) {
193 blur->begin();
194 RenderRasterizerClass::render_tree(kGlow);
195 render_viewer_sprite_layer(kGlow);
196 blur->end();
197 RasPtr->swapper->deactivate();
198 blur->draw(*RasPtr->swapper);
199 RasPtr->swapper->activate();
200 }
201
202 glAlphaFunc(GL_GREATER, 0.5);
203 }
204
render_node(sorted_node_data * node,bool SeeThruLiquids,RenderStep renderStep)205 void RenderRasterize_Shader::render_node(sorted_node_data *node, bool SeeThruLiquids, RenderStep renderStep)
206 {
207 // parasitic object detection
208 objectCount = 0;
209 objectY = 0;
210
211 RenderRasterizerClass::render_node(node, SeeThruLiquids, renderStep);
212
213 // turn off clipping planes
214 glDisable(GL_CLIP_PLANE0);
215 glDisable(GL_CLIP_PLANE1);
216 }
217
clip_to_window(clipping_window_data * win)218 void RenderRasterize_Shader::clip_to_window(clipping_window_data *win)
219 {
220 GLdouble clip[] = { 0., 0., 0., 0. };
221
222 // recenter to player's orientation temporarily
223 glPushMatrix();
224 glTranslatef(view->origin.x, view->origin.y, 0.);
225 glRotatef(view->yaw * (360/float(FULL_CIRCLE)) + 90., 0., 0., 1.);
226
227 glRotatef(-0.1, 0., 0., 1.); // leave some excess to avoid artifacts at edges
228 if (win->left.i != leftmost_clip.i || win->left.j != leftmost_clip.j) {
229 clip[0] = win->left.i;
230 clip[1] = win->left.j;
231 glEnable(GL_CLIP_PLANE0);
232 glClipPlane(GL_CLIP_PLANE0, clip);
233 } else {
234 glDisable(GL_CLIP_PLANE0);
235 }
236
237 glRotatef(0.2, 0., 0., 1.); // breathing room for right-hand clip
238 if (win->right.i != rightmost_clip.i || win->right.j != rightmost_clip.j) {
239 clip[0] = win->right.i;
240 clip[1] = win->right.j;
241 glEnable(GL_CLIP_PLANE1);
242 glClipPlane(GL_CLIP_PLANE1, clip);
243 } else {
244 glDisable(GL_CLIP_PLANE1);
245 }
246
247 glPopMatrix();
248 }
249
store_endpoint(endpoint_data * endpoint,long_vector2d & p)250 void RenderRasterize_Shader::store_endpoint(
251 endpoint_data *endpoint,
252 long_vector2d& p)
253 {
254 p.i = endpoint->vertex.x;
255 p.j = endpoint->vertex.y;
256 }
257
258
setupSpriteTexture(const rectangle_definition & rect,short type,float offset,RenderStep renderStep)259 TextureManager RenderRasterize_Shader::setupSpriteTexture(const rectangle_definition& rect, short type, float offset, RenderStep renderStep) {
260
261 Shader *s = NULL;
262 GLfloat color[3];
263 GLdouble shade = PIN(static_cast<GLfloat>(rect.ambient_shade)/static_cast<GLfloat>(FIXED_ONE),0,1);
264 color[0] = color[1] = color[2] = shade;
265
266 TextureManager TMgr;
267
268 TMgr.ShapeDesc = rect.ShapeDesc;
269 TMgr.LowLevelShape = rect.LowLevelShape;
270 TMgr.ShadingTables = rect.shading_tables;
271 TMgr.Texture = rect.texture;
272 TMgr.TransferMode = rect.transfer_mode;
273 TMgr.TransferData = rect.transfer_data;
274 TMgr.IsShadeless = (rect.flags&_SHADELESS_BIT) != 0;
275 TMgr.TextureType = type;
276
277 float flare = weaponFlare;
278
279 glEnable(GL_TEXTURE_2D);
280 glColor4f(color[0], color[1], color[2], 1);
281
282 switch(TMgr.TransferMode) {
283 case _static_transfer:
284 TMgr.IsShadeless = 1;
285 flare = -1;
286 s = Shader::get(renderStep == kGlow ? Shader::S_InvincibleBloom : Shader::S_Invincible);
287 s->enable();
288 break;
289 case _tinted_transfer:
290 flare = -1;
291 s = Shader::get(renderStep == kGlow ? Shader::S_InvisibleBloom : Shader::S_Invisible);
292 s->enable();
293 s->setFloat(Shader::U_Visibility, 1.0 - rect.transfer_data/32.0f);
294 break;
295 case _solid_transfer:
296 glColor4f(0,1,0,1);
297 break;
298 case _textured_transfer:
299 if(TMgr.IsShadeless) {
300 if (renderStep == kDiffuse) {
301 glColor4f(1,1,1,1);
302 } else {
303 glColor4f(0,0,0,1);
304 }
305 flare = -1;
306 }
307 break;
308 default:
309 glColor4f(0,0,1,1);
310 }
311
312 if(s == NULL) {
313 s = Shader::get(renderStep == kGlow ? Shader::S_SpriteBloom : Shader::S_Sprite);
314 s->enable();
315 }
316
317 if(TMgr.Setup()) {
318 TMgr.RenderNormal();
319 } else {
320 TMgr.ShapeDesc = UNONE;
321 return TMgr;
322 }
323
324 TMgr.SetupTextureMatrix();
325
326 if (renderStep == kGlow) {
327 s->setFloat(Shader::U_BloomScale, TMgr.BloomScale());
328 s->setFloat(Shader::U_BloomShift, TMgr.BloomShift());
329 }
330 s->setFloat(Shader::U_Flare, flare);
331 s->setFloat(Shader::U_SelfLuminosity, selfLuminosity);
332 s->setFloat(Shader::U_Pulsate, 0);
333 s->setFloat(Shader::U_Wobble, 0);
334 s->setFloat(Shader::U_Depth, offset);
335 s->setFloat(Shader::U_StrictDepthMode, OGL_ForceSpriteDepth() ? 1 : 0);
336 s->setFloat(Shader::U_Glow, 0);
337 return TMgr;
338 }
339
340 // Circle constants
341 const double Radian2Circle = 1/TWO_PI; // A circle is 2*pi radians
342 const double FullCircleReciprocal = 1/double(FULL_CIRCLE);
343
setupWallTexture(const shape_descriptor & Texture,short transferMode,float pulsate,float wobble,float intensity,float offset,RenderStep renderStep)344 TextureManager RenderRasterize_Shader::setupWallTexture(const shape_descriptor& Texture, short transferMode, float pulsate, float wobble, float intensity, float offset, RenderStep renderStep) {
345
346 Shader *s = NULL;
347
348 TextureManager TMgr;
349 LandscapeOptions *opts = NULL;
350 TMgr.ShapeDesc = Texture;
351 if (TMgr.ShapeDesc == UNONE) { return TMgr; }
352 get_shape_bitmap_and_shading_table(Texture, &TMgr.Texture, &TMgr.ShadingTables,
353 current_player->infravision_duration ? _shading_infravision : _shading_normal);
354
355 TMgr.TransferMode = _textured_transfer;
356 TMgr.IsShadeless = current_player->infravision_duration ? 1 : 0;
357 TMgr.TransferData = 0;
358
359 float flare = weaponFlare;
360
361 glEnable(GL_TEXTURE_2D);
362 glColor4f(intensity, intensity, intensity, 1.0);
363
364 switch(transferMode) {
365 case _xfer_static:
366 TMgr.TextureType = OGL_Txtr_Wall;
367 TMgr.TransferMode = _static_transfer;
368 TMgr.IsShadeless = 1;
369 flare = -1;
370 s = Shader::get(renderStep == kGlow ? Shader::S_InvincibleBloom : Shader::S_Invincible);
371 s->enable();
372 break;
373 case _xfer_landscape:
374 case _xfer_big_landscape:
375 {
376 TMgr.TextureType = OGL_Txtr_Landscape;
377 TMgr.TransferMode = _big_landscaped_transfer;
378 opts = View_GetLandscapeOptions(Texture);
379 TMgr.LandscapeVertRepeat = opts->VertRepeat;
380 TMgr.Landscape_AspRatExp = opts->OGL_AspRatExp;
381 s = Shader::get(renderStep == kGlow ? Shader::S_LandscapeBloom : Shader::S_Landscape);
382 s->enable();
383 }
384 break;
385 default:
386 TMgr.TextureType = OGL_Txtr_Wall;
387 if(TMgr.IsShadeless) {
388 if (renderStep == kDiffuse) {
389 glColor4f(1,1,1,1);
390 } else {
391 glColor4f(0,0,0,1);
392 }
393 flare = -1;
394 }
395 }
396
397 if(s == NULL) {
398 if(TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_BumpMap)) {
399 s = Shader::get(renderStep == kGlow ? Shader::S_BumpBloom : Shader::S_Bump);
400 } else {
401 s = Shader::get(renderStep == kGlow ? Shader::S_WallBloom : Shader::S_Wall);
402 }
403 s->enable();
404 }
405
406 if(TMgr.Setup()) {
407 TMgr.RenderNormal(); // must allocate first
408 if (TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_BumpMap)) {
409 glActiveTextureARB(GL_TEXTURE1_ARB);
410 TMgr.RenderBump();
411 glActiveTextureARB(GL_TEXTURE0_ARB);
412 }
413 } else {
414 TMgr.ShapeDesc = UNONE;
415 return TMgr;
416 }
417
418 TMgr.SetupTextureMatrix();
419
420 if (TMgr.TextureType == OGL_Txtr_Landscape && opts) {
421 double TexScale = ABS(TMgr.U_Scale);
422 double HorizScale = double(1 << opts->HorizExp);
423 s->setFloat(Shader::U_ScaleX, HorizScale * (npotTextures ? 1.0 : TexScale) * Radian2Circle);
424 s->setFloat(Shader::U_OffsetX, HorizScale * (0.25 + opts->Azimuth * FullCircleReciprocal));
425
426 short AdjustedVertExp = opts->VertExp + opts->OGL_AspRatExp;
427 double VertScale = (AdjustedVertExp >= 0) ? double(1 << AdjustedVertExp)
428 : 1/double(1 << (-AdjustedVertExp));
429 s->setFloat(Shader::U_ScaleY, VertScale * TexScale * Radian2Circle);
430 s->setFloat(Shader::U_OffsetY, (0.5 + TMgr.U_Offset) * TexScale);
431 }
432
433 if (renderStep == kGlow) {
434 if (TMgr.TextureType == OGL_Txtr_Landscape) {
435 s->setFloat(Shader::U_BloomScale, TMgr.LandscapeBloom());
436 } else {
437 s->setFloat(Shader::U_BloomScale, TMgr.BloomScale());
438 s->setFloat(Shader::U_BloomShift, TMgr.BloomShift());
439 }
440 }
441 s->setFloat(Shader::U_Flare, flare);
442 s->setFloat(Shader::U_SelfLuminosity, selfLuminosity);
443 s->setFloat(Shader::U_Pulsate, pulsate);
444 s->setFloat(Shader::U_Wobble, wobble);
445 s->setFloat(Shader::U_Depth, offset);
446 s->setFloat(Shader::U_Glow, 0);
447 return TMgr;
448 }
449
instantiate_transfer_mode(struct view_data * view,short transfer_mode,world_distance & x0,world_distance & y0)450 void instantiate_transfer_mode(struct view_data *view, short transfer_mode, world_distance &x0, world_distance &y0) {
451 short alternate_transfer_phase;
452 short transfer_phase = view->tick_count;
453
454 switch (transfer_mode) {
455
456 case _xfer_fast_horizontal_slide:
457 case _xfer_horizontal_slide:
458 case _xfer_vertical_slide:
459 case _xfer_fast_vertical_slide:
460 case _xfer_wander:
461 case _xfer_fast_wander:
462 x0 = y0= 0;
463 switch (transfer_mode) {
464 case _xfer_fast_horizontal_slide: transfer_phase<<= 1;
465 case _xfer_horizontal_slide: x0= (transfer_phase<<2)&(WORLD_ONE-1); break;
466
467 case _xfer_fast_vertical_slide: transfer_phase<<= 1;
468 case _xfer_vertical_slide: y0= (transfer_phase<<2)&(WORLD_ONE-1); break;
469
470 case _xfer_fast_wander: transfer_phase<<= 1;
471 case _xfer_wander:
472 alternate_transfer_phase= transfer_phase%(10*FULL_CIRCLE);
473 transfer_phase= transfer_phase%(6*FULL_CIRCLE);
474 x0 = (cosine_table[NORMALIZE_ANGLE(alternate_transfer_phase)] +
475 (cosine_table[NORMALIZE_ANGLE(2*alternate_transfer_phase)]>>1) +
476 (cosine_table[NORMALIZE_ANGLE(5*alternate_transfer_phase)]>>1))>>(WORLD_FRACTIONAL_BITS-TRIG_SHIFT+2);
477 y0 = (sine_table[NORMALIZE_ANGLE(transfer_phase)] +
478 (sine_table[NORMALIZE_ANGLE(2*transfer_phase)]>>1) +
479 (sine_table[NORMALIZE_ANGLE(3*transfer_phase)]>>1))>>(WORLD_FRACTIONAL_BITS-TRIG_SHIFT+2);
480 break;
481 }
482 break;
483 // wobble is done in the shader
484 default:
485 break;
486 }
487 }
488
calcWobble(short transferMode,short transfer_phase)489 float calcWobble(short transferMode, short transfer_phase) {
490 float wobble = 0;
491 switch(transferMode) {
492 case _xfer_fast_wobble:
493 transfer_phase*= 15;
494 case _xfer_pulsate:
495 case _xfer_wobble:
496 transfer_phase&= WORLD_ONE/16-1;
497 transfer_phase= (transfer_phase>=WORLD_ONE/32) ? (WORLD_ONE/32+WORLD_ONE/64 - transfer_phase) : (transfer_phase - WORLD_ONE/64);
498 wobble = transfer_phase / 1024.0;
499 break;
500 }
501 return wobble;
502 }
503
setupBlendFunc(short blendType)504 void setupBlendFunc(short blendType) {
505 switch(blendType)
506 {
507 case OGL_BlendType_Crossfade:
508 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
509 break;
510 case OGL_BlendType_Add:
511 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
512 break;
513 case OGL_BlendType_Crossfade_Premult:
514 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
515 break;
516 case OGL_BlendType_Add_Premult:
517 glBlendFunc(GL_ONE, GL_ONE);
518 break;
519 }
520 }
521
setupGlow(struct view_data * view,TextureManager & TMgr,float wobble,float intensity,float flare,float selfLuminosity,float offset,RenderStep renderStep)522 bool setupGlow(struct view_data *view, TextureManager &TMgr, float wobble, float intensity, float flare, float selfLuminosity, float offset, RenderStep renderStep) {
523 if (TMgr.TransferMode == _textured_transfer && TMgr.IsGlowMapped()) {
524 Shader *s = NULL;
525 if (TMgr.TextureType == OGL_Txtr_Wall) {
526 if (TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_BumpMap)) {
527 s = Shader::get(renderStep == kGlow ? Shader::S_BumpBloom : Shader::S_Bump);
528 } else {
529 s = Shader::get(renderStep == kGlow ? Shader::S_WallBloom : Shader::S_Wall);
530 }
531 } else {
532 s = Shader::get(renderStep == kGlow ? Shader::S_SpriteBloom : Shader::S_Sprite);
533 }
534
535 TMgr.RenderGlowing();
536 setupBlendFunc(TMgr.GlowBlend());
537 glEnable(GL_TEXTURE_2D);
538 glEnable(GL_BLEND);
539 glEnable(GL_ALPHA_TEST);
540 glAlphaFunc(GL_GREATER, 0.001);
541
542 s->enable();
543 if (renderStep == kGlow) {
544 s->setFloat(Shader::U_BloomScale, TMgr.GlowBloomScale());
545 s->setFloat(Shader::U_BloomShift, TMgr.GlowBloomShift());
546 }
547 s->setFloat(Shader::U_Flare, flare);
548 s->setFloat(Shader::U_SelfLuminosity, selfLuminosity);
549 s->setFloat(Shader::U_Wobble, wobble);
550 s->setFloat(Shader::U_Depth, offset - 1.0);
551 s->setFloat(Shader::U_Glow, TMgr.MinGlowIntensity());
552 return true;
553 }
554 return false;
555 }
556
render_node_floor_or_ceiling(clipping_window_data * window,polygon_data * polygon,horizontal_surface_data * surface,bool void_present,bool ceil,RenderStep renderStep)557 void RenderRasterize_Shader::render_node_floor_or_ceiling(clipping_window_data *window,
558 polygon_data *polygon, horizontal_surface_data *surface, bool void_present, bool ceil, RenderStep renderStep) {
559
560 float offset = 0;
561
562 const shape_descriptor& texture = AnimTxtr_Translate(surface->texture);
563 float intensity = get_light_intensity(surface->lightsource_index) / float(FIXED_ONE - 1);
564 float wobble = calcWobble(surface->transfer_mode, view->tick_count);
565 // note: wobble and pulsate behave the same way on floors and ceilings
566 // note 2: stronger wobble looks more like classic with default shaders
567 TextureManager TMgr = setupWallTexture(texture, surface->transfer_mode, wobble * 4.0, 0, intensity, offset, renderStep);
568 if(TMgr.ShapeDesc == UNONE) { return; }
569
570 if (TMgr.IsBlended()) {
571 glEnable(GL_BLEND);
572 setupBlendFunc(TMgr.NormalBlend());
573 glEnable(GL_ALPHA_TEST);
574 glAlphaFunc(GL_GREATER, 0.001);
575 } else {
576 glDisable(GL_BLEND);
577 glEnable(GL_ALPHA_TEST);
578 glAlphaFunc(GL_GREATER, 0.5);
579 }
580
581 // if (void_present) {
582 // glDisable(GL_BLEND);
583 // glDisable(GL_ALPHA_TEST);
584 // }
585
586 short vertex_count = polygon->vertex_count;
587
588 if (vertex_count) {
589 clip_to_window(window);
590
591 world_distance x = 0.0, y = 0.0;
592 instantiate_transfer_mode(view, surface->transfer_mode, x, y);
593
594 vec3 N;
595 vec3 T;
596 float sign;
597 if(ceil) {
598 N = vec3(0,0,-1);
599 T = vec3(0,1,0);
600 sign = 1;
601 } else {
602 N = vec3(0,0,1);
603 T = vec3(0,1,0);
604 sign = -1;
605 }
606 glNormal3f(N[0], N[1], N[2]);
607 glMultiTexCoord4fARB(GL_TEXTURE1_ARB, T[0], T[1], T[2], sign);
608
609 GLfloat vertex_array[MAXIMUM_VERTICES_PER_POLYGON * 3];
610 GLfloat texcoord_array[MAXIMUM_VERTICES_PER_POLYGON * 2];
611
612 GLfloat* vp = vertex_array;
613 GLfloat* tp = texcoord_array;
614 if (ceil)
615 {
616 for(short i = 0; i < vertex_count; ++i) {
617 world_point2d vertex = get_endpoint_data(polygon->endpoint_indexes[vertex_count - 1 - i])->vertex;
618 *vp++ = vertex.x;
619 *vp++ = vertex.y;
620 *vp++ = surface->height;
621 *tp++ = (vertex.x + surface->origin.x + x) / float(WORLD_ONE);
622 *tp++ = (vertex.y + surface->origin.y + y) / float(WORLD_ONE);
623 }
624 }
625 else
626 {
627 for(short i=0; i<vertex_count; ++i) {
628 world_point2d vertex = get_endpoint_data(polygon->endpoint_indexes[i])->vertex;
629 *vp++ = vertex.x;
630 *vp++ = vertex.y;
631 *vp++ = surface->height;
632 *tp++ = (vertex.x + surface->origin.x + x) / float(WORLD_ONE);
633 *tp++ = (vertex.y + surface->origin.y + y) / float(WORLD_ONE);
634 }
635 }
636 glVertexPointer(3, GL_FLOAT, 0, vertex_array);
637 glTexCoordPointer(2, GL_FLOAT, 0, texcoord_array);
638
639 glDrawArrays(GL_POLYGON, 0, vertex_count);
640
641 if (setupGlow(view, TMgr, wobble, intensity, weaponFlare, selfLuminosity, offset, renderStep)) {
642 glDrawArrays(GL_POLYGON, 0, vertex_count);
643 }
644
645 Shader::disable();
646 glMatrixMode(GL_TEXTURE);
647 glLoadIdentity();
648 glMatrixMode(GL_MODELVIEW);
649 }
650 }
651
render_node_side(clipping_window_data * window,vertical_surface_data * surface,bool void_present,RenderStep renderStep)652 void RenderRasterize_Shader::render_node_side(clipping_window_data *window, vertical_surface_data *surface, bool void_present, RenderStep renderStep) {
653
654 float offset = 0;
655 if (!void_present) {
656 offset = -2.0;
657 }
658
659 const shape_descriptor& texture = AnimTxtr_Translate(surface->texture_definition->texture);
660 float intensity = (get_light_intensity(surface->lightsource_index) + surface->ambient_delta) / float(FIXED_ONE - 1);
661 float wobble = calcWobble(surface->transfer_mode, view->tick_count);
662 float pulsate = 0;
663 if (surface->transfer_mode == _xfer_pulsate) {
664 pulsate = wobble;
665 wobble = 0;
666 }
667 TextureManager TMgr = setupWallTexture(texture, surface->transfer_mode, pulsate, wobble, intensity, offset, renderStep);
668 if(TMgr.ShapeDesc == UNONE) { return; }
669
670 if (TMgr.IsBlended()) {
671 glEnable(GL_BLEND);
672 setupBlendFunc(TMgr.NormalBlend());
673 glEnable(GL_ALPHA_TEST);
674 glAlphaFunc(GL_GREATER, 0.001);
675 } else {
676 glDisable(GL_BLEND);
677 glEnable(GL_ALPHA_TEST);
678 glAlphaFunc(GL_GREATER, 0.5);
679 }
680
681 // if (void_present) {
682 // glDisable(GL_BLEND);
683 // glDisable(GL_ALPHA_TEST);
684 // }
685
686 world_distance h= MIN(surface->h1, surface->hmax);
687
688 if (h>surface->h0) {
689
690 world_point2d vertex[2];
691 uint16 flags;
692 flagged_world_point3d vertices[MAXIMUM_VERTICES_PER_WORLD_POLYGON];
693 short vertex_count;
694
695 /* initialize the two posts of our trapezoid */
696 vertex_count= 2;
697 long_to_overflow_short_2d(surface->p0, vertex[0], flags);
698 long_to_overflow_short_2d(surface->p1, vertex[1], flags);
699
700 if (vertex_count) {
701 clip_to_window(window);
702
703 vertex_count= 4;
704 vertices[0].z= vertices[1].z= h + view->origin.z;
705 vertices[2].z= vertices[3].z= surface->h0 + view->origin.z;
706 vertices[0].x= vertices[3].x= vertex[0].x, vertices[0].y= vertices[3].y= vertex[0].y;
707 vertices[1].x= vertices[2].x= vertex[1].x, vertices[1].y= vertices[2].y= vertex[1].y;
708 vertices[0].flags = vertices[3].flags = 0;
709 vertices[1].flags = vertices[2].flags = 0;
710
711 double div = WORLD_ONE;
712 double dx = (surface->p1.i - surface->p0.i) / double(surface->length);
713 double dy = (surface->p1.j - surface->p0.j) / double(surface->length);
714
715 world_distance x0 = WORLD_FRACTIONAL_PART(surface->texture_definition->x0);
716 world_distance y0 = WORLD_FRACTIONAL_PART(surface->texture_definition->y0);
717
718 double tOffset = surface->h1 + view->origin.z + y0;
719
720 vec3 N(-dy, dx, 0);
721 vec3 T(dx, dy, 0);
722 float sign = 1;
723 glNormal3f(N[0], N[1], N[2]);
724 glMultiTexCoord4fARB(GL_TEXTURE1_ARB, T[0], T[1], T[2], sign);
725
726 world_distance x = 0.0, y = 0.0;
727 instantiate_transfer_mode(view, surface->transfer_mode, x, y);
728
729 x0 -= x;
730 tOffset -= y;
731
732 GLfloat vertex_array[12];
733 GLfloat texcoord_array[8];
734
735 GLfloat* vp = vertex_array;
736 GLfloat* tp = texcoord_array;
737
738 for(int i = 0; i < vertex_count; ++i) {
739 float p2 = 0;
740 if(i == 1 || i == 2) { p2 = surface->length; }
741
742 *vp++ = vertices[i].x;
743 *vp++ = vertices[i].y;
744 *vp++ = vertices[i].z;
745 *tp++ = (tOffset - vertices[i].z) / div;
746 *tp++ = (x0+p2) / div;
747 }
748 glVertexPointer(3, GL_FLOAT, 0, vertex_array);
749 glTexCoordPointer(2, GL_FLOAT, 0, texcoord_array);
750
751 glDrawArrays(GL_QUADS, 0, vertex_count);
752
753 if (setupGlow(view, TMgr, wobble, intensity, weaponFlare, selfLuminosity, offset, renderStep)) {
754 glDrawArrays(GL_QUADS, 0, vertex_count);
755 }
756
757 Shader::disable();
758 glMatrixMode(GL_TEXTURE);
759 glLoadIdentity();
760 glMatrixMode(GL_MODELVIEW);
761 }
762 }
763 }
764
765 extern void FlatBumpTexture(); // from OGL_Textures.cpp
766
RenderModel(rectangle_definition & RenderRectangle,short Collection,short CLUT,float flare,float selfLuminosity,RenderStep renderStep)767 bool RenderModel(rectangle_definition& RenderRectangle, short Collection, short CLUT, float flare, float selfLuminosity, RenderStep renderStep) {
768
769 OGL_ModelData *ModelPtr = RenderRectangle.ModelPtr;
770 OGL_SkinData *SkinPtr = ModelPtr->GetSkin(CLUT);
771 if(!SkinPtr) { return false; }
772
773 if (ModelPtr->Sidedness < 0) {
774 glEnable(GL_CULL_FACE);
775 glFrontFace(GL_CCW);
776 } else if (ModelPtr->Sidedness > 0) {
777 glEnable(GL_CULL_FACE);
778 glFrontFace(GL_CW);
779 } else {
780 glDisable(GL_CULL_FACE);
781 }
782
783 glEnable(GL_TEXTURE_2D);
784 if (SkinPtr->OpacityType != OGL_OpacType_Crisp || RenderRectangle.transfer_mode == _tinted_transfer) {
785 glEnable(GL_BLEND);
786 setupBlendFunc(SkinPtr->NormalBlend);
787 glEnable(GL_ALPHA_TEST);
788 glAlphaFunc(GL_GREATER, 0.001);
789 } else {
790 glDisable(GL_BLEND);
791 glEnable(GL_ALPHA_TEST);
792 glAlphaFunc(GL_GREATER, 0.5);
793 }
794
795 GLfloat color[3];
796 GLdouble shade = PIN(static_cast<GLfloat>(RenderRectangle.ambient_shade)/static_cast<GLfloat>(FIXED_ONE),0,1);
797 color[0] = color[1] = color[2] = shade;
798 glColor4f(color[0], color[1], color[2], 1.0);
799
800 Shader *s = NULL;
801 bool canGlow = false;
802 switch(RenderRectangle.transfer_mode) {
803 case _static_transfer:
804 flare = -1;
805 s = Shader::get(renderStep == kGlow ? Shader::S_InvincibleBloom : Shader::S_Invincible);
806 s->enable();
807 break;
808 case _tinted_transfer:
809 flare = -1;
810 s = Shader::get(renderStep == kGlow ? Shader::S_InvisibleBloom : Shader::S_Invisible);
811 s->enable();
812 s->setFloat(Shader::U_Visibility, 1.0 - RenderRectangle.transfer_data/32.0f);
813 break;
814 case _solid_transfer:
815 glColor4f(0,1,0,1);
816 break;
817 case _textured_transfer:
818 if((RenderRectangle.flags&_SHADELESS_BIT) != 0) {
819 if (renderStep == kDiffuse) {
820 glColor4f(1,1,1,1);
821 } else {
822 glColor4f(0,0,0,1);
823 }
824 flare = -1;
825 } else {
826 canGlow = true;
827 }
828 break;
829 default:
830 glColor4f(0,0,1,1);
831 }
832
833 if(s == NULL) {
834 if(TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_BumpMap)) {
835 s = Shader::get(renderStep == kGlow ? Shader::S_BumpBloom : Shader::S_Bump);
836 } else {
837 s = Shader::get(renderStep == kGlow ? Shader::S_WallBloom : Shader::S_Wall);
838 }
839 s->enable();
840 }
841
842 if (renderStep == kGlow) {
843 s->setFloat(Shader::U_BloomScale, SkinPtr->BloomScale);
844 s->setFloat(Shader::U_BloomShift, SkinPtr->BloomShift);
845 }
846 s->setFloat(Shader::U_Flare, flare);
847 s->setFloat(Shader::U_SelfLuminosity, selfLuminosity);
848 s->setFloat(Shader::U_Wobble, 0);
849 s->setFloat(Shader::U_Depth, 0);
850 s->setFloat(Shader::U_Glow, 0);
851
852 glVertexPointer(3,GL_FLOAT,0,ModelPtr->Model.PosBase());
853 glClientActiveTextureARB(GL_TEXTURE0_ARB);
854 if (ModelPtr->Model.TxtrCoords.empty()) {
855 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
856 } else {
857 glTexCoordPointer(2,GL_FLOAT,0,ModelPtr->Model.TCBase());
858 }
859
860 glEnableClientState(GL_NORMAL_ARRAY);
861 glNormalPointer(GL_FLOAT,0,ModelPtr->Model.NormBase());
862
863 glClientActiveTextureARB(GL_TEXTURE1_ARB);
864 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
865 glTexCoordPointer(4,GL_FLOAT,sizeof(vec4),ModelPtr->Model.TangentBase());
866
867 if(ModelPtr->Use(CLUT,OGL_SkinManager::Normal)) {
868 LoadModelSkin(SkinPtr->NormalImg, Collection, CLUT);
869 }
870
871 if(TEST_FLAG(Get_OGL_ConfigureData().Flags, OGL_Flag_BumpMap)) {
872 glActiveTextureARB(GL_TEXTURE1_ARB);
873 if(ModelPtr->Use(CLUT,OGL_SkinManager::Bump)) {
874 LoadModelSkin(SkinPtr->OffsetImg, Collection, CLUT);
875 }
876 if (!SkinPtr->OffsetImg.IsPresent()) {
877 FlatBumpTexture();
878 }
879 glActiveTextureARB(GL_TEXTURE0_ARB);
880 }
881
882 glDrawElements(GL_TRIANGLES,(GLsizei)ModelPtr->Model.NumVI(),GL_UNSIGNED_SHORT,ModelPtr->Model.VIBase());
883
884 if (canGlow && SkinPtr->GlowImg.IsPresent()) {
885 glEnable(GL_BLEND);
886 setupBlendFunc(SkinPtr->GlowBlend);
887 glEnable(GL_ALPHA_TEST);
888 glAlphaFunc(GL_GREATER, 0.001);
889
890 s->enable();
891 s->setFloat(Shader::U_Glow, SkinPtr->MinGlowIntensity);
892 if (renderStep == kGlow) {
893 s->setFloat(Shader::U_BloomScale, SkinPtr->GlowBloomScale);
894 s->setFloat(Shader::U_BloomShift, SkinPtr->GlowBloomShift);
895 }
896
897 if(ModelPtr->Use(CLUT,OGL_SkinManager::Glowing)) {
898 LoadModelSkin(SkinPtr->GlowImg, Collection, CLUT);
899 }
900 glDrawElements(GL_TRIANGLES,(GLsizei)ModelPtr->Model.NumVI(),GL_UNSIGNED_SHORT,ModelPtr->Model.VIBase());
901 }
902
903 glDisableClientState(GL_NORMAL_ARRAY);
904 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
905 glClientActiveTextureARB(GL_TEXTURE0_ARB);
906 if (ModelPtr->Model.TxtrCoords.empty()) {
907 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
908 }
909
910 // Restore the default render sidedness
911 glEnable(GL_CULL_FACE);
912 glFrontFace(GL_CW);
913 Shader::disable();
914 return true;
915 }
916
render_node_object(render_object_data * object,bool other_side_of_media,RenderStep renderStep)917 void RenderRasterize_Shader::render_node_object(render_object_data *object, bool other_side_of_media, RenderStep renderStep) {
918
919 if (!object->clipping_windows)
920 return;
921
922 clipping_window_data *win;
923
924 // To properly handle sprites in media, we render above and below
925 // the media boundary in separate passes, just like the original
926 // software renderer.
927 short media_index = get_polygon_data(object->node->polygon_index)->media_index;
928 media_data *media = (media_index != NONE) ? get_media_data(media_index) : NULL;
929 if (media) {
930 float h = media->height;
931 GLdouble plane[] = { 0.0, 0.0, 1.0, -h };
932 if (view->under_media_boundary ^ other_side_of_media) {
933 plane[2] = -1.0;
934 plane[3] = h;
935 }
936 glClipPlane(GL_CLIP_PLANE5, plane);
937 glEnable(GL_CLIP_PLANE5);
938 } else if (other_side_of_media) {
939 // When there's no media present, we can skip the second pass.
940 return;
941 }
942
943 for (win = object->clipping_windows; win; win = win->next_window)
944 {
945 clip_to_window(win);
946 _render_node_object_helper(object, renderStep);
947 }
948
949 glDisable(GL_CLIP_PLANE5);
950 }
951
_render_node_object_helper(render_object_data * object,RenderStep renderStep)952 void RenderRasterize_Shader::_render_node_object_helper(render_object_data *object, RenderStep renderStep) {
953
954 rectangle_definition& rect = object->rectangle;
955 const world_point3d& pos = rect.Position;
956
957 if(rect.ModelPtr) {
958 glPushMatrix();
959 glTranslated(pos.x, pos.y, pos.z);
960 glRotated((360.0/FULL_CIRCLE)*rect.Azimuth,0,0,1);
961 GLfloat HorizScale = rect.Scale*rect.HorizScale;
962 glScalef(HorizScale,HorizScale,rect.Scale);
963
964 short descriptor = GET_DESCRIPTOR_COLLECTION(rect.ShapeDesc);
965 short collection = GET_COLLECTION(descriptor);
966 short clut = ModifyCLUT(rect.transfer_mode,GET_COLLECTION_CLUT(descriptor));
967
968 RenderModel(rect, collection, clut, weaponFlare, selfLuminosity, renderStep);
969 glPopMatrix();
970 return;
971 }
972
973 glPushMatrix();
974 glTranslated(pos.x, pos.y, pos.z);
975
976 double yaw = view->virtual_yaw * FixedAngleToDegrees;
977 glRotated(yaw, 0.0, 0.0, 1.0);
978
979 float offset = 0;
980 if (OGL_ForceSpriteDepth()) {
981 // look for parasitic objects based on y position,
982 // and offset them to draw in proper depth order
983 if(pos.y == objectY) {
984 objectCount++;
985 offset = objectCount * -1.0;
986 } else {
987 objectCount = 0;
988 objectY = pos.y;
989 }
990 } else {
991 glDisable(GL_DEPTH_TEST);
992 }
993
994 TextureManager TMgr = setupSpriteTexture(rect, OGL_Txtr_Inhabitant, offset, renderStep);
995 if (TMgr.ShapeDesc == UNONE) { glPopMatrix(); return; }
996
997 float texCoords[2][2];
998
999 if(rect.flip_vertical) {
1000 texCoords[0][1] = TMgr.U_Offset;
1001 texCoords[0][0] = TMgr.U_Scale+TMgr.U_Offset;
1002 } else {
1003 texCoords[0][0] = TMgr.U_Offset;
1004 texCoords[0][1] = TMgr.U_Scale+TMgr.U_Offset;
1005 }
1006
1007 if(rect.flip_horizontal) {
1008 texCoords[1][1] = TMgr.V_Offset;
1009 texCoords[1][0] = TMgr.V_Scale+TMgr.V_Offset;
1010 } else {
1011 texCoords[1][0] = TMgr.V_Offset;
1012 texCoords[1][1] = TMgr.V_Scale+TMgr.V_Offset;
1013 }
1014
1015 if(TMgr.IsBlended() || TMgr.TransferMode == _tinted_transfer) {
1016 glEnable(GL_BLEND);
1017 setupBlendFunc(TMgr.NormalBlend());
1018 glEnable(GL_ALPHA_TEST);
1019 glAlphaFunc(GL_GREATER, 0.001);
1020 } else {
1021 glDisable(GL_BLEND);
1022 glEnable(GL_ALPHA_TEST);
1023 glAlphaFunc(GL_GREATER, 0.5);
1024 }
1025
1026 GLfloat vertex_array[12] = {
1027 0,
1028 rect.WorldLeft * rect.HorizScale * rect.Scale,
1029 rect.WorldTop * rect.Scale,
1030 0,
1031 rect.WorldRight * rect.HorizScale * rect.Scale,
1032 rect.WorldTop * rect.Scale,
1033 0,
1034 rect.WorldRight * rect.HorizScale * rect.Scale,
1035 rect.WorldBottom * rect.Scale,
1036 0,
1037 rect.WorldLeft * rect.HorizScale * rect.Scale,
1038 rect.WorldBottom * rect.Scale
1039 };
1040
1041 GLfloat texcoord_array[8] = {
1042 texCoords[0][0],
1043 texCoords[1][0],
1044 texCoords[0][0],
1045 texCoords[1][1],
1046 texCoords[0][1],
1047 texCoords[1][1],
1048 texCoords[0][1],
1049 texCoords[1][0]
1050 };
1051
1052 glVertexPointer(3, GL_FLOAT, 0, vertex_array);
1053 glTexCoordPointer(2, GL_FLOAT, 0, texcoord_array);
1054
1055 glDrawArrays(GL_QUADS, 0, 4);
1056
1057 if (setupGlow(view, TMgr, 0, 1, weaponFlare, selfLuminosity, offset, renderStep)) {
1058 glDrawArrays(GL_QUADS, 0, 4);
1059 }
1060
1061 glEnable(GL_DEPTH_TEST);
1062 glPopMatrix();
1063 Shader::disable();
1064 TMgr.RestoreTextureMatrix();
1065 }
1066
1067 extern void position_sprite_axis(short *x0, short *x1, short scale_width, short screen_width, short positioning_mode, _fixed position, bool flip, world_distance world_left, world_distance world_right);
1068
1069 extern GLdouble Screen_2_Clip[16];
1070
render_viewer_sprite_layer(RenderStep renderStep)1071 void RenderRasterize_Shader::render_viewer_sprite_layer(RenderStep renderStep)
1072 {
1073 if (!view->show_weapons_in_hand) return;
1074
1075 glMatrixMode(GL_TEXTURE);
1076 glPushMatrix();
1077
1078 glMatrixMode(GL_PROJECTION);
1079 glPushMatrix();
1080 glLoadMatrixd(Screen_2_Clip);
1081
1082 glMatrixMode(GL_MODELVIEW);
1083 glPushMatrix();
1084 glLoadIdentity();
1085
1086 rectangle_definition rect;
1087 weapon_display_information display_data;
1088 shape_information_data *shape_information;
1089 short count;
1090
1091 rect.ModelPtr = nullptr;
1092 rect.Opacity = 1;
1093
1094 /* get_weapon_display_information() returns true if there is a weapon to be drawn. it
1095 should initially be passed a count of zero. it returns the weaponÕs texture and
1096 enough information to draw it correctly. */
1097 count= 0;
1098 while (get_weapon_display_information(&count, &display_data))
1099 {
1100 /* fetch relevant shape data */
1101 shape_information= extended_get_shape_information(display_data.collection, display_data.low_level_shape_index);
1102
1103 // Nonexistent frame: skip
1104 if (!shape_information) continue;
1105
1106 // LP change: for the convenience of the OpenGL renderer
1107 rect.ShapeDesc = BUILD_DESCRIPTOR(display_data.collection,0);
1108 rect.LowLevelShape = display_data.low_level_shape_index;
1109
1110 if (shape_information->flags&_X_MIRRORED_BIT) display_data.flip_horizontal= !display_data.flip_horizontal;
1111 if (shape_information->flags&_Y_MIRRORED_BIT) display_data.flip_vertical= !display_data.flip_vertical;
1112
1113 /* calculate shape rectangle */
1114 position_sprite_axis(&rect.x0, &rect.x1, view->screen_height, view->screen_width, display_data.horizontal_positioning_mode,
1115 display_data.horizontal_position, display_data.flip_horizontal, shape_information->world_left, shape_information->world_right);
1116 position_sprite_axis(&rect.y0, &rect.y1, view->screen_height, view->screen_height, display_data.vertical_positioning_mode,
1117 display_data.vertical_position, display_data.flip_vertical, -shape_information->world_top, -shape_information->world_bottom);
1118
1119 /* set rectangle bitmap and shading table */
1120 extended_get_shape_bitmap_and_shading_table(display_data.collection, display_data.low_level_shape_index, &rect.texture, &rect.shading_tables, view->shading_mode);
1121 if (!rect.texture) continue;
1122
1123 rect.flags= 0;
1124
1125 /* initialize clipping window to full screen */
1126 rect.clip_left= 0;
1127 rect.clip_right= view->screen_width;
1128 rect.clip_top= 0;
1129 rect.clip_bottom= view->screen_height;
1130
1131 /* copy mirror flags */
1132 rect.flip_horizontal= display_data.flip_horizontal;
1133 rect.flip_vertical= display_data.flip_vertical;
1134
1135 /* lighting: depth of zero in the cameraÕs polygon index */
1136 rect.depth= 0;
1137 rect.ambient_shade= get_light_intensity(get_polygon_data(view->origin_polygon_index)->floor_lightsource_index);
1138 rect.ambient_shade= MAX(shape_information->minimum_light_intensity, rect.ambient_shade);
1139 if (view->shading_mode==_shading_infravision) rect.flags|= _SHADELESS_BIT;
1140
1141 // Calculate the object's horizontal position
1142 // for the convenience of doing teleport-in/teleport-out
1143 rect.xc = (rect.x0 + rect.x1) >> 1;
1144
1145 /* make the weapon reflect the ownerÕs transfer mode */
1146 instantiate_rectangle_transfer_mode(view, &rect, display_data.transfer_mode, display_data.transfer_phase);
1147
1148 render_viewer_sprite(rect, renderStep);
1149 }
1150
1151 Shader::disable();
1152
1153 glPopMatrix();
1154
1155 glMatrixMode(GL_PROJECTION);
1156 glPopMatrix();
1157
1158 glMatrixMode(GL_TEXTURE);
1159 glPopMatrix();
1160
1161 glMatrixMode(GL_MODELVIEW);
1162 }
1163
1164 struct ExtendedVertexData
1165 {
1166 GLdouble Vertex[4];
1167 GLdouble TexCoord[2];
1168 GLfloat Color[3];
1169 GLfloat GlowColor[3];
1170 };
1171
render_viewer_sprite(rectangle_definition & RenderRectangle,RenderStep renderStep)1172 void RenderRasterize_Shader::render_viewer_sprite(rectangle_definition& RenderRectangle, RenderStep renderStep)
1173 {
1174 // Find texture coordinates
1175 ExtendedVertexData ExtendedVertexList[4];
1176
1177 point2d TopLeft, BottomRight;
1178 // Clipped corners:
1179 TopLeft.x = MAX(RenderRectangle.x0,RenderRectangle.clip_left);
1180 TopLeft.y = MAX(RenderRectangle.y0,RenderRectangle.clip_top);
1181 BottomRight.x = MIN(RenderRectangle.x1,RenderRectangle.clip_right);
1182 BottomRight.y = MIN(RenderRectangle.y1,RenderRectangle.clip_bottom);
1183
1184 // Screen coordinates; weapons-in-hand are in the foreground
1185 ExtendedVertexList[0].Vertex[0] = TopLeft.x;
1186 ExtendedVertexList[0].Vertex[1] = TopLeft.y;
1187 ExtendedVertexList[0].Vertex[2] = 1;
1188 ExtendedVertexList[2].Vertex[0] = BottomRight.x;
1189 ExtendedVertexList[2].Vertex[1] = BottomRight.y;
1190 ExtendedVertexList[2].Vertex[2] = 1;
1191
1192 // Completely clipped away?
1193 if (BottomRight.x <= TopLeft.x) return;
1194 if (BottomRight.y <= TopLeft.y) return;
1195
1196 // Use that texture
1197 auto TMgr = setupSpriteTexture(RenderRectangle, OGL_Txtr_WeaponsInHand, 0, renderStep);
1198
1199 // Calculate the texture coordinates;
1200 // the scanline direction is downward, (texture coordinate 0)
1201 // while the line-to-line direction is rightward (texture coordinate 1)
1202 GLdouble U_Scale = TMgr.U_Scale/(RenderRectangle.y1 - RenderRectangle.y0);
1203 GLdouble V_Scale = TMgr.V_Scale/(RenderRectangle.x1 - RenderRectangle.x0);
1204 GLdouble U_Offset = TMgr.U_Offset;
1205 GLdouble V_Offset = TMgr.V_Offset;
1206
1207 if (RenderRectangle.flip_vertical)
1208 {
1209 ExtendedVertexList[0].TexCoord[0] = U_Offset + U_Scale*(RenderRectangle.y1 - TopLeft.y);
1210 ExtendedVertexList[2].TexCoord[0] = U_Offset + U_Scale*(RenderRectangle.y1 - BottomRight.y);
1211 } else {
1212 ExtendedVertexList[0].TexCoord[0] = U_Offset + U_Scale*(TopLeft.y - RenderRectangle.y0);
1213 ExtendedVertexList[2].TexCoord[0] = U_Offset + U_Scale*(BottomRight.y - RenderRectangle.y0);
1214 }
1215 if (RenderRectangle.flip_horizontal)
1216 {
1217 ExtendedVertexList[0].TexCoord[1] = V_Offset + V_Scale*(RenderRectangle.x1 - TopLeft.x);
1218 ExtendedVertexList[2].TexCoord[1] = V_Offset + V_Scale*(RenderRectangle.x1 - BottomRight.x);
1219 } else {
1220 ExtendedVertexList[0].TexCoord[1] = V_Offset + V_Scale*(TopLeft.x - RenderRectangle.x0);
1221 ExtendedVertexList[2].TexCoord[1] = V_Offset + V_Scale*(BottomRight.x - RenderRectangle.x0);
1222 }
1223
1224 // Fill in remaining points
1225 // Be sure that the order gives a sidedness the same as
1226 // that of the world-geometry polygons
1227 ExtendedVertexList[1].Vertex[0] = ExtendedVertexList[2].Vertex[0];
1228 ExtendedVertexList[1].Vertex[1] = ExtendedVertexList[0].Vertex[1];
1229 ExtendedVertexList[1].Vertex[2] = ExtendedVertexList[0].Vertex[2];
1230 ExtendedVertexList[1].TexCoord[0] = ExtendedVertexList[0].TexCoord[0];
1231 ExtendedVertexList[1].TexCoord[1] = ExtendedVertexList[2].TexCoord[1];
1232 ExtendedVertexList[3].Vertex[0] = ExtendedVertexList[0].Vertex[0];
1233 ExtendedVertexList[3].Vertex[1] = ExtendedVertexList[2].Vertex[1];
1234 ExtendedVertexList[3].Vertex[2] = ExtendedVertexList[2].Vertex[2];
1235 ExtendedVertexList[3].TexCoord[0] = ExtendedVertexList[2].TexCoord[0];
1236 ExtendedVertexList[3].TexCoord[1] = ExtendedVertexList[0].TexCoord[1];
1237
1238 if(TMgr.IsBlended() || TMgr.TransferMode == _tinted_transfer) {
1239 glEnable(GL_BLEND);
1240 setupBlendFunc(TMgr.NormalBlend());
1241 glEnable(GL_ALPHA_TEST);
1242 glAlphaFunc(GL_GREATER, 0.001);
1243 } else {
1244 glDisable(GL_BLEND);
1245 glEnable(GL_ALPHA_TEST);
1246 glAlphaFunc(GL_GREATER, 0.5);
1247 }
1248
1249 glDisable(GL_DEPTH_TEST);
1250
1251 // Location of data:
1252 glVertexPointer(3,GL_DOUBLE,sizeof(ExtendedVertexData),ExtendedVertexList[0].Vertex);
1253 glTexCoordPointer(2,GL_DOUBLE,sizeof(ExtendedVertexData),ExtendedVertexList[0].TexCoord);
1254 glEnable(GL_TEXTURE_2D);
1255
1256 // Go!
1257 glDrawArrays(GL_POLYGON,0,4);
1258
1259 if (setupGlow(view, TMgr, 0, 1, weaponFlare, selfLuminosity, 0, renderStep)) {
1260 glDrawArrays(GL_QUADS, 0, 4);
1261 }
1262
1263 glEnable(GL_DEPTH_TEST);
1264 Shader::disable();
1265 TMgr.RestoreTextureMatrix();
1266
1267 }
1268