EEVEE: GLSL refactor/cleanup

- add the use of DRWShaderLibrary to EEVEE's glsl codebase to reduce code
complexity and duplication.
- split bsdf_common_lib.glsl into multiple sub library which are now shared
with other engines.
- the surface shader code is now more organised and have its own files.
- change default world to use a material nodetree and make lookdev shader
more clear.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D8306
This commit is contained in:
Clément Foucault 2020-07-30 13:55:13 +02:00
parent 55401fbb3d
commit da741013a1
Notes: blender-bot 2023-02-13 21:35:05 +01:00
Referenced by commit f5eae90277, Fix T79493: EEVEE LightProbe Display
Referenced by issue #81105, Eevee SSR quality regression in 2.91 alpha
Referenced by issue #80141, Crash when adding a Volume Object or Quick Smoke
Referenced by issue #79605, Material Preview Icons Lost Transparency For Their Background
Referenced by issue #79568, EEVEE Film transparent not working
Referenced by issue #79541, Freestyle render is completely black
98 changed files with 1761 additions and 2271 deletions

View File

@ -187,10 +187,10 @@ set(LIB
)
data_to_c_simple(engines/eevee/shaders/ambient_occlusion_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/default_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/default_world_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/background_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/closure_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/common_uniforms_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/common_utiltex_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lights_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl SRC)
@ -205,8 +205,8 @@ data_to_c_simple(engines/eevee/shaders/lightprobe_grid_display_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_grid_fill_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_planar_display_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lightprobe_planar_display_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lit_surface_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lit_surface_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lookdev_world_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/closure_lit_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_bloom_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_dof_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_dof_frag.glsl SRC)
@ -230,7 +230,6 @@ data_to_c_simple(engines/eevee/shaders/object_motion_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/prepass_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/prepass_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/shadow_accum_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/shadow_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/shadow_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/bsdf_lut_frag.glsl SRC)
@ -241,9 +240,14 @@ data_to_c_simple(engines/eevee/shaders/octahedron_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/cubemap_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/bsdf_sampling_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/raytrace_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/renderpass_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/renderpass_postprocess_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/ssr_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/surface_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/surface_geom.glsl SRC)
data_to_c_simple(engines/eevee/shaders/surface_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/surface_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/update_noise_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/volumetric_accum_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/volumetric_lib.glsl SRC)
@ -289,6 +293,8 @@ data_to_c_simple(intern/shaders/common_globals_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_pointcloud_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_hair_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_hair_refine_vert.glsl SRC)
data_to_c_simple(intern/shaders/common_math_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_math_geom_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_view_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_fxaa_lib.glsl SRC)
data_to_c_simple(intern/shaders/common_smaa_lib.glsl SRC)

View File

@ -54,24 +54,30 @@ extern char datatoc_common_view_lib_glsl[];
static void eevee_create_shader_depth_of_field(const bool use_alpha)
{
char *frag = BLI_string_joinN(datatoc_common_view_lib_glsl, datatoc_effect_dof_frag_glsl);
e_data.dof_downsample_sh[use_alpha] = DRW_shader_create_fullscreen(
frag,
DRWShaderLibrary *lib = EEVEE_shader_lib_get();
e_data.dof_downsample_sh[use_alpha] = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_dof_frag_glsl,
lib,
use_alpha ? "#define USE_ALPHA_DOF\n"
"#define STEP_DOWNSAMPLE\n" :
"#define STEP_DOWNSAMPLE\n");
e_data.dof_scatter_sh[use_alpha] = DRW_shader_create(datatoc_effect_dof_vert_glsl,
NULL,
frag,
use_alpha ? "#define USE_ALPHA_DOF\n"
"#define STEP_SCATTER\n" :
"#define STEP_SCATTER\n");
e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen(frag,
use_alpha ?
"#define USE_ALPHA_DOF\n"
"#define STEP_RESOLVE\n" :
"#define STEP_RESOLVE\n");
MEM_freeN(frag);
e_data.dof_scatter_sh[use_alpha] = DRW_shader_create_with_shaderlib(
datatoc_effect_dof_vert_glsl,
NULL,
datatoc_effect_dof_frag_glsl,
lib,
use_alpha ? "#define USE_ALPHA_DOF\n"
"#define STEP_SCATTER\n" :
"#define STEP_SCATTER\n");
e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_dof_frag_glsl,
lib,
use_alpha ? "#define USE_ALPHA_DOF\n"
"#define STEP_RESOLVE\n" :
"#define STEP_RESOLVE\n");
}
int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),

View File

@ -326,38 +326,28 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
{
DRW_PASS_CREATE(psl->probe_background, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = NULL;
EEVEE_lookdev_cache_init(vedata, sldata, psl->probe_background, pinfo, &grp);
Scene *scene = draw_ctx->scene;
World *wo = scene->world;
if (grp == NULL) {
Scene *scene = draw_ctx->scene;
World *world = (scene->world) ? scene->world : EEVEE_world_default_get();
/* LookDev */
EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->probe_background, wo, pinfo);
if (!grp && wo) {
struct GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_PROBE);
const int options = VAR_WORLD_BACKGROUND | VAR_WORLD_PROBE;
struct GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, NULL, world, options);
grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
/* TODO (fclem): remove those (need to clean the GLSL files). */
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
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);
DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, geom, NULL);
}
/* Fallback if shader fails or if not using nodetree. */
if (grp == NULL) {
grp = DRW_shgroup_create(EEVEE_shaders_probe_default_sh_get(), psl->probe_background);
DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1);
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
DRW_shgroup_call(grp, geom, NULL);
}
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
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);
DRW_shgroup_uniform_block_ref(grp, "renderpass_block", &stl->g_data->renderpass_ubo);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
if (DRW_state_draw_support()) {

View File

@ -97,10 +97,9 @@ static void eevee_lookdev_hdri_preview_init(EEVEE_Data *vedata, EEVEE_ViewLayerD
void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
DRWShadingGroup **r_grp,
DRWPass *pass,
World *UNUSED(world),
EEVEE_LightProbesInfo *pinfo)
EEVEE_LightProbesInfo *pinfo,
DRWShadingGroup **r_shgrp)
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_TextureList *txl = vedata->txl;
@ -153,89 +152,88 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
const View3DShading *shading = &v3d->shading;
StudioLight *sl = BKE_studiolight_find(shading->lookdev_light,
STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE);
if (sl && (sl->flag & STUDIOLIGHT_TYPE_WORLD)) {
GPUShader *shader = probe_render ? EEVEE_shaders_default_studiolight_sh_get() :
EEVEE_shaders_background_studiolight_sh_get();
if (sl == NULL || (sl->flag & STUDIOLIGHT_TYPE_WORLD) == 0) {
return;
}
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
int cube_res = scene_eval->eevee.gi_cubemap_resolution;
GPUShader *shader = probe_render ? EEVEE_shaders_studiolight_probe_sh_get() :
EEVEE_shaders_studiolight_background_sh_get();
/* If one of the component is missing we start from scratch. */
if ((stl->lookdev_grid_data == NULL) || (stl->lookdev_cube_data == NULL) ||
(txl->lookdev_grid_tx == NULL) || (txl->lookdev_cube_tx == NULL) ||
(g_data->light_cache && g_data->light_cache->ref_res != cube_res)) {
eevee_lookdev_lightcache_delete(vedata);
}
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
int cube_res = scene_eval->eevee.gi_cubemap_resolution;
if (stl->lookdev_lightcache == NULL) {
/* If one of the component is missing we start from scratch. */
if ((stl->lookdev_grid_data == NULL) || (stl->lookdev_cube_data == NULL) ||
(txl->lookdev_grid_tx == NULL) || (txl->lookdev_cube_tx == NULL) ||
(g_data->light_cache && g_data->light_cache->ref_res != cube_res)) {
eevee_lookdev_lightcache_delete(vedata);
}
if (stl->lookdev_lightcache == NULL) {
#if defined(IRRADIANCE_SH_L2)
int grid_res = 4;
int grid_res = 4;
#elif defined(IRRADIANCE_HL2)
int grid_res = 4;
int grid_res = 4;
#endif
stl->lookdev_lightcache = EEVEE_lightcache_create(
1, 1, cube_res, 8, (int[3]){grid_res, grid_res, 1});
stl->lookdev_lightcache = EEVEE_lightcache_create(
1, 1, cube_res, 8, (int[3]){grid_res, grid_res, 1});
/* XXX: Fix memleak. TODO find out why. */
MEM_SAFE_FREE(stl->lookdev_cube_mips);
/* XXX: Fix memleak. TODO find out why. */
MEM_SAFE_FREE(stl->lookdev_cube_mips);
/* We do this to use a special light cache for lookdev.
* This light-cache needs to be per viewport. But we need to
* have correct freeing when the viewport is closed. So we
* need to reference all textures to the txl and the memblocks
* to the stl. */
stl->lookdev_grid_data = stl->lookdev_lightcache->grid_data;
stl->lookdev_cube_data = stl->lookdev_lightcache->cube_data;
stl->lookdev_cube_mips = stl->lookdev_lightcache->cube_mips;
txl->lookdev_grid_tx = stl->lookdev_lightcache->grid_tx.tex;
txl->lookdev_cube_tx = stl->lookdev_lightcache->cube_tx.tex;
}
/* We do this to use a special light cache for lookdev.
* This light-cache needs to be per viewport. But we need to
* have correct freeing when the viewport is closed. So we
* need to reference all textures to the txl and the memblocks
* to the stl. */
stl->lookdev_grid_data = stl->lookdev_lightcache->grid_data;
stl->lookdev_cube_data = stl->lookdev_lightcache->cube_data;
stl->lookdev_cube_mips = stl->lookdev_lightcache->cube_mips;
txl->lookdev_grid_tx = stl->lookdev_lightcache->grid_tx.tex;
txl->lookdev_cube_tx = stl->lookdev_lightcache->cube_tx.tex;
}
g_data->light_cache = stl->lookdev_lightcache;
g_data->light_cache = stl->lookdev_lightcache;
DRWShadingGroup *grp = *r_grp = DRW_shgroup_create(shader, pass);
axis_angle_to_mat3_single(g_data->studiolight_matrix, 'Z', shading->studiolight_rot_z);
DRW_shgroup_uniform_mat3(grp, "StudioLightMatrix", g_data->studiolight_matrix);
DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
axis_angle_to_mat3_single(g_data->studiolight_matrix, 'Z', shading->studiolight_rot_z);
DRW_shgroup_uniform_mat3(grp, "StudioLightMatrix", g_data->studiolight_matrix);
if (probe_render) {
DRW_shgroup_uniform_float_copy(
grp, "studioLightIntensity", shading->studiolight_intensity);
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
DRW_shgroup_uniform_texture(grp, "image", sl->equirect_radiance_gputexture);
/* Do not fadeout when doing probe rendering, only when drawing the background */
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
}
else {
float background_alpha = g_data->background_alpha * shading->studiolight_background;
float studiolight_blur = powf(shading->studiolight_blur, 2.5f);
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", background_alpha);
DRW_shgroup_uniform_float_copy(grp, "studioLightBlur", studiolight_blur);
DRW_shgroup_uniform_texture(grp, "probeCubes", txl->lookdev_cube_tx);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
}
if (probe_render) {
/* Avoid artifact with equirectangular mapping. */
eGPUSamplerState state = (GPU_SAMPLER_FILTER | GPU_SAMPLER_REPEAT_S);
DRW_shgroup_uniform_float_copy(grp, "studioLightIntensity", shading->studiolight_intensity);
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
DRW_shgroup_uniform_texture_ex(grp, "studioLight", sl->equirect_radiance_gputexture, state);
/* Do not fadeout when doing probe rendering, only when drawing the background */
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
}
else {
float background_alpha = g_data->background_alpha * shading->studiolight_background;
float studiolight_blur = powf(shading->studiolight_blur, 2.5f);
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", background_alpha);
DRW_shgroup_uniform_float_copy(grp, "studioLightBlur", studiolight_blur);
DRW_shgroup_uniform_texture(grp, "probeCubes", txl->lookdev_cube_tx);
}
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
/* Common UBOs are setup latter. */
*r_shgrp = grp;
/* Do we need to recalc the lightprobes? */
if (g_data->studiolight_index != sl->index ||
g_data->studiolight_rot_z != shading->studiolight_rot_z ||
g_data->studiolight_intensity != shading->studiolight_intensity ||
g_data->studiolight_cubemap_res != scene->eevee.gi_cubemap_resolution ||
g_data->studiolight_glossy_clamp != scene->eevee.gi_glossy_clamp ||
g_data->studiolight_filter_quality != scene->eevee.gi_filter_quality) {
stl->lookdev_lightcache->flag |= LIGHTCACHE_UPDATE_WORLD;
g_data->studiolight_index = sl->index;
g_data->studiolight_rot_z = shading->studiolight_rot_z;
g_data->studiolight_intensity = shading->studiolight_intensity;
g_data->studiolight_cubemap_res = scene->eevee.gi_cubemap_resolution;
g_data->studiolight_glossy_clamp = scene->eevee.gi_glossy_clamp;
g_data->studiolight_filter_quality = scene->eevee.gi_filter_quality;
}
/* Do we need to recalc the lightprobes? */
if (g_data->studiolight_index != sl->index ||
g_data->studiolight_rot_z != shading->studiolight_rot_z ||
g_data->studiolight_intensity != shading->studiolight_intensity ||
g_data->studiolight_cubemap_res != scene->eevee.gi_cubemap_resolution ||
g_data->studiolight_glossy_clamp != scene->eevee.gi_glossy_clamp ||
g_data->studiolight_filter_quality != scene->eevee.gi_filter_quality) {
stl->lookdev_lightcache->flag |= LIGHTCACHE_UPDATE_WORLD;
g_data->studiolight_index = sl->index;
g_data->studiolight_rot_z = shading->studiolight_rot_z;
g_data->studiolight_intensity = shading->studiolight_intensity;
g_data->studiolight_cubemap_res = scene->eevee.gi_cubemap_resolution;
g_data->studiolight_glossy_clamp = scene->eevee.gi_glossy_clamp;
g_data->studiolight_filter_quality = scene->eevee.gi_filter_quality;
}
}
}

View File

@ -31,6 +31,8 @@
#include "BLI_rand.h"
#include "BLI_string_utils.h"
#include "eevee_private.h"
extern char datatoc_bsdf_lut_frag_glsl[];
extern char datatoc_btdf_lut_frag_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
@ -45,15 +47,13 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
static float samples_len = 8192.0f;
static float inv_samples_len = 1.0f / 8192.0f;
char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl);
DRWShaderLibrary *lib = EEVEE_shader_lib_get();
struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl,
datatoc_lightprobe_geom_glsl,
datatoc_bsdf_lut_frag_glsl,
lib_str,
"#define HAMMERSLEY_SIZE 8192\n"
"#define BRDF_LUT_SIZE 64\n"
"#define NOISE_SIZE 64\n");
struct GPUShader *sh = DRW_shader_create_with_shaderlib(datatoc_lightprobe_vert_glsl,
datatoc_lightprobe_geom_glsl,
datatoc_bsdf_lut_frag_glsl,
lib,
"#define HAMMERSLEY_SIZE 8192\n");
DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
@ -105,16 +105,10 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
static float a2 = 0.0f;
static float inv_samples_len = 1.0f / 8192.0f;
char *frag_str = BLI_string_joinN(
datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl);
DRWShaderLibrary *lib = EEVEE_shader_lib_get();
struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str,
"#define HAMMERSLEY_SIZE 8192\n"
"#define BRDF_LUT_SIZE 64\n"
"#define NOISE_SIZE 64\n"
"#define LUT_SIZE 64\n");
MEM_freeN(frag_str);
struct GPUShader *sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_btdf_lut_frag_glsl, lib, "#define HAMMERSLEY_SIZE 8192\n");
DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);

View File

@ -56,37 +56,6 @@ static struct {
float noise_offsets[3];
} e_data = {NULL}; /* Engine data */
extern char datatoc_lights_lib_glsl[];
extern char datatoc_lightprobe_lib_glsl[];
extern char datatoc_ambient_occlusion_lib_glsl[];
extern char datatoc_prepass_frag_glsl[];
extern char datatoc_prepass_vert_glsl[];
extern char datatoc_default_frag_glsl[];
extern char datatoc_default_world_frag_glsl[];
extern char datatoc_ltc_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_common_hair_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_cubemap_lib_glsl[];
extern char datatoc_lit_surface_frag_glsl[];
extern char datatoc_lit_surface_vert_glsl[];
extern char datatoc_raytrace_lib_glsl[];
extern char datatoc_ssr_lib_glsl[];
extern char datatoc_shadow_vert_glsl[];
extern char datatoc_lightprobe_geom_glsl[];
extern char datatoc_lightprobe_vert_glsl[];
extern char datatoc_background_vert_glsl[];
extern char datatoc_update_noise_frag_glsl[];
extern char datatoc_volumetric_vert_glsl[];
extern char datatoc_volumetric_geom_glsl[];
extern char datatoc_volumetric_frag_glsl[];
extern char datatoc_volumetric_lib_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
typedef struct EeveeMaterialCache {
struct DRWShadingGroup *depth_grp;
struct DRWShadingGroup *shading_grp;
@ -238,46 +207,6 @@ void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const d
DRW_draw_pass(psl->update_noise_pass);
}
void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4])
{
/* view vectors for the corners of the view frustum.
* Can be used to recreate the world space position easily */
float view_vecs[4][4] = {
{-1.0f, -1.0f, -1.0f, 1.0f},
{1.0f, -1.0f, -1.0f, 1.0f},
{-1.0f, 1.0f, -1.0f, 1.0f},
{-1.0f, -1.0f, 1.0f, 1.0f},
};
/* convert the view vectors to view space */
const bool is_persp = (winmat[3][3] == 0.0f);
for (int i = 0; i < 4; i++) {
mul_project_m4_v3(invproj, view_vecs[i]);
/* normalized trick see:
* http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
if (is_persp) {
/* Divide XY by Z. */
mul_v2_fl(view_vecs[i], 1.0f / view_vecs[i][2]);
}
}
/**
* If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and
* view_vecs[1] is the vector going from the near-bottom-left corner to
* the far-top-right corner.
* If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner
* when Z = 1, and top-left corner if Z = 1.
* view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed)
* distance from the near plane to the far clip plane.
*/
copy_v4_v4(r_viewvecs[0], view_vecs[0]);
/* we need to store the differences */
r_viewvecs[1][0] = view_vecs[1][0] - view_vecs[0][0];
r_viewvecs[1][1] = view_vecs[2][1] - view_vecs[0][1];
r_viewvecs[1][2] = view_vecs[3][2] - view_vecs[0][2];
}
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
EEVEE_StorageList *stl,
@ -304,15 +233,6 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
sldata->common_data.alpha_hash_scale = 0.01f;
}
{
/* Update view_vecs */
float invproj[4][4], winmat[4][4];
DRW_view_winmat_get(NULL, winmat, false);
DRW_view_winmat_get(NULL, invproj, true);
EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs);
}
{
/* Update noise Framebuffer. */
GPU_framebuffer_ensure_config(
@ -391,39 +311,28 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
DRW_PASS_CREATE(psl->background_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = NULL;
EEVEE_lookdev_cache_init(vedata, sldata, psl->background_ps, NULL, &grp);
Scene *scene = draw_ctx->scene;
World *wo = scene->world;
if (grp == NULL) {
Scene *scene = draw_ctx->scene;
World *world = (scene->world) ? scene->world : EEVEE_world_default_get();
EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_ps, wo, NULL);
if (!grp && wo) {
struct GPUMaterial *gpumat = EEVEE_material_get(
vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND);
const int options = VAR_WORLD_BACKGROUND;
struct GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, NULL, world, options);
grp = DRW_shgroup_material_create(gpumat, psl->background_ps);
DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
/* TODO (fclem): remove those (need to clean the GLSL files). */
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
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);
DRW_shgroup_uniform_block_ref(grp, "renderpass_block", &stl->g_data->renderpass_ubo);
DRW_shgroup_call(grp, geom, NULL);
}
/* Fallback if shader fails or if not using nodetree. */
if (grp == NULL) {
GPUShader *sh = EEVEE_shaders_default_background_sh_get();
grp = DRW_shgroup_create(sh, psl->background_ps);
DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1);
DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
DRW_shgroup_call(grp, geom, NULL);
}
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
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);
DRW_shgroup_uniform_block_ref(grp, "renderpass_block", &stl->g_data->renderpass_ubo);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
#define EEVEE_PASS_CREATE(pass, state) \

View File

@ -56,14 +56,10 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
if (e_data.mist_sh == NULL) {
char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_effect_mist_frag_glsl);
DRWShaderLibrary *lib = EEVEE_shader_lib_get();
e_data.mist_sh = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n");
MEM_freeN(frag_str);
e_data.mist_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_mist_frag_glsl, lib, "#define FIRST_PASS\n");
}
/* Create FrameBuffer. */
@ -98,11 +94,11 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
}
else {
float near = -sldata->common_data.view_vecs[0][2];
float range = sldata->common_data.view_vecs[1][2];
float near = DRW_view_near_distance_get(NULL);
float far = DRW_view_far_distance_get(NULL);
/* Fallback */
g_data->mist_start = near;
g_data->mist_inv_dist = 1.0f / fabsf(range);
g_data->mist_inv_dist = 1.0f / fabsf(far - near);
g_data->mist_falloff = 1.0f;
}

View File

@ -68,27 +68,23 @@ extern char datatoc_common_view_lib_glsl[];
static void eevee_create_shader_motion_blur(void)
{
e_data.motion_blur_sh = DRW_shader_create_fullscreen(
datatoc_effect_motion_blur_frag_glsl,
"#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n");
e_data.motion_blur_object_sh = DRW_shader_create_with_lib(datatoc_object_motion_vert_glsl,
NULL,
datatoc_object_motion_frag_glsl,
datatoc_common_view_lib_glsl,
NULL);
e_data.velocity_tiles_sh = DRW_shader_create_fullscreen(
datatoc_effect_velocity_tile_frag_glsl,
"#define TILE_GATHER\n"
"#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n");
e_data.velocity_tiles_expand_sh = DRW_shader_create_fullscreen(
datatoc_effect_velocity_tile_frag_glsl,
"#define TILE_EXPANSION\n"
"#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n");
#define TILE_SIZE_STR "#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n"
DRWShaderLibrary *lib = EEVEE_shader_lib_get();
e_data.motion_blur_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_motion_blur_frag_glsl, lib, TILE_SIZE_STR);
e_data.motion_blur_object_sh = DRW_shader_create_with_shaderlib(
datatoc_object_motion_vert_glsl, NULL, datatoc_object_motion_frag_glsl, lib, NULL);
char *vert = BLI_string_joinN(datatoc_common_hair_lib_glsl, datatoc_object_motion_vert_glsl);
e_data.motion_blur_hair_sh = DRW_shader_create_with_lib(
vert, NULL, datatoc_object_motion_frag_glsl, datatoc_common_view_lib_glsl, "#define HAIR\n");
MEM_freeN(vert);
e_data.motion_blur_hair_sh = DRW_shader_create_with_shaderlib(datatoc_object_motion_vert_glsl,
NULL,
datatoc_object_motion_frag_glsl,
lib,
"#define HAIR\n");
e_data.velocity_tiles_sh = DRW_shader_create_fullscreen(datatoc_effect_velocity_tile_frag_glsl,
"#define TILE_GATHER\n" TILE_SIZE_STR);
e_data.velocity_tiles_expand_sh = DRW_shader_create_fullscreen(
datatoc_effect_velocity_tile_frag_glsl, "#define TILE_EXPANSION\n" TILE_SIZE_STR);
}
int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)

View File

@ -53,17 +53,14 @@ extern char datatoc_effect_gtao_frag_glsl[];
static void eevee_create_shader_occlusion(void)
{
char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_ambient_occlusion_lib_glsl,
datatoc_effect_gtao_frag_glsl);
DRWShaderLibrary *lib = EEVEE_shader_lib_get();
e_data.gtao_sh = DRW_shader_create_fullscreen(frag_str, NULL);
e_data.gtao_layer_sh = DRW_shader_create_fullscreen(frag_str, "#define LAYERED_DEPTH\n");
e_data.gtao_debug_sh = DRW_shader_create_fullscreen(frag_str, "#define DEBUG_AO\n");
MEM_freeN(frag_str);
e_data.gtao_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_gtao_frag_glsl, lib, NULL);
e_data.gtao_layer_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_gtao_frag_glsl, lib, "#define LAYERED_DEPTH\n");
e_data.gtao_debug_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_gtao_frag_glsl, lib, "#define DEBUG_AO\n");
}
int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)

