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