Merge branch 'master' into blender2.8
[blender.git] / source / blender / gpu / intern / gpu_batch.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2016 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Mike Erwin
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include "BLI_utildefines.h"
29 #include "BLI_math.h"
30
31 #include "GPU_batch.h"
32 #include "gpu_shader_private.h"
33
34 void Batch_set_builtin_program(Gwn_Batch *batch, GPUBuiltinShader shader_id)
35 {
36         GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
37         GWN_batch_program_set(batch, shader->program, shader->interface);
38 }
39
40 static Gwn_Batch *sphere_high = NULL;
41 static Gwn_Batch *sphere_med = NULL;
42 static Gwn_Batch *sphere_low = NULL;
43 static Gwn_Batch *sphere_wire_low = NULL;
44 static Gwn_Batch *sphere_wire_med = NULL;
45
46 static Gwn_VertBuf *vbo;
47 static Gwn_VertFormat format = {0};
48 static unsigned int pos_id, nor_id;
49 static unsigned int vert;
50
51 static void batch_sphere_lat_lon_vert(float lat, float lon)
52 {
53         float pos[3];
54         pos[0] = sinf(lat) * cosf(lon);
55         pos[1] = cosf(lat);
56         pos[2] = sinf(lat) * sinf(lon);
57
58         GWN_vertbuf_attr_set(vbo, nor_id, vert, pos);
59         GWN_vertbuf_attr_set(vbo, pos_id, vert++, pos);
60 }
61
62 /* Replacement for gluSphere */
63 static Gwn_Batch *batch_sphere(int lat_res, int lon_res)
64 {
65         const float lon_inc = 2 * M_PI / lon_res;
66         const float lat_inc = M_PI / lat_res;
67         float lon, lat;
68
69         if (format.attrib_ct == 0) {
70                 pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
71                 nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
72         }
73
74         vbo = GWN_vertbuf_create_with_format(&format);
75         GWN_vertbuf_data_alloc(vbo, (lat_res - 1) * lon_res * 6);
76         vert = 0;
77
78         lon = 0.0f;
79         for (int i = 0; i < lon_res; i++, lon += lon_inc) {
80                 lat = 0.0f;
81                 for (int j = 0; j < lat_res; j++, lat += lat_inc) {
82                         if (j != lat_res - 1) { /* Pole */
83                                 batch_sphere_lat_lon_vert(lat + lat_inc, lon + lon_inc);
84                                 batch_sphere_lat_lon_vert(lat + lat_inc, lon);
85                                 batch_sphere_lat_lon_vert(lat,           lon);
86                         }
87
88                         if (j != 0) { /* Pole */
89                                 batch_sphere_lat_lon_vert(lat,           lon + lon_inc);
90                                 batch_sphere_lat_lon_vert(lat + lat_inc, lon + lon_inc);
91                                 batch_sphere_lat_lon_vert(lat,           lon);
92                         }
93                 }
94         }
95
96         return GWN_batch_create(GWN_PRIM_TRIS, vbo, NULL);
97 }
98
99 static Gwn_Batch *batch_sphere_wire(int lat_res, int lon_res)
100 {
101         const float lon_inc = 2 * M_PI / lon_res;
102         const float lat_inc = M_PI / lat_res;
103         float lon, lat;
104
105         if (format.attrib_ct == 0) {
106                 pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
107                 nor_id = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
108         }
109
110         vbo = GWN_vertbuf_create_with_format(&format);
111         GWN_vertbuf_data_alloc(vbo, (lat_res * lon_res * 2) + ((lat_res - 1) * lon_res * 2));
112         vert = 0;
113
114         lon = 0.0f;
115         for (int i = 0; i < lon_res; i++, lon += lon_inc) {
116                 lat = 0.0f;
117                 for (int j = 0; j < lat_res; j++, lat += lat_inc) {
118                         batch_sphere_lat_lon_vert(lat + lat_inc, lon);
119                         batch_sphere_lat_lon_vert(lat,           lon);
120
121                         if (j != lat_res - 1) { /* Pole */
122                                 batch_sphere_lat_lon_vert(lat + lat_inc, lon + lon_inc);
123                                 batch_sphere_lat_lon_vert(lat + lat_inc, lon);
124                         }
125                 }
126         }
127
128         return GWN_batch_create(GWN_PRIM_LINES, vbo, NULL);
129 }
130
131 Gwn_Batch *Batch_get_sphere(int lod)
132 {
133         BLI_assert(lod >= 0 && lod <= 2);
134
135         if (lod == 0)
136                 return sphere_low;
137         else if (lod == 1)
138                 return sphere_med;
139         else
140                 return sphere_high;
141 }
142
143 Gwn_Batch *Batch_get_sphere_wire(int lod)
144 {
145         BLI_assert(lod >= 0 && lod <= 1);
146
147         if (lod == 0)
148                 return sphere_wire_low;
149         else
150                 return sphere_wire_med;
151 }
152
153 void gpu_batch_init(void)
154 {
155         /* Hard coded resolution */
156         sphere_low = batch_sphere(8, 16);
157         sphere_med = batch_sphere(16, 10);
158         sphere_high = batch_sphere(32, 24);
159
160         sphere_wire_low = batch_sphere_wire(6, 8);
161         sphere_wire_med = batch_sphere_wire(8, 16);
162 }
163
164 void gpu_batch_exit(void)
165 {
166         GWN_batch_discard_all(sphere_low);
167         GWN_batch_discard_all(sphere_med);
168         GWN_batch_discard_all(sphere_high);
169         GWN_batch_discard_all(sphere_wire_low);
170         GWN_batch_discard_all(sphere_wire_med);
171 }