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:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2016-08-28 17:50:49 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2016-08-28 17:50:59 +0300
commit116bab702e009ce8043b976b4a9c4afa4c7ff5b0 (patch)
treef8e6744eb82e9c5b1804b2f4d8cbf7c89bad430c /source/blender/editors/space_view3d
parenta5261e06a309982a47e207faf59194c59408dbad (diff)
Fix T47639: OpenGL render with smoke and fire incorrect when using
transparency. The issue is that we are rendering to a 0..1 clamped sRGB buffer with unpremultiplied alpha, where the correct thing to do would be to render to an unclamped linear premultiplied alpha buffer. Then we would just make fire purely emissive without affecting the alpha channel at all, but that doesn't work here. So for now, draw fire and smoke separately using different shaders and blend modes, like it used to before the smoke programs were rewritten (see rB0372b642).
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c193
1 files changed, 120 insertions, 73 deletions
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 8dbc2788744..06677ef4476 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -288,6 +288,108 @@ static int create_view_aligned_slices(VolumeSlicer *slicer,
return num_points;
}
+static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture *tex_spec,
+ bool use_fire, const float min[3],
+ const float ob_sizei[3], const float invsize[3])
+{
+ 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");
+
+ int soot_location;
+ int stepsize_location;
+ int densityscale_location;
+ int spec_location, flame_location;
+ int shadow_location, actcol_location;
+
+ if (use_fire) {
+ spec_location = GPU_shader_get_uniform(shader, "spectrum_texture");
+ flame_location = GPU_shader_get_uniform(shader, "flame_texture");
+ }
+ else {
+ shadow_location = GPU_shader_get_uniform(shader, "shadow_texture");
+ actcol_location = GPU_shader_get_uniform(shader, "active_color");
+ 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");
+ }
+
+ GPU_shader_bind(shader);
+
+ if (use_fire) {
+ GPU_texture_bind(sds->tex_flame, 2);
+ GPU_shader_uniform_texture(shader, flame_location, sds->tex_flame);
+
+ GPU_texture_bind(tex_spec, 3);
+ GPU_shader_uniform_texture(shader, spec_location, tex_spec);
+ }
+ else {
+ float density_scale = 10.0f;
+
+ GPU_shader_uniform_vector(shader, stepsize_location, 1, 1, &sds->dx);
+ GPU_shader_uniform_vector(shader, densityscale_location, 1, 1, &density_scale);
+
+ GPU_texture_bind(sds->tex, 0);
+ GPU_shader_uniform_texture(shader, soot_location, sds->tex);
+
+ GPU_texture_bind(sds->tex_shadow, 1);
+ GPU_shader_uniform_texture(shader, shadow_location, sds->tex_shadow);
+
+ float active_color[3] = { 0.9, 0.9, 0.9 };
+ 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);
+ }
+
+ 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);
+}
+
+static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec, bool use_fire)
+{
+ GPU_shader_unbind();
+
+ GPU_texture_unbind(sds->tex);
+
+ if (use_fire) {
+ GPU_texture_unbind(sds->tex_flame);
+ GPU_texture_unbind(tex_spec);
+ GPU_texture_free(tex_spec);
+ }
+ else {
+ GPU_texture_unbind(sds->tex_shadow);
+ }
+}
+
+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;
+
+ 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);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, NULL);
+
+ glDrawArrays(GL_TRIANGLES, 0, num_points);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ unbind_shader(sds, tex_spec, do_fire);
+
+ /* cleanup */
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDeleteBuffers(1, &vertex_buffer);
+}
+
void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
const float min[3], const float max[3],
const float viewnormal[3])
@@ -299,14 +401,23 @@ 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(
- (use_fire) ? GPU_SHADER_SMOKE_FIRE : GPU_SHADER_SMOKE);
+ GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_SMOKE);
if (!shader) {
fprintf(stderr, "Unable to create GLSL smoke shader.\n");
return;
}
+ GPUShader *fire_shader = NULL;
+ if (use_fire) {
+ fire_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SMOKE_FIRE);
+
+ if (!fire_shader) {
+ fprintf(stderr, "Unable to create GLSL fire shader.\n");
+ return;
+ }
+ }
+
const float ob_sizei[3] = {
1.0f / fabsf(ob->size[0]),
1.0f / fabsf(ob->size[1]),
@@ -320,50 +431,6 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
TIMEIT_START(draw);
#endif
- /* setup smoke shader */
-
- 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");
-
- GPU_shader_bind(shader);
-
- GPU_texture_bind(sds->tex, 0);
- GPU_shader_uniform_texture(shader, soot_location, sds->tex);
-
- GPU_texture_bind(sds->tex_shadow, 1);
- GPU_shader_uniform_texture(shader, shadow_location, sds->tex_shadow);
-
- GPUTexture *tex_spec = NULL;
-
- if (use_fire) {
- GPU_texture_bind(sds->tex_flame, 2);
- GPU_shader_uniform_texture(shader, flame_location, sds->tex_flame);
-
- tex_spec = create_flame_spectrum_texture();
- GPU_texture_bind(tex_spec, 3);
- GPU_shader_uniform_texture(shader, spec_location, tex_spec);
- }
-
- 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);
-
- 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);
-
/* setup slicing information */
const int max_slices = 256;
@@ -387,43 +454,23 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
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);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ draw_buffer(sds, shader, &slicer, ob_sizei, invsize, num_points, false);
- glDisableClientState(GL_VERTEX_ARRAY);
+ /* Draw fire separately (T47639). */
+ if (use_fire) {
+ glBlendFunc(GL_ONE, GL_ONE);
+ draw_buffer(sds, fire_shader, &slicer, ob_sizei, invsize, num_points, true);
+ }
#ifdef DEBUG_DRAW_TIME
printf("Draw Time: %f\n", (float)TIMEIT_VALUE(draw));
TIMEIT_END(draw);
#endif
- /* cleanup */
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glDeleteBuffers(1, &vertex_buffer);
-
- GPU_texture_unbind(sds->tex);
- GPU_texture_unbind(sds->tex_shadow);
-
- if (use_fire) {
- GPU_texture_unbind(sds->tex_flame);
- GPU_texture_unbind(tex_spec);
- GPU_texture_free(tex_spec);
- }
-
MEM_freeN(slicer.verts);
- GPU_shader_unbind();
-
glDepthMask(gl_depth_write);
if (!gl_blend) {