1 /*
2  *  Rasterizer_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 "Rasterizer_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_FBO.h"
22 #include "OGL_Textures.h"
23 #include "OGL_Shader.h"
24 #include "ChaseCam.h"
25 #include "preferences.h"
26 #include "fades.h"
27 #include "screen.h"
28 
29 #define MAXIMUM_VERTICES_PER_WORLD_POLYGON (MAXIMUM_VERTICES_PER_POLYGON+4)
30 
31 const float FixedAngleToDegrees = 360.0/(float(FIXED_ONE)*float(FULL_CIRCLE));
32 
33 const GLdouble kViewBaseMatrix[16] = {
34 	0,	0,	-1,	0,
35 	1,	0,	0,	0,
36 	0,	1,	0,	0,
37 	0,	0,	0,	1
38 };
39 
40 const GLdouble kViewBaseMatrixInverse[16] = {
41 	0,	1,	0,	0,
42 	0,	0,	1,	0,
43 	-1,	0,	0,	0,
44 	0,	0,	0,	1
45 };
46 
47 Rasterizer_Shader_Class::Rasterizer_Shader_Class() = default;
48 Rasterizer_Shader_Class::~Rasterizer_Shader_Class() = default;
49 
SetView(view_data & view)50 void Rasterizer_Shader_Class::SetView(view_data& view) {
51 	OGL_SetView(view);
52 
53 	if (view.screen_width != view_width || view.screen_height != view_height) {
54 		view_width = view.screen_width;
55 		view_height = view.screen_height;
56 		swapper.reset();
57 		swapper.reset(new FBOSwapper(view_width * MainScreenPixelScale(), view_height * MainScreenPixelScale(), false));
58 	}
59 
60 	float aspect = view.screen_width / float(view.screen_height);
61 	float deg2rad = 8.0 * atan(1.0) / 360.0;
62 	float xtan, ytan;
63 	if (View_FOV_FixHorizontalNotVertical()) {
64 		xtan = tan(view.field_of_view * deg2rad / 2.0);
65 		ytan = xtan / aspect;
66 	} else {
67 		ytan = tan(view.field_of_view * deg2rad / 2.0) / 2.0;
68 		xtan = ytan * aspect;
69 	}
70 
71 	// Adjust for view distortion during teleport effect
72 	ytan *= view.real_world_to_screen_y / double(view.world_to_screen_y);
73 	xtan *= view.real_world_to_screen_x / double(view.world_to_screen_x);
74 
75 	double yaw = view.virtual_yaw * FixedAngleToDegrees;
76 	double pitch = view.virtual_pitch * FixedAngleToDegrees;
77 	pitch = (pitch > 180.0 ? pitch - 360.0 : pitch);
78 
79 	glMatrixMode(GL_PROJECTION);
80 	glLoadIdentity();
81 	float nearVal = 64.0;
82 	float farVal = 128.0 * 1024.0;
83 	float x = xtan * nearVal;
84 	float y = ytan * nearVal;
85 	float yoff = 0.0;
86 	if (view.mimic_sw_perspective)
87 		yoff = y * tan(pitch * M_PI/360.0) * 4.8;
88 	glFrustum(-x, x, -y + yoff, y + yoff, nearVal, farVal);
89 
90 	glMatrixMode(GL_MODELVIEW);
91 
92 	// setup a rotation matrix for the landscape texture shader
93 	// this aligns the landscapes to the center of the screen for standard
94 	// pitch ranges, so that they don't need to be stretched
95 
96 	glLoadIdentity();
97 	glTranslated(view.origin.x, view.origin.y, view.origin.z);
98 	glRotated(yaw, 0.0, 0.0, 1.0);
99 	glRotated(-pitch, 0.0, 1.0, 0.0);
100 	glMultMatrixd(kViewBaseMatrixInverse);
101 
102 	GLfloat landscapeInverseMatrix[16];
103 	glGetFloatv(GL_MODELVIEW_MATRIX, landscapeInverseMatrix);
104 
105 	Shader *s;
106 
107 	s = Shader::get(Shader::S_Landscape);
108 	s->enable();
109 	s->setMatrix4(Shader::U_LandscapeInverseMatrix, landscapeInverseMatrix);
110 
111 	s = Shader::get(Shader::S_LandscapeBloom);
112 	s->enable();
113 	s->setMatrix4(Shader::U_LandscapeInverseMatrix, landscapeInverseMatrix);
114 
115 	Shader::disable();
116 
117 	// setup the normal view matrix
118 
119 	glLoadMatrixd(kViewBaseMatrix);
120 	if (!view.mimic_sw_perspective)
121 		glRotated(pitch, 0.0, 1.0, 0.0);
122 //	apperently 'roll' is not what i think it is
123 //	rubicon sets it to some strange value
124 //	double roll = view.roll * 360.0 / float(NUMBER_OF_ANGLES);
125 //	glRotated(roll, 1.0, 0.0, 0.0);
126 	glRotated(-yaw, 0.0, 0.0, 1.0);
127 	glTranslated(-view.origin.x, -view.origin.y, -view.origin.z);
128 }
129 
setupGL()130 void Rasterizer_Shader_Class::setupGL()
131 {
132 	view_width = 0;
133 	view_height = 0;
134 	swapper.reset();
135 
136 	smear_the_void = false;
137 	OGL_ConfigureData& ConfigureData = Get_OGL_ConfigureData();
138 	if (!TEST_FLAG(ConfigureData.Flags,OGL_Flag_VoidColor))
139 		smear_the_void = true;
140 }
141 
Begin()142 void Rasterizer_Shader_Class::Begin()
143 {
144 	Rasterizer_OGL_Class::Begin();
145 	swapper->activate();
146 	if (smear_the_void)
147 		swapper->current_contents().draw_full();
148 }
149 
End()150 void Rasterizer_Shader_Class::End()
151 {
152 	swapper->deactivate();
153 	swapper->swap();
154 
155 	float gamma_adj = get_actual_gamma_adjust(graphics_preferences->screen_mode.gamma_level);
156 	if (gamma_adj < 0.99f || gamma_adj > 1.01f) {
157 		Shader *s = Shader::get(Shader::S_Gamma);
158 		s->enable();
159 		s->setFloat(Shader::U_GammaAdjust, gamma_adj);
160 	}
161 	swapper->draw();
162 	Shader::disable();
163 
164 	SetForeground();
165 	glColor3f(0, 0, 0);
166 	OGL_RenderFrame(0, 0, view_width, view_height, 1);
167 
168 	Rasterizer_OGL_Class::End();
169 }
170 
171