1 /************************************************************************
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
28 typedef struct obj2d_s
{
52 static obj2d_t
*render2d_section_create()
54 obj2d_t
*r
= malloc(sizeof(obj2d_t
));
59 textbuffer_init(&r
->txt
,NULL
,0,0,0,0,0,0,0);
64 static void render2d_get_section(material_t
*m
, int t
)
66 if (!render2d_data
.current
) {
67 if (!render2d_data
.stack
) {
68 render2d_data
.current
= render2d_section_create();
69 render2d_data
.stack
= list_push(&render2d_data
.stack
,render2d_data
.current
);
71 render2d_data
.current
= render2d_data
.stack
;
75 if (render2d_data
.current
->type
!= RD2_NONE
) {
78 || render2d_data
.current
->type
!= t
81 && m
!= render2d_data
.current
->mat
84 if (!render2d_data
.current
->next
) {
85 render2d_data
.current
= render2d_section_create();
86 render2d_data
.stack
= list_push(&render2d_data
.stack
,render2d_data
.current
);
88 render2d_data
.current
= render2d_data
.current
->next
;
93 render2d_data
.current
->mat
= m
;
95 render2d_data
.current
->type
= t
;
98 /* render a 2d line */
99 void render2d_line(material_t
*m
, float x
, float y
, float ex
, float ey
)
102 render2d_get_section(m,RD2_LINE);
104 render2d_data.current->box.x = x;
105 render2d_data.current->box.y = y;
106 render2d_data.current->box.w = ex;
107 render2d_data.current->box.h = ey;
111 /* render a 2d quad of material */
112 void render2d_quad_mat(material_t
*m
, float x
, float y
, float w
, float h
)
114 render2d_get_section(m
,RD2_QUAD
);
116 y
= wm_data
.size
.height
-y
;
118 w
/= (float)wm_data
.size
.width
;
119 h
/= (float)wm_data
.size
.height
;
120 x
= (((x
/(float)wm_data
.size
.width
)*2.0)-1.0)+w
;
121 y
= (((y
/(float)wm_data
.size
.height
)*2.0)-1.0)-h
;
123 render2d_data
.current
->box
.x
= x
;
124 render2d_data
.current
->box
.y
= y
;
125 render2d_data
.current
->box
.w
= w
;
126 render2d_data
.current
->box
.h
= h
;
130 void render2d_text(float x
, float y
, int w
, int h
, int font
, int size
, char* str
)
133 render2d_get_section(NULL
,RD2_TEXT
);
137 textbuffer_adjust(&render2d_data
.current
->txt
,f
,size
,x
,y
,w
,h
,0,0);
138 textbuffer_addstr(&render2d_data
.current
->txt
,str
);
141 /* render a pregenerated textbuffer */
142 void render2d_textbuffer(textbuffer_t
*t
)
148 if (!t
|| !t
->length
)
151 render2d_get_section(NULL
,RD2_TEXT
);
153 render2d_data
.current
->itxt
= t
;
155 s
= (((float)t
->font_size
)*0.15);
156 s
/= (float)wm_data
.size
.height
;
159 y
= wm_data
.size
.height
-t
->y
;
161 x
= (((x
/(float)wm_data
.size
.width
)*2.0)-1.0);
162 y
= (((y
/(float)wm_data
.size
.height
)*2.0)-1.0);
164 render2d_data
.current
->box
.x
= x
;
165 render2d_data
.current
->box
.y
= y
;
166 render2d_data
.current
->box
.w
= s
;
167 render2d_data
.current
->box
.h
= s
;
170 /* render a textbuffer */
172 /* render 2d graphics to the frame */
182 glDisable(GL_DEPTH_TEST
);
184 render2d_data
.current
= render2d_data
.stack
;
186 if (render2d_data
.vao
== 0) {
187 GLfloat vertices
[8] = {-1.0,1.0, -1.0,-1.0, 1.0,1.0, 1.0,-1.0};
188 GLfloat texcoords
[8] = {0.0,0.0, 0.0,1.0, 1.0,0.0, 1.0,1.0};
189 glGenVertexArrays(1,&render2d_data
.vao
);
190 glBindVertexArray(render2d_data
.vao
);
191 glGenBuffers(2, render2d_data
.vbo
);
192 glBindBuffer(GL_ARRAY_BUFFER
, render2d_data
.vbo
[0]);
193 glBufferData(GL_ARRAY_BUFFER
, 32, vertices
, GL_STATIC_DRAW
);
194 glEnableVertexAttribArray(0);
195 glVertexAttribPointer(0,2,GL_FLOAT
,GL_FALSE
,0,0);
196 glBindBuffer(GL_ARRAY_BUFFER
, render2d_data
.vbo
[1]);
197 glBufferData(GL_ARRAY_BUFFER
, 32, texcoords
, GL_STATIC_DRAW
);
198 glEnableVertexAttribArray(1);
199 glVertexAttribPointer(1,2,GL_FLOAT
,GL_FALSE
,0,0);
200 glBindBuffer(GL_ARRAY_BUFFER
, 0);
204 if (!render2d_data
.shader
) {
205 render2d_data
.shader
= shader_create("ui");
206 shader_attribute(render2d_data
.shader
,0,"position");
207 shader_attribute(render2d_data
.shader
,1,"uvs");
210 shader_enable(render2d_data
.shader
);
212 glBindVertexArray(render2d_data
.vao
);
213 glEnableVertexAttribArray(0);
214 glEnableVertexAttribArray(1);
217 while (render2d_data
.current
&& render2d_data
.current
->type
!= RD2_NONE
) {
218 if (render2d_data
.current
->type
== RD2_TEXT
) {
219 txt
= render2d_data
.current
->itxt
;
221 txt
= &render2d_data
.current
->txt
;
222 for (i
=0; i
<txt
->data
.length
; i
++) {
223 t
= array_get_ptr(&txt
->data
,i
);
226 glGenVertexArrays(1,&t
->vao
);
227 glBindVertexArray(t
->vao
);
228 glGenBuffers(2, t
->vbo
);
229 glBindBuffer(GL_ARRAY_BUFFER
, t
->vbo
[0]);
230 glBufferData(GL_ARRAY_BUFFER
, t
->v
.length
*4, t
->v
.data
, GL_STATIC_DRAW
);
231 glEnableVertexAttribArray(0);
232 glVertexAttribPointer(0,2,GL_FLOAT
,GL_FALSE
,0,0);
233 glBindBuffer(GL_ARRAY_BUFFER
, t
->vbo
[1]);
234 glBufferData(GL_ARRAY_BUFFER
, t
->t
.length
*4, t
->t
.data
, GL_STATIC_DRAW
);
235 glEnableVertexAttribArray(1);
236 glVertexAttribPointer(1,2,GL_FLOAT
,GL_FALSE
,0,0);
240 glBindVertexArray(t
->vao
);
241 glEnableVertexAttribArray(0);
242 glEnableVertexAttribArray(1);
245 glDeleteBuffers(2, t
->vbo
);
246 glGenBuffers(2, t
->vbo
);
247 glBindBuffer(GL_ARRAY_BUFFER
, t
->vbo
[0]);
248 glBufferData(GL_ARRAY_BUFFER
, t
->v
.length
*4, t
->v
.data
, GL_STATIC_DRAW
);
249 glEnableVertexAttribArray(0);
250 glVertexAttribPointer(0,2,GL_FLOAT
,GL_FALSE
,0,0);
251 glBindBuffer(GL_ARRAY_BUFFER
, t
->vbo
[1]);
252 glBufferData(GL_ARRAY_BUFFER
, t
->t
.length
*4, t
->t
.data
, GL_STATIC_DRAW
);
253 glEnableVertexAttribArray(1);
254 glVertexAttribPointer(1,2,GL_FLOAT
,GL_FALSE
,0,0);
259 mat_bind_with_opts(t
->glid
,MATOPT_ALPHA_BLEND
|MATOPT_SDF_ALPHA
);
261 matrix_scale(&m
,render2d_data
.current
->box
.w
,render2d_data
.current
->box
.h
,1.0);
262 matrix_translate(&m
,render2d_data
.current
->box
.x
,render2d_data
.current
->box
.y
,1.0);
263 shader_uniform_matrix(render2d_data
.shader
,"transformationMatrix",&m
);
264 glDrawArrays(GL_TRIANGLES
,0,t
->v
.length
/2);
267 render2d_data
.current
->itxt
= NULL
;
268 textbuffer_clear(&render2d_data
.current
->txt
);
269 }else if (render2d_data
.current
->type
== RD2_QUAD
) {
271 glBindVertexArray(render2d_data
.vao
);
272 glEnableVertexAttribArray(0);
273 glEnableVertexAttribArray(1);
276 mat_use(render2d_data
.current
->mat
,render2d_data
.shader
);
279 matrix_scale(&m
,render2d_data
.current
->box
.w
,render2d_data
.current
->box
.h
,1.0);
280 matrix_translate(&m
,render2d_data
.current
->box
.x
,render2d_data
.current
->box
.y
,1.0);
281 shader_uniform_matrix(render2d_data
.shader
,"transformationMatrix",&m
);
283 glDrawArrays(GL_TRIANGLE_STRIP
,0,4);
284 render2d_data
.current
->mat
= NULL
;
287 render2d_data
.current
->type
= RD2_NONE
;
288 render2d_data
.current
= render2d_data
.current
->next
;
292 glDisableVertexAttribArray(0);
293 glDisableVertexAttribArray(1);
294 glBindVertexArray(0);
297 shader_disable(render2d_data
.shader
);
299 render2d_data
.current
= NULL
;