View File

@ -163,7 +163,7 @@ enum {
VAR_MAT_MESH = (1 << 0),
VAR_MAT_VOLUME = (1 << 1),
VAR_MAT_HAIR = (1 << 2),
VAR_MAT_PROBE = (1 << 3),
/* VAR_MAT_PROBE = (1 << 3), UNUSED */
VAR_MAT_BLEND = (1 << 4),
VAR_MAT_LOOKDEV = (1 << 5),
VAR_MAT_HOLDOUT = (1 << 6),
@ -747,7 +747,6 @@ typedef struct EEVEE_EffectsInfo {
* - sizeof(bool) == sizeof(int) in GLSL so use int in C */
typedef struct EEVEE_CommonUniformBuffer {
float prev_persmat[4][4]; /* mat4 */
float view_vecs[2][4]; /* vec4[2] */
float mip_ratio[10][4]; /* vec2[10] */
/* Ambient Occlusion */
/* -- 16 byte aligned -- */
@ -1001,7 +1000,6 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_materials_free(void);
void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]);
void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4]);
void EEVEE_material_renderpasses_init(EEVEE_Data *vedata);
void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples);
void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@ -1057,15 +1055,14 @@ void EEVEE_random_rotation_m4(int sample_ofs, float scale, float r_mat[4][4]);
/* eevee_shaders.c */
void EEVEE_shaders_lightprobe_shaders_init(void);
void EEVEE_shaders_material_shaders_init(void);
struct DRWShaderLibrary *EEVEE_shader_lib_get(void);
struct GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_default_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_filter_diffuse_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_filter_visibility_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_fill_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void);
struct GPUShader *EEVEE_shaders_default_studiolight_sh_get(void);
struct GPUShader *EEVEE_shaders_default_background_sh_get(void);
struct GPUShader *EEVEE_shaders_background_studiolight_sh_get(void);
struct GPUShader *EEVEE_shaders_studiolight_probe_sh_get(void);
struct GPUShader *EEVEE_shaders_studiolight_background_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void);
@ -1077,6 +1074,7 @@ struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo);
Material *EEVEE_material_default_diffuse_get(void);
Material *EEVEE_material_default_glossy_get(void);
Material *EEVEE_material_default_error_get(void);
World *EEVEE_world_default_get(void);
struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options);
struct GPUMaterial *EEVEE_material_get(
EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options);
@ -1300,10 +1298,9 @@ void EEVEE_render_update_passes(struct RenderEngine *engine,
/** eevee_lookdev.c */
void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
DRWShadingGroup **grp,
DRWPass *pass,
struct World *world,
EEVEE_LightProbesInfo *pinfo);
EEVEE_LightProbesInfo *pinfo,
DRWShadingGroup **r_shgrp);
void EEVEE_lookdev_draw(EEVEE_Data *vedata);
/** eevee_engine.c */

View File

@ -199,12 +199,10 @@ void EEVEE_renderpasses_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve
EEVEE_RENDERPASSES_WITH_POST_PROCESSING) > 0;
if (needs_post_processing) {
if (e_data.postprocess_sh == NULL) {
char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_renderpass_postprocess_frag_glsl);
e_data.postprocess_sh = DRW_shader_create_fullscreen(frag_str, NULL);
MEM_freeN(frag_str);
DRWShaderLibrary *lib = EEVEE_shader_lib_get();
e_data.postprocess_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_renderpass_postprocess_frag_glsl, lib, NULL);
}
DRW_PASS_CREATE(psl->renderpass_pass, DRW_STATE_WRITE_COLOR);

View File

@ -48,30 +48,12 @@ static struct {
struct GPUTexture *depth_src;
} e_data = {{NULL}}; /* Engine data */
extern char datatoc_ambient_occlusion_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_cubemap_lib_glsl[];
extern char datatoc_effect_ssr_frag_glsl[];
extern char datatoc_lightprobe_lib_glsl[];
extern char datatoc_raytrace_lib_glsl[];
static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
{
if (e_data.ssr_sh[options] == NULL) {
char *ssr_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_ambient_occlusion_lib_glsl,
datatoc_octahedron_lib_glsl,
datatoc_cubemap_lib_glsl,
datatoc_lightprobe_lib_glsl,
datatoc_raytrace_lib_glsl,
datatoc_effect_ssr_frag_glsl);
DRWShaderLibrary *lib = EEVEE_shader_lib_get();
DynStr *ds_defines = BLI_dynstr_new();
BLI_dynstr_append(ds_defines, SHADER_DEFINES);
@ -91,9 +73,9 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
char *ssr_define_str = BLI_dynstr_get_cstring(ds_defines);
BLI_dynstr_free(ds_defines);
e_data.ssr_sh[options] = DRW_shader_create_fullscreen(ssr_shader_str, ssr_define_str);
e_data.ssr_sh[options] = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_ssr_frag_glsl, lib, ssr_define_str);
MEM_freeN(ssr_shader_str);
MEM_freeN(ssr_define_str);
}

View File

@ -28,6 +28,8 @@
#include "BLI_dynstr.h"
#include "BLI_string_utils.h"
#include "DNA_world_types.h"
#include "MEM_guardedalloc.h"
#include "GPU_material.h"
@ -40,19 +42,17 @@
static const char *filter_defines = "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n"
#if defined(IRRADIANCE_SH_L2)
"#define IRRADIANCE_SH_L2\n"
#elif defined(IRRADIANCE_CUBEMAP)
"#define IRRADIANCE_CUBEMAP\n"
"#define IRRADIANCE_SH_L2\n";
#elif defined(IRRADIANCE_HL2)
"#define IRRADIANCE_HL2\n"
"#define IRRADIANCE_HL2\n";
#endif
"#define NOISE_SIZE 64\n";
static struct {
/* Lookdev */
struct GPUShader *studiolight_probe_sh;
struct GPUShader *studiolight_background_sh;
/* Probes */
struct GPUShader *probe_default_sh;
struct GPUShader *probe_default_studiolight_sh;
struct GPUShader *probe_background_studiolight_sh;
struct GPUShader *probe_grid_display_sh;
struct GPUShader *probe_cube_display_sh;
struct GPUShader *probe_planar_display_sh;
@ -70,17 +70,16 @@ static struct {
struct GPUShader *taa_resolve_reproject_sh;
/* General purpose Shaders. */
struct GPUShader *default_background;
struct GPUShader *lookdev_background;
struct GPUShader *update_noise_sh;
/* Shader strings */
char *frag_shader_lib;
char *vert_shader_str;
char *vert_shadow_shader_str;
char *vert_background_shader_str;
char *vert_volume_shader_str;
char *geom_volume_shader_str;
char *volume_shader_lib;
char *closure_lit_lib;
char *surface_lit_frag;
char *surface_prepass_frag;
char *surface_geom_barycentric;
DRWShaderLibrary *lib;
/* LookDev Materials */
Material *glossy_mat;
@ -88,6 +87,8 @@ static struct {
Material *error_mat;
World *default_world;
/* Default Material */
struct {
bNodeTree *ntree;
@ -103,16 +104,39 @@ static struct {
} world;
} e_data = {NULL}; /* Engine data */
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_common_hair_lib_glsl[];
extern char datatoc_common_math_lib_glsl[];
extern char datatoc_common_math_geom_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_gpu_shader_common_obinfos_lib_glsl[];
extern char datatoc_ambient_occlusion_lib_glsl[];
extern char datatoc_background_vert_glsl[];
extern char datatoc_common_hair_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_lut_frag_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_btdf_lut_frag_glsl[];
extern char datatoc_closure_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_common_utiltex_lib_glsl[];
extern char datatoc_cubemap_lib_glsl[];
extern char datatoc_default_world_frag_glsl[];
extern char datatoc_default_frag_glsl[];
extern char datatoc_lookdev_world_frag_glsl[];
extern char datatoc_effect_bloom_frag_glsl[];
extern char datatoc_effect_dof_frag_glsl[];
extern char datatoc_effect_dof_vert_glsl[];
extern char datatoc_effect_downsample_cube_frag_glsl[];
extern char datatoc_effect_downsample_frag_glsl[];
extern char datatoc_effect_gtao_frag_glsl[];
extern char datatoc_effect_minmaxz_frag_glsl[];
extern char datatoc_effect_mist_frag_glsl[];
extern char datatoc_effect_motion_blur_frag_glsl[];
extern char datatoc_effect_ssr_frag_glsl[];
extern char datatoc_effect_subsurface_frag_glsl[];
extern char datatoc_effect_temporal_aa_glsl[];
extern char datatoc_effect_translucency_frag_glsl[];
extern char datatoc_effect_velocity_resolve_frag_glsl[];
extern char datatoc_effect_velocity_tile_frag_glsl[];
extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_lightprobe_cube_display_frag_glsl[];
extern char datatoc_lightprobe_cube_display_vert_glsl[];
@ -131,72 +155,111 @@ extern char datatoc_lightprobe_planar_downsample_geom_glsl[];
extern char datatoc_lightprobe_planar_downsample_vert_glsl[];
extern char datatoc_lightprobe_vert_glsl[];
extern char datatoc_lights_lib_glsl[];
extern char datatoc_lit_surface_frag_glsl[];
extern char datatoc_lit_surface_vert_glsl[];
extern char datatoc_closure_lit_lib_glsl[];
extern char datatoc_ltc_lib_glsl[];
extern char datatoc_object_motion_frag_glsl[];
extern char datatoc_object_motion_vert_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_prepass_frag_glsl[];
extern char datatoc_prepass_vert_glsl[];
extern char datatoc_raytrace_lib_glsl[];
extern char datatoc_renderpass_lib_glsl[];
extern char datatoc_renderpass_postprocess_frag_glsl[];
extern char datatoc_shadow_accum_frag_glsl[];
extern char datatoc_shadow_frag_glsl[];
extern char datatoc_shadow_vert_glsl[];
extern char datatoc_ssr_lib_glsl[];
extern char datatoc_surface_frag_glsl[];
extern char datatoc_surface_geom_glsl[];
extern char datatoc_surface_lib_glsl[];
extern char datatoc_surface_vert_glsl[];
extern char datatoc_update_noise_frag_glsl[];
extern char datatoc_volumetric_accum_frag_glsl[];
extern char datatoc_volumetric_frag_glsl[];
extern char datatoc_volumetric_geom_glsl[];
extern char datatoc_volumetric_integration_frag_glsl[];
extern char datatoc_volumetric_lib_glsl[];
extern char datatoc_volumetric_resolve_frag_glsl[];
extern char datatoc_volumetric_scatter_frag_glsl[];
extern char datatoc_volumetric_vert_glsl[];
/* Velocity Resolve */
extern char datatoc_effect_velocity_resolve_frag_glsl[];
/* Temporal Sampling */
extern char datatoc_effect_temporal_aa_glsl[];
/* *********** FUNCTIONS *********** */
static void eevee_shader_library_ensure(void)
{
if (e_data.lib == NULL) {
e_data.lib = DRW_shader_library_create();
/* NOTE: Theses needs to be ordered by dependencies. */
DRW_SHADER_LIB_ADD(e_data.lib, common_math_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_math_geom_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_hair_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_uniforms_lib);
DRW_SHADER_LIB_ADD(e_data.lib, gpu_shader_common_obinfos_lib);
DRW_SHADER_LIB_ADD(e_data.lib, renderpass_lib);
DRW_SHADER_LIB_ADD(e_data.lib, bsdf_common_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_utiltex_lib);
DRW_SHADER_LIB_ADD(e_data.lib, bsdf_sampling_lib);
DRW_SHADER_LIB_ADD(e_data.lib, cubemap_lib);
DRW_SHADER_LIB_ADD(e_data.lib, raytrace_lib);
DRW_SHADER_LIB_ADD(e_data.lib, ambient_occlusion_lib);
DRW_SHADER_LIB_ADD(e_data.lib, octahedron_lib);
DRW_SHADER_LIB_ADD(e_data.lib, irradiance_lib);
DRW_SHADER_LIB_ADD(e_data.lib, lightprobe_lib);
DRW_SHADER_LIB_ADD(e_data.lib, ltc_lib);
DRW_SHADER_LIB_ADD(e_data.lib, lights_lib);
DRW_SHADER_LIB_ADD(e_data.lib, surface_lib);
DRW_SHADER_LIB_ADD(e_data.lib, volumetric_lib);
DRW_SHADER_LIB_ADD(e_data.lib, closure_lib);
DRW_SHADER_LIB_ADD(e_data.lib, ssr_lib);
/* Add one for each Closure */
e_data.closure_lit_lib = BLI_string_joinN(datatoc_closure_lit_lib_glsl,
datatoc_closure_lit_lib_glsl,
datatoc_closure_lit_lib_glsl,
datatoc_closure_lit_lib_glsl,
datatoc_closure_lit_lib_glsl,
datatoc_closure_lit_lib_glsl,
datatoc_closure_lit_lib_glsl,
datatoc_closure_lit_lib_glsl,
datatoc_closure_lit_lib_glsl,
datatoc_closure_lit_lib_glsl,
datatoc_closure_lit_lib_glsl);
DRW_shader_library_add_file(e_data.lib, e_data.closure_lit_lib, "closure_lit_lib.glsl");
e_data.surface_lit_frag = DRW_shader_library_create_shader_string(e_data.lib,
datatoc_surface_frag_glsl);
e_data.surface_prepass_frag = DRW_shader_library_create_shader_string(
e_data.lib, datatoc_prepass_frag_glsl);
e_data.surface_geom_barycentric = DRW_shader_library_create_shader_string(
e_data.lib, datatoc_surface_geom_glsl);
}
}
void EEVEE_shaders_lightprobe_shaders_init(void)
{
BLI_assert(e_data.probe_filter_glossy_sh == NULL);
char *shader_str = NULL;
shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_lightprobe_filter_glossy_frag_glsl);
eevee_shader_library_ensure();
e_data.probe_filter_glossy_sh = DRW_shader_create(
datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, shader_str, filter_defines);
e_data.probe_filter_glossy_sh = DRW_shader_create_with_shaderlib(
datatoc_lightprobe_vert_glsl,
datatoc_lightprobe_geom_glsl,
datatoc_lightprobe_filter_glossy_frag_glsl,
e_data.lib,
filter_defines);
e_data.probe_default_sh = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
NULL,
datatoc_default_world_frag_glsl,
datatoc_common_view_lib_glsl,
NULL);
e_data.probe_filter_diffuse_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_lightprobe_filter_diffuse_frag_glsl, e_data.lib, filter_defines);
MEM_freeN(shader_str);
e_data.probe_filter_visibility_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_lightprobe_filter_visibility_frag_glsl, e_data.lib, filter_defines);
shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_lightprobe_filter_diffuse_frag_glsl);
e_data.probe_filter_diffuse_sh = DRW_shader_create_fullscreen(shader_str, filter_defines);
MEM_freeN(shader_str);
shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_lightprobe_filter_visibility_frag_glsl);
e_data.probe_filter_visibility_sh = DRW_shader_create_fullscreen(shader_str, filter_defines);
MEM_freeN(shader_str);
e_data.probe_grid_fill_sh = DRW_shader_create_fullscreen(datatoc_lightprobe_grid_fill_frag_glsl,
filter_defines);
e_data.probe_grid_fill_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_lightprobe_grid_fill_frag_glsl, e_data.lib, filter_defines);
e_data.probe_planar_downsample_sh = DRW_shader_create(
datatoc_lightprobe_planar_downsample_vert_glsl,
@ -207,60 +270,13 @@ void EEVEE_shaders_lightprobe_shaders_init(void)
void EEVEE_shaders_material_shaders_init(void)
{
e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_ambient_occlusion_lib_glsl,
datatoc_raytrace_lib_glsl,
datatoc_ssr_lib_glsl,
datatoc_octahedron_lib_glsl,
datatoc_cubemap_lib_glsl,
datatoc_irradiance_lib_glsl,
datatoc_lightprobe_lib_glsl,
datatoc_ltc_lib_glsl,
datatoc_lights_lib_glsl,
/* Add one for each Closure */
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
datatoc_lit_surface_frag_glsl,
datatoc_volumetric_lib_glsl);
eevee_shader_library_ensure();
}
e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_ambient_occlusion_lib_glsl,
datatoc_octahedron_lib_glsl,
datatoc_cubemap_lib_glsl,
datatoc_irradiance_lib_glsl,
datatoc_lightprobe_lib_glsl,
datatoc_ltc_lib_glsl,
datatoc_lights_lib_glsl,
datatoc_volumetric_lib_glsl,
datatoc_volumetric_frag_glsl);
e_data.vert_shader_str = BLI_string_joinN(
datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl);
e_data.vert_shadow_shader_str = BLI_string_joinN(
datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl);
e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_background_vert_glsl);
e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_volumetric_vert_glsl);
e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_volumetric_geom_glsl);
DRWShaderLibrary *EEVEE_shader_lib_get(void)
{
eevee_shader_library_ensure();
return e_data.lib;
}
GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void)
@ -268,11 +284,6 @@ GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void)
return e_data.probe_filter_glossy_sh;
}
GPUShader *EEVEE_shaders_probe_default_sh_get(void)
{
return e_data.probe_default_sh;
}
GPUShader *EEVEE_shaders_probe_filter_diffuse_sh_get(void)
{
return e_data.probe_filter_diffuse_sh;
@ -293,59 +304,40 @@ GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void)
return e_data.probe_planar_downsample_sh;
}
GPUShader *EEVEE_shaders_default_studiolight_sh_get(void)
GPUShader *EEVEE_shaders_studiolight_probe_sh_get(void)
{
if (e_data.probe_default_studiolight_sh == NULL) {
e_data.probe_default_studiolight_sh = DRW_shader_create_with_lib(
datatoc_background_vert_glsl,
NULL,
datatoc_default_world_frag_glsl,
datatoc_common_view_lib_glsl,
"#define LOOKDEV\n");
if (e_data.studiolight_probe_sh == NULL) {
e_data.studiolight_probe_sh = DRW_shader_create_with_shaderlib(datatoc_background_vert_glsl,
NULL,
datatoc_lookdev_world_frag_glsl,
e_data.lib,
SHADER_DEFINES);
}
return e_data.probe_default_studiolight_sh;
return e_data.studiolight_probe_sh;
}
GPUShader *EEVEE_shaders_background_studiolight_sh_get(void)
GPUShader *EEVEE_shaders_studiolight_background_sh_get(void)
{
if (e_data.probe_background_studiolight_sh == NULL) {
char *frag_str = BLI_string_joinN(datatoc_octahedron_lib_glsl,
datatoc_cubemap_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_lightprobe_lib_glsl,
datatoc_default_world_frag_glsl);
e_data.probe_background_studiolight_sh = DRW_shader_create_with_lib(
if (e_data.studiolight_background_sh == NULL) {
e_data.studiolight_background_sh = DRW_shader_create_with_shaderlib(
datatoc_background_vert_glsl,
NULL,
frag_str,
datatoc_common_view_lib_glsl,
datatoc_lookdev_world_frag_glsl,
e_data.lib,
"#define LOOKDEV_BG\n" SHADER_DEFINES);
MEM_freeN(frag_str);
}
return e_data.probe_background_studiolight_sh;
return e_data.studiolight_background_sh;
}
GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void)
{
if (e_data.probe_cube_display_sh == NULL) {
char *shader_str = BLI_string_joinN(datatoc_octahedron_lib_glsl,
datatoc_cubemap_lib_glsl,
datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_lightprobe_lib_glsl,
datatoc_lightprobe_cube_display_frag_glsl);
char *vert_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_lightprobe_cube_display_vert_glsl);
e_data.probe_cube_display_sh = DRW_shader_create(vert_str, NULL, shader_str, SHADER_DEFINES);
MEM_freeN(vert_str);
MEM_freeN(shader_str);
e_data.probe_cube_display_sh = DRW_shader_create_with_shaderlib(
datatoc_lightprobe_cube_display_vert_glsl,
NULL,
datatoc_lightprobe_cube_display_frag_glsl,
e_data.lib,
SHADER_DEFINES);
}
return e_data.probe_cube_display_sh;
}
@ -353,22 +345,12 @@ GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void)
GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void)
{
if (e_data.probe_grid_display_sh == NULL) {
char *shader_str = BLI_string_joinN(datatoc_octahedron_lib_glsl,
datatoc_cubemap_lib_glsl,
datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_irradiance_lib_glsl,
datatoc_lightprobe_lib_glsl,
datatoc_lightprobe_grid_display_frag_glsl);
char *vert_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_lightprobe_grid_display_vert_glsl);
e_data.probe_grid_display_sh = DRW_shader_create(vert_str, NULL, shader_str, filter_defines);
MEM_freeN(vert_str);
MEM_freeN(shader_str);
e_data.probe_grid_display_sh = DRW_shader_create_with_shaderlib(
datatoc_lightprobe_grid_display_vert_glsl,
NULL,
datatoc_lightprobe_grid_display_frag_glsl,
e_data.lib,
filter_defines);
}
return e_data.probe_grid_display_sh;
}
@ -376,16 +358,12 @@ GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void)
GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void)
{
if (e_data.probe_planar_display_sh == NULL) {
char *vert_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_lightprobe_planar_display_vert_glsl);
char *shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_lightprobe_planar_display_frag_glsl);
e_data.probe_planar_display_sh = DRW_shader_create(vert_str, NULL, shader_str, NULL);
MEM_freeN(vert_str);
MEM_freeN(shader_str);
e_data.probe_planar_display_sh = DRW_shader_create_with_shaderlib(
datatoc_lightprobe_planar_display_vert_glsl,
NULL,
datatoc_lightprobe_planar_display_frag_glsl,
e_data.lib,
NULL);
}
return e_data.probe_planar_display_sh;
}
@ -393,34 +371,17 @@ GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void)
GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void)
{
if (e_data.velocity_resolve_sh == NULL) {
char *frag_str = BLI_string_joinN(datatoc_common_uniforms_lib_glsl,
datatoc_common_view_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_effect_velocity_resolve_frag_glsl);
e_data.velocity_resolve_sh = DRW_shader_create_fullscreen(frag_str, NULL);
MEM_freeN(frag_str);
e_data.velocity_resolve_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_velocity_resolve_frag_glsl, e_data.lib, NULL);
}
return e_data.velocity_resolve_sh;
}
GPUShader *EEVEE_shaders_default_background_sh_get(void)
{
if (e_data.default_background == NULL) {
e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
NULL,
datatoc_default_world_frag_glsl,
datatoc_common_view_lib_glsl,
NULL);
}
return e_data.default_background;
}
GPUShader *EEVEE_shaders_update_noise_sh_get(void)
{
if (e_data.update_noise_sh == NULL) {
e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL);
e_data.update_noise_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_update_noise_frag_glsl, e_data.lib, NULL);
}
return e_data.update_noise_sh;
}
@ -437,13 +398,8 @@ GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects)
sh = &e_data.taa_resolve_sh;
}
if (*sh == NULL) {
char *frag_str = BLI_string_joinN(datatoc_common_uniforms_lib_glsl,
datatoc_common_view_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_effect_temporal_aa_glsl);
*sh = DRW_shader_create_fullscreen(frag_str, define);
MEM_freeN(frag_str);
*sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_temporal_aa_glsl, e_data.lib, define);
}
return *sh;
@ -583,6 +539,18 @@ struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo)
return e_data.world.ntree;
}
World *EEVEE_world_default_get(void)
{
if (e_data.default_world == NULL) {
e_data.default_world = BKE_id_new_nomain(ID_WO, "EEVEEE default world");
copy_v3_fl(&e_data.default_world->horr, 0.0f);
e_data.default_world->use_nodes = 0;
e_data.default_world->nodetree = NULL;
BLI_listbase_clear(&e_data.default_world->gpumaterial);
}
return e_data.default_world;
}
static char *eevee_get_defines(int options)
{
char *str = NULL;
@ -605,7 +573,7 @@ static char *eevee_get_defines(int options)
if ((options & VAR_MAT_HAIR) != 0) {
BLI_dynstr_append(ds, "#define HAIR_SHADER\n");
}
if ((options & (VAR_MAT_PROBE | VAR_WORLD_PROBE)) != 0) {
if ((options & VAR_WORLD_PROBE) != 0) {
BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n");
}
if ((options & VAR_MAT_HASH) != 0) {
@ -635,13 +603,13 @@ static char *eevee_get_vert(int options)
char *str = NULL;
if ((options & VAR_MAT_VOLUME) != 0) {
str = BLI_strdup(e_data.vert_volume_shader_str);
str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_volumetric_vert_glsl);
}
else if ((options & (VAR_WORLD_PROBE | VAR_WORLD_BACKGROUND)) != 0) {
str = BLI_strdup(e_data.vert_background_shader_str);
str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_background_vert_glsl);
}
else {
str = BLI_strdup(e_data.vert_shader_str);
str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_surface_vert_glsl);
}
return str;
@ -652,7 +620,7 @@ static char *eevee_get_geom(int options)
char *str = NULL;
if ((options & VAR_MAT_VOLUME) != 0) {
str = BLI_strdup(e_data.geom_volume_shader_str);
str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_volumetric_geom_glsl);
}
return str;
@ -663,18 +631,36 @@ static char *eevee_get_frag(int options)
char *str = NULL;
if ((options & VAR_MAT_VOLUME) != 0) {
str = BLI_strdup(e_data.volume_shader_lib);
str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_volumetric_frag_glsl);
}
else if ((options & VAR_MAT_DEPTH) != 0) {
str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
str = BLI_strdup(e_data.surface_prepass_frag);
}
else {
str = BLI_strdup(e_data.frag_shader_lib);
str = BLI_strdup(e_data.surface_lit_frag);
}
return str;
}
static void eevee_material_post_eval(GPUMaterial *mat,
int options,
const char **UNUSED(vert_code),
const char **geom_code,
const char **UNUSED(frag_lib),
const char **UNUSED(defines))
{
const bool is_hair = (options & VAR_MAT_HAIR) != 0;
const bool is_mesh = (options & VAR_MAT_MESH) != 0;
/* Force geometry usage if GPU_BARYCENTRIC_DIST or GPU_BARYCENTRIC_TEXCO are used.
* Note: GPU_BARYCENTRIC_TEXCO only requires it if the shader is not drawing hairs. */
if (!is_hair && is_mesh && GPU_material_flag_get(mat, GPU_MATFLAG_BARYCENTRIC) &&
*geom_code == NULL) {
*geom_code = e_data.surface_geom_barycentric;
}
}
static struct GPUMaterial *eevee_material_get_ex(
struct Scene *scene, Material *ma, World *wo, int options, bool deferred)
{
@ -702,14 +688,16 @@ static struct GPUMaterial *eevee_material_get_ex(
char *frag = eevee_get_frag(options);
if (ma) {
GPUMaterialEvalCallbackFn *cbfn = &eevee_material_post_eval;
bNodeTree *ntree = !is_default ? ma->nodetree : EEVEE_shader_default_surface_nodetree(ma);
mat = DRW_shader_create_from_material(
scene, ma, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred);
scene, ma, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred, cbfn);
}
else {
bNodeTree *ntree = !is_default ? wo->nodetree : EEVEE_shader_default_world_nodetree(wo);
mat = DRW_shader_create_from_world(
scene, wo, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred);
scene, wo, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred, NULL);
}
MEM_SAFE_FREE(defines);
@ -764,30 +752,31 @@ struct GPUMaterial *EEVEE_material_get(
void EEVEE_shaders_free(void)
{
MEM_SAFE_FREE(e_data.frag_shader_lib);
MEM_SAFE_FREE(e_data.vert_shader_str);
MEM_SAFE_FREE(e_data.vert_shadow_shader_str);
MEM_SAFE_FREE(e_data.vert_background_shader_str);
MEM_SAFE_FREE(e_data.vert_volume_shader_str);
MEM_SAFE_FREE(e_data.geom_volume_shader_str);
MEM_SAFE_FREE(e_data.volume_shader_lib);
DRW_SHADER_FREE_SAFE(e_data.default_background);
MEM_SAFE_FREE(e_data.closure_lit_lib);
MEM_SAFE_FREE(e_data.surface_prepass_frag);
MEM_SAFE_FREE(e_data.surface_lit_frag);
MEM_SAFE_FREE(e_data.surface_geom_barycentric);
DRW_SHADER_FREE_SAFE(e_data.lookdev_background);
DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_default_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_visibility_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_grid_fill_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_planar_downsample_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_default_studiolight_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_background_studiolight_sh);
DRW_SHADER_FREE_SAFE(e_data.studiolight_probe_sh);
DRW_SHADER_FREE_SAFE(e_data.studiolight_background_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_grid_display_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_cube_display_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_planar_display_sh);
DRW_SHADER_FREE_SAFE(e_data.velocity_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.taa_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.taa_resolve_reproject_sh);
DRW_SHADER_LIB_FREE_SAFE(e_data.lib);
if (e_data.default_world) {
BKE_id_free(NULL, e_data.default_world);
e_data.default_world = NULL;
}
if (e_data.glossy_mat) {
BKE_id_free(NULL, e_data.glossy_mat);
e_data.glossy_mat = NULL;

View File

@ -42,11 +42,6 @@ static struct {
extern char datatoc_shadow_vert_glsl[];
extern char datatoc_shadow_frag_glsl[];
extern char datatoc_shadow_accum_frag_glsl[];
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_lights_lib_glsl[];
extern char datatoc_raytrace_lib_glsl[];
void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh)
{
@ -65,23 +60,13 @@ void EEVEE_shadows_init(EEVEE_ViewLayerData *sldata)
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
if (!e_data.shadow_sh) {
e_data.shadow_sh = DRW_shader_create_with_lib(datatoc_shadow_vert_glsl,
NULL,
datatoc_shadow_frag_glsl,
datatoc_common_view_lib_glsl,
NULL);
}
DRWShaderLibrary *lib = EEVEE_shader_lib_get();
if (!e_data.shadow_accum_sh) {
char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_raytrace_lib_glsl,
datatoc_lights_lib_glsl,
datatoc_shadow_accum_frag_glsl);
e_data.shadow_sh = DRW_shader_create_with_shaderlib(
datatoc_shadow_vert_glsl, NULL, datatoc_shadow_frag_glsl, lib, NULL);
e_data.shadow_accum_sh = DRW_shader_create_fullscreen(frag_str, SHADER_DEFINES);
MEM_freeN(frag_str);
e_data.shadow_accum_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_shadow_accum_frag_glsl, lib, SHADER_DEFINES);
}
if (!sldata->lights) {

View File

@ -38,41 +38,19 @@ static struct {
struct GPUShader *sss_sh[3];
} e_data = {{NULL}}; /* Engine data */
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_lights_lib_glsl[];
extern char datatoc_raytrace_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_cubemap_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_effect_subsurface_frag_glsl[];
extern char datatoc_effect_translucency_frag_glsl[];
static void eevee_create_shader_subsurface(void)
{
char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_effect_subsurface_frag_glsl);
DRWShaderLibrary *lib = EEVEE_shader_lib_get();
/* TODO(fclem) remove some of these dependencies. */
char *frag_translucent_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_raytrace_lib_glsl,
datatoc_octahedron_lib_glsl,
datatoc_cubemap_lib_glsl,
datatoc_lights_lib_glsl,
datatoc_effect_translucency_frag_glsl);
e_data.sss_sh[0] = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n");
e_data.sss_sh[1] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n");
e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_translucent_str,
"#define EEVEE_TRANSLUCENCY\n" SHADER_DEFINES);
MEM_freeN(frag_translucent_str);
MEM_freeN(frag_str);
e_data.sss_sh[0] = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_subsurface_frag_glsl, lib, "#define FIRST_PASS\n");
e_data.sss_sh[1] = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_subsurface_frag_glsl, lib, "#define SECOND_PASS\n");
e_data.sss_sh[2] = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_translucency_frag_glsl, lib, "#define EEVEE_TRANSLUCENCY\n" SHADER_DEFINES);
}
void EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *UNUSED(vedata))

