Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_view3d/drawvolume.c')
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c597
1 files changed, 295 insertions, 302 deletions
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index d6691f431dd..e93d840eddd 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -46,7 +46,9 @@
#include "BIF_gl.h"
-#include "GPU_extensions.h"
+#include "GPU_debug.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
#include "view3d_intern.h" // own include
@@ -59,375 +61,366 @@ struct GPUTexture;
# include "PIL_time_utildefines.h"
#endif
-static int intersect_edges(float (*points)[3], float a, float b, float c, float d, float edges[12][2][3])
+static GPUTexture *create_flame_spectrum_texture(void)
{
- int i;
- float t;
- int numpoints = 0;
-
- for (i = 0; i < 12; i++) {
- t = -(a * edges[i][0][0] + b * edges[i][0][1] + c * edges[i][0][2] + d) /
- (a * edges[i][1][0] + b * edges[i][1][1] + c * edges[i][1][2]);
- if ((t > 0) && (t < 1)) {
- points[numpoints][0] = edges[i][0][0] + edges[i][1][0] * t;
- points[numpoints][1] = edges[i][0][1] + edges[i][1][1] * t;
- points[numpoints][2] = edges[i][0][2] + edges[i][1][2] * t;
- numpoints++;
- }
- }
- return numpoints;
-}
-
-static bool convex(const float p0[3], const float up[3], const float a[3], const float b[3])
-{
- /* Vec3 va = a-p0, vb = b-p0; */
- float va[3], vb[3], tmp[3];
- sub_v3_v3v3(va, a, p0);
- sub_v3_v3v3(vb, b, p0);
- cross_v3_v3v3(tmp, va, vb);
- return dot_v3v3(up, tmp) >= 0;
-}
-
-void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
- GPUTexture *tex, const float min[3], const float max[3],
- const int res[3], float dx, float UNUSED(base_scale), const float viewnormal[3],
- GPUTexture *tex_shadow, GPUTexture *tex_flame)
-{
- const float ob_sizei[3] = {
- 1.0f / fabsf(ob->size[0]),
- 1.0f / fabsf(ob->size[1]),
- 1.0f / fabsf(ob->size[2])};
-
- int i, j, k, n, good_index;
- float d /*, d0 */ /* UNUSED */, dd, ds;
- float (*points)[3] = NULL;
- int numpoints = 0;
- float cor[3] = {1.0f, 1.0f, 1.0f};
- int gl_depth = 0, gl_blend = 0;
-
- const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) != 0;
-
- /* draw slices of smoke is adapted from c++ code authored
- * by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */
- float cv[][3] = {
- {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
- {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
- };
-
- /* edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] */
- float edges[12][2][3] = {
- {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
- {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
- {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
- {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
-
- {{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
- {{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
- {{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
- {{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
-
- {{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
- {{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
- {{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}},
- {{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}
- };
-
- unsigned char *spec_data;
- float *spec_pixels;
- GPUTexture *tex_spec;
- GPUProgram *smoke_program;
- int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED : GPU_PROGRAM_SMOKE;
- float size[3];
-
- if (!tex) {
- printf("Could not allocate 3D texture for 3D View smoke drawing.\n");
- return;
- }
-
-#ifdef DEBUG_DRAW_TIME
- TIMEIT_START(draw);
-#endif
-
- /* generate flame spectrum texture */
#define SPEC_WIDTH 256
#define FIRE_THRESH 7
#define MAX_FIRE_ALPHA 0.06f
#define FULL_ON_FIRE 100
- spec_data = malloc(SPEC_WIDTH * 4 * sizeof(unsigned char));
- flame_get_spectrum(spec_data, SPEC_WIDTH, 1500, 3000);
- spec_pixels = malloc(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float));
+
+ GPUTexture *tex;
+ int i, j, k;
+ float *spec_data = MEM_mallocN(SPEC_WIDTH * 4 * sizeof(float), "spec_data");
+ float *spec_pixels = MEM_mallocN(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels");
+
+ blackbody_temperature_to_rgb_table(spec_data, SPEC_WIDTH, 1500, 3000);
+
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++) {
for (k = 0; k < SPEC_WIDTH; k++) {
int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4;
if (k >= FIRE_THRESH) {
- spec_pixels[index] = ((float)spec_data[k * 4]) / 255.0f;
- spec_pixels[index + 1] = ((float)spec_data[k * 4 + 1]) / 255.0f;
- spec_pixels[index + 2] = ((float)spec_data[k * 4 + 2]) / 255.0f;
+ spec_pixels[index] = (spec_data[k * 4]);
+ spec_pixels[index + 1] = (spec_data[k * 4 + 1]);
+ spec_pixels[index + 2] = (spec_data[k * 4 + 2]);
spec_pixels[index + 3] = MAX_FIRE_ALPHA * (
(k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH));
}
else {
- spec_pixels[index] = spec_pixels[index + 1] = spec_pixels[index + 2] = spec_pixels[index + 3] = 0.0f;
+ zero_v4(&spec_pixels[index]);
}
}
}
}
- tex_spec = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);
+ tex = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);
+
+ MEM_freeN(spec_data);
+ MEM_freeN(spec_pixels);
#undef SPEC_WIDTH
#undef FIRE_THRESH
#undef MAX_FIRE_ALPHA
#undef FULL_ON_FIRE
- sub_v3_v3v3(size, max, min);
-
- /* maxx, maxy, maxz */
- cv[0][0] = max[0];
- cv[0][1] = max[1];
- cv[0][2] = max[2];
- /* minx, maxy, maxz */
- cv[1][0] = min[0];
- cv[1][1] = max[1];
- cv[1][2] = max[2];
- /* minx, miny, maxz */
- cv[2][0] = min[0];
- cv[2][1] = min[1];
- cv[2][2] = max[2];
- /* maxx, miny, maxz */
- cv[3][0] = max[0];
- cv[3][1] = min[1];
- cv[3][2] = max[2];
-
- /* maxx, maxy, minz */
- cv[4][0] = max[0];
- cv[4][1] = max[1];
- cv[4][2] = min[2];
- /* minx, maxy, minz */
- cv[5][0] = min[0];
- cv[5][1] = max[1];
- cv[5][2] = min[2];
- /* minx, miny, minz */
- cv[6][0] = min[0];
- cv[6][1] = min[1];
- cv[6][2] = min[2];
- /* maxx, miny, minz */
- cv[7][0] = max[0];
- cv[7][1] = min[1];
- cv[7][2] = min[2];
-
- copy_v3_v3(edges[0][0], cv[4]); /* maxx, maxy, minz */
- copy_v3_v3(edges[1][0], cv[5]); /* minx, maxy, minz */
- copy_v3_v3(edges[2][0], cv[6]); /* minx, miny, minz */
- copy_v3_v3(edges[3][0], cv[7]); /* maxx, miny, minz */
-
- copy_v3_v3(edges[4][0], cv[3]); /* maxx, miny, maxz */
- copy_v3_v3(edges[5][0], cv[2]); /* minx, miny, maxz */
- copy_v3_v3(edges[6][0], cv[6]); /* minx, miny, minz */
- copy_v3_v3(edges[7][0], cv[7]); /* maxx, miny, minz */
-
- copy_v3_v3(edges[8][0], cv[1]); /* minx, maxy, maxz */
- copy_v3_v3(edges[9][0], cv[2]); /* minx, miny, maxz */
- copy_v3_v3(edges[10][0], cv[6]); /* minx, miny, minz */
- copy_v3_v3(edges[11][0], cv[5]); /* minx, maxy, minz */
-
- // printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]);
- // printf("min[2]: %f, max[2]: %f\n", min[2], max[2]);
-
- edges[0][1][2] = size[2];
- edges[1][1][2] = size[2];
- edges[2][1][2] = size[2];
- edges[3][1][2] = size[2];
-
- edges[4][1][1] = size[1];
- edges[5][1][1] = size[1];
- edges[6][1][1] = size[1];
- edges[7][1][1] = size[1];
-
- edges[8][1][0] = size[0];
- edges[9][1][0] = size[0];
- edges[10][1][0] = size[0];
- edges[11][1][0] = size[0];
+ return tex;
+}
- glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
- glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);
+typedef struct VolumeSlicer {
+ float size[3];
+ float min[3];
+ float max[3];
+ float (*verts)[3];
+} VolumeSlicer;
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_BLEND);
+/* *************************** View Aligned Slicing ************************** */
+
+/* Code adapted from:
+ * "GPU-based Volume Rendering, Real-time Volume Graphics", AK Peters/CRC Press
+ */
+static int create_view_aligned_slices(VolumeSlicer *slicer,
+ const int num_slices,
+ const float view_dir[3])
+{
+ const int indices[] = { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5 };
+
+ const float vertices[8][3] = {
+ { slicer->min[0], slicer->min[1], slicer->min[2] },
+ { slicer->max[0], slicer->min[1], slicer->min[2] },
+ { slicer->max[0], slicer->max[1], slicer->min[2] },
+ { slicer->min[0], slicer->max[1], slicer->min[2] },
+ { slicer->min[0], slicer->min[1], slicer->max[2] },
+ { slicer->max[0], slicer->min[1], slicer->max[2] },
+ { slicer->max[0], slicer->max[1], slicer->max[2] },
+ { slicer->min[0], slicer->max[1], slicer->max[2] }
+ };
+
+ const int edges[12][2] = {
+ { 0, 1 }, { 1, 2 }, { 2, 3 },
+ { 3, 0 }, { 0, 4 }, { 1, 5 },
+ { 2, 6 }, { 3, 7 }, { 4, 5 },
+ { 5, 6 }, { 6, 7 }, { 7, 4 }
+ };
+
+ const int edge_list[8][12] = {
+ { 0, 1, 5, 6, 4, 8, 11, 9, 3, 7, 2, 10 },
+ { 0, 4, 3, 11, 1, 2, 6, 7, 5, 9, 8, 10 },
+ { 1, 5, 0, 8, 2, 3, 7, 4, 6, 10, 9, 11 },
+ { 7, 11, 10, 8, 2, 6, 1, 9, 3, 0, 4, 5 },
+ { 8, 5, 9, 1, 11, 10, 7, 6, 4, 3, 0, 2 },
+ { 9, 6, 10, 2, 8, 11, 4, 7, 5, 0, 1, 3 },
+ { 9, 8, 5, 4, 6, 1, 2, 0, 10, 7, 11, 3 },
+ { 10, 9, 6, 5, 7, 2, 3, 1, 11, 4, 8, 0 }
+ };
- /* find cube vertex that is closest to the viewer */
- for (i = 0; i < 8; i++) {
- float x, y, z;
+ /* find vertex that is the furthest from the view plane */
+ int max_index = 0;
+ float max_dist, min_dist;
+ min_dist = max_dist = dot_v3v3(view_dir, vertices[0]);
- x = cv[i][0] - viewnormal[0] * size[0] * 0.5f;
- y = cv[i][1] - viewnormal[1] * size[1] * 0.5f;
- z = cv[i][2] - viewnormal[2] * size[2] * 0.5f;
+ for (int i = 1; i < 8; i++) {
+ float dist = dot_v3v3(view_dir, vertices[i]);
- if ((x >= min[0]) && (x <= max[0]) &&
- (y >= min[1]) && (y <= max[1]) &&
- (z >= min[2]) && (z <= max[2]))
- {
- break;
+ if (dist > max_dist) {
+ max_dist = dist;
+ max_index = i;
+ }
+
+ if (dist < min_dist) {
+ min_dist = dist;
}
}
- if (i >= 8) {
- /* fallback, avoid using buffer over-run */
- i = 0;
+ max_dist -= FLT_EPSILON;
+ min_dist += FLT_EPSILON;
+
+ /* start and direction vectors */
+ float vec_start[12][3], vec_dir[12][3];
+ /* lambda intersection values */
+ float lambda[12], lambda_inc[12];
+ float denom = 0.0f;
+
+ float plane_dist = min_dist;
+ float plane_dist_inc = (max_dist - min_dist) / (float)num_slices;
+
+ /* for all egdes */
+ for (int i = 0; i < 12; i++) {
+ copy_v3_v3(vec_start[i], vertices[edges[edge_list[max_index][i]][0]]);
+ copy_v3_v3(vec_dir[i], vertices[edges[edge_list[max_index][i]][1]]);
+ sub_v3_v3(vec_dir[i], vec_start[i]);
+
+ denom = dot_v3v3(vec_dir[i], view_dir);
+
+ if (1.0f + denom != 1.0f) {
+ lambda_inc[i] = plane_dist_inc / denom;
+ lambda[i] = (plane_dist - dot_v3v3(vec_start[i], view_dir)) / denom;
+ }
+ else {
+ lambda[i] = -1.0f;
+ lambda_inc[i] = 0.0f;
+ }
}
- // printf("i: %d\n", i);
- // printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]);
+ float intersections[6][3];
+ float dL[12];
+ int num_points = 0;
+ /* find intersections for each slice, process them in back to front order */
+ for (int i = 0; i < num_slices; i++) {
+ for (int e = 0; e < 12; e++) {
+ dL[e] = lambda[e] + i * lambda_inc[e];
+ }
+
+ if ((dL[0] >= 0.0f) && (dL[0] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[0], vec_start[0], vec_dir[0], dL[0]);
+ }
+ else if ((dL[1] >= 0.0f) && (dL[1] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[0], vec_start[1], vec_dir[1], dL[1]);
+ }
+ else if ((dL[3] >= 0.0f) && (dL[3] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[0], vec_start[3], vec_dir[3], dL[3]);
+ }
+ else continue;
+
+ if ((dL[2] >= 0.0f) && (dL[2] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[1], vec_start[2], vec_dir[2], dL[2]);
+ }
+ else if ((dL[0] >= 0.0f) && (dL[0] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[1], vec_start[0], vec_dir[0], dL[0]);
+ }
+ else if ((dL[1] >= 0.0f) && (dL[1] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[1], vec_start[1], vec_dir[1], dL[1]);
+ }
+ else {
+ madd_v3_v3v3fl(intersections[1], vec_start[3], vec_dir[3], dL[3]);
+ }
+
+ if ((dL[4] >= 0.0f) && (dL[4] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[2], vec_start[4], vec_dir[4], dL[4]);
+ }
+ else if ((dL[5] >= 0.0f) && (dL[5] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[2], vec_start[5], vec_dir[5], dL[5]);
+ }
+ else {
+ madd_v3_v3v3fl(intersections[2], vec_start[7], vec_dir[7], dL[7]);
+ }
+
+ if ((dL[6] >= 0.0f) && (dL[6] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[3], vec_start[6], vec_dir[6], dL[6]);
+ }
+ else if ((dL[4] >= 0.0f) && (dL[4] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[3], vec_start[4], vec_dir[4], dL[4]);
+ }
+ else if ((dL[5] >= 0.0f) && (dL[5] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[3], vec_start[5], vec_dir[5], dL[5]);
+ }
+ else {
+ madd_v3_v3v3fl(intersections[3], vec_start[7], vec_dir[7], dL[7]);
+ }
+
+ if ((dL[8] >= 0.0f) && (dL[8] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[4], vec_start[8], vec_dir[8], dL[8]);
+ }
+ else if ((dL[9] >= 0.0f) && (dL[9] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[4], vec_start[9], vec_dir[9], dL[9]);
+ }
+ else {
+ madd_v3_v3v3fl(intersections[4], vec_start[11], vec_dir[11], dL[11]);
+ }
- smoke_program = GPU_shader_get_builtin_program(progtype);
- if (smoke_program) {
- GPU_program_bind(smoke_program);
+ if ((dL[10] >= 0.0f) && (dL[10] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[5], vec_start[10], vec_dir[10], dL[10]);
+ }
+ else if ((dL[8] >= 0.0f) && (dL[8] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[5], vec_start[8], vec_dir[8], dL[8]);
+ }
+ else if ((dL[9] >= 0.0f) && (dL[9] < 1.0f)) {
+ madd_v3_v3v3fl(intersections[5], vec_start[9], vec_dir[9], dL[9]);
+ }
+ else {
+ madd_v3_v3v3fl(intersections[5], vec_start[11], vec_dir[11], dL[11]);
+ }
- /* cell spacing */
- GPU_program_parameter_4f(smoke_program, 0, dx, dx, dx, 1.0);
- /* custom parameter for smoke style (higher = thicker) */
- if (sds->active_fields & SM_ACTIVE_COLORS)
- GPU_program_parameter_4f(smoke_program, 1, 1.0, 1.0, 1.0, 10.0);
- else
- GPU_program_parameter_4f(smoke_program, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0);
+ for (int e = 0; e < 12; e++) {
+ copy_v3_v3(slicer->verts[num_points++], intersections[indices[e]]);
+ }
}
- else
- printf("Your gfx card does not support 3D View smoke drawing.\n");
- GPU_texture_bind(tex, 0);
- if (tex_shadow)
- GPU_texture_bind(tex_shadow, 1);
- else
- printf("No volume shadow\n");
+ return num_points;
+}
- if (tex_flame) {
- GPU_texture_bind(tex_flame, 2);
- GPU_texture_bind(tex_spec, 3);
+void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
+ const float min[3], const float max[3],
+ const float viewnormal[3])
+{
+ if (!sds->tex || !sds->tex_shadow) {
+ fprintf(stderr, "Could not allocate 3D texture for volume rendering!\n");
+ return;
}
- if (!GPU_non_power_of_two_support()) {
- cor[0] = (float)res[0] / (float)power_of_2_max_u(res[0]);
- cor[1] = (float)res[1] / (float)power_of_2_max_u(res[1]);
- cor[2] = (float)res[2] / (float)power_of_2_max_u(res[2]);
+ const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) && sds->tex_flame;
+
+ GPUShader *shader = GPU_shader_get_builtin_shader(
+ (use_fire) ? GPU_SHADER_SMOKE_FIRE : GPU_SHADER_SMOKE);
+
+ if (!shader) {
+ fprintf(stderr, "Unable to create GLSL smoke shader.\n");
+ return;
}
- cor[0] /= size[0];
- cor[1] /= size[1];
- cor[2] /= size[2];
+ const float ob_sizei[3] = {
+ 1.0f / fabsf(ob->size[0]),
+ 1.0f / fabsf(ob->size[1]),
+ 1.0f / fabsf(ob->size[2])
+ };
+
+ const float size[3] = { max[0] - min[0], max[1] - min[1], max[2] - min[2] };
+ const float invsize[3] = { 1.0f / size[0], 1.0f / size[1], 1.0f / size[2] };
- /* our slices are defined by the plane equation a*x + b*y +c*z + d = 0
- * (a,b,c), the plane normal, are given by viewdir
- * d is the parameter along the view direction. the first d is given by
- * inserting previously found vertex into the plane equation */
+#ifdef DEBUG_DRAW_TIME
+ TIMEIT_START(draw);
+#endif
- /* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */
- ds = (fabsf(viewnormal[0]) * size[0] + fabsf(viewnormal[1]) * size[1] + fabsf(viewnormal[2]) * size[2]);
- dd = max_fff(sds->global_size[0], sds->global_size[1], sds->global_size[2]) / 128.f;
- n = 0;
- good_index = i;
+ /* setup smoke shader */
- // printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds);
+ int soot_location = GPU_shader_get_uniform(shader, "soot_texture");
+ int spec_location = GPU_shader_get_uniform(shader, "spectrum_texture");
+ int shadow_location = GPU_shader_get_uniform(shader, "shadow_texture");
+ int flame_location = GPU_shader_get_uniform(shader, "flame_texture");
+ int actcol_location = GPU_shader_get_uniform(shader, "active_color");
+ int stepsize_location = GPU_shader_get_uniform(shader, "step_size");
+ int densityscale_location = GPU_shader_get_uniform(shader, "density_scale");
+ int invsize_location = GPU_shader_get_uniform(shader, "invsize");
+ int ob_sizei_location = GPU_shader_get_uniform(shader, "ob_sizei");
+ int min_location = GPU_shader_get_uniform(shader, "min_location");
- points = MEM_callocN(sizeof(*points) * 12, "smoke_points_preview");
+ GPU_shader_bind(shader);
- while (1) {
- float p0[3];
- float tmp_point[3], tmp_point2[3];
+ GPU_texture_bind(sds->tex, 0);
+ GPU_shader_uniform_texture(shader, soot_location, sds->tex);
- if (dd * (float)n > ds)
- break;
+ GPU_texture_bind(sds->tex_shadow, 1);
+ GPU_shader_uniform_texture(shader, shadow_location, sds->tex_shadow);
- copy_v3_v3(tmp_point, viewnormal);
- mul_v3_fl(tmp_point, -dd * ((ds / dd) - (float)n));
- add_v3_v3v3(tmp_point2, cv[good_index], tmp_point);
- d = dot_v3v3(tmp_point2, viewnormal);
+ GPUTexture *tex_spec = NULL;
- // printf("my d: %f\n", d);
+ if (use_fire) {
+ GPU_texture_bind(sds->tex_flame, 2);
+ GPU_shader_uniform_texture(shader, flame_location, sds->tex_flame);
- /* intersect_edges returns the intersection points of all cube edges with
- * the given plane that lie within the cube */
- numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges);
+ tex_spec = create_flame_spectrum_texture();
+ GPU_texture_bind(tex_spec, 3);
+ GPU_shader_uniform_texture(shader, spec_location, tex_spec);
+ }
- // printf("points: %d\n", numpoints);
+ float active_color[3] = { 0.9, 0.9, 0.9 };
+ float density_scale = 10.0f;
+ if ((sds->active_fields & SM_ACTIVE_COLORS) == 0)
+ mul_v3_v3(active_color, sds->active_color);
- if (numpoints > 2) {
- copy_v3_v3(p0, points[0]);
+ GPU_shader_uniform_vector(shader, actcol_location, 3, 1, active_color);
+ GPU_shader_uniform_vector(shader, stepsize_location, 1, 1, &sds->dx);
+ GPU_shader_uniform_vector(shader, densityscale_location, 1, 1, &density_scale);
+ GPU_shader_uniform_vector(shader, min_location, 3, 1, min);
+ GPU_shader_uniform_vector(shader, ob_sizei_location, 3, 1, ob_sizei);
+ GPU_shader_uniform_vector(shader, invsize_location, 3, 1, invsize);
- /* sort points to get a convex polygon */
- for (i = 1; i < numpoints - 1; i++) {
- for (j = i + 1; j < numpoints; j++) {
- if (!convex(p0, viewnormal, points[j], points[i])) {
- swap_v3_v3(points[i], points[j]);
- }
- }
- }
+ /* setup slicing information */
- /* render fire slice */
- if (use_fire) {
- if (GLEW_VERSION_1_4)
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
- else
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-
- GPU_program_parameter_4f(smoke_program, 2, 1.0, 0.0, 0.0, 0.0);
- glBegin(GL_POLYGON);
- glColor3f(1.0, 1.0, 1.0);
- for (i = 0; i < numpoints; i++) {
- glTexCoord3d((points[i][0] - min[0]) * cor[0],
- (points[i][1] - min[1]) * cor[1],
- (points[i][2] - min[2]) * cor[2]);
- glVertex3f(points[i][0] * ob_sizei[0],
- points[i][1] * ob_sizei[1],
- points[i][2] * ob_sizei[2]);
- }
- glEnd();
- }
+ const int max_slices = 256;
+ const int max_points = max_slices * 12;
- /* render smoke slice */
- if (GLEW_VERSION_1_4)
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- else
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- GPU_program_parameter_4f(smoke_program, 2, -1.0, 0.0, 0.0, 0.0);
- glBegin(GL_POLYGON);
- glColor3f(1.0, 1.0, 1.0);
- for (i = 0; i < numpoints; i++) {
- glTexCoord3d((points[i][0] - min[0]) * cor[0],
- (points[i][1] - min[1]) * cor[1],
- (points[i][2] - min[2]) * cor[2]);
- glVertex3f(points[i][0] * ob_sizei[0],
- points[i][1] * ob_sizei[1],
- points[i][2] * ob_sizei[2]);
- }
- glEnd();
- }
- n++;
- }
+ VolumeSlicer slicer;
+ copy_v3_v3(slicer.min, min);
+ copy_v3_v3(slicer.max, max);
+ copy_v3_v3(slicer.size, size);
+ slicer.verts = MEM_mallocN(sizeof(float) * 3 * max_points, "smoke_slice_vertices");
+
+ const int num_points = create_view_aligned_slices(&slicer, max_slices, viewnormal);
+
+ /* setup buffer and draw */
+
+ int gl_depth = 0, gl_blend = 0;
+ glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
+ glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ GLuint vertex_buffer;
+ glGenBuffers(1, &vertex_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * num_points, &slicer.verts[0][0], GL_STATIC_DRAW);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, NULL);
+
+ glDrawArrays(GL_TRIANGLES, 0, num_points);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
#ifdef DEBUG_DRAW_TIME
printf("Draw Time: %f\n", (float)TIMEIT_VALUE(draw));
TIMEIT_END(draw);
#endif
- if (tex_shadow)
- GPU_texture_unbind(tex_shadow);
- GPU_texture_unbind(tex);
- if (tex_flame) {
- GPU_texture_unbind(tex_flame);
- GPU_texture_unbind(tex_spec);
- }
- GPU_texture_free(tex_spec);
+ /* cleanup */
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glDeleteBuffers(1, &vertex_buffer);
- free(spec_data);
- free(spec_pixels);
+ GPU_texture_unbind(sds->tex);
+ GPU_texture_unbind(sds->tex_shadow);
- if (smoke_program)
- GPU_program_unbind(smoke_program);
+ if (use_fire) {
+ GPU_texture_unbind(sds->tex_flame);
+ GPU_texture_unbind(tex_spec);
+ GPU_texture_free(tex_spec);
+ }
+ MEM_freeN(slicer.verts);
- MEM_freeN(points);
+ GPU_shader_unbind();
if (!gl_blend) {
glDisable(GL_BLEND);