4 #include "shaders/blit.h"
5 #include "shaders/standard.h"
6 #include "shaders/vblend.h"
7 #include "shaders/unlit.h"
9 static void render_water_texture( m4x3f camera
);
10 static void render_water_surface( m4x4f pv
, m4x3f camera
);
11 static void render_world( m4x4f projection
, m4x3f camera
);
12 static void shader_link_standard_ub( GLuint shader
, int texture_id
);
13 static void render_world_depth( m4x4f projection
, m4x3f camera
);
20 GLuint fb
, colour
, rb
;
27 static struct pipeline
36 struct ub_world_lighting
39 v4f g_light_colours
[3],
40 g_light_directions
[3],
60 float shadow_spread
, shadow_length
;
62 GLuint fb_depthmap
, rgb_depthmap
;
63 GLuint ubo_world_lighting
,
74 .colour
= { 1.36f
, 1.35f
, 1.01f
},
75 .dir
= { 0.63f
, -0.08f
}
79 .colour
= { 0.33f
, 0.56f
, 0.64f
},
80 .dir
= { -2.60f
, -0.13f
}
84 .colour
= { 0.05f
, 0.05f
, 0.23f
},
85 .dir
= { 2.60f
, -0.84f
}
88 .shadow_spread
= 0.65f
,
89 .shadow_length
= 9.50f
,
93 .g_ambient_colour
= { 0.09f
, 0.03f
, 0.07f
}
101 * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
103 static void plane_clip_projection( m4x4f mat
, v4f plane
)
107 (vg_signf(plane
[0]) + mat
[2][0]) / mat
[0][0],
108 (vg_signf(plane
[1]) + mat
[2][1]) / mat
[1][1],
110 (1.0f
+ mat
[2][2]) / mat
[3][2]
113 v4_muls( plane
, 2.0f
/ v4_dot(plane
,c
), c
);
117 mat
[2][2] = c
[2] + 1.0f
;
121 static void pipeline_projection( m4x4f mat
, float nearz
, float farz
)
123 m4x4_projection( mat
,
125 (float)vg_window_x
/ (float)vg_window_y
,
132 static void shader_link_standard_ub( GLuint shader
, int texture_id
)
134 GLuint idx
= glGetUniformBlockIndex( shader
, "ub_world_lighting" );
135 glUniformBlockBinding( shader
, idx
, 0 );
137 glActiveTexture( GL_TEXTURE0
+ texture_id
);
138 glBindTexture( GL_TEXTURE_2D
, gpipeline
.rgb_depthmap
);
139 glUniform1i( glGetUniformLocation( shader
, "g_world_depth" ), texture_id
);
142 static void render_update_lighting_ub(void)
144 struct ub_world_lighting
*winf
= &gpipeline
.ub_world_lighting
;
147 for( int i
=0; i
<3; i
++ )
149 struct light_widget
*lw
= &gpipeline
.widgets
[i
];
153 float pitch
= lw
->dir
[0],
157 v3_copy( (v3f
){ xz
*cosf(yaw
), sinf(pitch
), xz
*sinf(yaw
) },
158 winf
->g_light_directions
[c
] );
159 v3_copy( lw
->colour
, winf
->g_light_colours
[c
] );
165 winf
->g_light_count
= c
;
166 winf
->g_light_directions
[0][3] = gpipeline
.shadow_length
;
167 winf
->g_light_colours
[0][3] = gpipeline
.shadow_spread
;
169 glBindBuffer( GL_UNIFORM_BUFFER
, gpipeline
.ubo_world_lighting
);
170 glBufferSubData( GL_UNIFORM_BUFFER
, 0, sizeof(struct ub_world_lighting
),
171 &gpipeline
.ub_world_lighting
);
178 static void fb_use( struct framebuffer
*fb
)
182 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
183 glViewport( 0, 0, vg_window_x
, vg_window_y
);
187 glBindFramebuffer( GL_FRAMEBUFFER
, fb
->fb
);
188 glViewport( 0, 0, vg_window_x
/ fb
->div
, vg_window_y
/ fb
->div
);
192 __attribute__((warn_unused_result
))
193 static int fb_init( struct framebuffer
*fb
)
195 i32 ix
= vg_window_x
/ fb
->div
,
196 iy
= vg_window_y
/ fb
->div
;
198 glGenFramebuffers( 1, &fb
->fb
);
199 glBindFramebuffer( GL_FRAMEBUFFER
, fb
->fb
);
201 glGenTextures( 1, &fb
->colour
);
202 glBindTexture( GL_TEXTURE_2D
, fb
->colour
);
203 glTexImage2D( GL_TEXTURE_2D
, 0, fb
->format
, ix
, iy
,
204 0, fb
->format
, GL_UNSIGNED_BYTE
, NULL
);
206 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
207 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
208 glFramebufferTexture2D( GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
209 GL_TEXTURE_2D
, fb
->colour
, 0);
211 glGenRenderbuffers( 1, &fb
->rb
);
212 glBindRenderbuffer( GL_RENDERBUFFER
, fb
->rb
);
213 glRenderbufferStorage( GL_RENDERBUFFER
, GL_DEPTH24_STENCIL8
, ix
, iy
);
215 glFramebufferRenderbuffer( GL_FRAMEBUFFER
, GL_DEPTH_STENCIL_ATTACHMENT
,
216 GL_RENDERBUFFER
, fb
->rb
);
217 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
219 if( VG_CHECK_GL_ERR() )
222 vg_error( "Error while creating standard framebuffer\n" );
230 static void fb_free( struct framebuffer
*fb
)
232 glDeleteTextures( 1, &fb
->colour
);
233 glDeleteFramebuffers( 1, &fb
->fb
);
236 static void fb_bindtex( struct framebuffer
*fb
, int texture
)
238 glActiveTexture( GL_TEXTURE0
+ texture
);
239 glBindTexture( GL_TEXTURE_2D
, fb
->colour
);
242 static void fb_resize( struct framebuffer
*fb
)
247 i32 ix
= vg_window_x
/ fb
->div
,
248 iy
= vg_window_y
/ fb
->div
;
250 glBindTexture( GL_TEXTURE_2D
, fb
->colour
);
251 glTexImage2D( GL_TEXTURE_2D
, 0, fb
->format
, ix
, iy
, 0,
252 fb
->format
, GL_UNSIGNED_BYTE
, NULL
);
254 glBindRenderbuffer( GL_RENDERBUFFER
, fb
->rb
);
255 glRenderbufferStorage( GL_RENDERBUFFER
, GL_DEPTH24_STENCIL8
, ix
, iy
);
258 static void render_fb_resize(void)
260 if( gpipeline
.ready
)
262 glBindTexture( GL_TEXTURE_2D
, gpipeline
.rgb_background
);
263 glTexImage2D( GL_TEXTURE_2D
, 0, GL_RGB
, vg_window_x
, vg_window_y
, 0,
264 GL_RGB
, GL_UNSIGNED_BYTE
, NULL
);
271 static int render_init(void)
273 shader_blit_register();
274 shader_standard_register();
275 shader_vblend_register();
276 shader_unlit_register();
278 if( vg_acquire_thread_sync(1) )
280 vg_info( "Allocating framebuffers\n" );
282 glGenFramebuffers( 1, &gpipeline
.fb_background
);
283 glBindFramebuffer( GL_FRAMEBUFFER
, gpipeline
.fb_background
);
285 glGenTextures( 1, &gpipeline
.rgb_background
);
286 glBindTexture( GL_TEXTURE_2D
, gpipeline
.rgb_background
);
287 glTexImage2D( GL_TEXTURE_2D
, 0, GL_RGB
, vg_window_x
, vg_window_y
,
288 0, GL_RGB
, GL_UNSIGNED_BYTE
, NULL
);
290 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
291 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
292 glFramebufferTexture2D( GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
294 gpipeline
.rgb_background
, 0);
296 if( VG_CHECK_GL_ERR() )
298 vg_error( "Error while creating back buffer\n" );
299 vg_release_thread_sync(1);
304 * World depth map, maybe this should be moved to world.h
307 glGenFramebuffers( 1, &gpipeline
.fb_depthmap
);
308 glBindFramebuffer( GL_FRAMEBUFFER
, gpipeline
.fb_depthmap
);
310 glGenTextures( 1, &gpipeline
.rgb_depthmap
);
311 glBindTexture( GL_TEXTURE_2D
, gpipeline
.rgb_depthmap
);
312 glTexImage2D( GL_TEXTURE_2D
, 0, GL_R32F
, 1024, 1024, 0,
313 GL_RED
, GL_FLOAT
, NULL
);
314 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
315 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
318 glFramebufferTexture2D( GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
320 gpipeline
.rgb_depthmap
, 0);
322 if( VG_CHECK_GL_ERR() )
324 vg_error( "Error while creating world depth buffer\n" );
325 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
326 vg_release_thread_sync(1);
330 float quad
[] = { 0.0f
, 0.0f
, 1.0f
, 1.0f
, 0.0f
, 1.0f
,
331 0.0f
, 0.0f
, 1.0f
, 0.0f
, 1.0f
, 1.0f
};
333 glGenVertexArrays( 1, &gpipeline
.fsquad
.vao
);
334 glGenBuffers( 1, &gpipeline
.fsquad
.vbo
);
335 glBindVertexArray( gpipeline
.fsquad
.vao
);
336 glBindBuffer( GL_ARRAY_BUFFER
, gpipeline
.fsquad
.vbo
);
337 glBufferData( GL_ARRAY_BUFFER
, sizeof(quad
), quad
, GL_STATIC_DRAW
);
338 glBindVertexArray( gpipeline
.fsquad
.vao
);
339 glVertexAttribPointer( 0, 2, GL_FLOAT
, GL_FALSE
,
340 sizeof(float)*2, (void*)0 );
341 glEnableVertexAttribArray( 0 );
343 if( VG_CHECK_GL_ERR() )
345 vg_error( "Error while creating fsquad\n" );
346 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
347 vg_release_thread_sync(1);
351 glGenBuffers( 1, &gpipeline
.ubo_world_lighting
);
352 glBindBuffer( GL_UNIFORM_BUFFER
, gpipeline
.ubo_world_lighting
);
353 glBufferData( GL_UNIFORM_BUFFER
, sizeof(struct ub_world_lighting
),
354 NULL
, GL_DYNAMIC_DRAW
);
356 render_update_lighting_ub();
357 glBindBufferBase( GL_UNIFORM_BUFFER
, 0, gpipeline
.ubo_world_lighting
);
359 if( VG_CHECK_GL_ERR() )
361 vg_error( "Error while creating world uniform buffers\n" );
362 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
363 vg_release_thread_sync(1);
367 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
368 vg_success( "Done\n" );
371 vg_release_thread_sync(1);
378 static void render_free(void *_
)
380 glDeleteVertexArrays( 1, &gpipeline
.fsquad
.vao
);
381 glDeleteBuffers( 1, &gpipeline
.fsquad
.vbo
);
383 glDeleteFramebuffers( 1, &gpipeline
.fb_background
);
384 glDeleteFramebuffers( 1, &gpipeline
.fb_depthmap
);
386 glDeleteTextures( 1, &gpipeline
.rgb_background
);
387 glDeleteTextures( 1, &gpipeline
.rgb_depthmap
);
393 static void render_fsquad(void)
395 glBindVertexArray( gpipeline
.fsquad
.vao
);
396 glDrawArrays( GL_TRIANGLES
, 0, 6 );
399 #endif /* RENDER_H */