View File

@ -50,9 +50,6 @@
#include "eevee_private.h"
static struct {
char *volumetric_common_lib;
char *volumetric_common_lights_lib;
struct GPUShader *volumetric_clear_sh;
struct GPUShader *scatter_sh;
struct GPUShader *scatter_with_lights_sh;
@ -96,57 +93,48 @@ 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);
DRWShaderLibrary *lib = EEVEE_shader_lib_get();
e_data.volumetric_common_lights_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_octahedron_lib_glsl,
datatoc_cubemap_lib_glsl,
datatoc_irradiance_lib_glsl,
datatoc_lights_lib_glsl,
datatoc_volumetric_lib_glsl);
e_data.volumetric_clear_sh = DRW_shader_create_with_shaderlib(datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
datatoc_volumetric_frag_glsl,
lib,
SHADER_DEFINES
"#define VOLUMETRICS\n"
"#define CLEAR\n");
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,
"#define VOLUMETRICS\n"
"#define CLEAR\n");
e_data.scatter_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
datatoc_volumetric_scatter_frag_glsl,
e_data.volumetric_common_lights_lib,
SHADER_DEFINES
"#define VOLUMETRICS\n"
"#define VOLUME_SHADOW\n");
e_data.scatter_with_lights_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
datatoc_volumetric_scatter_frag_glsl,
e_data.volumetric_common_lights_lib,
SHADER_DEFINES
"#define VOLUMETRICS\n"
"#define VOLUME_LIGHTING\n"
"#define VOLUME_SHADOW\n");
e_data.volumetric_integration_sh = DRW_shader_create_with_lib(
e_data.scatter_sh = DRW_shader_create_with_shaderlib(datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
datatoc_volumetric_scatter_frag_glsl,
lib,
SHADER_DEFINES
"#define VOLUMETRICS\n"
"#define VOLUME_SHADOW\n");
e_data.scatter_with_lights_sh = DRW_shader_create_with_shaderlib(
datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
datatoc_volumetric_scatter_frag_glsl,
lib,
SHADER_DEFINES
"#define VOLUMETRICS\n"
"#define VOLUME_LIGHTING\n"
"#define VOLUME_SHADOW\n");
e_data.volumetric_integration_sh = DRW_shader_create_with_shaderlib(
datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
datatoc_volumetric_integration_frag_glsl,
e_data.volumetric_common_lib,
lib,
USE_VOLUME_OPTI ? "#extension GL_ARB_shader_image_load_store: enable\n"
"#extension GL_ARB_shading_language_420pack: enable\n"
"#define USE_VOLUME_OPTI\n" :
NULL);
e_data.volumetric_resolve_sh = DRW_shader_create_with_lib(datatoc_common_fullscreen_vert_glsl,
NULL,
datatoc_volumetric_resolve_frag_glsl,
e_data.volumetric_common_lib,
NULL);
e_data.volumetric_accum_sh = DRW_shader_create_fullscreen(datatoc_volumetric_accum_frag_glsl,
NULL);
"#define USE_VOLUME_OPTI\n" SHADER_DEFINES :
SHADER_DEFINES);
e_data.volumetric_resolve_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_volumetric_resolve_frag_glsl, lib, SHADER_DEFINES);
e_data.volumetric_accum_sh = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_volumetric_accum_frag_glsl, lib, SHADER_DEFINES);
const float density[4] = {1.0f, 1.0f, 1.0f, 1.0f};
e_data.dummy_density = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, density);
@ -258,17 +246,11 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
common_data->vol_shadow_steps = 0;
}
/* Update view_vecs */
float invproj[4][4], winmat[4][4];
DRW_view_winmat_get(NULL, winmat, false);
DRW_view_winmat_get(NULL, invproj, true);
EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs);
if (DRW_view_is_persp_get(NULL)) {
float sample_distribution = scene_eval->eevee.volumetric_sample_distribution;
sample_distribution = 4.0f * (max_ff(1.0f - sample_distribution, 1e-2f));
const float clip_start = common_data->view_vecs[0][2];
const float clip_start = DRW_view_near_distance_get(NULL);
/* Negate */
float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f);
float far = integration_end = min_ff(-integration_end, near - 1e-4f);
@ -279,8 +261,8 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
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];
const float clip_start = DRW_view_near_distance_get(NULL);
const float clip_end = DRW_view_far_distance_get(NULL);
integration_start = min_ff(integration_end, clip_start);
integration_end = max_ff(-integration_end, clip_end);
@ -842,9 +824,6 @@ void EEVEE_volumes_free_smoke_textures(void)
void EEVEE_volumes_free(void)
{
MEM_SAFE_FREE(e_data.volumetric_common_lib);
MEM_SAFE_FREE(e_data.volumetric_common_lights_lib);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_scatter);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_transmit);

View File

@ -1,4 +1,7 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(raytrace_lib.glsl)
/* Based on Practical Realtime Strategies for Accurate Indirect Occlusion
* http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf
* http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx
@ -24,12 +27,6 @@
#define MAX_SEARCH_ITER 32
#define MAX_LOD 6.0
#ifndef UTIL_TEX
# define UTIL_TEX
uniform sampler2DArray utilTex;
# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
uniform sampler2D horizonBuffer;
/* aoSettings flags */
@ -243,6 +240,11 @@ float gtao_multibounce(float visibility, vec3 albedo)
return max(x, ((x * a + b) * x + c) * x);
}
float specular_occlusion(float NV, float AO, float roughness)
{
return saturate(pow(NV + AO, roughness) - 1.0 + AO);
}
/* Use the right occlusion */
float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec4 rand, out vec3 bent_normal)
{

View File

@ -1,17 +1,17 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
in vec2 pos;
out vec3 viewPosition;
#ifndef VOLUMETRICS
/* necessary for compilation*/
out vec3 worldPosition;
out vec3 worldNormal;
out vec3 viewNormal;
#endif
RESOURCE_ID_VARYING
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
PASS_RESOURCE_ID
gl_Position = vec4(pos, 1.0, 1.0);
viewPosition = vec3(pos, -1.0);
@ -22,6 +22,6 @@ void main()
#endif
#ifdef USE_ATTR
pass_attr(viewPosition);
pass_attr(viewPosition, NormalMatrix, ModelMatrixInverse);
#endif
}

View File

