gpuray_glsl

view src/gpuscene.cc @ 4:2ed3da7dc0bc

broken
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 10 Nov 2014 01:26:00 +0200
parents f234630e38ff
children
line source
1 #include <algorithm>
2 #include <assert.h>
3 #include "gpuscene.h"
4 #include "sphere.h"
5 #include "plane.h"
6 #include "box.h"
7 #include "opengl.h"
9 GPUScene::GPUScene()
10 {
11 glGenTextures(NUM_TEXTURES, textures);
13 for(int i=0; i<NUM_TEXTURES; i++) {
14 glBindTexture(GL_TEXTURE_2D, textures[i]);
15 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
16 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
17 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
18 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
19 }
21 xform_buf = 0;
22 }
24 GPUScene::~GPUScene()
25 {
26 glDeleteTextures(NUM_TEXTURES, textures);
27 delete [] xform_buf;
28 }
30 bool GPUScene::create_textures()
31 {
32 // must be first to generate the megatecture rectangles
33 create_megatexture();
35 Sphere *sph;
36 Plane *plane;
37 Box *box;
38 Cone *cone;
40 std::vector<Sphere*> spheres;
41 std::vector<Plane*> planes;
42 std::vector<Box*> boxes;
43 std::vector<Cone*> cones;
45 // collect all objects into the different type-specific arrays
46 for(auto obj : objects) {
47 if((sph = dynamic_cast<Sphere*>(obj))) {
48 spheres.push_back(sph);
50 } else if((plane = dynamic_cast<Plane*>(obj))) {
51 planes.push_back(plane);
53 } else if((box = dynamic_cast<Box*>(obj))) {
54 boxes.push_back(box);
56 } else if((cone = dynamic_cast<Cone*>(obj))) {
57 cones.push_back(cone);
59 } else {
60 fprintf(stderr, "skipping object of unknown type: %s\n", obj->get_name());
61 }
62 }
64 create_sphere_texture(spheres);
65 create_plane_texture(planes);
66 create_box_texture(boxes);
67 create_cone_texture(cones);
69 create_env_texture();
70 create_xform_texture();
72 return true;
73 }
75 unsigned int GPUScene::get_texture(int which) const
76 {
77 return textures[which];
78 }
80 #define MAT_START 4
81 static void copy_material(Vector4 *ptr, const Material *mtl)
82 {
83 ptr[MAT_START].x = mtl->diffuse.x;
84 ptr[MAT_START].y = mtl->diffuse.y;
85 ptr[MAT_START].z = mtl->diffuse.z;
86 ptr[MAT_START].w = mtl->transparency;
88 ptr[MAT_START + 1].x = mtl->specular.x;
89 ptr[MAT_START + 1].y = mtl->specular.y;
90 ptr[MAT_START + 1].z = mtl->specular.z;
91 ptr[MAT_START + 1].w = mtl->shininess;
93 ptr[MAT_START + 2].x = mtl->reflectivity;
94 ptr[MAT_START + 2].y = mtl->ior;
96 ptr[MAT_START + 3] = mtl->mega_rect;
97 }
99 int GPUScene::object_index(const Object *obj) const
100 {
101 for(int i=0; i<(int)objects.size(); i++) {
102 if(objects[i] == obj) {
103 return i;
104 }
105 }
106 abort(); // can't happen
107 return -1;
108 }
110 #define OBJ_LINE_WIDTH 16
111 void GPUScene::create_sphere_texture(const std::vector<Sphere*> &spheres)
112 {
113 int xsz = OBJ_LINE_WIDTH;
114 int ysz = (int)spheres.size() + 1;
115 int tex_ysz = next_pow2(ysz);
117 Vector4 *pixels = new Vector4[xsz * tex_ysz];
119 pixels[0].x = (float)ysz;
120 pixels[0].y = (float)tex_ysz;
121 pixels[0].z = 0.5;
122 pixels[0].w = 1.0;
124 Vector4 *pixptr = pixels + xsz;
126 for(size_t i=0; i<spheres.size(); i++) {
127 pixptr[0].x = object_index(spheres[i]);
129 pixptr[1].x = spheres[i]->pos.x;
130 pixptr[1].y = spheres[i]->pos.y;
131 pixptr[1].z = spheres[i]->pos.z;
132 pixptr[1].w = spheres[i]->radius;
134 copy_material(pixptr, &spheres[i]->material);
135 pixptr += OBJ_LINE_WIDTH;
136 }
138 glBindTexture(GL_TEXTURE_2D, textures[TEX_SPHERE]);
139 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, pixels);
141 delete [] pixels;
142 }
144 void GPUScene::create_plane_texture(const std::vector<Plane*> &planes)
145 {
146 int xsz = OBJ_LINE_WIDTH;
147 int ysz = (int)planes.size() + 1;
148 int tex_ysz = next_pow2(ysz);
150 Vector4 *pixels = new Vector4[xsz * tex_ysz];
152 pixels[0].x = (float)ysz;
153 pixels[0].y = (float)tex_ysz;
155 Vector4 *pixptr = pixels + xsz;
157 for(size_t i=0; i<planes.size(); i++) {
158 pixptr[0].x = object_index(planes[i]);
160 pixptr[1].x = planes[i]->normal.x;
161 pixptr[1].y = planes[i]->normal.y;
162 pixptr[1].z = planes[i]->normal.z;
163 pixptr[1].w = planes[i]->dist;
165 copy_material(pixptr, &planes[i]->material);
166 pixptr += OBJ_LINE_WIDTH;
167 }
169 glBindTexture(GL_TEXTURE_2D, textures[TEX_PLANE]);
170 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, pixels);
172 delete [] pixels;
173 }
175 void GPUScene::create_box_texture(const std::vector<Box*> &boxes)
176 {
177 int xsz = OBJ_LINE_WIDTH;
178 int ysz = (int)boxes.size() + 1;
179 int tex_ysz = next_pow2(ysz);
181 Vector4 *pixels = new Vector4[xsz * tex_ysz];
183 pixels[0].x = (float)ysz;
184 pixels[0].y = (float)tex_ysz;
186 Vector4 *pixptr = pixels + xsz;
188 for(size_t i=0; i<boxes.size(); i++) {
189 pixptr[0].x = object_index(boxes[i]);
190 pixptr[1] = boxes[i]->min;
191 pixptr[2] = boxes[i]->max;
193 copy_material(pixptr, &boxes[i]->material);
194 pixptr += OBJ_LINE_WIDTH;
195 }
197 glBindTexture(GL_TEXTURE_2D, textures[TEX_BOX]);
198 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, pixels);
200 delete [] pixels;
201 }
203 void GPUScene::create_cone_texture(const std::vector<Cone*> &cones)
204 {
205 int xsz = OBJ_LINE_WIDTH;
206 int ysz = (int)cones.size() + 1;
207 int tex_ysz = next_pow2(ysz);
209 Vector4 *pixels = new Vector4[xsz * tex_ysz];
211 pixels[0].x = (float)ysz;
212 pixels[0].y = (float)tex_ysz;
214 Vector4 *pixptr = pixels + xsz;
216 for(size_t i=0; i<cones.size(); i++) {
217 pixptr[0].x = object_index(cones[i]);
219 pixptr[1].x = cones[i]->angle;
220 pixptr[1].y = cones[i]->ymin;
221 pixptr[1].z = cones[i]->ymax;
222 pixptr[1].w = 0.0;
224 copy_material(pixptr, &cones[i]->material);
225 pixptr += OBJ_LINE_WIDTH;
226 }
228 glBindTexture(GL_TEXTURE_2D, textures[TEX_SPHERE]);
229 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, pixels);
231 delete [] pixels;
232 }
235 void GPUScene::create_megatexture()
236 {
237 // at least a 1x1 dummy white texture
238 int xsz = 1;
239 int ysz = 1;
240 int num_textures = 0;
242 for(auto obj : objects) {
243 // only need 2D textures at this point
244 Texture *tex = dynamic_cast<Texture2D*>(obj->material.tex);
245 if(tex) {
246 const Image *img = tex->get_image();
248 xsz = std::max(xsz, img->xsz);
249 ysz += img->ysz;
250 num_textures++;
251 }
252 }
254 int tex_xsz = next_pow2(xsz);
255 int tex_ysz = next_pow2(ysz);
257 Color *pixels = new Color[tex_xsz * tex_ysz];
259 // null texture
260 pixels[0] = Color(1, 1, 1);
262 Color *pixptr = pixels + tex_xsz;
264 float offs_y = 0.0;
265 for(auto obj : objects) {
266 Texture *tex = dynamic_cast<Texture2D*>(obj->material.tex);
267 if(tex) {
268 const Image *img = tex->get_image();
270 Vector4 rect{0.0, offs_y, (float)img->xsz / (float)tex_xsz,
271 (float)img->ysz / (float)tex_ysz};
273 offs_y += rect.w;
275 obj->material.mega_rect = rect;
277 for(int i=0; i<img->ysz; i++) {
278 memcpy(pixptr, img->pixels + i * img->xsz, img->xsz * sizeof *pixels);
279 pixptr += tex_xsz;
280 }
281 } else {
282 obj->material.mega_rect = Vector4(0, 0, 0, 0);
283 }
284 }
286 glBindTexture(GL_TEXTURE_2D, textures[TEX_TEXTURE]);
287 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, tex_xsz, tex_ysz, 0, GL_RGB, GL_FLOAT, pixels);
289 delete [] pixels;
290 }
292 void GPUScene::create_env_texture()
293 {
294 // create the scene cubemap, or a null cubemap if we don't have one
295 glDeleteTextures(1, textures + TEX_ENV); // cause it's not a 2D texture :)
297 glGenTextures(1, textures + TEX_ENV);
298 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[TEX_ENV]);
299 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
300 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
301 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
302 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
303 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
305 if(envmap) {
306 // we have an environment cubemap, just pass the data to OpenGL
307 for(int i=0; i<6; i++) {
308 const Image *img = envmap->get_image(i);
310 int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
311 glTexImage2D(face, 0, GL_RGB16F, img->xsz, img->ysz, 0, GL_RGB, GL_FLOAT, img->pixels);
312 }
313 } else {
314 // we don't have an env cubemap, make a dummy 1x1 cubemap with the background color
315 for(int i=0; i<6; i++) {
316 int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
317 glTexImage2D(face, 0, GL_RGB16F, 1, 1, 0, GL_RGB, GL_FLOAT, &bgcolor);
318 }
319 }
320 }
322 #define XFORM_LINE_WIDTH OBJ_LINE_WIDTH
323 void GPUScene::create_xform_texture()
324 {
325 int tex_xsz = XFORM_LINE_WIDTH;
326 int tex_ysz = next_pow2((int)objects.size() + 1); // leave space for the descriptor
328 glBindTexture(GL_TEXTURE_2D, textures[TEX_XFORM]);
329 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, tex_xsz, tex_ysz, 0, GL_RGBA, GL_FLOAT, 0);
331 update_xform_texture();
332 }
334 void GPUScene::update_xform_texture()
335 {
336 int tex_xsz = XFORM_LINE_WIDTH;
337 int tex_ysz = next_pow2((int)objects.size() + 1); // leave space for the descriptor
339 if(!xform_buf) {
340 xform_buf = new Vector4[tex_xsz * tex_ysz];
341 xform_buf[0].x = tex_ysz; // descriptor
342 }
344 Vector4 *pixptr = xform_buf + tex_xsz;
345 for(auto obj : objects) {
346 for(int i=0; i<4; i++) {
347 pixptr[i] = obj->xform.get_column_vector(i);
348 pixptr[i + 4] = obj->inv_xform.get_column_vector(i);
349 }
350 pixptr += tex_xsz;
351 }
353 glBindTexture(GL_TEXTURE_2D, textures[TEX_XFORM]);
354 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex_xsz, tex_ysz, GL_RGBA, GL_FLOAT, xform_buf);
355 }