diff options
author | OmarSquircleArt <omar.squircleart@gmail.com> | 2019-08-30 18:23:04 +0300 |
---|---|---|
committer | OmarSquircleArt <omar.squircleart@gmail.com> | 2019-08-30 18:28:57 +0300 |
commit | 8cd0da88e55a0c0f88297a5f0f770eb40acc6219 (patch) | |
tree | 585b9bcc07ce392c6164ac0230d56d617ac051ca /source | |
parent | ac646bc20dafe176c1b84ee5beddf980aba11358 (diff) |
GPU: Split gpu_shader_material into multiple files.
This patch continue the efforts to split the `gpu_shader_material` file
started in D5569.
Dependency resolution is now recursive. Each shading node gets its own
file. Additionally, some utility files are added to be shared between
files, like `math_util`, `color_util`, and `hash`. Some files are always
included because they may be used in the execution function, like
`world_normals`.
Some glsl functions appeared to be unused, so they were removed, like
`output_node`, `bits_to_01`, and `exp_blender`. Other functions have
been renamed to be more general and get used as utils, like `texco_norm`
which became `vector_normalize`.
A lot of the opengl tests fails, but those same tests also fail in
master, so this is probably unrelated to this patch.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5616
Diffstat (limited to 'source')
98 files changed, 4202 insertions, 3620 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 4a67f5f6af8..f11dcc9bcf0 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -232,10 +232,94 @@ 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_geometry.glsl SRC) -data_to_c_simple(shaders/gpu_shader_material.glsl SRC) -data_to_c_simple(shaders/gpu_shader_material_hash.glsl SRC) -data_to_c_simple(shaders/gpu_shader_material_magic.glsl SRC) -data_to_c_simple(shaders/gpu_shader_material_white_noise.glsl SRC) + +data_to_c_simple(shaders/material/gpu_shader_material_add_shader.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_ambient_occlusion.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_anisotropic.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_attribute.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_background.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_bevel.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_blackbody.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_bright_contrast.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_bump.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_camera.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_cell_noise.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_clamp.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_color_ramp.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_color_util.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_combine_hsv.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_combine_rgb.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_combine_xyz.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_diffuse.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_displacement.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_eevee_specular.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_emission.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_fractal_noise.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_fresnel.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_gamma.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_geometry.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_glass.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_glossy.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_hair_info.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_hash.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_holdout.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_hue_sat_val.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_invert.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_layer_weight.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_light_falloff.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_light_path.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_mapping.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_map_range.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_math.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_math_util.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_mix_rgb.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_mix_shader.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_noise.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_normal.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_normal_map.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_object_info.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_output_material.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_output_world.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_particle_info.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_principled.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_refraction.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_rgb_curves.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_rgb_to_bw.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_separate_hsv.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_separate_rgb.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_separate_xyz.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_set.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_shader_to_rgba.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_squeeze.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_subsurface_scattering.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tangent.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_brick.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_checker.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_environment.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_gradient.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_image.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_magic.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_musgrave.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_noise.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_sky.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_texture_coordinates.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_voronoi.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_wave.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_tex_white_noise.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_toon.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_translucent.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_transparent.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_uv_map.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_vector_curves.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_vector_displacement.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_vector_math.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_velvet.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_volume_absorption.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_volume_info.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_volume_principled.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_volume_scatter.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_wireframe.glsl SRC) +data_to_c_simple(shaders/material/gpu_shader_material_world_normals.glsl SRC) data_to_c_simple(shaders/gpu_shader_gpencil_stroke_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_gpencil_stroke_frag.glsl SRC) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 8199f0ca194..d655a43561e 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -414,7 +414,7 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t } else if (to == GPU_FLOAT) { if (from == GPU_VEC4) { - BLI_dynstr_appendf(ds, "convert_rgba_to_float(%s)", name); + BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.2126, 0.7152, 0.0722))", name); } else if (from == GPU_VEC3) { BLI_dynstr_appendf(ds, "(%s.r + %s.g + %s.b) / 3.0", name, name, name); @@ -1376,8 +1376,8 @@ void GPU_code_generate_glsl_lib(void) } FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh"); - for (int i = 0; gpu_material_libraries[i].code; i++) { - gpu_parse_material_library(FUNCTION_HASH, &gpu_material_libraries[i]); + for (int i = 0; gpu_material_libraries[i]; i++) { + gpu_parse_material_library(FUNCTION_HASH, gpu_material_libraries[i]); } } @@ -1780,17 +1780,22 @@ GPUNodeLink *GPU_builtin(eGPUBuiltin builtin) return link; } -static void gpu_material_use_library(GPUMaterial *material, GPUMaterialLibrary *library) +static void gpu_material_use_library_with_dependencies(GSet *used_libraries, + GPUMaterialLibrary *library) { - GSet *used_libraries = gpu_material_used_libraries(material); - if (BLI_gset_add(used_libraries, library->code)) { for (int i = 0; library->dependencies[i]; i++) { - BLI_gset_add(used_libraries, library->dependencies[i]); + gpu_material_use_library_with_dependencies(used_libraries, library->dependencies[i]); } } } +static void gpu_material_use_library(GPUMaterial *material, GPUMaterialLibrary *library) +{ + GSet *used_libraries = gpu_material_used_libraries(material); + gpu_material_use_library_with_dependencies(used_libraries, library); +} + bool GPU_link(GPUMaterial *mat, const char *name, ...) { GPUNode *node; @@ -1971,9 +1976,13 @@ static char *code_generate_material_library(GPUMaterial *material, const char *f GSet *used_libraries = gpu_material_used_libraries(material); + /* Always include those because they may be needed by the execution function. */ + gpu_material_use_library_with_dependencies(used_libraries, + &gpu_shader_material_world_normals_library); + /* Add library code in order, for dependencies. */ - for (int i = 0; gpu_material_libraries[i].code; i++) { - GPUMaterialLibrary *library = &gpu_material_libraries[i]; + for (int i = 0; gpu_material_libraries[i]; i++) { + GPUMaterialLibrary *library = gpu_material_libraries[i]; if (BLI_gset_haskey(used_libraries, library->code)) { BLI_dynstr_append(ds, library->code); } diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h index 7160a56a60e..99a71094753 100644 --- a/source/blender/gpu/intern/gpu_material_library.h +++ b/source/blender/gpu/intern/gpu_material_library.h @@ -31,19 +31,627 @@ typedef struct GPUMaterialLibrary { char *code; - char *dependencies[8]; + struct GPUMaterialLibrary *dependencies[8]; } GPUMaterialLibrary; -extern char datatoc_gpu_shader_material_glsl[]; +extern char datatoc_gpu_shader_material_add_shader_glsl[]; +extern char datatoc_gpu_shader_material_ambient_occlusion_glsl[]; +extern char datatoc_gpu_shader_material_anisotropic_glsl[]; +extern char datatoc_gpu_shader_material_attribute_glsl[]; +extern char datatoc_gpu_shader_material_background_glsl[]; +extern char datatoc_gpu_shader_material_bevel_glsl[]; +extern char datatoc_gpu_shader_material_blackbody_glsl[]; +extern char datatoc_gpu_shader_material_bright_contrast_glsl[]; +extern char datatoc_gpu_shader_material_bump_glsl[]; +extern char datatoc_gpu_shader_material_camera_glsl[]; +extern char datatoc_gpu_shader_material_cell_noise_glsl[]; +extern char datatoc_gpu_shader_material_clamp_glsl[]; +extern char datatoc_gpu_shader_material_color_ramp_glsl[]; +extern char datatoc_gpu_shader_material_color_util_glsl[]; +extern char datatoc_gpu_shader_material_combine_hsv_glsl[]; +extern char datatoc_gpu_shader_material_combine_rgb_glsl[]; +extern char datatoc_gpu_shader_material_combine_xyz_glsl[]; +extern char datatoc_gpu_shader_material_diffuse_glsl[]; +extern char datatoc_gpu_shader_material_displacement_glsl[]; +extern char datatoc_gpu_shader_material_eevee_specular_glsl[]; +extern char datatoc_gpu_shader_material_emission_glsl[]; +extern char datatoc_gpu_shader_material_fractal_noise_glsl[]; +extern char datatoc_gpu_shader_material_fresnel_glsl[]; +extern char datatoc_gpu_shader_material_gamma_glsl[]; +extern char datatoc_gpu_shader_material_geometry_glsl[]; +extern char datatoc_gpu_shader_material_glass_glsl[]; +extern char datatoc_gpu_shader_material_glossy_glsl[]; +extern char datatoc_gpu_shader_material_hair_info_glsl[]; extern char datatoc_gpu_shader_material_hash_glsl[]; -extern char datatoc_gpu_shader_material_magic_glsl[]; -extern char datatoc_gpu_shader_material_white_noise_glsl[]; +extern char datatoc_gpu_shader_material_holdout_glsl[]; +extern char datatoc_gpu_shader_material_hue_sat_val_glsl[]; +extern char datatoc_gpu_shader_material_invert_glsl[]; +extern char datatoc_gpu_shader_material_layer_weight_glsl[]; +extern char datatoc_gpu_shader_material_light_falloff_glsl[]; +extern char datatoc_gpu_shader_material_light_path_glsl[]; +extern char datatoc_gpu_shader_material_mapping_glsl[]; +extern char datatoc_gpu_shader_material_map_range_glsl[]; +extern char datatoc_gpu_shader_material_math_glsl[]; +extern char datatoc_gpu_shader_material_math_util_glsl[]; +extern char datatoc_gpu_shader_material_mix_rgb_glsl[]; +extern char datatoc_gpu_shader_material_mix_shader_glsl[]; +extern char datatoc_gpu_shader_material_noise_glsl[]; +extern char datatoc_gpu_shader_material_normal_glsl[]; +extern char datatoc_gpu_shader_material_normal_map_glsl[]; +extern char datatoc_gpu_shader_material_object_info_glsl[]; +extern char datatoc_gpu_shader_material_output_material_glsl[]; +extern char datatoc_gpu_shader_material_output_world_glsl[]; +extern char datatoc_gpu_shader_material_particle_info_glsl[]; +extern char datatoc_gpu_shader_material_principled_glsl[]; +extern char datatoc_gpu_shader_material_refraction_glsl[]; +extern char datatoc_gpu_shader_material_rgb_curves_glsl[]; +extern char datatoc_gpu_shader_material_rgb_to_bw_glsl[]; +extern char datatoc_gpu_shader_material_separate_hsv_glsl[]; +extern char datatoc_gpu_shader_material_separate_rgb_glsl[]; +extern char datatoc_gpu_shader_material_separate_xyz_glsl[]; +extern char datatoc_gpu_shader_material_set_glsl[]; +extern char datatoc_gpu_shader_material_shader_to_rgba_glsl[]; +extern char datatoc_gpu_shader_material_squeeze_glsl[]; +extern char datatoc_gpu_shader_material_subsurface_scattering_glsl[]; +extern char datatoc_gpu_shader_material_tangent_glsl[]; +extern char datatoc_gpu_shader_material_tex_brick_glsl[]; +extern char datatoc_gpu_shader_material_tex_checker_glsl[]; +extern char datatoc_gpu_shader_material_tex_environment_glsl[]; +extern char datatoc_gpu_shader_material_tex_gradient_glsl[]; +extern char datatoc_gpu_shader_material_tex_image_glsl[]; +extern char datatoc_gpu_shader_material_tex_magic_glsl[]; +extern char datatoc_gpu_shader_material_tex_musgrave_glsl[]; +extern char datatoc_gpu_shader_material_tex_noise_glsl[]; +extern char datatoc_gpu_shader_material_tex_sky_glsl[]; +extern char datatoc_gpu_shader_material_texture_coordinates_glsl[]; +extern char datatoc_gpu_shader_material_tex_voronoi_glsl[]; +extern char datatoc_gpu_shader_material_tex_wave_glsl[]; +extern char datatoc_gpu_shader_material_tex_white_noise_glsl[]; +extern char datatoc_gpu_shader_material_toon_glsl[]; +extern char datatoc_gpu_shader_material_translucent_glsl[]; +extern char datatoc_gpu_shader_material_transparent_glsl[]; +extern char datatoc_gpu_shader_material_uv_map_glsl[]; +extern char datatoc_gpu_shader_material_vector_curves_glsl[]; +extern char datatoc_gpu_shader_material_vector_displacement_glsl[]; +extern char datatoc_gpu_shader_material_vector_math_glsl[]; +extern char datatoc_gpu_shader_material_velvet_glsl[]; +extern char datatoc_gpu_shader_material_volume_absorption_glsl[]; +extern char datatoc_gpu_shader_material_volume_info_glsl[]; +extern char datatoc_gpu_shader_material_volume_principled_glsl[]; +extern char datatoc_gpu_shader_material_volume_scatter_glsl[]; +extern char datatoc_gpu_shader_material_wireframe_glsl[]; +extern char datatoc_gpu_shader_material_world_normals_glsl[]; -static GPUMaterialLibrary gpu_material_libraries[] = { - {datatoc_gpu_shader_material_hash_glsl, {NULL}}, - {datatoc_gpu_shader_material_glsl, {datatoc_gpu_shader_material_hash_glsl, NULL}}, - {datatoc_gpu_shader_material_magic_glsl, {NULL}}, - {datatoc_gpu_shader_material_white_noise_glsl, {datatoc_gpu_shader_material_hash_glsl, NULL}}, - {NULL, {NULL}}}; +static GPUMaterialLibrary gpu_shader_material_math_util_library = { + .code = datatoc_gpu_shader_material_math_util_glsl, + .dependencies = {NULL}, +}; +static GPUMaterialLibrary gpu_shader_material_color_util_library = { + .code = datatoc_gpu_shader_material_color_util_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_hash_library = { + .code = datatoc_gpu_shader_material_hash_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_noise_library = { + .code = datatoc_gpu_shader_material_noise_glsl, + .dependencies = {&gpu_shader_material_math_util_library, + &gpu_shader_material_hash_library, + NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_fractal_noise_library = { + .code = datatoc_gpu_shader_material_fractal_noise_glsl, + .dependencies = {&gpu_shader_material_noise_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_cell_noise_library = { + .code = datatoc_gpu_shader_material_cell_noise_glsl, + .dependencies = {&gpu_shader_material_math_util_library, + &gpu_shader_material_hash_library, + NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_add_shader_library = { + .code = datatoc_gpu_shader_material_add_shader_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_ambient_occlusion_library = { + .code = datatoc_gpu_shader_material_ambient_occlusion_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_glossy_library = { + .code = datatoc_gpu_shader_material_glossy_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_anisotropic_library = { + .code = datatoc_gpu_shader_material_anisotropic_glsl, + .dependencies = {&gpu_shader_material_glossy_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_attribute_library = { + .code = datatoc_gpu_shader_material_attribute_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_background_library = { + .code = datatoc_gpu_shader_material_background_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_bevel_library = { + .code = datatoc_gpu_shader_material_bevel_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_blackbody_library = { + .code = datatoc_gpu_shader_material_blackbody_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_bright_contrast_library = { + .code = datatoc_gpu_shader_material_bright_contrast_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_bump_library = { + .code = datatoc_gpu_shader_material_bump_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_camera_library = { + .code = datatoc_gpu_shader_material_camera_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_clamp_library = { + .code = datatoc_gpu_shader_material_clamp_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_color_ramp_library = { + .code = datatoc_gpu_shader_material_color_ramp_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_combine_hsv_library = { + .code = datatoc_gpu_shader_material_combine_hsv_glsl, + .dependencies = {&gpu_shader_material_color_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_combine_rgb_library = { + .code = datatoc_gpu_shader_material_combine_rgb_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_combine_xyz_library = { + .code = datatoc_gpu_shader_material_combine_xyz_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_diffuse_library = { + .code = datatoc_gpu_shader_material_diffuse_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_displacement_library = { + .code = datatoc_gpu_shader_material_displacement_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_eevee_specular_library = { + .code = datatoc_gpu_shader_material_eevee_specular_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_emission_library = { + .code = datatoc_gpu_shader_material_emission_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_fresnel_library = { + .code = datatoc_gpu_shader_material_fresnel_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_gamma_library = { + .code = datatoc_gpu_shader_material_gamma_glsl, + .dependencies = {&gpu_shader_material_math_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tangent_library = { + .code = datatoc_gpu_shader_material_tangent_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_geometry_library = { + .code = datatoc_gpu_shader_material_geometry_glsl, + .dependencies = {&gpu_shader_material_tangent_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_glass_library = { + .code = datatoc_gpu_shader_material_glass_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_hair_info_library = { + .code = datatoc_gpu_shader_material_hair_info_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_holdout_library = { + .code = datatoc_gpu_shader_material_holdout_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_hue_sat_val_library = { + .code = datatoc_gpu_shader_material_hue_sat_val_glsl, + .dependencies = {&gpu_shader_material_color_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_invert_library = { + .code = datatoc_gpu_shader_material_invert_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_layer_weight_library = { + .code = datatoc_gpu_shader_material_layer_weight_glsl, + .dependencies = {&gpu_shader_material_fresnel_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_light_falloff_library = { + .code = datatoc_gpu_shader_material_light_falloff_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_light_path_library = { + .code = datatoc_gpu_shader_material_light_path_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_mapping_library = { + .code = datatoc_gpu_shader_material_mapping_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_map_range_library = { + .code = datatoc_gpu_shader_material_map_range_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_math_library = { + .code = datatoc_gpu_shader_material_math_glsl, + .dependencies = {&gpu_shader_material_math_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_mix_rgb_library = { + .code = datatoc_gpu_shader_material_mix_rgb_glsl, + .dependencies = {&gpu_shader_material_color_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_mix_shader_library = { + .code = datatoc_gpu_shader_material_mix_shader_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_normal_library = { + .code = datatoc_gpu_shader_material_normal_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_normal_map_library = { + .code = datatoc_gpu_shader_material_normal_map_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_object_info_library = { + .code = datatoc_gpu_shader_material_object_info_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_output_material_library = { + .code = datatoc_gpu_shader_material_output_material_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_output_world_library = { + .code = datatoc_gpu_shader_material_output_world_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_particle_info_library = { + .code = datatoc_gpu_shader_material_particle_info_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_principled_library = { + .code = datatoc_gpu_shader_material_principled_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_refraction_library = { + .code = datatoc_gpu_shader_material_refraction_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_rgb_curves_library = { + .code = datatoc_gpu_shader_material_rgb_curves_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_rgb_to_bw_library = { + .code = datatoc_gpu_shader_material_rgb_to_bw_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_separate_hsv_library = { + .code = datatoc_gpu_shader_material_separate_hsv_glsl, + .dependencies = {&gpu_shader_material_color_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_separate_rgb_library = { + .code = datatoc_gpu_shader_material_separate_rgb_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_separate_xyz_library = { + .code = datatoc_gpu_shader_material_separate_xyz_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_set_library = { + .code = datatoc_gpu_shader_material_set_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_shader_to_rgba_library = { + .code = datatoc_gpu_shader_material_shader_to_rgba_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_squeeze_library = { + .code = datatoc_gpu_shader_material_squeeze_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_subsurface_scattering_library = { + .code = datatoc_gpu_shader_material_subsurface_scattering_glsl, + .dependencies = {&gpu_shader_material_diffuse_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_brick_library = { + .code = datatoc_gpu_shader_material_tex_brick_glsl, + .dependencies = {&gpu_shader_material_math_util_library, + &gpu_shader_material_hash_library, + NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_checker_library = { + .code = datatoc_gpu_shader_material_tex_checker_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_environment_library = { + .code = datatoc_gpu_shader_material_tex_environment_glsl, + .dependencies = {&gpu_shader_material_math_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_gradient_library = { + .code = datatoc_gpu_shader_material_tex_gradient_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_image_library = { + .code = datatoc_gpu_shader_material_tex_image_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_magic_library = { + .code = datatoc_gpu_shader_material_tex_magic_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_musgrave_library = { + .code = datatoc_gpu_shader_material_tex_musgrave_glsl, + .dependencies = {&gpu_shader_material_noise_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_noise_library = { + .code = datatoc_gpu_shader_material_tex_noise_glsl, + .dependencies = {&gpu_shader_material_fractal_noise_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_sky_library = { + .code = datatoc_gpu_shader_material_tex_sky_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_texture_coordinates_library = { + .code = datatoc_gpu_shader_material_texture_coordinates_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_voronoi_library = { + .code = datatoc_gpu_shader_material_tex_voronoi_glsl, + .dependencies = {&gpu_shader_material_math_util_library, + &gpu_shader_material_cell_noise_library, + NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_wave_library = { + .code = datatoc_gpu_shader_material_tex_wave_glsl, + .dependencies = {&gpu_shader_material_fractal_noise_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_tex_white_noise_library = { + .code = datatoc_gpu_shader_material_tex_white_noise_glsl, + .dependencies = {&gpu_shader_material_hash_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_toon_library = { + .code = datatoc_gpu_shader_material_toon_glsl, + .dependencies = {&gpu_shader_material_diffuse_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_translucent_library = { + .code = datatoc_gpu_shader_material_translucent_glsl, + .dependencies = {&gpu_shader_material_diffuse_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_transparent_library = { + .code = datatoc_gpu_shader_material_transparent_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_uv_map_library = { + .code = datatoc_gpu_shader_material_uv_map_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_vector_curves_library = { + .code = datatoc_gpu_shader_material_vector_curves_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_vector_displacement_library = { + .code = datatoc_gpu_shader_material_vector_displacement_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_vector_math_library = { + .code = datatoc_gpu_shader_material_vector_math_glsl, + .dependencies = {&gpu_shader_material_math_util_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_velvet_library = { + .code = datatoc_gpu_shader_material_velvet_glsl, + .dependencies = {&gpu_shader_material_diffuse_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_volume_absorption_library = { + .code = datatoc_gpu_shader_material_volume_absorption_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_volume_info_library = { + .code = datatoc_gpu_shader_material_volume_info_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_volume_principled_library = { + .code = datatoc_gpu_shader_material_volume_principled_glsl, + .dependencies = {&gpu_shader_material_blackbody_library, NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_volume_scatter_library = { + .code = datatoc_gpu_shader_material_volume_scatter_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_wireframe_library = { + .code = datatoc_gpu_shader_material_wireframe_glsl, + .dependencies = {NULL}, +}; + +static GPUMaterialLibrary gpu_shader_material_world_normals_library = { + .code = datatoc_gpu_shader_material_world_normals_glsl, + .dependencies = {&gpu_shader_material_texture_coordinates_library, NULL}, +}; + +static GPUMaterialLibrary *gpu_material_libraries[] = { + &gpu_shader_material_math_util_library, + &gpu_shader_material_color_util_library, + &gpu_shader_material_hash_library, + &gpu_shader_material_noise_library, + &gpu_shader_material_fractal_noise_library, + &gpu_shader_material_cell_noise_library, + &gpu_shader_material_add_shader_library, + &gpu_shader_material_ambient_occlusion_library, + &gpu_shader_material_glossy_library, + &gpu_shader_material_anisotropic_library, + &gpu_shader_material_attribute_library, + &gpu_shader_material_background_library, + &gpu_shader_material_bevel_library, + &gpu_shader_material_blackbody_library, + &gpu_shader_material_bright_contrast_library, + &gpu_shader_material_bump_library, + &gpu_shader_material_camera_library, + &gpu_shader_material_clamp_library, + &gpu_shader_material_color_ramp_library, + &gpu_shader_material_combine_hsv_library, + &gpu_shader_material_combine_rgb_library, + &gpu_shader_material_combine_xyz_library, + &gpu_shader_material_diffuse_library, + &gpu_shader_material_displacement_library, + &gpu_shader_material_eevee_specular_library, + &gpu_shader_material_emission_library, + &gpu_shader_material_fresnel_library, + &gpu_shader_material_gamma_library, + &gpu_shader_material_tangent_library, + &gpu_shader_material_geometry_library, + &gpu_shader_material_glass_library, + &gpu_shader_material_hair_info_library, + &gpu_shader_material_holdout_library, + &gpu_shader_material_hue_sat_val_library, + &gpu_shader_material_invert_library, + &gpu_shader_material_layer_weight_library, + &gpu_shader_material_light_falloff_library, + &gpu_shader_material_light_path_library, + &gpu_shader_material_mapping_library, + &gpu_shader_material_map_range_library, + &gpu_shader_material_math_library, + &gpu_shader_material_mix_rgb_library, + &gpu_shader_material_mix_shader_library, + &gpu_shader_material_normal_library, + &gpu_shader_material_normal_map_library, + &gpu_shader_material_object_info_library, + &gpu_shader_material_output_material_library, + &gpu_shader_material_output_world_library, + &gpu_shader_material_particle_info_library, + &gpu_shader_material_principled_library, + &gpu_shader_material_refraction_library, + &gpu_shader_material_rgb_curves_library, + &gpu_shader_material_rgb_to_bw_library, + &gpu_shader_material_separate_hsv_library, + &gpu_shader_material_separate_rgb_library, + &gpu_shader_material_separate_xyz_library, + &gpu_shader_material_set_library, + &gpu_shader_material_shader_to_rgba_library, + &gpu_shader_material_squeeze_library, + &gpu_shader_material_subsurface_scattering_library, + &gpu_shader_material_tex_brick_library, + &gpu_shader_material_tex_checker_library, + &gpu_shader_material_tex_environment_library, + &gpu_shader_material_tex_gradient_library, + &gpu_shader_material_tex_image_library, + &gpu_shader_material_tex_magic_library, + &gpu_shader_material_tex_musgrave_library, + &gpu_shader_material_tex_noise_library, + &gpu_shader_material_tex_sky_library, + &gpu_shader_material_texture_coordinates_library, + &gpu_shader_material_tex_voronoi_library, + &gpu_shader_material_tex_wave_library, + &gpu_shader_material_tex_white_noise_library, + &gpu_shader_material_toon_library, + &gpu_shader_material_translucent_library, + &gpu_shader_material_transparent_library, + &gpu_shader_material_uv_map_library, + &gpu_shader_material_vector_curves_library, + &gpu_shader_material_vector_displacement_library, + &gpu_shader_material_vector_math_library, + &gpu_shader_material_velvet_library, + &gpu_shader_material_volume_absorption_library, + &gpu_shader_material_volume_info_library, + &gpu_shader_material_volume_principled_library, + &gpu_shader_material_volume_scatter_library, + &gpu_shader_material_wireframe_library, + &gpu_shader_material_world_normals_library, + NULL}; #endif diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl deleted file mode 100644 index 6f5d9b92b8e..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ /dev/null @@ -1,3583 +0,0 @@ - -/* Converters */ - -float convert_rgba_to_float(vec4 color) -{ - return dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); -} - -float exp_blender(float f) -{ - return pow(2.71828182846, f); -} - -float compatible_pow(float x, float y) -{ - if (y == 0.0) { /* x^0 -> 1, including 0^0 */ - return 1.0; - } - - /* glsl pow doesn't accept negative x */ - if (x < 0.0) { - if (mod(-y, 2.0) == 0.0) { - return pow(-x, y); - } - else { - return -pow(-x, y); - } - } - else if (x == 0.0) { - return 0.0; - } - - return pow(x, y); -} - -void rgb_to_hsv(vec4 rgb, out vec4 outcol) -{ - float cmax, cmin, h, s, v, cdelta; - vec3 c; - - cmax = max(rgb[0], max(rgb[1], rgb[2])); - cmin = min(rgb[0], min(rgb[1], rgb[2])); - cdelta = cmax - cmin; - - v = cmax; - if (cmax != 0.0) { - s = cdelta / cmax; - } - else { - s = 0.0; - h = 0.0; - } - - if (s == 0.0) { - h = 0.0; - } - else { - c = (vec3(cmax) - rgb.xyz) / cdelta; - - if (rgb.x == cmax) { - h = c[2] - c[1]; - } - else if (rgb.y == cmax) { - h = 2.0 + c[0] - c[2]; - } - else { - h = 4.0 + c[1] - c[0]; - } - - h /= 6.0; - - if (h < 0.0) { - h += 1.0; - } - } - - outcol = vec4(h, s, v, rgb.w); -} - -void hsv_to_rgb(vec4 hsv, out vec4 outcol) -{ - float i, f, p, q, t, h, s, v; - vec3 rgb; - - h = hsv[0]; - s = hsv[1]; - v = hsv[2]; - - if (s == 0.0) { - rgb = vec3(v, v, v); - } - else { - if (h == 1.0) { - h = 0.0; - } - - h *= 6.0; - i = floor(h); - f = h - i; - rgb = vec3(f, f, f); - p = v * (1.0 - s); - q = v * (1.0 - (s * f)); - t = v * (1.0 - (s * (1.0 - f))); - - if (i == 0.0) { - rgb = vec3(v, t, p); - } - else if (i == 1.0) { - rgb = vec3(q, v, p); - } - else if (i == 2.0) { - rgb = vec3(p, v, t); - } - else if (i == 3.0) { - rgb = vec3(p, q, v); - } - else if (i == 4.0) { - rgb = vec3(t, p, v); - } - else { - rgb = vec3(v, p, q); - } - } - - outcol = vec4(rgb, hsv.w); -} - -void color_to_normal_new_shading(vec3 color, out vec3 normal) -{ - normal = vec3(2.0) * color - vec3(1.0); -} - -void color_to_blender_normal_new_shading(vec3 color, out vec3 normal) -{ - normal = vec3(2.0, -2.0, -2.0) * color - vec3(1.0); -} - -#ifndef M_PI -# define M_PI 3.14159265358979323846 -#endif -#ifndef M_1_PI -# define M_1_PI 0.318309886183790671538 -#endif - -/*********** SHADER NODES ***************/ - -void particle_info(vec4 sprops, - vec4 loc, - vec3 vel, - vec3 avel, - out float index, - out float random, - out float age, - out float life_time, - out vec3 location, - out float size, - out vec3 velocity, - out vec3 angular_velocity) -{ - index = sprops.x; - random = loc.w; - age = sprops.y; - life_time = sprops.z; - size = sprops.w; - - location = loc.xyz; - velocity = vel; - angular_velocity = avel; -} - -void vect_normalize(vec3 vin, out vec3 vout) -{ - vout = normalize(vin); -} - -void direction_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) -{ - vout = (mat * vec4(vin, 0.0)).xyz; -} - -void normal_transform_transposed_m4v3(vec3 vin, mat4 mat, out vec3 vout) -{ - vout = transpose(mat3(mat)) * vin; -} - -void point_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) -{ - vout = (mat * vec4(vin, 1.0)).xyz; -} - -void point_texco_remap_square(vec3 vin, out vec3 vout) -{ - vout = vin * 2.0 - 1.0; -} - -void point_texco_clamp(vec3 vin, sampler2D ima, out vec3 vout) -{ - vec2 half_texel_size = 0.5 / vec2(textureSize(ima, 0).xy); - vout = clamp(vin, half_texel_size.xyy, 1.0 - half_texel_size.xyy); -} - -void point_map_to_sphere(vec3 vin, out vec3 vout) -{ - float len = length(vin); - float v, u; - if (len > 0.0) { - if (vin.x == 0.0 && vin.y == 0.0) { - u = 0.0; - } - else { - u = (1.0 - atan(vin.x, vin.y) / M_PI) / 2.0; - } - - v = 1.0 - acos(vin.z / len) / M_PI; - } - else { - v = u = 0.0; - } - - vout = vec3(u, v, 0.0); -} - -void point_map_to_tube(vec3 vin, out vec3 vout) -{ - float u, v; - v = (vin.z + 1.0) * 0.5; - float len = sqrt(vin.x * vin.x + vin.y * vin[1]); - if (len > 0.0) { - u = (1.0 - (atan(vin.x / len, vin.y / len) / M_PI)) * 0.5; - } - else { - v = u = 0.0; - } - - vout = vec3(u, v, 0.0); -} - -void mapping( - vec3 vec, vec4 m0, vec4 m1, vec4 m2, vec4 m3, vec3 minvec, vec3 maxvec, out vec3 outvec) -{ - mat4 mat = mat4(m0, m1, m2, m3); - outvec = (mat * vec4(vec, 1.0)).xyz; - outvec = clamp(outvec, minvec, maxvec); -} - -void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist) -{ - outdepth = abs(co.z); - outdist = length(co); - outview = normalize(co); -} - -void math_add(float a, float b, out float result) -{ - result = a + b; -} - -void math_subtract(float a, float b, out float result) -{ - result = a - b; -} - -void math_multiply(float a, float b, out float result) -{ - result = a * b; -} - -void math_divide(float a, float b, out float result) -{ - result = (b != 0.0) ? a / b : 0.0; -} - -void math_power(float a, float b, out float result) -{ - if (a >= 0.0) { - result = compatible_pow(a, b); - } - else { - float fraction = mod(abs(b), 1.0); - if (fraction > 0.999 || fraction < 0.001) { - result = compatible_pow(a, floor(b + 0.5)); - } - else { - result = 0.0; - } - } -} - -void math_logarithm(float a, float b, out float result) -{ - result = (a > 0.0 && b > 0.0) ? log2(a) / log2(b) : 0.0; -} - -void math_sqrt(float a, float b, out float result) -{ - result = (a > 0.0) ? sqrt(a) : 0.0; -} - -void math_absolute(float a, float b, out float result) -{ - result = abs(a); -} - -void math_minimum(float a, float b, out float result) -{ - result = min(a, b); -} - -void math_maximum(float a, float b, out float result) -{ - result = max(a, b); -} - -void math_less_than(float a, float b, out float result) -{ - result = (a < b) ? 1.0 : 0.0; -} - -void math_greater_than(float a, float b, out float result) -{ - result = (a > b) ? 1.0 : 0.0; -} - -void math_round(float a, float b, out float result) -{ - result = floor(a + 0.5); -} - -void math_floor(float a, float b, out float result) -{ - result = floor(a); -} - -void math_ceil(float a, float b, out float result) -{ - result = ceil(a); -} - -void math_fraction(float a, float b, out float result) -{ - result = a - floor(a); -} - -/* Change sign to match C convention. mod in GLSL will take absolute for negative numbers. - * See https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/mod.xhtml - */ -void math_modulo(float a, float b, out float result) -{ - result = (b != 0.0 && a != b) ? sign(a) * mod(abs(a), b) : 0.0; -} - -void math_sine(float a, float b, out float result) -{ - result = sin(a); -} - -void math_cosine(float a, float b, out float result) -{ - result = cos(a); -} - -void math_tangent(float a, float b, out float result) -{ - result = tan(a); -} - -void math_arcsine(float a, float b, out float result) -{ - result = (a <= 1.0 && a >= -1.0) ? asin(a) : 0.0; -} - -void math_arccosine(float a, float b, out float result) -{ - result = (a <= 1.0 && a >= -1.0) ? acos(a) : 0.0; -} - -void math_arctangent(float a, float b, out float result) -{ - result = atan(a); -} - -void math_arctan2(float a, float b, out float result) -{ - result = atan(a, b); -} - -void squeeze(float val, float width, float center, out float outval) -{ - outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width))); -} - -void map_range( - float value, float fromMin, float fromMax, float toMin, float toMax, out float result) -{ - if (fromMax != fromMin) { - result = toMin + ((value - fromMin) / (fromMax - fromMin)) * (toMax - toMin); - } - else { - result = 0.0; - } -} - -vec3 safe_divide(vec3 a, vec3 b) -{ - return vec3((b.x != 0.0) ? a.x / b.x : 0.0, - (b.y != 0.0) ? a.y / b.y : 0.0, - (b.z != 0.0) ? a.z / b.z : 0.0); -} - -void vector_math_add(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = a + b; -} - -void vector_math_subtract(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = a - b; -} - -void vector_math_multiply(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = a * b; -} - -void vector_math_divide(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = safe_divide(a, b); -} - -void vector_math_cross(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = cross(a, b); -} - -void vector_math_project(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - float lenSquared = dot(b, b); - outVector = (lenSquared != 0.0) ? (dot(a, b) / lenSquared) * b : vec3(0.0); -} - -void vector_math_reflect(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = reflect(a, normalize(b)); -} - -void vector_math_dot(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outValue = dot(a, b); -} - -void vector_math_distance(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outValue = distance(a, b); -} - -void vector_math_length(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outValue = length(a); -} - -void vector_math_scale(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = a * scale; -} - -void vector_math_normalize(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = normalize(a); -} - -void vector_math_snap(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = floor(safe_divide(a, b)) * b; -} - -void vector_math_floor(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = floor(a); -} - -void vector_math_ceil(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = ceil(a); -} - -void vector_math_modulo(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - math_modulo(a.x, b.x, outVector.x); - math_modulo(a.y, b.y, outVector.y); - math_modulo(a.z, b.z, outVector.z); -} - -void vector_math_fraction(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = fract(a); -} - -void vector_math_absolute(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = abs(a); -} - -void vector_math_minimum(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = min(a, b); -} - -void vector_math_maximum(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) -{ - outVector = max(a, b); -} - -void vector_math_mix(float strength, vec3 a, vec3 b, out vec3 outVector) -{ - outVector = strength * a + (1 - strength) * b; -} - -void vec_math_negate(vec3 v, out vec3 outv) -{ - outv = -v; -} - -void invert_z(vec3 v, out vec3 outv) -{ - v.z = -v.z; - outv = v; -} - -void normal_new_shading(vec3 nor, vec3 dir, out vec3 outnor, out float outdot) -{ - outnor = dir; - outdot = dot(normalize(nor), dir); -} - -void curves_vec(float fac, vec3 vec, sampler1DArray curvemap, float layer, out vec3 outvec) -{ - vec4 co = vec4(vec * 0.5 + 0.5, layer); - outvec.x = texture(curvemap, co.xw).x; - outvec.y = texture(curvemap, co.yw).y; - outvec.z = texture(curvemap, co.zw).z; - outvec = mix(vec, outvec, fac); -} - -/* ext is vec4(in_x, in_dy, out_x, out_dy). */ -float curve_extrapolate(float x, float y, vec4 ext) -{ - if (x < 0.0) { - return y + x * ext.y; - } - else if (x > 1.0) { - return y + (x - 1.0) * ext.w; - } - else { - return y; - } -} - -#define RANGE_RESCALE(x, min, range) ((x - min) * range) - -void curves_rgb(float fac, - vec4 col, - sampler1DArray curvemap, - float layer, - vec4 range, - vec4 ext_r, - vec4 ext_g, - vec4 ext_b, - vec4 ext_a, - out vec4 outcol) -{ - vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); - vec3 samp; - samp.r = texture(curvemap, co.xw).a; - samp.g = texture(curvemap, co.yw).a; - samp.b = texture(curvemap, co.zw).a; - - samp.r = curve_extrapolate(co.x, samp.r, ext_a); - samp.g = curve_extrapolate(co.y, samp.g, ext_a); - samp.b = curve_extrapolate(co.z, samp.b, ext_a); - - vec3 rgb_min = vec3(ext_r.x, ext_g.x, ext_b.x); - co.xyz = RANGE_RESCALE(samp.rgb, rgb_min, range.rgb); - - samp.r = texture(curvemap, co.xw).r; - samp.g = texture(curvemap, co.yw).g; - samp.b = texture(curvemap, co.zw).b; - - outcol.r = curve_extrapolate(co.x, samp.r, ext_r); - outcol.g = curve_extrapolate(co.y, samp.g, ext_g); - outcol.b = curve_extrapolate(co.z, samp.b, ext_b); - outcol.a = col.a; - - outcol = mix(col, outcol, fac); -} - -void curves_rgb_opti(float fac, - vec4 col, - sampler1DArray curvemap, - float layer, - vec4 range, - vec4 ext_a, - out vec4 outcol) -{ - vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); - vec3 samp; - samp.r = texture(curvemap, co.xw).a; - samp.g = texture(curvemap, co.yw).a; - samp.b = texture(curvemap, co.zw).a; - - outcol.r = curve_extrapolate(co.x, samp.r, ext_a); - outcol.g = curve_extrapolate(co.y, samp.g, ext_a); - outcol.b = curve_extrapolate(co.z, samp.b, ext_a); - outcol.a = col.a; - - outcol = mix(col, outcol, fac); -} - -void set_value(float val, out float outval) -{ - outval = val; -} - -void set_rgb(vec3 col, out vec3 outcol) -{ - outcol = col; -} - -void set_rgba(vec4 col, out vec4 outcol) -{ - outcol = col; -} - -void set_value_zero(out float outval) -{ - outval = 0.0; -} - -void set_value_one(out float outval) -{ - outval = 1.0; -} - -void set_rgb_zero(out vec3 outval) -{ - outval = vec3(0.0); -} - -void set_rgb_one(out vec3 outval) -{ - outval = vec3(1.0); -} - -void set_rgba_zero(out vec4 outval) -{ - outval = vec4(0.0); -} - -void set_rgba_one(out vec4 outval) -{ - outval = vec4(1.0); -} - -void brightness_contrast(vec4 col, float brightness, float contrast, out vec4 outcol) -{ - float a = 1.0 + contrast; - float b = brightness - contrast * 0.5; - - outcol.r = max(a * col.r + b, 0.0); - outcol.g = max(a * col.g + b, 0.0); - outcol.b = max(a * col.b + b, 0.0); - outcol.a = col.a; -} - -void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col2, fac); - outcol.a = col1.a; -} - -void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 + col2, fac); - outcol.a = col1.a; -} - -void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 * col2, fac); - outcol.a = col1.a; -} - -void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = vec4(1.0) - (vec4(facm) + fac * (vec4(1.0) - col2)) * (vec4(1.0) - col1); - outcol.a = col1.a; -} - -void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - if (outcol.r < 0.5) { - outcol.r *= facm + 2.0 * fac * col2.r; - } - else { - outcol.r = 1.0 - (facm + 2.0 * fac * (1.0 - col2.r)) * (1.0 - outcol.r); - } - - if (outcol.g < 0.5) { - outcol.g *= facm + 2.0 * fac * col2.g; - } - else { - outcol.g = 1.0 - (facm + 2.0 * fac * (1.0 - col2.g)) * (1.0 - outcol.g); - } - - if (outcol.b < 0.5) { - outcol.b *= facm + 2.0 * fac * col2.b; - } - else { - outcol.b = 1.0 - (facm + 2.0 * fac * (1.0 - col2.b)) * (1.0 - outcol.b); - } -} - -void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 - col2, fac); - outcol.a = col1.a; -} - -void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - if (col2.r != 0.0) { - outcol.r = facm * outcol.r + fac * outcol.r / col2.r; - } - if (col2.g != 0.0) { - outcol.g = facm * outcol.g + fac * outcol.g / col2.g; - } - if (col2.b != 0.0) { - outcol.b = facm * outcol.b + fac * outcol.b / col2.b; - } -} - -void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, abs(col1 - col2), fac); - outcol.a = col1.a; -} - -void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol.rgb = min(col1.rgb, col2.rgb * fac); - outcol.a = col1.a; -} - -void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol.rgb = max(col1.rgb, col2.rgb * fac); - outcol.a = col1.a; -} - -void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = col1; - - if (outcol.r != 0.0) { - float tmp = 1.0 - fac * col2.r; - if (tmp <= 0.0) { - outcol.r = 1.0; - } - else if ((tmp = outcol.r / tmp) > 1.0) { - outcol.r = 1.0; - } - else { - outcol.r = tmp; - } - } - if (outcol.g != 0.0) { - float tmp = 1.0 - fac * col2.g; - if (tmp <= 0.0) { - outcol.g = 1.0; - } - else if ((tmp = outcol.g / tmp) > 1.0) { - outcol.g = 1.0; - } - else { - outcol.g = tmp; - } - } - if (outcol.b != 0.0) { - float tmp = 1.0 - fac * col2.b; - if (tmp <= 0.0) { - outcol.b = 1.0; - } - else if ((tmp = outcol.b / tmp) > 1.0) { - outcol.b = 1.0; - } - else { - outcol.b = tmp; - } - } -} - -void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float tmp, facm = 1.0 - fac; - - outcol = col1; - - tmp = facm + fac * col2.r; - if (tmp <= 0.0) { - outcol.r = 0.0; - } - else if ((tmp = (1.0 - (1.0 - outcol.r) / tmp)) < 0.0) { - outcol.r = 0.0; - } - else if (tmp > 1.0) { - outcol.r = 1.0; - } - else { - outcol.r = tmp; - } - - tmp = facm + fac * col2.g; - if (tmp <= 0.0) { - outcol.g = 0.0; - } - else if ((tmp = (1.0 - (1.0 - outcol.g) / tmp)) < 0.0) { - outcol.g = 0.0; - } - else if (tmp > 1.0) { - outcol.g = 1.0; - } - else { - outcol.g = tmp; - } - - tmp = facm + fac * col2.b; - if (tmp <= 0.0) { - outcol.b = 0.0; - } - else if ((tmp = (1.0 - (1.0 - outcol.b) / tmp)) < 0.0) { - outcol.b = 0.0; - } - else if (tmp > 1.0) { - outcol.b = 1.0; - } - else { - outcol.b = tmp; - } -} - -void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - vec4 hsv, hsv2, tmp; - rgb_to_hsv(col2, hsv2); - - if (hsv2.y != 0.0) { - rgb_to_hsv(outcol, hsv); - hsv.x = hsv2.x; - hsv_to_rgb(hsv, tmp); - - outcol = mix(outcol, tmp, fac); - outcol.a = col1.a; - } -} - -void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - vec4 hsv, hsv2; - rgb_to_hsv(outcol, hsv); - - if (hsv.y != 0.0) { - rgb_to_hsv(col2, hsv2); - - hsv.y = facm * hsv.y + fac * hsv2.y; - hsv_to_rgb(hsv, outcol); - } -} - -void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - vec4 hsv, hsv2; - rgb_to_hsv(col1, hsv); - rgb_to_hsv(col2, hsv2); - - hsv.z = facm * hsv.z + fac * hsv2.z; - hsv_to_rgb(hsv, outcol); -} - -void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - vec4 hsv, hsv2, tmp; - rgb_to_hsv(col2, hsv2); - - if (hsv2.y != 0.0) { - rgb_to_hsv(outcol, hsv); - hsv.x = hsv2.x; - hsv.y = hsv2.y; - hsv_to_rgb(hsv, tmp); - - outcol = mix(outcol, tmp, fac); - outcol.a = col1.a; - } -} - -void mix_soft(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - vec4 one = vec4(1.0); - vec4 scr = one - (one - col2) * (one - col1); - outcol = facm * col1 + fac * ((one - col1) * col2 * col1 + col1 * scr); -} - -void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - - outcol = col1 + fac * (2.0 * (col2 - vec4(0.5))); -} - -void valtorgb_opti_constant( - float fac, float edge, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) -{ - outcol = (fac > edge) ? color2 : color1; - outalpha = outcol.a; -} - -void valtorgb_opti_linear( - float fac, vec2 mulbias, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) -{ - fac = clamp(fac * mulbias.x + mulbias.y, 0.0, 1.0); - outcol = mix(color1, color2, fac); - outalpha = outcol.a; -} - -void valtorgb(float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) -{ - outcol = texture(colormap, vec2(fac, layer)); - outalpha = outcol.a; -} - -void valtorgb_nearest( - float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = texelFetch(colormap, ivec2(fac * (textureSize(colormap, 0).x - 1), layer), 0); - outalpha = outcol.a; -} - -void rgbtobw(vec4 color, out float outval) -{ - vec3 factors = vec3(0.2126, 0.7152, 0.0722); - outval = dot(color.rgb, factors); -} - -void invert(float fac, vec4 col, out vec4 outcol) -{ - outcol.xyz = mix(col.xyz, vec3(1.0) - col.xyz, fac); - outcol.w = col.w; -} - -void clamp_vec3(vec3 vec, vec3 min, vec3 max, out vec3 out_vec) -{ - out_vec = clamp(vec, min, max); -} - -void clamp_value(float value, float min, float max, out float result) -{ - result = clamp(value, min, max); -} - -void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol) -{ - vec4 hsv; - - rgb_to_hsv(col, hsv); - - hsv[0] = fract(hsv[0] + hue + 0.5); - hsv[1] = clamp(hsv[1] * sat, 0.0, 1.0); - hsv[2] = hsv[2] * value; - - hsv_to_rgb(hsv, outcol); - - outcol = mix(col, outcol, fac); -} - -void separate_rgb(vec4 col, out float r, out float g, out float b) -{ - r = col.r; - g = col.g; - b = col.b; -} - -void combine_rgb(float r, float g, float b, out vec4 col) -{ - col = vec4(r, g, b, 1.0); -} - -void separate_xyz(vec3 vec, out float x, out float y, out float z) -{ - x = vec.r; - y = vec.g; - z = vec.b; -} - -void combine_xyz(float x, float y, float z, out vec3 vec) -{ - vec = vec3(x, y, z); -} - -void separate_hsv(vec4 col, out float h, out float s, out float v) -{ - vec4 hsv; - - rgb_to_hsv(col, hsv); - h = hsv[0]; - s = hsv[1]; - v = hsv[2]; -} - -void combine_hsv(float h, float s, float v, out vec4 col) -{ - hsv_to_rgb(vec4(h, s, v, 1.0), col); -} - -void output_node(vec4 rgb, float alpha, out vec4 outrgb) -{ - outrgb = vec4(rgb.rgb, alpha); -} - -/*********** TEXTURES ***************/ - -void texco_norm(vec3 normal, out vec3 outnormal) -{ - /* corresponds to shi->orn, which is negated so cancels - out blender normal negation */ - outnormal = normalize(normal); -} - -vec3 mtex_2d_mapping(vec3 vec) -{ - return vec3(vec.xy * 0.5 + vec2(0.5), vec.z); -} - -/** helper method to extract the upper left 3x3 matrix from a 4x4 matrix */ -mat3 to_mat3(mat4 m4) -{ - mat3 m3; - m3[0] = m4[0].xyz; - m3[1] = m4[1].xyz; - m3[2] = m4[2].xyz; - return m3; -} - -/*********** NEW SHADER UTILITIES **************/ - -float fresnel_dielectric_0(float eta) -{ - /* compute fresnel reflactance at normal incidence => cosi = 1.0 */ - float A = (eta - 1.0) / (eta + 1.0); - - return A * A; -} - -float fresnel_dielectric_cos(float cosi, float eta) -{ - /* compute fresnel reflectance without explicitly computing - * the refracted direction */ - float c = abs(cosi); - float g = eta * eta - 1.0 + c * c; - float result; - - if (g > 0.0) { - g = sqrt(g); - float A = (g - c) / (g + c); - float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0); - result = 0.5 * A * A * (1.0 + B * B); - } - else { - result = 1.0; /* TIR (no refracted component) */ - } - - return result; -} - -float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) -{ - /* compute fresnel reflectance without explicitly computing - * the refracted direction */ - return fresnel_dielectric_cos(dot(Incoming, Normal), eta); -} - -float hypot(float x, float y) -{ - return sqrt(x * x + y * y); -} - -void generated_from_orco(vec3 orco, out vec3 generated) -{ -#ifdef VOLUMETRICS -# ifdef MESH_SHADER - generated = volumeObjectLocalCoord; -# else - generated = worldPosition; -# endif -#else - generated = orco; -#endif -} - -int floor_to_int(float x) -{ - return int(floor(x)); -} - -int quick_floor(float x) -{ - return int(x) - ((x < 0) ? 1 : 0); -} - -float integer_noise(int n) -{ - int nn; - n = (n + 1013) & 0x7fffffff; - n = (n >> 13) ^ n; - nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; - return 0.5 * (float(nn) / 1073741824.0); -} - -/* Cell Noise */ - -float bits_to_01(uint bits) -{ - return (float(bits) / 4294967295.0); -} - -float cellnoise(vec3 p) -{ - int ix = quick_floor(p.x); - int iy = quick_floor(p.y); - int iz = quick_floor(p.z); - - return hash_uint3_to_float(uint(ix), uint(iy), uint(iz)); -} - -vec3 cellnoise_color(vec3 p) -{ - float r = cellnoise(p.xyz); - float g = cellnoise(p.yxz); - float b = cellnoise(p.yzx); - - return vec3(r, g, b); -} - -float floorfrac(float x, out int i) -{ - float x_floor = floor(x); - i = int(x_floor); - return x - x_floor; -} - -/* bsdfs */ - -vec3 tint_from_color(vec3 color) -{ - float lum = dot(color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */ - return (lum > 0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */ -} - -void convert_metallic_to_specular_tinted(vec3 basecol, - vec3 basecol_tint, - float metallic, - float specular_fac, - float specular_tint, - out vec3 diffuse, - out vec3 f0) -{ - vec3 tmp_col = mix(vec3(1.0), basecol_tint, specular_tint); - f0 = mix((0.08 * specular_fac) * tmp_col, basecol, metallic); - diffuse = basecol * (1.0 - metallic); -} - -vec3 principled_sheen(float NV, vec3 basecol_tint, float sheen_tint) -{ - float f = 1.0 - NV; - /* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps, - * therefore we need to clamp value. */ - f = clamp(f, 0.0, 1.0); - /* Empirical approximation (manual curve fitting). Can be refined. */ - float sheen = f * f * f * 0.077 + f * 0.01 + 0.00026; - return sheen * mix(vec3(1.0), basecol_tint, sheen_tint); -} - -#ifndef VOLUMETRICS -void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) -{ - N = normalize(N); - result = CLOSURE_DEFAULT; - eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance); - closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result); - result.radiance *= color.rgb; -} - -void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result) -{ - N = normalize(N); - vec3 out_spec, ssr_spec; - eevee_closure_glossy(N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec); - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = out_spec * color.rgb; - closure_load_ssr_data(ssr_spec * color.rgb, roughness, N, viewCameraVec, int(ssr_id), result); -} - -void node_bsdf_anisotropic(vec4 color, - float roughness, - float anisotropy, - float rotation, - vec3 N, - vec3 T, - out Closure result) -{ - node_bsdf_glossy(color, roughness, N, -1, result); -} - -void node_bsdf_glass( - vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result) -{ - N = normalize(N); - vec3 out_spec, out_refr, ssr_spec; - vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : - color.rgb; /* Simulate 2 transmission event */ - eevee_closure_glass( - N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); - out_refr *= refr_color; - out_spec *= color.rgb; - float fresnel = F_eta(ior, dot(N, cameraVec)); - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = mix(out_refr, out_spec, fresnel); - closure_load_ssr_data( - ssr_spec * color.rgb * fresnel, roughness, N, viewCameraVec, int(ssr_id), result); -} - -void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result) -{ - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_bsdf_principled(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - N = normalize(N); - ior = max(ior, 1e-5); - metallic = saturate(metallic); - transmission = saturate(transmission); - float dielectric = 1.0 - metallic; - transmission *= dielectric; - sheen *= dielectric; - subsurface_color *= dielectric; - - vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec; - vec3 ctint = tint_from_color(base_color.rgb); - convert_metallic_to_specular_tinted( - base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); - - float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); - - /* Far from being accurate, but 2 glossy evaluation is too expensive. - * Most noticeable difference is at grazing angles since the bsdf lut - * f0 color interpolation is done on top of this interpolation. */ - vec3 f0_glass = mix(vec3(1.0), base_color.rgb, specular_tint); - float fresnel = F_eta(ior, NV); - vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel; - f0 = mix(f0, spec_col, transmission); - - vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic); - - vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); - - float sss_scalef = avg(sss_scale) * subsurface; - eevee_closure_principled(N, - mixed_ss_base_color, - f0, - f90, - int(ssr_id), - roughness, - CN, - clearcoat * 0.25, - clearcoat_roughness, - 1.0, - sss_scalef, - ior, - out_diff, - out_trans, - out_spec, - out_refr, - ssr_spec); - - vec3 refr_color = base_color.rgb; - refr_color *= (refractionDepth > 0.0) ? refr_color : - vec3(1.0); /* Simulate 2 transmission event */ - out_refr *= refr_color * (1.0 - fresnel) * transmission; - - result = CLOSURE_DEFAULT; - result.radiance = out_spec + out_refr; - result.radiance += out_diff * out_sheen; /* Coarse approx. */ - - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - - vec3 sss_radiance = (out_diff + out_trans) * alpha; -# ifndef USE_SSS - result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission); -# else -# ifdef USE_SSS_ALBEDO - vec3 sss_albedo = mixed_ss_base_color; -# else - sss_radiance *= mixed_ss_base_color; -# endif - sss_radiance *= (1.0 - transmission); - closure_load_sss_data(sss_scalef, - sss_radiance, -# ifdef USE_SSS_ALBEDO - sss_albedo, -# endif - int(sss_id), - result); -# endif /* USE_SSS */ - - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_principled_dielectric(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - N = normalize(N); - metallic = saturate(metallic); - float dielectric = 1.0 - metallic; - - vec3 diffuse, f0, out_diff, out_spec, ssr_spec; - vec3 ctint = tint_from_color(base_color.rgb); - convert_metallic_to_specular_tinted( - base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); - - float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); - - eevee_closure_default( - N, diffuse, f0, vec3(1.0), int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec); - - result = CLOSURE_DEFAULT; - result.radiance = out_spec + out_diff * (diffuse + out_sheen); - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_principled_metallic(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - N = normalize(N); - vec3 out_spec, ssr_spec; - - vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); - - eevee_closure_glossy(N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, out_spec, ssr_spec); - - result = CLOSURE_DEFAULT; - result.radiance = out_spec; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_principled_clearcoat(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - vec3 out_spec, ssr_spec; - N = normalize(N); - - vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); - - eevee_closure_clearcoat(N, - base_color.rgb, - f90, - int(ssr_id), - roughness, - CN, - clearcoat * 0.25, - clearcoat_roughness, - 1.0, - out_spec, - ssr_spec); - - result = CLOSURE_DEFAULT; - result.radiance = out_spec; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_principled_subsurface(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - metallic = saturate(metallic); - N = normalize(N); - - vec3 diffuse, f0, out_diff, out_spec, out_trans, ssr_spec; - vec3 ctint = tint_from_color(base_color.rgb); - convert_metallic_to_specular_tinted( - base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); - - subsurface_color = subsurface_color * (1.0 - metallic); - vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); - float sss_scalef = avg(sss_scale) * subsurface; - - float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); - - vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); - - eevee_closure_skin(N, - mixed_ss_base_color, - f0, - f90, - int(ssr_id), - roughness, - 1.0, - sss_scalef, - out_diff, - out_trans, - out_spec, - ssr_spec); - - result = CLOSURE_DEFAULT; - result.radiance = out_spec; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - - vec3 sss_radiance = (out_diff + out_trans) * alpha; -# ifndef USE_SSS - result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission); -# else -# ifdef USE_SSS_ALBEDO - vec3 sss_albedo = mixed_ss_base_color; -# else - sss_radiance *= mixed_ss_base_color; -# endif - sss_radiance *= (1.0 - transmission); - closure_load_sss_data(sss_scalef, - sss_radiance, -# ifdef USE_SSS_ALBEDO - sss_albedo, -# endif - int(sss_id), - result); -# endif /* USE_SSS */ - - result.radiance += out_diff * out_sheen; - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_principled_glass(vec4 base_color, - float subsurface, - vec3 subsurface_radius, - vec4 subsurface_color, - float metallic, - float specular, - float specular_tint, - float roughness, - float anisotropic, - float anisotropic_rotation, - float sheen, - float sheen_tint, - float clearcoat, - float clearcoat_roughness, - float ior, - float transmission, - float transmission_roughness, - vec4 emission, - float alpha, - vec3 N, - vec3 CN, - vec3 T, - vec3 I, - float ssr_id, - float sss_id, - vec3 sss_scale, - out Closure result) -{ - ior = max(ior, 1e-5); - N = normalize(N); - - vec3 f0, out_spec, out_refr, ssr_spec; - f0 = mix(vec3(1.0), base_color.rgb, specular_tint); - - eevee_closure_glass( - N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); - - vec3 refr_color = base_color.rgb; - refr_color *= (refractionDepth > 0.0) ? refr_color : - vec3(1.0); /* Simulate 2 transmission events */ - out_refr *= refr_color; - - float fresnel = F_eta(ior, dot(N, cameraVec)); - vec3 spec_col = F_color_blend(ior, fresnel, f0); - out_spec *= spec_col; - ssr_spec *= spec_col * fresnel; - - result = CLOSURE_DEFAULT; - result.radiance = mix(out_refr, out_spec, fresnel); - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - result.radiance += emission.rgb; - result.radiance *= alpha; - result.transmittance = vec3(1.0 - alpha); -} - -void node_bsdf_translucent(vec4 color, vec3 N, out Closure result) -{ - node_bsdf_diffuse(color, 0.0, -N, result); -} - -void node_bsdf_transparent(vec4 color, out Closure result) -{ - result = CLOSURE_DEFAULT; - result.radiance = vec3(0.0); - result.transmittance = abs(color.rgb); -} - -void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result) -{ - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_subsurface_scattering(vec4 color, - float scale, - vec3 radius, - float sharpen, - float texture_blur, - vec3 N, - float sss_id, - out Closure result) -{ -# if defined(USE_SSS) - N = normalize(N); - vec3 out_diff, out_trans; - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result); - - eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans); - - vec3 sss_radiance = out_diff + out_trans; -# ifdef USE_SSS_ALBEDO - /* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */ - vec3 sss_albedo = mix(color.rgb, vec3(1.0), texture_blur); - sss_radiance *= mix(vec3(1.0), color.rgb, texture_blur); -# else - sss_radiance *= color.rgb; -# endif - closure_load_sss_data(scale, - sss_radiance, -# ifdef USE_SSS_ALBEDO - sss_albedo, -# endif - int(sss_id), - result); -# else - node_bsdf_diffuse(color, 0.0, N, result); -# endif -} - -void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result) -{ - N = normalize(N); - vec3 out_refr; - color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */ - eevee_closure_refraction(N, roughness, ior, out_refr); - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.radiance = out_refr * color.rgb; -} - -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); - result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal); - result_color = result_ao * color; -} - -void node_wireframe(float size, vec2 barycentric, vec3 barycentric_dist, out float fac) -{ - vec3 barys = barycentric.xyy; - barys.z = 1.0 - barycentric.x - barycentric.y; - - size *= 0.5; - vec3 s = step(-size, -barys * barycentric_dist); - - fac = max(s.x, max(s.y, s.z)); -} - -void node_wireframe_screenspace(float size, vec2 barycentric, out float fac) -{ - vec3 barys = barycentric.xyy; - barys.z = 1.0 - barycentric.x - barycentric.y; - - size *= (1.0 / 3.0); - vec3 dx = dFdx(barys); - vec3 dy = dFdy(barys); - vec3 deltas = sqrt(dx * dx + dy * dy); - - vec3 s = step(-deltas * size, -barys); - - fac = max(s.x, max(s.y, s.z)); -} - -#else /* VOLUMETRICS */ - -/* Stub all bsdf functions not compatible with volumetrics. */ -# define node_bsdf_diffuse -# define node_bsdf_glossy -# define node_bsdf_anisotropic -# define node_bsdf_glass -# define node_bsdf_toon -# define node_bsdf_principled -# define node_bsdf_principled_dielectric -# define node_bsdf_principled_metallic -# define node_bsdf_principled_clearcoat -# define node_bsdf_principled_subsurface -# define node_bsdf_principled_glass -# define node_bsdf_translucent -# define node_bsdf_transparent -# define node_bsdf_velvet -# define node_subsurface_scattering -# define node_bsdf_refraction -# define node_ambient_occlusion -# define node_wireframe -# define node_wireframe_screenspace - -#endif /* VOLUMETRICS */ - -/* emission */ - -void node_emission(vec4 color, float strength, vec3 vN, out Closure result) -{ - result = CLOSURE_DEFAULT; -#ifndef VOLUMETRICS - result.radiance = color.rgb * strength; - result.ssr_normal = normal_encode(vN, viewCameraVec); -#else - result.emission = color.rgb * strength; -#endif -} - -/* background */ - -void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec) -{ -#ifdef MESH_SHADER - worldvec = worldPosition; -#else - vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); - - vec3 co = co_homogenous.xyz / co_homogenous.w; -# if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) - worldvec = mat3(ViewMatrixInverse) * co; -# else - worldvec = mat3(ModelMatrixInverse) * (mat3(ViewMatrixInverse) * co); -# endif -#endif -} - -void node_background(vec4 color, float strength, out Closure result) -{ -#ifndef VOLUMETRICS - color *= strength; - result = CLOSURE_DEFAULT; - result.radiance = color.rgb; - result.transmittance = vec3(0.0); -#else - result = CLOSURE_DEFAULT; -#endif -} - -/* volumes */ - -void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result) -{ -#ifdef VOLUMETRICS - result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy); -#else - result = CLOSURE_DEFAULT; -#endif -} - -void node_volume_absorption(vec4 color, float density, out Closure result) -{ -#ifdef VOLUMETRICS - result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0); -#else - result = CLOSURE_DEFAULT; -#endif -} - -void node_blackbody(float temperature, sampler1DArray spectrummap, float layer, out vec4 color) -{ - if (temperature >= 12000.0) { - color = vec4(0.826270103, 0.994478524, 1.56626022, 1.0); - } - else if (temperature < 965.0) { - color = vec4(4.70366907, 0.0, 0.0, 1.0); - } - else { - float t = (temperature - 965.0) / (12000.0 - 965.0); - color = vec4(texture(spectrummap, vec2(t, layer)).rgb, 1.0); - } -} - -void node_volume_principled(vec4 color, - float density, - float anisotropy, - vec4 absorption_color, - float emission_strength, - vec4 emission_color, - float blackbody_intensity, - vec4 blackbody_tint, - float temperature, - float density_attribute, - vec4 color_attribute, - float temperature_attribute, - sampler1DArray spectrummap, - float layer, - out Closure result) -{ -#ifdef VOLUMETRICS - vec3 absorption_coeff = vec3(0.0); - vec3 scatter_coeff = vec3(0.0); - vec3 emission_coeff = vec3(0.0); - - /* Compute density. */ - density = max(density, 0.0); - - if (density > 1e-5) { - density = max(density * density_attribute, 0.0); - } - - if (density > 1e-5) { - /* Compute scattering and absorption coefficients. */ - vec3 scatter_color = color.rgb * color_attribute.rgb; - - scatter_coeff = scatter_color * density; - absorption_color.rgb = sqrt(max(absorption_color.rgb, 0.0)); - absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) * - density; - } - - /* Compute emission. */ - emission_strength = max(emission_strength, 0.0); - - if (emission_strength > 1e-5) { - emission_coeff += emission_strength * emission_color.rgb; - } - - if (blackbody_intensity > 1e-3) { - /* Add temperature from attribute. */ - float T = max(temperature * max(temperature_attribute, 0.0), 0.0); - - /* Stefan-Boltzman law. */ - float T2 = T * T; - float T4 = T2 * T2; - float sigma = 5.670373e-8 * 1e-6 / M_PI; - float intensity = sigma * mix(1.0, T4, blackbody_intensity); - - if (intensity > 1e-5) { - vec4 bb; - node_blackbody(T, spectrummap, layer, bb); - emission_coeff += bb.rgb * blackbody_tint.rgb * intensity; - } - } - - result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy); -#else - result = CLOSURE_DEFAULT; -#endif -} - -void node_holdout(out Closure result) -{ - result = CLOSURE_DEFAULT; -#ifndef VOLUMETRICS - result.holdout = 1.0; - result.flag = CLOSURE_HOLDOUT_FLAG; -#endif -} - -/* closures */ - -void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader) -{ - shader = closure_mix(shader1, shader2, fac); -} - -void node_add_shader(Closure shader1, Closure shader2, out Closure shader) -{ - shader = closure_add(shader1, shader2); -} - -/* fresnel */ - -void node_fresnel(float ior, vec3 N, vec3 I, out float result) -{ - N = normalize(N); - /* handle perspective/orthographic */ - vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - - float eta = max(ior, 0.00001); - result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta); -} - -/* layer_weight */ - -void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float facing) -{ - N = normalize(N); - - /* fresnel */ - float eta = max(1.0 - blend, 0.00001); - vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - - fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta); - - /* facing */ - facing = abs(dot(I_view, N)); - if (blend != 0.5) { - blend = clamp(blend, 0.0, 0.99999); - blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend); - facing = pow(facing, blend); - } - facing = 1.0 - facing; -} - -/* gamma */ - -void node_gamma(vec4 col, float gamma, out vec4 outcol) -{ - outcol = col; - - if (col.r > 0.0) { - outcol.r = compatible_pow(col.r, gamma); - } - if (col.g > 0.0) { - outcol.g = compatible_pow(col.g, gamma); - } - if (col.b > 0.0) { - outcol.b = compatible_pow(col.b, gamma); - } -} - -/* geometry */ - -void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) -{ -#if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; -#else - vec3 cos = vec3(0.0); -#endif - outvec = texture(tex, cos).aaa; - outcol = vec4(outvec, 1.0); - outf = avg(outvec); -} - -uniform vec3 volumeColor = vec3(1.0); - -void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) -{ -#if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; -#else - vec3 cos = vec3(0.0); -#endif - - vec4 value = texture(tex, cos).rgba; - /* Density is premultiplied for interpolation, divide it out here. */ - if (value.a > 1e-8) { - value.rgb /= value.a; - } - - outvec = value.rgb * volumeColor; - outcol = vec4(outvec, 1.0); - outf = avg(outvec); -} - -void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) -{ -#if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; -#else - vec3 cos = vec3(0.0); -#endif - outf = texture(tex, cos).r; - outvec = vec3(outf, outf, outf); - outcol = vec4(outf, outf, outf, 1.0); -} - -void node_attribute_volume_temperature( - sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf) -{ -#if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; -#else - vec3 cos = vec3(0.0); -#endif - float flame = texture(tex, cos).r; - - outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0; - outvec = vec3(outf, outf, outf); - outcol = vec4(outf, outf, outf, 1.0); -} - -void node_volume_info(sampler3D densitySampler, - sampler3D flameSampler, - vec2 temperature, - out vec4 outColor, - out float outDensity, - out float outFlame, - out float outTemprature) -{ -#if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 p = volumeObjectLocalCoord; -#else - vec3 p = vec3(0.0); -#endif - - vec4 density = texture(densitySampler, p); - outDensity = density.a; - - /* Density is premultiplied for interpolation, divide it out here. */ - if (density.a > 1e-8) { - density.rgb /= density.a; - } - outColor = vec4(density.rgb * volumeColor, 1.0); - - float flame = texture(flameSampler, p).r; - outFlame = flame; - - outTemprature = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0; -} - -void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf) -{ - outcol = vec4(attr, 1.0); - outvec = attr; - outf = avg(attr); -} - -void node_uvmap(vec3 attr_uv, out vec3 outvec) -{ - outvec = attr_uv; -} - -void tangent_orco_x(vec3 orco_in, out vec3 orco_out) -{ - orco_out = orco_in.xzy * vec3(0.0, -0.5, 0.5) + vec3(0.0, 0.25, -0.25); -} - -void tangent_orco_y(vec3 orco_in, out vec3 orco_out) -{ - orco_out = orco_in.zyx * vec3(-0.5, 0.0, 0.5) + vec3(0.25, 0.0, -0.25); -} - -void tangent_orco_z(vec3 orco_in, out vec3 orco_out) -{ - orco_out = orco_in.yxz * vec3(-0.5, 0.5, 0.0) + vec3(0.25, -0.25, 0.0); -} - -void node_tangentmap(vec4 attr_tangent, out vec3 tangent) -{ - tangent = normalize(attr_tangent.xyz); -} - -void node_tangent(vec3 N, vec3 orco, mat4 objmat, out vec3 T) -{ - T = (objmat * vec4(orco, 0.0)).xyz; - T = cross(N, normalize(cross(T, N))); -} - -void node_geometry(vec3 I, - vec3 N, - vec3 orco, - mat4 objmat, - mat4 toworld, - vec2 barycentric, - out vec3 position, - out vec3 normal, - out vec3 tangent, - out vec3 true_normal, - out vec3 incoming, - out vec3 parametric, - out float backfacing, - out float pointiness) -{ - /* handle perspective/orthographic */ - vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - incoming = -(toworld * vec4(I_view, 0.0)).xyz; - -#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) - position = -incoming; - true_normal = normal = incoming; - tangent = parametric = vec3(0.0); - vec3(0.0); - backfacing = 0.0; - pointiness = 0.0; -#else - - position = worldPosition; -# ifndef VOLUMETRICS - normal = normalize(N); - vec3 B = dFdx(worldPosition); - vec3 T = dFdy(worldPosition); - true_normal = normalize(cross(B, T)); -# else - normal = (toworld * vec4(N, 0.0)).xyz; - true_normal = normal; -# endif - tangent_orco_z(orco, orco); - node_tangent(N, orco, objmat, tangent); - - parametric = vec3(barycentric, 0.0); - backfacing = (gl_FrontFacing) ? 0.0 : 1.0; - pointiness = 0.5; -#endif -} - -void generated_texco(vec3 I, vec3 attr_orco, out vec3 generated) -{ - vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); - co.xyz = normalize(co.xyz); -#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) - generated = (ViewMatrixInverse * co).xyz; -#else - generated_from_orco(attr_orco, generated); -#endif -} - -void node_tex_coord(vec3 I, - vec3 wN, - mat4 obmatinv, - vec4 camerafac, - vec3 attr_orco, - vec3 attr_uv, - out vec3 generated, - out vec3 normal, - out vec3 uv, - out vec3 object, - out vec3 camera, - out vec3 window, - out vec3 reflection) -{ - generated = attr_orco; - normal = normalize(normal_world_to_object(wN)); - uv = attr_uv; - object = (obmatinv * (ViewMatrixInverse * vec4(I, 1.0))).xyz; - camera = vec3(I.xy, -I.z); - vec4 projvec = ProjectionMatrix * vec4(I, 1.0); - window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0); - reflection = -reflect(cameraVec, normalize(wN)); -} - -void node_tex_coord_background(vec3 I, - vec3 N, - mat4 obmatinv, - vec4 camerafac, - vec3 attr_orco, - vec3 attr_uv, - out vec3 generated, - out vec3 normal, - out vec3 uv, - out vec3 object, - out vec3 camera, - out vec3 window, - out vec3 reflection) -{ - vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); - - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); - - co = normalize(co); - - vec3 coords = (ViewMatrixInverse * co).xyz; - - generated = coords; - normal = -coords; - uv = vec3(attr_uv.xy, 0.0); - object = (obmatinv * vec4(coords, 1.0)).xyz; - - camera = vec3(co.xy, -co.z); - window = vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0); - - reflection = -coords; -} - -#if defined(WORLD_BACKGROUND) || (defined(PROBE_CAPTURE) && !defined(MESH_SHADER)) -# define node_tex_coord node_tex_coord_background -#endif - -/* textures */ - -float calc_gradient(vec3 p, int gradient_type) -{ - float x, y, z; - x = p.x; - y = p.y; - z = p.z; - if (gradient_type == 0) { /* linear */ - return x; - } - else if (gradient_type == 1) { /* quadratic */ - float r = max(x, 0.0); - return r * r; - } - else if (gradient_type == 2) { /* easing */ - float r = min(max(x, 0.0), 1.0); - float t = r * r; - return (3.0 * t - 2.0 * t * r); - } - else if (gradient_type == 3) { /* diagonal */ - return (x + y) * 0.5; - } - else if (gradient_type == 4) { /* radial */ - return atan(y, x) / (M_PI * 2) + 0.5; - } - else { - /* Bias a little bit for the case where p is a unit length vector, - * to get exactly zero instead of a small random value depending - * on float precision. */ - float r = max(0.999999 - sqrt(x * x + y * y + z * z), 0.0); - if (gradient_type == 5) { /* quadratic sphere */ - return r * r; - } - else if (gradient_type == 6) { /* sphere */ - return r; - } - } - return 0.0; -} - -void node_tex_gradient(vec3 co, float gradient_type, out vec4 color, out float fac) -{ - float f = calc_gradient(co, int(gradient_type)); - f = clamp(f, 0.0, 1.0); - - color = vec4(f, f, f, 1.0); - fac = f; -} - -void node_tex_checker( - vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac) -{ - vec3 p = co * scale; - - /* Prevent precision issues on unit coordinates. */ - p = (p + 0.000001) * 0.999999; - - int xi = int(abs(floor(p.x))); - int yi = int(abs(floor(p.y))); - int zi = int(abs(floor(p.z))); - - bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2))); - - color = check ? color1 : color2; - fac = check ? 1.0 : 0.0; -} - -vec2 calc_brick_texture(vec3 p, - float mortar_size, - float mortar_smooth, - float bias, - float brick_width, - float row_height, - float offset_amount, - int offset_frequency, - float squash_amount, - int squash_frequency) -{ - int bricknum, rownum; - float offset = 0.0; - float x, y; - - rownum = floor_to_int(p.y / row_height); - - if (offset_frequency != 0 && squash_frequency != 0) { - brick_width *= (rownum % squash_frequency != 0) ? 1.0 : squash_amount; /* squash */ - offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width * offset_amount); /* offset */ - } - - bricknum = floor_to_int((p.x + offset) / brick_width); - - x = (p.x + offset) - brick_width * bricknum; - y = p.y - row_height * rownum; - - float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0); - - float min_dist = min(min(x, y), min(brick_width - x, row_height - y)); - if (min_dist >= mortar_size) { - return vec2(tint, 0.0); - } - else if (mortar_smooth == 0.0) { - return vec2(tint, 1.0); - } - else { - min_dist = 1.0 - min_dist / mortar_size; - return vec2(tint, smoothstep(0.0, mortar_smooth, min_dist)); - } -} - -void node_tex_brick(vec3 co, - vec4 color1, - vec4 color2, - vec4 mortar, - float scale, - float mortar_size, - float mortar_smooth, - float bias, - float brick_width, - float row_height, - float offset_amount, - float offset_frequency, - float squash_amount, - float squash_frequency, - out vec4 color, - out float fac) -{ - vec2 f2 = calc_brick_texture(co * scale, - mortar_size, - mortar_smooth, - bias, - brick_width, - row_height, - offset_amount, - int(offset_frequency), - squash_amount, - int(squash_frequency)); - float tint = f2.x; - float f = f2.y; - if (f != 1.0) { - float facm = 1.0 - tint; - color1 = facm * color1 + tint * color2; - } - color = mix(color1, mortar, f); - fac = f; -} - -void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac) -{ - color = vec4(1.0); - fac = 1.0; -} - -void node_tex_environment_equirectangular(vec3 co, float clamp_size, sampler2D ima, out vec3 uv) -{ - vec3 nco = normalize(co); - uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; - uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; - - /* Fix pole bleeding */ - float half_height = clamp_size / float(textureSize(ima, 0).y); - uv.y = clamp(uv.y, half_height, 1.0 - half_height); - uv.z = 0.0; -} - -void node_tex_environment_mirror_ball(vec3 co, out vec3 uv) -{ - vec3 nco = normalize(co); - nco.y -= 1.0; - - float div = 2.0 * sqrt(max(-0.5 * nco.y, 0.0)); - nco /= max(1e-8, div); - - uv = 0.5 * nco.xzz + 0.5; -} - -void node_tex_environment_empty(vec3 co, out vec4 color) -{ - color = vec4(1.0, 0.0, 1.0, 1.0); -} - -/* 16bits floats limits. Higher/Lower values produce +/-inf. */ -#define safe_color(a) (clamp(a, -65520.0, 65520.0)) - -void tex_color_alpha_clear(vec4 color, out vec4 result) -{ - result = vec4(color.rgb, 1.0); -} - -void tex_color_alpha_premultiply(vec4 color, out vec4 result) -{ - result = vec4(color.rgb * color.a, 1.0); -} - -void tex_color_alpha_unpremultiply(vec4 color, out vec4 result) -{ - if (color.a == 0.0 || color.a == 1.0) { - result = vec4(color.rgb, 1.0); - } - else { - result = vec4(color.rgb / color.a, 1.0); - } -} - -void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - color = safe_color(texture(ima, co.xy)); - alpha = color.a; -} - -void node_tex_image_linear_no_mip(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - color = safe_color(textureLod(ima, co.xy, 0.0)); - alpha = color.a; -} - -void node_tex_image_nearest(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - ivec2 pix = ivec2(fract(co.xy) * textureSize(ima, 0).xy); - color = safe_color(texelFetch(ima, pix, 0)); - alpha = color.a; -} - -/* @arg f: signed distance to texel center. */ -void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3) -{ - vec2 f2 = f * f; - vec2 f3 = f2 * f; - /* Bspline coefs (optimized) */ - w3 = f3 / 6.0; - w0 = -w3 + f2 * 0.5 - f * 0.5 + 1.0 / 6.0; - w1 = f3 * 0.5 - f2 * 1.0 + 2.0 / 3.0; - w2 = 1.0 - w0 - w1 - w3; -} - -void node_tex_image_cubic_ex( - vec3 co, sampler2D ima, float do_extend, out vec4 color, out float alpha) -{ - vec2 tex_size = vec2(textureSize(ima, 0).xy); - - co.xy *= tex_size; - /* texel center */ - vec2 tc = floor(co.xy - 0.5) + 0.5; - vec2 w0, w1, w2, w3; - cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); - -#if 1 /* Optimized version using 4 filtered tap. */ - vec2 s0 = w0 + w1; - vec2 s1 = w2 + w3; - - vec2 f0 = w1 / (w0 + w1); - vec2 f1 = w3 / (w2 + w3); - - vec4 final_co; - final_co.xy = tc - 1.0 + f0; - final_co.zw = tc + 1.0 + f1; - - if (do_extend == 1.0) { - final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5); - } - final_co /= tex_size.xyxy; - - color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y; - color += safe_color(textureLod(ima, final_co.zy, 0.0)) * s1.x * s0.y; - color += safe_color(textureLod(ima, final_co.xw, 0.0)) * s0.x * s1.y; - color += safe_color(textureLod(ima, final_co.zw, 0.0)) * s1.x * s1.y; - -#else /* Reference bruteforce 16 tap. */ - color = texelFetch(ima, ivec2(tc + vec2(-1.0, -1.0)), 0) * w0.x * w0.y; - color += texelFetch(ima, ivec2(tc + vec2(0.0, -1.0)), 0) * w1.x * w0.y; - color += texelFetch(ima, ivec2(tc + vec2(1.0, -1.0)), 0) * w2.x * w0.y; - color += texelFetch(ima, ivec2(tc + vec2(2.0, -1.0)), 0) * w3.x * w0.y; - - color += texelFetch(ima, ivec2(tc + vec2(-1.0, 0.0)), 0) * w0.x * w1.y; - color += texelFetch(ima, ivec2(tc + vec2(0.0, 0.0)), 0) * w1.x * w1.y; - color += texelFetch(ima, ivec2(tc + vec2(1.0, 0.0)), 0) * w2.x * w1.y; - color += texelFetch(ima, ivec2(tc + vec2(2.0, 0.0)), 0) * w3.x * w1.y; - - color += texelFetch(ima, ivec2(tc + vec2(-1.0, 1.0)), 0) * w0.x * w2.y; - color += texelFetch(ima, ivec2(tc + vec2(0.0, 1.0)), 0) * w1.x * w2.y; - color += texelFetch(ima, ivec2(tc + vec2(1.0, 1.0)), 0) * w2.x * w2.y; - color += texelFetch(ima, ivec2(tc + vec2(2.0, 1.0)), 0) * w3.x * w2.y; - - color += texelFetch(ima, ivec2(tc + vec2(-1.0, 2.0)), 0) * w0.x * w3.y; - color += texelFetch(ima, ivec2(tc + vec2(0.0, 2.0)), 0) * w1.x * w3.y; - color += texelFetch(ima, ivec2(tc + vec2(1.0, 2.0)), 0) * w2.x * w3.y; - color += texelFetch(ima, ivec2(tc + vec2(2.0, 2.0)), 0) * w3.x * w3.y; -#endif - - alpha = color.a; -} - -void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); -} - -void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - node_tex_image_cubic_ex(co, ima, 1.0, color, alpha); -} - -void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - /* use cubic for now */ - node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); -} - -void tex_box_sample_linear( - vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) -{ - /* X projection */ - vec2 uv = texco.yz; - if (N.x < 0.0) { - uv.x = 1.0 - uv.x; - } - color1 = texture(ima, uv); - /* Y projection */ - uv = texco.xz; - if (N.y > 0.0) { - uv.x = 1.0 - uv.x; - } - color2 = texture(ima, uv); - /* Z projection */ - uv = texco.yx; - if (N.z > 0.0) { - uv.x = 1.0 - uv.x; - } - color3 = texture(ima, uv); -} - -void tex_box_sample_nearest( - vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) -{ - /* X projection */ - vec2 uv = texco.yz; - if (N.x < 0.0) { - uv.x = 1.0 - uv.x; - } - ivec2 pix = ivec2(uv.xy * textureSize(ima, 0).xy); - color1 = texelFetch(ima, pix, 0); - /* Y projection */ - uv = texco.xz; - if (N.y > 0.0) { - uv.x = 1.0 - uv.x; - } - pix = ivec2(uv.xy * textureSize(ima, 0).xy); - color2 = texelFetch(ima, pix, 0); - /* Z projection */ - uv = texco.yx; - if (N.z > 0.0) { - uv.x = 1.0 - uv.x; - } - pix = ivec2(uv.xy * textureSize(ima, 0).xy); - color3 = texelFetch(ima, pix, 0); -} - -void tex_box_sample_cubic( - vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) -{ - float alpha; - /* X projection */ - vec2 uv = texco.yz; - if (N.x < 0.0) { - uv.x = 1.0 - uv.x; - } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color1, alpha); - /* Y projection */ - uv = texco.xz; - if (N.y > 0.0) { - uv.x = 1.0 - uv.x; - } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha); - /* Z projection */ - uv = texco.yx; - if (N.z > 0.0) { - uv.x = 1.0 - uv.x; - } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color3, alpha); -} - -void tex_box_sample_smart( - vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) -{ - tex_box_sample_cubic(texco, N, ima, color1, color2, color3); -} - -void node_tex_image_box(vec3 texco, - vec3 N, - vec4 color1, - vec4 color2, - vec4 color3, - sampler2D ima, - float blend, - out vec4 color, - out float alpha) -{ - /* project from direction vector to barycentric coordinates in triangles */ - N = abs(N); - N /= dot(N, vec3(1.0)); - - /* basic idea is to think of this as a triangle, each corner representing - * one of the 3 faces of the cube. in the corners we have single textures, - * in between we blend between two textures, and in the middle we a blend - * between three textures. - * - * the Nxyz values are the barycentric coordinates in an equilateral - * triangle, which in case of blending, in the middle has a smaller - * equilateral triangle where 3 textures blend. this divides things into - * 7 zones, with an if () test for each zone - * EDIT: Now there is only 4 if's. */ - - float limit = 0.5 + 0.5 * blend; - - vec3 weight; - weight = N.xyz / (N.xyx + N.yzz); - weight = clamp((weight - 0.5 * (1.0 - blend)) / max(1e-8, blend), 0.0, 1.0); - - /* test for mixes between two textures */ - if (N.z < (1.0 - limit) * (N.y + N.x)) { - weight.z = 0.0; - weight.y = 1.0 - weight.x; - } - else if (N.x < (1.0 - limit) * (N.y + N.z)) { - weight.x = 0.0; - weight.z = 1.0 - weight.y; - } - else if (N.y < (1.0 - limit) * (N.x + N.z)) { - weight.y = 0.0; - weight.x = 1.0 - weight.z; - } - else { - /* last case, we have a mix between three */ - weight = ((2.0 - limit) * N + (limit - 1.0)) / max(1e-8, blend); - } - - color = weight.x * color1 + weight.y * color2 + weight.z * color3; - alpha = color.a; -} - -void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - vec2 tex_size = vec2(textureSize(ima, 0).xy); - vec2 minco = min(co.xy, 1.0 - co.xy); - minco = clamp(minco * tex_size + 0.5, 0.0, 1.0); - float fac = minco.x * minco.y; - - color = mix(vec4(0.0), icolor, fac); - alpha = color.a; -} - -void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - vec4 minco = vec4(co.xy, 1.0 - co.xy); - color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor; - alpha = color.a; -} - -void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - vec2 tex_size = vec2(textureSize(ima, 0).xy); - - co.xy *= tex_size; - /* texel center */ - vec2 tc = floor(co.xy - 0.5) + 0.5; - vec2 w0, w1, w2, w3; - cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); - - /* TODO Optimize this part. I'm sure there is a smarter way to do that. - * Could do that when sampling? */ -#define CLIP_CUBIC_SAMPLE(samp, size) \ - (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size)))) - ivec2 itex_size = textureSize(ima, 0).xy; - float fac; - fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, -1.0), itex_size) * w1.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, -1.0), itex_size) * w2.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, -1.0), itex_size) * w3.x * w0.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 0.0), itex_size) * w1.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 0.0), itex_size) * w2.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 0.0), itex_size) * w3.x * w1.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 1.0), itex_size) * w1.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 1.0), itex_size) * w2.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 1.0), itex_size) * w3.x * w2.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 2.0), itex_size) * w1.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 2.0), itex_size) * w2.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 2.0), itex_size) * w3.x * w3.y; -#undef CLIP_CUBIC_SAMPLE - - color = mix(vec4(0.0), icolor, fac); - alpha = color.a; -} - -void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - tex_clip_cubic(co, ima, icolor, color, alpha); -} - -void node_tex_image_empty(vec3 co, out vec4 color, out float alpha) -{ - color = vec4(0.0); - alpha = 0.0; -} - -float noise_fade(float t) -{ - return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); -} - -float noise_scale3(float result) -{ - return 0.9820 * result; -} - -float noise_nerp(float t, float a, float b) -{ - return (1.0 - t) * a + t * b; -} - -float noise_grad(uint hash, float x, float y, float z) -{ - uint h = hash & 15u; - float u = h < 8u ? x : y; - float vt = ((h == 12u) || (h == 14u)) ? x : z; - float v = h < 4u ? y : vt; - return (((h & 1u) != 0u) ? -u : u) + (((h & 2u) != 0u) ? -v : v); -} - -float noise_perlin(float x, float y, float z) -{ - int X; - float fx = floorfrac(x, X); - int Y; - float fy = floorfrac(y, Y); - int Z; - float fz = floorfrac(z, Z); - - float u = noise_fade(fx); - float v = noise_fade(fy); - float w = noise_fade(fz); - - float noise_u[2], noise_v[2]; - - noise_u[0] = noise_nerp(u, - noise_grad(hash_int3(X, Y, Z), fx, fy, fz), - noise_grad(hash_int3(X + 1, Y, Z), fx - 1.0, fy, fz)); - - noise_u[1] = noise_nerp(u, - noise_grad(hash_int3(X, Y + 1, Z), fx, fy - 1.0, fz), - noise_grad(hash_int3(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz)); - - noise_v[0] = noise_nerp(v, noise_u[0], noise_u[1]); - - noise_u[0] = noise_nerp(u, - noise_grad(hash_int3(X, Y, Z + 1), fx, fy, fz - 1.0), - noise_grad(hash_int3(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0)); - - noise_u[1] = noise_nerp( - u, - noise_grad(hash_int3(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0), - noise_grad(hash_int3(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0)); - - noise_v[1] = noise_nerp(v, noise_u[0], noise_u[1]); - - float r = noise_scale3(noise_nerp(w, noise_v[0], noise_v[1])); - - return (isinf(r)) ? 0.0 : r; -} - -float noise(vec3 p) -{ - return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5; -} - -float snoise(vec3 p) -{ - return noise_perlin(p.x, p.y, p.z); -} - -float noise_turbulence(vec3 p, float octaves, int hard) -{ - float fscale = 1.0; - float amp = 1.0; - float sum = 0.0; - octaves = clamp(octaves, 0.0, 16.0); - int n = int(octaves); - for (int i = 0; i <= n; i++) { - float t = noise(fscale * p); - if (hard != 0) { - t = abs(2.0 * t - 1.0); - } - sum += t * amp; - amp *= 0.5; - fscale *= 2.0; - } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = noise(fscale * p); - if (hard != 0) { - t = abs(2.0 * t - 1.0); - } - float sum2 = sum + t * amp; - sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); - sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1)); - return (1.0 - rmd) * sum + rmd * sum2; - } - else { - sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); - return sum; - } -} - -void node_tex_noise( - vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac) -{ - vec3 p = co * scale; - int hard = 0; - if (distortion != 0.0) { - vec3 r, offset = vec3(13.5, 13.5, 13.5); - r.x = noise(p + offset) * distortion; - r.y = noise(p) * distortion; - r.z = noise(p - offset) * distortion; - p += r; - } - - fac = noise_turbulence(p, detail, hard); - color = vec4(fac, - noise_turbulence(vec3(p.y, p.x, p.z), detail, hard), - noise_turbulence(vec3(p.y, p.z, p.x), detail, hard), - 1); -} - -/* Musgrave fBm - * - * H: fractal increment parameter - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * - * from "Texturing and Modelling: A procedural approach" - */ - -float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves) -{ - float rmd; - float value = 0.0; - float pwr = 1.0; - float pwHL = pow(lacunarity, -H); - - for (int i = 0; i < int(octaves); i++) { - value += snoise(p) * pwr; - pwr *= pwHL; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) { - value += rmd * snoise(p) * pwr; - } - - return value; -} - -/* Musgrave Multifractal - * - * H: highest fractal dimension - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - */ - -float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octaves) -{ - float rmd; - float value = 1.0; - float pwr = 1.0; - float pwHL = pow(lacunarity, -H); - - for (int i = 0; i < int(octaves); i++) { - value *= (pwr * snoise(p) + 1.0); - pwr *= pwHL; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) { - value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */ - } - - return value; -} - -/* Musgrave Heterogeneous Terrain - * - * H: fractal dimension of the roughest area - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * offset: raises the terrain from `sea level' - */ - -float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset) -{ - float value, increment, rmd; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; - - /* first unscaled octave of function; later octaves are scaled */ - value = offset + snoise(p); - p *= lacunarity; - - for (int i = 1; i < int(octaves); i++) { - increment = (snoise(p) + offset) * pwr * value; - value += increment; - pwr *= pwHL; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) { - increment = (snoise(p) + offset) * pwr * value; - value += rmd * increment; - } - - return value; -} - -/* Hybrid Additive/Multiplicative Multifractal Terrain - * - * H: fractal dimension of the roughest area - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * offset: raises the terrain from `sea level' - */ - -float noise_musgrave_hybrid_multi_fractal( - vec3 p, float H, float lacunarity, float octaves, float offset, float gain) -{ - float result, signal, weight, rmd; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; - - result = snoise(p) + offset; - weight = gain * result; - p *= lacunarity; - - for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) { - if (weight > 1.0) { - weight = 1.0; - } - - signal = (snoise(p) + offset) * pwr; - pwr *= pwHL; - result += weight * signal; - weight *= gain * signal; - p *= lacunarity; - } - - rmd = octaves - floor(octaves); - if (rmd != 0.0) { - result += rmd * ((snoise(p) + offset) * pwr); - } - - return result; -} - -/* Ridged Multifractal Terrain - * - * H: fractal dimension of the roughest area - * lacunarity: gap between successive frequencies - * octaves: number of frequencies in the fBm - * offset: raises the terrain from `sea level' - */ - -float noise_musgrave_ridged_multi_fractal( - vec3 p, float H, float lacunarity, float octaves, float offset, float gain) -{ - float result, signal, weight; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; - - signal = offset - abs(snoise(p)); - signal *= signal; - result = signal; - weight = 1.0; - - for (int i = 1; i < int(octaves); i++) { - p *= lacunarity; - weight = clamp(signal * gain, 0.0, 1.0); - signal = offset - abs(snoise(p)); - signal *= signal; - signal *= weight; - result += signal * pwr; - pwr *= pwHL; - } - - return result; -} - -float svm_musgrave(int type, - float dimension, - float lacunarity, - float octaves, - float offset, - float intensity, - float gain, - vec3 p) -{ - if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */) { - return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves); - } - else if (type == 1 /* NODE_MUSGRAVE_FBM */) { - return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves); - } - else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */) { - return intensity * - noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); - } - else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */) { - return intensity * - noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); - } - else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */) { - return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset); - } - return 0.0; -} - -void node_tex_musgrave(vec3 co, - float scale, - float detail, - float dimension, - float lacunarity, - float offset, - float gain, - float type, - out vec4 color, - out float fac) -{ - fac = svm_musgrave(int(type), dimension, lacunarity, detail, offset, 1.0, gain, co *scale); - - color = vec4(fac, fac, fac, 1.0); -} - -void node_tex_sky(vec3 co, out vec4 color) -{ - color = vec4(1.0); -} - -void node_tex_voronoi(vec3 co, - float scale, - float exponent, - float coloring, - float metric, - float feature, - out vec4 color, - out float fac) -{ - vec3 p = co * scale; - int xx, yy, zz, xi, yi, zi; - vec4 da = vec4(1e10); - vec3 pa[4] = vec3[4](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); - - xi = floor_to_int(p[0]); - yi = floor_to_int(p[1]); - zi = floor_to_int(p[2]); - - for (xx = xi - 1; xx <= xi + 1; xx++) { - for (yy = yi - 1; yy <= yi + 1; yy++) { - for (zz = zi - 1; zz <= zi + 1; zz++) { - vec3 ip = vec3(xx, yy, zz); - vec3 vp = cellnoise_color(ip); - vec3 pd = p - (vp + ip); - - float d = 0.0; - if (metric == 0.0) { /* SHD_VORONOI_DISTANCE 0 */ - d = dot(pd, pd); - } - else if (metric == 1.0) { /* SHD_VORONOI_MANHATTAN 1 */ - d = abs(pd[0]) + abs(pd[1]) + abs(pd[2]); - } - else if (metric == 2.0) { /* SHD_VORONOI_CHEBYCHEV 2 */ - d = max(abs(pd[0]), max(abs(pd[1]), abs(pd[2]))); - } - else if (metric == 3.0) { /* SHD_VORONOI_MINKOWSKI 3 */ - d = pow(pow(abs(pd[0]), exponent) + pow(abs(pd[1]), exponent) + - pow(abs(pd[2]), exponent), - 1.0 / exponent); - } - - vp += vec3(xx, yy, zz); - if (d < da[0]) { - da.yzw = da.xyz; - da[0] = d; - - pa[3] = pa[2]; - pa[2] = pa[1]; - pa[1] = pa[0]; - pa[0] = vp; - } - else if (d < da[1]) { - da.zw = da.yz; - da[1] = d; - - pa[3] = pa[2]; - pa[2] = pa[1]; - pa[1] = vp; - } - else if (d < da[2]) { - da[3] = da[2]; - da[2] = d; - - pa[3] = pa[2]; - pa[2] = vp; - } - else if (d < da[3]) { - da[3] = d; - pa[3] = vp; - } - } - } - } - - if (coloring == 0.0) { - /* Intensity output */ - if (feature == 0.0) { /* F1 */ - fac = abs(da[0]); - } - else if (feature == 1.0) { /* F2 */ - fac = abs(da[1]); - } - else if (feature == 2.0) { /* F3 */ - fac = abs(da[2]); - } - else if (feature == 3.0) { /* F4 */ - fac = abs(da[3]); - } - else if (feature == 4.0) { /* F2F1 */ - fac = abs(da[1] - da[0]); - } - color = vec4(fac, fac, fac, 1.0); - } - else { - /* Color output */ - vec3 col = vec3(fac, fac, fac); - if (feature == 0.0) { /* F1 */ - col = pa[0]; - } - else if (feature == 1.0) { /* F2 */ - col = pa[1]; - } - else if (feature == 2.0) { /* F3 */ - col = pa[2]; - } - else if (feature == 3.0) { /* F4 */ - col = pa[3]; - } - else if (feature == 4.0) { /* F2F1 */ - col = abs(pa[1] - pa[0]); - } - - color = vec4(cellnoise_color(col), 1.0); - fac = (color.x + color.y + color.z) * (1.0 / 3.0); - } -} - -float calc_wave( - vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile) -{ - float n; - - if (wave_type == 0) { /* type bands */ - n = (p.x + p.y + p.z) * 10.0; - } - else { /* type rings */ - n = length(p) * 20.0; - } - - if (distortion != 0.0) { - n += distortion * noise_turbulence(p * detail_scale, detail, 0); - } - - if (wave_profile == 0) { /* profile sin */ - return 0.5 + 0.5 * sin(n); - } - else { /* profile saw */ - n /= 2.0 * M_PI; - n -= int(n); - return (n < 0.0) ? n + 1.0 : n; - } -} - -void node_tex_wave(vec3 co, - float scale, - float distortion, - float detail, - float detail_scale, - float wave_type, - float wave_profile, - out vec4 color, - out float fac) -{ - float f; - f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile)); - - color = vec4(f, f, f, 1.0); - fac = f; -} - -/* light path */ - -void node_light_path(out float is_camera_ray, - out float is_shadow_ray, - out float is_diffuse_ray, - out float is_glossy_ray, - out float is_singular_ray, - out float is_reflection_ray, - out float is_transmission_ray, - out float ray_length, - out float ray_depth, - out float diffuse_depth, - out float glossy_depth, - out float transparent_depth, - out float transmission_depth) -{ - /* Supported. */ - is_camera_ray = (rayType == EEVEE_RAY_CAMERA) ? 1.0 : 0.0; - is_shadow_ray = (rayType == EEVEE_RAY_SHADOW) ? 1.0 : 0.0; - is_diffuse_ray = (rayType == EEVEE_RAY_DIFFUSE) ? 1.0 : 0.0; - is_glossy_ray = (rayType == EEVEE_RAY_GLOSSY) ? 1.0 : 0.0; - /* Kind of supported. */ - is_singular_ray = is_glossy_ray; - is_reflection_ray = is_glossy_ray; - is_transmission_ray = is_glossy_ray; - ray_depth = rayDepth; - diffuse_depth = (is_diffuse_ray == 1.0) ? rayDepth : 0.0; - glossy_depth = (is_glossy_ray == 1.0) ? rayDepth : 0.0; - transmission_depth = (is_transmission_ray == 1.0) ? glossy_depth : 0.0; - /* Not supported. */ - ray_length = 1.0; - transparent_depth = 0.0; -} - -void node_light_falloff( - float strength, float tsmooth, out float quadratic, out float linear, out float constant) -{ - quadratic = strength; - linear = strength; - constant = strength; -} - -void node_object_info(mat4 obmat, - vec4 obcolor, - vec4 info, - float mat_index, - out vec3 location, - out vec4 color, - out float object_index, - out float material_index, - out float random) -{ - location = obmat[3].xyz; - color = obcolor; - object_index = info.x; - material_index = mat_index; - random = info.z; -} - -void node_normal_map(vec4 info, vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) -{ - if (all(equal(tangent, vec4(0.0, 0.0, 0.0, 1.0)))) { - outnormal = normal; - return; - } - tangent *= (gl_FrontFacing ? 1.0 : -1.0); - vec3 B = tangent.w * cross(normal, tangent.xyz) * info.w; - - outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal; - outnormal = normalize(outnormal); -} - -void node_bump( - float strength, float dist, float height, vec3 N, vec3 surf_pos, float invert, out vec3 result) -{ - N = mat3(ViewMatrix) * normalize(N); - dist *= gl_FrontFacing ? invert : -invert; - - vec3 dPdx = dFdx(surf_pos); - vec3 dPdy = dFdy(surf_pos); - - /* Get surface tangents from normal. */ - vec3 Rx = cross(dPdy, N); - vec3 Ry = cross(N, dPdx); - - /* Compute surface gradient and determinant. */ - float det = dot(dPdx, Rx); - - float dHdx = dFdx(height); - float dHdy = dFdy(height); - vec3 surfgrad = dHdx * Rx + dHdy * Ry; - - strength = max(strength, 0.0); - - result = normalize(abs(det) * N - dist * sign(det) * surfgrad); - result = normalize(mix(N, result, strength)); - - result = mat3(ViewMatrixInverse) * result; -} - -void node_bevel(float radius, vec3 N, out vec3 result) -{ - result = N; -} - -void node_hair_info(out float is_strand, - out float intercept, - out float thickness, - out vec3 tangent, - out float random) -{ -#ifdef HAIR_SHADER - is_strand = 1.0; - intercept = hairTime; - thickness = hairThickness; - tangent = normalize(worldNormal); - random = wang_hash_noise( - uint(hairStrandID)); /* TODO: could be precomputed per strand instead. */ -#else - is_strand = 0.0; - intercept = 0.0; - thickness = 0.0; - tangent = vec3(1.0); - random = 0.0; -#endif -} - -void node_displacement_object( - float height, float midlevel, float scale, vec3 N, mat4 obmat, out vec3 result) -{ - N = (vec4(N, 0.0) * obmat).xyz; - result = (height - midlevel) * scale * normalize(N); - result = (obmat * vec4(result, 0.0)).xyz; -} - -void node_displacement_world(float height, float midlevel, float scale, vec3 N, out vec3 result) -{ - result = (height - midlevel) * scale * normalize(N); -} - -void node_vector_displacement_tangent(vec4 vector, - float midlevel, - float scale, - vec4 tangent, - vec3 normal, - mat4 obmat, - mat4 viewmat, - out vec3 result) -{ - /* TODO(fclem) this is broken. revisit latter. */ - vec3 N_object = normalize(((vec4(normal, 0.0) * viewmat) * obmat).xyz); - vec3 T_object = normalize(((vec4(tangent.xyz, 0.0) * viewmat) * obmat).xyz); - vec3 B_object = tangent.w * normalize(cross(N_object, T_object)); - - vec3 offset = (vector.xyz - vec3(midlevel)) * scale; - result = offset.x * T_object + offset.y * N_object + offset.z * B_object; - result = (obmat * vec4(result, 0.0)).xyz; -} - -void node_vector_displacement_object( - vec4 vector, float midlevel, float scale, mat4 obmat, out vec3 result) -{ - result = (vector.xyz - vec3(midlevel)) * scale; - result = (obmat * vec4(result, 0.0)).xyz; -} - -void node_vector_displacement_world(vec4 vector, float midlevel, float scale, out vec3 result) -{ - result = (vector.xyz - vec3(midlevel)) * scale; -} - -/* output */ - -void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result) -{ -#ifdef VOLUMETRICS - result = volume; -#else - result = surface; -#endif -} - -uniform float backgroundAlpha; - -void node_output_world(Closure surface, Closure volume, out Closure result) -{ -#ifndef VOLUMETRICS - result.radiance = surface.radiance * backgroundAlpha; - result.transmittance = vec3(1.0 - backgroundAlpha); -#else - result = volume; -#endif /* VOLUMETRICS */ -} - -/* TODO : clean this ifdef mess */ -/* EEVEE output */ -void world_normals_get(out vec3 N) -{ -#ifndef VOLUMETRICS -# 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.0 - cos_theta * cos_theta)); - N = normalize(worldNormal * sin_theta + B * cos_theta); -# else - N = gl_FrontFacing ? worldNormal : -worldNormal; -# endif -#else - generated_from_orco(vec3(0.0), N); -#endif -} - -#ifndef VOLUMETRICS -void node_eevee_specular(vec4 diffuse, - vec4 specular, - float roughness, - vec4 emissive, - float transp, - vec3 normal, - float clearcoat, - float clearcoat_roughness, - vec3 clearcoat_normal, - float occlusion, - float ssr_id, - out Closure result) -{ - normal = normalize(normal); - - vec3 out_diff, out_spec, ssr_spec; - eevee_closure_default_clearcoat(normal, - diffuse.rgb, - specular.rgb, - vec3(1.0), - int(ssr_id), - roughness, - clearcoat_normal, - clearcoat * 0.25, - clearcoat_roughness, - occlusion, - out_diff, - out_spec, - ssr_spec); - - float alpha = 1.0 - transp; - result = CLOSURE_DEFAULT; - result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb; - result.radiance *= alpha; - result.transmittance = vec3(transp); - - closure_load_ssr_data(ssr_spec * alpha, roughness, normal, viewCameraVec, int(ssr_id), result); -} - -void node_shader_to_rgba(Closure cl, out vec4 outcol, out float outalpha) -{ - vec4 spec_accum = vec4(0.0); - if (ssrToggle && FLAG_TEST(cl.flag, CLOSURE_SSR_FLAG)) { - vec3 V = cameraVec; - vec3 vN = normal_decode(cl.ssr_normal, viewCameraVec); - vec3 N = transform_direction(ViewMatrixInverse, vN); - float roughness = cl.ssr_data.a; - float roughnessSquared = max(1e-3, roughness * roughness); - fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum); - } - - outalpha = avg(cl.transmittance); - outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0); - -# ifdef USE_SSS -# ifdef USE_SSS_ALBEDO - outcol.rgb += cl.sss_data.rgb * cl.sss_albedo; -# else - outcol.rgb += cl.sss_data.rgb; -# endif -# endif -} - -#endif /* VOLUMETRICS */ diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl new file mode 100644 index 00000000000..99117400c57 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl @@ -0,0 +1,4 @@ +void node_add_shader(Closure shader1, Closure shader2, out Closure shader) +{ + shader = closure_add(shader1, shader2); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl new file mode 100644 index 00000000000..8f8ebebb5f1 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl @@ -0,0 +1,13 @@ +#ifndef VOLUMETRICS +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); + result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal); + result_color = result_ao * color; +} +#else +/* Stub ambient occlusion because it is not compatible with volumetrics. */ +# define node_ambient_occlusion +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl new file mode 100644 index 00000000000..a8a900b40c6 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl @@ -0,0 +1,15 @@ +#ifndef VOLUMETRICS +void node_bsdf_anisotropic(vec4 color, + float roughness, + float anisotropy, + float rotation, + vec3 N, + vec3 T, + out Closure result) +{ + node_bsdf_glossy(color, roughness, N, -1, result); +} +#else +/* Stub anisotropic because it is not compatible with volumetrics. */ +# define node_bsdf_anisotropic +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl new file mode 100644 index 00000000000..10e1b4563bc --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl @@ -0,0 +1,6 @@ +void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf) +{ + outcol = vec4(attr, 1.0); + outvec = attr; + outf = avg(attr); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_background.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_background.glsl new file mode 100644 index 00000000000..69ef4dcb7c7 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_background.glsl @@ -0,0 +1,11 @@ +void node_background(vec4 color, float strength, out Closure result) +{ +#ifndef VOLUMETRICS + color *= strength; + result = CLOSURE_DEFAULT; + result.radiance = color.rgb; + result.transmittance = vec3(0.0); +#else + result = CLOSURE_DEFAULT; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_bevel.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_bevel.glsl new file mode 100644 index 00000000000..0d99390c2f9 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_bevel.glsl @@ -0,0 +1,4 @@ +void node_bevel(float radius, vec3 N, out vec3 result) +{ + result = N; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_blackbody.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_blackbody.glsl new file mode 100644 index 00000000000..d0111aa3839 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_blackbody.glsl @@ -0,0 +1,13 @@ +void node_blackbody(float temperature, sampler1DArray spectrummap, float layer, out vec4 color) +{ + if (temperature >= 12000.0) { + color = vec4(0.826270103, 0.994478524, 1.56626022, 1.0); + } + else if (temperature < 965.0) { + color = vec4(4.70366907, 0.0, 0.0, 1.0); + } + else { + float t = (temperature - 965.0) / (12000.0 - 965.0); + color = vec4(texture(spectrummap, vec2(t, layer)).rgb, 1.0); + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_bright_contrast.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_bright_contrast.glsl new file mode 100644 index 00000000000..a5a10833065 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_bright_contrast.glsl @@ -0,0 +1,10 @@ +void brightness_contrast(vec4 col, float brightness, float contrast, out vec4 outcol) +{ + float a = 1.0 + contrast; + float b = brightness - contrast * 0.5; + + outcol.r = max(a * col.r + b, 0.0); + outcol.g = max(a * col.g + b, 0.0); + outcol.b = max(a * col.b + b, 0.0); + outcol.a = col.a; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl new file mode 100644 index 00000000000..1137e5acdc6 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl @@ -0,0 +1,27 @@ +void node_bump( + float strength, float dist, float height, vec3 N, vec3 surf_pos, float invert, out vec3 result) +{ + N = mat3(ViewMatrix) * normalize(N); + dist *= gl_FrontFacing ? invert : -invert; + + vec3 dPdx = dFdx(surf_pos); + vec3 dPdy = dFdy(surf_pos); + + /* Get surface tangents from normal. */ + vec3 Rx = cross(dPdy, N); + vec3 Ry = cross(N, dPdx); + + /* Compute surface gradient and determinant. */ + float det = dot(dPdx, Rx); + + float dHdx = dFdx(height); + float dHdy = dFdy(height); + vec3 surfgrad = dHdx * Rx + dHdy * Ry; + + strength = max(strength, 0.0); + + result = normalize(abs(det) * N - dist * sign(det) * surfgrad); + result = normalize(mix(N, result, strength)); + + result = mat3(ViewMatrixInverse) * result; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_camera.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_camera.glsl new file mode 100644 index 00000000000..03e61e9f472 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_camera.glsl @@ -0,0 +1,6 @@ +void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist) +{ + outdepth = abs(co.z); + outdist = length(co); + outview = normalize(co); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_cell_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_cell_noise.glsl new file mode 100644 index 00000000000..881f2386cd4 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_cell_noise.glsl @@ -0,0 +1,17 @@ +float cellnoise(vec3 p) +{ + int ix = quick_floor(p.x); + int iy = quick_floor(p.y); + int iz = quick_floor(p.z); + + return hash_uint3_to_float(uint(ix), uint(iy), uint(iz)); +} + +vec3 cellnoise_color(vec3 p) +{ + float r = cellnoise(p.xyz); + float g = cellnoise(p.yxz); + float b = cellnoise(p.yzx); + + return vec3(r, g, b); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl new file mode 100644 index 00000000000..b8842064b6f --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl @@ -0,0 +1,4 @@ +void clamp_value(float value, float min, float max, out float result) +{ + result = clamp(value, min, max); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_color_ramp.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_color_ramp.glsl new file mode 100644 index 00000000000..9fe45f91f45 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_color_ramp.glsl @@ -0,0 +1,28 @@ +void valtorgb_opti_constant( + float fac, float edge, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) +{ + outcol = (fac > edge) ? color2 : color1; + outalpha = outcol.a; +} + +void valtorgb_opti_linear( + float fac, vec2 mulbias, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) +{ + fac = clamp(fac * mulbias.x + mulbias.y, 0.0, 1.0); + outcol = mix(color1, color2, fac); + outalpha = outcol.a; +} + +void valtorgb(float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) +{ + outcol = texture(colormap, vec2(fac, layer)); + outalpha = outcol.a; +} + +void valtorgb_nearest( + float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = texelFetch(colormap, ivec2(fac * (textureSize(colormap, 0).x - 1), layer), 0); + outalpha = outcol.a; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl new file mode 100644 index 00000000000..a5c3a990d90 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl @@ -0,0 +1,111 @@ +void rgb_to_hsv(vec4 rgb, out vec4 outcol) +{ + float cmax, cmin, h, s, v, cdelta; + vec3 c; + + cmax = max(rgb[0], max(rgb[1], rgb[2])); + cmin = min(rgb[0], min(rgb[1], rgb[2])); + cdelta = cmax - cmin; + + v = cmax; + if (cmax != 0.0) { + s = cdelta / cmax; + } + else { + s = 0.0; + h = 0.0; + } + + if (s == 0.0) { + h = 0.0; + } + else { + c = (vec3(cmax) - rgb.xyz) / cdelta; + + if (rgb.x == cmax) { + h = c[2] - c[1]; + } + else if (rgb.y == cmax) { + h = 2.0 + c[0] - c[2]; + } + else { + h = 4.0 + c[1] - c[0]; + } + + h /= 6.0; + + if (h < 0.0) { + h += 1.0; + } + } + + outcol = vec4(h, s, v, rgb.w); +} + +void hsv_to_rgb(vec4 hsv, out vec4 outcol) +{ + float i, f, p, q, t, h, s, v; + vec3 rgb; + + h = hsv[0]; + s = hsv[1]; + v = hsv[2]; + + if (s == 0.0) { + rgb = vec3(v, v, v); + } + else { + if (h == 1.0) { + h = 0.0; + } + + h *= 6.0; + i = floor(h); + f = h - i; + rgb = vec3(f, f, f); + p = v * (1.0 - s); + q = v * (1.0 - (s * f)); + t = v * (1.0 - (s * (1.0 - f))); + + if (i == 0.0) { + rgb = vec3(v, t, p); + } + else if (i == 1.0) { + rgb = vec3(q, v, p); + } + else if (i == 2.0) { + rgb = vec3(p, v, t); + } + else if (i == 3.0) { + rgb = vec3(p, q, v); + } + else if (i == 4.0) { + rgb = vec3(t, p, v); + } + else { + rgb = vec3(v, p, q); + } + } + + outcol = vec4(rgb, hsv.w); +} + +void color_alpha_clear(vec4 color, out vec4 result) +{ + result = vec4(color.rgb, 1.0); +} + +void color_alpha_premultiply(vec4 color, out vec4 result) +{ + result = vec4(color.rgb * color.a, 1.0); +} + +void color_alpha_unpremultiply(vec4 color, out vec4 result) +{ + if (color.a == 0.0 || color.a == 1.0) { + result = vec4(color.rgb, 1.0); + } + else { + result = vec4(color.rgb / color.a, 1.0); + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_combine_hsv.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_combine_hsv.glsl new file mode 100644 index 00000000000..2ce061da3cb --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_combine_hsv.glsl @@ -0,0 +1,4 @@ +void combine_hsv(float h, float s, float v, out vec4 col) +{ + hsv_to_rgb(vec4(h, s, v, 1.0), col); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_combine_rgb.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_combine_rgb.glsl new file mode 100644 index 00000000000..d9c882a048f --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_combine_rgb.glsl @@ -0,0 +1,4 @@ +void combine_rgb(float r, float g, float b, out vec4 col) +{ + col = vec4(r, g, b, 1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_combine_xyz.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_combine_xyz.glsl new file mode 100644 index 00000000000..d8d132ff1f9 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_combine_xyz.glsl @@ -0,0 +1,4 @@ +void combine_xyz(float x, float y, float z, out vec3 vec) +{ + vec = vec3(x, y, z); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl new file mode 100644 index 00000000000..14acf9925a2 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl @@ -0,0 +1,13 @@ +#ifndef VOLUMETRICS +void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) +{ + N = normalize(N); + result = CLOSURE_DEFAULT; + eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance); + closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result); + result.radiance *= color.rgb; +} +#else +/* Stub diffuse because it is not compatible with volumetrics. */ +# define node_bsdf_diffuse +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_displacement.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_displacement.glsl new file mode 100644 index 00000000000..0838b5c8b71 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_displacement.glsl @@ -0,0 +1,12 @@ +void node_displacement_object( + float height, float midlevel, float scale, vec3 N, mat4 obmat, out vec3 result) +{ + N = (vec4(N, 0.0) * obmat).xyz; + result = (height - midlevel) * scale * normalize(N); + result = (obmat * vec4(result, 0.0)).xyz; +} + +void node_displacement_world(float height, float midlevel, float scale, vec3 N, out vec3 result) +{ + result = (height - midlevel) * scale * normalize(N); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl new file mode 100644 index 00000000000..e69a53b6596 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl @@ -0,0 +1,40 @@ +#ifndef VOLUMETRICS +void node_eevee_specular(vec4 diffuse, + vec4 specular, + float roughness, + vec4 emissive, + float transp, + vec3 normal, + float clearcoat, + float clearcoat_roughness, + vec3 clearcoat_normal, + float occlusion, + float ssr_id, + out Closure result) +{ + normal = normalize(normal); + + vec3 out_diff, out_spec, ssr_spec; + eevee_closure_default_clearcoat(normal, + diffuse.rgb, + specular.rgb, + vec3(1.0), + int(ssr_id), + roughness, + clearcoat_normal, + clearcoat * 0.25, + clearcoat_roughness, + occlusion, + out_diff, + out_spec, + ssr_spec); + + float alpha = 1.0 - transp; + result = CLOSURE_DEFAULT; + result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb; + result.radiance *= alpha; + result.transmittance = vec3(transp); + + closure_load_ssr_data(ssr_spec * alpha, roughness, normal, viewCameraVec, int(ssr_id), result); +} +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl new file mode 100644 index 00000000000..092b9ed08bb --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl @@ -0,0 +1,10 @@ +void node_emission(vec4 color, float strength, vec3 vN, out Closure result) +{ + result = CLOSURE_DEFAULT; +#ifndef VOLUMETRICS + result.radiance = color.rgb * strength; + result.ssr_normal = normal_encode(vN, viewCameraVec); +#else + result.emission = color.rgb * strength; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl new file mode 100644 index 00000000000..2a925c2a622 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl @@ -0,0 +1,32 @@ +float noise_turbulence(vec3 p, float octaves, int hard) +{ + float fscale = 1.0; + float amp = 1.0; + float sum = 0.0; + octaves = clamp(octaves, 0.0, 16.0); + int n = int(octaves); + for (int i = 0; i <= n; i++) { + float t = noise(fscale * p); + if (hard != 0) { + t = abs(2.0 * t - 1.0); + } + sum += t * amp; + amp *= 0.5; + fscale *= 2.0; + } + float rmd = octaves - floor(octaves); + if (rmd != 0.0) { + float t = noise(fscale * p); + if (hard != 0) { + t = abs(2.0 * t - 1.0); + } + float sum2 = sum + t * amp; + sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); + sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1)); + return (1.0 - rmd) * sum + rmd * sum2; + } + else { + sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); + return sum; + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_fresnel.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_fresnel.glsl new file mode 100644 index 00000000000..7a4d28f2dd6 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_fresnel.glsl @@ -0,0 +1,37 @@ +float fresnel_dielectric_cos(float cosi, float eta) +{ + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + float c = abs(cosi); + float g = eta * eta - 1.0 + c * c; + float result; + + if (g > 0.0) { + g = sqrt(g); + float A = (g - c) / (g + c); + float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0); + result = 0.5 * A * A * (1.0 + B * B); + } + else { + result = 1.0; /* TIR (no refracted component) */ + } + + return result; +} + +float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) +{ + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + return fresnel_dielectric_cos(dot(Incoming, Normal), eta); +} + +void node_fresnel(float ior, vec3 N, vec3 I, out float result) +{ + N = normalize(N); + /* handle perspective/orthographic */ + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + + float eta = max(ior, 0.00001); + result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_gamma.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_gamma.glsl new file mode 100644 index 00000000000..5733992f8dd --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_gamma.glsl @@ -0,0 +1,14 @@ +void node_gamma(vec4 col, float gamma, out vec4 outcol) +{ + outcol = col; + + if (col.r > 0.0) { + outcol.r = compatible_pow(col.r, gamma); + } + if (col.g > 0.0) { + outcol.g = compatible_pow(col.g, gamma); + } + if (col.b > 0.0) { + outcol.b = compatible_pow(col.b, gamma); + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_geometry.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_geometry.glsl new file mode 100644 index 00000000000..79614495499 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_geometry.glsl @@ -0,0 +1,46 @@ +void node_geometry(vec3 I, + vec3 N, + vec3 orco, + mat4 objmat, + mat4 toworld, + vec2 barycentric, + out vec3 position, + out vec3 normal, + out vec3 tangent, + out vec3 true_normal, + out vec3 incoming, + out vec3 parametric, + out float backfacing, + out float pointiness) +{ + /* handle perspective/orthographic */ + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + incoming = -(toworld * vec4(I_view, 0.0)).xyz; + +#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) + position = -incoming; + true_normal = normal = incoming; + tangent = parametric = vec3(0.0); + vec3(0.0); + backfacing = 0.0; + pointiness = 0.0; +#else + + position = worldPosition; +# ifndef VOLUMETRICS + normal = normalize(N); + vec3 B = dFdx(worldPosition); + vec3 T = dFdy(worldPosition); + true_normal = normalize(cross(B, T)); +# else + normal = (toworld * vec4(N, 0.0)).xyz; + true_normal = normal; +# endif + tangent_orco_z(orco, orco); + node_tangent(N, orco, objmat, tangent); + + parametric = vec3(barycentric, 0.0); + backfacing = (gl_FrontFacing) ? 0.0 : 1.0; + pointiness = 0.5; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl new file mode 100644 index 00000000000..8cc8ba2dd15 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl @@ -0,0 +1,23 @@ +#ifndef VOLUMETRICS +void node_bsdf_glass( + vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result) +{ + N = normalize(N); + vec3 out_spec, out_refr, ssr_spec; + vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : + color.rgb; /* Simulate 2 transmission event */ + eevee_closure_glass( + N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); + out_refr *= refr_color; + out_spec *= color.rgb; + float fresnel = F_eta(ior, dot(N, cameraVec)); + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = mix(out_refr, out_spec, fresnel); + closure_load_ssr_data( + ssr_spec * color.rgb * fresnel, roughness, N, viewCameraVec, int(ssr_id), result); +} +#else +/* Stub glass because it is not compatible with volumetrics. */ +# define node_bsdf_glass +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl new file mode 100644 index 00000000000..4d582e63725 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl @@ -0,0 +1,15 @@ +#ifndef VOLUMETRICS +void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result) +{ + N = normalize(N); + vec3 out_spec, ssr_spec; + eevee_closure_glossy(N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec); + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = out_spec * color.rgb; + closure_load_ssr_data(ssr_spec * color.rgb, roughness, N, viewCameraVec, int(ssr_id), result); +} +#else +/* Stub glossy because it is not compatible with volumetrics. */ +# define node_bsdf_glossy +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl new file mode 100644 index 00000000000..3b23ac976ae --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl @@ -0,0 +1,21 @@ +void node_hair_info(out float is_strand, + out float intercept, + out float thickness, + out vec3 tangent, + out float random) +{ +#ifdef HAIR_SHADER + is_strand = 1.0; + intercept = hairTime; + thickness = hairThickness; + tangent = normalize(worldNormal); + random = wang_hash_noise( + uint(hairStrandID)); /* TODO: could be precomputed per strand instead. */ +#else + is_strand = 0.0; + intercept = 0.0; + thickness = 0.0; + tangent = vec3(1.0); + random = 0.0; +#endif +} diff --git a/source/blender/gpu/shaders/gpu_shader_material_hash.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl index 9f95da0a75b..86191451e5f 100644 --- a/source/blender/gpu/shaders/gpu_shader_material_hash.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl @@ -204,3 +204,14 @@ vec3 hash_vec4_to_vec3(vec4 k) { return vec3(hash_vec4_to_float(k.xyzw), hash_vec4_to_float(k.zxwy), hash_vec4_to_float(k.wzyx)); } + +/* Other Hash Functions */ + +float integer_noise(int n) +{ + int nn; + n = (n + 1013) & 0x7fffffff; + n = (n >> 13) ^ n; + nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; + return 0.5 * (float(nn) / 1073741824.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_holdout.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_holdout.glsl new file mode 100644 index 00000000000..50ce2bf2ab8 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_holdout.glsl @@ -0,0 +1,8 @@ +void node_holdout(out Closure result) +{ + result = CLOSURE_DEFAULT; +#ifndef VOLUMETRICS + result.holdout = 1.0; + result.flag = CLOSURE_HOLDOUT_FLAG; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_hue_sat_val.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_hue_sat_val.glsl new file mode 100644 index 00000000000..64ac73ecdf3 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_hue_sat_val.glsl @@ -0,0 +1,14 @@ +void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol) +{ + vec4 hsv; + + rgb_to_hsv(col, hsv); + + hsv[0] = fract(hsv[0] + hue + 0.5); + hsv[1] = clamp(hsv[1] * sat, 0.0, 1.0); + hsv[2] = hsv[2] * value; + + hsv_to_rgb(hsv, outcol); + + outcol = mix(col, outcol, fac); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_invert.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_invert.glsl new file mode 100644 index 00000000000..5cf362a9947 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_invert.glsl @@ -0,0 +1,5 @@ +void invert(float fac, vec4 col, out vec4 outcol) +{ + outcol.xyz = mix(col.xyz, vec3(1.0) - col.xyz, fac); + outcol.w = col.w; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_layer_weight.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_layer_weight.glsl new file mode 100644 index 00000000000..588d295bcc4 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_layer_weight.glsl @@ -0,0 +1,19 @@ +void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float facing) +{ + N = normalize(N); + + /* fresnel */ + float eta = max(1.0 - blend, 0.00001); + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + + fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta); + + /* facing */ + facing = abs(dot(I_view, N)); + if (blend != 0.5) { + blend = clamp(blend, 0.0, 0.99999); + blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend); + facing = pow(facing, blend); + } + facing = 1.0 - facing; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_light_falloff.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_light_falloff.glsl new file mode 100644 index 00000000000..f3eae653f95 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_light_falloff.glsl @@ -0,0 +1,7 @@ +void node_light_falloff( + float strength, float tsmooth, out float quadratic, out float linear, out float constant) +{ + quadratic = strength; + linear = strength; + constant = strength; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl new file mode 100644 index 00000000000..50c87e3f105 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl @@ -0,0 +1,31 @@ +void node_light_path(out float is_camera_ray, + out float is_shadow_ray, + out float is_diffuse_ray, + out float is_glossy_ray, + out float is_singular_ray, + out float is_reflection_ray, + out float is_transmission_ray, + out float ray_length, + out float ray_depth, + out float diffuse_depth, + out float glossy_depth, + out float transparent_depth, + out float transmission_depth) +{ + /* Supported. */ + is_camera_ray = (rayType == EEVEE_RAY_CAMERA) ? 1.0 : 0.0; + is_shadow_ray = (rayType == EEVEE_RAY_SHADOW) ? 1.0 : 0.0; + is_diffuse_ray = (rayType == EEVEE_RAY_DIFFUSE) ? 1.0 : 0.0; + is_glossy_ray = (rayType == EEVEE_RAY_GLOSSY) ? 1.0 : 0.0; + /* Kind of supported. */ + is_singular_ray = is_glossy_ray; + is_reflection_ray = is_glossy_ray; + is_transmission_ray = is_glossy_ray; + ray_depth = rayDepth; + diffuse_depth = (is_diffuse_ray == 1.0) ? rayDepth : 0.0; + glossy_depth = (is_glossy_ray == 1.0) ? rayDepth : 0.0; + transmission_depth = (is_transmission_ray == 1.0) ? glossy_depth : 0.0; + /* Not supported. */ + ray_length = 1.0; + transparent_depth = 0.0; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_map_range.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_map_range.glsl new file mode 100644 index 00000000000..a185774f4b3 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_map_range.glsl @@ -0,0 +1,10 @@ +void map_range( + float value, float fromMin, float fromMax, float toMin, float toMax, out float result) +{ + if (fromMax != fromMin) { + result = toMin + ((value - fromMin) / (fromMax - fromMin)) * (toMax - toMin); + } + else { + result = 0.0; + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl new file mode 100644 index 00000000000..ef47ac2be98 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl @@ -0,0 +1,7 @@ +void mapping( + vec3 vec, vec4 m0, vec4 m1, vec4 m2, vec4 m3, vec3 minvec, vec3 maxvec, out vec3 outvec) +{ + mat4 mat = mat4(m0, m1, m2, m3); + outvec = (mat * vec4(vec, 1.0)).xyz; + outvec = clamp(outvec, minvec, maxvec); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_math.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_math.glsl new file mode 100644 index 00000000000..4fac770e8fe --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_math.glsl @@ -0,0 +1,130 @@ +void math_add(float a, float b, out float result) +{ + result = a + b; +} + +void math_subtract(float a, float b, out float result) +{ + result = a - b; +} + +void math_multiply(float a, float b, out float result) +{ + result = a * b; +} + +void math_divide(float a, float b, out float result) +{ + result = safe_divide(a, b); +} + +void math_power(float a, float b, out float result) +{ + if (a >= 0.0) { + result = compatible_pow(a, b); + } + else { + float fraction = mod(abs(b), 1.0); + if (fraction > 0.999 || fraction < 0.001) { + result = compatible_pow(a, floor(b + 0.5)); + } + else { + result = 0.0; + } + } +} + +void math_logarithm(float a, float b, out float result) +{ + result = (a > 0.0 && b > 0.0) ? log2(a) / log2(b) : 0.0; +} + +void math_sqrt(float a, float b, out float result) +{ + result = (a > 0.0) ? sqrt(a) : 0.0; +} + +void math_absolute(float a, float b, out float result) +{ + result = abs(a); +} + +void math_minimum(float a, float b, out float result) +{ + result = min(a, b); +} + +void math_maximum(float a, float b, out float result) +{ + result = max(a, b); +} + +void math_less_than(float a, float b, out float result) +{ + result = (a < b) ? 1.0 : 0.0; +} + +void math_greater_than(float a, float b, out float result) +{ + result = (a > b) ? 1.0 : 0.0; +} + +void math_round(float a, float b, out float result) +{ + result = floor(a + 0.5); +} + +void math_floor(float a, float b, out float result) +{ + result = floor(a); +} + +void math_ceil(float a, float b, out float result) +{ + result = ceil(a); +} + +void math_fraction(float a, float b, out float result) +{ + result = a - floor(a); +} + +void math_modulo(float a, float b, out float result) +{ + result = c_mod(a, b); +} + +void math_sine(float a, float b, out float result) +{ + result = sin(a); +} + +void math_cosine(float a, float b, out float result) +{ + result = cos(a); +} + +void math_tangent(float a, float b, out float result) +{ + result = tan(a); +} + +void math_arcsine(float a, float b, out float result) +{ + result = (a <= 1.0 && a >= -1.0) ? asin(a) : 0.0; +} + +void math_arccosine(float a, float b, out float result) +{ + result = (a <= 1.0 && a >= -1.0) ? acos(a) : 0.0; +} + +void math_arctangent(float a, float b, out float result) +{ + result = atan(a); +} + +void math_arctan2(float a, float b, out float result) +{ + result = atan(a, b); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl new file mode 100644 index 00000000000..0be7da0cc4c --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl @@ -0,0 +1,101 @@ +/* Float Math */ + +float safe_divide(float a, float b) +{ + return (b != 0.0) ? a / b : 0.0; +} + +/* Modulo with C sign convention. mod in GLSL will take absolute for negative numbers. */ +float c_mod(float a, float b) +{ + return (b != 0.0 && a != b) ? sign(a) * mod(abs(a), b) : 0.0; +} + +float compatible_pow(float x, float y) +{ + if (y == 0.0) { /* x^0 -> 1, including 0^0 */ + return 1.0; + } + + /* glsl pow doesn't accept negative x */ + if (x < 0.0) { + if (mod(-y, 2.0) == 0.0) { + return pow(-x, y); + } + else { + return -pow(-x, y); + } + } + else if (x == 0.0) { + return 0.0; + } + + return pow(x, y); +} + +float hypot(float x, float y) +{ + return sqrt(x * x + y * y); +} + +int floor_to_int(float x) +{ + return int(floor(x)); +} + +int quick_floor(float x) +{ + return int(x) - ((x < 0) ? 1 : 0); +} + +float floorfrac(float x, out int i) +{ + float x_floor = floor(x); + i = int(x_floor); + return x - x_floor; +} + +/* Vector Math */ + +vec3 safe_divide(vec3 a, vec3 b) +{ + return vec3(safe_divide(a.x, b.x), safe_divide(a.y, b.y), safe_divide(a.z, b.z)); +} + +vec3 c_mod(vec3 a, vec3 b) +{ + return vec3(c_mod(a.x, b.x), c_mod(a.y, b.y), c_mod(a.z, b.z)); +} + +void vector_mix(float strength, vec3 a, vec3 b, out vec3 outVector) +{ + outVector = strength * a + (1 - strength) * b; +} + +void invert_z(vec3 v, out vec3 outv) +{ + v.z = -v.z; + outv = v; +} + +void vector_normalize(vec3 normal, out vec3 outnormal) +{ + outnormal = normalize(normal); +} + +/* Matirx Math */ + +void direction_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) +{ + vout = (mat * vec4(vin, 0.0)).xyz; +} + +void normal_transform_transposed_m4v3(vec3 vin, mat4 mat, out vec3 vout) +{ + vout = transpose(mat3(mat)) * vin; +} + +void point_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) +{ + vout = (mat * vec4(vin, 1.0)).xyz; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl new file mode 100644 index 00000000000..abe6081489d --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl @@ -0,0 +1,291 @@ +void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col2, fac); + outcol.a = col1.a; +} + +void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 + col2, fac); + outcol.a = col1.a; +} + +void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 * col2, fac); + outcol.a = col1.a; +} + +void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = vec4(1.0) - (vec4(facm) + fac * (vec4(1.0) - col2)) * (vec4(1.0) - col1); + outcol.a = col1.a; +} + +void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + if (outcol.r < 0.5) { + outcol.r *= facm + 2.0 * fac * col2.r; + } + else { + outcol.r = 1.0 - (facm + 2.0 * fac * (1.0 - col2.r)) * (1.0 - outcol.r); + } + + if (outcol.g < 0.5) { + outcol.g *= facm + 2.0 * fac * col2.g; + } + else { + outcol.g = 1.0 - (facm + 2.0 * fac * (1.0 - col2.g)) * (1.0 - outcol.g); + } + + if (outcol.b < 0.5) { + outcol.b *= facm + 2.0 * fac * col2.b; + } + else { + outcol.b = 1.0 - (facm + 2.0 * fac * (1.0 - col2.b)) * (1.0 - outcol.b); + } +} + +void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 - col2, fac); + outcol.a = col1.a; +} + +void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + if (col2.r != 0.0) { + outcol.r = facm * outcol.r + fac * outcol.r / col2.r; + } + if (col2.g != 0.0) { + outcol.g = facm * outcol.g + fac * outcol.g / col2.g; + } + if (col2.b != 0.0) { + outcol.b = facm * outcol.b + fac * outcol.b / col2.b; + } +} + +void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, abs(col1 - col2), fac); + outcol.a = col1.a; +} + +void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol.rgb = min(col1.rgb, col2.rgb * fac); + outcol.a = col1.a; +} + +void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol.rgb = max(col1.rgb, col2.rgb * fac); + outcol.a = col1.a; +} + +void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = col1; + + if (outcol.r != 0.0) { + float tmp = 1.0 - fac * col2.r; + if (tmp <= 0.0) { + outcol.r = 1.0; + } + else if ((tmp = outcol.r / tmp) > 1.0) { + outcol.r = 1.0; + } + else { + outcol.r = tmp; + } + } + if (outcol.g != 0.0) { + float tmp = 1.0 - fac * col2.g; + if (tmp <= 0.0) { + outcol.g = 1.0; + } + else if ((tmp = outcol.g / tmp) > 1.0) { + outcol.g = 1.0; + } + else { + outcol.g = tmp; + } + } + if (outcol.b != 0.0) { + float tmp = 1.0 - fac * col2.b; + if (tmp <= 0.0) { + outcol.b = 1.0; + } + else if ((tmp = outcol.b / tmp) > 1.0) { + outcol.b = 1.0; + } + else { + outcol.b = tmp; + } + } +} + +void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float tmp, facm = 1.0 - fac; + + outcol = col1; + + tmp = facm + fac * col2.r; + if (tmp <= 0.0) { + outcol.r = 0.0; + } + else if ((tmp = (1.0 - (1.0 - outcol.r) / tmp)) < 0.0) { + outcol.r = 0.0; + } + else if (tmp > 1.0) { + outcol.r = 1.0; + } + else { + outcol.r = tmp; + } + + tmp = facm + fac * col2.g; + if (tmp <= 0.0) { + outcol.g = 0.0; + } + else if ((tmp = (1.0 - (1.0 - outcol.g) / tmp)) < 0.0) { + outcol.g = 0.0; + } + else if (tmp > 1.0) { + outcol.g = 1.0; + } + else { + outcol.g = tmp; + } + + tmp = facm + fac * col2.b; + if (tmp <= 0.0) { + outcol.b = 0.0; + } + else if ((tmp = (1.0 - (1.0 - outcol.b) / tmp)) < 0.0) { + outcol.b = 0.0; + } + else if (tmp > 1.0) { + outcol.b = 1.0; + } + else { + outcol.b = tmp; + } +} + +void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2, tmp; + rgb_to_hsv(col2, hsv2); + + if (hsv2.y != 0.0) { + rgb_to_hsv(outcol, hsv); + hsv.x = hsv2.x; + hsv_to_rgb(hsv, tmp); + + outcol = mix(outcol, tmp, fac); + outcol.a = col1.a; + } +} + +void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2; + rgb_to_hsv(outcol, hsv); + + if (hsv.y != 0.0) { + rgb_to_hsv(col2, hsv2); + + hsv.y = facm * hsv.y + fac * hsv2.y; + hsv_to_rgb(hsv, outcol); + } +} + +void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + vec4 hsv, hsv2; + rgb_to_hsv(col1, hsv); + rgb_to_hsv(col2, hsv2); + + hsv.z = facm * hsv.z + fac * hsv2.z; + hsv_to_rgb(hsv, outcol); +} + +void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2, tmp; + rgb_to_hsv(col2, hsv2); + + if (hsv2.y != 0.0) { + rgb_to_hsv(outcol, hsv); + hsv.x = hsv2.x; + hsv.y = hsv2.y; + hsv_to_rgb(hsv, tmp); + + outcol = mix(outcol, tmp, fac); + outcol.a = col1.a; + } +} + +void mix_soft(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + vec4 one = vec4(1.0); + vec4 scr = one - (one - col2) * (one - col1); + outcol = facm * col1 + fac * ((one - col1) * col2 * col1 + col1 * scr); +} + +void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + + outcol = col1 + fac * (2.0 * (col2 - vec4(0.5))); +} + +void clamp_color(vec3 vec, vec3 min, vec3 max, out vec3 out_vec) +{ + out_vec = clamp(vec, min, max); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl new file mode 100644 index 00000000000..c303d21d7c1 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl @@ -0,0 +1,4 @@ +void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader) +{ + shader = closure_mix(shader1, shader2, fac); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl new file mode 100644 index 00000000000..8c6a10e3fe7 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl @@ -0,0 +1,74 @@ +float noise_fade(float t) +{ + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +float noise_scale3(float result) +{ + return 0.9820 * result; +} + +float noise_nerp(float t, float a, float b) +{ + return (1.0 - t) * a + t * b; +} + +float noise_grad(uint hash, float x, float y, float z) +{ + uint h = hash & 15u; + float u = h < 8u ? x : y; + float vt = ((h == 12u) || (h == 14u)) ? x : z; + float v = h < 4u ? y : vt; + return (((h & 1u) != 0u) ? -u : u) + (((h & 2u) != 0u) ? -v : v); +} + +float noise_perlin(float x, float y, float z) +{ + int X; + float fx = floorfrac(x, X); + int Y; + float fy = floorfrac(y, Y); + int Z; + float fz = floorfrac(z, Z); + + float u = noise_fade(fx); + float v = noise_fade(fy); + float w = noise_fade(fz); + + float noise_u[2], noise_v[2]; + + noise_u[0] = noise_nerp(u, + noise_grad(hash_int3(X, Y, Z), fx, fy, fz), + noise_grad(hash_int3(X + 1, Y, Z), fx - 1.0, fy, fz)); + + noise_u[1] = noise_nerp(u, + noise_grad(hash_int3(X, Y + 1, Z), fx, fy - 1.0, fz), + noise_grad(hash_int3(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz)); + + noise_v[0] = noise_nerp(v, noise_u[0], noise_u[1]); + + noise_u[0] = noise_nerp(u, + noise_grad(hash_int3(X, Y, Z + 1), fx, fy, fz - 1.0), + noise_grad(hash_int3(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0)); + + noise_u[1] = noise_nerp( + u, + noise_grad(hash_int3(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0), + noise_grad(hash_int3(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0)); + + noise_v[1] = noise_nerp(v, noise_u[0], noise_u[1]); + + float r = noise_scale3(noise_nerp(w, noise_v[0], noise_v[1])); + + return (isinf(r)) ? 0.0 : r; +} + +float noise(vec3 p) +{ + return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5; +} + +float snoise(vec3 p) +{ + return noise_perlin(p.x, p.y, p.z); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_normal.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_normal.glsl new file mode 100644 index 00000000000..4f6e68909ad --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_normal.glsl @@ -0,0 +1,5 @@ +void normal_new_shading(vec3 nor, vec3 dir, out vec3 outnor, out float outdot) +{ + outnor = dir; + outdot = dot(normalize(nor), dir); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_normal_map.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_normal_map.glsl new file mode 100644 index 00000000000..6930e0c5dad --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_normal_map.glsl @@ -0,0 +1,22 @@ +void node_normal_map(vec4 info, vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) +{ + if (all(equal(tangent, vec4(0.0, 0.0, 0.0, 1.0)))) { + outnormal = normal; + return; + } + tangent *= (gl_FrontFacing ? 1.0 : -1.0); + vec3 B = tangent.w * cross(normal, tangent.xyz) * info.w; + + outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal; + outnormal = normalize(outnormal); +} + +void color_to_normal_new_shading(vec3 color, out vec3 normal) +{ + normal = vec3(2.0) * color - vec3(1.0); +} + +void color_to_blender_normal_new_shading(vec3 color, out vec3 normal) +{ + normal = vec3(2.0, -2.0, -2.0) * color - vec3(1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl new file mode 100644 index 00000000000..ff77b0beea2 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl @@ -0,0 +1,16 @@ +void node_object_info(mat4 obmat, + vec4 obcolor, + vec4 info, + float mat_index, + out vec3 location, + out vec4 color, + out float object_index, + out float material_index, + out float random) +{ + location = obmat[3].xyz; + color = obcolor; + object_index = info.x; + material_index = mat_index; + random = info.z; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl new file mode 100644 index 00000000000..62f76d46088 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl @@ -0,0 +1,8 @@ +void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result) +{ +#ifdef VOLUMETRICS + result = volume; +#else + result = surface; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_output_world.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_output_world.glsl new file mode 100644 index 00000000000..ba391df185e --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_output_world.glsl @@ -0,0 +1,11 @@ +uniform float backgroundAlpha; + +void node_output_world(Closure surface, Closure volume, out Closure result) +{ +#ifndef VOLUMETRICS + result.radiance = surface.radiance * backgroundAlpha; + result.transmittance = vec3(1.0 - backgroundAlpha); +#else + result = volume; +#endif /* VOLUMETRICS */ +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_particle_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_particle_info.glsl new file mode 100644 index 00000000000..bdd60c20a81 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_particle_info.glsl @@ -0,0 +1,23 @@ +void particle_info(vec4 sprops, + vec4 loc, + vec3 vel, + vec3 avel, + out float index, + out float random, + out float age, + out float life_time, + out vec3 location, + out float size, + out vec3 velocity, + out vec3 angular_velocity) +{ + index = sprops.x; + random = loc.w; + age = sprops.y; + life_time = sprops.z; + size = sprops.w; + + location = loc.xyz; + velocity = vel; + angular_velocity = avel; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl new file mode 100644 index 00000000000..c6b640c572d --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -0,0 +1,439 @@ +#ifndef VOLUMETRICS +vec3 tint_from_color(vec3 color) +{ + float lum = dot(color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */ + return (lum > 0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */ +} + +void convert_metallic_to_specular_tinted(vec3 basecol, + vec3 basecol_tint, + float metallic, + float specular_fac, + float specular_tint, + out vec3 diffuse, + out vec3 f0) +{ + vec3 tmp_col = mix(vec3(1.0), basecol_tint, specular_tint); + f0 = mix((0.08 * specular_fac) * tmp_col, basecol, metallic); + diffuse = basecol * (1.0 - metallic); +} + +vec3 principled_sheen(float NV, vec3 basecol_tint, float sheen_tint) +{ + float f = 1.0 - NV; + /* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps, + * therefore we need to clamp value. */ + f = clamp(f, 0.0, 1.0); + /* Empirical approximation (manual curve fitting). Can be refined. */ + float sheen = f * f * f * 0.077 + f * 0.01 + 0.00026; + return sheen * mix(vec3(1.0), basecol_tint, sheen_tint); +} + +void node_bsdf_principled(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + N = normalize(N); + ior = max(ior, 1e-5); + metallic = saturate(metallic); + transmission = saturate(transmission); + float dielectric = 1.0 - metallic; + transmission *= dielectric; + sheen *= dielectric; + subsurface_color *= dielectric; + + vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec; + vec3 ctint = tint_from_color(base_color.rgb); + convert_metallic_to_specular_tinted( + base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); + + float NV = dot(N, cameraVec); + vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + + /* Far from being accurate, but 2 glossy evaluation is too expensive. + * Most noticeable difference is at grazing angles since the bsdf lut + * f0 color interpolation is done on top of this interpolation. */ + vec3 f0_glass = mix(vec3(1.0), base_color.rgb, specular_tint); + float fresnel = F_eta(ior, NV); + vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel; + f0 = mix(f0, spec_col, transmission); + + vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic); + + vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); + + float sss_scalef = avg(sss_scale) * subsurface; + eevee_closure_principled(N, + mixed_ss_base_color, + f0, + f90, + int(ssr_id), + roughness, + CN, + clearcoat * 0.25, + clearcoat_roughness, + 1.0, + sss_scalef, + ior, + out_diff, + out_trans, + out_spec, + out_refr, + ssr_spec); + + vec3 refr_color = base_color.rgb; + refr_color *= (refractionDepth > 0.0) ? refr_color : + vec3(1.0); /* Simulate 2 transmission event */ + out_refr *= refr_color * (1.0 - fresnel) * transmission; + + result = CLOSURE_DEFAULT; + result.radiance = out_spec + out_refr; + result.radiance += out_diff * out_sheen; /* Coarse approx. */ + + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + + vec3 sss_radiance = (out_diff + out_trans) * alpha; +# ifndef USE_SSS + result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission); +# else +# ifdef USE_SSS_ALBEDO + vec3 sss_albedo = mixed_ss_base_color; +# else + sss_radiance *= mixed_ss_base_color; +# endif + sss_radiance *= (1.0 - transmission); + closure_load_sss_data(sss_scalef, + sss_radiance, +# ifdef USE_SSS_ALBEDO + sss_albedo, +# endif + int(sss_id), + result); +# endif /* USE_SSS */ + + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} + +void node_bsdf_principled_dielectric(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + N = normalize(N); + metallic = saturate(metallic); + float dielectric = 1.0 - metallic; + + vec3 diffuse, f0, out_diff, out_spec, ssr_spec; + vec3 ctint = tint_from_color(base_color.rgb); + convert_metallic_to_specular_tinted( + base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); + + float NV = dot(N, cameraVec); + vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + + eevee_closure_default( + N, diffuse, f0, vec3(1.0), int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec); + + result = CLOSURE_DEFAULT; + result.radiance = out_spec + out_diff * (diffuse + out_sheen); + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} + +void node_bsdf_principled_metallic(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + N = normalize(N); + vec3 out_spec, ssr_spec; + + vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); + + eevee_closure_glossy(N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, out_spec, ssr_spec); + + result = CLOSURE_DEFAULT; + result.radiance = out_spec; + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} + +void node_bsdf_principled_clearcoat(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + vec3 out_spec, ssr_spec; + N = normalize(N); + + vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); + + eevee_closure_clearcoat(N, + base_color.rgb, + f90, + int(ssr_id), + roughness, + CN, + clearcoat * 0.25, + clearcoat_roughness, + 1.0, + out_spec, + ssr_spec); + + result = CLOSURE_DEFAULT; + result.radiance = out_spec; + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} + +void node_bsdf_principled_subsurface(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + metallic = saturate(metallic); + N = normalize(N); + + vec3 diffuse, f0, out_diff, out_spec, out_trans, ssr_spec; + vec3 ctint = tint_from_color(base_color.rgb); + convert_metallic_to_specular_tinted( + base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); + + subsurface_color = subsurface_color * (1.0 - metallic); + vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); + float sss_scalef = avg(sss_scale) * subsurface; + + float NV = dot(N, cameraVec); + vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + + vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); + + eevee_closure_skin(N, + mixed_ss_base_color, + f0, + f90, + int(ssr_id), + roughness, + 1.0, + sss_scalef, + out_diff, + out_trans, + out_spec, + ssr_spec); + + result = CLOSURE_DEFAULT; + result.radiance = out_spec; + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + + vec3 sss_radiance = (out_diff + out_trans) * alpha; +# ifndef USE_SSS + result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission); +# else +# ifdef USE_SSS_ALBEDO + vec3 sss_albedo = mixed_ss_base_color; +# else + sss_radiance *= mixed_ss_base_color; +# endif + sss_radiance *= (1.0 - transmission); + closure_load_sss_data(sss_scalef, + sss_radiance, +# ifdef USE_SSS_ALBEDO + sss_albedo, +# endif + int(sss_id), + result); +# endif /* USE_SSS */ + + result.radiance += out_diff * out_sheen; + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} + +void node_bsdf_principled_glass(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec4 emission, + float alpha, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + ior = max(ior, 1e-5); + N = normalize(N); + + vec3 f0, out_spec, out_refr, ssr_spec; + f0 = mix(vec3(1.0), base_color.rgb, specular_tint); + + eevee_closure_glass( + N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); + + vec3 refr_color = base_color.rgb; + refr_color *= (refractionDepth > 0.0) ? refr_color : + vec3(1.0); /* Simulate 2 transmission events */ + out_refr *= refr_color; + + float fresnel = F_eta(ior, dot(N, cameraVec)); + vec3 spec_col = F_color_blend(ior, fresnel, f0); + out_spec *= spec_col; + ssr_spec *= spec_col * fresnel; + + result = CLOSURE_DEFAULT; + result.radiance = mix(out_refr, out_spec, fresnel); + closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); + result.radiance += emission.rgb; + result.radiance *= alpha; + result.transmittance = vec3(1.0 - alpha); +} +#else +/* Stub principled because it is not compatible with volumetrics. */ +# define node_bsdf_principled +# define node_bsdf_principled_dielectric +# define node_bsdf_principled_metallic +# define node_bsdf_principled_clearcoat +# define node_bsdf_principled_subsurface +# define node_bsdf_principled_glass +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl new file mode 100644 index 00000000000..04394a9420b --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl @@ -0,0 +1,16 @@ +#ifndef VOLUMETRICS +void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result) +{ + N = normalize(N); + vec3 out_refr; + color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */ + eevee_closure_refraction(N, roughness, ior, out_refr); + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.radiance = out_refr * color.rgb; +} +#else +/* Stub refraction because it is not compatible with volumetrics. */ +# define node_bsdf_refraction +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_rgb_curves.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_curves.glsl new file mode 100644 index 00000000000..054fdddf7c3 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_curves.glsl @@ -0,0 +1,73 @@ +/* ext is vec4(in_x, in_dy, out_x, out_dy). */ +float curve_extrapolate(float x, float y, vec4 ext) +{ + if (x < 0.0) { + return y + x * ext.y; + } + else if (x > 1.0) { + return y + (x - 1.0) * ext.w; + } + else { + return y; + } +} + +#define RANGE_RESCALE(x, min, range) ((x - min) * range) + +void curves_rgb(float fac, + vec4 col, + sampler1DArray curvemap, + float layer, + vec4 range, + vec4 ext_r, + vec4 ext_g, + vec4 ext_b, + vec4 ext_a, + out vec4 outcol) +{ + vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); + vec3 samp; + samp.r = texture(curvemap, co.xw).a; + samp.g = texture(curvemap, co.yw).a; + samp.b = texture(curvemap, co.zw).a; + + samp.r = curve_extrapolate(co.x, samp.r, ext_a); + samp.g = curve_extrapolate(co.y, samp.g, ext_a); + samp.b = curve_extrapolate(co.z, samp.b, ext_a); + + vec3 rgb_min = vec3(ext_r.x, ext_g.x, ext_b.x); + co.xyz = RANGE_RESCALE(samp.rgb, rgb_min, range.rgb); + + samp.r = texture(curvemap, co.xw).r; + samp.g = texture(curvemap, co.yw).g; + samp.b = texture(curvemap, co.zw).b; + + outcol.r = curve_extrapolate(co.x, samp.r, ext_r); + outcol.g = curve_extrapolate(co.y, samp.g, ext_g); + outcol.b = curve_extrapolate(co.z, samp.b, ext_b); + outcol.a = col.a; + + outcol = mix(col, outcol, fac); +} + +void curves_rgb_opti(float fac, + vec4 col, + sampler1DArray curvemap, + float layer, + vec4 range, + vec4 ext_a, + out vec4 outcol) +{ + vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); + vec3 samp; + samp.r = texture(curvemap, co.xw).a; + samp.g = texture(curvemap, co.yw).a; + samp.b = texture(curvemap, co.zw).a; + + outcol.r = curve_extrapolate(co.x, samp.r, ext_a); + outcol.g = curve_extrapolate(co.y, samp.g, ext_a); + outcol.b = curve_extrapolate(co.z, samp.b, ext_a); + outcol.a = col.a; + + outcol = mix(col, outcol, fac); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_rgb_to_bw.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_to_bw.glsl new file mode 100644 index 00000000000..ceca02a2356 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_to_bw.glsl @@ -0,0 +1,5 @@ +void rgbtobw(vec4 color, out float outval) +{ + vec3 factors = vec3(0.2126, 0.7152, 0.0722); + outval = dot(color.rgb, factors); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_separate_hsv.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_separate_hsv.glsl new file mode 100644 index 00000000000..fb64e424c6c --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_separate_hsv.glsl @@ -0,0 +1,9 @@ +void separate_hsv(vec4 col, out float h, out float s, out float v) +{ + vec4 hsv; + + rgb_to_hsv(col, hsv); + h = hsv[0]; + s = hsv[1]; + v = hsv[2]; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_separate_rgb.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_separate_rgb.glsl new file mode 100644 index 00000000000..4232b4c001e --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_separate_rgb.glsl @@ -0,0 +1,6 @@ +void separate_rgb(vec4 col, out float r, out float g, out float b) +{ + r = col.r; + g = col.g; + b = col.b; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_separate_xyz.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_separate_xyz.glsl new file mode 100644 index 00000000000..fac29ccc135 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_separate_xyz.glsl @@ -0,0 +1,6 @@ +void separate_xyz(vec3 vec, out float x, out float y, out float z) +{ + x = vec.r; + y = vec.g; + z = vec.b; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_set.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_set.glsl new file mode 100644 index 00000000000..dc2ecb05351 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_set.glsl @@ -0,0 +1,44 @@ +void set_value(float val, out float outval) +{ + outval = val; +} + +void set_rgb(vec3 col, out vec3 outcol) +{ + outcol = col; +} + +void set_rgba(vec4 col, out vec4 outcol) +{ + outcol = col; +} + +void set_value_zero(out float outval) +{ + outval = 0.0; +} + +void set_value_one(out float outval) +{ + outval = 1.0; +} + +void set_rgb_zero(out vec3 outval) +{ + outval = vec3(0.0); +} + +void set_rgb_one(out vec3 outval) +{ + outval = vec3(1.0); +} + +void set_rgba_zero(out vec4 outval) +{ + outval = vec4(0.0); +} + +void set_rgba_one(out vec4 outval) +{ + outval = vec4(1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl new file mode 100644 index 00000000000..0a587c7e471 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl @@ -0,0 +1,25 @@ +#ifndef VOLUMETRICS +void node_shader_to_rgba(Closure cl, out vec4 outcol, out float outalpha) +{ + vec4 spec_accum = vec4(0.0); + if (ssrToggle && FLAG_TEST(cl.flag, CLOSURE_SSR_FLAG)) { + vec3 V = cameraVec; + vec3 vN = normal_decode(cl.ssr_normal, viewCameraVec); + vec3 N = transform_direction(ViewMatrixInverse, vN); + float roughness = cl.ssr_data.a; + float roughnessSquared = max(1e-3, roughness * roughness); + fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum); + } + + outalpha = avg(cl.transmittance); + outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0); + +# ifdef USE_SSS +# ifdef USE_SSS_ALBEDO + outcol.rgb += cl.sss_data.rgb * cl.sss_albedo; +# else + outcol.rgb += cl.sss_data.rgb; +# endif +# endif +} +#endif /* VOLUMETRICS */ diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_squeeze.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_squeeze.glsl new file mode 100644 index 00000000000..b73bdebf7f6 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_squeeze.glsl @@ -0,0 +1,4 @@ +void squeeze(float val, float width, float center, out float outval) +{ + outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width))); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl new file mode 100644 index 00000000000..fc81f3c4674 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl @@ -0,0 +1,42 @@ +#ifndef VOLUMETRICS +void node_subsurface_scattering(vec4 color, + float scale, + vec3 radius, + float sharpen, + float texture_blur, + vec3 N, + float sss_id, + out Closure result) +{ +# if defined(USE_SSS) + N = normalize(N); + vec3 out_diff, out_trans; + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result); + + eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans); + + vec3 sss_radiance = out_diff + out_trans; +# ifdef USE_SSS_ALBEDO + /* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */ + vec3 sss_albedo = mix(color.rgb, vec3(1.0), texture_blur); + sss_radiance *= mix(vec3(1.0), color.rgb, texture_blur); +# else + sss_radiance *= color.rgb; +# endif + closure_load_sss_data(scale, + sss_radiance, +# ifdef USE_SSS_ALBEDO + sss_albedo, +# endif + int(sss_id), + result); +# else + node_bsdf_diffuse(color, 0.0, N, result); +# endif +} +#else +/* Stub subsurface scattering because it is not compatible with volumetrics. */ +# define node_subsurface_scattering +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tangent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tangent.glsl new file mode 100644 index 00000000000..ff2dbc7ead3 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tangent.glsl @@ -0,0 +1,25 @@ +void tangent_orco_x(vec3 orco_in, out vec3 orco_out) +{ + orco_out = orco_in.xzy * vec3(0.0, -0.5, 0.5) + vec3(0.0, 0.25, -0.25); +} + +void tangent_orco_y(vec3 orco_in, out vec3 orco_out) +{ + orco_out = orco_in.zyx * vec3(-0.5, 0.0, 0.5) + vec3(0.25, 0.0, -0.25); +} + +void tangent_orco_z(vec3 orco_in, out vec3 orco_out) +{ + orco_out = orco_in.yxz * vec3(-0.5, 0.5, 0.0) + vec3(0.25, -0.25, 0.0); +} + +void node_tangentmap(vec4 attr_tangent, out vec3 tangent) +{ + tangent = normalize(attr_tangent.xyz); +} + +void node_tangent(vec3 N, vec3 orco, mat4 objmat, out vec3 T) +{ + T = (objmat * vec4(orco, 0.0)).xyz; + T = cross(N, normalize(cross(T, N))); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl new file mode 100644 index 00000000000..e252e5ba726 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl @@ -0,0 +1,78 @@ +vec2 calc_brick_texture(vec3 p, + float mortar_size, + float mortar_smooth, + float bias, + float brick_width, + float row_height, + float offset_amount, + int offset_frequency, + float squash_amount, + int squash_frequency) +{ + int bricknum, rownum; + float offset = 0.0; + float x, y; + + rownum = floor_to_int(p.y / row_height); + + if (offset_frequency != 0 && squash_frequency != 0) { + brick_width *= (rownum % squash_frequency != 0) ? 1.0 : squash_amount; /* squash */ + offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width * offset_amount); /* offset */ + } + + bricknum = floor_to_int((p.x + offset) / brick_width); + + x = (p.x + offset) - brick_width * bricknum; + y = p.y - row_height * rownum; + + float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0); + + float min_dist = min(min(x, y), min(brick_width - x, row_height - y)); + if (min_dist >= mortar_size) { + return vec2(tint, 0.0); + } + else if (mortar_smooth == 0.0) { + return vec2(tint, 1.0); + } + else { + min_dist = 1.0 - min_dist / mortar_size; + return vec2(tint, smoothstep(0.0, mortar_smooth, min_dist)); + } +} + +void node_tex_brick(vec3 co, + vec4 color1, + vec4 color2, + vec4 mortar, + float scale, + float mortar_size, + float mortar_smooth, + float bias, + float brick_width, + float row_height, + float offset_amount, + float offset_frequency, + float squash_amount, + float squash_frequency, + out vec4 color, + out float fac) +{ + vec2 f2 = calc_brick_texture(co * scale, + mortar_size, + mortar_smooth, + bias, + brick_width, + row_height, + offset_amount, + int(offset_frequency), + squash_amount, + int(squash_frequency)); + float tint = f2.x; + float f = f2.y; + if (f != 1.0) { + float facm = 1.0 - tint; + color1 = facm * color1 + tint * color2; + } + color = mix(color1, mortar, f); + fac = f; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl new file mode 100644 index 00000000000..f534f3bddf3 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl @@ -0,0 +1,17 @@ +void node_tex_checker( + vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac) +{ + vec3 p = co * scale; + + /* Prevent precision issues on unit coordinates. */ + p = (p + 0.000001) * 0.999999; + + int xi = int(abs(floor(p.x))); + int yi = int(abs(floor(p.y))); + int zi = int(abs(floor(p.z))); + + bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2))); + + color = check ? color1 : color2; + fac = check ? 1.0 : 0.0; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl new file mode 100644 index 00000000000..9bd36f8a757 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl @@ -0,0 +1,44 @@ +void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec) +{ +#ifdef MESH_SHADER + worldvec = worldPosition; +#else + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); + + vec3 co = co_homogenous.xyz / co_homogenous.w; +# if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) + worldvec = mat3(ViewMatrixInverse) * co; +# else + worldvec = mat3(ModelMatrixInverse) * (mat3(ViewMatrixInverse) * co); +# endif +#endif +} + +void node_tex_environment_equirectangular(vec3 co, float clamp_size, sampler2D ima, out vec3 uv) +{ + vec3 nco = normalize(co); + uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; + uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; + + /* Fix pole bleeding */ + float half_height = clamp_size / float(textureSize(ima, 0).y); + uv.y = clamp(uv.y, half_height, 1.0 - half_height); + uv.z = 0.0; +} + +void node_tex_environment_mirror_ball(vec3 co, out vec3 uv) +{ + vec3 nco = normalize(co); + nco.y -= 1.0; + + float div = 2.0 * sqrt(max(-0.5 * nco.y, 0.0)); + nco /= max(1e-8, div); + + uv = 0.5 * nco.xzz + 0.5; +} + +void node_tex_environment_empty(vec3 co, out vec4 color) +{ + color = vec4(1.0, 0.0, 1.0, 1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_gradient.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_gradient.glsl new file mode 100644 index 00000000000..f2f7e615267 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_gradient.glsl @@ -0,0 +1,47 @@ +float calc_gradient(vec3 p, int gradient_type) +{ + float x, y, z; + x = p.x; + y = p.y; + z = p.z; + if (gradient_type == 0) { /* linear */ + return x; + } + else if (gradient_type == 1) { /* quadratic */ + float r = max(x, 0.0); + return r * r; + } + else if (gradient_type == 2) { /* easing */ + float r = min(max(x, 0.0), 1.0); + float t = r * r; + return (3.0 * t - 2.0 * t * r); + } + else if (gradient_type == 3) { /* diagonal */ + return (x + y) * 0.5; + } + else if (gradient_type == 4) { /* radial */ + return atan(y, x) / (M_PI * 2) + 0.5; + } + else { + /* Bias a little bit for the case where p is a unit length vector, + * to get exactly zero instead of a small random value depending + * on float precision. */ + float r = max(0.999999 - sqrt(x * x + y * y + z * z), 0.0); + if (gradient_type == 5) { /* quadratic sphere */ + return r * r; + } + else if (gradient_type == 6) { /* sphere */ + return r; + } + } + return 0.0; +} + +void node_tex_gradient(vec3 co, float gradient_type, out vec4 color, out float fac) +{ + float f = calc_gradient(co, int(gradient_type)); + f = clamp(f, 0.0, 1.0); + + color = vec4(f, f, f, 1.0); + fac = f; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl new file mode 100644 index 00000000000..c234e064d36 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl @@ -0,0 +1,355 @@ +void point_texco_remap_square(vec3 vin, out vec3 vout) +{ + vout = vin * 2.0 - 1.0; +} + +void point_texco_clamp(vec3 vin, sampler2D ima, out vec3 vout) +{ + vec2 half_texel_size = 0.5 / vec2(textureSize(ima, 0).xy); + vout = clamp(vin, half_texel_size.xyy, 1.0 - half_texel_size.xyy); +} + +void point_map_to_sphere(vec3 vin, out vec3 vout) +{ + float len = length(vin); + float v, u; + if (len > 0.0) { + if (vin.x == 0.0 && vin.y == 0.0) { + u = 0.0; + } + else { + u = (1.0 - atan(vin.x, vin.y) / M_PI) / 2.0; + } + + v = 1.0 - acos(vin.z / len) / M_PI; + } + else { + v = u = 0.0; + } + + vout = vec3(u, v, 0.0); +} + +void point_map_to_tube(vec3 vin, out vec3 vout) +{ + float u, v; + v = (vin.z + 1.0) * 0.5; + float len = sqrt(vin.x * vin.x + vin.y * vin[1]); + if (len > 0.0) { + u = (1.0 - (atan(vin.x / len, vin.y / len) / M_PI)) * 0.5; + } + else { + v = u = 0.0; + } + + vout = vec3(u, v, 0.0); +} + +/* 16bits floats limits. Higher/Lower values produce +/-inf. */ +#define safe_color(a) (clamp(a, -65520.0, 65520.0)) + +void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + color = safe_color(texture(ima, co.xy)); + alpha = color.a; +} + +void node_tex_image_linear_no_mip(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + color = safe_color(textureLod(ima, co.xy, 0.0)); + alpha = color.a; +} + +void node_tex_image_nearest(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + ivec2 pix = ivec2(fract(co.xy) * textureSize(ima, 0).xy); + color = safe_color(texelFetch(ima, pix, 0)); + alpha = color.a; +} + +/* @arg f: signed distance to texel center. */ +void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3) +{ + vec2 f2 = f * f; + vec2 f3 = f2 * f; + /* Bspline coefs (optimized) */ + w3 = f3 / 6.0; + w0 = -w3 + f2 * 0.5 - f * 0.5 + 1.0 / 6.0; + w1 = f3 * 0.5 - f2 * 1.0 + 2.0 / 3.0; + w2 = 1.0 - w0 - w1 - w3; +} + +void node_tex_image_cubic_ex( + vec3 co, sampler2D ima, float do_extend, out vec4 color, out float alpha) +{ + vec2 tex_size = vec2(textureSize(ima, 0).xy); + + co.xy *= tex_size; + /* texel center */ + vec2 tc = floor(co.xy - 0.5) + 0.5; + vec2 w0, w1, w2, w3; + cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); + +#if 1 /* Optimized version using 4 filtered tap. */ + vec2 s0 = w0 + w1; + vec2 s1 = w2 + w3; + + vec2 f0 = w1 / (w0 + w1); + vec2 f1 = w3 / (w2 + w3); + + vec4 final_co; + final_co.xy = tc - 1.0 + f0; + final_co.zw = tc + 1.0 + f1; + + if (do_extend == 1.0) { + final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5); + } + final_co /= tex_size.xyxy; + + color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y; + color += safe_color(textureLod(ima, final_co.zy, 0.0)) * s1.x * s0.y; + color += safe_color(textureLod(ima, final_co.xw, 0.0)) * s0.x * s1.y; + color += safe_color(textureLod(ima, final_co.zw, 0.0)) * s1.x * s1.y; + +#else /* Reference bruteforce 16 tap. */ + color = texelFetch(ima, ivec2(tc + vec2(-1.0, -1.0)), 0) * w0.x * w0.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, -1.0)), 0) * w1.x * w0.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, -1.0)), 0) * w2.x * w0.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, -1.0)), 0) * w3.x * w0.y; + + color += texelFetch(ima, ivec2(tc + vec2(-1.0, 0.0)), 0) * w0.x * w1.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, 0.0)), 0) * w1.x * w1.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, 0.0)), 0) * w2.x * w1.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, 0.0)), 0) * w3.x * w1.y; + + color += texelFetch(ima, ivec2(tc + vec2(-1.0, 1.0)), 0) * w0.x * w2.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, 1.0)), 0) * w1.x * w2.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, 1.0)), 0) * w2.x * w2.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, 1.0)), 0) * w3.x * w2.y; + + color += texelFetch(ima, ivec2(tc + vec2(-1.0, 2.0)), 0) * w0.x * w3.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, 2.0)), 0) * w1.x * w3.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, 2.0)), 0) * w2.x * w3.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, 2.0)), 0) * w3.x * w3.y; +#endif + + alpha = color.a; +} + +void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); +} + +void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + node_tex_image_cubic_ex(co, ima, 1.0, color, alpha); +} + +void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + /* use cubic for now */ + node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); +} + +void tex_box_sample_linear( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + /* X projection */ + vec2 uv = texco.yz; + if (N.x < 0.0) { + uv.x = 1.0 - uv.x; + } + color1 = texture(ima, uv); + /* Y projection */ + uv = texco.xz; + if (N.y > 0.0) { + uv.x = 1.0 - uv.x; + } + color2 = texture(ima, uv); + /* Z projection */ + uv = texco.yx; + if (N.z > 0.0) { + uv.x = 1.0 - uv.x; + } + color3 = texture(ima, uv); +} + +void tex_box_sample_nearest( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + /* X projection */ + vec2 uv = texco.yz; + if (N.x < 0.0) { + uv.x = 1.0 - uv.x; + } + ivec2 pix = ivec2(uv.xy * textureSize(ima, 0).xy); + color1 = texelFetch(ima, pix, 0); + /* Y projection */ + uv = texco.xz; + if (N.y > 0.0) { + uv.x = 1.0 - uv.x; + } + pix = ivec2(uv.xy * textureSize(ima, 0).xy); + color2 = texelFetch(ima, pix, 0); + /* Z projection */ + uv = texco.yx; + if (N.z > 0.0) { + uv.x = 1.0 - uv.x; + } + pix = ivec2(uv.xy * textureSize(ima, 0).xy); + color3 = texelFetch(ima, pix, 0); +} + +void tex_box_sample_cubic( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + float alpha; + /* X projection */ + vec2 uv = texco.yz; + if (N.x < 0.0) { + uv.x = 1.0 - uv.x; + } + node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color1, alpha); + /* Y projection */ + uv = texco.xz; + if (N.y > 0.0) { + uv.x = 1.0 - uv.x; + } + node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha); + /* Z projection */ + uv = texco.yx; + if (N.z > 0.0) { + uv.x = 1.0 - uv.x; + } + node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color3, alpha); +} + +void tex_box_sample_smart( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + tex_box_sample_cubic(texco, N, ima, color1, color2, color3); +} + +void node_tex_image_box(vec3 texco, + vec3 N, + vec4 color1, + vec4 color2, + vec4 color3, + sampler2D ima, + float blend, + out vec4 color, + out float alpha) +{ + /* project from direction vector to barycentric coordinates in triangles */ + N = abs(N); + N /= dot(N, vec3(1.0)); + + /* basic idea is to think of this as a triangle, each corner representing + * one of the 3 faces of the cube. in the corners we have single textures, + * in between we blend between two textures, and in the middle we a blend + * between three textures. + * + * the Nxyz values are the barycentric coordinates in an equilateral + * triangle, which in case of blending, in the middle has a smaller + * equilateral triangle where 3 textures blend. this divides things into + * 7 zones, with an if () test for each zone + * EDIT: Now there is only 4 if's. */ + + float limit = 0.5 + 0.5 * blend; + + vec3 weight; + weight = N.xyz / (N.xyx + N.yzz); + weight = clamp((weight - 0.5 * (1.0 - blend)) / max(1e-8, blend), 0.0, 1.0); + + /* test for mixes between two textures */ + if (N.z < (1.0 - limit) * (N.y + N.x)) { + weight.z = 0.0; + weight.y = 1.0 - weight.x; + } + else if (N.x < (1.0 - limit) * (N.y + N.z)) { + weight.x = 0.0; + weight.z = 1.0 - weight.y; + } + else if (N.y < (1.0 - limit) * (N.x + N.z)) { + weight.y = 0.0; + weight.x = 1.0 - weight.z; + } + else { + /* last case, we have a mix between three */ + weight = ((2.0 - limit) * N + (limit - 1.0)) / max(1e-8, blend); + } + + color = weight.x * color1 + weight.y * color2 + weight.z * color3; + alpha = color.a; +} + +void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) +{ + vec2 tex_size = vec2(textureSize(ima, 0).xy); + vec2 minco = min(co.xy, 1.0 - co.xy); + minco = clamp(minco * tex_size + 0.5, 0.0, 1.0); + float fac = minco.x * minco.y; + + color = mix(vec4(0.0), icolor, fac); + alpha = color.a; +} + +void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) +{ + vec4 minco = vec4(co.xy, 1.0 - co.xy); + color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor; + alpha = color.a; +} + +void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) +{ + vec2 tex_size = vec2(textureSize(ima, 0).xy); + + co.xy *= tex_size; + /* texel center */ + vec2 tc = floor(co.xy - 0.5) + 0.5; + vec2 w0, w1, w2, w3; + cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); + + /* TODO Optimize this part. I'm sure there is a smarter way to do that. + * Could do that when sampling? */ +#define CLIP_CUBIC_SAMPLE(samp, size) \ + (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size)))) + ivec2 itex_size = textureSize(ima, 0).xy; + float fac; + fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, -1.0), itex_size) * w1.x * w0.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, -1.0), itex_size) * w2.x * w0.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, -1.0), itex_size) * w3.x * w0.y; + + fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 0.0), itex_size) * w1.x * w1.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 0.0), itex_size) * w2.x * w1.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 0.0), itex_size) * w3.x * w1.y; + + fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 1.0), itex_size) * w1.x * w2.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 1.0), itex_size) * w2.x * w2.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 1.0), itex_size) * w3.x * w2.y; + + fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 2.0), itex_size) * w1.x * w3.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 2.0), itex_size) * w2.x * w3.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 2.0), itex_size) * w3.x * w3.y; +#undef CLIP_CUBIC_SAMPLE + + color = mix(vec4(0.0), icolor, fac); + alpha = color.a; +} + +void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) +{ + tex_clip_cubic(co, ima, icolor, color, alpha); +} + +void node_tex_image_empty(vec3 co, out vec4 color, out float alpha) +{ + color = vec4(0.0); + alpha = 0.0; +} diff --git a/source/blender/gpu/shaders/gpu_shader_material_magic.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_magic.glsl index 942c507cc38..942c507cc38 100644 --- a/source/blender/gpu/shaders/gpu_shader_material_magic.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_magic.glsl diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl new file mode 100644 index 00000000000..52332c45c3d --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl @@ -0,0 +1,208 @@ +/* Musgrave fBm + * + * H: fractal increment parameter + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * + * from "Texturing and Modelling: A procedural approach" + */ + +float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves) +{ + float rmd; + float value = 0.0; + float pwr = 1.0; + float pwHL = pow(lacunarity, -H); + + for (int i = 0; i < int(octaves); i++) { + value += snoise(p) * pwr; + pwr *= pwHL; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) { + value += rmd * snoise(p) * pwr; + } + + return value; +} + +/* Musgrave Multifractal + * + * H: highest fractal dimension + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + */ + +float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octaves) +{ + float rmd; + float value = 1.0; + float pwr = 1.0; + float pwHL = pow(lacunarity, -H); + + for (int i = 0; i < int(octaves); i++) { + value *= (pwr * snoise(p) + 1.0); + pwr *= pwHL; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) { + value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */ + } + + return value; +} + +/* Musgrave Heterogeneous Terrain + * + * H: fractal dimension of the roughest area + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * offset: raises the terrain from `sea level' + */ + +float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset) +{ + float value, increment, rmd; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; + + /* first unscaled octave of function; later octaves are scaled */ + value = offset + snoise(p); + p *= lacunarity; + + for (int i = 1; i < int(octaves); i++) { + increment = (snoise(p) + offset) * pwr * value; + value += increment; + pwr *= pwHL; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) { + increment = (snoise(p) + offset) * pwr * value; + value += rmd * increment; + } + + return value; +} + +/* Hybrid Additive/Multiplicative Multifractal Terrain + * + * H: fractal dimension of the roughest area + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * offset: raises the terrain from `sea level' + */ + +float noise_musgrave_hybrid_multi_fractal( + vec3 p, float H, float lacunarity, float octaves, float offset, float gain) +{ + float result, signal, weight, rmd; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; + + result = snoise(p) + offset; + weight = gain * result; + p *= lacunarity; + + for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) { + if (weight > 1.0) { + weight = 1.0; + } + + signal = (snoise(p) + offset) * pwr; + pwr *= pwHL; + result += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } + + rmd = octaves - floor(octaves); + if (rmd != 0.0) { + result += rmd * ((snoise(p) + offset) * pwr); + } + + return result; +} + +/* Ridged Multifractal Terrain + * + * H: fractal dimension of the roughest area + * lacunarity: gap between successive frequencies + * octaves: number of frequencies in the fBm + * offset: raises the terrain from `sea level' + */ + +float noise_musgrave_ridged_multi_fractal( + vec3 p, float H, float lacunarity, float octaves, float offset, float gain) +{ + float result, signal, weight; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; + + signal = offset - abs(snoise(p)); + signal *= signal; + result = signal; + weight = 1.0; + + for (int i = 1; i < int(octaves); i++) { + p *= lacunarity; + weight = clamp(signal * gain, 0.0, 1.0); + signal = offset - abs(snoise(p)); + signal *= signal; + signal *= weight; + result += signal * pwr; + pwr *= pwHL; + } + + return result; +} + +float svm_musgrave(int type, + float dimension, + float lacunarity, + float octaves, + float offset, + float intensity, + float gain, + vec3 p) +{ + if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */) { + return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves); + } + else if (type == 1 /* NODE_MUSGRAVE_FBM */) { + return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves); + } + else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */) { + return intensity * + noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); + } + else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */) { + return intensity * + noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); + } + else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */) { + return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset); + } + return 0.0; +} + +void node_tex_musgrave(vec3 co, + float scale, + float detail, + float dimension, + float lacunarity, + float offset, + float gain, + float type, + out vec4 color, + out float fac) +{ + fac = svm_musgrave(int(type), dimension, lacunarity, detail, offset, 1.0, gain, co *scale); + + color = vec4(fac, fac, fac, 1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl new file mode 100644 index 00000000000..30e27da16e8 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl @@ -0,0 +1,19 @@ +void node_tex_noise( + vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac) +{ + vec3 p = co * scale; + int hard = 0; + if (distortion != 0.0) { + vec3 r, offset = vec3(13.5, 13.5, 13.5); + r.x = noise(p + offset) * distortion; + r.y = noise(p) * distortion; + r.z = noise(p - offset) * distortion; + p += r; + } + + fac = noise_turbulence(p, detail, hard); + color = vec4(fac, + noise_turbulence(vec3(p.y, p.x, p.z), detail, hard), + noise_turbulence(vec3(p.y, p.z, p.x), detail, hard), + 1); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl new file mode 100644 index 00000000000..981d17b4283 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl @@ -0,0 +1,4 @@ +void node_tex_sky(vec3 co, out vec4 color) +{ + color = vec4(1.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_voronoi.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_voronoi.glsl new file mode 100644 index 00000000000..018b74fd1a5 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_voronoi.glsl @@ -0,0 +1,116 @@ +void node_tex_voronoi(vec3 co, + float scale, + float exponent, + float coloring, + float metric, + float feature, + out vec4 color, + out float fac) +{ + vec3 p = co * scale; + int xx, yy, zz, xi, yi, zi; + vec4 da = vec4(1e10); + vec3 pa[4] = vec3[4](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); + + xi = floor_to_int(p[0]); + yi = floor_to_int(p[1]); + zi = floor_to_int(p[2]); + + for (xx = xi - 1; xx <= xi + 1; xx++) { + for (yy = yi - 1; yy <= yi + 1; yy++) { + for (zz = zi - 1; zz <= zi + 1; zz++) { + vec3 ip = vec3(xx, yy, zz); + vec3 vp = cellnoise_color(ip); + vec3 pd = p - (vp + ip); + + float d = 0.0; + if (metric == 0.0) { /* SHD_VORONOI_DISTANCE 0 */ + d = dot(pd, pd); + } + else if (metric == 1.0) { /* SHD_VORONOI_MANHATTAN 1 */ + d = abs(pd[0]) + abs(pd[1]) + abs(pd[2]); + } + else if (metric == 2.0) { /* SHD_VORONOI_CHEBYCHEV 2 */ + d = max(abs(pd[0]), max(abs(pd[1]), abs(pd[2]))); + } + else if (metric == 3.0) { /* SHD_VORONOI_MINKOWSKI 3 */ + d = pow(pow(abs(pd[0]), exponent) + pow(abs(pd[1]), exponent) + + pow(abs(pd[2]), exponent), + 1.0 / exponent); + } + + vp += vec3(xx, yy, zz); + if (d < da[0]) { + da.yzw = da.xyz; + da[0] = d; + + pa[3] = pa[2]; + pa[2] = pa[1]; + pa[1] = pa[0]; + pa[0] = vp; + } + else if (d < da[1]) { + da.zw = da.yz; + da[1] = d; + + pa[3] = pa[2]; + pa[2] = pa[1]; + pa[1] = vp; + } + else if (d < da[2]) { + da[3] = da[2]; + da[2] = d; + + pa[3] = pa[2]; + pa[2] = vp; + } + else if (d < da[3]) { + da[3] = d; + pa[3] = vp; + } + } + } + } + + if (coloring == 0.0) { + /* Intensity output */ + if (feature == 0.0) { /* F1 */ + fac = abs(da[0]); + } + else if (feature == 1.0) { /* F2 */ + fac = abs(da[1]); + } + else if (feature == 2.0) { /* F3 */ + fac = abs(da[2]); + } + else if (feature == 3.0) { /* F4 */ + fac = abs(da[3]); + } + else if (feature == 4.0) { /* F2F1 */ + fac = abs(da[1] - da[0]); + } + color = vec4(fac, fac, fac, 1.0); + } + else { + /* Color output */ + vec3 col = vec3(fac, fac, fac); + if (feature == 0.0) { /* F1 */ + col = pa[0]; + } + else if (feature == 1.0) { /* F2 */ + col = pa[1]; + } + else if (feature == 2.0) { /* F3 */ + col = pa[2]; + } + else if (feature == 3.0) { /* F4 */ + col = pa[3]; + } + else if (feature == 4.0) { /* F2F1 */ + col = abs(pa[1] - pa[0]); + } + + color = vec4(cellnoise_color(col), 1.0); + fac = (color.x + color.y + color.z) * (1.0 / 3.0); + } +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl new file mode 100644 index 00000000000..2196848a4ef --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl @@ -0,0 +1,42 @@ +float calc_wave( + vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile) +{ + float n; + + if (wave_type == 0) { /* type bands */ + n = (p.x + p.y + p.z) * 10.0; + } + else { /* type rings */ + n = length(p) * 20.0; + } + + if (distortion != 0.0) { + n += distortion * noise_turbulence(p * detail_scale, detail, 0); + } + + if (wave_profile == 0) { /* profile sin */ + return 0.5 + 0.5 * sin(n); + } + else { /* profile saw */ + n /= 2.0 * M_PI; + n -= int(n); + return (n < 0.0) ? n + 1.0 : n; + } +} + +void node_tex_wave(vec3 co, + float scale, + float distortion, + float detail, + float detail_scale, + float wave_type, + float wave_profile, + out vec4 color, + out float fac) +{ + float f; + f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile)); + + color = vec4(f, f, f, 1.0); + fac = f; +} diff --git a/source/blender/gpu/shaders/gpu_shader_material_white_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_white_noise.glsl index fce511deb79..fce511deb79 100644 --- a/source/blender/gpu/shaders/gpu_shader_material_white_noise.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_white_noise.glsl diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl new file mode 100644 index 00000000000..24276156d55 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl @@ -0,0 +1,92 @@ +vec3 mtex_2d_mapping(vec3 vec) +{ + return vec3(vec.xy * 0.5 + vec2(0.5), vec.z); +} + +void generated_from_orco(vec3 orco, out vec3 generated) +{ +#ifdef VOLUMETRICS +# ifdef MESH_SHADER + generated = volumeObjectLocalCoord; +# else + generated = worldPosition; +# endif +#else + generated = orco; +#endif +} + +void generated_texco(vec3 I, vec3 attr_orco, out vec3 generated) +{ + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + co.xyz = normalize(co.xyz); +#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) + generated = (ViewMatrixInverse * co).xyz; +#else + generated_from_orco(attr_orco, generated); +#endif +} + +void node_tex_coord(vec3 I, + vec3 wN, + mat4 obmatinv, + vec4 camerafac, + vec3 attr_orco, + vec3 attr_uv, + out vec3 generated, + out vec3 normal, + out vec3 uv, + out vec3 object, + out vec3 camera, + out vec3 window, + out vec3 reflection) +{ + generated = attr_orco; + normal = normalize(normal_world_to_object(wN)); + uv = attr_uv; + object = (obmatinv * (ViewMatrixInverse * vec4(I, 1.0))).xyz; + camera = vec3(I.xy, -I.z); + vec4 projvec = ProjectionMatrix * vec4(I, 1.0); + window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0); + reflection = -reflect(cameraVec, normalize(wN)); +} + +void node_tex_coord_background(vec3 I, + vec3 N, + mat4 obmatinv, + vec4 camerafac, + vec3 attr_orco, + vec3 attr_uv, + out vec3 generated, + out vec3 normal, + out vec3 uv, + out vec3 object, + out vec3 camera, + out vec3 window, + out vec3 reflection) +{ + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + + co = normalize(co); + + vec3 coords = (ViewMatrixInverse * co).xyz; + + generated = coords; + normal = -coords; + uv = vec3(attr_uv.xy, 0.0); + object = (obmatinv * vec4(coords, 1.0)).xyz; + + camera = vec3(co.xy, -co.z); + window = vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0); + + reflection = -coords; +} + +#if defined(WORLD_BACKGROUND) || (defined(PROBE_CAPTURE) && !defined(MESH_SHADER)) +# define node_tex_coord node_tex_coord_background +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_toon.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_toon.glsl new file mode 100644 index 00000000000..02d288d42bf --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_toon.glsl @@ -0,0 +1,9 @@ +#ifndef VOLUMETRICS +void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result) +{ + node_bsdf_diffuse(color, 0.0, N, result); +} +#else +/* Stub toon because it is not compatible with volumetrics. */ +# define node_bsdf_toon +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl new file mode 100644 index 00000000000..ea41790e6aa --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl @@ -0,0 +1,9 @@ +#ifndef VOLUMETRICS +void node_bsdf_translucent(vec4 color, vec3 N, out Closure result) +{ + node_bsdf_diffuse(color, 0.0, -N, result); +} +#else +/* Stub translucent because it is not compatible with volumetrics. */ +# define node_bsdf_translucent +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_transparent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_transparent.glsl new file mode 100644 index 00000000000..800d0f81d4a --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_transparent.glsl @@ -0,0 +1,11 @@ +#ifndef VOLUMETRICS +void node_bsdf_transparent(vec4 color, out Closure result) +{ + result = CLOSURE_DEFAULT; + result.radiance = vec3(0.0); + result.transmittance = abs(color.rgb); +} +#else +/* Stub transparent because it is not compatible with volumetrics. */ +# define node_bsdf_transparent +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_uv_map.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_uv_map.glsl new file mode 100644 index 00000000000..d8fcbbfc361 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_uv_map.glsl @@ -0,0 +1,4 @@ +void node_uvmap(vec3 attr_uv, out vec3 outvec) +{ + outvec = attr_uv; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_curves.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_curves.glsl new file mode 100644 index 00000000000..35d2e903cf4 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_curves.glsl @@ -0,0 +1,8 @@ +void curves_vec(float fac, vec3 vec, sampler1DArray curvemap, float layer, out vec3 outvec) +{ + vec4 co = vec4(vec * 0.5 + 0.5, layer); + outvec.x = texture(curvemap, co.xw).x; + outvec.y = texture(curvemap, co.yw).y; + outvec.z = texture(curvemap, co.zw).z; + outvec = mix(vec, outvec, fac); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_displacement.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_displacement.glsl new file mode 100644 index 00000000000..b6b955dcdb4 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_displacement.glsl @@ -0,0 +1,30 @@ +void node_vector_displacement_tangent(vec4 vector, + float midlevel, + float scale, + vec4 tangent, + vec3 normal, + mat4 obmat, + mat4 viewmat, + out vec3 result) +{ + /* TODO(fclem) this is broken. revisit latter. */ + vec3 N_object = normalize(((vec4(normal, 0.0) * viewmat) * obmat).xyz); + vec3 T_object = normalize(((vec4(tangent.xyz, 0.0) * viewmat) * obmat).xyz); + vec3 B_object = tangent.w * normalize(cross(N_object, T_object)); + + vec3 offset = (vector.xyz - vec3(midlevel)) * scale; + result = offset.x * T_object + offset.y * N_object + offset.z * B_object; + result = (obmat * vec4(result, 0.0)).xyz; +} + +void node_vector_displacement_object( + vec4 vector, float midlevel, float scale, mat4 obmat, out vec3 result) +{ + result = (vector.xyz - vec3(midlevel)) * scale; + result = (obmat * vec4(result, 0.0)).xyz; +} + +void node_vector_displacement_world(vec4 vector, float midlevel, float scale, out vec3 result) +{ + result = (vector.xyz - vec3(midlevel)) * scale; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl new file mode 100644 index 00000000000..93132b6044f --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl @@ -0,0 +1,100 @@ +void vector_math_add(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = a + b; +} + +void vector_math_subtract(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = a - b; +} + +void vector_math_multiply(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = a * b; +} + +void vector_math_divide(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = safe_divide(a, b); +} + +void vector_math_cross(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = cross(a, b); +} + +void vector_math_project(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + float lenSquared = dot(b, b); + outVector = (lenSquared != 0.0) ? (dot(a, b) / lenSquared) * b : vec3(0.0); +} + +void vector_math_reflect(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = reflect(a, normalize(b)); +} + +void vector_math_dot(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outValue = dot(a, b); +} + +void vector_math_distance(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outValue = distance(a, b); +} + +void vector_math_length(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outValue = length(a); +} + +void vector_math_scale(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = a * scale; +} + +void vector_math_normalize(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = normalize(a); +} + +void vector_math_snap(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = floor(safe_divide(a, b)) * b; +} + +void vector_math_floor(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = floor(a); +} + +void vector_math_ceil(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = ceil(a); +} + +void vector_math_modulo(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = c_mod(a, b); +} + +void vector_math_fraction(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = fract(a); +} + +void vector_math_absolute(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = abs(a); +} + +void vector_math_minimum(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = min(a, b); +} + +void vector_math_maximum(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue) +{ + outVector = max(a, b); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_velvet.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_velvet.glsl new file mode 100644 index 00000000000..9646ffff8ca --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_velvet.glsl @@ -0,0 +1,9 @@ +#ifndef VOLUMETRICS +void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result) +{ + node_bsdf_diffuse(color, 0.0, N, result); +} +#else +/* Stub velvet because it is not compatible with volumetrics. */ +# define node_bsdf_velvet +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_absorption.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_absorption.glsl new file mode 100644 index 00000000000..e6c0880cd07 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_absorption.glsl @@ -0,0 +1,8 @@ +void node_volume_absorption(vec4 color, float density, out Closure result) +{ +#ifdef VOLUMETRICS + result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0); +#else + result = CLOSURE_DEFAULT; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl new file mode 100644 index 00000000000..501aeb6f34e --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl @@ -0,0 +1,88 @@ +void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + outvec = texture(tex, cos).aaa; + outcol = vec4(outvec, 1.0); + outf = avg(outvec); +} + +uniform vec3 volumeColor = vec3(1.0); + +void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + + vec4 value = texture(tex, cos).rgba; + /* Density is premultiplied for interpolation, divide it out here. */ + if (value.a > 1e-8) { + value.rgb /= value.a; + } + + outvec = value.rgb * volumeColor; + outcol = vec4(outvec, 1.0); + outf = avg(outvec); +} + +void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + outf = texture(tex, cos).r; + outvec = vec3(outf, outf, outf); + outcol = vec4(outf, outf, outf, 1.0); +} + +void node_attribute_volume_temperature( + sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf) +{ +#if defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 cos = volumeObjectLocalCoord; +#else + vec3 cos = vec3(0.0); +#endif + float flame = texture(tex, cos).r; + + outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0; + outvec = vec3(outf, outf, outf); + outcol = vec4(outf, outf, outf, 1.0); +} + +void node_volume_info(sampler3D densitySampler, + sampler3D flameSampler, + vec2 temperature, + out vec4 outColor, + out float outDensity, + out float outFlame, + out float outTemprature) +{ +#if defined(MESH_SHADER) && defined(VOLUMETRICS) + vec3 p = volumeObjectLocalCoord; +#else + vec3 p = vec3(0.0); +#endif + + vec4 density = texture(densitySampler, p); + outDensity = density.a; + + /* Density is premultiplied for interpolation, divide it out here. */ + if (density.a > 1e-8) { + density.rgb /= density.a; + } + outColor = vec4(density.rgb * volumeColor, 1.0); + + float flame = texture(flameSampler, p).r; + outFlame = flame; + + outTemprature = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0; +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl new file mode 100644 index 00000000000..884d5415c51 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl @@ -0,0 +1,67 @@ +void node_volume_principled(vec4 color, + float density, + float anisotropy, + vec4 absorption_color, + float emission_strength, + vec4 emission_color, + float blackbody_intensity, + vec4 blackbody_tint, + float temperature, + float density_attribute, + vec4 color_attribute, + float temperature_attribute, + sampler1DArray spectrummap, + float layer, + out Closure result) +{ +#ifdef VOLUMETRICS + vec3 absorption_coeff = vec3(0.0); + vec3 scatter_coeff = vec3(0.0); + vec3 emission_coeff = vec3(0.0); + + /* Compute density. */ + density = max(density, 0.0); + + if (density > 1e-5) { + density = max(density * density_attribute, 0.0); + } + + if (density > 1e-5) { + /* Compute scattering and absorption coefficients. */ + vec3 scatter_color = color.rgb * color_attribute.rgb; + + scatter_coeff = scatter_color * density; + absorption_color.rgb = sqrt(max(absorption_color.rgb, 0.0)); + absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) * + density; + } + + /* Compute emission. */ + emission_strength = max(emission_strength, 0.0); + + if (emission_strength > 1e-5) { + emission_coeff += emission_strength * emission_color.rgb; + } + + if (blackbody_intensity > 1e-3) { + /* Add temperature from attribute. */ + float T = max(temperature * max(temperature_attribute, 0.0), 0.0); + + /* Stefan-Boltzman law. */ + float T2 = T * T; + float T4 = T2 * T2; + float sigma = 5.670373e-8 * 1e-6 / M_PI; + float intensity = sigma * mix(1.0, T4, blackbody_intensity); + + if (intensity > 1e-5) { + vec4 bb; + node_blackbody(T, spectrummap, layer, bb); + emission_coeff += bb.rgb * blackbody_tint.rgb * intensity; + } + } + + result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy); +#else + result = CLOSURE_DEFAULT; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_scatter.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_scatter.glsl new file mode 100644 index 00000000000..02c54658be5 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_scatter.glsl @@ -0,0 +1,8 @@ +void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result) +{ +#ifdef VOLUMETRICS + result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy); +#else + result = CLOSURE_DEFAULT; +#endif +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_wireframe.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_wireframe.glsl new file mode 100644 index 00000000000..2fcf1b8d914 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_wireframe.glsl @@ -0,0 +1,31 @@ +#ifndef VOLUMETRICS +void node_wireframe(float size, vec2 barycentric, vec3 barycentric_dist, out float fac) +{ + vec3 barys = barycentric.xyy; + barys.z = 1.0 - barycentric.x - barycentric.y; + + size *= 0.5; + vec3 s = step(-size, -barys * barycentric_dist); + + fac = max(s.x, max(s.y, s.z)); +} + +void node_wireframe_screenspace(float size, vec2 barycentric, out float fac) +{ + vec3 barys = barycentric.xyy; + barys.z = 1.0 - barycentric.x - barycentric.y; + + size *= (1.0 / 3.0); + vec3 dx = dFdx(barys); + vec3 dy = dFdy(barys); + vec3 deltas = sqrt(dx * dx + dy * dy); + + vec3 s = step(-deltas * size, -barys); + + fac = max(s.x, max(s.y, s.z)); +} +#else +/* Stub wireframe because it is not compatible with volumetrics. */ +# define node_wireframe +# define node_wireframe_screenspace +#endif diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl new file mode 100644 index 00000000000..f9691beee6f --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl @@ -0,0 +1,25 @@ +/* TODO : clean this ifdef mess */ +void world_normals_get(out vec3 N) +{ +#ifndef VOLUMETRICS +# 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.0 - cos_theta * cos_theta)); + N = normalize(worldNormal * sin_theta + B * cos_theta); +# else + N = gl_FrontFacing ? worldNormal : -worldNormal; +# endif +#else + generated_from_orco(vec3(0.0), N); +#endif +} diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c index 2e8f81979a8..65676a5ea91 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.c @@ -283,7 +283,7 @@ void node_shader_gpu_tex_mapping(GPUMaterial *mat, GPU_link(mat, "mapping", in[0].link, tmat0, tmat1, tmat2, tmat3, tmin, tmax, &in[0].link); if (texmap->type == TEXMAP_TYPE_NORMAL) { - GPU_link(mat, "texco_norm", in[0].link, &in[0].link); + GPU_link(mat, "vector_normalize", in[0].link, &in[0].link); } } } diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c index eca0d96f2c8..e58a5d72f28 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mapping.c +++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c @@ -115,7 +115,7 @@ static int gpu_shader_mapping(GPUMaterial *mat, GPU_stack_link(mat, node, "mapping", in, out, tmat0, tmat1, tmat2, tmat3, tmin, tmax); if (texmap->type == TEXMAP_TYPE_NORMAL) { - GPU_link(mat, "texco_norm", out[0].link, &out[0].link); + GPU_link(mat, "vector_normalize", out[0].link, &out[0].link); } return true; diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c index 872f4f9da9c..ae2184d8237 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c @@ -92,7 +92,7 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat, if (ret && node->custom2 & SHD_MIXRGB_CLAMP) { float min[3] = {0.0f, 0.0f, 0.0f}; float max[3] = {1.0f, 1.0f, 1.0f}; - GPU_link(mat, "clamp_vec3", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link); + GPU_link(mat, "clamp_color", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link); } return ret; } diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c index 712c64084cc..18015d94f03 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c @@ -114,8 +114,8 @@ static int gpu_shader_normal_map(GPUMaterial *mat, break; } - GPU_link(mat, "vector_math_mix", strength, realnorm, negnorm, &out[0].link); - GPU_link(mat, "vect_normalize", out[0].link, &out[0].link); + GPU_link(mat, "vector_mix", strength, realnorm, negnorm, &out[0].link); + GPU_link(mat, "vector_normalize", out[0].link, &out[0].link); return true; } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index bd8355ec885..a02262950a8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -124,15 +124,15 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) || IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) { /* Don't let alpha affect color output in these cases. */ - GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); } else { /* Always output with premultiplied alpha. */ if (ima->alpha_mode == IMA_ALPHA_PREMUL) { - GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); } else { - GPU_link(mat, "tex_color_alpha_premultiply", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_premultiply", out[0].link, &out[0].link); } } } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 6f3614e357d..5eaf09659d8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -183,7 +183,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) || IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) { /* Don't let alpha affect color output in these cases. */ - GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); } else { /* Output premultiplied alpha depending on alpha socket usage. This makes @@ -192,18 +192,18 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, * not, then there will be no artifacts from zero alpha areas. */ if (ima->alpha_mode == IMA_ALPHA_PREMUL) { if (out[1].hasoutput) { - GPU_link(mat, "tex_color_alpha_unpremultiply", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_unpremultiply", out[0].link, &out[0].link); } else { - GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); } } else { if (out[1].hasoutput) { - GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); } else { - GPU_link(mat, "tex_color_alpha_premultiply", out[0].link, &out[0].link); + GPU_link(mat, "color_alpha_premultiply", out[0].link, &out[0].link); } } } diff --git a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c b/source/blender/nodes/shader/nodes/node_shader_vectTransform.c index fe0e7b1d638..563ef89162b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c +++ b/source/blender/nodes/shader/nodes/node_shader_vectTransform.c @@ -132,7 +132,7 @@ static int gpu_shader_vect_transform(GPUMaterial *mat, } if (nodeprop->type == SHD_VECT_TRANSFORM_TYPE_NORMAL) { - GPU_link(mat, "vect_normalize", out[0].link, &out[0].link); + GPU_link(mat, "vector_normalize", out[0].link, &out[0].link); } return true; |