This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/draw/engines/eevee/eevee_volumes.c

616 lines
24 KiB
C
Raw Normal View History

/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
2019-01-23 11:29:18 +11:00
* Copyright 2016, Blender Foundation.
*/
/** \file \ingroup draw_engine
*
* Volumetric effects rendering using frostbite approach.
*/
#include "DRW_render.h"
#include "BLI_rand.h"
#include "BLI_string_utils.h"
2018-02-07 11:18:50 +11:00
#include "DNA_object_force_types.h"
#include "DNA_smoke_types.h"
#include "DNA_world_types.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
#include "ED_screen.h"
#include "DEG_depsgraph_query.h"
#include "eevee_private.h"
#include "GPU_draw.h"
#include "GPU_texture.h"
#include "GPU_material.h"
static struct {
char *volumetric_common_lib;
char *volumetric_common_lamps_lib;
struct GPUShader *volumetric_clear_sh;
struct GPUShader *volumetric_scatter_sh;
struct GPUShader *volumetric_scatter_with_lamps_sh;
struct GPUShader *volumetric_integration_sh;
struct GPUShader *volumetric_resolve_sh;
GPUTexture *color_src;
GPUTexture *depth_src;
/* List of all smoke domains rendered within this frame. */
ListBase smoke_domains;
} e_data = {NULL}; /* Engine data */
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_lamps_lib_glsl[];
extern char datatoc_volumetric_frag_glsl[];
extern char datatoc_volumetric_geom_glsl[];
extern char datatoc_volumetric_vert_glsl[];
extern char datatoc_volumetric_resolve_frag_glsl[];
extern char datatoc_volumetric_scatter_frag_glsl[];
extern char datatoc_volumetric_integration_frag_glsl[];
extern char datatoc_volumetric_lib_glsl[];
extern char datatoc_common_fullscreen_vert_glsl[];
static void eevee_create_shader_volumes(void)
{
e_data.volumetric_common_lib = BLI_string_joinN(
datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_volumetric_lib_glsl);
e_data.volumetric_common_lamps_lib = BLI_string_joinN(
datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_octahedron_lib_glsl,
datatoc_irradiance_lib_glsl,
datatoc_lamps_lib_glsl,
datatoc_volumetric_lib_glsl);
2017-11-20 14:28:24 +11:00
e_data.volumetric_clear_sh = DRW_shader_create_with_lib(
datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
datatoc_volumetric_frag_glsl,
e_data.volumetric_common_lib,
2017-11-20 14:28:24 +11:00
"#define VOLUMETRICS\n"
"#define CLEAR\n");
2017-11-20 14:28:24 +11:00
e_data.volumetric_scatter_sh = DRW_shader_create_with_lib(
datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
datatoc_volumetric_scatter_frag_glsl,
e_data.volumetric_common_lamps_lib,
2017-11-20 14:28:24 +11:00
SHADER_DEFINES
"#define VOLUMETRICS\n"
"#define VOLUME_SHADOW\n");
e_data.volumetric_scatter_with_lamps_sh = DRW_shader_create_with_lib(
datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
datatoc_volumetric_scatter_frag_glsl,
e_data.volumetric_common_lamps_lib,
SHADER_DEFINES
"#define VOLUMETRICS\n"
"#define VOLUME_LIGHTING\n"
"#define VOLUME_SHADOW\n");
2017-11-20 14:28:24 +11:00
e_data.volumetric_integration_sh = DRW_shader_create_with_lib(
datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
datatoc_volumetric_integration_frag_glsl,
e_data.volumetric_common_lib, NULL);
2017-11-20 14:28:24 +11:00
e_data.volumetric_resolve_sh = DRW_shader_create_with_lib(
datatoc_common_fullscreen_vert_glsl, NULL,
2017-11-20 14:28:24 +11:00
datatoc_volumetric_resolve_frag_glsl,
e_data.volumetric_common_lib, NULL);
}
2018-05-11 07:48:52 +02:00
void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample)
2018-02-02 01:18:25 +01:00
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
double ht_point[3];
double ht_offset[3] = {0.0, 0.0};
2018-05-11 07:48:52 +02:00
uint ht_primes[3] = {3, 7, 2};
2018-02-02 01:18:25 +01:00
BLI_halton_3D(ht_primes, ht_offset, current_sample, ht_point);
common_data->vol_jitter[0] = (float)ht_point[0];
common_data->vol_jitter[1] = (float)ht_point[1];
common_data->vol_jitter[2] = (float)ht_point[2];
}
int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
const float *viewport_size = DRW_viewport_size_get();
BLI_listbase_clear(&e_data.smoke_domains);
if (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_ENABLED) {
/* Shaders */
if (!e_data.volumetric_scatter_sh) {
eevee_create_shader_volumes();
}
const int tile_size = scene_eval->eevee.volumetric_tile_size;
/* Find Froxel Texture resolution. */
int tex_size[3];
tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
tex_size[2] = max_ii(scene_eval->eevee.volumetric_samples, 1);
common_data->vol_coord_scale[0] = viewport_size[0] / (float)(tile_size * tex_size[0]);
common_data->vol_coord_scale[1] = viewport_size[1] / (float)(tile_size * tex_size[1]);
/* TODO compute snap to maxZBuffer for clustered rendering */
if ((common_data->vol_tex_size[0] != tex_size[0]) ||
(common_data->vol_tex_size[1] != tex_size[1]) ||
(common_data->vol_tex_size[2] != tex_size[2]))
{
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
GPUFramebuffer: Refactor (Part 2) This refactor modernise the use of framebuffers. It also touches a lot of files so breaking down changes we have: - GPUTexture: Allow textures to be attached to more than one GPUFrameBuffer. This allows to create and configure more FBO without the need to attach and detach texture at drawing time. - GPUFrameBuffer: The wrapper starts to mimic opengl a bit closer. This allows to configure the framebuffer inside a context other than the one that will be rendering the framebuffer. We do the actual configuration when binding the FBO. We also Keep track of config validity and save drawbuffers state in the FBO. We remove the different bind/unbind functions. These make little sense now that we have separate contexts. - DRWFrameBuffer: We replace DRW_framebuffer functions by GPU_framebuffer ones to avoid another layer of abstraction. We move the DRW convenience functions to GPUFramebuffer instead and even add new ones. The MACRO GPU_framebuffer_ensure_config is pretty much all you need to create and config a GPUFramebuffer. - DRWTexture: Due to the removal of DRWFrameBuffer, we needed to create functions to create textures for thoses framebuffers. Pool textures are now using default texture parameters for the texture type asked. - DRWManager: Make sure no framebuffer object is bound when doing cache filling. - GPUViewport: Add new color_only_fb and depth_only_fb along with FB API usage update. This let draw engines render to color/depth only target and without the need to attach/detach textures. - WM_window: Assert when a framebuffer is bound when changing context. This balance the fact we are not track ogl context inside GPUFramebuffer. - Eevee, Clay, Mode engines: Update to new API. This comes with a lot of code simplification. This also come with some cleanups in some engine codes.
2018-03-25 17:46:48 +02:00
GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
common_data->vol_tex_size[0] = tex_size[0];
common_data->vol_tex_size[1] = tex_size[1];
common_data->vol_tex_size[2] = tex_size[2];
common_data->vol_inv_tex_size[0] = 1.0f / (float)(tex_size[0]);
common_data->vol_inv_tex_size[1] = 1.0f / (float)(tex_size[1]);
common_data->vol_inv_tex_size[2] = 1.0f / (float)(tex_size[2]);
}
/* Like frostbite's paper, 5% blend of the new frame. */
common_data->vol_history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
if (txl->volume_prop_scattering == NULL) {
/* Volume properties: We evaluate all volumetric objects
* and store their final properties into each froxel */
txl->volume_prop_scattering = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
txl->volume_prop_extinction = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
txl->volume_prop_emission = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
txl->volume_prop_phase = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
GPU_RG16F, DRW_TEX_FILTER, NULL);
/* Volume scattering: We compute for each froxel the
* Scattered light towards the view. We also resolve temporal
* super sampling during this stage. */
txl->volume_scatter = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
txl->volume_transmittance = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
/* Final integration: We compute for each froxel the
* amount of scattered light and extinction coef at this
* given depth. We use theses textures as double buffer
* for the volumetric history. */
txl->volume_scatter_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
txl->volume_transmittance_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
}
/* Temporal Super sampling jitter */
2018-05-11 07:48:52 +02:00
uint ht_primes[3] = {3, 7, 2};
uint current_sample = 0;
/* If TAA is in use do not use the history buffer. */
bool do_taa = ((effects->enabled_effects & EFFECT_TAA) != 0);
if (draw_ctx->evil_C != NULL) {
struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
do_taa = do_taa && (ED_screen_animation_no_scrub(wm) == NULL);
}
if (do_taa) {
common_data->vol_history_alpha = 0.0f;
current_sample = effects->taa_current_sample - 1;
effects->volume_current_sample = -1;
}
else {
2018-05-11 07:48:52 +02:00
const uint max_sample = (ht_primes[0] * ht_primes[1] * ht_primes[2]);
current_sample = effects->volume_current_sample = (effects->volume_current_sample + 1) % max_sample;
if (current_sample != max_sample - 1) {
DRW_viewport_request_redraw();
}
}
2018-02-02 01:18:25 +01:00
EEVEE_volumes_set_jitter(sldata, current_sample);
/* Framebuffer setup */
GPUFramebuffer: Refactor (Part 2) This refactor modernise the use of framebuffers. It also touches a lot of files so breaking down changes we have: - GPUTexture: Allow textures to be attached to more than one GPUFrameBuffer. This allows to create and configure more FBO without the need to attach and detach texture at drawing time. - GPUFrameBuffer: The wrapper starts to mimic opengl a bit closer. This allows to configure the framebuffer inside a context other than the one that will be rendering the framebuffer. We do the actual configuration when binding the FBO. We also Keep track of config validity and save drawbuffers state in the FBO. We remove the different bind/unbind functions. These make little sense now that we have separate contexts. - DRWFrameBuffer: We replace DRW_framebuffer functions by GPU_framebuffer ones to avoid another layer of abstraction. We move the DRW convenience functions to GPUFramebuffer instead and even add new ones. The MACRO GPU_framebuffer_ensure_config is pretty much all you need to create and config a GPUFramebuffer. - DRWTexture: Due to the removal of DRWFrameBuffer, we needed to create functions to create textures for thoses framebuffers. Pool textures are now using default texture parameters for the texture type asked. - DRWManager: Make sure no framebuffer object is bound when doing cache filling. - GPUViewport: Add new color_only_fb and depth_only_fb along with FB API usage update. This let draw engines render to color/depth only target and without the need to attach/detach textures. - WM_window: Assert when a framebuffer is bound when changing context. This balance the fact we are not track ogl context inside GPUFramebuffer. - Eevee, Clay, Mode engines: Update to new API. This comes with a lot of code simplification. This also come with some cleanups in some engine codes.
2018-03-25 17:46:48 +02:00
GPU_framebuffer_ensure_config(&fbl->volumetric_fb, {
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(txl->volume_prop_scattering),
GPU_ATTACHMENT_TEXTURE(txl->volume_prop_extinction),
GPU_ATTACHMENT_TEXTURE(txl->volume_prop_emission),
GPU_ATTACHMENT_TEXTURE(txl->volume_prop_phase)
});
GPU_framebuffer_ensure_config(&fbl->volumetric_scat_fb, {
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(txl->volume_scatter),
GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance)
});
GPU_framebuffer_ensure_config(&fbl->volumetric_integ_fb, {
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_history),
GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_history)
});
float integration_start = scene_eval->eevee.volumetric_start;
float integration_end = scene_eval->eevee.volumetric_end;
common_data->vol_light_clamp = scene_eval->eevee.volumetric_light_clamp;
common_data->vol_shadow_steps = (float)scene_eval->eevee.volumetric_shadow_samples;
if ((scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_SHADOWS) == 0) {
common_data->vol_shadow_steps = 0;
}
if (DRW_viewport_is_persp_get()) {
float sample_distribution = scene_eval->eevee.volumetric_sample_distribution;
sample_distribution = 4.0f * (1.00001f - sample_distribution);
const float clip_start = common_data->view_vecs[0][2];
/* Negate */
float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f);
float far = integration_end = min_ff(-integration_end, near - 1e-4f);
common_data->vol_depth_param[0] = (far - near * exp2(1.0f / sample_distribution)) / (far - near);
common_data->vol_depth_param[1] = (1.0f - common_data->vol_depth_param[0]) / near;
common_data->vol_depth_param[2] = sample_distribution;
}
else {
const float clip_start = common_data->view_vecs[0][2];
const float clip_end = clip_start + common_data->view_vecs[1][2];
integration_start = min_ff(integration_end, clip_start);
integration_end = max_ff(-integration_end, clip_end);
common_data->vol_depth_param[0] = integration_start;
common_data->vol_depth_param[1] = integration_end;
common_data->vol_depth_param[2] = 1.0f / (integration_end - integration_start);
}
/* Disable clamp if equal to 0. */
if (common_data->vol_light_clamp == 0.0) {
common_data->vol_light_clamp = FLT_MAX;
}
common_data->vol_use_lights = (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_LIGHTS) != 0;
return EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER;
}
/* Cleanup to release memory */
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
GPUFramebuffer: Refactor (Part 2) This refactor modernise the use of framebuffers. It also touches a lot of files so breaking down changes we have: - GPUTexture: Allow textures to be attached to more than one GPUFrameBuffer. This allows to create and configure more FBO without the need to attach and detach texture at drawing time. - GPUFrameBuffer: The wrapper starts to mimic opengl a bit closer. This allows to configure the framebuffer inside a context other than the one that will be rendering the framebuffer. We do the actual configuration when binding the FBO. We also Keep track of config validity and save drawbuffers state in the FBO. We remove the different bind/unbind functions. These make little sense now that we have separate contexts. - DRWFrameBuffer: We replace DRW_framebuffer functions by GPU_framebuffer ones to avoid another layer of abstraction. We move the DRW convenience functions to GPUFramebuffer instead and even add new ones. The MACRO GPU_framebuffer_ensure_config is pretty much all you need to create and config a GPUFramebuffer. - DRWTexture: Due to the removal of DRWFrameBuffer, we needed to create functions to create textures for thoses framebuffers. Pool textures are now using default texture parameters for the texture type asked. - DRWManager: Make sure no framebuffer object is bound when doing cache filling. - GPUViewport: Add new color_only_fb and depth_only_fb along with FB API usage update. This let draw engines render to color/depth only target and without the need to attach/detach textures. - WM_window: Assert when a framebuffer is bound when changing context. This balance the fact we are not track ogl context inside GPUFramebuffer. - Eevee, Clay, Mode engines: Update to new API. This comes with a lot of code simplification. This also come with some cleanups in some engine codes.
2018-03-25 17:46:48 +02:00
GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
return 0;
}
void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
LightCache *lcache = stl->g_data->light_cache;
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
DRWShadingGroup *grp = NULL;
/* Quick breakdown of the Volumetric rendering:
*
* The rendering is separated in 4 stages:
*
* - Material Parameters : we collect volume properties of
* all participating media in the scene and store them in
* a 3D texture aligned with the 3D frustum.
* This is done in 2 passes, one that clear the texture
* and/or evaluate the world volumes, and the 2nd one that
* additively render object volumes.
*
* - Light Scattering : the volume properties then are sampled
* and light scattering is evaluated for each cell of the
2018-09-18 16:35:13 +10:00
* volume texture. Temporal super-sampling (if enabled) occurs here.
*
* - Volume Integration : the scattered light and extinction is
2018-09-18 16:35:13 +10:00
* integrated (accumulated) along the view-rays. The result is stored
* for every cell in another texture.
*
2018-09-18 16:35:13 +10:00
* - Full-screen Resolve : From the previous stage, we get two
* 3D textures that contains integrated scattered light and extinction
* for "every" positions in the frustum. We only need to sample
2018-09-18 16:35:13 +10:00
* them and blend the scene color with those factors. This also
* work for alpha blended materials.
**/
/* World pass is not additive as it also clear the buffer. */
psl->volumetric_world_ps = DRW_pass_create("Volumetric World", DRW_STATE_WRITE_COLOR);
/* World Volumetric */
struct World *wo = scene->world;
if (wo != NULL && wo->use_nodes && wo->nodetree) {
struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
grp = DRW_shgroup_material_empty_tri_batch_create(mat,
psl->volumetric_world_ps,
common_data->vol_tex_size[2]);
if (grp) {
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
2018-09-19 18:19:49 +02:00
/* TODO (fclem): remove those (need to clean the GLSL files). */
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
}
}
if (grp == NULL) {
/* If no world or volume material is present just clear the buffer with this drawcall */
grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_clear_sh,
psl->volumetric_world_ps,
common_data->vol_tex_size[2]);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
}
/* Volumetric Objects */
psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties", DRW_STATE_WRITE_COLOR |
DRW_STATE_ADDITIVE);
struct GPUShader *scatter_sh = (common_data->vol_use_lights) ? e_data.volumetric_scatter_with_lamps_sh
: e_data.volumetric_scatter_sh;
psl->volumetric_scatter_ps = DRW_pass_create("Volumetric Scattering", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_empty_tri_batch_create(scatter_sh, psl->volumetric_scatter_ps,
common_data->vol_tex_size[2]);
DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &lcache->grid_tx.tex);
DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_prop_scattering);
DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_prop_extinction);
DRW_shgroup_uniform_texture_ref(grp, "volumeEmission", &txl->volume_prop_emission);
DRW_shgroup_uniform_texture_ref(grp, "volumePhase", &txl->volume_prop_phase);
DRW_shgroup_uniform_texture_ref(grp, "historyScattering", &txl->volume_scatter_history);
DRW_shgroup_uniform_texture_ref(grp, "historyTransmittance", &txl->volume_transmittance_history);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
psl->volumetric_integration_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh,
psl->volumetric_integration_ps,
common_data->vol_tex_size[2]);
DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmittance);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps);
DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter);
DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmittance);
DRW_shgroup_uniform_texture_ref(grp, "inSceneColor", &e_data.color_src);
DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
}
void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Scene *scene, Object *ob)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
float *texcoloc = NULL;
float *texcosize = NULL;
struct ModifierData *md = NULL;
Material *ma = give_current_material(ob, 1);
if (ma == NULL) {
return;
}
struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
/* If shader failed to compile or is currently compiling. */
if (GPU_material_status(mat) != GPU_MAT_SUCCESS) {
return;
}
DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, sldata->common_data.vol_tex_size[2]);
/* Making sure it's updated. */
invert_m4_m4(ob->imat, ob->obmat);
BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize);
2018-09-19 18:19:49 +02:00
/* TODO(fclem) remove those "unnecessary" UBOs */
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_mat4(grp, "volumeObjectMatrix", ob->imat);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
/* Smoke Simulation */
if (((ob->base_flag & BASE_FROM_DUPLI) == 0) &&
(md = modifiers_findByType(ob, eModifierType_Smoke)) &&
(modifier_isEnabled(scene, md, eModifierMode_Realtime)))
{
SmokeModifierData *smd = (SmokeModifierData *)md;
SmokeDomainSettings *sds = smd->domain;
if (sds == NULL) {
return;
}
/* Don't show smoke before simulation starts, this could be made an option in the future. */
const bool show_smoke = ((int)DEG_get_ctime(draw_ctx->depsgraph) >= sds->point_cache[0]->startframe);
if (sds->fluid && show_smoke) {
if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOW_HIGHRES)) {
GPU_create_smoke(smd, 0);
}
else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOW_HIGHRES)) {
GPU_create_smoke(smd, 1);
}
BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(smd));
}
if (sds->tex != NULL) {
DRW_shgroup_uniform_texture_ref(grp, "sampdensity", &sds->tex);
}
if (sds->tex_flame != NULL) {
DRW_shgroup_uniform_texture_ref(grp, "sampflame", &sds->tex_flame);
}
/* Output is such that 0..1 maps to 0..1000K */
DRW_shgroup_uniform_vec2(grp, "unftemperature", &sds->flame_ignition, 1);
}
}
void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
DRW_stats_group_start("Volumetrics");
/* Step 1: Participating Media Properties */
GPUFramebuffer: Refactor (Part 2) This refactor modernise the use of framebuffers. It also touches a lot of files so breaking down changes we have: - GPUTexture: Allow textures to be attached to more than one GPUFrameBuffer. This allows to create and configure more FBO without the need to attach and detach texture at drawing time. - GPUFrameBuffer: The wrapper starts to mimic opengl a bit closer. This allows to configure the framebuffer inside a context other than the one that will be rendering the framebuffer. We do the actual configuration when binding the FBO. We also Keep track of config validity and save drawbuffers state in the FBO. We remove the different bind/unbind functions. These make little sense now that we have separate contexts. - DRWFrameBuffer: We replace DRW_framebuffer functions by GPU_framebuffer ones to avoid another layer of abstraction. We move the DRW convenience functions to GPUFramebuffer instead and even add new ones. The MACRO GPU_framebuffer_ensure_config is pretty much all you need to create and config a GPUFramebuffer. - DRWTexture: Due to the removal of DRWFrameBuffer, we needed to create functions to create textures for thoses framebuffers. Pool textures are now using default texture parameters for the texture type asked. - DRWManager: Make sure no framebuffer object is bound when doing cache filling. - GPUViewport: Add new color_only_fb and depth_only_fb along with FB API usage update. This let draw engines render to color/depth only target and without the need to attach/detach textures. - WM_window: Assert when a framebuffer is bound when changing context. This balance the fact we are not track ogl context inside GPUFramebuffer. - Eevee, Clay, Mode engines: Update to new API. This comes with a lot of code simplification. This also come with some cleanups in some engine codes.
2018-03-25 17:46:48 +02:00
GPU_framebuffer_bind(fbl->volumetric_fb);
DRW_draw_pass(psl->volumetric_world_ps);
DRW_draw_pass(psl->volumetric_objects_ps);
/* Step 2: Scatter Light */
GPUFramebuffer: Refactor (Part 2) This refactor modernise the use of framebuffers. It also touches a lot of files so breaking down changes we have: - GPUTexture: Allow textures to be attached to more than one GPUFrameBuffer. This allows to create and configure more FBO without the need to attach and detach texture at drawing time. - GPUFrameBuffer: The wrapper starts to mimic opengl a bit closer. This allows to configure the framebuffer inside a context other than the one that will be rendering the framebuffer. We do the actual configuration when binding the FBO. We also Keep track of config validity and save drawbuffers state in the FBO. We remove the different bind/unbind functions. These make little sense now that we have separate contexts. - DRWFrameBuffer: We replace DRW_framebuffer functions by GPU_framebuffer ones to avoid another layer of abstraction. We move the DRW convenience functions to GPUFramebuffer instead and even add new ones. The MACRO GPU_framebuffer_ensure_config is pretty much all you need to create and config a GPUFramebuffer. - DRWTexture: Due to the removal of DRWFrameBuffer, we needed to create functions to create textures for thoses framebuffers. Pool textures are now using default texture parameters for the texture type asked. - DRWManager: Make sure no framebuffer object is bound when doing cache filling. - GPUViewport: Add new color_only_fb and depth_only_fb along with FB API usage update. This let draw engines render to color/depth only target and without the need to attach/detach textures. - WM_window: Assert when a framebuffer is bound when changing context. This balance the fact we are not track ogl context inside GPUFramebuffer. - Eevee, Clay, Mode engines: Update to new API. This comes with a lot of code simplification. This also come with some cleanups in some engine codes.
2018-03-25 17:46:48 +02:00
GPU_framebuffer_bind(fbl->volumetric_scat_fb);
DRW_draw_pass(psl->volumetric_scatter_ps);
/* Step 3: Integration */
GPUFramebuffer: Refactor (Part 2) This refactor modernise the use of framebuffers. It also touches a lot of files so breaking down changes we have: - GPUTexture: Allow textures to be attached to more than one GPUFrameBuffer. This allows to create and configure more FBO without the need to attach and detach texture at drawing time. - GPUFrameBuffer: The wrapper starts to mimic opengl a bit closer. This allows to configure the framebuffer inside a context other than the one that will be rendering the framebuffer. We do the actual configuration when binding the FBO. We also Keep track of config validity and save drawbuffers state in the FBO. We remove the different bind/unbind functions. These make little sense now that we have separate contexts. - DRWFrameBuffer: We replace DRW_framebuffer functions by GPU_framebuffer ones to avoid another layer of abstraction. We move the DRW convenience functions to GPUFramebuffer instead and even add new ones. The MACRO GPU_framebuffer_ensure_config is pretty much all you need to create and config a GPUFramebuffer. - DRWTexture: Due to the removal of DRWFrameBuffer, we needed to create functions to create textures for thoses framebuffers. Pool textures are now using default texture parameters for the texture type asked. - DRWManager: Make sure no framebuffer object is bound when doing cache filling. - GPUViewport: Add new color_only_fb and depth_only_fb along with FB API usage update. This let draw engines render to color/depth only target and without the need to attach/detach textures. - WM_window: Assert when a framebuffer is bound when changing context. This balance the fact we are not track ogl context inside GPUFramebuffer. - Eevee, Clay, Mode engines: Update to new API. This comes with a lot of code simplification. This also come with some cleanups in some engine codes.
2018-03-25 17:46:48 +02:00
GPU_framebuffer_bind(fbl->volumetric_integ_fb);
DRW_draw_pass(psl->volumetric_integration_ps);
/* Swap volume history buffers */
SWAP(struct GPUFrameBuffer *, fbl->volumetric_scat_fb, fbl->volumetric_integ_fb);
SWAP(GPUTexture *, txl->volume_scatter, txl->volume_scatter_history);
SWAP(GPUTexture *, txl->volume_transmittance, txl->volume_transmittance_history);
/* Restore */
GPUFramebuffer: Refactor (Part 2) This refactor modernise the use of framebuffers. It also touches a lot of files so breaking down changes we have: - GPUTexture: Allow textures to be attached to more than one GPUFrameBuffer. This allows to create and configure more FBO without the need to attach and detach texture at drawing time. - GPUFrameBuffer: The wrapper starts to mimic opengl a bit closer. This allows to configure the framebuffer inside a context other than the one that will be rendering the framebuffer. We do the actual configuration when binding the FBO. We also Keep track of config validity and save drawbuffers state in the FBO. We remove the different bind/unbind functions. These make little sense now that we have separate contexts. - DRWFrameBuffer: We replace DRW_framebuffer functions by GPU_framebuffer ones to avoid another layer of abstraction. We move the DRW convenience functions to GPUFramebuffer instead and even add new ones. The MACRO GPU_framebuffer_ensure_config is pretty much all you need to create and config a GPUFramebuffer. - DRWTexture: Due to the removal of DRWFrameBuffer, we needed to create functions to create textures for thoses framebuffers. Pool textures are now using default texture parameters for the texture type asked. - DRWManager: Make sure no framebuffer object is bound when doing cache filling. - GPUViewport: Add new color_only_fb and depth_only_fb along with FB API usage update. This let draw engines render to color/depth only target and without the need to attach/detach textures. - WM_window: Assert when a framebuffer is bound when changing context. This balance the fact we are not track ogl context inside GPUFramebuffer. - Eevee, Clay, Mode engines: Update to new API. This comes with a lot of code simplification. This also come with some cleanups in some engine codes.
2018-03-25 17:46:48 +02:00
GPU_framebuffer_bind(fbl->main_fb);
DRW_stats_group_end();
}
}
void EEVEE_volumes_resolve(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
e_data.color_src = txl->color;
e_data.depth_src = dtxl->depth;
/* Step 4: Apply for opaque */
GPUFramebuffer: Refactor (Part 2) This refactor modernise the use of framebuffers. It also touches a lot of files so breaking down changes we have: - GPUTexture: Allow textures to be attached to more than one GPUFrameBuffer. This allows to create and configure more FBO without the need to attach and detach texture at drawing time. - GPUFrameBuffer: The wrapper starts to mimic opengl a bit closer. This allows to configure the framebuffer inside a context other than the one that will be rendering the framebuffer. We do the actual configuration when binding the FBO. We also Keep track of config validity and save drawbuffers state in the FBO. We remove the different bind/unbind functions. These make little sense now that we have separate contexts. - DRWFrameBuffer: We replace DRW_framebuffer functions by GPU_framebuffer ones to avoid another layer of abstraction. We move the DRW convenience functions to GPUFramebuffer instead and even add new ones. The MACRO GPU_framebuffer_ensure_config is pretty much all you need to create and config a GPUFramebuffer. - DRWTexture: Due to the removal of DRWFrameBuffer, we needed to create functions to create textures for thoses framebuffers. Pool textures are now using default texture parameters for the texture type asked. - DRWManager: Make sure no framebuffer object is bound when doing cache filling. - GPUViewport: Add new color_only_fb and depth_only_fb along with FB API usage update. This let draw engines render to color/depth only target and without the need to attach/detach textures. - WM_window: Assert when a framebuffer is bound when changing context. This balance the fact we are not track ogl context inside GPUFramebuffer. - Eevee, Clay, Mode engines: Update to new API. This comes with a lot of code simplification. This also come with some cleanups in some engine codes.
2018-03-25 17:46:48 +02:00
GPU_framebuffer_bind(fbl->effect_color_fb);
DRW_draw_pass(psl->volumetric_resolve_ps);
/* Swap the buffers and rebind depth to the current buffer */
GPUFramebuffer: Refactor (Part 2) This refactor modernise the use of framebuffers. It also touches a lot of files so breaking down changes we have: - GPUTexture: Allow textures to be attached to more than one GPUFrameBuffer. This allows to create and configure more FBO without the need to attach and detach texture at drawing time. - GPUFrameBuffer: The wrapper starts to mimic opengl a bit closer. This allows to configure the framebuffer inside a context other than the one that will be rendering the framebuffer. We do the actual configuration when binding the FBO. We also Keep track of config validity and save drawbuffers state in the FBO. We remove the different bind/unbind functions. These make little sense now that we have separate contexts. - DRWFrameBuffer: We replace DRW_framebuffer functions by GPU_framebuffer ones to avoid another layer of abstraction. We move the DRW convenience functions to GPUFramebuffer instead and even add new ones. The MACRO GPU_framebuffer_ensure_config is pretty much all you need to create and config a GPUFramebuffer. - DRWTexture: Due to the removal of DRWFrameBuffer, we needed to create functions to create textures for thoses framebuffers. Pool textures are now using default texture parameters for the texture type asked. - DRWManager: Make sure no framebuffer object is bound when doing cache filling. - GPUViewport: Add new color_only_fb and depth_only_fb along with FB API usage update. This let draw engines render to color/depth only target and without the need to attach/detach textures. - WM_window: Assert when a framebuffer is bound when changing context. This balance the fact we are not track ogl context inside GPUFramebuffer. - Eevee, Clay, Mode engines: Update to new API. This comes with a lot of code simplification. This also come with some cleanups in some engine codes.
2018-03-25 17:46:48 +02:00
SWAP(GPUFrameBuffer *, fbl->main_fb, fbl->effect_fb);
SWAP(GPUFrameBuffer *, fbl->main_color_fb, fbl->effect_color_fb);
SWAP(GPUTexture *, txl->color, txl->color_post);
/* Restore */
GPU_framebuffer_texture_detach(fbl->effect_fb, dtxl->depth);
GPUFramebuffer: Refactor (Part 2) This refactor modernise the use of framebuffers. It also touches a lot of files so breaking down changes we have: - GPUTexture: Allow textures to be attached to more than one GPUFrameBuffer. This allows to create and configure more FBO without the need to attach and detach texture at drawing time. - GPUFrameBuffer: The wrapper starts to mimic opengl a bit closer. This allows to configure the framebuffer inside a context other than the one that will be rendering the framebuffer. We do the actual configuration when binding the FBO. We also Keep track of config validity and save drawbuffers state in the FBO. We remove the different bind/unbind functions. These make little sense now that we have separate contexts. - DRWFrameBuffer: We replace DRW_framebuffer functions by GPU_framebuffer ones to avoid another layer of abstraction. We move the DRW convenience functions to GPUFramebuffer instead and even add new ones. The MACRO GPU_framebuffer_ensure_config is pretty much all you need to create and config a GPUFramebuffer. - DRWTexture: Due to the removal of DRWFrameBuffer, we needed to create functions to create textures for thoses framebuffers. Pool textures are now using default texture parameters for the texture type asked. - DRWManager: Make sure no framebuffer object is bound when doing cache filling. - GPUViewport: Add new color_only_fb and depth_only_fb along with FB API usage update. This let draw engines render to color/depth only target and without the need to attach/detach textures. - WM_window: Assert when a framebuffer is bound when changing context. This balance the fact we are not track ogl context inside GPUFramebuffer. - Eevee, Clay, Mode engines: Update to new API. This comes with a lot of code simplification. This also come with some cleanups in some engine codes.
2018-03-25 17:46:48 +02:00
GPU_framebuffer_texture_attach(fbl->main_fb, dtxl->depth, 0, 0);
GPU_framebuffer_bind(fbl->main_fb);
}
}
void EEVEE_volumes_free_smoke_textures(void)
{
/* Free Smoke Textures after rendering */
for (LinkData *link = e_data.smoke_domains.first; link; link = link->next) {
SmokeModifierData *smd = (SmokeModifierData *)link->data;
GPU_free_smoke(smd);
}
BLI_freelistN(&e_data.smoke_domains);
}
void EEVEE_volumes_free(void)
{
MEM_SAFE_FREE(e_data.volumetric_common_lib);
MEM_SAFE_FREE(e_data.volumetric_common_lamps_lib);
DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_with_lamps_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh);
}