@ -1,487 +1,7 @@
#define M_PI 3.14159265358979323846 /* pi */
#define M_2PI 6.28318530717958647692 /* 2*pi */
#define M_PI_2 1.57079632679489661923 /* pi/2 */
#define M_1_PI 0.318309886183790671538 /* 1/pi */
#define M_1_2PI 0.159154943091895335768 /* 1/(2*pi) */
#define M_1_PI2 0.101321183642337771443 /* 1/(pi^2) */
#define FLT_MAX 3.402823e+38
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#define LUT_SIZE 64
/* Buffers */
uniform sampler2D colorBuffer;
uniform sampler2D depthBuffer;
uniform sampler2D maxzBuffer;
uniform sampler2D minzBuffer;
uniform sampler2DArray planarDepth;
#define cameraForward ViewMatrixInverse[2].xyz
#define cameraPos ViewMatrixInverse[3].xyz
#define cameraVec \
((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward)
#define viewCameraVec \
((ProjectionMatrix[3][3] == 0.0) ? normalize(-viewPosition) : vec3(0.0, 0.0, 1.0))
/* ------- Structures -------- */
/* ------ Lights ----- */
struct LightData {
vec4 position_influence; /* w : InfluenceRadius (inversed and squared) */
vec4 color_spec; /* w : Spec Intensity */
vec4 spotdata_radius_shadow; /* x : spot size, y : spot blend, z : radius, w: shadow id */
vec4 rightvec_sizex; /* xyz: Normalized up vector, w: area size X or spot scale X */
vec4 upvec_sizey; /* xyz: Normalized right vector, w: area size Y or spot scale Y */
vec4 forwardvec_type; /* xyz: Normalized forward vector, w: Light Type */
};
/* convenience aliases */
#define l_color color_spec.rgb
#define l_spec color_spec.a
#define l_position position_influence.xyz
#define l_influence position_influence.w
#define l_sizex rightvec_sizex.w
#define l_sizey upvec_sizey.w
#define l_right rightvec_sizex.xyz
#define l_up upvec_sizey.xyz
#define l_forward forwardvec_type.xyz
#define l_type forwardvec_type.w
#define l_spot_size spotdata_radius_shadow.x
#define l_spot_blend spotdata_radius_shadow.y
#define l_radius spotdata_radius_shadow.z
#define l_shadowid spotdata_radius_shadow.w
/* ------ Shadows ----- */
#ifndef MAX_CASCADE_NUM
# define MAX_CASCADE_NUM 4
#endif
struct ShadowData {
vec4 near_far_bias_id;
vec4 contact_shadow_data;
};
struct ShadowCubeData {
mat4 shadowmat;
vec4 position;
};
struct ShadowCascadeData {
mat4 shadowmat[MAX_CASCADE_NUM];
vec4 split_start_distances;
vec4 split_end_distances;
vec4 shadow_vec_id;
};
/* convenience aliases */
#define sh_near near_far_bias_id.x
#define sh_far near_far_bias_id.y
#define sh_bias near_far_bias_id.z
#define sh_data_index near_far_bias_id.w
#define sh_contact_dist contact_shadow_data.x
#define sh_contact_offset contact_shadow_data.y
#define sh_contact_spread contact_shadow_data.z
#define sh_contact_thickness contact_shadow_data.w
#define sh_shadow_vec shadow_vec_id.xyz
#define sh_tex_index shadow_vec_id.w
/* ------ Render Passes ----- */
layout(std140) uniform renderpass_block
{
bool renderPassDiffuse;
bool renderPassDiffuseLight;
bool renderPassGlossy;
bool renderPassGlossyLight;
bool renderPassEmit;
bool renderPassSSSColor;
bool renderPassEnvironment;
};
vec3 render_pass_diffuse_mask(vec3 diffuse_color, vec3 diffuse_light)
{
return renderPassDiffuse ? (renderPassDiffuseLight ? diffuse_light : diffuse_color) : vec3(0.0);
}
vec3 render_pass_sss_mask(vec3 sss_color)
{
return renderPassSSSColor ? sss_color : vec3(0.0);
}
vec3 render_pass_glossy_mask(vec3 specular_color, vec3 specular_light)
{
return renderPassGlossy ? (renderPassGlossyLight ? specular_light : specular_color) : vec3(0.0);
}
vec3 render_pass_emission_mask(vec3 emission_light)
{
return renderPassEmit ? emission_light : vec3(0.0);
}
/* ------- Convenience functions --------- */
vec3 mul(mat3 m, vec3 v)
{
return m * v;
}
mat3 mul(mat3 m1, mat3 m2)
{
return m1 * m2;
}
vec3 transform_direction(mat4 m, vec3 v)
{
return mat3(m) * v;
}
vec3 transform_point(mat4 m, vec3 v)
{
return (m * vec4(v, 1.0)).xyz;
}
vec3 project_point(mat4 m, vec3 v)
{
vec4 tmp = m * vec4(v, 1.0);
return tmp.xyz / tmp.w;
}
#define min3(a, b, c) min(a, min(b, c))
#define min4(a, b, c, d) min(a, min3(b, c, d))
#define min5(a, b, c, d, e) min(a, min4(b, c, d, e))
#define min6(a, b, c, d, e, f) min(a, min5(b, c, d, e, f))
#define min7(a, b, c, d, e, f, g) min(a, min6(b, c, d, e, f, g))
#define min8(a, b, c, d, e, f, g, h) min(a, min7(b, c, d, e, f, g, h))
#define min9(a, b, c, d, e, f, g, h, i) min(a, min8(b, c, d, e, f, g, h, i))
#define max3(a, b, c) max(a, max(b, c))
#define max4(a, b, c, d) max(a, max3(b, c, d))
#define max5(a, b, c, d, e) max(a, max4(b, c, d, e))
#define max6(a, b, c, d, e, f) max(a, max5(b, c, d, e, f))
#define max7(a, b, c, d, e, f, g) max(a, max6(b, c, d, e, f, g))
#define max8(a, b, c, d, e, f, g, h) max(a, max7(b, c, d, e, f, g, h))
#define max9(a, b, c, d, e, f, g, h, i) max(a, max8(b, c, d, e, f, g, h, i))
#define avg3(a, b, c) (a + b + c) * (1.0 / 3.0)
#define avg4(a, b, c, d) (a + b + c + d) * (1.0 / 4.0)
#define avg5(a, b, c, d, e) (a + b + c + d + e) * (1.0 / 5.0)
#define avg6(a, b, c, d, e, f) (a + b + c + d + e + f) * (1.0 / 6.0)
#define avg7(a, b, c, d, e, f, g) (a + b + c + d + e + f + g) * (1.0 / 7.0)
#define avg8(a, b, c, d, e, f, g, h) (a + b + c + d + e + f + g + h) * (1.0 / 8.0)
#define avg9(a, b, c, d, e, f, g, h, i) (a + b + c + d + e + f + g + h + i) * (1.0 / 9.0)
float min_v2(vec2 v)
{
return min(v.x, v.y);
}
float min_v3(vec3 v)
{
return min(v.x, min(v.y, v.z));
}
float min_v4(vec4 v)
{
return min(min(v.x, v.y), min(v.z, v.w));
}
float max_v2(vec2 v)
{
return max(v.x, v.y);
}
float max_v3(vec3 v)
{
return max(v.x, max(v.y, v.z));
}
float max_v4(vec4 v)
{
return max(max(v.x, v.y), max(v.z, v.w));
}
float sum(vec2 v)
{
return dot(vec2(1.0), v);
}
float sum(vec3 v)
{
return dot(vec3(1.0), v);
}
float sum(vec4 v)
{
return dot(vec4(1.0), v);
}
float avg(vec2 v)
{
return dot(vec2(1.0 / 2.0), v);
}
float avg(vec3 v)
{
return dot(vec3(1.0 / 3.0), v);
}
float avg(vec4 v)
{
return dot(vec4(1.0 / 4.0), v);
}
float saturate(float a)
{
return clamp(a, 0.0, 1.0);
}
vec2 saturate(vec2 a)
{
return clamp(a, 0.0, 1.0);
}
vec3 saturate(vec3 a)
{
return clamp(a, 0.0, 1.0);
}
vec4 saturate(vec4 a)
{
return clamp(a, 0.0, 1.0);
}
float distance_squared(vec2 a, vec2 b)
{
a -= b;
return dot(a, a);
}
float distance_squared(vec3 a, vec3 b)
{
a -= b;
return dot(a, a);
}
float len_squared(vec3 a)
{
return dot(a, a);
}
float inverse_distance(vec3 V)
{
return max(1 / length(V), 1e-8);
}
vec2 mip_ratio_interp(float mip)
{
float low_mip = floor(mip);
return mix(mipRatio[int(low_mip)], mipRatio[int(low_mip + 1.0)], mip - low_mip);
}
/* ------- RNG ------- */
float wang_hash_noise(uint s)
{
s = (s ^ 61u) ^ (s >> 16u);
s *= 9u;
s = s ^ (s >> 4u);
s *= 0x27d4eb2du;
s = s ^ (s >> 15u);
return fract(float(s) / 4294967296.0);
}
/* ------- Fast Math ------- */
/* [Drobot2014a] Low Level Optimizations for GCN */
float fast_sqrt(float v)
{
return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1));
}
vec2 fast_sqrt(vec2 v)
{
return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1));
}
/* [Eberly2014] GPGPU Programming for Games and Science */
float fast_acos(float v)
{
float res = -0.156583 * abs(v) + M_PI_2;
res *= fast_sqrt(1.0 - abs(v));
return (v >= 0) ? res : M_PI - res;
}
vec2 fast_acos(vec2 v)
{
vec2 res = -0.156583 * abs(v) + M_PI_2;
res *= fast_sqrt(1.0 - abs(v));
v.x = (v.x >= 0) ? res.x : M_PI - res.x;
v.y = (v.y >= 0) ? res.y : M_PI - res.y;
return v;
}
float point_plane_projection_dist(vec3 lineorigin, vec3 planeorigin, vec3 planenormal)
{
return dot(planenormal, planeorigin - lineorigin);
}
float line_plane_intersect_dist(vec3 lineorigin,
vec3 linedirection,
vec3 planeorigin,
vec3 planenormal)
{
return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection);
}
float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec4 plane)
{
vec3 plane_co = plane.xyz * (-plane.w / len_squared(plane.xyz));
vec3 h = lineorigin - plane_co;
return -dot(plane.xyz, h) / dot(plane.xyz, linedirection);
}
vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal)
{
float dist = line_plane_intersect_dist(lineorigin, linedirection, planeorigin, planenormal);
return lineorigin + linedirection * dist;
}
vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec4 plane)
{
float dist = line_plane_intersect_dist(lineorigin, linedirection, plane);
return lineorigin + linedirection * dist;
}
float line_aligned_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin)
{
/* aligned plane normal */
vec3 L = planeorigin - lineorigin;
float diskdist = length(L);
vec3 planenormal = -normalize(L);
return -diskdist / dot(planenormal, linedirection);
}
vec3 line_aligned_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin)
{
float dist = line_aligned_plane_intersect_dist(lineorigin, linedirection, planeorigin);
if (dist < 0) {
/* if intersection is behind we fake the intersection to be
* really far and (hopefully) not inside the radius of interest */
dist = 1e16;
}
return lineorigin + linedirection * dist;
}
float line_unit_sphere_intersect_dist(vec3 lineorigin, vec3 linedirection)
{
float a = dot(linedirection, linedirection);
float b = dot(linedirection, lineorigin);
float c = dot(lineorigin, lineorigin) - 1;
float dist = 1e15;
float determinant = b * b - a * c;
if (determinant >= 0) {
dist = (sqrt(determinant) - b) / a;
}
return dist;
}
float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection)
{
/* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
*/
vec3 firstplane = (vec3(1.0) - lineorigin) / linedirection;
vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection;
vec3 furthestplane = max(firstplane, secondplane);
return min_v3(furthestplane);
}
/* Return texture coordinates to sample Surface LUT */
vec2 lut_coords(float cosTheta, float roughness)
{
float theta = acos(cosTheta);
vec2 coords = vec2(roughness, theta / M_PI_2);
/* scale and bias coordinates, for correct filtered lookup */
return coords * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE;
}
vec2 lut_coords_ltc(float cosTheta, float roughness)
{
vec2 coords = vec2(roughness, sqrt(1.0 - cosTheta));
/* scale and bias coordinates, for correct filtered lookup */
return coords * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE;
}
/* -- Tangent Space conversion -- */
vec3 tangent_to_world(vec3 vector, vec3 N, vec3 T, vec3 B)
{
return T * vector.x + B * vector.y + N * vector.z;
}
vec3 world_to_tangent(vec3 vector, vec3 N, vec3 T, vec3 B)
{
return vec3(dot(T, vector), dot(B, vector), dot(N, vector));
}
void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B)
{
vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
T = normalize(cross(UpVector, N));
B = cross(N, T);
}
/* ---- Opengl Depth conversion ---- */
float linear_depth(bool is_persp, float z, float zf, float zn)
{
if (is_persp) {
return (zn * zf) / (z * (zn - zf) + zf);
}
else {
return (z * 2.0 - 1.0) * zf;
}
}
float buffer_depth(bool is_persp, float z, float zf, float zn)
{
if (is_persp) {
return (zf * (zn - z)) / (z * (zn - zf));
}
else {
return (z / (zf * 2.0)) + 0.5;
}
}
float get_view_z_from_depth(float depth)
{
if (ProjectionMatrix[3][3] == 0.0) {
float d = 2.0 * depth - 1.0;
return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
}
else {
return viewVecs[0].z + depth * viewVecs[1].z;
}
}
float get_depth_from_view_z(float z)
{
if (ProjectionMatrix[3][3] == 0.0) {
float d = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2];
return d * 0.5 + 0.5;
}
else {
return (z - viewVecs[0].z) / viewVecs[1].z;
}
}
vec2 get_uvs_from_view(vec3 view)
{
vec3 ndc = project_point(ProjectionMatrix, view);
return ndc.xy * 0.5 + 0.5;
}
vec3 get_view_space_from_depth(vec2 uvcoords, float depth)
{
if (ProjectionMatrix[3][3] == 0.0) {
return vec3(viewVecs[0].xy + uvcoords * viewVecs[1].xy, 1.0) * get_view_z_from_depth(depth);
}
else {
return viewVecs[0].xyz + vec3(uvcoords, depth) * viewVecs[1].xyz;
}
}
vec3 get_world_space_from_depth(vec2 uvcoords, float depth)
{
return (ViewMatrixInverse * vec4(get_view_space_from_depth(uvcoords, depth), 1.0)).xyz;
}
vec3 get_specular_reflection_dominant_dir(vec3 N, vec3 V, float roughness)
vec3 specular_dominant_dir(vec3 N, vec3 V, float roughness)
{
vec3 R = -reflect(V, N);
float smoothness = 1.0 - roughness;
@ -489,13 +9,6 @@ vec3 get_specular_reflection_dominant_dir(vec3 N, vec3 V, float roughness)
return normalize(mix(N, R, fac));
}
float specular_occlusion(float NV, float AO, float roughness)
{
return saturate(pow(NV + AO, roughness) - 1.0 + AO);
}
/* --- Refraction utils --- */
float ior_from_f0(float f0)
{
float f = sqrt(f0);
@ -508,7 +21,7 @@ float f0_from_ior(float eta)
return A * A;
}
vec3 get_specular_refraction_dominant_dir(vec3 N, vec3 V, float roughness, float ior)
vec3 refraction_dominant_dir(vec3 N, vec3 V, float roughness, float ior)
{
/* TODO: This a bad approximation. Better approximation should fit
* the refracted vector and roughness into the best prefiltered reflection
@ -527,128 +40,6 @@ vec3 get_specular_refraction_dominant_dir(vec3 N, vec3 V, float roughness, float
return R;
}
float get_btdf_lut(sampler2DArray btdf_lut_tex, float NV, float roughness, float ior)
{
const vec3 lut_scale_bias_texel_size = vec3((LUT_SIZE - 1.0), 0.5, 1.5) / LUT_SIZE;
vec3 coords;
/* Try to compensate for the low resolution and interpolation error. */
coords.x = (ior > 1.0) ? (0.9 + lut_scale_bias_texel_size.z) +
(0.1 - lut_scale_bias_texel_size.z) * f0_from_ior(ior) :
(0.9 + lut_scale_bias_texel_size.z) * ior * ior;
coords.y = 1.0 - saturate(NV);
coords.xy *= lut_scale_bias_texel_size.x;
coords.xy += lut_scale_bias_texel_size.y;
const float lut_lvl_ofs = 4.0; /* First texture lvl of roughness. */
const float lut_lvl_scale = 16.0; /* How many lvl of roughness in the lut. */
float mip = roughness * lut_lvl_scale;
float mip_floor = floor(mip);
coords.z = lut_lvl_ofs + mip_floor + 1.0;
float btdf_high = textureLod(btdf_lut_tex, coords, 0.0).r;
coords.z -= 1.0;
float btdf_low = textureLod(btdf_lut_tex, coords, 0.0).r;
float btdf = (ior == 1.0) ? 1.0 : mix(btdf_low, btdf_high, mip - coords.z);
return btdf;
}
/* ---- Encode / Decode Normal buffer data ---- */
/* From http://aras-p.info/texts/CompactNormalStorage.html
* Using Method #4: Spheremap Transform */
vec2 normal_encode(vec3 n, vec3 view)
{
float p = sqrt(n.z * 8.0 + 8.0);
return n.xy / p + 0.5;
}
vec3 normal_decode(vec2 enc, vec3 view)
{
vec2 fenc = enc * 4.0 - 2.0;
float f = dot(fenc, fenc);
float g = sqrt(1.0 - f / 4.0);
vec3 n;
n.xy = fenc * g;
n.z = 1 - f / 2;
return n;
}
/* ---- RGBM (shared multiplier) encoding ---- */
/* From http://iwasbeingirony.blogspot.fr/2010/06/difference-between-rgbm-and-rgbd.html */
/* Higher RGBM_MAX_RANGE gives imprecision issues in low intensity. */
#define RGBM_MAX_RANGE 512.0
vec4 rgbm_encode(vec3 rgb)
{
float maxRGB = max_v3(rgb);
float M = maxRGB / RGBM_MAX_RANGE;
M = ceil(M * 255.0) / 255.0;
return vec4(rgb / (M * RGBM_MAX_RANGE), M);
}
vec3 rgbm_decode(vec4 data)
{
return data.rgb * (data.a * RGBM_MAX_RANGE);
}
/* ---- RGBE (shared exponent) encoding ---- */
vec4 rgbe_encode(vec3 rgb)
{
float maxRGB = max_v3(rgb);
float fexp = ceil(log2(maxRGB));
return vec4(rgb / exp2(fexp), (fexp + 128.0) / 255.0);
}
vec3 rgbe_decode(vec4 data)
{
float fexp = data.a * 255.0 - 128.0;
return data.rgb * exp2(fexp);
}
#if 1
# define irradiance_encode rgbe_encode
# define irradiance_decode rgbe_decode
#else /* No ecoding (when using floating point format) */
# define irradiance_encode(X) (X).rgbb
# define irradiance_decode(X) (X).rgb
#endif
/* Irradiance Visibility Encoding */
#if 1
vec4 visibility_encode(vec2 accum, float range)
{
accum /= range;
vec4 data;
data.x = fract(accum.x);
data.y = floor(accum.x) / 255.0;
data.z = fract(accum.y);
data.w = floor(accum.y) / 255.0;
return data;
}
vec2 visibility_decode(vec4 data, float range)
{
return (data.xz + data.yw * 255.0) * range;
}
#else /* No ecoding (when using floating point format) */
vec4 visibility_encode(vec2 accum, float range)
{
return accum.xyxy;
}
vec2 visibility_decode(vec4 data, float range)
{
return data.xy;
}
#endif
/* Fresnel monochromatic, perfect mirror */
float F_eta(float eta, float cos_theta)
{
@ -766,265 +157,3 @@ float cone_cosine(float r)
/* Jimenez 2016 in Practical Realtime Strategies for Accurate Indirect Occlusion*/
return exp2(-3.32193 * r * r);
}
/* --------- Closure ---------- */
#ifdef VOLUMETRICS
struct Closure {
vec3 absorption;
vec3 scatter;
vec3 emission;
float anisotropy;
};
Closure nodetree_exec(void); /* Prototype */
# define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), vec3(0.0), 0.0)
Closure closure_mix(Closure cl1, Closure cl2, float fac)
{
Closure cl;
cl.absorption = mix(cl1.absorption, cl2.absorption, fac);
cl.scatter = mix(cl1.scatter, cl2.scatter, fac);
cl.emission = mix(cl1.emission, cl2.emission, fac);
cl.anisotropy = mix(cl1.anisotropy, cl2.anisotropy, fac);
return cl;
}
Closure closure_add(Closure cl1, Closure cl2)
{
Closure cl;
cl.absorption = cl1.absorption + cl2.absorption;
cl.scatter = cl1.scatter + cl2.scatter;
cl.emission = cl1.emission + cl2.emission;
cl.anisotropy = (cl1.anisotropy + cl2.anisotropy) / 2.0; /* Average phase (no multi lobe) */
return cl;
}
Closure closure_emission(vec3 rgb)
{
Closure cl = CLOSURE_DEFAULT;
cl.emission = rgb;
return cl;
}
#else /* VOLUMETRICS */
struct Closure {
vec3 radiance;
vec3 transmittance;
float holdout;
# ifdef USE_SSS
vec3 sss_irradiance;
vec3 sss_albedo;
float sss_radius;
# endif
vec4 ssr_data;
vec2 ssr_normal;
int flag;
};
Closure nodetree_exec(void); /* Prototype */
# define FLAG_TEST(flag, val) (((flag) & (val)) != 0)
# define CLOSURE_SSR_FLAG 1
# define CLOSURE_SSS_FLAG 2
# define CLOSURE_HOLDOUT_FLAG 4
# ifdef USE_SSS
# define CLOSURE_DEFAULT \
Closure(vec3(0.0), vec3(0.0), 0.0, vec3(0.0), vec3(0.0), 0.0, vec4(0.0), vec2(0.0), 0)
# else
# define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), 0.0, vec4(0.0), vec2(0.0), 0)
# endif
uniform int outputSsrId = 1;
uniform int outputSssId = 1;
void closure_load_ssr_data(
vec3 ssr_spec, float roughness, vec3 N, vec3 viewVec, int ssr_id, inout Closure cl)
{
/* Still encode to avoid artifacts in the SSR pass. */
vec3 vN = normalize(mat3(ViewMatrix) * N);
cl.ssr_normal = normal_encode(vN, viewVec);
if (ssr_id == outputSsrId) {
cl.ssr_data = vec4(ssr_spec, roughness);
cl.flag |= CLOSURE_SSR_FLAG;
}
}
void closure_load_sss_data(
float radius, vec3 sss_irradiance, vec3 sss_albedo, int sss_id, inout Closure cl)
{
# ifdef USE_SSS
if (sss_id == outputSssId) {
cl.sss_irradiance = sss_irradiance;
cl.sss_radius = radius;
cl.sss_albedo = sss_albedo;
cl.flag |= CLOSURE_SSS_FLAG;
cl.radiance += render_pass_diffuse_mask(sss_albedo, vec3(0));
}
else
# endif
{
cl.radiance += render_pass_diffuse_mask(sss_albedo, sss_irradiance * sss_albedo);
}
}
Closure closure_mix(Closure cl1, Closure cl2, float fac)
{
Closure cl;
cl.holdout = mix(cl1.holdout, cl2.holdout, fac);
if (FLAG_TEST(cl1.flag, CLOSURE_HOLDOUT_FLAG)) {
fac = 1.0;
}
else if (FLAG_TEST(cl2.flag, CLOSURE_HOLDOUT_FLAG)) {
fac = 0.0;
}
cl.transmittance = mix(cl1.transmittance, cl2.transmittance, fac);
cl.radiance = mix(cl1.radiance, cl2.radiance, fac);
cl.flag = cl1.flag | cl2.flag;
cl.ssr_data = mix(cl1.ssr_data, cl2.ssr_data, fac);
bool use_cl1_ssr = FLAG_TEST(cl1.flag, CLOSURE_SSR_FLAG);
/* When mixing SSR don't blend roughness and normals but only specular (ssr_data.xyz).*/
cl.ssr_data.w = (use_cl1_ssr) ? cl1.ssr_data.w : cl2.ssr_data.w;
cl.ssr_normal = (use_cl1_ssr) ? cl1.ssr_normal : cl2.ssr_normal;
# ifdef USE_SSS
cl.sss_albedo = mix(cl1.sss_albedo, cl2.sss_albedo, fac);
bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
/* It also does not make sense to mix SSS radius or irradiance. */
cl.sss_radius = (use_cl1_sss) ? cl1.sss_radius : cl2.sss_radius;
cl.sss_irradiance = (use_cl1_sss) ? cl1.sss_irradiance : cl2.sss_irradiance;
# endif
return cl;
}
Closure closure_add(Closure cl1, Closure cl2)
{
Closure cl;
cl.transmittance = cl1.transmittance + cl2.transmittance;
cl.radiance = cl1.radiance + cl2.radiance;
cl.holdout = cl1.holdout + cl2.holdout;
cl.flag = cl1.flag | cl2.flag;
cl.ssr_data = cl1.ssr_data + cl2.ssr_data;
bool use_cl1_ssr = FLAG_TEST(cl1.flag, CLOSURE_SSR_FLAG);
/* When mixing SSR don't blend roughness and normals.*/
cl.ssr_data.w = (use_cl1_ssr) ? cl1.ssr_data.w : cl2.ssr_data.w;
cl.ssr_normal = (use_cl1_ssr) ? cl1.ssr_normal : cl2.ssr_normal;
# ifdef USE_SSS
cl.sss_albedo = cl1.sss_albedo + cl2.sss_albedo;
bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
/* It also does not make sense to mix SSS radius or irradiance. */
cl.sss_radius = (use_cl1_sss) ? cl1.sss_radius : cl2.sss_radius;
cl.sss_irradiance = (use_cl1_sss) ? cl1.sss_irradiance : cl2.sss_irradiance;
# endif
return cl;
}
Closure closure_emission(vec3 rgb)
{
Closure cl = CLOSURE_DEFAULT;
cl.radiance = rgb;
return cl;
}
/* Breaking this across multiple lines causes issues for some older GLSL compilers. */
/* clang-format off */
# if defined(MESH_SHADER) && !defined(DEPTH_SHADER)
/* clang-format on */
# ifndef USE_ALPHA_BLEND
layout(location = 0) out vec4 outRadiance;
layout(location = 1) out vec2 ssrNormals;
layout(location = 2) out vec4 ssrData;
# ifdef USE_SSS
layout(location = 3) out vec3 sssIrradiance;
layout(location = 4) out float sssRadius;
layout(location = 5) out vec3 sssAlbedo;
# endif
# else /* USE_ALPHA_BLEND */
/* Use dual source blending to be able to make a whole range of effects. */
layout(location = 0, index = 0) out vec4 outRadiance;
layout(location = 0, index = 1) out vec4 outTransmittance;
# endif /* USE_ALPHA_BLEND */
# if defined(USE_ALPHA_BLEND)
/* Prototype because this file is included before volumetric_lib.glsl */
void volumetric_resolve(vec2 frag_uvs,
float frag_depth,
out vec3 transmittance,
out vec3 scattering);
# endif
# define NODETREE_EXEC
void main()
{
Closure cl = nodetree_exec();
float holdout = saturate(1.0 - cl.holdout);
float transmit = saturate(avg(cl.transmittance));
float alpha = 1.0 - transmit;
# ifdef USE_ALPHA_BLEND
vec2 uvs = gl_FragCoord.xy * volCoordScale.zw;
vec3 vol_transmit, vol_scatter;
volumetric_resolve(uvs, gl_FragCoord.z, vol_transmit, vol_scatter);
/* Removes part of the volume scattering that have
* already been added to the destination pixels.
* Since we do that using the blending pipeline we need to account for material transmittance. */
vol_scatter -= vol_scatter * cl.transmittance;
cl.radiance = cl.radiance * holdout * vol_transmit + vol_scatter;
outRadiance = vec4(cl.radiance, alpha * holdout);
outTransmittance = vec4(cl.transmittance, transmit) * holdout;
# else
outRadiance = vec4(cl.radiance, holdout);
ssrNormals = cl.ssr_normal;
ssrData = cl.ssr_data;
# ifdef USE_SSS
sssIrradiance = cl.sss_irradiance;
sssRadius = cl.sss_radius;
sssAlbedo = cl.sss_albedo;
# endif
# endif
/* For Probe capture */
# ifdef USE_SSS
float fac = float(!sssToggle);
/* TODO(fclem) we shouldn't need this.
* Just disable USE_SSS when USE_REFRACTION is enabled. */
# ifdef USE_REFRACTION
/* SSRefraction pass is done after the SSS pass.
* In order to not loose the diffuse light totally we
* need to merge the SSS radiance to the main radiance. */
fac = 1.0;
# endif
outRadiance.rgb += cl.sss_irradiance.rgb * cl.sss_albedo.rgb * fac;
# endif
# ifdef LOOKDEV
gl_FragDepth = 0.0;
# endif
# ifndef USE_ALPHA_BLEND
float alpha_div = 1.0 / max(1e-8, alpha);
outRadiance.rgb *= alpha_div;
ssrData.rgb *= alpha_div;
# ifdef USE_SSS
sssAlbedo.rgb *= alpha_div;
# endif
# endif
}
# endif /* MESH_SHADER */
#endif /* VOLUMETRICS */

View File

