naev 0.11.5
nebula.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "naev.h"
13#include "nebula.h"
14
15#include "camera.h"
16#include "conf.h"
17#include "gui.h"
18#include "log.h"
19#include "menu.h"
20#include "opengl.h"
21#include "player.h"
22#include "rng.h"
23#include "spfx.h"
24#include "vec2.h"
25
26#define NEBULA_PUFF_BUFFER 300
28/* Nebula properties */
29static double nebu_hue = 0.;
30static double nebu_density = 0.;
31static double nebu_dx = 0.;
32static double nebu_view = 0.;
33static double nebu_dt = 0.;
34static double nebu_time = 0.;
36/* Nebula scaling stuff. */
37static double nebu_scale = 4.;
38static int nebu_dofbo = 0;
39static GLuint nebu_fbo = GL_INVALID_VALUE;
40static GLuint nebu_tex = GL_INVALID_VALUE;
41static GLfloat nebu_render_w= 0.;
42static GLfloat nebu_render_h= 0.;
43static mat4 nebu_render_P;
44
50typedef struct NebulaPuff_ {
52 double height;
53 double s;
54 double rx;
55 double ry;
57static NebulaPuff *nebu_puffs = NULL;
58static int nebu_npuffs = 0;
59static double puff_x = 0.;
60static double puff_y = 0.;
61
62/*
63 * prototypes
64 */
65/* Puffs. */
66static void nebu_renderPuffs( int below_player );
67/* Nebula render methods. */
68static void nebu_renderBackground( const double dt );
69static void nebu_blitFBO (void);
70
76int nebu_init (void)
77{
78 nebu_time = -1000.0 * RNGF();
79 return nebu_resize();
80}
81
87int nebu_resize (void)
88{
89 double scale;
90 GLfloat fbo_w, fbo_h;
91
92 scale = conf.nebu_scale * gl_screen.scale;
93 fbo_w = round(gl_screen.nw/scale);
94 fbo_h = round(gl_screen.nh/scale);
95 if (scale == nebu_scale && fbo_w == nebu_render_w && fbo_h == nebu_render_h)
96 return 0;
97
98 nebu_scale = scale;
99 nebu_render_w = fbo_w;
100 nebu_render_h = fbo_h;
101 nebu_dofbo = (nebu_scale != 1.);
102 glDeleteTextures( 1, &nebu_tex );
103 glDeleteFramebuffers( 1, &nebu_fbo );
104
105 if (nebu_dofbo)
106 gl_fboCreate( &nebu_fbo, &nebu_tex, nebu_render_w, nebu_render_h );
107
108 /* Set up the matrices. */
109 nebu_render_P = mat4_identity();
110 mat4_translate( &nebu_render_P, -nebu_render_w/2., -nebu_render_h/2., 0. );
111 mat4_scale( &nebu_render_P, nebu_render_w, nebu_render_h, 1. );
112 glUseProgram(shaders.nebula_background.program);
113 gl_uniformMat4(shaders.nebula_background.projection, &nebu_render_P);
114 glUseProgram(shaders.nebula.program);
115 gl_uniformMat4(shaders.nebula.projection, &nebu_render_P);
116 glUseProgram(0);
117
118 return 0;
119}
120
127{
128 return nebu_view;
129}
130
134void nebu_exit (void)
135{
136 if (nebu_dofbo) {
137 glDeleteFramebuffers( 1, &nebu_fbo );
138 glDeleteTextures( 1, &nebu_tex );
139 }
140}
141
147void nebu_render( const double dt )
148{
150 nebu_renderPuffs( 1 );
151}
152
158static void nebu_renderBackground( const double dt )
159{
160 /* calculate frame to draw */
161 nebu_time += dt * nebu_dt;
162
163 if (nebu_dofbo) {
164 glBindFramebuffer(GL_FRAMEBUFFER, nebu_fbo);
165 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
166 }
167
168 /* Start the program. */
169 glUseProgram(shaders.nebula_background.program);
170
171 /* Set shader uniforms. */
172 glUniform1f(shaders.nebula_background.eddy_scale, nebu_view * cam_getZoom() / nebu_scale);
173 glUniform1f(shaders.nebula_background.time, nebu_time);
174 glUniform1f(shaders.nebula_background.nonuniformity, conf.nebu_nonuniformity);
175
176 /* Draw. */
177 glEnableVertexAttribArray( shaders.nebula_background.vertex );
178 gl_vboActivateAttribOffset( gl_squareVBO, shaders.nebula_background.vertex, 0, 2, GL_FLOAT, 0 );
179 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
180 nebu_blitFBO();
181
182 /* Clean up. */
183 glDisableVertexAttribArray( shaders.nebula_background.vertex );
184 glUseProgram(0);
185 gl_checkErr();
186}
187
191static void nebu_blitFBO (void)
192{
193 if (!nebu_dofbo)
194 return;
195
196 glBindFramebuffer(GL_FRAMEBUFFER, gl_screen.current_fbo);
197
198 glUseProgram(shaders.texture.program);
199
200 glBindTexture( GL_TEXTURE_2D, nebu_tex );
201
202 glEnableVertexAttribArray( shaders.texture.vertex );
203 gl_vboActivateAttribOffset( gl_squareVBO, shaders.texture.vertex,
204 0, 2, GL_FLOAT, 0 );
205
206 /* Set shader uniforms. */
207 gl_uniformColour(shaders.texture.colour, &cWhite);
208
209 const mat4 ortho = mat4_ortho(0, 1, 0, 1, 1, -1);
210 const mat4 I = mat4_identity();
211 gl_uniformMat4( shaders.texture.projection, &ortho );
212 gl_uniformMat4( shaders.texture.tex_mat, &I );
213
214 /* Draw. */
215 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
216
217 /* Clear state. */
218 glDisableVertexAttribArray( shaders.texture.vertex );
219}
220
224void nebu_update( double dt )
225{
226 (void) dt;
227 double mod = 1.;
228 double bonus = 0.;
229
230 if (player.p != NULL) {
231 mod = player.p->stats.ew_detect;
232 bonus = player.p->stats.nebu_visibility;
233 }
234
235 /* At density 1200 you have zero visibility. */
236 nebu_view = (1200. - nebu_density) * mod + bonus;
237
238 /* Below only care if not simulating. */
239 if (space_isSimulation())
240 return;
241
242 /* Update puffs. */
243 for (int i=0; i<nebu_npuffs; i++) {
244 double dx, dy;
245 NebulaPuff *puff = &nebu_puffs[i];
246
247 /* Get camera stuff. */
248 cam_getDPos( &dx, &dy );
249
250 /* Calculate new position */
251 puff->pos.x -= dx * puff->height;
252 puff->pos.y -= dy * puff->height;
253
254 /* Check boundaries */
255 if (puff->pos.x > SCREEN_W + NEBULA_PUFF_BUFFER)
256 puff->pos.x -= SCREEN_W + 2.*NEBULA_PUFF_BUFFER;
257 else if (puff->pos.y > SCREEN_H + NEBULA_PUFF_BUFFER)
258 puff->pos.y -= SCREEN_H + 2.*NEBULA_PUFF_BUFFER;
259 else if (puff->pos.x < -NEBULA_PUFF_BUFFER)
260 puff->pos.x += SCREEN_W + 2.*NEBULA_PUFF_BUFFER;
261 else if (puff->pos.y < -NEBULA_PUFF_BUFFER)
262 puff->pos.y += SCREEN_H + 2.*NEBULA_PUFF_BUFFER;
263 }
264}
265
271void nebu_renderOverlay( const double dt )
272{
273 (void) dt;
274 double gx, gy, z;
275
276 /* Get GUI offsets. */
277 gui_getOffset( &gx, &gy );
278
279 /* Get zoom. */
280 z = cam_getZoom();
281
282 /*
283 * Renders the puffs
284 */
285 nebu_renderPuffs( 0 );
286
287 /* Prepare the matrix */
288 if (nebu_dofbo) {
289 glBindFramebuffer(GL_FRAMEBUFFER, nebu_fbo);
290 glClearColor( 0., 0., 0., 0. );
291 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
292 }
293
294 /* Start the program. */
295 glUseProgram(shaders.nebula.program);
296
297 /* Set shader uniforms. */
298 glUniform1f(shaders.nebula.horizon, nebu_view * z / nebu_scale);
299 glUniform1f(shaders.nebula.eddy_scale, nebu_dx * z / nebu_scale);
300 glUniform1f(shaders.nebula.time, nebu_time);
301 glUniform1f(shaders.nebula.nonuniformity, conf.nebu_nonuniformity);
302
303 /* Draw. */
304 glEnableVertexAttribArray(shaders.nebula.vertex);
305 gl_vboActivateAttribOffset( gl_squareVBO, shaders.nebula.vertex, 0, 2, GL_FLOAT, 0 );
306 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
307 nebu_blitFBO();
308
309 /* Clean up. */
310 glDisableVertexAttribArray( shaders.nebula.vertex );
311 glClearColor( 0., 0., 0., 1. );
312 glUseProgram(0);
313 gl_checkErr();
314
315 /* Reset puff movement. */
316 puff_x = 0.;
317 puff_y = 0.;
318}
319
325static void nebu_renderPuffs( int below_player )
326{
327 /* Main menu shouldn't have puffs */
329 return;
330
331 for (int i=0; i<nebu_npuffs; i++) {
332 double x, y, s;
333 mat4 projection;
334 NebulaPuff *puff = &nebu_puffs[i];
335
336 /* Separate by layers */
337 if ((!below_player && (puff->height < 1.)) ||
338 (below_player && (puff->height > 1.)))
339 continue;
340
341 /* Set up variables and do quick visibility check. */
342 /* TODO this is weird in the sense that size gets scaled, but position doesn't with zoom... Probably should be harmonized... */
343 s = puff->s * cam_getZoom();
344 x = puff->pos.x - NEBULA_PUFF_BUFFER - s;
345 y = puff->pos.y - NEBULA_PUFF_BUFFER - s;
346 if ((x < -s) || (x > SCREEN_W+s) ||
347 (y < -s) || (y > SCREEN_H+s))
348 continue;
349
350 /* Render */
351 glUseProgram( shaders.nebula_puff.program );
352
353 projection = gl_view_matrix;
354 mat4_translate( &projection, x, y, 0. );
355 mat4_scale( &projection, s, s, 1. );
356 glEnableVertexAttribArray(shaders.nebula_puff.vertex);
357 gl_vboActivateAttribOffset( gl_circleVBO, shaders.nebula_puff.vertex, 0, 2, GL_FLOAT, 0 );
358
359 /* Uniforms. */
360 gl_uniformMat4( shaders.nebula_puff.projection, &projection );
361 glUniform1f( shaders.nebula_puff.time, nebu_time / 1.5 );
362 glUniform2f( shaders.nebula_puff.r, puff->rx, puff->ry );
363
364 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
365
366 glDisableVertexAttribArray(shaders.nebula_puff.vertex);
367 glUseProgram(0);
368 gl_checkErr();
369 }
370}
371
379void nebu_prep( double density, double volatility, double hue )
380{
381 glColour col;
382
383 /* Set the hue. */
384 nebu_hue = hue;
385 glUseProgram(shaders.nebula.program);
386 glUniform1f(shaders.nebula.hue, nebu_hue);
387 glUseProgram(shaders.nebula_background.program);
388 glUniform1f(shaders.nebula_background.hue, nebu_hue);
389 glUniform1f(shaders.nebula_background.volatility, volatility);
390
391 /* Also set the hue for trails */
392 col_hsv2rgb( &col, nebu_hue*360., 0.7, 1.0 );
393 glUseProgram(shaders.trail.program);
394 glUniform3f( shaders.trail.nebu_col, col.r, col.g, col.b );
395
396 /* Also set the hue for puffs. */
397 col_hsv2rgb( &col, nebu_hue*360., 0.95, 1.0 );
398 glUseProgram(shaders.nebula_puff.program);
399 glUniform3f( shaders.nebula_puff.nebu_col, col.r, col.g, col.b );
400
401 /* Done setting shaders. */
402 glUseProgram(0);
403
404 /* Set density parameters. */
405 nebu_density = density;
406 nebu_update( 0. );
407 nebu_dt = (2.*density + 200.) / 10e3; /* Faster at higher density */
408 nebu_dx = 15e3 / pow(density, 1./3.); /* Closer at higher density */
409 nebu_time = 0.;
410
411 nebu_npuffs = density/2.;
412 nebu_puffs = realloc(nebu_puffs, sizeof(NebulaPuff)*nebu_npuffs);
413 for (int i=0; i<nebu_npuffs; i++) {
414 NebulaPuff *np = &nebu_puffs[i];
415
416 /* Position */
417 np->pos.x = (SCREEN_W+2.*NEBULA_PUFF_BUFFER)*RNGF();
418 np->pos.y = (SCREEN_H+2.*NEBULA_PUFF_BUFFER)*RNGF();
419
420 /* Maybe make size related? */
421 np->s = RNG(10,32);
422 np->height = RNGF() + 0.2;
423
424 /* Seed. */
425 np->rx = RNGF()*2000.-1000.;
426 np->ry = RNGF()*2000.-1000.;
427 }
428}
void cam_getDPos(double *dx, double *dy)
Gets the camera position differential (change in last frame).
Definition camera.c:127
double cam_getZoom(void)
Gets the camera zoom.
Definition camera.c:97
void col_hsv2rgb(glColour *c, float h, float s, float v)
Changes colour space from HSV to RGB.
Definition colour.c:65
void gui_getOffset(double *x, double *y)
Gets the GUI offset.
Definition gui.c:2062
void mat4_translate(mat4 *m, double x, double y, double z)
Translates a homogenous transformation matrix.
Definition mat4.c:99
mat4 mat4_identity(void)
Creates an identity matrix.
Definition mat4.c:195
void mat4_scale(mat4 *m, double x, double y, double z)
Scales a homogeneous transformation matrix.
Definition mat4.c:82
mat4 mat4_ortho(double left, double right, double bottom, double top, double nearVal, double farVal)
Creates an orthographic projection matrix.
Definition mat4.c:209
Handles the important game menus.
#define MENU_MAIN
Definition menu.h:9
#define menu_isOpen(f)
Definition menu.h:16
Header file with generic functions and naev-specifics.
void nebu_update(double dt)
Updates visibility and stuff.
Definition nebula.c:224
void nebu_exit(void)
Cleans up the nebu subsystem.
Definition nebula.c:134
static NebulaPuff * nebu_puffs
Definition nebula.c:57
int nebu_resize(void)
Handles a screen s.
Definition nebula.c:87
static double nebu_time
Definition nebula.c:34
#define NEBULA_PUFF_BUFFER
Definition nebula.c:26
static void nebu_renderPuffs(int below_player)
Renders the puffs.
Definition nebula.c:325
void nebu_renderOverlay(const double dt)
Renders the nebula overlay (hides what player can't see).
Definition nebula.c:271
double nebu_getSightRadius(void)
Gets the nebula view radius.
Definition nebula.c:126
void nebu_render(const double dt)
Renders the nebula.
Definition nebula.c:147
static void nebu_blitFBO(void)
If we're drawing the nebula buffered, copy to the screen.
Definition nebula.c:191
static double nebu_density
Definition nebula.c:30
static double nebu_dx
Definition nebula.c:31
void nebu_prep(double density, double volatility, double hue)
Prepares the nebualae to be rendered.
Definition nebula.c:379
static double nebu_hue
Definition nebula.c:29
static double nebu_scale
Definition nebula.c:37
int nebu_init(void)
Initializes the nebula.
Definition nebula.c:76
static int nebu_npuffs
Definition nebula.c:58
static void nebu_renderBackground(const double dt)
Renders the nebula using the multitexture approach.
Definition nebula.c:158
static double nebu_dt
Definition nebula.c:33
static double nebu_view
Definition nebula.c:32
glInfo gl_screen
Definition opengl.c:51
int gl_fboCreate(GLuint *fbo, GLuint *tex, GLsizei width, GLsizei height)
Creates a framebuffer and its associated texture.
Definition opengl_tex.c:252
void gl_vboActivateAttribOffset(gl_vbo *vbo, GLuint index, GLuint offset, GLint size, GLenum type, GLsizei stride)
Activates a VBO's offset.
Definition opengl_vbo.c:226
Player_t player
Definition player.c:74
int space_isSimulation(void)
returns whether we're just simulating.
Definition space.c:1530
Represents a nebula puff.
Definition nebula.c:50
vec2 pos
Definition nebula.c:51
double ry
Definition nebula.c:55
double rx
Definition nebula.c:54
double height
Definition nebula.c:52
double s
Definition nebula.c:53
ShipStats stats
Definition pilot.h:294
double nebu_scale
Definition conf.h:90
double nebu_nonuniformity
Definition conf.h:99
Pilot * p
Definition player.h:101
double ew_detect
Definition shipstats.h:244
double nebu_visibility
Definition shipstats.h:297
double scale
Definition opengl.h:52
int nw
Definition opengl.h:47
int nh
Definition opengl.h:48
GLuint current_fbo
Definition opengl.h:70
Definition mat4.h:10
Represents a 2d vector.
Definition vec2.h:32
double y
Definition vec2.h:34
double x
Definition vec2.h:33