2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
9 #include "shaders/blit.h"
10 #include "shaders/blitblur.h"
11 #include "shaders/standard.h"
12 #include "shaders/vblend.h"
14 VG_STATIC
void render_water_texture( camera
*cam
);
15 VG_STATIC
void render_water_surface( camera
*cam
);
16 VG_STATIC
void render_world( camera
*cam
);
17 VG_STATIC
void shader_link_standard_ub( GLuint shader
, int texture_id
);
18 VG_STATIC
void render_world_depth( camera
*cam
);
25 GLuint fb
, colour
, rb
;
33 * All standard buffers used in rendering
35 VG_STATIC
struct pipeline
48 struct ub_world_lighting
51 v4f g_light_colours
[3],
52 g_light_directions
[3],
73 float shadow_spread
, shadow_length
;
75 GLuint fb_depthmap
, rgb_depthmap
;
76 GLuint ubo_world_lighting
,
87 .colour
= { 1.36f
, 1.35f
, 1.01f
},
88 .dir
= { 0.63f
, -0.08f
}
92 .colour
= { 0.33f
, 0.56f
, 0.64f
},
93 .dir
= { -2.60f
, -0.13f
}
97 .colour
= { 0.05f
, 0.05f
, 0.23f
},
98 .dir
= { 2.60f
, -0.84f
}
101 .shadow_spread
= 0.65f
,
102 .shadow_length
= 9.50f
,
106 .g_ambient_colour
= { 0.09f
, 0.03f
, 0.07f
}
113 VG_STATIC
void shader_link_standard_ub( GLuint shader
, int texture_id
)
115 GLuint idx
= glGetUniformBlockIndex( shader
, "ub_world_lighting" );
116 glUniformBlockBinding( shader
, idx
, 0 );
118 glActiveTexture( GL_TEXTURE0
+ texture_id
);
119 glBindTexture( GL_TEXTURE_2D
, gpipeline
.rgb_depthmap
);
120 glUniform1i( glGetUniformLocation( shader
, "g_world_depth" ), texture_id
);
123 VG_STATIC
void render_update_lighting_ub(void)
125 struct ub_world_lighting
*winf
= &gpipeline
.ub_world_lighting
;
128 for( int i
=0; i
<3; i
++ )
130 struct light_widget
*lw
= &gpipeline
.widgets
[i
];
134 float pitch
= lw
->dir
[0],
138 v3_copy( (v3f
){ xz
*cosf(yaw
), sinf(pitch
), xz
*sinf(yaw
) },
139 winf
->g_light_directions
[c
] );
140 v3_copy( lw
->colour
, winf
->g_light_colours
[c
] );
146 winf
->g_light_count
= c
;
147 winf
->g_light_directions
[0][3] = gpipeline
.shadow_length
;
148 winf
->g_light_colours
[0][3] = gpipeline
.shadow_spread
;
150 if( vg
.quality_profile
== k_quality_profile_low
)
151 winf
->g_shadow_samples
= 0;
153 winf
->g_shadow_samples
= 8;
155 glBindBuffer( GL_UNIFORM_BUFFER
, gpipeline
.ubo_world_lighting
);
156 glBufferSubData( GL_UNIFORM_BUFFER
, 0, sizeof(struct ub_world_lighting
),
157 &gpipeline
.ub_world_lighting
);
164 VG_STATIC
void fb_use( struct framebuffer
*fb
)
168 glBindFramebuffer( GL_FRAMEBUFFER
, gpipeline
.fb_background
);
169 glViewport( 0, 0, vg
.window_x
, vg
.window_y
);
173 glBindFramebuffer( GL_FRAMEBUFFER
, fb
->fb
);
174 glViewport( 0, 0, vg
.window_x
/ fb
->div
, vg
.window_y
/ fb
->div
);
178 VG_STATIC
void fb_init( struct framebuffer
*fb
)
180 i32 ix
= vg
.window_x
/ fb
->div
,
181 iy
= vg
.window_y
/ fb
->div
;
183 glGenFramebuffers( 1, &fb
->fb
);
184 glBindFramebuffer( GL_FRAMEBUFFER
, fb
->fb
);
186 glGenTextures( 1, &fb
->colour
);
187 glBindTexture( GL_TEXTURE_2D
, fb
->colour
);
188 glTexImage2D( GL_TEXTURE_2D
, 0, fb
->format
, ix
, iy
,
189 0, fb
->format
, GL_UNSIGNED_BYTE
, NULL
);
191 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
192 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
193 glFramebufferTexture2D( GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
194 GL_TEXTURE_2D
, fb
->colour
, 0);
196 glGenRenderbuffers( 1, &fb
->rb
);
197 glBindRenderbuffer( GL_RENDERBUFFER
, fb
->rb
);
198 glRenderbufferStorage( GL_RENDERBUFFER
, GL_DEPTH24_STENCIL8
, ix
, iy
);
200 glFramebufferRenderbuffer( GL_FRAMEBUFFER
, GL_DEPTH_STENCIL_ATTACHMENT
,
201 GL_RENDERBUFFER
, fb
->rb
);
202 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
208 VG_STATIC
void fb_free( struct framebuffer
*fb
)
210 glDeleteTextures( 1, &fb
->colour
);
211 glDeleteFramebuffers( 1, &fb
->fb
);
214 VG_STATIC
void fb_bindtex( struct framebuffer
*fb
, int texture
)
216 glActiveTexture( GL_TEXTURE0
+ texture
);
217 glBindTexture( GL_TEXTURE_2D
, fb
->colour
);
220 VG_STATIC
void fb_resize( struct framebuffer
*fb
)
225 i32 ix
= vg
.window_x
/ fb
->div
,
226 iy
= vg
.window_y
/ fb
->div
;
228 glBindTexture( GL_TEXTURE_2D
, fb
->colour
);
229 glTexImage2D( GL_TEXTURE_2D
, 0, fb
->format
, ix
, iy
, 0,
230 fb
->format
, GL_UNSIGNED_BYTE
, NULL
);
232 glBindRenderbuffer( GL_RENDERBUFFER
, fb
->rb
);
233 glRenderbufferStorage( GL_RENDERBUFFER
, GL_DEPTH24_STENCIL8
, ix
, iy
);
236 VG_STATIC
void render_fb_resize(void)
238 if( gpipeline
.ready
)
240 glBindTexture( GL_TEXTURE_2D
, gpipeline
.rgb_background
);
241 glTexImage2D( GL_TEXTURE_2D
, 0, GL_RGB
, vg
.window_x
, vg
.window_y
, 0,
242 GL_RGB
, GL_UNSIGNED_BYTE
, NULL
);
244 /* FIXME: Resizeother textures and rb */
248 VG_STATIC
void render_init_temp_buffer(void)
250 vg_info( "[render] Allocate framebuffer\n" );
252 glGenFramebuffers( 1, &gpipeline
.fb_background
);
253 glBindFramebuffer( GL_FRAMEBUFFER
, gpipeline
.fb_background
);
255 glGenTextures( 1, &gpipeline
.rgb_background
);
256 glBindTexture( GL_TEXTURE_2D
, gpipeline
.rgb_background
);
257 glTexImage2D( GL_TEXTURE_2D
, 0, GL_RGB
, vg
.window_x
, vg
.window_y
,
258 0, GL_RGB
, GL_UNSIGNED_BYTE
, NULL
);
259 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
260 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
261 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
262 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
263 glFramebufferTexture2D( GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
265 gpipeline
.rgb_background
, 0 );
267 glGenTextures( 1, &gpipeline
.mv_background
);
268 glBindTexture( GL_TEXTURE_2D
, gpipeline
.mv_background
);
270 glTexImage2D( GL_TEXTURE_2D
, 0, GL_RG
, vg
.window_x
, vg
.window_y
,
271 0, GL_RG
, GL_FLOAT
, NULL
);
273 glTexImage2D( GL_TEXTURE_2D
, 0, GL_RGBA16F
, vg
.window_x
, vg
.window_y
,
274 0, GL_RGBA
, GL_FLOAT
, NULL
);
276 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
277 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
278 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
279 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
280 glFramebufferTexture2D( GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT1
,
282 gpipeline
.mv_background
, 0 );
285 glGenRenderbuffers( 1, &gpipeline
.rb_background
);
286 glBindRenderbuffer( GL_RENDERBUFFER
, gpipeline
.rb_background
);
287 glRenderbufferStorage( GL_RENDERBUFFER
, GL_DEPTH24_STENCIL8
,
288 vg
.window_x
, vg
.window_y
);
289 glFramebufferRenderbuffer( GL_FRAMEBUFFER
, GL_DEPTH_STENCIL_ATTACHMENT
,
290 GL_RENDERBUFFER
, gpipeline
.rb_background
);
292 GLuint attachments
[] = { GL_COLOR_ATTACHMENT0
, GL_COLOR_ATTACHMENT1
};
293 glDrawBuffers( 2, attachments
);
295 GLenum result
= glCheckFramebufferStatus( GL_FRAMEBUFFER
);
297 if( result
!= GL_FRAMEBUFFER_COMPLETE
)
299 if( result
== GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
)
300 vg_fatal_exit_loop( "Main RT: Incomplete attachment" );
301 else if( result
== GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
)
302 vg_fatal_exit_loop( "Main RT: Missing attachment" );
303 else if( result
== GL_FRAMEBUFFER_UNSUPPORTED
)
304 vg_fatal_exit_loop( "Main RT: Unsupported framebuffer format" );
306 vg_fatal_exit_loop( "Main RT: Generic Error" );
309 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
313 /* used for drawing world depth from the top view, used in our water and
314 * lighting calculations */
315 VG_STATIC
void render_init_depthmap_buffer(void)
317 vg_info( "[render] Allocate depth map buffer\n" );
319 glGenFramebuffers( 1, &gpipeline
.fb_depthmap
);
320 glBindFramebuffer( GL_FRAMEBUFFER
, gpipeline
.fb_depthmap
);
322 glGenTextures( 1, &gpipeline
.rgb_depthmap
);
323 glBindTexture( GL_TEXTURE_2D
, gpipeline
.rgb_depthmap
);
324 glTexImage2D( GL_TEXTURE_2D
, 0, GL_R32F
, 1024, 1024, 0,
325 GL_RED
, GL_FLOAT
, NULL
);
326 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
327 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
330 glFramebufferTexture2D( GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
332 gpipeline
.rgb_depthmap
, 0);
337 VG_STATIC
void render_init_fs_quad(void)
339 vg_info( "[render] Allocate quad\n" );
341 float quad
[] = { 0.0f
, 0.0f
, 1.0f
, 1.0f
, 0.0f
, 1.0f
,
342 0.0f
, 0.0f
, 1.0f
, 0.0f
, 1.0f
, 1.0f
,
344 0.2f
, 0.0f
, 0.8f
, 1.0f
, 0.2f
, 1.0f
,
345 0.2f
, 0.0f
, 0.8f
, 0.0f
, 0.8f
, 1.0f
};
347 glGenVertexArrays( 1, &gpipeline
.fsquad
.vao
);
348 glGenBuffers( 1, &gpipeline
.fsquad
.vbo
);
349 glBindVertexArray( gpipeline
.fsquad
.vao
);
350 glBindBuffer( GL_ARRAY_BUFFER
, gpipeline
.fsquad
.vbo
);
351 glBufferData( GL_ARRAY_BUFFER
, sizeof(quad
), quad
, GL_STATIC_DRAW
);
352 glBindVertexArray( gpipeline
.fsquad
.vao
);
353 glVertexAttribPointer( 0, 2, GL_FLOAT
, GL_FALSE
,
354 sizeof(float)*2, (void*)0 );
355 glEnableVertexAttribArray( 0 );
360 VG_STATIC
void render_init_uniform_buffers(void)
362 vg_info( "[render] Allocate uniform buffer\n" );
364 glGenBuffers( 1, &gpipeline
.ubo_world_lighting
);
365 glBindBuffer( GL_UNIFORM_BUFFER
, gpipeline
.ubo_world_lighting
);
366 glBufferData( GL_UNIFORM_BUFFER
, sizeof(struct ub_world_lighting
),
367 NULL
, GL_DYNAMIC_DRAW
);
369 render_update_lighting_ub();
370 glBindBufferBase( GL_UNIFORM_BUFFER
, 0, gpipeline
.ubo_world_lighting
);
375 VG_STATIC
void render_init(void)
377 shader_blit_register();
378 shader_blitblur_register();
379 shader_standard_register();
380 shader_vblend_register();
382 vg_acquire_thread_sync();
384 render_init_temp_buffer();
385 render_init_depthmap_buffer();
386 render_init_fs_quad();
387 render_init_uniform_buffers();
389 glBindFramebuffer( GL_FRAMEBUFFER
, 0 );
393 vg_release_thread_sync();
399 VG_STATIC
void render_fsquad(void)
401 glBindVertexArray( gpipeline
.fsquad
.vao
);
402 glDrawArrays( GL_TRIANGLES
, 0, 6 );
405 VG_STATIC
void render_fsquad1(void)
407 glBindVertexArray( gpipeline
.fsquad
.vao
);
408 glDrawArrays( GL_TRIANGLES
, 6, 6 );
411 #endif /* RENDER_H */