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:
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
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
|
@ -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;
|
||||
}
|
|
@ -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. */
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
|
||||
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
|
||||
|
||||
uniform sampler2D depthBuffer;
|
||||
|
||||
uniform mat4 prevViewProjMatrix;
|
||||
uniform mat4 currViewProjMatrixInv;
|
||||
uniform mat4 nextViewProjMatrix;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(cubemap_lib.glsl)
|
||||
|
||||
flat in int pid;
|
||||
in vec2 quadCoord;
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
|
||||
/* XXX TODO fix code duplication */
|
||||
struct CubeData {
|
||||
vec4 position_type;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
|
||||
uniform float sphere_size;
|
||||
uniform int offset;
|
||||
uniform ivec3 grid_resolution;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
|
||||
uniform sampler2DArray probePlanars;
|
||||
|
||||
in vec3 worldPosition;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
|
||||
in vec3 pos;
|
||||
|
||||
in int probe_id;
|
||||
|
|
|
@ -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
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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;
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
|
||||
|
||||
uniform sampler2D colorTex;
|
||||
uniform sampler2D depthTex;
|
||||
uniform sampler2D lineTex;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 { \
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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, "");
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue