[Bf-blender-cvs] [0372b64] master: OpenGL: port smoke drawing code to GLSL.
Kévin Dietrich
noreply at git.blender.org
Sun Jan 10 07:36:53 CET 2016
Commit: 0372b642705c5304f252f7691b188fc65dd51b59
Author: Kévin Dietrich
Date: Sun Jan 10 07:36:23 2016 +0100
Branches: master
https://developer.blender.org/rB0372b642705c5304f252f7691b188fc65dd51b59
OpenGL: port smoke drawing code to GLSL.
Beside the obvious ARB -> GLSL change, the texture slicing algorithm had
to be rewritten.
Although this new algorithm has the same behaviour as the old one (view
aligned slicing), it works with an arbitrary number of slices (which
could eventually be set by the user), which means we can preallocate the
buffer. The previous algorithm would slice from the begining to the end
of the volume's bbox, and draw the slices as it generates them.
Also support for ARB program was removed.
Patch by myself, with some minor fixes by Brecht.
Reviewers: brecht, #opengl_gfx
Differential Revision: https://developer.blender.org/D1694
===================================================================
M source/blender/editors/space_view3d/drawvolume.c
M source/blender/gpu/CMakeLists.txt
M source/blender/gpu/GPU_shader.h
M source/blender/gpu/intern/gpu_shader.c
D source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl
D source/blender/gpu/shaders/gpu_program_smoke_frag.glsl
A source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
A source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl
===================================================================
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 72d84b4..591cf94 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -46,6 +46,7 @@
#include "BIF_gl.h"
+#include "GPU_debug.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -60,35 +61,6 @@ struct GPUTexture;
# include "PIL_time_utildefines.h"
#endif
-static int intersect_edges(float (*points)[3], float a, float b, float c, float d, const float edges[12][2][3])
-{
- 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;
-}
-
static GPUTexture *create_flame_spectrum_texture(void)
{
#define SPEC_WIDTH 256
@@ -134,218 +106,308 @@ static GPUTexture *create_flame_spectrum_texture(void)
return tex;
}
-void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
- const float min[3], const float max[3],
- const float viewnormal[3])
+typedef struct VolumeSlicer {
+ float size[3];
+ float min[3];
+ float max[3];
+ float (*verts)[3];
+} VolumeSlicer;
+
+/* *************************** 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])
{
- GPUTexture *tex_spec = NULL;
- GPUProgram *smoke_program;
- const int progtype = (sds->active_fields & SM_ACTIVE_COLORS) ? GPU_PROGRAM_SMOKE_COLORED
- : GPU_PROGRAM_SMOKE;
+ 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 float ob_sizei[3] = {
- 1.0f / fabsf(ob->size[0]),
- 1.0f / fabsf(ob->size[1]),
- 1.0f / fabsf(ob->size[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 }
};
- int i, j, n, good_index;
- float d /*, d0 */ /* UNUSED */, dd, ds;
- float (*points)[3] = NULL;
- int numpoints = 0;
- int gl_depth = 0, gl_blend = 0;
+ 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 }
+ };
- const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) != 0;
+ /* 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]);
- /* draw slices of smoke is adapted from c++ code authored
- * by: Johannes Schmid and Ingemar Rask, 2006, johnny at grob.org */
- const float verts[8][3] = {
- { max[0], max[1], max[2] },
- { min[0], max[1], max[2] },
- { min[0], min[1], max[2] },
- { max[0], min[1], max[2] },
- { max[0], max[1], min[2] },
- { min[0], max[1], min[2] },
- { min[0], min[1], min[2] },
- { max[0], min[1], min[2] }
- };
+ for (int i = 1; i < 8; i++) {
+ float dist = dot_v3v3(view_dir, vertices[i]);
- 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] };
+ if (dist > max_dist) {
+ max_dist = dist;
+ max_index = i;
+ }
- /* edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] */
- const float edges[12][2][3] = {
- {{verts[4][0], verts[4][1], verts[4][2]}, {0.0f, 0.0f, size[2]}},
- {{verts[5][0], verts[5][1], verts[5][2]}, {0.0f, 0.0f, size[2]}},
- {{verts[6][0], verts[6][1], verts[6][2]}, {0.0f, 0.0f, size[2]}},
- {{verts[7][0], verts[7][1], verts[7][2]}, {0.0f, 0.0f, size[2]}},
-
- {{verts[3][0], verts[3][1], verts[3][2]}, {0.0f, size[1], 0.0f}},
- {{verts[2][0], verts[2][1], verts[2][2]}, {0.0f, size[1], 0.0f}},
- {{verts[6][0], verts[6][1], verts[6][2]}, {0.0f, size[1], 0.0f}},
- {{verts[7][0], verts[7][1], verts[7][2]}, {0.0f, size[1], 0.0f}},
-
- {{verts[1][0], verts[1][1], verts[1][2]}, {size[0], 0.0f, 0.0f}},
- {{verts[2][0], verts[2][1], verts[2][2]}, {size[0], 0.0f, 0.0f}},
- {{verts[6][0], verts[6][1], verts[6][2]}, {size[0], 0.0f, 0.0f}},
- {{verts[5][0], verts[5][1], verts[5][2]}, {size[0], 0.0f, 0.0f}}
- };
+ if (dist < min_dist) {
+ min_dist = dist;
+ }
+ }
- if (!sds->tex) {
- printf("Could not allocate 3D texture for 3D View smoke drawing.\n");
- return;
+ 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;
+ }
}
-#ifdef DEBUG_DRAW_TIME
- TIMEIT_START(draw);
-#endif
+ 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];
+ }
- // 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]);
+ 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;
- glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
- glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);
+ 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]);
+ }
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_BLEND);
+ 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]);
+ }
- /* find cube vertex that is closest to the viewer */
- for (i = 0; i < 8; i++) {
- float x = verts[i][0] - viewnormal[0] * size[0] * 0.5f;
- float y = verts[i][1] - viewnormal[1] * size[1] * 0.5f;
- float z = verts[i][2] - viewnormal[2] * size[2] * 0.5f;
-
- if ((x >= min[0]) && (x <= max[0]) &&
- (y >= min[1]) && (y <= max[1]) &&
- (z >= min[2]) && (z <= max[2]))
- {
- break;
+ 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_d
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list