diff options
Diffstat (limited to 'source/blender/draw/engines/workbench')
5 files changed, 112 insertions, 55 deletions
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl index 1f14e506dcf..5b949a6d952 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -3,9 +3,15 @@ uniform mat4 ProjectionMatrix; uniform mat4 ModelMatrixInverse; uniform mat4 ModelViewMatrixInverse; uniform mat4 ModelMatrix; +uniform vec3 OrcoTexCoFactors[2]; uniform sampler2D depthBuffer; + uniform sampler3D densityTexture; +uniform sampler3D shadowTexture; +uniform sampler3D flameTexture; +uniform sampler1D flameColorTexture; +uniform sampler1D transferTexture; uniform int samplesLen = 256; uniform float stepLength; /* Step length in local space. */ @@ -62,15 +68,35 @@ float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction) { - scattering = vec3(0.0); - extinction = 1e-8; + vec3 co = ls_pos * 0.5 + 0.5; +#ifdef USE_COBA + float val = texture(densityTexture, co).r; + vec4 tval = texture(transferTexture, val) * densityScale; + tval.rgb = pow(tval.rgb, vec3(2.2)); + scattering = tval.rgb * 1500.0; + extinction = max(1e-4, tval.a * 50.0); +#else + float flame = texture(flameTexture, co).r; + vec4 emission = texture(flameColorTexture, flame); + float shadows = texture(shadowTexture, co).r; + vec4 density = texture(densityTexture, co); /* rgb: color, a: density */ + + scattering = density.rgb * density.a * densityScale; + extinction = max(1e-4, dot(scattering, vec3(0.33333))); - vec4 density = texture(densityTexture, ls_pos * 0.5 + 0.5); - density.rgb /= density.a; - density *= densityScale; + scattering *= shadows * M_PI; + /* 800 is arbitrary and here to mimic old viewport. TODO make it a parameter */ + scattering += pow(emission.rgb, vec3(2.2)) * emission.a * 800.0; +#endif +} - scattering = density.rgb; - extinction = max(1e-8, density.a); +void eval_volume_step(inout vec3 Lscat, float extinction, float step_len, out float Tr) +{ + Lscat *= phase_function_isotropic(); + /* Evaluate Scattering */ + Tr = exp(-extinction * step_len); + /* integrate along the current step segment */ + Lscat = (Lscat - Lscat * Tr) / extinction; } #define P(x) ((x + 0.5) * (1.0 / 16.0)) @@ -96,18 +122,15 @@ vec4 volume_integration( vec3 ls_pos = ray_ori + ray_dir * ray_len; vec3 Lscat; - float s_extinction; + float s_extinction, Tr; volume_properties(ls_pos, Lscat, s_extinction); - /* Evaluate Scattering */ - float Tr = exp(-s_extinction * step_len); - /* integrate along the current step segment */ - Lscat = (Lscat - Lscat * Tr) / s_extinction; + eval_volume_step(Lscat, s_extinction, step_len, Tr); /* accumulate and also take into account the transmittance from previous steps */ final_scattering += final_transmittance * Lscat; final_transmittance *= Tr; } - return vec4(final_scattering, 1.0 - final_transmittance); + return vec4(final_scattering, final_transmittance); } void main() @@ -134,15 +157,11 @@ void main() step_len = 1.0 / step_len; vec3 Lscat; - float s_extinction; + float s_extinction, Tr; volume_properties(localPos, Lscat, s_extinction); - /* Evaluate Scattering */ - float Tr = exp(-s_extinction * step_len); - /* integrate along the current step segment */ - Lscat = (Lscat - Lscat * Tr) / s_extinction; - - fragColor = vec4(Lscat, 1.0 - Tr); + eval_volume_step(Lscat, s_extinction, step_len, Tr); + fragColor = vec4(Lscat, Tr); #else vec2 screen_uv = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0).xy); bool is_persp = ProjectionMatrix[3][3] == 0.0; @@ -156,10 +175,13 @@ void main() vec3 vs_ray_dir = (is_persp) ? (vs_ray_end - vs_ray_ori) : vec3(0.0, 0.0, -1.0); vs_ray_dir /= abs(vs_ray_dir.z); - vec3 ls_ray_dir = mat3(ModelViewMatrixInverse) * vs_ray_dir; + vec3 ls_ray_dir = mat3(ModelViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1] * 2.0; vec3 ls_ray_ori = (ModelViewMatrixInverse * vec4(vs_ray_ori, 1.0)).xyz; vec3 ls_ray_end = (ModelViewMatrixInverse * vec4(vs_ray_end, 1.0)).xyz; + ls_ray_ori = (OrcoTexCoFactors[0] + ls_ray_ori * OrcoTexCoFactors[1]) * 2.0 - 1.0; + ls_ray_end = (OrcoTexCoFactors[0] + ls_ray_end * OrcoTexCoFactors[1]) * 2.0 - 1.0; + /* TODO: Align rays to volume center so that it mimics old behaviour of slicing the volume. */ float dist = line_unit_box_intersect_dist(ls_ray_ori, ls_ray_dir); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl index 90a22d9d02f..7ce21c3d5ca 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl @@ -1,5 +1,6 @@ uniform mat4 ModelViewProjectionMatrix; +uniform vec3 OrcoTexCoFactors[2]; uniform float slicePosition; uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */ @@ -23,9 +24,10 @@ void main() else { localPos = vec3(pos.xy, slicePosition * 2.0 - 1.0); } - - gl_Position = ModelViewProjectionMatrix * vec4(localPos, 1.0); + vec3 final_pos = localPos; #else - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 final_pos = pos; #endif + final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0]) / OrcoTexCoFactors[1]; + gl_Position = ModelViewProjectionMatrix * vec4(final_pos, 1.0); } diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 7fbe928d29e..a1345afcf11 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -649,7 +649,7 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o if (!psys_check_enabled(ob, psys, false)) { continue; } - if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { continue; } ParticleSettings *part = psys->part; @@ -701,7 +701,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) return; /* Do not draw solid in this case. */ } - if (!DRW_check_object_visible_within_active_context(ob)) { + if (!DRW_object_is_visible_in_active_context(ob) || (ob->dt < OB_SOLID)) { return; } diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 0d4329c9699..cb11864df54 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -420,7 +420,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O if (!psys_check_enabled(ob, psys, false)) { continue; } - if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { continue; } ParticleSettings *part = psys->part; @@ -487,7 +487,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) return; /* Do not draw solid in this case. */ } - if (!DRW_check_object_visible_within_active_context(ob)) { + if (!DRW_object_is_visible_in_active_context(ob) || (ob->dt < OB_SOLID)) { return; } diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index ea4152486af..b0c08a2dc28 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -35,7 +35,11 @@ static struct { struct GPUShader *volume_sh; + struct GPUShader *volume_coba_sh; struct GPUShader *volume_slice_sh; + struct GPUShader *volume_slice_coba_sh; + struct GPUTexture *dummy_tex; + struct GPUTexture *dummy_coba_tex; } e_data = {NULL}; extern char datatoc_workbench_volume_vert_glsl[]; @@ -47,21 +51,39 @@ void workbench_volume_engine_init(void) e_data.volume_sh = DRW_shader_create( datatoc_workbench_volume_vert_glsl, NULL, datatoc_workbench_volume_frag_glsl, NULL); + e_data.volume_coba_sh = DRW_shader_create( + datatoc_workbench_volume_vert_glsl, NULL, + datatoc_workbench_volume_frag_glsl, + "#define USE_COBA\n"); e_data.volume_slice_sh = DRW_shader_create( datatoc_workbench_volume_vert_glsl, NULL, - datatoc_workbench_volume_frag_glsl, "#define VOLUME_SLICE"); + datatoc_workbench_volume_frag_glsl, + "#define VOLUME_SLICE\n"); + e_data.volume_slice_coba_sh = DRW_shader_create( + datatoc_workbench_volume_vert_glsl, NULL, + datatoc_workbench_volume_frag_glsl, + "#define VOLUME_SLICE\n" + "#define USE_COBA\n"); + + float pixel[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + e_data.dummy_tex = GPU_texture_create_3D(1, 1, 1, GPU_RGBA8, pixel, NULL); + e_data.dummy_coba_tex = GPU_texture_create_1D(1, GPU_RGBA8, pixel, NULL); } } void workbench_volume_engine_free(void) { DRW_SHADER_FREE_SAFE(e_data.volume_sh); + DRW_SHADER_FREE_SAFE(e_data.volume_coba_sh); DRW_SHADER_FREE_SAFE(e_data.volume_slice_sh); + DRW_SHADER_FREE_SAFE(e_data.volume_slice_coba_sh); + DRW_TEXTURE_FREE_SAFE(e_data.dummy_tex); + DRW_TEXTURE_FREE_SAFE(e_data.dummy_coba_tex); } void workbench_volume_cache_init(WORKBENCH_Data *vedata) { - vedata->psl->volume_pass = DRW_pass_create("Volumes", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL | DRW_STATE_CULL_FRONT); + vedata->psl->volume_pass = DRW_pass_create("Volumes", DRW_STATE_WRITE_COLOR | DRW_STATE_TRANSMISSION | DRW_STATE_CULL_FRONT); } void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Object *ob, ModifierData *md) @@ -70,6 +92,7 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Objec SmokeDomainSettings *sds = smd->domain; WORKBENCH_PrivateData *wpd = vedata->stl->g_data; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + DRWShadingGroup *grp = NULL; /* Don't show smoke before simulation starts, this could be made an option in the future. */ if (!sds->fluid || CFRA < sds->point_cache[0]->startframe) { @@ -77,21 +100,26 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Objec } wpd->volumes_do = true; - - if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { + if (sds->use_coba) { + GPU_create_smoke_coba_field(smd); + } + else if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { GPU_create_smoke(smd, 0); } else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { GPU_create_smoke(smd, 1); } - if (sds->tex == NULL) { + if ((!sds->use_coba && sds->tex == NULL) || + (sds->use_coba && sds->tex_field == NULL)) + { return; } - if (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED && - sds->axis_slice_method == AXIS_SLICE_SINGLE) - { + const bool use_slice = (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED && + sds->axis_slice_method == AXIS_SLICE_SINGLE); + + if (use_slice) { float invviewmat[4][4]; DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); @@ -99,41 +127,46 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Objec ? axis_dominant_v3_single(invviewmat[2]) : sds->slice_axis - 1; - DRWShadingGroup *grp = DRW_shgroup_create(e_data.volume_slice_sh, vedata->psl->volume_pass); - DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex); - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness); + GPUShader *sh = (sds->use_coba) ? e_data.volume_slice_coba_sh : e_data.volume_slice_sh; + grp = DRW_shgroup_create(sh, vedata->psl->volume_pass); DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth); DRW_shgroup_uniform_int_copy(grp, "sliceAxis", axis); - DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT); - BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd)); - - /* TODO Flame rendering */ - /* TODO COBA Rendering */ - - DRW_shgroup_call_object_add(grp, DRW_cache_quad_get(), ob); } else { int max_slices = max_iii(sds->res[0], sds->res[1], sds->res[2]) * sds->slice_per_voxel; - DRWShadingGroup *grp = DRW_shgroup_create(e_data.volume_sh, vedata->psl->volume_pass); + GPUShader *sh = (sds->use_coba) ? e_data.volume_coba_sh : e_data.volume_sh; + grp = DRW_shgroup_create(sh, vedata->psl->volume_pass); DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex); - DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness); DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slices); /* TODO FIXME : This step size is in object space but the ray itself * is NOT unit length in object space so the required number of subdivisions * is tricky to get. */ DRW_shgroup_uniform_float_copy(grp, "stepLength", 8.0f / max_slices); - DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT); - BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd)); + } - /* TODO Flame rendering */ - /* TODO COBA Rendering */ + if (sds->use_coba) { + DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex_field); + DRW_shgroup_uniform_texture(grp, "transferTexture", sds->tex_coba); + } + else { + DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex); + DRW_shgroup_uniform_texture(grp, "shadowTexture", sds->tex_shadow); + DRW_shgroup_uniform_texture(grp, "flameTexture", (sds->tex_flame) ? sds->tex_flame : e_data.dummy_tex); + DRW_shgroup_uniform_texture(grp, "flameColorTexture", (sds->tex_flame) ? sds->tex_flame_coba : e_data.dummy_coba_tex); + } + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness); + DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT); + if (use_slice) { + DRW_shgroup_call_object_add(grp, DRW_cache_quad_get(), ob); + } + else { DRW_shgroup_call_object_add(grp, DRW_cache_cube_get(), ob); } + + BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd)); } void workbench_volume_smoke_textures_free(WORKBENCH_PrivateData *wpd) |