latest
[carveJwlIkooP6JGAAIwe30JlM.git] / render.h
1 #include "common.h"
2 #include "model.h"
3
4 static void render_water_texture( m4x3f camera );
5 static void render_water_surface( m4x4f pv, m4x3f camera );
6 static void render_world( m4x4f projection, m4x3f camera );
7 static void shader_link_standard_ub( GLuint shader, int texture_id );
8 static void render_world_depth( m4x4f projection, m4x3f camera );
9
10 #ifndef RENDER_H
11 #define RENDER_H
12
13 static struct pipeline
14 {
15 float fov;
16 glmesh fsquad;
17
18 GLuint fb_background,
19 rgb_background;
20
21 /* STD140 */
22 struct ub_world_lighting
23 {
24 /* v3f (padded) */
25 v4f g_light_colours[3],
26 g_light_directions[3],
27 g_ambient_colour;
28
29 v4f g_water_plane,
30 g_depth_bounds;
31
32 float g_water_fog;
33 int g_light_count;
34 int g_light_preview;
35 }
36 ub_world_lighting;
37
38 struct light_widget
39 {
40 int enabled;
41 v2f dir;
42 v3f colour;
43 }
44 widgets[3];
45
46 float shadow_spread, shadow_length;
47
48 GLuint fb_depthmap, rgb_depthmap;
49 GLuint ubo_world_lighting,
50 ubo_world;
51 }
52 gpipeline =
53 {
54 .widgets =
55 {
56 {
57 .enabled = 1,
58 .colour = { 1.36f, 1.35f, 1.01f },
59 .dir = { 0.63f, -0.08f }
60 },
61 {
62 .enabled = 1,
63 .colour = { 0.33f, 0.56f, 0.64f },
64 .dir = { -2.60f, -0.13f }
65 },
66 {
67 .enabled = 1,
68 .colour = { 0.05f, 0.05f, 0.23f },
69 .dir = { 2.60f, -0.84f }
70 }
71 },
72 .shadow_spread = 0.65f,
73 .shadow_length = 9.50f,
74
75 .ub_world_lighting =
76 {
77 .g_ambient_colour = { 0.09f, 0.03f, 0.07f }
78 }
79 };
80
81 /*
82 * Matrix Projections
83 */
84 /*
85 * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
86 */
87 static void plane_clip_projection( m4x4f mat, v4f plane )
88 {
89 v4f c =
90 {
91 (vg_signf(plane[0]) + mat[2][0]) / mat[0][0],
92 (vg_signf(plane[1]) + mat[2][1]) / mat[1][1],
93 -1.0f,
94 (1.0f + mat[2][2]) / mat[3][2]
95 };
96
97 v4_muls( plane, 2.0f / v4_dot(plane,c), c );
98
99 mat[0][2] = c[0];
100 mat[1][2] = c[1];
101 mat[2][2] = c[2] + 1.0f;
102 mat[3][2] = c[3];
103 }
104
105 static void pipeline_projection( m4x4f mat, float nearz, float farz )
106 {
107 m4x4_projection( mat,
108 gpipeline.fov,
109 (float)vg_window_x / (float)vg_window_y,
110 nearz, farz );
111 }
112
113 /*
114 * Shaders
115 */
116 static void shader_link_standard_ub( GLuint shader, int texture_id )
117 {
118 GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" );
119 glUniformBlockBinding( shader, idx, 0 );
120
121 glActiveTexture( GL_TEXTURE0 + texture_id );
122 glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_depthmap );
123 glUniform1i( glGetUniformLocation( shader, "g_world_depth" ), texture_id );
124 }
125
126 static void render_update_lighting_ub(void)
127 {
128 struct ub_world_lighting *winf = &gpipeline.ub_world_lighting;
129 int c = 0;
130
131 for( int i=0; i<3; i++ )
132 {
133 struct light_widget *lw = &gpipeline.widgets[i];
134
135 if( lw->enabled )
136 {
137 float pitch = lw->dir[0],
138 yaw = lw->dir[1],
139 xz = cosf( pitch );
140
141 v3_copy( (v3f){ xz*cosf(yaw), sinf(pitch), xz*sinf(yaw) },
142 winf->g_light_directions[c] );
143 v3_copy( lw->colour, winf->g_light_colours[c] );
144
145 c ++;
146 }
147 }
148
149 winf->g_light_count = c;
150 winf->g_light_directions[0][3] = gpipeline.shadow_length;
151 winf->g_light_colours[0][3] = gpipeline.shadow_spread;
152
153 glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting );
154 glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting),
155 &gpipeline.ub_world_lighting );
156 }
157
158 static void render_alloc_ub(void)
159 {
160 glGenBuffers( 1, &gpipeline.ubo_world_lighting );
161 glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting );
162 glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting),
163 NULL, GL_DYNAMIC_DRAW );
164
165 render_update_lighting_ub();
166 glBindBufferBase( GL_UNIFORM_BUFFER, 0, gpipeline.ubo_world_lighting );
167 }
168
169 /*
170 * Framebuffers
171 */
172 struct framebuffer
173 {
174 GLuint fb, colour, rb;
175 int div;
176 GLuint format;
177 };
178
179 static void fb_use( struct framebuffer *fb )
180 {
181 if( !fb )
182 {
183 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
184 glViewport( 0, 0, vg_window_x, vg_window_y );
185 }
186 else
187 {
188 glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
189 glViewport( 0, 0, vg_window_x / fb->div, vg_window_y / fb->div );
190 }
191 }
192
193 static void fb_init( struct framebuffer *fb )
194 {
195 i32 ix = vg_window_x / fb->div,
196 iy = vg_window_y / fb->div;
197
198 glGenFramebuffers( 1, &fb->fb );
199 glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
200
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);
205
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);
210
211 glGenRenderbuffers( 1, &fb->rb );
212 glBindRenderbuffer( GL_RENDERBUFFER, fb->rb );
213 glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, ix, iy );
214
215 glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
216 GL_RENDERBUFFER, fb->rb );
217 }
218
219 static void fb_bindtex( struct framebuffer *fb, int texture )
220 {
221 glActiveTexture( GL_TEXTURE0 + texture );
222 glBindTexture( GL_TEXTURE_2D, fb->colour );
223 }
224
225 static void fb_resize( struct framebuffer *fb )
226 {
227 i32 ix = vg_window_x / fb->div,
228 iy = vg_window_y / fb->div;
229
230 glBindTexture( GL_TEXTURE_2D, fb->colour );
231 glTexImage2D( GL_TEXTURE_2D, 0, fb->format, ix, iy, 0,
232 fb->format, GL_UNSIGNED_BYTE, NULL );
233
234 glBindRenderbuffer( GL_RENDERBUFFER, fb->rb );
235 glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, ix, iy );
236 }
237
238 static void render_fb_resize(void)
239 {
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 );
243 }
244
245 /*
246 * Vg
247 */
248 static void render_init(void)
249 {
250 glGenFramebuffers( 1, &gpipeline.fb_background );
251 glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_background );
252
253 glGenTextures( 1, &gpipeline.rgb_background );
254 glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background );
255 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y,
256 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
257
258 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
259 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
260 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
261 GL_TEXTURE_2D,
262 gpipeline.rgb_background, 0);
263
264 /*
265 * World depth map, maybe this should be moved to world.h
266 * TODO: review
267 */
268 glGenFramebuffers( 1, &gpipeline.fb_depthmap );
269 glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_depthmap );
270
271 glGenTextures( 1, &gpipeline.rgb_depthmap );
272 glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_depthmap );
273 glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, 1024, 1024, 0,
274 GL_RED, GL_FLOAT, NULL );
275 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
276 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
277 vg_tex2d_clamp();
278
279 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
280 GL_TEXTURE_2D,
281 gpipeline.rgb_depthmap, 0);
282
283 float quad[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
284 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f };
285
286 glGenVertexArrays( 1, &gpipeline.fsquad.vao );
287 glGenBuffers( 1, &gpipeline.fsquad.vbo );
288 glBindVertexArray( gpipeline.fsquad.vao );
289 glBindBuffer( GL_ARRAY_BUFFER, gpipeline.fsquad.vbo );
290 glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
291 glBindVertexArray( gpipeline.fsquad.vao );
292 glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE,
293 sizeof(float)*2, (void*)0 );
294 glEnableVertexAttribArray( 0 );
295 VG_CHECK_GL();
296
297 render_alloc_ub();
298 }
299
300 static void render_free(void)
301 {
302 /* TODO: ... */
303 }
304
305 /*
306 * Utility
307 */
308 static void render_fsquad(void)
309 {
310 glBindVertexArray( gpipeline.fsquad.vao );
311 glDrawArrays( GL_TRIANGLES, 0, 6 );
312 }
313
314 #endif /* RENDER_H */