reworked lighting uniforms
[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_directional,
20 g_sun_colour,
21 g_shadow_colour;
22
23 v4f g_water_plane,
24 g_depth_bounds;
25 float g_water_fog;
26 }
27 ub_world_lighting;
28
29 GLuint fb_depthmap, rgb_depthmap;
30 GLuint ubo_world_lighting,
31 ubo_world;
32 }
33 gpipeline;
34
35 static void render_water_texture( m4x3f camera );
36 static void render_water_surface( m4x4f pv, m4x3f camera );
37 static void render_world( m4x4f projection, m4x3f camera );
38 static void render_world_depth( m4x4f projection, m4x3f camera );
39
40 /*
41 * Matrix Projections
42 */
43 /*
44 * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
45 */
46 static void plane_clip_projection( m4x4f mat, v4f plane )
47 {
48 v4f c =
49 {
50 (vg_signf(plane[0]) + mat[2][0]) / mat[0][0],
51 (vg_signf(plane[1]) + mat[2][1]) / mat[1][1],
52 -1.0f,
53 (1.0f + mat[2][2]) / mat[3][2]
54 };
55
56 v4_muls( plane, 2.0f / v4_dot(plane,c), c );
57
58 mat[0][2] = c[0];
59 mat[1][2] = c[1];
60 mat[2][2] = c[2] + 1.0f;
61 mat[3][2] = c[3];
62 }
63
64 static void pipeline_projection( m4x4f mat, float nearz, float farz )
65 {
66 m4x4_projection( mat,
67 gpipeline.fov,
68 (float)vg_window_x / (float)vg_window_y,
69 nearz, farz );
70 }
71
72 /*
73 * Shaders
74 */
75 static void shader_link_standard_ub( GLuint shader, int texture_id )
76 {
77 GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" );
78 glUniformBlockBinding( shader, idx, 0 );
79
80 glActiveTexture( GL_TEXTURE0 + texture_id );
81 glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_depthmap );
82 glUniform1i( glGetUniformLocation( shader, "g_world_depth" ), texture_id );
83 }
84
85 static void render_update_lighting_ub(void)
86 {
87 glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting );
88
89 glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting),
90 &gpipeline.ub_world_lighting );
91 }
92
93 static void render_alloc_ub(void)
94 {
95 glGenBuffers( 1, &gpipeline.ubo_world_lighting );
96 glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting );
97 glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting),
98 NULL, GL_DYNAMIC_DRAW );
99
100 render_update_lighting_ub();
101 glBindBufferBase( GL_UNIFORM_BUFFER, 0, gpipeline.ubo_world_lighting );
102 }
103
104 /*
105 * Framebuffers
106 */
107 struct framebuffer
108 {
109 GLuint fb, colour, rb;
110 int div;
111 GLuint format;
112 };
113
114 static void fb_use( struct framebuffer *fb )
115 {
116 if( !fb )
117 {
118 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
119 glViewport( 0, 0, vg_window_x, vg_window_y );
120 }
121 else
122 {
123 glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
124 glViewport( 0, 0, vg_window_x / fb->div, vg_window_y / fb->div );
125 }
126 }
127
128 static void fb_init( struct framebuffer *fb )
129 {
130 i32 ix = vg_window_x / fb->div,
131 iy = vg_window_y / fb->div;
132
133 glGenFramebuffers( 1, &fb->fb );
134 glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
135
136 glGenTextures( 1, &fb->colour );
137 glBindTexture( GL_TEXTURE_2D, fb->colour );
138 glTexImage2D( GL_TEXTURE_2D, 0, fb->format, ix, iy,
139 0, fb->format, GL_UNSIGNED_BYTE, NULL);
140
141 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
142 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
143 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
144 GL_TEXTURE_2D, fb->colour, 0);
145
146 glGenRenderbuffers( 1, &fb->rb );
147 glBindRenderbuffer( GL_RENDERBUFFER, fb->rb );
148 glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, ix, iy );
149
150 glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
151 GL_RENDERBUFFER, fb->rb );
152 }
153
154 static void fb_bindtex( struct framebuffer *fb, int texture )
155 {
156 glActiveTexture( GL_TEXTURE0 + texture );
157 glBindTexture( GL_TEXTURE_2D, fb->colour );
158 }
159
160 static void fb_resize( struct framebuffer *fb )
161 {
162 i32 ix = vg_window_x / fb->div,
163 iy = vg_window_y / fb->div;
164
165 glBindTexture( GL_TEXTURE_2D, fb->colour );
166 glTexImage2D( GL_TEXTURE_2D, 0, fb->format, ix, iy, 0,
167 fb->format, GL_UNSIGNED_BYTE, NULL );
168
169 glBindRenderbuffer( GL_RENDERBUFFER, fb->rb );
170 glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, ix, iy );
171 }
172
173 static void render_fb_resize(void)
174 {
175 glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background );
176 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y, 0,
177 GL_RGB, GL_UNSIGNED_BYTE, NULL );
178 }
179
180 /*
181 * Vg
182 */
183 static void render_init(void)
184 {
185 glGenFramebuffers( 1, &gpipeline.fb_background );
186 glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_background );
187
188 glGenTextures( 1, &gpipeline.rgb_background );
189 glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background );
190 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y,
191 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
192
193 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
194 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
195 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
196 GL_TEXTURE_2D,
197 gpipeline.rgb_background, 0);
198
199 /*
200 * World depth map, maybe this should be moved to world.h
201 * TODO: review
202 */
203 glGenFramebuffers( 1, &gpipeline.fb_depthmap );
204 glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_depthmap );
205
206 glGenTextures( 1, &gpipeline.rgb_depthmap );
207 glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_depthmap );
208 glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, 1024, 1024, 0,
209 GL_RED, GL_FLOAT, NULL );
210 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
211 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
212 vg_tex2d_clamp();
213
214 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
215 GL_TEXTURE_2D,
216 gpipeline.rgb_depthmap, 0);
217
218 float quad[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
219 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f };
220
221 glGenVertexArrays( 1, &gpipeline.fsquad.vao );
222 glGenBuffers( 1, &gpipeline.fsquad.vbo );
223 glBindVertexArray( gpipeline.fsquad.vao );
224 glBindBuffer( GL_ARRAY_BUFFER, gpipeline.fsquad.vbo );
225 glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
226 glBindVertexArray( gpipeline.fsquad.vao );
227 glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE,
228 sizeof(float)*2, (void*)0 );
229 glEnableVertexAttribArray( 0 );
230 VG_CHECK_GL();
231
232 render_alloc_ub();
233 }
234
235 static void render_free(void)
236 {
237 /* TODO: ... */
238 }
239
240 /*
241 * Utility
242 */
243 static void render_fsquad(void)
244 {
245 glBindVertexArray( gpipeline.fsquad.vao );
246 glDrawArrays( GL_TRIANGLES, 0, 6 );
247 }
248
249 #endif /* RENDER_H */