naev 0.12.5
nebula.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
9
10#include "nebula.h"
11
12#include "camera.h"
13#include "conf.h"
14#include "gui.h"
15#include "menu.h"
16#include "ntracing.h"
17#include "opengl.h"
18#include "player.h"
19#include "rng.h"
20#include "vec2.h"
21
22#define NEBULA_PUFF_BUFFER 300
23
24/* Nebula properties */
25static double nebu_hue = 0.;
26static double nebu_density = 0.;
27static double nebu_dx =
28 0.;
29static double nebu_view = 0.;
30static double nebu_dt = 0.;
31static double nebu_time = 0.;
32
33/* Nebula scaling stuff. */
34static double nebu_scale = 4.;
35static int nebu_dofbo = 0;
36static GLuint nebu_fbo = GL_INVALID_VALUE;
37static GLuint nebu_tex = GL_INVALID_VALUE;
38static GLfloat nebu_render_w = 0.;
39static GLfloat nebu_render_h = 0.;
40static mat4 nebu_render_P;
41
47typedef struct NebulaPuff_ {
49 double height;
50 double s;
51 double rx;
52 double ry;
54static NebulaPuff *nebu_puffs = NULL;
55static int nebu_npuffs = 0;
56static double puff_x = 0.;
57static double puff_y = 0.;
58
59/*
60 * prototypes
61 */
62/* Puffs. */
63static void nebu_renderPuffs( int below_player );
64/* Nebula render methods. */
65static void nebu_renderBackground( const double dt );
66static void nebu_blitFBO( void );
67
73int nebu_init( void )
74{
75 nebu_time = -1000.0 * RNGF();
76 return nebu_resize();
77}
78
84int nebu_resize( void )
85{
86 double scale;
87 GLfloat fbo_w, fbo_h;
88
89 scale = conf.nebu_scale * gl_screen.scale;
90 fbo_w = round( gl_screen.nw / scale );
91 fbo_h = round( gl_screen.nh / scale );
92 if ( scale == nebu_scale && fbo_w == nebu_render_w &&
93 fbo_h == nebu_render_h )
94 return 0;
95
96 nebu_scale = scale;
97 nebu_render_w = fbo_w;
98 nebu_render_h = fbo_h;
99 nebu_dofbo = ( nebu_scale != 1. );
100 glDeleteTextures( 1, &nebu_tex );
101 glDeleteFramebuffers( 1, &nebu_fbo );
102
103 if ( nebu_dofbo )
104 gl_fboCreate( &nebu_fbo, &nebu_tex, nebu_render_w, nebu_render_h );
105
106 /* Set up the matrices. */
107 nebu_render_P = mat4_identity();
108 mat4_translate_scale_xy( &nebu_render_P, -nebu_render_w / 2.,
109 -nebu_render_h / 2., nebu_render_w, nebu_render_h );
110 glUseProgram( shaders.nebula_background.program );
111 gl_uniformMat4( shaders.nebula_background.projection, &nebu_render_P );
112 glUseProgram( shaders.nebula.program );
113 gl_uniformMat4( shaders.nebula.projection, &nebu_render_P );
114 glUseProgram( 0 );
115
116 return 0;
117}
118
125{
126 return nebu_view;
127}
128
132void nebu_exit( void )
133{
134 if ( nebu_dofbo ) {
135 glDeleteFramebuffers( 1, &nebu_fbo );
136 glDeleteTextures( 1, &nebu_tex );
137 }
138}
139
145void nebu_render( const double dt )
146{
147 NTracingZone( _ctx, 1 );
148
150 nebu_renderPuffs( 1 );
151
152 NTracingZoneEnd( _ctx );
153}
154
160static void nebu_renderBackground( const double dt )
161{
162 /* calculate frame to draw */
163 nebu_time += dt * nebu_dt;
164
165 if ( nebu_dofbo ) {
166 glBindFramebuffer( GL_FRAMEBUFFER, nebu_fbo );
167 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
168 }
169
170 /* Start the program. */
171 glUseProgram( shaders.nebula_background.program );
172
173 /* Set shader uniforms. */
174 glUniform1f( shaders.nebula_background.eddy_scale,
176 glUniform1f( shaders.nebula_background.time, nebu_time );
177 glUniform1f( shaders.nebula_background.nonuniformity,
178 conf.nebu_nonuniformity );
179
180 /* Draw. */
181 glEnableVertexAttribArray( shaders.nebula_background.vertex );
182 gl_vboActivateAttribOffset( gl_squareVBO, shaders.nebula_background.vertex,
183 0, 2, GL_FLOAT, 0 );
184 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
185 nebu_blitFBO();
186
187 /* Clean up. */
188 glDisableVertexAttribArray( shaders.nebula_background.vertex );
189 glUseProgram( 0 );
190 gl_checkErr();
191}
192
196static void nebu_blitFBO( void )
197{
198 if ( !nebu_dofbo )
199 return;
200
201 glBindFramebuffer( GL_FRAMEBUFFER, gl_screen.current_fbo );
202 const mat4 ortho = mat4_ortho( 0, 1, 0, 1, 1, -1 );
203 const mat4 I = mat4_identity();
204 gl_renderTextureRawH( nebu_tex, &ortho, &I, &cWhite );
205}
206
210void nebu_update( double dt )
211{
212 (void)dt;
213 double mod = 1.;
214 double bonus = 0.;
215
216 if ( player.p != NULL ) {
217 mod = player.p->stats.ew_detect;
218 bonus = player.p->stats.nebu_visibility;
219 }
220
221 /* At 1600. density you have zero visibility. */
222 nebu_view = ( 1600. - nebu_density ) * mod + bonus;
223
224 /* Below only care if not simulating. */
225 if ( space_isSimulation() )
226 return;
227
228 /* Update puffs. */
229 for ( int i = 0; i < nebu_npuffs; i++ ) {
230 double dx, dy;
231 NebulaPuff *puff = &nebu_puffs[i];
232
233 /* Get camera stuff. */
234 cam_getDPos( &dx, &dy );
235
236 /* Calculate new position */
237 puff->pos.x -= dx * puff->height;
238 puff->pos.y -= dy * puff->height;
239
240 /* Check boundaries */
241 if ( puff->pos.x > SCREEN_W + NEBULA_PUFF_BUFFER )
242 puff->pos.x -= SCREEN_W + 2. * NEBULA_PUFF_BUFFER;
243 else if ( puff->pos.y > SCREEN_H + NEBULA_PUFF_BUFFER )
244 puff->pos.y -= SCREEN_H + 2. * NEBULA_PUFF_BUFFER;
245 else if ( puff->pos.x < -NEBULA_PUFF_BUFFER )
246 puff->pos.x += SCREEN_W + 2. * NEBULA_PUFF_BUFFER;
247 else if ( puff->pos.y < -NEBULA_PUFF_BUFFER )
248 puff->pos.y += SCREEN_H + 2. * NEBULA_PUFF_BUFFER;
249 }
250}
251
257void nebu_renderOverlay( const double dt )
258{
259 (void)dt;
260 double gx, gy, z;
261
262 NTracingZone( _ctx, 1 );
263
264 /* Get GUI offsets. */
265 gui_getOffset( &gx, &gy );
266
267 /* Get zoom. */
268 z = cam_getZoom();
269
270 /*
271 * Renders the puffs
272 */
273 nebu_renderPuffs( 0 );
274
275 /* Prepare the matrix */
276 if ( nebu_dofbo ) {
277 glBindFramebuffer( GL_FRAMEBUFFER, nebu_fbo );
278 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
279 }
280
281 /* Start the program. */
282 glUseProgram( shaders.nebula.program );
283
284 /* Set shader uniforms. */
285 glUniform1f( shaders.nebula.horizon, nebu_view * z / nebu_scale );
286 glUniform1f( shaders.nebula.eddy_scale, nebu_dx * z / nebu_scale );
287 glUniform1f( shaders.nebula.time, nebu_time );
288 glUniform1f( shaders.nebula.nonuniformity, conf.nebu_nonuniformity );
289
290 /* Draw. */
291 glEnableVertexAttribArray( shaders.nebula.vertex );
292 gl_vboActivateAttribOffset( gl_squareVBO, shaders.nebula.vertex, 0, 2,
293 GL_FLOAT, 0 );
294 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
295 nebu_blitFBO();
296
297 /* Clean up. */
298 glDisableVertexAttribArray( shaders.nebula.vertex );
299 glUseProgram( 0 );
300 gl_checkErr();
301
302 /* Reset puff movement. */
303 puff_x = 0.;
304 puff_y = 0.;
305
306 NTracingZoneEnd( _ctx );
307}
308
314static void nebu_renderPuffs( int below_player )
315{
316 /* Main menu shouldn't have puffs */
317 if ( menu_isOpen( MENU_MAIN ) )
318 return;
319
320 for ( int i = 0; i < nebu_npuffs; i++ ) {
321 double x, y, s;
322 mat4 projection;
323 NebulaPuff *puff = &nebu_puffs[i];
324
325 /* Separate by layers */
326 if ( ( !below_player && ( puff->height < 1. ) ) ||
327 ( below_player && ( puff->height > 1. ) ) )
328 continue;
329
330 /* Set up variables and do quick visibility check. */
331 /* TODO this is weird in the sense that size gets scaled, but position
332 * doesn't with zoom... Probably should be harmonized... */
333 s = puff->s * cam_getZoom();
334 x = puff->pos.x - NEBULA_PUFF_BUFFER - s;
335 y = puff->pos.y - NEBULA_PUFF_BUFFER - s;
336 if ( ( x < -s ) || ( x > SCREEN_W + s ) || ( y < -s ) ||
337 ( y > SCREEN_H + s ) )
338 continue;
339
340 /* Render */
341 glUseProgram( shaders.nebula_puff.program );
342
343 projection = gl_view_matrix;
344 mat4_translate_scale_xy( &projection, x, y, s, s );
345 glEnableVertexAttribArray( shaders.nebula_puff.vertex );
346 gl_vboActivateAttribOffset( gl_circleVBO, shaders.nebula_puff.vertex, 0,
347 2, GL_FLOAT, 0 );
348
349 /* Uniforms. */
350 gl_uniformMat4( shaders.nebula_puff.projection, &projection );
351 glUniform1f( shaders.nebula_puff.time, nebu_time / 1.5 );
352 glUniform2f( shaders.nebula_puff.r, puff->rx, puff->ry );
353
354 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
355
356 glDisableVertexAttribArray( shaders.nebula_puff.vertex );
357 glUseProgram( 0 );
358 gl_checkErr();
359 }
360}
361
362void nebu_updateColour( void )
363{
364 glColour col;
365 double saturation = conf.nebu_saturation;
366 double value = conf.nebu_saturation * 0.5 + 0.5;
367
368 glUseProgram( shaders.nebula.program );
369 glUniform1f( shaders.nebula.saturation, conf.nebu_saturation );
370 glUseProgram( shaders.nebula_background.program );
371 glUniform1f( shaders.nebula_background.saturation, conf.nebu_saturation );
372
373 /* Set up ambient colour. */
374 col_hsv2rgb( &col, nebu_hue * 360., saturation, value );
375 gltf_lightAmbient( 3.0 * col.r, 3.0 * col.g, 3.0 * col.b );
376 gltf_lightIntensity( 0.5 );
377
378 /* Also set the hue for trails */
379 col_hsv2rgb( &col, nebu_hue * 360., 0.7 * conf.nebu_saturation, value );
380 spfx_setNebulaColour( col.r, col.g, col.b );
381
382 /* Also set the hue for puffs. */
383 col_hsv2rgb( &col, nebu_hue * 360., 0.95 * conf.nebu_saturation, value );
384 glUseProgram( shaders.nebula_puff.program );
385 glUniform3f( shaders.nebula_puff.nebu_col, col.r, col.g, col.b );
386
387 glUseProgram( 0 );
388}
389
397void nebu_prep( double density, double volatility, double hue )
398{
399 NTracingZone( _ctx, 1 );
400
401 /* Set the hue. */
402 nebu_hue = hue;
403 glUseProgram( shaders.nebula.program );
404 glUniform1f( shaders.nebula.hue, nebu_hue );
405 glUseProgram( shaders.nebula_background.program );
406 glUniform1f( shaders.nebula_background.hue, nebu_hue );
407 glUniform1f( shaders.nebula_background.volatility, volatility );
408
409 /* Update the colour. */
410 nebu_updateColour();
411
412 if ( density > 0. ) {
413 /* Set density parameters. */
414 nebu_density = density;
415 nebu_update( 0. );
416 nebu_dt = ( 2. * density + 200. ) / 10e3; /* Faster at higher density */
417 nebu_dx = 15e3 / pow( density, 1. / 3. ); /* Closer at higher density */
418 nebu_time = 0.;
419
420 nebu_npuffs = density / 2.;
421 nebu_puffs = realloc( nebu_puffs, sizeof( NebulaPuff ) * nebu_npuffs );
422 for ( int i = 0; i < nebu_npuffs; i++ ) {
423 NebulaPuff *np = &nebu_puffs[i];
424
425 /* Position */
426 np->pos.x = ( SCREEN_W + 2. * NEBULA_PUFF_BUFFER ) * RNGF();
427 np->pos.y = ( SCREEN_H + 2. * NEBULA_PUFF_BUFFER ) * RNGF();
428
429 /* Maybe make size related? */
430 np->s = RNG( 10, 32 );
431 np->height = RNGF() + 0.2;
432
433 /* Seed. */
434 np->rx = RNGF() * 2000. - 1000.;
435 np->ry = RNGF() * 2000. - 1000.;
436 }
437 }
438
439 NTracingZoneEnd( _ctx );
440}
void cam_getDPos(double *dx, double *dy)
Gets the camera position differential (change in last frame).
Definition camera.c:131
double cam_getZoom(void)
Gets the camera zoom.
Definition camera.c:101
void col_hsv2rgb(glColour *c, float h, float s, float v)
Changes colour space from HSV to RGB.
Definition colour.c:61
void gui_getOffset(double *x, double *y)
Gets the GUI offset.
Definition gui.c:2159
mat4 mat4_identity(void)
Creates an identity matrix.
Definition mat4.c:335
mat4 mat4_ortho(double left, double right, double bottom, double top, double nearVal, double farVal)
Creates an orthographic projection matrix.
Definition mat4.c:347
Handles the important game menus.
#define MENU_MAIN
Definition menu.h:9
#define menu_isOpen(f)
Definition menu.h:16
void nebu_update(double dt)
Updates visibility and stuff.
Definition nebula.c:210
void nebu_exit(void)
Cleans up the nebu subsystem.
Definition nebula.c:132
static NebulaPuff * nebu_puffs
Definition nebula.c:54
int nebu_resize(void)
Handles a screen s.
Definition nebula.c:84
static double nebu_time
Definition nebula.c:31
#define NEBULA_PUFF_BUFFER
Definition nebula.c:22
static void nebu_renderPuffs(int below_player)
Renders the puffs.
Definition nebula.c:314
void nebu_renderOverlay(const double dt)
Renders the nebula overlay (hides what player can't see).
Definition nebula.c:257
double nebu_getSightRadius(void)
Gets the nebula view radius.
Definition nebula.c:124
void nebu_render(const double dt)
Renders the nebula.
Definition nebula.c:145
static void nebu_blitFBO(void)
If we're drawing the nebula buffered, copy to the screen.
Definition nebula.c:196
static double nebu_density
Definition nebula.c:26
static double nebu_dx
Definition nebula.c:27
void nebu_prep(double density, double volatility, double hue)
Prepares the nebualae to be rendered.
Definition nebula.c:397
static double nebu_hue
Definition nebula.c:25
static double nebu_scale
Definition nebula.c:34
int nebu_init(void)
Initializes the nebula.
Definition nebula.c:73
static int nebu_npuffs
Definition nebula.c:55
static void nebu_renderBackground(const double dt)
Renders the nebula using the multitexture approach.
Definition nebula.c:160
static double nebu_dt
Definition nebula.c:30
static double nebu_view
Definition nebula.c:29
glInfo gl_screen
Definition opengl.c:47
void gl_renderTextureRawH(GLuint texture, const mat4 *projection, const mat4 *tex_mat, const glColour *c)
Texture blitting backend.
int gl_fboCreate(GLuint *fbo, GLuint *tex, GLsizei width, GLsizei height)
Creates a framebuffer and its associated texture.
Definition opengl_tex.c:268
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:224
Player_t player
Definition player.c:77
int space_isSimulation(void)
returns whether we're just simulating.
Definition space.c:1601
void spfx_setNebulaColour(double r, double g, double b)
Sets the nebula colour where applicable.
Definition spfx.c:1002
Represents a nebula puff.
Definition nebula.c:47
vec2 pos
Definition nebula.c:48
double ry
Definition nebula.c:52
double rx
Definition nebula.c:51
double height
Definition nebula.c:49
double s
Definition nebula.c:50
Definition mat4.h:12
Represents a 2d vector.
Definition vec2.h:45
double y
Definition vec2.h:47
double x
Definition vec2.h:46