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:
authorDalai Felinto <dfelinto@gmail.com>2016-11-02 12:48:06 +0300
committerDalai Felinto <dfelinto@gmail.com>2016-11-02 12:59:52 +0300
commita41bbd3053c8f07c24ccb07eaeff09cc078cc4d4 (patch)
treeaed76b27fa7b6fde5023b6d3ecd5f5079ed24aad /source/blender/editors/space_view3d/drawvolume.c
parentfb6f42dc4f0dc24a992a631b7aac3290449e815a (diff)
parent13ee9b8ebe08ee95478f51537f10e9a1b1e4d863 (diff)
Merge remote-tracking branch 'origin/master' into blender2.8
Diffstat (limited to 'source/blender/editors/space_view3d/drawvolume.c')
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c187
1 files changed, 116 insertions, 71 deletions
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 9cfcd6cef05..584f442bd44 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -1,4 +1,4 @@
-/*
+/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -42,6 +42,7 @@
#include "BLI_math.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_texture.h"
#include "smoke_API.h"
@@ -62,28 +63,33 @@ struct GPUTexture;
# include "PIL_time_utildefines.h"
#endif
-static GPUTexture *create_flame_spectrum_texture(void)
+/* *************************** Transfer functions *************************** */
+
+enum {
+ TFUNC_FLAME_SPECTRUM = 0,
+ TFUNC_COLOR_RAMP = 1,
+};
+
+#define TFUNC_WIDTH 256
+
+static void create_flame_spectrum_texture(float *data)
{
-#define SPEC_WIDTH 256
#define FIRE_THRESH 7
#define MAX_FIRE_ALPHA 0.06f
#define FULL_ON_FIRE 100
- 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");
+ float *spec_pixels = MEM_mallocN(TFUNC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels");
- blackbody_temperature_to_rgb_table(spec_data, SPEC_WIDTH, 1500, 3000);
+ blackbody_temperature_to_rgb_table(data, TFUNC_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;
+ for (int i = 0; i < 16; i++) {
+ for (int j = 0; j < 16; j++) {
+ for (int k = 0; k < TFUNC_WIDTH; k++) {
+ int index = (j * TFUNC_WIDTH * 16 + i * TFUNC_WIDTH + k) * 4;
if (k >= FIRE_THRESH) {
- 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] = (data[k * 4]);
+ spec_pixels[index + 1] = (data[k * 4 + 1]);
+ spec_pixels[index + 2] = (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));
}
@@ -94,19 +100,69 @@ static GPUTexture *create_flame_spectrum_texture(void)
}
}
- tex = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);
+ memcpy(data, spec_pixels, sizeof(float) * 4 * TFUNC_WIDTH);
- MEM_freeN(spec_data);
MEM_freeN(spec_pixels);
-#undef SPEC_WIDTH
#undef FIRE_THRESH
#undef MAX_FIRE_ALPHA
#undef FULL_ON_FIRE
+}
+
+static void create_color_ramp(const ColorBand *coba, float *data)
+{
+ for (int i = 0; i < TFUNC_WIDTH; i++) {
+ do_colorband(coba, (float)i / TFUNC_WIDTH, &data[i * 4]);
+ }
+}
+
+static GPUTexture *create_transfer_function(int type, const ColorBand *coba)
+{
+ float *data = MEM_mallocN(sizeof(float) * 4 * TFUNC_WIDTH, __func__);
+
+ switch (type) {
+ case TFUNC_FLAME_SPECTRUM:
+ create_flame_spectrum_texture(data);
+ break;
+ case TFUNC_COLOR_RAMP:
+ create_color_ramp(coba, data);
+ break;
+ }
+
+ GPUTexture *tex = GPU_texture_create_1D(TFUNC_WIDTH, data, NULL);
+
+ MEM_freeN(data);
return tex;
}
+static GPUTexture *create_field_texture(SmokeDomainSettings *sds)
+{
+ float *field = NULL;
+
+ switch (sds->coba_field) {
+#ifdef WITH_SMOKE
+ case FLUID_FIELD_DENSITY: field = smoke_get_density(sds->fluid); break;
+ case FLUID_FIELD_HEAT: field = smoke_get_heat(sds->fluid); break;
+ case FLUID_FIELD_FUEL: field = smoke_get_fuel(sds->fluid); break;
+ case FLUID_FIELD_REACT: field = smoke_get_react(sds->fluid); break;
+ case FLUID_FIELD_FLAME: field = smoke_get_flame(sds->fluid); break;
+ case FLUID_FIELD_VELOCITY_X: field = smoke_get_velocity_x(sds->fluid); break;
+ case FLUID_FIELD_VELOCITY_Y: field = smoke_get_velocity_y(sds->fluid); break;
+ case FLUID_FIELD_VELOCITY_Z: field = smoke_get_velocity_z(sds->fluid); break;
+ case FLUID_FIELD_COLOR_R: field = smoke_get_color_r(sds->fluid); break;
+ case FLUID_FIELD_COLOR_G: field = smoke_get_color_g(sds->fluid); break;
+ case FLUID_FIELD_COLOR_B: field = smoke_get_color_b(sds->fluid); break;
+ case FLUID_FIELD_FORCE_X: field = smoke_get_force_x(sds->fluid); break;
+ case FLUID_FIELD_FORCE_Y: field = smoke_get_force_y(sds->fluid); break;
+ case FLUID_FIELD_FORCE_Z: field = smoke_get_force_z(sds->fluid); break;
+#endif
+ default: return NULL;
+ }
+
+ return GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, field);
+}
+
typedef struct VolumeSlicer {
float size[3];
float min[3];
@@ -347,6 +403,7 @@ static int create_view_aligned_slices(VolumeSlicer *slicer,
}
static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture *tex_spec,
+ GPUTexture *tex_tfunc, GPUTexture *tex_coba,
bool use_fire, const float min[3],
const float ob_sizei[3], const float invsize[3])
{
@@ -359,6 +416,8 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
int densityscale_location;
int spec_location, flame_location;
int shadow_location, actcol_location;
+ int tfunc_location = 0;
+ int coba_location = 0;
if (use_fire) {
spec_location = GPU_shader_get_uniform(shader, "spectrum_texture");
@@ -370,6 +429,11 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
soot_location = GPU_shader_get_uniform(shader, "soot_texture");
stepsize_location = GPU_shader_get_uniform(shader, "step_size");
densityscale_location = GPU_shader_get_uniform(shader, "density_scale");
+
+ if (sds->use_coba) {
+ tfunc_location = GPU_shader_get_uniform(shader, "transfer_texture");
+ coba_location = GPU_shader_get_uniform(shader, "color_band_texture");
+ }
}
GPU_shader_bind(shader);
@@ -397,6 +461,14 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
if ((sds->active_fields & SM_ACTIVE_COLORS) == 0)
mul_v3_v3(active_color, sds->active_color);
GPU_shader_uniform_vector(shader, actcol_location, 3, 1, active_color);
+
+ if (sds->use_coba) {
+ GPU_texture_bind(tex_tfunc, 4);
+ GPU_shader_uniform_texture(shader, tfunc_location, tex_tfunc);
+
+ GPU_texture_bind(tex_coba, 5);
+ GPU_shader_uniform_texture(shader, coba_location, tex_coba);
+ }
}
GPU_shader_uniform_vector(shader, min_location, 3, 1, min);
@@ -404,7 +476,8 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
GPU_shader_uniform_vector(shader, invsize_location, 3, 1, invsize);
}
-static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec, bool use_fire)
+static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec,
+ GPUTexture *tex_tfunc, GPUTexture *tex_coba, bool use_fire)
{
GPU_shader_unbind();
@@ -417,20 +490,30 @@ static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec, bool u
}
else {
GPU_texture_unbind(sds->tex_shadow);
+
+ if (sds->use_coba) {
+ GPU_texture_unbind(tex_tfunc);
+ GPU_texture_free(tex_tfunc);
+
+ GPU_texture_unbind(tex_coba);
+ GPU_texture_free(tex_coba);
+ }
}
}
static void draw_buffer(SmokeDomainSettings *sds, GPUShader *shader, const VolumeSlicer *slicer,
const float ob_sizei[3], const float invsize[3], const int num_points, const bool do_fire)
{
- GPUTexture *tex_spec = (do_fire) ? create_flame_spectrum_texture() : NULL;
+ GPUTexture *tex_spec = (do_fire) ? create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL) : NULL;
+ GPUTexture *tex_tfunc = (sds->use_coba) ? create_transfer_function(TFUNC_COLOR_RAMP, sds->coba) : NULL;
+ GPUTexture *tex_coba = (sds->use_coba) ? create_field_texture(sds) : NULL;
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);
- bind_shader(sds, shader, tex_spec, do_fire, slicer->min, ob_sizei, invsize);
+ bind_shader(sds, shader, tex_spec, tex_tfunc, tex_coba, do_fire, slicer->min, ob_sizei, invsize);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, NULL);
@@ -439,7 +522,7 @@ static void draw_buffer(SmokeDomainSettings *sds, GPUShader *shader, const Volum
glDisableClientState(GL_VERTEX_ARRAY);
- unbind_shader(sds, tex_spec, do_fire);
+ unbind_shader(sds, tex_spec, tex_tfunc, tex_coba, do_fire);
/* cleanup */
@@ -459,7 +542,16 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) && sds->tex_flame;
- GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_SMOKE);
+ GPUBuiltinShader builtin_shader;
+
+ if (sds->use_coba) {
+ builtin_shader = GPU_SHADER_SMOKE_COBA;
+ }
+ else {
+ builtin_shader = GPU_SHADER_SMOKE;
+ }
+
+ GPUShader *shader = GPU_shader_get_builtin_shader(builtin_shader);
if (!shader) {
fprintf(stderr, "Unable to create GLSL smoke shader.\n");
@@ -549,7 +641,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
draw_buffer(sds, shader, &slicer, ob_sizei, invsize, num_points, false);
/* Draw fire separately (T47639). */
- if (use_fire) {
+ if (use_fire && !sds->use_coba) {
glBlendFunc(GL_ONE, GL_ONE);
draw_buffer(sds, fire_shader, &slicer, ob_sizei, invsize, num_points, true);
}
@@ -759,50 +851,3 @@ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3])
UNUSED_VARS(domain, viewnormal);
#endif
}
-
-#ifdef SMOKE_DEBUG_HEAT
-void draw_smoke_heat(SmokeDomainSettings *domain, Object *ob)
-{
- float x, y, z;
- float x0, y0, z0;
- int *base_res = domain->base_res;
- int *res = domain->res;
- int *res_min = domain->res_min;
- int *res_max = domain->res_max;
- float *heat = smoke_get_heat(domain->fluid);
-
- float min[3];
- float *cell_size = domain->cell_size;
- float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.f;
- float vf = domain->scale / 16.f * 2.f; /* velocity factor */
-
- /* set first position so that it doesn't jump when domain moves */
- x0 = res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size);
- y0 = res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size);
- z0 = res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size);
- if (x0 < res_min[0]) x0 += step_size;
- if (y0 < res_min[1]) y0 += step_size;
- if (z0 < res_min[2]) z0 += step_size;
- add_v3_v3v3(min, domain->p0, domain->obj_shift_f);
-
- for (x = floor(x0); x < res_max[0]; x += step_size)
- for (y = floor(y0); y < res_max[1]; y += step_size)
- for (z = floor(z0); z < res_max[2]; z += step_size) {
- int index = (floor(x) - res_min[0]) + (floor(y) - res_min[1]) * res[0] + (floor(z) - res_min[2]) * res[0] * res[1];
-
- float pos[3] = {min[0] + ((float)x + 0.5f) * cell_size[0], min[1] + ((float)y + 0.5f) * cell_size[1], min[2] + ((float)z + 0.5f) * cell_size[2]};
-
- /* draw heat as different sized points */
- if (heat[index] >= 0.01f) {
- float col_gb = 1.0f - heat[index];
- CLAMP(col_gb, 0.0f, 1.0f);
- glColor3f(1.0f, col_gb, col_gb);
- glPointSize(24.0f * heat[index]);
-
- glBegin(GL_POINTS);
- glVertex3f(pos[0], pos[1], pos[2]);
- glEnd();
- }
- }
-}
-#endif