@ -1,3 +1,4 @@
#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl)
out vec4 FragColor;
@ -5,8 +6,8 @@ void main()
{
vec3 N, T, B, V;
float NV = (1.0 - (clamp(gl_FragCoord.y / BRDF_LUT_SIZE, 1e-4, 0.9999)));
float sqrtRoughness = clamp(gl_FragCoord.x / BRDF_LUT_SIZE, 1e-4, 0.9999);
float NV = (1.0 - (clamp(gl_FragCoord.y / b, 1e-4, 0.9999)));
float sqrtRoughness = clamp(gl_FragCoord.x / LUT_SIZE, 1e-4, 0.9999);
float a = sqrtRoughness * sqrtRoughness;
float a2 = a * a;

View File

@ -1,6 +1,7 @@
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
uniform sampler1D texHammersley;
uniform sampler2D texJitter;
uniform float sampleCount;
uniform float invSampleCount;
@ -8,8 +9,7 @@ vec2 jitternoise = vec2(0.0);
#ifndef UTIL_TEX
# define UTIL_TEX
uniform sampler2DArray utilTex;
# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
void setup_noise(void)
@ -17,6 +17,11 @@ void setup_noise(void)
jitternoise = texelfetch_noise_tex(gl_FragCoord.xy).rg; /* Global variable */
}
vec3 tangent_to_world(vec3 vector, vec3 N, vec3 T, vec3 B)
{
return T * vector.x + B * vector.y + N * vector.z;
}
#ifdef HAMMERSLEY_SIZE
vec3 hammersley_3d(float i, float invsamplenbr)
{

View File

@ -1,3 +1,4 @@
#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl)
uniform float a2;
@ -7,8 +8,8 @@ void main()
{
vec3 N, T, B, V;
float x = gl_FragCoord.x / BRDF_LUT_SIZE;
float y = gl_FragCoord.y / BRDF_LUT_SIZE;
float x = gl_FragCoord.x / LUT_SIZE;
float y = gl_FragCoord.y / LUT_SIZE;
/* There is little variation if ior > 1.0 so we
* maximize LUT precision for ior < 1.0 */
x = x * 1.1;

View File

@ -0,0 +1,181 @@
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
#ifndef VOLUMETRICS
uniform int outputSsrId = 1;
uniform int outputSssId = 1;
#endif
struct Closure {
#ifdef VOLUMETRICS
vec3 absorption;
vec3 scatter;
vec3 emission;
float anisotropy;
#else /* SURFACE */
vec3 radiance;
vec3 transmittance;
float holdout;
vec4 ssr_data;
vec2 ssr_normal;
int flag;
# ifdef USE_SSS
vec3 sss_irradiance;
vec3 sss_albedo;
float sss_radius;
# endif
#endif
};
/* Prototype */
Closure nodetree_exec(void);
/* clang-format off */
/* Avoid multiline defines. */
#ifdef VOLUMETRICS
# define CLOSURE_DEFAULT Closure(vec3(0), vec3(0), vec3(0), 0.0)
#elif !defined(USE_SSS)
# define CLOSURE_DEFAULT Closure(vec3(0), vec3(0), 0.0, vec4(0), vec2(0), 0)
#else
# define CLOSURE_DEFAULT Closure(vec3(0), vec3(0), 0.0, vec4(0), vec2(0), 0, vec3(0), vec3(0), 0.0)
#endif
/* clang-format on */
#define FLAG_TEST(flag, val) (((flag) & (val)) != 0)
#define CLOSURE_SSR_FLAG 1
#define CLOSURE_SSS_FLAG 2
#define CLOSURE_HOLDOUT_FLAG 4
#ifdef VOLUMETRICS
Closure closure_mix(Closure cl1, Closure cl2, float fac)
{
Closure cl;
cl.absorption = mix(cl1.absorption, cl2.absorption, fac);
cl.scatter = mix(cl1.scatter, cl2.scatter, fac);
cl.emission = mix(cl1.emission, cl2.emission, fac);
cl.anisotropy = mix(cl1.anisotropy, cl2.anisotropy, fac);
return cl;
}
Closure closure_add(Closure cl1, Closure cl2)
{
Closure cl;
cl.absorption = cl1.absorption + cl2.absorption;
cl.scatter = cl1.scatter + cl2.scatter;
cl.emission = cl1.emission + cl2.emission;
cl.anisotropy = (cl1.anisotropy + cl2.anisotropy) / 2.0; /* Average phase (no multi lobe) */
return cl;
}
Closure closure_emission(vec3 rgb)
{
Closure cl = CLOSURE_DEFAULT;
cl.emission = rgb;
return cl;
}
#else /* SURFACE */
Closure closure_mix(Closure cl1, Closure cl2, float fac)
{
Closure cl;
cl.holdout = mix(cl1.holdout, cl2.holdout, fac);
if (FLAG_TEST(cl1.flag, CLOSURE_HOLDOUT_FLAG)) {
fac = 1.0;
}
else if (FLAG_TEST(cl2.flag, CLOSURE_HOLDOUT_FLAG)) {
fac = 0.0;
}
cl.transmittance = mix(cl1.transmittance, cl2.transmittance, fac);
cl.radiance = mix(cl1.radiance, cl2.radiance, fac);
cl.flag = cl1.flag | cl2.flag;
cl.ssr_data = mix(cl1.ssr_data, cl2.ssr_data, fac);
bool use_cl1_ssr = FLAG_TEST(cl1.flag, CLOSURE_SSR_FLAG);
/* When mixing SSR don't blend roughness and normals but only specular (ssr_data.xyz).*/
cl.ssr_data.w = (use_cl1_ssr) ? cl1.ssr_data.w : cl2.ssr_data.w;
cl.ssr_normal = (use_cl1_ssr) ? cl1.ssr_normal : cl2.ssr_normal;
# ifdef USE_SSS
cl.sss_albedo = mix(cl1.sss_albedo, cl2.sss_albedo, fac);
bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
/* It also does not make sense to mix SSS radius or irradiance. */
cl.sss_radius = (use_cl1_sss) ? cl1.sss_radius : cl2.sss_radius;
cl.sss_irradiance = (use_cl1_sss) ? cl1.sss_irradiance : cl2.sss_irradiance;
# endif
return cl;
}
Closure closure_add(Closure cl1, Closure cl2)
{
Closure cl;
cl.transmittance = cl1.transmittance + cl2.transmittance;
cl.radiance = cl1.radiance + cl2.radiance;
cl.holdout = cl1.holdout + cl2.holdout;
cl.flag = cl1.flag | cl2.flag;
cl.ssr_data = cl1.ssr_data + cl2.ssr_data;
bool use_cl1_ssr = FLAG_TEST(cl1.flag, CLOSURE_SSR_FLAG);
/* When mixing SSR don't blend roughness and normals.*/
cl.ssr_data.w = (use_cl1_ssr) ? cl1.ssr_data.w : cl2.ssr_data.w;
cl.ssr_normal = (use_cl1_ssr) ? cl1.ssr_normal : cl2.ssr_normal;
# ifdef USE_SSS
cl.sss_albedo = cl1.sss_albedo + cl2.sss_albedo;
bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
/* It also does not make sense to mix SSS radius or irradiance. */
cl.sss_radius = (use_cl1_sss) ? cl1.sss_radius : cl2.sss_radius;
cl.sss_irradiance = (use_cl1_sss) ? cl1.sss_irradiance : cl2.sss_irradiance;
# endif
return cl;
}
Closure closure_emission(vec3 rgb)
{
Closure cl = CLOSURE_DEFAULT;
cl.radiance = rgb;
return cl;
}
#endif
#ifndef VOLUMETRICS
void closure_load_ssr_data(
vec3 ssr_spec, float roughness, vec3 N, vec3 viewVec, int ssr_id, inout Closure cl)
{
/* Still encode to avoid artifacts in the SSR pass. */
vec3 vN = normalize(mat3(ViewMatrix) * N);
cl.ssr_normal = normal_encode(vN, viewVec);
if (ssr_id == outputSsrId) {
cl.ssr_data = vec4(ssr_spec, roughness);
cl.flag |= CLOSURE_SSR_FLAG;
}
}
void closure_load_sss_data(
float radius, vec3 sss_irradiance, vec3 sss_albedo, int sss_id, inout Closure cl)
{
# ifdef USE_SSS
if (sss_id == outputSssId) {
cl.sss_irradiance = sss_irradiance;
cl.sss_radius = radius;
cl.sss_albedo = sss_albedo;
cl.flag |= CLOSURE_SSS_FLAG;
cl.radiance += render_pass_diffuse_mask(sss_albedo, vec3(0));
}
else
# endif
{
cl.radiance += render_pass_diffuse_mask(sss_albedo, sss_irradiance * sss_albedo);
}
}
#endif

View File

@ -1,32 +1,8 @@
#ifndef LIT_SURFACE_UNIFORM
# define LIT_SURFACE_UNIFORM
uniform float refractionDepth;
# ifndef UTIL_TEX
# define UTIL_TEX
uniform sampler2DArray utilTex;
# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
# endif /* UTIL_TEX */
in vec3 worldPosition;
in vec3 viewPosition;
in vec3 worldNormal;
in vec3 viewNormal;
# ifdef HAIR_SHADER
in vec3 hairTangent; /* world space */
in float hairThickTime;
in float hairThickness;
in float hairTime;
flat in int hairStrandID;
uniform int hairThicknessRes = 1;
# endif
#endif /* LIT_SURFACE_UNIFORM */
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl)
#pragma BLENDER_REQUIRE(ssr_lib.glsl)
/**
* AUTO CONFIG
@ -209,7 +185,7 @@ void CLOSURE_NAME(vec3 N
vec3 V = cameraVec;
vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
/* ---------------------------------------------------------------- */
/* -------------------- SCENE LIGHTS LIGHTING --------------------- */
@ -328,11 +304,11 @@ void CLOSURE_NAME(vec3 N
# endif
# ifdef CLOSURE_GLOSSY
vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
vec3 spec_dir = specular_dominant_dir(N, V, roughnessSquared);
# endif
# ifdef CLOSURE_CLEARCOAT
vec3 C_spec_dir = get_specular_reflection_dominant_dir(C_N, V, C_roughnessSquared);
vec3 C_spec_dir = specular_dominant_dir(C_N, V, C_roughnessSquared);
# endif
# ifdef CLOSURE_REFRACTION
@ -345,7 +321,7 @@ void CLOSURE_NAME(vec3 N
line_plane_intersect(
worldPosition, refr_V, worldPosition - N * refractionDepth, N) :
worldPosition;
vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior);
vec3 refr_dir = refraction_dominant_dir(N, refr_V, roughness, final_ior);
# endif
# ifdef CLOSURE_REFRACTION
@ -485,7 +461,7 @@ void CLOSURE_NAME(vec3 N
# endif
# ifdef CLOSURE_REFRACTION
float btdf = get_btdf_lut(utilTex, NV, roughness, ior);
float btdf = get_btdf_lut(NV, roughness, ior);
out_refr += refr_accum.rgb * btdf;
# endif

View File

@ -2,7 +2,6 @@
layout(std140) uniform common_block
{
mat4 pastViewProjectionMatrix;
vec4 viewVecs[2];
vec2 mipRatio[10]; /* To correct mip level texel misalignment */
/* Ambient Occlusion */
vec4 aoParameters[2];
@ -70,3 +69,9 @@ layout(std140) uniform common_block
#define ssrQuality ssrParameters.x
#define ssrThickness ssrParameters.y
#define ssrPixelSize ssrParameters.zw
vec2 mip_ratio_interp(float mip)
{
float low_mip = floor(mip);
return mix(mipRatio[int(low_mip)], mipRatio[int(low_mip + 1.0)], mip - low_mip);
}

View File

@ -0,0 +1,65 @@
#pragma BLENDER_REQUIRE(bsdf_common_lib.glsl)
/* ---------------------------------------------------------------------- */
/** \name Utiltex
*
* Utiltex is a sampler2DArray that stores a number of useful small utilitary textures and lookup
* tables.
* \{ */
uniform sampler2DArray utilTex;
#define LUT_SIZE 64
#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
/* Return texture coordinates to sample Surface LUT */
vec2 lut_coords(float cosTheta, float roughness)
{
float theta = acos(cosTheta);
vec2 coords = vec2(roughness, theta / M_PI_2);
/* scale and bias coordinates, for correct filtered lookup */
return coords * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE;
}
vec2 lut_coords_ltc(float cosTheta, float roughness)
{
vec2 coords = vec2(roughness, sqrt(1.0 - cosTheta));
/* scale and bias coordinates, for correct filtered lookup */
return coords * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE;
}
float get_btdf_lut(float NV, float roughness, float ior)
{
const vec3 lut_scale_bias_texel_size = vec3((LUT_SIZE - 1.0), 0.5, 1.5) / LUT_SIZE;
vec3 coords;
/* Try to compensate for the low resolution and interpolation error. */
coords.x = (ior > 1.0) ? (0.9 + lut_scale_bias_texel_size.z) +
(0.1 - lut_scale_bias_texel_size.z) * f0_from_ior(ior) :
(0.9 + lut_scale_bias_texel_size.z) * ior * ior;
coords.y = 1.0 - saturate(NV);
coords.xy *= lut_scale_bias_texel_size.x;
coords.xy += lut_scale_bias_texel_size.y;
const float lut_lvl_ofs = 4.0; /* First texture lvl of roughness. */
const float lut_lvl_scale = 16.0; /* How many lvl of roughness in the lut. */
float mip = roughness * lut_lvl_scale;
float mip_floor = floor(mip);
coords.z = lut_lvl_ofs + mip_floor + 1.0;
float btdf_high = textureLod(utilTex, coords, 0.0).r;
coords.z -= 1.0;
float btdf_low = textureLod(utilTex, coords, 0.0).r;
float btdf = (ior == 1.0) ? 1.0 : mix(btdf_low, btdf_high, mip - coords.z);
return btdf;
}
/** \} */

View File

@ -1,51 +0,0 @@
uniform vec3 basecol;
uniform float metallic;
uniform float specular;
uniform float roughness;
Closure nodetree_exec(void)
{
#ifdef HAIR_SHADER
vec3 B = normalize(cross(worldNormal, hairTangent));
float cos_theta;
if (hairThicknessRes == 1) {
vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
/* Random cosine normal distribution on the hair surface. */
cos_theta = rand.x * 2.0 - 1.0;
}
else {
/* Shade as a cylinder. */
cos_theta = hairThickTime / hairThickness;
}
float sin_theta = sqrt(max(0.0, 1.0f - cos_theta * cos_theta));
vec3 N = normalize(worldNormal * sin_theta + B * cos_theta);
vec3 vN = mat3(ViewMatrix) * N;
#else
vec3 N = normalize(gl_FrontFacing ? worldNormal : -worldNormal);
vec3 vN = normalize(gl_FrontFacing ? viewNormal : -viewNormal);
#endif
vec3 dielectric = vec3(0.034) * specular * 2.0;
vec3 albedo = mix(basecol, vec3(0.0), metallic);
vec3 f0 = mix(dielectric, basecol, metallic);
vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
vec3 out_diff, out_spec, ssr_spec;
eevee_closure_default(N, albedo, f0, f90, 1, roughness, 1.0, true, out_diff, out_spec, ssr_spec);
Closure cl = CLOSURE_DEFAULT;
cl.radiance = render_pass_glossy_mask(vec3(1.0), out_spec) +
render_pass_diffuse_mask(albedo, out_diff * albedo);
closure_load_ssr_data(ssr_spec, roughness, N, viewCameraVec, 1, cl);
#ifdef LOOKDEV
gl_FragDepth = 0.0;
#endif
#ifdef HOLDOUT
cl = CLOSURE_DEFAULT;
cl.holdout = 1.0;
#endif
return cl;
}

View File

@ -1,4 +1,8 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
uniform sampler2D colorBuffer;
uniform sampler2D depthBuffer;
@ -18,9 +22,6 @@ uniform vec4 bokehParams[2];
uniform vec2 nearFar; /* Near & far view depths values */
#define M_PI 3.1415926535897932384626433832795
#define M_2PI 6.2831853071795864769252868
/* -------------- Utils ------------- */
/* divide by sensor size to get the normalized size */
@ -34,11 +35,6 @@ uniform vec2 nearFar; /* Near & far view depths values */
#define weighted_sum(a, b, c, d, e) \
(a * e.x + b * e.y + c * e.z + d * e.w) / max(1e-6, dot(e, vec4(1.0)));
float max_v4(vec4 v)
{
return max(max(v.x, v.y), max(v.z, v.w));
}
vec4 safe_color(vec4 c)
{
/* Clamp to avoid black square artifacts if a pixel goes NaN. */

View File

@ -1,4 +1,6 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
uniform vec4 bokehParams[2];
#define bokeh_rotation bokehParams[0].x
@ -15,8 +17,6 @@ flat out float smoothFac;
flat out ivec2 edge;
out vec2 particlecoord;
#define M_PI 3.1415926535897932384626433832795
/* Scatter pass, calculate a triangle covering the CoC. */
void main()
{

View File

@ -1,14 +1,34 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl)
/**
* This shader only compute maximum horizon angles for each directions.
* The final integration is done at the resolve stage with the shading normal.
*/
uniform float rotationOffset;
out vec4 FragColor;
#ifdef DEBUG_AO
uniform sampler2D normalBuffer;
#ifdef LAYERED_DEPTH
uniform sampler2DArray depthBufferLayered;
uniform int layer;
# define gtao_depthBuffer depthBufferLayered
# define gtao_textureLod(a, b, c) textureLod(a, vec3(b, layer), c)
#else
uniform sampler2D depthBuffer;
# define gtao_depthBuffer depthBuffer
# define gtao_textureLod(a, b, c) textureLod(a, b, c)
#endif
uniform float rotationOffset;
#ifdef DEBUG_AO
void main()
{
@ -34,18 +54,6 @@ void main()
#else
# ifdef LAYERED_DEPTH
uniform sampler2DArray depthBufferLayered;
uniform int layer;
# define gtao_depthBuffer depthBufferLayered
# define gtao_textureLod(a, b, c) textureLod(a, vec3(b, layer), c)
# else
# define gtao_depthBuffer depthBuffer
# define gtao_textureLod(a, b, c) textureLod(a, b, c)
# endif
void main()
{
vec2 uvs = saturate(gl_FragCoord.xy / vec2(textureSize(gtao_depthBuffer, 0).xy));

View File

@ -1,5 +1,10 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
/* Convert depth to Mist factor */
uniform vec3 mistSettings;
uniform sampler2D depthBuffer;
#define mistStart mistSettings.x
#define mistInvDistance mistSettings.y

View File

@ -1,4 +1,6 @@
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
/*
* Based on:
* A Fast and Stable Feature-Aware Motion Blur Filter
@ -15,11 +17,6 @@ uniform sampler2D tileMaxBuffer;
#define KERNEL 8
/* TODO(fclem) deduplicate this code. */
uniform sampler2DArray utilTex;
#define LUT_SIZE 64
#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
uniform float depthScale;
uniform ivec2 tileBufferSize;
uniform vec2 viewportSize;

View File

@ -1,4 +1,11 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(raytrace_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(ssr_lib.glsl)
/* Based on Stochastic Screen Space Reflections
* https://www.ea.com/frostbite/news/stochastic-screen-space-reflections */
@ -131,7 +138,7 @@ void main()
return;
}
vec4 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0);
vec4 rand = texelfetch_noise_tex(halfres_texel);
/* Gives *perfect* reflection for very small roughness */
if (roughness < 0.04) {

View File

@ -1,4 +1,9 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl)
/* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */
#define MAX_SSS_SAMPLES 65
@ -14,36 +19,16 @@ uniform sampler2D sssIrradiance;
uniform sampler2D sssRadius;
uniform sampler2D sssAlbedo;
#ifndef UTIL_TEX
# define UTIL_TEX
uniform sampler2DArray utilTex;
# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
layout(location = 0) out vec4 sssRadiance;
float get_view_z_from_depth(float depth)
{
if (ProjectionMatrix[3][3] == 0.0) {
float d = 2.0 * depth - 1.0;
return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
}
else {
return viewVecs[0].z + depth * viewVecs[1].z;
}
}
#define LUT_SIZE 64
#define M_PI_2 1.5707963267948966 /* pi/2 */
#define M_2PI 6.2831853071795865 /* 2*pi */
void main(void)
{
vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO precompute */
vec2 uvs = gl_FragCoord.xy * pixel_size;
vec3 sss_irradiance = texture(sssIrradiance, uvs).rgb;
float sss_radius = texture(sssRadius, uvs).r;
float depth_view = get_view_z_from_depth(texture(depthBuffer, uvs).r);
float depth = texture(depthBuffer, uvs).r;
float depth_view = get_view_z_from_depth(depth);
float rand = texelfetch_noise_tex(gl_FragCoord.xy).r;
#ifdef FIRST_PASS

View File

@ -1,5 +1,11 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
uniform sampler2D colorBuffer;
uniform sampler2D depthBuffer;
uniform sampler2D colorHistoryBuffer;
uniform mat4 prevViewProjectionMatrix;
out vec4 FragColor;

View File

@ -1,11 +1,16 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(lights_lib.glsl)
in vec4 uvcoordsvar;
out vec4 FragColor;
uniform sampler2D depthBuffer;
uniform sampler1D sssTexProfile;
uniform sampler2D sssRadius;
uniform sampler2DArray sssShadowCubes;
uniform sampler2DArray sssShadowCascades;
@ -27,12 +32,6 @@ vec3 sss_profile(float s)
return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb;
}
#ifndef UTIL_TEX
# define UTIL_TEX
uniform sampler2DArray utilTex;
# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
float light_translucent_power_with_falloff(LightData ld, vec3 N, vec4 l_vector)
{
float power, falloff;

View File

@ -1,4 +1,8 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
uniform sampler2D depthBuffer;
uniform mat4 prevViewProjMatrix;
uniform mat4 currViewProjMatrixInv;
uniform mat4 nextViewProjMatrix;

View File

@ -1,18 +1,71 @@
uniform sampler2DArray irradianceGrid;
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl)
#pragma BLENDER_REQUIRE(octahedron_lib.glsl)
#define IRRADIANCE_LIB
/* ---------------------------------------------------------------------- */
/** \name Structure
* \{ */
#if defined(IRRADIANCE_SH_L2)
struct IrradianceData {
vec3 shcoefs[9];
};
#else /* defined(IRRADIANCE_HL2) */
struct IrradianceData {
vec3 cubesides[3];
};
#endif
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Resources
* \{ */
uniform sampler2DArray irradianceGrid;
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Functions
* \{ */
vec4 irradiance_encode(vec3 rgb)
{
float maxRGB = max_v3(rgb);
float fexp = ceil(log2(maxRGB));
return vec4(rgb / exp2(fexp), (fexp + 128.0) / 255.0);
}
vec3 irradiance_decode(vec4 data)
{
float fexp = data.a * 255.0 - 128.0;
return data.rgb * exp2(fexp);
}
vec4 visibility_encode(vec2 accum, float range)
{
accum /= range;
vec4 data;
data.x = fract(accum.x);
data.y = floor(accum.x) / 255.0;
data.z = fract(accum.y);
data.w = floor(accum.y) / 255.0;
return data;
}
vec2 visibility_decode(vec4 data, float range)
{
return (data.xz + data.yw * 255.0) * range;
}
IrradianceData load_irradiance_cell(int cell, vec3 N)
{
/* Keep in sync with diffuse_filter_probe() */
@ -155,3 +208,5 @@ vec3 irradiance_from_cell_get(int cell, vec3 ir_dir)
IrradianceData ir_data = load_irradiance_cell(cell, ir_dir);
return compute_irradiance(ir_dir, ir_data);
}
/** \} */

View File

@ -1,4 +1,7 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(cubemap_lib.glsl)
flat in int pid;
in vec2 quadCoord;

View File

@ -1,4 +1,6 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
/* XXX TODO fix code duplication */
struct CubeData {
vec4 position_type;

View File

@ -1,4 +1,8 @@
#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(irradiance_lib.glsl)
uniform samplerCube probeHdr;
uniform int probeSize;
uniform float lodFactor;

View File

@ -1,4 +1,7 @@
#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
uniform samplerCube probeHdr;
uniform float roughnessSquared;
uniform float texelSize;

View File

@ -1,4 +1,8 @@
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl)
#pragma BLENDER_REQUIRE(irradiance_lib.glsl)
uniform samplerCube probeDepth;
uniform int outputSize;
uniform float lodFactor;

View File

@ -40,9 +40,6 @@ void main()
for (int v = 0; v < 3; v++) {
gl_Position = vPos[v];
worldPosition = x_axis[fFace] * vPos[v].x + y_axis[fFace] * vPos[v].y + maj_axes[fFace];
#ifdef USE_ATTR
pass_attr(v);
#endif
EmitVertex();
}

View File

@ -1,4 +1,6 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
uniform float sphere_size;
uniform int offset;
uniform ivec3 grid_resolution;

View File

@ -1,3 +1,12 @@
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl)
#pragma BLENDER_REQUIRE(cubemap_lib.glsl)
#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl)
#pragma BLENDER_REQUIRE(irradiance_lib.glsl)
/* ----------- Uniforms --------- */
uniform sampler2DArray probePlanars;
@ -73,12 +82,6 @@ struct GridData {
# define MAX_PLANAR 1
#endif
#ifndef UTIL_TEX
# define UTIL_TEX
uniform sampler2DArray utilTex;
# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
layout(std140) uniform probe_block
{
CubeData probes_data[MAX_PROBE];
@ -218,7 +221,7 @@ void fallback_cubemap(vec3 N,
inout vec4 spec_accum)
{
/* Specular probes */
vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
vec3 spec_dir = specular_dominant_dir(N, V, roughnessSquared);
#ifdef SSR_AO
vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
@ -246,7 +249,6 @@ void fallback_cubemap(vec3 N,
}
}
#ifdef IRRADIANCE_LIB
vec3 probe_evaluate_grid(GridData gd, vec3 W, vec3 N, vec3 localpos)
{
localpos = localpos * 0.5 + 0.5;
@ -308,5 +310,3 @@ vec3 probe_evaluate_world_diff(vec3 N)
{
return irradiance_from_cell_get(0, N);
}
#endif /* IRRADIANCE_LIB */

View File

@ -1,4 +1,6 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
uniform sampler2DArray probePlanars;
in vec3 worldPosition;

View File

@ -1,4 +1,6 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
in vec3 pos;
in int probe_id;

View File

@ -1,8 +1,76 @@
uniform sampler2DArrayShadow shadowCubeTexture;
uniform sampler2DArrayShadow shadowCascadeTexture;
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(raytrace_lib.glsl)
#pragma BLENDER_REQUIRE(ltc_lib.glsl)
#define LAMPS_LIB
#ifndef MAX_CASCADE_NUM
# define MAX_CASCADE_NUM 4
#endif
/* ---------------------------------------------------------------------- */
/** \name Structure
* \{ */
struct LightData {
vec4 position_influence; /* w : InfluenceRadius (inversed and squared) */
vec4 color_spec; /* w : Spec Intensity */
vec4 spotdata_radius_shadow; /* x : spot size, y : spot blend, z : radius, w: shadow id */
vec4 rightvec_sizex; /* xyz: Normalized up vector, w: area size X or spot scale X */
vec4 upvec_sizey; /* xyz: Normalized right vector, w: area size Y or spot scale Y */
vec4 forwardvec_type; /* xyz: Normalized forward vector, w: Light Type */
};
/* convenience aliases */
#define l_color color_spec.rgb
#define l_spec color_spec.a
#define l_position position_influence.xyz
#define l_influence position_influence.w
#define l_sizex rightvec_sizex.w
#define l_sizey upvec_sizey.w
#define l_right rightvec_sizex.xyz
#define l_up upvec_sizey.xyz
#define l_forward forwardvec_type.xyz
#define l_type forwardvec_type.w
#define l_spot_size spotdata_radius_shadow.x
#define l_spot_blend spotdata_radius_shadow.y
#define l_radius spotdata_radius_shadow.z
#define l_shadowid spotdata_radius_shadow.w
struct ShadowData {
vec4 near_far_bias_id;
vec4 contact_shadow_data;
};
struct ShadowCubeData {
mat4 shadowmat;
vec4 position;
};
struct ShadowCascadeData {
mat4 shadowmat[MAX_CASCADE_NUM];
vec4 split_start_distances;
vec4 split_end_distances;
vec4 shadow_vec_id;
};
/* convenience aliases */
#define sh_near near_far_bias_id.x
#define sh_far near_far_bias_id.y
#define sh_bias near_far_bias_id.z
#define sh_data_index near_far_bias_id.w
#define sh_contact_dist contact_shadow_data.x
#define sh_contact_offset contact_shadow_data.y
#define sh_contact_spread contact_shadow_data.z
#define sh_contact_thickness contact_shadow_data.w
#define sh_shadow_vec shadow_vec_id.xyz
#define sh_tex_index shadow_vec_id.w
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Resources
* \{ */
layout(std140) uniform shadow_block
{
@ -16,6 +84,15 @@ layout(std140) uniform light_block
LightData lights_data[MAX_LIGHT];
};
uniform sampler2DArrayShadow shadowCubeTexture;
uniform sampler2DArrayShadow shadowCascadeTexture;
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Shadow Functions
* \{ */
/* type */
#define POINT 0.0
#define SUN 1.0
@ -133,9 +210,11 @@ float sample_cascade_shadow(int shadow_id, vec3 W)
#undef scube
#undef scsmd
/* ----------------------------------------------------------- */
/* --------------------- Light Functions --------------------- */
/* ----------------------------------------------------------- */
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Light Functions
* \{ */
/* From Frostbite PBR Course
* Distance based attenuation
@ -258,7 +337,6 @@ float light_visibility(LightData ld,
l_atten);
}
#ifdef USE_LTC
float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector)
{
if (ld.l_type == AREA_RECT) {
@ -321,4 +399,5 @@ float light_specular(LightData ld, vec4 ltc_mat, vec3 N, vec3 V, vec4 l_vector)
return ltc_evaluate_disk(N, V, ltc_matrix(ltc_mat), points);
}
}
#endif
/** \} */

View File

@ -1,20 +1,17 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
uniform sampler2D studioLight;
uniform float backgroundAlpha;
uniform vec3 color;
out vec4 FragColor;
#if defined(LOOKDEV_BG) || defined(LOOKDEV)
uniform mat3 StudioLightMatrix;
uniform sampler2D image;
uniform float studioLightIntensity = 1.0;
uniform float studioLightBlur = 0.0;
in vec3 viewPosition;
# ifndef M_PI
# define M_PI 3.14159265358979323846
# endif
out vec4 FragColor;
vec3 background_transform_to_world(vec3 viewvec)
{
@ -35,36 +32,20 @@ vec4 node_tex_environment_equirectangular(vec3 co, sampler2D ima)
vec3 nco = normalize(co);
float u = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5;
float v = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5;
/* Fix pole bleeding */
float width = float(textureSize(ima, 0).x);
float texel_width = 1.0 / width;
v = clamp(v, texel_width, 1.0 - texel_width);
/* Fix u = 0 seam */
/* This is caused by texture filtering, since uv don't have smooth derivatives
* at u = 0 or 2PI, hardware filtering is using the smallest mipmap for certain
* texels. So we force the highest mipmap and don't do anisotropic filtering. */
return textureLod(ima, vec2(u, v), 0.0);
}
#endif
void main()
{
vec3 worldvec = background_transform_to_world(viewPosition);
vec3 background_color;
#if defined(LOOKDEV_BG)
vec3 worldvec = background_transform_to_world(viewPosition);
background_color = probe_evaluate_world_spec(worldvec, studioLightBlur).rgb;
background_color *= studioLightIntensity;
#elif defined(LOOKDEV)
vec3 worldvec = background_transform_to_world(viewPosition);
background_color = node_tex_environment_equirectangular(StudioLightMatrix * worldvec, image).rgb;
background_color *= studioLightIntensity;
#else
background_color = color;
worldvec = StudioLightMatrix * worldvec;
background_color = node_tex_environment_equirectangular(worldvec, studioLight).rgb;
background_color *= studioLightIntensity;
#endif
FragColor = vec4(clamp(background_color, vec3(0.0), vec3(1e10)), 1.0) * backgroundAlpha;

View File

@ -8,12 +8,6 @@
#define USE_LTC
#ifndef UTIL_TEX
# define UTIL_TEX
uniform sampler2DArray utilTex;
# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
/* Diffuse *clipped* sphere integral. */
float diffuse_sphere_integral(float avg_dir_z, float form_factor)
{

View File

@ -1,4 +1,7 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
uniform mat4 currModelMatrix;
uniform mat4 prevModelMatrix;
uniform mat4 nextModelMatrix;
@ -19,6 +22,8 @@ out vec3 nextWorldPos;
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
#ifdef HAIR
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
float time, thick_time, thickness;

View File

@ -1,4 +1,14 @@
/* Required by some nodes. */
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl)
#pragma BLENDER_REQUIRE(closure_lib.glsl)
#pragma BLENDER_REQUIRE(closure_lit_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
#ifdef USE_ALPHA_HASH
/* From the paper "Hashed Alpha Testing" by Chris Wyman and Morgan McGuire */
@ -56,8 +66,6 @@ float hashed_alpha_threshold(vec3 co)
#endif
#define NODETREE_EXEC
void main()
{
#if defined(USE_ALPHA_HASH)
@ -66,11 +74,9 @@ void main()
float opacity = saturate(1.0 - avg(cl.transmittance));
# if defined(USE_ALPHA_HASH)
/* Hashed Alpha Testing */
if (opacity < hashed_alpha_threshold(worldPosition)) {
discard;
}
# endif
#endif
}

View File

@ -1,16 +1,14 @@
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#ifndef HAIR_SHADER
in vec3 pos;
#endif
void main()
{
#ifdef GPU_INTEL
/* Due to some shader compiler bug, we somewhat
* need to access gl_VertexID to make it work. even
* if it's actually dead code. */
gl_Position.x = float(gl_VertexID);
#endif
GPU_INTEL_VERTEX_SHADER_WORKAROUND
#ifdef HAIR_SHADER
float time, thick_time, thickness;
@ -34,5 +32,4 @@ void main()
#ifdef CLIP_PLANES
gl_ClipDistance[0] = dot(vec4(worldPosition.xyz, 1.0), clipPlanes[0]);
#endif
/* TODO motion vectors */
}

View File

@ -1,3 +1,11 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl)
uniform sampler2D maxzBuffer;
uniform sampler2DArray planarDepth;
#define MAX_STEP 256
float sample_depth(vec2 uv, int index, float lod)

View File

@ -0,0 +1,43 @@
/* ---------------------------------------------------------------------- */
/** \name Resources
* \{ */
layout(std140) uniform renderpass_block
{
bool renderPassDiffuse;
bool renderPassDiffuseLight;
bool renderPassGlossy;
bool renderPassGlossyLight;
bool renderPassEmit;
bool renderPassSSSColor;
bool renderPassEnvironment;
};
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Functions
* \{ */
vec3 render_pass_diffuse_mask(vec3 diffuse_color, vec3 diffuse_light)
{
return renderPassDiffuse ? (renderPassDiffuseLight ? diffuse_light : diffuse_color) : vec3(0.0);
}
vec3 render_pass_sss_mask(vec3 sss_color)
{
return renderPassSSSColor ? sss_color : vec3(0.0);
}
vec3 render_pass_glossy_mask(vec3 specular_color, vec3 specular_light)
{
return renderPassGlossy ? (renderPassGlossyLight ? specular_light : specular_color) : vec3(0.0);
}
vec3 render_pass_emission_mask(vec3 emission_light)
{
return renderPassEmit ? emission_light : vec3(0.0);
}
/** \} */

View File

@ -1,3 +1,7 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#define PASS_POST_UNDEFINED 0
#define PASS_POST_ACCUMULATED_COLOR 1
#define PASS_POST_ACCUMULATED_LIGHT 2
@ -9,6 +13,8 @@
uniform int postProcessType;
uniform int currentSample;
uniform sampler2D depthBuffer;
uniform sampler2D inputBuffer;
uniform sampler2D inputSecondLightBuffer;
uniform sampler2D inputColorBuffer;

View File

@ -1,12 +1,12 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(lights_lib.glsl)
uniform sampler2D depthBuffer;
out vec4 fragColor;
#ifndef UTIL_TEX
# define UTIL_TEX
uniform sampler2DArray utilTex;
# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
void main()
{
if (laNumLight == 0) {

View File

@ -1,39 +1,23 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
in vec3 pos;
in vec3 nor;
#ifdef MESH_SHADER
out vec3 worldPosition;
out vec3 viewPosition;
out vec3 worldNormal;
out vec3 viewNormal;
#endif
#ifdef HAIR_SHADER
out vec3 hairTangent;
out float hairThickTime;
out float hairThickness;
out float hairTime;
flat out int hairStrandID;
#endif
void main()
{
#ifdef GPU_INTEL
/* Due to some shader compiler bug, we somewhat
* need to access gl_VertexID to make it work. even
* if it's actually dead code. */
gl_Position.x = float(gl_VertexID);
#endif
GPU_INTEL_VERTEX_SHADER_WORKAROUND
#ifdef HAIR_SHADER
hairStrandID = hair_get_strand_id();
vec3 world_pos, binor;
vec3 pos, binor;
hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0),
ModelMatrixInverse,
ViewMatrixInverse[3].xyz,
ViewMatrixInverse[2].xyz,
world_pos,
pos,
hairTangent,
binor,
hairTime,
@ -41,6 +25,7 @@ void main()
hairThickTime);
worldNormal = cross(hairTangent, binor);
vec3 world_pos = pos;
#else
vec3 world_pos = point_object_to_world(pos);
#endif
@ -57,7 +42,10 @@ void main()
/* No need to normalize since this is just a rotation. */
viewNormal = normal_world_to_view(worldNormal);
# ifdef USE_ATTR
pass_attr(pos);
# ifdef HAIR_SHADER
pos = hair_get_strand_pos();
# endif
pass_attr(pos, NormalMatrix, ModelMatrixInverse);
# endif
#endif
}

View File

@ -1,3 +1,10 @@
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(bsdf_common_lib.glsl)
#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl)
#pragma BLENDER_REQUIRE(raytrace_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
/* ------------ Refraction ------------ */
#define BTDF_BIAS 0.85

View File

@ -0,0 +1,89 @@
/* Required by some nodes. */
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(closure_lib.glsl)
#pragma BLENDER_REQUIRE(closure_lit_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
#pragma BLENDER_REQUIRE(volumetric_lib.glsl)
#ifdef USE_ALPHA_BLEND
/* Use dual source blending to be able to make a whole range of effects. */
layout(location = 0, index = 0) out vec4 outRadiance;
layout(location = 0, index = 1) out vec4 outTransmittance;
#else /* OPAQUE */
layout(location = 0) out vec4 outRadiance;
layout(location = 1) out vec2 ssrNormals;
layout(location = 2) out vec4 ssrData;
# ifdef USE_SSS
layout(location = 3) out vec3 sssIrradiance;
layout(location = 4) out float sssRadius;
layout(location = 5) out vec3 sssAlbedo;
# endif
#endif
void main()
{
Closure cl = nodetree_exec();
float holdout = saturate(1.0 - cl.holdout);
float transmit = saturate(avg(cl.transmittance));
float alpha = 1.0 - transmit;
#ifdef USE_ALPHA_BLEND
vec2 uvs = gl_FragCoord.xy * volCoordScale.zw;
vec3 vol_transmit, vol_scatter;
volumetric_resolve(uvs, gl_FragCoord.z, vol_transmit, vol_scatter);
/* Removes part of the volume scattering that have
* already been added to the destination pixels.
* Since we do that using the blending pipeline we need to account for material transmittance. */
vol_scatter -= vol_scatter * cl.transmittance;
cl.radiance = cl.radiance * holdout * vol_transmit + vol_scatter;
outRadiance = vec4(cl.radiance, alpha * holdout);
outTransmittance = vec4(cl.transmittance, transmit) * holdout;
#else
outRadiance = vec4(cl.radiance, holdout);
ssrNormals = cl.ssr_normal;
ssrData = cl.ssr_data;
# ifdef USE_SSS
sssIrradiance = cl.sss_irradiance;
sssRadius = cl.sss_radius;
sssAlbedo = cl.sss_albedo;
# endif
#endif
/* For Probe capture */
#ifdef USE_SSS
float fac = float(!sssToggle);
/* TODO(fclem) we shouldn't need this.
* Just disable USE_SSS when USE_REFRACTION is enabled. */
# ifdef USE_REFRACTION
/* SSRefraction pass is done after the SSS pass.
* In order to not loose the diffuse light totally we
* need to merge the SSS radiance to the main radiance. */
fac = 1.0;
# endif
outRadiance.rgb += cl.sss_irradiance.rgb * cl.sss_albedo.rgb * fac;
#endif
#ifndef USE_ALPHA_BLEND
float alpha_div = 1.0 / max(1e-8, alpha);
outRadiance.rgb *= alpha_div;
ssrData.rgb *= alpha_div;
# ifdef USE_SSS
sssAlbedo.rgb *= alpha_div;
# endif
#endif
#ifdef LOOKDEV
/* Lookdev spheres are rendered in front. */
gl_FragDepth = 0.0;
#endif
}

View File

@ -0,0 +1,46 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
RESOURCE_ID_VARYING
/* Only used to compute barycentric coordinates. */
void main()
{
#ifdef DO_BARYCENTRIC_DISTANCES
dataAttrOut.barycentricDist = calc_barycentric_distances(
dataIn[0].worldPosition, dataIn[1].worldPosition, dataIn[2].worldPosition);
#endif
PASS_RESOURCE_ID
#ifdef USE_ATTR
pass_attr(0);
#endif
PASS_SURFACE_INTERFACE(0);
gl_Position = gl_in[0].gl_Position;
gl_ClipDistance[0] = gl_in[0].gl_ClipDistance[0];
EmitVertex();
#ifdef USE_ATTR
pass_attr(1);
#endif
PASS_SURFACE_INTERFACE(1);
gl_Position = gl_in[1].gl_Position;
gl_ClipDistance[0] = gl_in[1].gl_ClipDistance[0];
EmitVertex();
#ifdef USE_ATTR
pass_attr(2);
#endif
PASS_SURFACE_INTERFACE(2);
gl_Position = gl_in[2].gl_Position;
gl_ClipDistance[0] = gl_in[2].gl_ClipDistance[0];
EmitVertex();
EndPrimitive();
}

View File

@ -0,0 +1,43 @@
/** This describe the entire interface of the shader. */
/* Samplers */
uniform sampler2D colorBuffer;
uniform sampler2D depthBuffer;
/* Uniforms */
uniform float refractionDepth;
#define SURFACE_INTERFACE \
vec3 worldPosition; \
vec3 viewPosition; \
vec3 worldNormal; \
vec3 viewNormal;
#ifdef GPU_GEOMETRY_SHADER
in ShaderStageInterface{SURFACE_INTERFACE} dataIn[];
out ShaderStageInterface{SURFACE_INTERFACE} dataOut;
# define PASS_SURFACE_INTERFACE(vert) \
dataOut.worldPosition = dataIn[vert].worldPosition; \
dataOut.viewPosition = dataIn[vert].viewPosition; \
dataOut.worldNormal = dataIn[vert].worldNormal; \
dataOut.viewNormal = dataIn[vert].viewNormal;
#else
IN_OUT ShaderStageInterface{SURFACE_INTERFACE};
#endif
#ifdef HAIR_SHADER
IN_OUT ShaderHairInterface
{
/* world space */
vec3 hairTangent;
float hairThickTime;
float hairThickness;
float hairTime;
flat int hairStrandID;
};
#endif

View File

@ -1,32 +1,20 @@
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
#ifndef HAIR_SHADER
in vec3 pos;
in vec3 nor;
#endif
#ifdef MESH_SHADER
out vec3 worldPosition;
out vec3 viewPosition;
out vec3 worldNormal;
out vec3 viewNormal;
#endif
#ifdef HAIR_SHADER
out vec3 hairTangent;
out float hairThickTime;
out float hairThickness;
out float hairTime;
flat out int hairStrandID;
#endif
RESOURCE_ID_VARYING
void main()
{
#ifdef GPU_INTEL
/* Due to some shader compiler bug, we somewhat
* need to access gl_VertexID to make it work. even
* if it's actually dead code. */
gl_Position.x = float(gl_VertexID);
#endif
GPU_INTEL_VERTEX_SHADER_WORKAROUND
PASS_RESOURCE_ID
#ifdef HAIR_SHADER
hairStrandID = hair_get_strand_id();
@ -63,7 +51,10 @@ void main()
/* No need to normalize since this is just a rotation. */
viewNormal = normal_world_to_view(worldNormal);
# ifdef USE_ATTR
pass_attr(pos);
# ifdef HAIR_SHADER
pos = hair_get_strand_pos();
# endif
pass_attr(pos, NormalMatrix, ModelMatrixInverse);
# endif
#endif
}

View File

@ -1,11 +1,11 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
uniform sampler2D blueNoise;
uniform vec3 offsets;
out vec4 FragColor;
#define M_2PI 6.28318530717958647692
void main(void)
{
vec3 blue_noise = texelFetch(blueNoise, ivec2(gl_FragCoord.xy), 0).xyz;

View File

@ -1,9 +1,10 @@
#pragma BLENDER_REQUIRE(volumetric_lib.glsl)
#pragma BLENDER_REQUIRE(closure_lib.glsl)
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
#define NODETREE_EXEC
#ifdef MESH_SHADER
uniform vec3 volumeOrcoLoc;
uniform vec3 volumeOrcoSize;

View File

@ -1,4 +1,6 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#ifdef MESH_SHADER
/* TODO tight slices */
layout(triangles) in;
@ -12,12 +14,16 @@ in vec4 vPos[];
flat out int slice;
RESOURCE_ID_VARYING
#ifdef MESH_SHADER
/* TODO tight slices */
void main()
{
gl_Layer = slice = int(vPos[0].z);
PASS_RESOURCE_ID
# ifdef USE_ATTR
pass_attr(0);
# endif
@ -48,6 +54,8 @@ void main()
{
gl_Layer = slice = int(vPos[0].z);
PASS_RESOURCE_ID
# ifdef USE_ATTR
pass_attr(0);
# endif

View File

@ -1,4 +1,6 @@
#pragma BLENDER_REQUIRE(volumetric_lib.glsl)
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
@ -11,9 +13,11 @@ uniform sampler3D volumeExtinction;
#ifdef USE_VOLUME_OPTI
uniform layout(binding = 0, r11f_g11f_b10f) writeonly restrict image3D finalScattering_img;
uniform layout(binding = 1, r11f_g11f_b10f) writeonly restrict image3D finalTransmittance_img;
vec3 finalScattering;
vec3 finalTransmittance;
#else
flat in int slice;
layout(location = 0) out vec3 finalScattering;

View File

@ -1,4 +1,8 @@
#pragma BLENDER_REQUIRE(lights_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(irradiance_lib.glsl)
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
@ -58,7 +62,6 @@ float phase_function(vec3 v, vec3 l, float g)
return (1 - sqr_g) / max(1e-8, 4.0 * M_PI * pow(1 + sqr_g - 2 * g * cos_theta, 3.0 / 2.0));
}
#ifdef LAMPS_LIB
vec3 light_volume(LightData ld, vec4 l_vector)
{
float power;
@ -95,7 +98,7 @@ vec3 light_volume(LightData ld, vec4 l_vector)
return tint * lum;
}
# define VOLUMETRIC_SHADOW_MAX_STEP 32.0
#define VOLUMETRIC_SHADOW_MAX_STEP 32.0
vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction)
{
@ -109,7 +112,7 @@ vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction)
vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D volume_extinction)
{
# if defined(VOLUME_SHADOW)
#if defined(VOLUME_SHADOW)
/* Heterogeneous volume shadows */
float dd = l_vector.w / volShadowSteps;
vec3 L = l_vector.xyz * l_vector.w;
@ -120,27 +123,24 @@ vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D v
shadow *= exp(-s_extinction * dd);
}
return shadow;
# else
#else
return vec3(1.0);
# endif /* VOLUME_SHADOW */
#endif /* VOLUME_SHADOW */
}
#endif
#ifdef IRRADIANCE_LIB
vec3 irradiance_volumetric(vec3 wpos)
{
# ifdef IRRADIANCE_HL2
#ifdef IRRADIANCE_HL2
IrradianceData ir_data = load_irradiance_cell(0, vec3(1.0));
vec3 irradiance = ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2];
ir_data = load_irradiance_cell(0, vec3(-1.0));
irradiance += ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2];
irradiance *= 0.16666666; /* 1/6 */
return irradiance;
# else
#else
return vec3(0.0);
# endif
}
#endif
}
uniform sampler3D inScattering;
uniform sampler3D inTransmittance;

View File

@ -1,4 +1,6 @@
#pragma BLENDER_REQUIRE(volumetric_lib.glsl)
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */

View File

@ -1,4 +1,6 @@
#pragma BLENDER_REQUIRE(volumetric_lib.glsl)
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */

View File

@ -1,6 +1,10 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
out vec4 vPos;
RESOURCE_ID_VARYING
void main()
{
/* Generate Triangle : less memory fetches from a VBO */
@ -25,7 +29,9 @@ void main()
vPos.z = float(t_id);
vPos.w = 1.0;
PASS_RESOURCE_ID
#ifdef USE_ATTR
pass_attr(vec3(0.0));
pass_attr(vec3(0.0), mat3(1), mat4(1));
#endif
}

View File

@ -1,4 +1,6 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
uniform sampler2D colorTex;
uniform sampler2D depthTex;
uniform sampler2D lineTex;

View File

@ -14,19 +14,6 @@ layout(depth_greater) out float gl_FragDepth;
layout(location = 0) out vec4 fragColor;
layout(location = 1) out vec4 lineOutput;
#define cameraPos ViewMatrixInverse[3].xyz
float get_depth_from_view_z(float z)
{
if (ProjectionMatrix[3][3] == 0.0) {
z = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2];
}
else {
z = z * ProjectionMatrix[2][2] / (1.0 - ProjectionMatrix[3][2]);
}
return z * 0.5 + 0.5;
}
void main()
{
const float sphere_radius = 0.05;

View File

@ -14,8 +14,6 @@ uniform float meshSize;
uniform float lineKernel = 0.0;
uniform sampler2D depthBuffer;
#define cameraPos (ViewMatrixInverse[3].xyz)
uniform int gridFlag;
#define STEPS_LEN 8

View File

@ -7,8 +7,6 @@ uniform float meshSize;
uniform int gridFlag;
#define cameraPos (ViewMatrixInverse[3].xyz)
#define PLANE_XY (1 << 4)
#define PLANE_XZ (1 << 5)
#define PLANE_YZ (1 << 6)

View File

@ -28,7 +28,7 @@ void cavity_compute(vec2 screenco,
return;
}
vec3 position = view_position_from_depth(screenco, depth, ViewVecs, ProjectionMatrix);
vec3 position = get_view_space_from_depth(screenco, depth);
vec3 normal = workbench_normal_decode(texture(normalBuffer, screenco));
vec2 jitter_co = (screenco * world_data.viewport_size.xy) * world_data.cavity_jitter_scale;
@ -68,7 +68,7 @@ void cavity_compute(vec2 screenco,
bool is_background = (s_depth == 1.0);
/* This trick provide good edge effect even if no neighbor is found. */
s_depth = (is_background) ? depth : s_depth;
vec3 s_pos = view_position_from_depth(uvcoords, s_depth, ViewVecs, ProjectionMatrix);
vec3 s_pos = get_view_space_from_depth(uvcoords, s_depth);
if (is_background) {
s_pos.z -= world_data.cavity_distance;

View File

@ -67,31 +67,3 @@ void workbench_float_pair_decode(float data, out float v1, out float v2)
v1 = float(idata & v1_mask) * (1.0 / float(v1_mask));
v2 = float(idata >> int(ROUGHNESS_BITS)) * (1.0 / float(v2_mask));
}
vec3 view_vector_from_screen_uv(vec2 uv, vec4 viewvecs[2], mat4 proj_mat)
{
if (proj_mat[3][3] == 0.0) {
return normalize(vec3(viewvecs[0].xy + uv * viewvecs[1].xy, 1.0));
}
else {
return vec3(0.0, 0.0, 1.0);
}
}
vec3 view_position_from_depth(vec2 uvcoords, float depth, vec4 viewvecs[2], mat4 proj_mat)
{
if (proj_mat[3][3] == 0.0) {
/* Perspective */
float d = 2.0 * depth - 1.0;
float zview = -proj_mat[3][2] / (d + proj_mat[2][2]);
return zview * vec3(viewvecs[0].xy + uvcoords * viewvecs[1].xy, 1.0);
}
else {
/* Orthographic */
vec3 offset = vec3(uvcoords, depth);
return viewvecs[0].xyz + offset * viewvecs[1].xyz;
}
}

View File

@ -14,7 +14,7 @@ out vec4 fragColor;
void main()
{
/* Normal and Incident vector are in viewspace. Lighting is evaluated in viewspace. */
vec3 I = view_vector_from_screen_uv(uvcoordsvar.st, ViewVecs, ProjectionMatrix);
vec3 I = get_view_vector_from_screen_uv(uvcoordsvar.st);
vec3 N = workbench_normal_decode(texture(normalBuffer, uvcoordsvar.st));
vec4 mat_data = texture(materialBuffer, uvcoordsvar.st);

View File

@ -1,3 +1,6 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
/**
* Separable Hexagonal Bokeh Blur by Colin Barré-Brisebois
* https://colinbarrebrisebois.com/2017/04/18/hexagonal-bokeh-blur-revisited-part-1-basic-3-pass-version/
@ -21,13 +24,6 @@ uniform sampler2D noiseTex;
#define dof_distance dofParams.y
#define dof_invsensorsize dofParams.z
#define M_PI 3.1415926535897932 /* pi */
float max_v4(vec4 v)
{
return max(max(v.x, v.y), max(v.z, v.w));
}
#define weighted_sum(a, b, c, d, e, e_sum) \
((a)*e.x + (b)*e.y + (c)*e.z + (d)*e.w) / max(1e-6, e_sum);

View File

@ -57,7 +57,7 @@ void main()
{
/* Normal and Incident vector are in viewspace. Lighting is evaluated in viewspace. */
vec2 uv_viewport = gl_FragCoord.xy * world_data.viewport_size_inv;
vec3 I = view_vector_from_screen_uv(uv_viewport, ViewVecs, ProjectionMatrix);
vec3 I = get_view_vector_from_screen_uv(uv_viewport);
vec3 N = normalize(normal_interp);
vec3 color = color_interp;

View File

@ -1,4 +1,5 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_common_obinfos_lib.glsl)
#pragma BLENDER_REQUIRE(workbench_data_lib.glsl)
@ -33,11 +34,6 @@ float phase_function_isotropic()
return 1.0 / (4.0 * M_PI);
}
float max_v3(vec3 v)
{
return max(v.x, max(v.y, v.z));
}
float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection)
{
/* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
@ -194,8 +190,8 @@ void main()
float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r;
float depth_end = min(depth, gl_FragCoord.z);
vec3 vs_ray_end = view_position_from_depth(screen_uv, depth_end, ViewVecs, ProjectionMatrix);
vec3 vs_ray_ori = view_position_from_depth(screen_uv, 0.0, ViewVecs, ProjectionMatrix);
vec3 vs_ray_end = get_view_space_from_depth(screen_uv, depth_end);
vec3 vs_ray_ori = get_view_space_from_depth(screen_uv, 0.0);
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);

View File

@ -28,6 +28,8 @@
#include "workbench_engine.h"
#include "workbench_private.h"
extern char datatoc_common_math_lib_glsl[];
extern char datatoc_common_math_geom_lib_glsl[];
extern char datatoc_common_hair_lib_glsl[];
extern char datatoc_common_pointcloud_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
@ -119,6 +121,8 @@ void workbench_shader_library_ensure(void)
if (e_data.lib == NULL) {
e_data.lib = DRW_shader_library_create();
/* NOTE: Theses needs to be ordered by dependencies. */
DRW_SHADER_LIB_ADD(e_data.lib, common_math_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_math_geom_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_hair_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_pointcloud_lib);

View File

@ -198,6 +198,17 @@ void DRW_uniformbuffer_free(struct GPUUniformBuffer *ubo);
} while (0)
/* Shaders */
#ifndef __GPU_MATERIAL_H__
/* FIXME: Meh avoid including all GPUMaterial. */
typedef void(GPUMaterialEvalCallbackFn)(struct GPUMaterial *mat,
int options,
const char **vert_code,
const char **geom_code,
const char **frag_lib,
const char **defines);
#endif
struct GPUShader *DRW_shader_create(const char *vert,
const char *geom,
const char *frag,
@ -237,7 +248,8 @@ struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
const char *geom,
const char *frag_lib,
const char *defines,
bool deferred);
bool deferred,
GPUMaterialEvalCallbackFn *callback);
struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
struct Material *ma,
struct bNodeTree *ntree,
@ -248,7 +260,8 @@ struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
const char *geom,
const char *frag_lib,
const char *defines,
bool deferred);
bool deferred,
GPUMaterialEvalCallbackFn *callback);
void DRW_shader_free(struct GPUShader *shader);
#define DRW_SHADER_FREE_SAFE(shader) \
do { \

View File

@ -430,7 +430,8 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
const char *geom,
const char *frag_lib,
const char *defines,
bool deferred)
bool deferred,
GPUMaterialEvalCallbackFn *callback)
{
GPUMaterial *mat = NULL;
if (DRW_state_is_image_render() || !deferred) {
@ -450,7 +451,8 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
geom,
frag_lib,
defines,
wo->id.name);
wo->id.name,
callback);
}
if (GPU_material_status(mat) == GPU_MAT_QUEUED) {
@ -470,7 +472,8 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
const char *geom,
const char *frag_lib,
const char *defines,
bool deferred)
bool deferred,
GPUMaterialEvalCallbackFn *callback)
{
GPUMaterial *mat = NULL;
if (DRW_state_is_image_render() || !deferred) {
@ -490,7 +493,8 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
geom,
frag_lib,
defines,
ma->id.name);
ma->id.name,
callback);
}
if (GPU_material_status(mat) == GPU_MAT_QUEUED) {

View File

@ -95,7 +95,7 @@ void hair_get_interp_attrs(
* For final drawing, the vertex index and the number of vertex per segment
*/
#ifndef HAIR_PHASE_SUBDIV
#if !defined(HAIR_PHASE_SUBDIV) && defined(GPU_VERTEX_SHADER)
int hair_get_strand_id(void)
{
return gl_VertexID / (hairStrandsRes * hairThicknessRes);
@ -206,4 +206,24 @@ vec3 hair_get_strand_pos(void)
return texelFetch(hairPointBuffer, id).point_position;
}
vec2 hair_get_barycentric(void)
{
/* To match cycles without breaking into individual segment we encode if we need to invert
* the first component into the second component. We invert if the barycentricTexCo.y
* is NOT 0.0 or 1.0. */
int id = hair_get_base_id();
return vec2(float((id % 2) == 1), float(((id % 4) % 3) > 0));
}
#endif
/* To be fed the result of hair_get_barycentric from vertex shader. */
vec2 hair_resolve_barycentric(vec2 vert_barycentric)
{
if (fract(vert_barycentric.y) != 0.0) {
return vec2(vert_barycentric.x, 0.0);
}
else {
return vec2(1.0 - vert_barycentric.x, 0.0);
}
}

View File

@ -22,6 +22,16 @@ layout(std140) uniform viewBlock
vec4 CameraTexCoFactors;
};
#define ViewNear (ViewVecs[0].w)
#define ViewFar (ViewVecs[1].w)
#define cameraForward ViewMatrixInverse[2].xyz
#define cameraPos ViewMatrixInverse[3].xyz
#define cameraVec \
((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward)
#define viewCameraVec \
((ProjectionMatrix[3][3] == 0.0) ? normalize(-viewPosition) : vec3(0.0, 0.0, 1.0))
#ifdef world_clip_planes_calc_clip_distance
# undef world_clip_planes_calc_clip_distance
# define world_clip_planes_calc_clip_distance(p) \
@ -104,10 +114,13 @@ uniform int resourceId;
/* Use this to declare and pass the value if
* the fragment shader uses the resource_id. */
# define RESOURCE_ID_VARYING flat out int resourceIDFrag;
# define RESOURCE_ID_VARYING_GEOM flat out int resourceIDGeom;
# define PASS_RESOURCE_ID resourceIDFrag = resource_id;
# define PASS_RESOURCE_ID_GEOM resourceIDGeom = resource_id;
# ifdef USE_GEOMETRY_SHADER
# define RESOURCE_ID_VARYING flat out int resourceIDGeom;
# define PASS_RESOURCE_ID resourceIDGeom = resource_id;
# else
# define RESOURCE_ID_VARYING flat out int resourceIDFrag;
# define PASS_RESOURCE_ID resourceIDFrag = resource_id;
# endif
#endif
/* If used in a fragment / geometry shader, we pass
@ -118,7 +131,7 @@ uniform int resourceId;
flat in int resourceIDGeom[];
# define resource_id resourceIDGeom
# define PASS_RESOURCE_ID(i) resourceIDFrag = resource_id[i];
# define PASS_RESOURCE_ID resourceIDFrag = resource_id[0];
#endif
#ifdef GPU_FRAGMENT_SHADER
@ -171,9 +184,12 @@ uniform mat4 ModelMatrixInverse;
* Note: This is only valid because we are only using the mat3 of the ViewMatrixInverse.
* ViewMatrix * transpose(ModelMatrixInverse)
**/
#define normal_object_to_view(n) (mat3(ViewMatrix) * (transpose(mat3(ModelMatrixInverse)) * n))
#define normal_object_to_world(n) (transpose(mat3(ModelMatrixInverse)) * n)
#define normal_world_to_object(n) (transpose(mat3(ModelMatrix)) * n)
#define NormalMatrix transpose(mat3(ModelMatrixInverse))
#define NormalMatrixInverse transpose(mat3(ModelMatrix))
#define normal_object_to_view(n) (mat3(ViewMatrix) * (NormalMatrix * n))
#define normal_object_to_world(n) (NormalMatrix * n)
#define normal_world_to_object(n) (NormalMatrixInverse * n)
#define normal_world_to_view(n) (mat3(ViewMatrix) * n)
#define normal_view_to_world(n) (mat3(ViewMatrixInverse) * n)
@ -199,3 +215,78 @@ uniform mat4 ModelMatrixInverse;
#define DRW_BASE_FROM_DUPLI (1 << 2)
#define DRW_BASE_FROM_SET (1 << 3)
#define DRW_BASE_ACTIVE (1 << 4)
/* ---- Opengl Depth conversion ---- */
float linear_depth(bool is_persp, float z, float zf, float zn)
{
if (is_persp) {
return (zn * zf) / (z * (zn - zf) + zf);
}
else {
return (z * 2.0 - 1.0) * zf;
}
}
float buffer_depth(bool is_persp, float z, float zf, float zn)
{
if (is_persp) {
return (zf * (zn - z)) / (z * (zn - zf));
}
else {
return (z / (zf * 2.0)) + 0.5;
}
}
float get_view_z_from_depth(float depth)
{
if (ProjectionMatrix[3][3] == 0.0) {
float d = 2.0 * depth - 1.0;
return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
}
else {
return ViewVecs[0].z + depth * ViewVecs[1].z;
}
}
float get_depth_from_view_z(float z)
{
if (ProjectionMatrix[3][3] == 0.0) {
float d = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2];
return d * 0.5 + 0.5;
}
else {
return (z - ViewVecs[0].z) / ViewVecs[1].z;
}
}
vec2 get_uvs_from_view(vec3 view)
{
vec4 ndc = ProjectionMatrix * vec4(view, 1.0);
return (ndc.xy / ndc.w) * 0.5 + 0.5;
}
vec3 get_view_space_from_depth(vec2 uvcoords, float depth)
{
if (ProjectionMatrix[3][3] == 0.0) {
return vec3(ViewVecs[0].xy + uvcoords * ViewVecs[1].xy, 1.0) * get_view_z_from_depth(depth);
}
else {
return ViewVecs[0].xyz + vec3(uvcoords, depth) * ViewVecs[1].xyz;
}
}
vec3 get_world_space_from_depth(vec2 uvcoords, float depth)
{
return (ViewMatrixInverse * vec4(get_view_space_from_depth(uvcoords, depth), 1.0)).xyz;
}
vec3 get_view_vector_from_screen_uv(vec2 uv)
{
if (ProjectionMatrix[3][3] == 0.0) {
return normalize(vec3(ViewVecs[0].xy + uv * ViewVecs[1].xy, 1.0));
}
else {
return vec3(0.0, 0.0, 1.0);
}
}

View File

@ -214,6 +214,8 @@ data_to_c_simple(shaders/gpu_shader_text_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_keyframe_diamond_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_keyframe_diamond_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_codegen_lib.glsl SRC)
data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC)
data_to_c_simple(shaders/material/gpu_shader_material_add_shader.glsl SRC)

View File

@ -110,6 +110,7 @@ typedef enum eGPUMatFlag {
GPU_MATFLAG_GLOSSY = (1 << 1),
GPU_MATFLAG_REFRACT = (1 << 2),
GPU_MATFLAG_SSS = (1 << 3),
GPU_MATFLAG_BARYCENTRIC = (1 << 4),
} eGPUMatFlag;
typedef enum eGPUBlendMode {
@ -137,6 +138,13 @@ typedef enum eGPUMaterialStatus {
GPU_MAT_SUCCESS,
} eGPUMaterialStatus;
typedef void(GPUMaterialEvalCallbackFn)(GPUMaterial *mat,
int options,
const char **vert_code,
const char **geom_code,
const char **frag_lib,
const char **defines);
GPUNodeLink *GPU_constant(const float *num);
GPUNodeLink *GPU_uniform(const float *num);
GPUNodeLink *GPU_attribute(GPUMaterial *mat, CustomDataType type, const char *name);
@ -190,7 +198,8 @@ GPUMaterial *GPU_material_from_nodetree(struct Scene *scene,
const char *geom_code,
const char *frag_lib,
const char *defines,
const char *name);
const char *name,
GPUMaterialEvalCallbackFn *callback);
void GPU_material_compile(GPUMaterial *mat);
void GPU_material_free(struct ListBase *gpumaterial);

View File

@ -55,8 +55,8 @@
#include <stdarg.h>
#include <string.h>
extern char datatoc_gpu_shader_codegen_lib_glsl[];
extern char datatoc_gpu_shader_common_obinfos_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
/* -------------------- GPUPass Cache ------------------ */
/**
@ -307,11 +307,6 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
int builtins = 0;
ListBase ubo_inputs = {NULL, NULL};
/* Attributes */
LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
BLI_dynstr_appendf(ds, "in %s var%d;\n", gpu_data_type_to_string(attr->gputype), attr->id);
}
/* Textures */
LISTBASE_FOREACH (GPUMaterialTexture *, tex, &graph->textures) {
if (tex->colorband) {
@ -378,7 +373,7 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
LISTBASE_FOREACH (LinkData *, link, &ubo_inputs) {
GPUInput *input = (GPUInput *)(link->data);
BLI_dynstr_appendf(ds, "\t%s unf%d;\n", gpu_data_type_to_string(input->type), input->id);
BLI_dynstr_appendf(ds, " %s unf%d;\n", gpu_data_type_to_string(input->type), input->id);
}
BLI_dynstr_append(ds, "};\n");
BLI_freelistN(&ubo_inputs);
@ -395,10 +390,10 @@ static void codegen_declare_tmps(DynStr *ds, GPUNodeGraph *graph)
/* declare temporary variables for node output storage */
LISTBASE_FOREACH (GPUOutput *, output, &node->outputs) {
if (output->type == GPU_CLOSURE) {
BLI_dynstr_appendf(ds, "\tClosure tmp%d;\n", output->id);
BLI_dynstr_appendf(ds, " Closure tmp%d;\n", output->id);
}
else {
BLI_dynstr_appendf(ds, "\t%s tmp%d;\n", gpu_data_type_to_string(output->type), output->id);
BLI_dynstr_appendf(ds, " %s tmp%d;\n", gpu_data_type_to_string(output->type), output->id);
}
}
}
@ -408,7 +403,7 @@ static void codegen_declare_tmps(DynStr *ds, GPUNodeGraph *graph)
static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph, GPUOutput *finaloutput)
{
LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) {
BLI_dynstr_appendf(ds, "\t%s(", node->name);
BLI_dynstr_appendf(ds, " %s(", node->name);
LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
if (input->source == GPU_SOURCE_TEX) {
@ -501,21 +496,24 @@ static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph, GPUOutput *f
BLI_dynstr_append(ds, ");\n");
}
BLI_dynstr_appendf(ds, "\n\treturn tmp%d", finaloutput->id);
BLI_dynstr_append(ds, ";\n");
BLI_dynstr_appendf(ds, "\n return tmp%d;\n", finaloutput->id);
}
static char *code_generate_fragment(GPUMaterial *material, GPUNodeGraph *graph)
static char *code_generate_fragment(GPUMaterial *material,
GPUNodeGraph *graph,
const char *interface_str)
{
DynStr *ds = BLI_dynstr_new();
char *code;
int builtins;
#if 0
BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);
#endif
codegen_set_unique_ids(graph);
/* Attributes, Shader stage interface. */
if (interface_str) {
BLI_dynstr_appendf(ds, "in codegenInterface {%s};\n\n", interface_str);
}
builtins = codegen_process_uniforms_functions(material, ds, graph);
if (builtins & (GPU_OBJECT_INFO | GPU_OBJECT_COLOR)) {
@ -523,73 +521,61 @@ static char *code_generate_fragment(GPUMaterial *material, GPUNodeGraph *graph)
}
if (builtins & GPU_BARYCENTRIC_TEXCO) {
BLI_dynstr_append(ds, "in vec2 barycentricTexCo;\n");
}
if (builtins & GPU_BARYCENTRIC_DIST) {
BLI_dynstr_append(ds, "flat in vec3 barycentricDist;\n");
BLI_dynstr_append(ds, datatoc_gpu_shader_codegen_lib_glsl);
}
BLI_dynstr_append(ds, "Closure nodetree_exec(void)\n{\n");
if (builtins & GPU_BARYCENTRIC_TEXCO) {
BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
BLI_dynstr_append(ds,
"\tvec2 barytexco = vec2((fract(barycentricTexCo.y) != 0.0)\n"
"\t ? barycentricTexCo.x\n"
"\t : 1.0 - barycentricTexCo.x,\n"
"\t 0.0);\n");
BLI_dynstr_append(ds, "#else\n");
BLI_dynstr_append(ds, "\tvec2 barytexco = barycentricTexCo;\n");
BLI_dynstr_append(ds, "#endif\n");
BLI_dynstr_append(ds, " vec2 barytexco = barycentric_resolve(barycentricTexCo);\n");
}
/* TODO(fclem) get rid of that. */
if (builtins & GPU_VIEW_MATRIX) {
BLI_dynstr_append(ds, "\t#define viewmat ViewMatrix\n");
BLI_dynstr_append(ds, " #define viewmat ViewMatrix\n");
}
if (builtins & GPU_CAMERA_TEXCO_FACTORS) {
BLI_dynstr_append(ds, "\t#define camtexfac CameraTexCoFactors\n");
BLI_dynstr_append(ds, " #define camtexfac CameraTexCoFactors\n");
}
if (builtins & GPU_OBJECT_MATRIX) {
BLI_dynstr_append(ds, "\t#define objmat ModelMatrix\n");
BLI_dynstr_append(ds, " #define objmat ModelMatrix\n");
}
if (builtins & GPU_INVERSE_OBJECT_MATRIX) {
BLI_dynstr_append(ds, "\t#define objinv ModelMatrixInverse\n");
BLI_dynstr_append(ds, " #define objinv ModelMatrixInverse\n");
}
if (builtins & GPU_INVERSE_VIEW_MATRIX) {
BLI_dynstr_append(ds, "\t#define viewinv ViewMatrixInverse\n");
BLI_dynstr_append(ds, " #define viewinv ViewMatrixInverse\n");
}
if (builtins & GPU_LOC_TO_VIEW_MATRIX) {
BLI_dynstr_append(ds, "\t#define localtoviewmat (ViewMatrix * ModelMatrix)\n");
BLI_dynstr_append(ds, " #define localtoviewmat (ViewMatrix * ModelMatrix)\n");
}
if (builtins & GPU_INVERSE_LOC_TO_VIEW_MATRIX) {
BLI_dynstr_append(ds,
"\t#define invlocaltoviewmat (ModelMatrixInverse * ViewMatrixInverse)\n");
" #define invlocaltoviewmat (ModelMatrixInverse * ViewMatrixInverse)\n");
}
if (builtins & GPU_VIEW_NORMAL) {
BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
BLI_dynstr_append(ds, "\tvec3 n;\n");
BLI_dynstr_append(ds, "\tworld_normals_get(n);\n");
BLI_dynstr_append(ds, "\tvec3 facingnormal = transform_direction(ViewMatrix, n);\n");
BLI_dynstr_append(ds, " vec3 n;\n");
BLI_dynstr_append(ds, " world_normals_get(n);\n");
BLI_dynstr_append(ds, " vec3 facingnormal = transform_direction(ViewMatrix, n);\n");
BLI_dynstr_append(ds, "#else\n");
BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing ? viewNormal: -viewNormal;\n");
BLI_dynstr_append(ds, " vec3 facingnormal = gl_FrontFacing ? viewNormal: -viewNormal;\n");
BLI_dynstr_append(ds, "#endif\n");
}
if (builtins & GPU_WORLD_NORMAL) {
BLI_dynstr_append(ds, "\tvec3 facingwnormal;\n");
BLI_dynstr_append(ds, " vec3 facingwnormal;\n");
if (builtins & GPU_VIEW_NORMAL) {
BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
BLI_dynstr_append(ds, "\tfacingwnormal = n;\n");
BLI_dynstr_append(ds, " facingwnormal = n;\n");
BLI_dynstr_append(ds, "#else\n");
BLI_dynstr_append(ds, "\tworld_normals_get(facingwnormal);\n");
BLI_dynstr_append(ds, " world_normals_get(facingwnormal);\n");
BLI_dynstr_append(ds, "#endif\n");
}
else {
BLI_dynstr_append(ds, "\tworld_normals_get(facingwnormal);\n");
BLI_dynstr_append(ds, " world_normals_get(facingwnormal);\n");
}
}
if (builtins & GPU_VIEW_POSITION) {
BLI_dynstr_append(ds, "\t#define viewposition viewPosition\n");
BLI_dynstr_append(ds, " #define viewposition viewPosition\n");
}
codegen_declare_tmps(ds, graph);
@ -597,21 +583,6 @@ static char *code_generate_fragment(GPUMaterial *material, GPUNodeGraph *graph)
BLI_dynstr_append(ds, "}\n");
/* XXX This cannot go into gpu_shader_material.glsl because main()
* would be parsed and generate error */
/* Old glsl mode compat. */
/* TODO(fclem) This is only used by world shader now. get rid of it? */
BLI_dynstr_append(ds, "#ifndef NODETREE_EXEC\n");
BLI_dynstr_append(ds, "out vec4 fragColor;\n");
BLI_dynstr_append(ds, "void main()\n");
BLI_dynstr_append(ds, "{\n");
BLI_dynstr_append(ds, "\tClosure cl = nodetree_exec();\n");
BLI_dynstr_append(ds,
"\tfragColor = vec4(cl.radiance, "
"saturate(1.0 - avg(cl.transmittance)));\n");
BLI_dynstr_append(ds, "}\n");
BLI_dynstr_append(ds, "#endif\n\n");
/* create shader */
code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
@ -646,21 +617,48 @@ static const char *attr_prefix_get(CustomDataType type)
}
}
static char *code_generate_vertex(GPUNodeGraph *graph, const char *vert_code, bool use_geom)
/* We talk about shader stage interface, not to be mistaken with GPUShaderInterface. */
static char *code_generate_interface(GPUNodeGraph *graph, int builtins)
{
DynStr *ds = BLI_dynstr_new();
char *code;
int builtins = 0;
if (BLI_listbase_is_empty(&graph->attributes) &&
(builtins & (GPU_BARYCENTRIC_DIST | GPU_BARYCENTRIC_TEXCO)) == 0) {
return NULL;
}
/* Hairs uv and col attributes are passed by bufferTextures. */
BLI_dynstr_append(ds,
"#ifdef HAIR_SHADER\n"
"#define DEFINE_ATTR(type, attr) uniform samplerBuffer attr\n"
"#else\n"
"#define DEFINE_ATTR(type, attr) in type attr\n"
"#endif\n");
DynStr *ds = BLI_dynstr_new();
BLI_dynstr_append(ds, "\n");
LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
BLI_dynstr_appendf(ds, "%s var%d;\n", gpu_data_type_to_string(attr->gputype), attr->id);
}
if (builtins & GPU_BARYCENTRIC_TEXCO) {
BLI_dynstr_append(ds, "vec2 barycentricTexCo;\n");
}
if (builtins & GPU_BARYCENTRIC_DIST) {
BLI_dynstr_append(ds, "vec3 barycentricDist;\n");
}
char *code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
return code;
}
static char *code_generate_vertex(GPUNodeGraph *graph,
const char *interface_str,
const char *vert_code,
int builtins)
{
DynStr *ds = BLI_dynstr_new();
BLI_dynstr_append(ds, datatoc_gpu_shader_codegen_lib_glsl);
/* Inputs */
LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
const char *type_str = gpu_data_type_to_string(attr->gputype);
const char *prefix = attr_prefix_get(attr->type);
/* XXX FIXME : see notes in mesh_render_data_create() */
/* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
if (attr->type == CD_ORCO) {
@ -669,188 +667,58 @@ static char *code_generate_vertex(GPUNodeGraph *graph, const char *vert_code, bo
BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n");
}
else if (attr->name[0] == '\0') {
BLI_dynstr_appendf(ds,
"DEFINE_ATTR(%s, %s);\n",
gpu_data_type_to_string(attr->gputype),
attr_prefix_get(attr->type));
BLI_dynstr_appendf(ds, "#define att%d %s\n", attr->id, attr_prefix_get(attr->type));
BLI_dynstr_appendf(ds, "DEFINE_ATTR(%s, %s);\n", type_str, prefix);
BLI_dynstr_appendf(ds, "#define att%d %s\n", attr->id, prefix);
}
else {
char attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
GPU_vertformat_safe_attr_name(attr->name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
BLI_dynstr_appendf(ds,
"DEFINE_ATTR(%s, %s%s);\n",
gpu_data_type_to_string(attr->gputype),
attr_prefix_get(attr->type),
attr_safe_name);
BLI_dynstr_appendf(
ds, "#define att%d %s%s\n", attr->id, attr_prefix_get(attr->type), attr_safe_name);
}
BLI_dynstr_appendf(ds,
"out %s var%d%s;\n",
gpu_data_type_to_string(attr->gputype),
attr->id,
use_geom ? "g" : "");
}
LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) {
LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
if (input->source == GPU_SOURCE_BUILTIN) {
builtins |= input->builtin;
}
BLI_dynstr_appendf(ds, "DEFINE_ATTR(%s, %s%s);\n", type_str, prefix, attr_safe_name);
BLI_dynstr_appendf(ds, "#define att%d %s%s\n", attr->id, prefix, attr_safe_name);
}
}
if (builtins & GPU_BARYCENTRIC_TEXCO) {
BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
BLI_dynstr_appendf(ds, "out vec2 barycentricTexCo%s;\n", use_geom ? "g" : "");
BLI_dynstr_append(ds, "#endif\n");
/* Outputs interface */
if (interface_str) {
BLI_dynstr_appendf(ds, "out codegenInterface {%s};\n\n", interface_str);
}
if (builtins & GPU_BARYCENTRIC_DIST) {
BLI_dynstr_append(ds, "out vec3 barycentricPosg;\n");
}
BLI_dynstr_append(ds, "\n#define USE_ATTR\n");
/* Prototype, defined later (this is because of matrices definition). */
BLI_dynstr_append(ds, "void pass_attr(in vec3 position);\n");
/* Prototype. Needed for hair functions. */
BLI_dynstr_append(ds, "void pass_attr(vec3 position, mat3 normalmat, mat4 modelmatinv);\n");
BLI_dynstr_append(ds, "#define USE_ATTR\n\n");
BLI_dynstr_append(ds, vert_code);
BLI_dynstr_append(ds, "\n");
if (use_geom) {
/* XXX HACK: Eevee specific. */
char *vert_new, *vert_new2;
vert_new = BLI_str_replaceN(vert_code, "worldPosition", "worldPositiong");
vert_new2 = vert_new;
vert_new = BLI_str_replaceN(vert_new2, "viewPosition", "viewPositiong");
MEM_freeN(vert_new2);
vert_new2 = vert_new;
vert_new = BLI_str_replaceN(vert_new2, "worldNormal", "worldNormalg");
MEM_freeN(vert_new2);
vert_new2 = vert_new;
vert_new = BLI_str_replaceN(vert_new2, "viewNormal", "viewNormalg");
MEM_freeN(vert_new2);
BLI_dynstr_append(ds, vert_new);
MEM_freeN(vert_new);
}
else {
BLI_dynstr_append(ds, vert_code);
}
BLI_dynstr_append(ds, "\n");
BLI_dynstr_append(ds, use_geom ? "RESOURCE_ID_VARYING_GEOM\n" : "RESOURCE_ID_VARYING\n");
/* Prototype because defined later. */
BLI_dynstr_append(ds,
"vec2 hair_get_customdata_vec2(const samplerBuffer);\n"
"vec3 hair_get_customdata_vec3(const samplerBuffer);\n"
"vec4 hair_get_customdata_vec4(const samplerBuffer);\n"
"vec3 hair_get_strand_pos(void);\n"
"int hair_get_base_id(void);\n"
"\n");
BLI_dynstr_append(ds, "void pass_attr(in vec3 position) {\n");
BLI_dynstr_append(ds, use_geom ? "\tPASS_RESOURCE_ID_GEOM\n" : "\tPASS_RESOURCE_ID\n");
BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
if (builtins & GPU_BARYCENTRIC_TEXCO) {
/* To match cycles without breaking into individual segment we encode if we need to invert
* the first component into the second component. We invert if the barycentricTexCo.y
* is NOT 0.0 or 1.0. */
BLI_dynstr_append(ds, "\tint _base_id = hair_get_base_id();\n");
BLI_dynstr_appendf(
ds, "\tbarycentricTexCo%s.x = float((_base_id %% 2) == 1);\n", use_geom ? "g" : "");
BLI_dynstr_appendf(
ds, "\tbarycentricTexCo%s.y = float(((_base_id %% 4) %% 3) > 0);\n", use_geom ? "g" : "");
}
if (builtins & GPU_BARYCENTRIC_DIST) {
BLI_dynstr_append(ds, "\tbarycentricPosg = position;\n");
}
LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
if (attr->type == CD_TANGENT) {
/* Not supported by hairs */
BLI_dynstr_appendf(ds, "\tvar%d%s = vec4(0.0);\n", attr->id, use_geom ? "g" : "");
}
else if (attr->type == CD_ORCO) {
BLI_dynstr_appendf(ds,
"\tvar%d%s = OrcoTexCoFactors[0].xyz + (ModelMatrixInverse * "
"vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1].xyz;\n",
attr->id,
use_geom ? "g" : "");
/* TODO: fix ORCO with modifiers. */
}
else {
BLI_dynstr_appendf(ds,
"\tvar%d%s = hair_get_customdata_%s(att%d);\n",
attr->id,
use_geom ? "g" : "",
gpu_data_type_to_string(attr->gputype),
attr->id);
}
}
BLI_dynstr_append(ds, "#else /* MESH_SHADER */\n");
BLI_dynstr_append(ds, "void pass_attr(vec3 position, mat3 normalmat, mat4 modelmatinv) {\n");
/* GPU_BARYCENTRIC_TEXCO cannot be computed based on gl_VertexID
* for MESH_SHADER because of indexed drawing. In this case a
* geometry shader is needed. */
if (builtins & GPU_BARYCENTRIC_TEXCO) {
BLI_dynstr_appendf(ds, " barycentricTexCo = barycentric_get();\n");
}
if (builtins & GPU_BARYCENTRIC_DIST) {
BLI_dynstr_append(ds, "\tbarycentricPosg = (ModelMatrix * vec4(position, 1.0)).xyz;\n");
BLI_dynstr_appendf(ds, " barycentricDist = vec3(0);\n");
}
LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
if (attr->type == CD_TANGENT) { /* silly exception */
BLI_dynstr_appendf(ds,
"\tvar%d%s.xyz = transpose(mat3(ModelMatrixInverse)) * att%d.xyz;\n",
attr->id,
use_geom ? "g" : "",
attr->id);
BLI_dynstr_appendf(ds, "\tvar%d%s.w = att%d.w;\n", attr->id, use_geom ? "g" : "", attr->id);
/* Normalize only if vector is not null. */
BLI_dynstr_appendf(ds,
"\tfloat lvar%d = dot(var%d%s.xyz, var%d%s.xyz);\n",
attr->id,
attr->id,
use_geom ? "g" : "",
attr->id,
use_geom ? "g" : "");
BLI_dynstr_appendf(ds,
"\tvar%d%s.xyz *= (lvar%d > 0.0) ? inversesqrt(lvar%d) : 1.0;\n",
attr->id,
use_geom ? "g" : "",
attr->id,
attr->id);
BLI_dynstr_appendf(ds, " var%d = tangent_get(att%d, normalmat);\n", attr->id, attr->id);
}
else if (attr->type == CD_ORCO) {
BLI_dynstr_appendf(ds,
"\tvar%d%s = OrcoTexCoFactors[0].xyz + position *"
" OrcoTexCoFactors[1].xyz;\n",
attr->id,
use_geom ? "g" : "");
/* See mesh_create_loop_orco() for explanation. */
BLI_dynstr_appendf(ds,
"\tif (orco.w == 0.0) { var%d%s = orco.xyz * 0.5 + 0.5; }\n",
attr->id,
use_geom ? "g" : "");
BLI_dynstr_appendf(
ds, " var%d = orco_get(position, modelmatinv, OrcoTexCoFactors, orco);\n", attr->id);
}
else {
BLI_dynstr_appendf(ds, "\tvar%d%s = att%d;\n", attr->id, use_geom ? "g" : "", attr->id);
const char *type_str = gpu_data_type_to_string(attr->gputype);
BLI_dynstr_appendf(ds, " var%d = GET_ATTR(%s, att%d);\n", attr->id, type_str, attr->id);
}
}
BLI_dynstr_append(ds, "#endif /* HAIR_SHADER */\n");
BLI_dynstr_append(ds, "}\n");
code = BLI_dynstr_get_cstring(ds);
char *code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
@ -864,144 +732,46 @@ static char *code_generate_vertex(GPUNodeGraph *graph, const char *vert_code, bo
}
static char *code_generate_geometry(GPUNodeGraph *graph,
const char *interface_str,
const char *geom_code,
const char *defines)
int builtins)
{
if (!geom_code) {
return NULL;
}
DynStr *ds = BLI_dynstr_new();
char *code;
int builtins = 0;
/* XXX we should not make specific eevee cases here. */
bool is_hair_shader = (strstr(defines, "HAIR_SHADER") != NULL);
/* Create prototype because attributes cannot be declared before layout. */
BLI_dynstr_append(ds, "void pass_attr(in int vert);\n");
BLI_dynstr_append(ds, "void calc_barycentric_distances(vec3 pos0, vec3 pos1, vec3 pos2);\n");
BLI_dynstr_append(ds, "#define USE_ATTR\n");
LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) {
LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
if (input->source == GPU_SOURCE_BUILTIN) {
builtins |= input->builtin;
}
}
/* Attributes, Shader interface; */
if (interface_str) {
BLI_dynstr_appendf(ds, "in codegenInterface {%s} dataAttrIn[];\n\n", interface_str);
BLI_dynstr_appendf(ds, "out codegenInterface {%s} dataAttrOut;\n\n", interface_str);
}
/* Generate varying declarations. */
LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
BLI_dynstr_appendf(ds, "in %s var%dg[];\n", gpu_data_type_to_string(attr->gputype), attr->id);
BLI_dynstr_appendf(ds, "out %s var%d;\n", gpu_data_type_to_string(attr->gputype), attr->id);
}
if (builtins & GPU_BARYCENTRIC_TEXCO) {
BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
BLI_dynstr_append(ds, "in vec2 barycentricTexCog[];\n");
BLI_dynstr_append(ds, "#endif\n");
BLI_dynstr_append(ds, "out vec2 barycentricTexCo;\n");
}
BLI_dynstr_append(ds, datatoc_gpu_shader_codegen_lib_glsl);
if (builtins & GPU_BARYCENTRIC_DIST) {
BLI_dynstr_append(ds, "in vec3 barycentricPosg[];\n");
BLI_dynstr_append(ds, "flat out vec3 barycentricDist;\n");
/* geom_code should do something with this, but may not. */
BLI_dynstr_append(ds, "#define DO_BARYCENTRIC_DISTANCES\n");
}
if (geom_code == NULL) {
/* Force geometry usage if GPU_BARYCENTRIC_DIST or GPU_BARYCENTRIC_TEXCO are used.
* Note: GPU_BARYCENTRIC_TEXCO only requires it if the shader is not drawing hairs. */
if ((builtins & (GPU_BARYCENTRIC_DIST | GPU_BARYCENTRIC_TEXCO)) == 0 || is_hair_shader) {
/* Early out */
BLI_dynstr_free(ds);
return NULL;
}
else {
/* Force geom shader usage */
/* TODO put in external file. */
BLI_dynstr_append(ds, "layout(triangles) in;\n");
BLI_dynstr_append(ds, "layout(triangle_strip, max_vertices=3) out;\n");
BLI_dynstr_append(ds, "in vec3 worldPositiong[];\n");
BLI_dynstr_append(ds, "in vec3 viewPositiong[];\n");
BLI_dynstr_append(ds, "in vec3 worldNormalg[];\n");
BLI_dynstr_append(ds, "in vec3 viewNormalg[];\n");
BLI_dynstr_append(ds, "out vec3 worldPosition;\n");
BLI_dynstr_append(ds, "out vec3 viewPosition;\n");
BLI_dynstr_append(ds, "out vec3 worldNormal;\n");
BLI_dynstr_append(ds, "out vec3 viewNormal;\n");
BLI_dynstr_append(ds, datatoc_common_view_lib_glsl);
BLI_dynstr_append(ds, "void main(){\n");
if (builtins & GPU_BARYCENTRIC_DIST) {
BLI_dynstr_append(ds,
"\tcalc_barycentric_distances(barycentricPosg[0], barycentricPosg[1], "
"barycentricPosg[2]);\n");
}
for (int i = 0; i < 3; i++) {
BLI_dynstr_appendf(ds, "\tgl_Position = gl_in[%d].gl_Position;\n", i);
BLI_dynstr_appendf(ds, "\tgl_ClipDistance[0] = gl_in[%d].gl_ClipDistance[0];\n", i);
BLI_dynstr_appendf(ds, "\tpass_attr(%d);\n", i);
BLI_dynstr_append(ds, "\tEmitVertex();\n");
}
BLI_dynstr_append(ds, "}\n");
}
}
else {
BLI_dynstr_append(ds, geom_code);
}
if (builtins & GPU_BARYCENTRIC_DIST) {
BLI_dynstr_append(ds, "void calc_barycentric_distances(vec3 pos0, vec3 pos1, vec3 pos2) {\n");
BLI_dynstr_append(ds, "\tvec3 edge21 = pos2 - pos1;\n");
BLI_dynstr_append(ds, "\tvec3 edge10 = pos1 - pos0;\n");
BLI_dynstr_append(ds, "\tvec3 edge02 = pos0 - pos2;\n");
BLI_dynstr_append(ds, "\tvec3 d21 = normalize(edge21);\n");
BLI_dynstr_append(ds, "\tvec3 d10 = normalize(edge10);\n");
BLI_dynstr_append(ds, "\tvec3 d02 = normalize(edge02);\n");
BLI_dynstr_append(ds, "\tfloat d = dot(d21, edge02);\n");
BLI_dynstr_append(ds, "\tbarycentricDist.x = sqrt(dot(edge02, edge02) - d * d);\n");
BLI_dynstr_append(ds, "\td = dot(d02, edge10);\n");
BLI_dynstr_append(ds, "\tbarycentricDist.y = sqrt(dot(edge10, edge10) - d * d);\n");
BLI_dynstr_append(ds, "\td = dot(d10, edge21);\n");
BLI_dynstr_append(ds, "\tbarycentricDist.z = sqrt(dot(edge21, edge21) - d * d);\n");
BLI_dynstr_append(ds, "}\n");
}
BLI_dynstr_append(ds, "RESOURCE_ID_VARYING\n");
/* Generate varying assignments. */
BLI_dynstr_append(ds, "void pass_attr(in int vert) {\n");
BLI_dynstr_append(ds, "\tPASS_RESOURCE_ID(vert)\n");
/* XXX HACK: Eevee specific. */
if (geom_code == NULL) {
BLI_dynstr_append(ds, "\tworldPosition = worldPositiong[vert];\n");
BLI_dynstr_append(ds, "\tviewPosition = viewPositiong[vert];\n");
BLI_dynstr_append(ds, "\tworldNormal = worldNormalg[vert];\n");
BLI_dynstr_append(ds, "\tviewNormal = viewNormalg[vert];\n");
}
BLI_dynstr_append(ds, "#define USE_ATTR\n");
BLI_dynstr_append(ds, "void pass_attr(const int vert) {\n");
if (builtins & GPU_BARYCENTRIC_TEXCO) {
BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
BLI_dynstr_append(ds, "\tbarycentricTexCo = barycentricTexCog[vert];\n");
BLI_dynstr_append(ds, "#else\n");
BLI_dynstr_append(ds, "\tbarycentricTexCo.x = float((vert % 3) == 0);\n");
BLI_dynstr_append(ds, "\tbarycentricTexCo.y = float((vert % 3) == 1);\n");
BLI_dynstr_append(ds, "#endif\n");
BLI_dynstr_append(ds, " dataAttrOut.barycentricTexCo = calc_barycentric_co(vert);\n");
}
LISTBASE_FOREACH (GPUMaterialAttribute *, attr, &graph->attributes) {
/* TODO let shader choose what to do depending on what the attribute is. */
BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", attr->id, attr->id);
BLI_dynstr_appendf(ds, " dataAttrOut.var%d = dataAttrIn[vert].var%d;\n", attr->id, attr->id);
}
BLI_dynstr_append(ds, "}\n");
BLI_dynstr_append(ds, "}\n\n");
code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_append(ds, geom_code);
char *code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
return code;
@ -1031,8 +801,17 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
* generated VBOs are ready to accept the future shader. */
gpu_node_graph_prune_unused(graph);
int builtins = 0;
LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) {
LISTBASE_FOREACH (GPUInput *, input, &node->inputs) {
if (input->source == GPU_SOURCE_BUILTIN) {
builtins |= input->builtin;
}
}
}
/* generate code */
char *fragmentgen = code_generate_fragment(material, graph);
char *interface_str = code_generate_interface(graph, builtins);
char *fragmentgen = code_generate_fragment(material, graph, interface_str);
/* Cache lookup: Reuse shaders already compiled */
uint32_t hash = gpu_pass_hash(fragmentgen, defines, &graph->attributes);
@ -1040,6 +819,7 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
if (pass_hash && (pass_hash->next == NULL || pass_hash->next->hash != hash)) {
/* No collision, just return the pass. */
MEM_SAFE_FREE(interface_str);
MEM_freeN(fragmentgen);
if (!gpu_pass_is_valid(pass_hash)) {
/* Shader has already been created but failed to compile. */
@ -1054,10 +834,11 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
GSet *used_libraries = gpu_material_used_libraries(material);
char *tmp = gpu_material_library_generate_code(used_libraries, frag_lib);
char *geometrycode = code_generate_geometry(graph, geom_code, defines);
char *vertexcode = code_generate_vertex(graph, vert_code, (geometrycode != NULL));
char *geometrycode = code_generate_geometry(graph, interface_str, geom_code, builtins);
char *vertexcode = code_generate_vertex(graph, interface_str, vert_code, builtins);
char *fragmentcode = BLI_strdupcat(tmp, fragmentgen);
MEM_SAFE_FREE(interface_str);
MEM_freeN(fragmentgen);
MEM_freeN(tmp);

View File

@ -85,7 +85,7 @@ struct GPUMaterial {
bool has_surface_output;
/* Only used by Eevee to know which bsdf are used. */
int flag;
eGPUMatFlag flag;
/* Used by 2.8 pipeline */
GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */
@ -659,7 +659,8 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
const char *geom_code,
const char *frag_lib,
const char *defines,
const char *name)
const char *name,
GPUMaterialEvalCallbackFn *callback)
{
LinkData *link;
bool has_volume_output, has_surface_output;
@ -696,6 +697,9 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
mat->has_volume_output = has_volume_output;
if (mat->graph.outlink) {
if (callback) {
callback(mat, options, &vert_code, &geom_code, &frag_lib, &defines);
}
/* HACK: this is only for eevee. We add the define here after the nodetree evaluation. */
if (GPU_material_flag_get(mat, GPU_MATFLAG_SSS)) {
defines = BLI_string_joinN(defines,

View File

@ -341,7 +341,7 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
gpu_shader_standard_extensions(standard_extensions);
if (vertexcode) {
const char *source[6];
const char *source[7];
/* custom limit, may be too small, beware */
int num_source = 0;
@ -352,6 +352,9 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
source[num_source++] = standard_extensions;
source[num_source++] = standard_defines;
if (geocode) {
source[num_source++] = "#define USE_GEOMETRY_SHADER\n";
}
if (defines) {
source[num_source++] = defines;
}
@ -375,7 +378,7 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
}
if (fragcode) {
const char *source[7];
const char *source[8];
int num_source = 0;
source[num_source++] = gpu_shader_version();
@ -385,6 +388,9 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
source[num_source++] = standard_extensions;
source[num_source++] = standard_defines;
if (geocode) {
source[num_source++] = "#define USE_GEOMETRY_SHADER\n";
}
if (defines) {
source[num_source++] = defines;
}
@ -453,6 +459,9 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
if (!status) {
glGetProgramInfoLog(shader->program, sizeof(log), &length, log);
/* print attached shaders in pipeline order */
if (defines) {
shader_print_errors("linking", log, &defines, 1);
}
if (vertexcode) {
shader_print_errors("linking", log, &vertexcode, 1);
}

View File

@ -0,0 +1,87 @@
vec3 calc_barycentric_distances(vec3 pos0, vec3 pos1, vec3 pos2)
{
vec3 edge21 = pos2 - pos1;
vec3 edge10 = pos1 - pos0;
vec3 edge02 = pos0 - pos2;
vec3 d21 = normalize(edge21);
vec3 d10 = normalize(edge10);
vec3 d02 = normalize(edge02);
vec3 dists;
float d = dot(d21, edge02);
dists.x = sqrt(dot(edge02, edge02) - d * d);
d = dot(d02, edge10);
dists.y = sqrt(dot(edge10, edge10) - d * d);
d = dot(d10, edge21);
dists.z = sqrt(dot(edge21, edge21) - d * d);
return dists;
}
vec2 calc_barycentric_co(int vertid)
{
vec2 bary;
bary.x = float((vertid % 3) == 0);
bary.y = float((vertid % 3) == 1);
return bary;
}
#ifdef HAIR_SHADER
/* Hairs uv and col attributes are passed by bufferTextures. */
# define DEFINE_ATTR(type, attr) uniform samplerBuffer attr
# define GET_ATTR(type, attr) hair_get_customdata_##type(attr)
# define barycentric_get() hair_get_barycentric()
# define barycentric_resolve(bary) hair_resolve_barycentric(bary)
vec3 orco_get(vec3 local_pos, mat4 modelmatinv, vec4 orco_madd[2], const samplerBuffer orco_samp)
{
/* TODO: fix ORCO with modifiers. */
vec3 orco = (modelmatinv * vec4(local_pos, 1.0)).xyz;
return orco_madd[0].xyz + orco * orco_madd[1].xyz;
}
vec4 tangent_get(const samplerBuffer attr, mat3 normalmat)
{
/* Unsupported */
return vec4(0.0);
}
#else /* MESH_SHADER */
# define DEFINE_ATTR(type, attr) in type attr
# define GET_ATTR(type, attr) attr
/* Calculated in geom shader later with calc_barycentric_co. */
# define barycentric_get() vec2(0)
# define barycentric_resolve(bary) bary
vec3 orco_get(vec3 local_pos, mat4 modelmatinv, vec4 orco_madd[2], vec4 orco)
{
/* If the object does not have any deformation, the orco layer calculation is done on the fly
* using the orco_madd factors.
* We know when there is no orco layer when orco.w is 1.0 because it uses the generic vertex
* attrib (which is [0,0,0,1]). */
if (orco.w == 0.0) {
return orco.xyz * 0.5 + 0.5;
}
else {
return orco_madd[0].xyz + local_pos * orco_madd[1].xyz;
}
}
vec4 tangent_get(vec4 attr, mat3 normalmat)
{
vec4 tangent;
tangent.xyz = normalmat * attr.xyz;
tangent.w = attr.w;
float len_sqr = dot(tangent.xyz, tangent.xyz);
/* Normalize only if vector is not null. */
if (len_sqr > 0.0) {
tangent.xyz *= inversesqrt(len_sqr);
}
return tangent;
}
#endif

View File

@ -3,7 +3,7 @@ void node_ambient_occlusion(
vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao)
{
vec3 bent_normal;
vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal);
result_color = result_ao * color;
}

View File

@ -1,3 +1,15 @@
float wang_hash_noise(uint s)
{
s = (s ^ 61u) ^ (s >> 16u);
s *= 9u;
s = s ^ (s >> 4u);
s *= 0x27d4eb2du;
s = s ^ (s >> 15u);
return fract(float(s) / 4294967296.0);
}
void node_hair_info(out float is_strand,
out float intercept,
out float thickness,

View File

@ -6,7 +6,7 @@ void world_normals_get(out vec3 N)
vec3 B = normalize(cross(worldNormal, hairTangent));
float cos_theta;
if (hairThicknessRes == 1) {
vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
/* Random cosine normal distribution on the hair surface. */
cos_theta = rand.x * 2.0 - 1.0;
}

View File

@ -45,6 +45,9 @@ static int node_shader_gpu_geometry(GPUMaterial *mat,
float val[4] = {0.0f, 0.0f, 0.0f, 0.0f};
GPUNodeLink *bary_link = (!out[5].hasoutput) ? GPU_constant(val) :
GPU_builtin(GPU_BARYCENTRIC_TEXCO);
if (out[5].hasoutput) {
GPU_material_flag_set(mat, GPU_MATFLAG_BARYCENTRIC);
}
/* Opti: don't request orco if not needed. */
GPUNodeLink *orco_link = (!out[2].hasoutput) ? GPU_constant(val) :
GPU_attribute(mat, CD_ORCO, "");

View File

@ -36,6 +36,7 @@ static int node_shader_gpu_wireframe(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
GPU_material_flag_set(mat, GPU_MATFLAG_BARYCENTRIC);
/* node->custom1 is use_pixel_size */
if (node->custom1) {
return GPU_stack_link(