diff options
author | Clément Fukhaut <turjuque@gmail.com> | 2016-05-03 20:41:41 +0300 |
---|---|---|
committer | Clément Fukhaut <turjuque@gmail.com> | 2016-05-03 20:41:41 +0300 |
commit | 655cfca4524fc8295cb7ead9f2ccaf4f79d3f221 (patch) | |
tree | 3e4557940e8683cccca2d3fa4852a26bb9249ca6 /source/blender/gpu | |
parent | 7c777fe0383304219ab47251e2fe437d0ba90a7f (diff) |
Implemented SSR :
- Still pretty rough implementation does only works with sharp glossy shader
- No Glossy reflection
- 2 algorithm but only one acheive decent results the other needs to be debuged.
Changed pbr settings location :
- They are now stored in structs like the FX options
Diffstat (limited to 'source/blender/gpu')
-rw-r--r-- | source/blender/gpu/CMakeLists.txt | 4 | ||||
-rw-r--r-- | source/blender/gpu/GPU_material.h | 49 | ||||
-rw-r--r-- | source/blender/gpu/GPU_shader.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/GPU_ssr.h | 64 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.c | 133 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_codegen.h | 7 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 50 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_material.c | 219 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader.c | 14 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_ssr.c | 170 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_material.glsl | 2 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_material_bsdf_frag.glsl | 49 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_material_ssr_frag.glsl | 204 |
13 files changed, 807 insertions, 159 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index b73e48040f3..ca54151b5f7 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -58,6 +58,7 @@ set(SRC intern/gpu_material.c intern/gpu_select.c intern/gpu_shader.c + intern/gpu_ssr.c intern/gpu_texture.c shaders/gpu_shader_fx_lib.glsl @@ -70,6 +71,7 @@ set(SRC shaders/gpu_shader_fx_vert.glsl shaders/gpu_shader_material.glsl shaders/gpu_shader_material_bsdf_frag.glsl + shaders/gpu_shader_material_ssr_frag.glsl shaders/gpu_shader_sep_gaussian_blur_frag.glsl shaders/gpu_shader_sep_gaussian_blur_vert.glsl shaders/gpu_shader_basic_frag.glsl @@ -99,6 +101,7 @@ set(SRC GPU_material.h GPU_select.h GPU_shader.h + GPU_ssr.h GPU_texture.h intern/gpu_codegen.h intern/gpu_private.h @@ -109,6 +112,7 @@ data_to_c_simple(shaders/gpu_shader_smoke_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_smoke_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_material.glsl SRC) data_to_c_simple(shaders/gpu_shader_material_bsdf_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_material_ssr_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_basic_frag.glsl SRC) diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index ffe1263d0d3..e7e811dc9c1 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -65,6 +65,7 @@ typedef struct GPUMaterial GPUMaterial; typedef struct GPULamp GPULamp; typedef struct GPUParticleInfo GPUParticleInfo; typedef struct GPUProbe GPUProbe; +typedef struct GPUSSR GPUSSR; /* Functions to create GPU Materials nodes */ @@ -100,25 +101,32 @@ typedef enum GPUBuiltin { GPU_PARTICLE_ANG_VELOCITY = (1 << 12), GPU_LOC_TO_VIEW_MATRIX = (1 << 13), GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14), - GPU_PBR_LOD_FACTOR = (1 << 15), - GPU_PBR_PROBE = (1 << 16), - GPU_PBR_PLANAR_REFLECT = (1 << 17), - GPU_PBR_PLANAR_REFRACT = (1 << 18), - GPU_PBR_SH0 = (1 << 19), - GPU_PBR_SH1 = (1 << 20), - GPU_PBR_SH2 = (1 << 21), - GPU_PBR_SH3 = (1 << 22), - GPU_PBR_SH4 = (1 << 23), - GPU_PBR_SH5 = (1 << 24), - GPU_PBR_SH6 = (1 << 25), - GPU_PBR_SH7 = (1 << 26), - GPU_PBR_SH8 = (1 << 27), - GPU_PBR_CORRECTION_MATRIX = (1 << 28), - GPU_PBR_PLANAR_RFL_MATRIX = (1 << 29), - GPU_PBR_PROBE_POSITION = (1 << 30), - GPU_PBR_PLANAR_VECTOR = (1 << 31), } GPUBuiltin; +typedef enum GPUPBRBuiltin { + GPU_LOD_FACTOR = (1 << 0), + GPU_PROBE = (1 << 1), + GPU_PLANAR_REFLECT = (1 << 2), + GPU_PLANAR_REFRACT = (1 << 3), + GPU_SH0 = (1 << 4), + GPU_SH1 = (1 << 5), + GPU_SH2 = (1 << 6), + GPU_SH3 = (1 << 7), + GPU_SH4 = (1 << 8), + GPU_SH5 = (1 << 9), + GPU_SH6 = (1 << 10), + GPU_SH7 = (1 << 11), + GPU_SH8 = (1 << 12), + GPU_CORRECTION_MATRIX = (1 << 13), + GPU_PLANAR_RFL_MATRIX = (1 << 14), + GPU_PROBE_POSITION = (1 << 15), + GPU_PLANAR_VECTOR = (1 << 16), + GPU_SSR = (1 << 17), + GPU_SSR_PARAMETERS = (1 << 18), + GPU_SSR_PARAMETERS2 = (1 << 19), + GPU_PIXEL_PROJ_MATRIX = (1 << 20), +} GPUPBRBuiltin; + typedef enum GPUOpenGLBuiltin { GPU_MATCAP_NORMAL = 1, GPU_COLOR = 2, @@ -230,6 +238,7 @@ GPUNodeLink *GPU_image_preview(struct PreviewImage *prv); GPUNodeLink *GPU_texture(int size, float *pixels); GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, GPUDynamicType dynamictype, void *data); GPUNodeLink *GPU_builtin(GPUBuiltin builtin); +GPUNodeLink *GPU_pbr_builtin(GPUPBRBuiltin builtin); GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin); void GPU_node_link_set_type(GPUNodeLink *link, GPUType type); @@ -253,7 +262,7 @@ GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]); GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo); GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv, - bool use_realistic_preview, bool use_planar_probe, bool use_alpha_as_depth, int samplecount, int parallax_correc); + bool use_realistic_preview, bool use_planar_probe, bool use_alpha_as_depth, bool use_ssr, int samplecount, int parallax_correc); GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, bool use_opensubdiv); void GPU_material_free(struct ListBase *gpumaterial); @@ -266,7 +275,7 @@ void GPU_material_bind( void GPU_material_bind_uniforms( GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4], float autobumpscale, GPUParticleInfo *pi); -void GPU_material_bind_uniforms_probe(GPUMaterial *material, GPUProbe *probe); +void GPU_material_bind_uniforms_probe(GPUMaterial *material, GPUProbe *probe, GPUSSR *ssr,struct GPUSSRSettings *ssr_settings,struct GPUBRDFSettings *brdf_settings); void GPU_material_unbind(GPUMaterial *material); bool GPU_material_bound(GPUMaterial *material); struct Scene *GPU_material_scene(GPUMaterial *material); @@ -467,6 +476,8 @@ void GPU_material_update_fvar_offset(GPUMaterial *gpu_material, struct DerivedMesh *dm); #endif +void GPU_pbr_settings_validate(struct GPUPBRSettings *pbr_settings); + #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 3cc7bc74703..b57fbe1e92a 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -51,6 +51,7 @@ enum { GPU_SHADER_FLAGS_PROBE_ELIPS_CORREC = (1 << 3), GPU_SHADER_FLAGS_PROBE_PLANAR = (1 << 4), GPU_SHADER_FLAGS_ALPHA_DEPTH = (1 << 5), + GPU_SHADER_FLAGS_SSR = (1 << 6), }; GPUShader *GPU_shader_create( diff --git a/source/blender/gpu/GPU_ssr.h b/source/blender/gpu/GPU_ssr.h new file mode 100644 index 00000000000..9a526fdd421 --- /dev/null +++ b/source/blender/gpu/GPU_ssr.h @@ -0,0 +1,64 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Clement Foucault. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file GPU_ssr.h + * \ingroup gpu + */ + +#ifndef __GPU_SSR_H__ +#define __GPU_SSR_H__ + +#include "BLI_sys_types.h" /* for bool */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct GPUSSR { + int w, h; + float clipsta, clipend; + + /* Matrix that project to pixel coordinate (not Normalized Device Coordinates) */ + float pixelprojmat[4][4]; + + struct GPUTexture *tex; + struct GPUTexture *depth; + struct GPUFrameBuffer *fb; +} GPUSSR; + +void GPU_ssr_free(GPUSSR *ssr); +bool GPU_ssr_is_valid(GPUSSR *ssr, int w, int h); +GPUSSR *GPU_ssr_create(int width, int height); +void GPU_ssr_buffer_bind(GPUSSR *ssr, float winmat[4][4], int winsize[2], float clipsta, float clipend); +void GPU_ssr_buffer_unbind(GPUSSR *ssr); +void GPU_pbr_init_ssr_settings(struct GPUSSRSettings *ssr_settings); + +#ifdef __cplusplus +} +#endif + +#endif /*__GPU_SSR_H__*/ diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 3236c5798cf..149029d11f3 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -57,6 +57,7 @@ extern char datatoc_gpu_shader_material_glsl[]; extern char datatoc_gpu_shader_material_bsdf_frag_glsl[]; +extern char datatoc_gpu_shader_material_ssr_frag_glsl[]; extern char datatoc_gpu_shader_vertex_glsl[]; extern char datatoc_gpu_shader_vertex_world_glsl[]; extern char datatoc_gpu_shader_geometry_glsl[]; @@ -409,40 +410,54 @@ const char *GPU_builtin_name(GPUBuiltin builtin) return "unfparticlevel"; else if (builtin == GPU_PARTICLE_ANG_VELOCITY) return "unfparticleangvel"; - else if (builtin == GPU_PBR_PROBE) + else + return ""; +} + +const char *GPU_pbrbuiltin_name(GPUPBRBuiltin pbrbuiltin) +{ + if (pbrbuiltin == GPU_PROBE) return "unfprobe"; - else if (builtin == GPU_PBR_PLANAR_REFLECT) + else if (pbrbuiltin == GPU_PLANAR_REFLECT) return "unfreflect"; - else if (builtin == GPU_PBR_PLANAR_REFRACT) + else if (pbrbuiltin == GPU_PLANAR_REFRACT) return "unfrefract"; - else if (builtin == GPU_PBR_LOD_FACTOR) + else if (pbrbuiltin == GPU_LOD_FACTOR) return "unflodfactor"; - else if (builtin == GPU_PBR_SH0) + else if (pbrbuiltin == GPU_SH0) return "unfsh0"; - else if (builtin == GPU_PBR_SH1) + else if (pbrbuiltin == GPU_SH1) return "unfsh1"; - else if (builtin == GPU_PBR_SH2) + else if (pbrbuiltin == GPU_SH2) return "unfsh2"; - else if (builtin == GPU_PBR_SH3) + else if (pbrbuiltin == GPU_SH3) return "unfsh3"; - else if (builtin == GPU_PBR_SH4) + else if (pbrbuiltin == GPU_SH4) return "unfsh4"; - else if (builtin == GPU_PBR_SH5) + else if (pbrbuiltin == GPU_SH5) return "unfsh5"; - else if (builtin == GPU_PBR_SH6) + else if (pbrbuiltin == GPU_SH6) return "unfsh6"; - else if (builtin == GPU_PBR_SH7) + else if (pbrbuiltin == GPU_SH7) return "unfsh7"; - else if (builtin == GPU_PBR_SH8) + else if (pbrbuiltin == GPU_SH8) return "unfsh8"; - else if (builtin == GPU_PBR_CORRECTION_MATRIX) + else if (pbrbuiltin == GPU_CORRECTION_MATRIX) return "unfprobecorrectionmat"; - else if (builtin == GPU_PBR_PLANAR_RFL_MATRIX) + else if (pbrbuiltin == GPU_PLANAR_RFL_MATRIX) return "unfplanarreflectmat"; - else if (builtin == GPU_PBR_PROBE_POSITION) + else if (pbrbuiltin == GPU_PROBE_POSITION) return "unfprobepos"; - else if (builtin == GPU_PBR_PLANAR_VECTOR) + else if (pbrbuiltin == GPU_PLANAR_VECTOR) return "unfplanarvec"; + else if (pbrbuiltin == GPU_SSR) + return "unfssr"; + else if (pbrbuiltin == GPU_SSR_PARAMETERS) + return "unfssrparam"; + else if (pbrbuiltin == GPU_SSR_PARAMETERS2) + return "unfssrparam2"; + else if (pbrbuiltin == GPU_PIXEL_PROJ_MATRIX) + return "unfpixelprojmat"; else return ""; } @@ -469,8 +484,8 @@ static void codegen_set_unique_ids(ListBase *nodes) GPUNode *node; GPUInput *input; GPUOutput *output; - /* tex slot (texid) 0-2 is pbr textures */ - int id = 1, texid = 3; + /* tex slot (texid) 0-3 are pbr textures */ + int id = 1, texid = 4; bindhash = BLI_ghash_ptr_new("codegen_set_unique_ids1 gh"); definehash = BLI_ghash_ptr_new("codegen_set_unique_ids2 gh"); @@ -537,7 +552,7 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes) GPUNode *node; GPUInput *input; const char *name; - int builtins = 0; + int builtins = 0, pbrbuiltins = 0; /* print uniforms */ for (node = nodes->first; node; node = node->next) { @@ -561,12 +576,6 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes) /* XXX always here */ continue; } - if (input->builtin == GPU_PBR_PROBE) { - BLI_dynstr_appendf(ds, "uniform samplerCube %s;\n", name); - } - else if (input->builtin == GPU_PBR_PLANAR_REFLECT || input->builtin == GPU_PBR_PLANAR_REFRACT) { - BLI_dynstr_appendf(ds, "uniform sampler2D %s;\n", name); - } else if (gpu_str_prefix(name, "unf")) { BLI_dynstr_appendf(ds, "uniform %s %s;\n", GPU_DATATYPE_STR[input->type], name); @@ -578,6 +587,24 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes) } } } + else if (input->source == GPU_SOURCE_PBR_BUILTIN) { + /* only define each builtin uniform/varying once */ + if (!(pbrbuiltins & input->pbrbuiltin)) { + pbrbuiltins |= input->pbrbuiltin; + name = GPU_pbrbuiltin_name(input->pbrbuiltin); + + if (input->pbrbuiltin == GPU_PROBE) { + BLI_dynstr_appendf(ds, "uniform samplerCube %s;\n", name); + } + else if (input->pbrbuiltin & (GPU_PLANAR_REFLECT | GPU_PLANAR_REFRACT | GPU_SSR)) { + BLI_dynstr_appendf(ds, "uniform sampler2D %s;\n", name); + } + else { + BLI_dynstr_appendf(ds, "uniform %s %s;\n", + GPU_DATATYPE_STR[input->type], name); + } + } + } else if (input->source == GPU_SOURCE_VEC_UNIFORM) { if (input->dynamicvec) { /* only create uniforms for dynamic vectors */ @@ -669,6 +696,9 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final else BLI_dynstr_append(ds, GPU_builtin_name(input->builtin)); } + else if (input->source == GPU_SOURCE_PBR_BUILTIN) { + BLI_dynstr_append(ds, GPU_pbrbuiltin_name(input->pbrbuiltin)); + } else if (input->source == GPU_SOURCE_VEC_UNIFORM) { if (input->dynamicvec) BLI_dynstr_appendf(ds, "unf%d", input->id); @@ -697,16 +727,16 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final BLI_dynstr_append(ds, ");\n"); } - BLI_dynstr_appendf(ds, "#ifndef ALPHA_AS_DEPTH"); + BLI_dynstr_appendf(ds, "\n#ifndef ALPHA_AS_DEPTH\n"); BLI_dynstr_append(ds, "\n\tgl_FragColor = "); codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id); BLI_dynstr_append(ds, ";\n"); - BLI_dynstr_appendf(ds, "#else"); - /* Encode Depth in Alpha if we are capturing for planar reflection */ + BLI_dynstr_appendf(ds, "\n#else\n"); + /* Encode Depth in Alpha if we are capturing for planar reflection / ssr */ BLI_dynstr_append(ds, "\n\tgl_FragColor = vec4("); codegen_convert_datatype(ds, finaloutput->type, GPU_VEC3, "tmp", finaloutput->id); - BLI_dynstr_append(ds, ", -varposition.z + 1.0);\n"); - BLI_dynstr_appendf(ds, "#endif\n"); + BLI_dynstr_append(ds, ", varposition.z);\n"); + BLI_dynstr_appendf(ds, "\n#endif\n"); } static char *code_generate_fragment(ListBase *nodes, const GPUMatType type, GPUOutput *output) @@ -733,10 +763,10 @@ static char *code_generate_fragment(ListBase *nodes, const GPUMatType type, GPUO #endif if (type == GPU_MATERIAL_TYPE_MESH_REAL_SH) { + BLI_dynstr_append(ds, datatoc_gpu_shader_material_ssr_frag_glsl); BLI_dynstr_append(ds, datatoc_gpu_shader_material_bsdf_frag_glsl); } - /* XXX */ BLI_dynstr_appendf(ds, "%s vec3 varposition;\n", GLEW_VERSION_3_0 ? "in" : "varying"); @@ -1027,6 +1057,7 @@ static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) #endif } if (input->source == GPU_SOURCE_BUILTIN || + input->source == GPU_SOURCE_PBR_BUILTIN || input->source == GPU_SOURCE_OPENGL_BUILTIN) { continue; @@ -1213,6 +1244,14 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType MEM_freeN(link); } + else if (link->pbrbuiltin) { + /* builtin uniform */ + input->type = type; + input->source = GPU_SOURCE_PBR_BUILTIN; + input->pbrbuiltin = link->pbrbuiltin; + + MEM_freeN(link); + } else if (link->oglbuiltin) { /* builtin uniform */ input->type = type; @@ -1424,17 +1463,22 @@ static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *a } } -static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin) +static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin, int *pbrbuiltin) { GPUNode *node; GPUInput *input; *builtin = 0; + *pbrbuiltin = 0; - for (node = nodes->first; node; node = node->next) - for (input = node->inputs.first; input; input = input->next) + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_BUILTIN) *builtin |= input->builtin; + else if (input->source == GPU_SOURCE_PBR_BUILTIN) + *pbrbuiltin |= input->pbrbuiltin; + } + } } /* varargs linking */ @@ -1540,6 +1584,15 @@ GPUNodeLink *GPU_builtin(GPUBuiltin builtin) return link; } +GPUNodeLink *GPU_pbr_builtin(GPUPBRBuiltin builtin) +{ + GPUNodeLink *link = GPU_node_link_create(); + + link->pbrbuiltin = builtin; + + return link; +} + GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin) { GPUNodeLink *link = GPU_node_link_create(); @@ -1706,7 +1759,7 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink) GPUPass *GPU_generate_pass( ListBase *nodes, GPUNodeLink *outlink, - GPUVertexAttribs *attribs, int *builtins, + GPUVertexAttribs *attribs, int *builtins, int *pbrbuiltins, const GPUMatType type, const char *UNUSED(name), const bool use_opensubdiv, const bool use_new_shading, @@ -1714,6 +1767,7 @@ GPUPass *GPU_generate_pass( const bool use_box_correction, const bool use_ellipsoid_correction, const bool use_alpha_as_depth, + const bool use_ssr, const int samplecount) { GPUShader *shader; @@ -1731,8 +1785,7 @@ GPUPass *GPU_generate_pass( gpu_nodes_prune(nodes, outlink); gpu_nodes_get_vertex_attributes(nodes, attribs); - gpu_nodes_get_builtin_flag(nodes, builtins); - + gpu_nodes_get_builtin_flag(nodes, builtins, pbrbuiltins); /* generate code and compile with opengl */ fragmentcode = code_generate_fragment(nodes, type, outlink->output); @@ -1758,6 +1811,9 @@ GPUPass *GPU_generate_pass( if (use_alpha_as_depth) { flags |= GPU_SHADER_FLAGS_ALPHA_DEPTH; } + if (use_ssr) { + flags |= GPU_SHADER_FLAGS_SSR; + } shader = GPU_shader_create_ex(vertexcode, fragmentcode, @@ -1778,6 +1834,7 @@ GPUPass *GPU_generate_pass( MEM_freeN(vertexcode); memset(attribs, 0, sizeof(*attribs)); memset(builtins, 0, sizeof(*builtins)); + memset(pbrbuiltins, 0, sizeof(*pbrbuiltins)); gpu_nodes_free(nodes); return NULL; } diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 47a9ae16fb3..7f1fef9c262 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -54,6 +54,7 @@ struct PreviewImage; typedef enum GPUDataSource { GPU_SOURCE_VEC_UNIFORM, GPU_SOURCE_BUILTIN, + GPU_SOURCE_PBR_BUILTIN, GPU_SOURCE_OPENGL_BUILTIN, GPU_SOURCE_TEX_PIXEL, GPU_SOURCE_TEX, @@ -106,6 +107,7 @@ struct GPUNodeLink { GPUBuiltin builtin; GPUOpenGLBuiltin oglbuiltin; + GPUPBRBuiltin pbrbuiltin; struct GPUOutput *output; }; @@ -154,6 +156,7 @@ typedef struct GPUInput { char attribname[MAX_CUSTOMDATA_LAYER_NAME]; /* attribute name */ int attribfirst; /* this is the first one that is bound */ GPUBuiltin builtin; /* builtin uniform */ + GPUPBRBuiltin pbrbuiltin; /* PBR builtin uniform */ GPUOpenGLBuiltin oglbuiltin; /* opengl built in varying */ } GPUInput; @@ -173,7 +176,7 @@ struct GPUPass { typedef struct GPUPass GPUPass; GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink, - struct GPUVertexAttribs *attribs, int *builtin, + struct GPUVertexAttribs *attribs, int *builtins, int *pbrbuiltins, const GPUMatType type, const char *name, const bool use_opensubdiv, const bool use_new_shading, @@ -181,6 +184,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink, const bool use_box_correction, const bool use_ellipsoid_correction, const bool use_alpha_as_depth, + const bool use_ssr, const int samplecount); struct GPUShader *GPU_pass_shader(GPUPass *pass); @@ -197,6 +201,7 @@ void gpu_codegen_exit(void); /* Material calls */ const char *GPU_builtin_name(GPUBuiltin builtin); +const char *GPU_pbrbuiltin_name(GPUBuiltin builtin); void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node); int GPU_link_changed(struct GPUNodeLink *link); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 2e1f9d9b19f..febb1beddbc 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -1581,6 +1581,7 @@ static struct GPUMaterialState { DupliObject *dob; Scene *gscene; GPUProbe *gprobe; + GPUSSR *gssr; int glay; bool gscenelock; float (*gviewmat)[4]; @@ -1601,9 +1602,11 @@ static struct GPUMaterialState { bool is_planar_probe; bool is_realistic_mat; bool is_alpha_as_depth; + bool use_ssr; int pbr_samples; int parallax_correc; - + GPUBRDFSettings *gbrdfsettings; + GPUSSRSettings *gssrsettings; } GMS = {NULL}; /* fixed function material, alpha handed by caller */ @@ -1748,17 +1751,12 @@ void GPU_begin_object_materials( GMS.gviewmat = rv3d->viewmat; GMS.gviewinv = rv3d->viewinv; GMS.gviewcamtexcofac = rv3d->viewcamtexcofac; - GMS.is_realistic_mat = (v3d->flag3 & V3D_REALISTIC_MAT); - GMS.is_alpha_as_depth = (v3d->flag3 & V3D_REFLECTION_PASS); + GMS.is_realistic_mat = (new_shading_nodes && (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_ENABLE)); + GMS.is_alpha_as_depth = (v3d->flag3 & (V3D_REFLECTION_PASS | V3D_PROBE_CAPTURE)); GMS.gprobe = NULL; - - /* This prevent from generating and keeping lots of shaders in memory - * if realistic mat is turned off. */ - if (GMS.is_realistic_mat) - GMS.pbr_samples = (v3d->pbr_samples <= 0) ? 16 : 16 * v3d->pbr_samples; - else - GMS.pbr_samples = 0; - + GMS.gssr = NULL; + GMS.gbrdfsettings = NULL; + GMS.gssrsettings = NULL; /* alpha pass setup. there's various cases to handle here: * - object transparency on: only solid materials draw in the first pass, @@ -1792,10 +1790,25 @@ void GPU_begin_object_materials( GMS.alphablend[0] = GPU_BLEND_SOLID; } else { + + GMS.pbr_samples = 0; GMS.is_planar_probe = false; GMS.parallax_correc = 0; - if (new_shading_nodes && (v3d->flag3 & V3D_REALISTIC_MAT) && !(v3d->flag2 & V3D_RENDER_SHADOW)) { + if (GMS.is_realistic_mat && !(v3d->flag2 & V3D_RENDER_SHADOW)) { + + /* This prevent from generating and keeping lots of shaders in memory + * if realistic mat is turned off. */ + GMS.pbr_samples = (v3d->pbr_settings.brdf->samples <= 0) ? 16 : 16 * v3d->pbr_settings.brdf->samples; + + GMS.use_ssr = (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_SSR); + GMS.gbrdfsettings = v3d->pbr_settings.brdf; + GMS.gssrsettings = v3d->pbr_settings.ssr; + + /* Screen space reflections */ + if (v3d->ssr_buffer && !(v3d->flag3 & V3D_PROBE_CAPTURE) && (v3d->pbr_settings.pbr_flag & GPU_PBR_FLAG_SSR)) + GMS.gssr = v3d->ssr_buffer; + /* Picking the right probe */ /* XXX need to be done clearer */ if (ob->probetype == OB_PROBE_CUBEMAP || ob->probetype == OB_PROBE_PLANAR) { @@ -1851,7 +1864,7 @@ void GPU_begin_object_materials( if (glsl) { GMS.gmatbuf[0] = &defmaterial; - GPU_material_from_blender(GMS.gscene, &defmaterial, GMS.is_opensubdiv, GMS.is_realistic_mat, GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.pbr_samples, GMS.parallax_correc); + GPU_material_from_blender(GMS.gscene, &defmaterial, GMS.is_opensubdiv, GMS.is_realistic_mat, GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.use_ssr, GMS.pbr_samples, GMS.parallax_correc); } GMS.alphablend[0] = GPU_BLEND_SOLID; @@ -1865,7 +1878,7 @@ void GPU_begin_object_materials( if (ma == NULL) ma = &defmaterial; /* create glsl material if requested */ - gpumat = glsl ? GPU_material_from_blender(GMS.gscene, ma, GMS.is_opensubdiv, GMS.is_realistic_mat, GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.pbr_samples, GMS.parallax_correc) : NULL; + gpumat = glsl ? GPU_material_from_blender(GMS.gscene, ma, GMS.is_opensubdiv, GMS.is_realistic_mat, GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.use_ssr, GMS.pbr_samples, GMS.parallax_correc) : NULL; if (gpumat) { /* do glsl only if creating it succeed, else fallback */ @@ -1964,7 +1977,7 @@ int GPU_object_material_bind(int nr, void *attribs) /* unbind glsl material */ if (GMS.gboundmat) { if (GMS.is_alpha_pass) glDepthMask(0); - GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv, GMS.is_realistic_mat, GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.pbr_samples, GMS.parallax_correc)); + GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv, GMS.is_realistic_mat, GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.use_ssr, GMS.pbr_samples, GMS.parallax_correc)); GMS.gboundmat = NULL; } @@ -1991,7 +2004,7 @@ int GPU_object_material_bind(int nr, void *attribs) float auto_bump_scale; - GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv, GMS.is_realistic_mat, GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.pbr_samples, GMS.parallax_correc); + GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv, GMS.is_realistic_mat, GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.use_ssr, GMS.pbr_samples, GMS.parallax_correc); GPU_material_vertex_attributes(gpumat, gattribs); if (GMS.dob) @@ -2004,7 +2017,7 @@ int GPU_object_material_bind(int nr, void *attribs) auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f; GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &particle_info); - GPU_material_bind_uniforms_probe(gpumat, GMS.gprobe); + GPU_material_bind_uniforms_probe(gpumat, GMS.gprobe, GMS.gssr, GMS.gssrsettings, GMS.gbrdfsettings); GMS.gboundmat = mat; @@ -2092,7 +2105,7 @@ void GPU_object_material_unbind(void) glDisable(GL_CULL_FACE); if (GMS.is_alpha_pass) glDepthMask(0); - GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv, GMS.is_realistic_mat, GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.pbr_samples, GMS.parallax_correc)); + GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv, GMS.is_realistic_mat, GMS.is_planar_probe, GMS.is_alpha_as_depth, GMS.use_ssr, GMS.pbr_samples, GMS.parallax_correc)); GMS.gboundmat = NULL; } else @@ -2393,6 +2406,7 @@ void GPU_draw_update_fvar_offset(DerivedMesh *dm) GMS.is_realistic_mat, GMS.is_planar_probe, GMS.is_alpha_as_depth, + GMS.use_ssr, GMS.pbr_samples, GMS.parallax_correc); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index ee80f56a680..b01216667ff 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -68,6 +68,7 @@ #include "GPU_shader.h" #include "GPU_texture.h" #include "GPU_draw.h" +#include "GPU_ssr.h" #include "gpu_codegen.h" @@ -148,7 +149,7 @@ struct GPUMaterial { /* for binding the material */ GPUPass *pass; GPUVertexAttribs attribs; - int builtins; + int builtins, pbrbuiltins; int alpha, obcolalpha; int dynproperty; @@ -170,9 +171,12 @@ struct GPUMaterial { int correcmatloc, planarreflloc, planarobjloc; int probecoloc, planarvecloc; int shloc[9]; + int ssrloc, ssrparamsloc, ssrparams2loc; + int pixelprojmatloc; GPUTexture *bindedcubeprobe; GPUTexture *bindedreflprobe; GPUTexture *bindedrefrprobe; + GPUTexture *bindedssr; ListBase lamps; bool bound; @@ -187,6 +191,7 @@ struct GPUMaterial { int parallax_correc; bool is_planar_probe; bool is_alpha_as_depth; + bool use_ssr; bool is_opensubdiv; }; @@ -294,8 +299,9 @@ static int GPU_material_construct_end(GPUMaterial *material, const char *passnam { if (material->outlink) { GPUNodeLink *outlink = material->outlink; + material->pass = GPU_generate_pass(&material->nodes, outlink, - &material->attribs, &material->builtins, material->type, + &material->attribs, &material->builtins, &material->pbrbuiltins, material->type, passname, material->is_opensubdiv, GPU_material_use_new_shading_nodes(material), @@ -303,6 +309,7 @@ static int GPU_material_construct_end(GPUMaterial *material, const char *passnam material->parallax_correc & OB_PROBE_PARRALAX_BOX, material->parallax_correc & OB_PROBE_PARRALAX_ELLIPSOID, material->is_alpha_as_depth, + material->use_ssr, material->samplecount); if (!material->pass) @@ -338,40 +345,50 @@ static int GPU_material_construct_end(GPUMaterial *material, const char *passnam material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY)); if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY)); - if (material->builtins & GPU_PBR_LOD_FACTOR) - material->lodfactorloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_LOD_FACTOR)); - if (material->builtins & GPU_PBR_PROBE) - material->probeloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_PROBE)); - if (material->builtins & GPU_PBR_PLANAR_REFLECT) - material->reflectloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_PLANAR_REFLECT)); - if (material->builtins & GPU_PBR_PLANAR_REFRACT) - material->refractloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_PLANAR_REFRACT)); - if (material->builtins & GPU_PBR_SH0) - material->shloc[0] = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_SH0)); - if (material->builtins & GPU_PBR_SH1) - material->shloc[1] = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_SH1)); - if (material->builtins & GPU_PBR_SH2) - material->shloc[2] = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_SH2)); - if (material->builtins & GPU_PBR_SH3) - material->shloc[3] = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_SH3)); - if (material->builtins & GPU_PBR_SH4) - material->shloc[4] = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_SH4)); - if (material->builtins & GPU_PBR_SH5) - material->shloc[5] = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_SH5)); - if (material->builtins & GPU_PBR_SH6) - material->shloc[6] = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_SH6)); - if (material->builtins & GPU_PBR_SH7) - material->shloc[7] = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_SH7)); - if (material->builtins & GPU_PBR_SH8) - material->shloc[8] = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_SH8)); - if (material->builtins & GPU_PBR_CORRECTION_MATRIX) - material->correcmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_CORRECTION_MATRIX)); - if (material->builtins & GPU_PBR_PLANAR_RFL_MATRIX) - material->planarreflloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_PLANAR_RFL_MATRIX)); - if (material->builtins & GPU_PBR_PROBE_POSITION) - material->probecoloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_PROBE_POSITION)); - if (material->builtins & GPU_PBR_PLANAR_VECTOR) - material->planarvecloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PBR_PLANAR_VECTOR)); + + if (material->pbrbuiltins & GPU_PROBE) + material->probeloc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_PROBE)); + if (material->pbrbuiltins & GPU_LOD_FACTOR) + material->lodfactorloc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_LOD_FACTOR)); + if (material->pbrbuiltins & GPU_PLANAR_REFLECT) + material->reflectloc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_PLANAR_REFLECT)); + if (material->pbrbuiltins & GPU_PLANAR_REFRACT) + material->refractloc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_PLANAR_REFRACT)); + if (material->pbrbuiltins & GPU_SH0) + material->shloc[0] = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SH0)); + if (material->pbrbuiltins & GPU_SH1) + material->shloc[1] = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SH1)); + if (material->pbrbuiltins & GPU_SH2) + material->shloc[2] = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SH2)); + if (material->pbrbuiltins & GPU_SH3) + material->shloc[3] = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SH3)); + if (material->pbrbuiltins & GPU_SH4) + material->shloc[4] = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SH4)); + if (material->pbrbuiltins & GPU_SH5) + material->shloc[5] = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SH5)); + if (material->pbrbuiltins & GPU_SH6) + material->shloc[6] = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SH6)); + if (material->pbrbuiltins & GPU_SH7) + material->shloc[7] = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SH7)); + if (material->pbrbuiltins & GPU_SH8) + material->shloc[8] = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SH8)); + if (material->pbrbuiltins & GPU_CORRECTION_MATRIX) + material->correcmatloc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_CORRECTION_MATRIX)); + if (material->pbrbuiltins & GPU_PLANAR_RFL_MATRIX) + material->planarreflloc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_PLANAR_RFL_MATRIX)); + if (material->pbrbuiltins & GPU_PROBE_POSITION) + material->probecoloc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_PROBE_POSITION)); + if (material->pbrbuiltins & GPU_PLANAR_VECTOR) + material->planarvecloc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_PLANAR_VECTOR)); + if (material->pbrbuiltins & GPU_SSR) + material->ssrloc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SSR)); + if (material->pbrbuiltins & GPU_SSR_PARAMETERS) + material->ssrparamsloc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SSR_PARAMETERS)); + if (material->pbrbuiltins & GPU_SSR_PARAMETERS2) + material->ssrparams2loc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_SSR_PARAMETERS2)); + if (material->pbrbuiltins & GPU_PIXEL_PROJ_MATRIX) + material->pixelprojmatloc = GPU_shader_get_uniform(shader, GPU_pbrbuiltin_name(GPU_PIXEL_PROJ_MATRIX)); + return 1; } @@ -504,6 +521,7 @@ void GPU_material_bind( material->bindedcubeprobe = NULL; material->bindedreflprobe = NULL; material->bindedrefrprobe = NULL; + material->bindedssr = NULL; } } @@ -561,14 +579,50 @@ void GPU_material_bind_uniforms( } } -void GPU_material_bind_uniforms_probe(GPUMaterial *material, GPUProbe *probe) +void GPU_material_bind_uniforms_probe(GPUMaterial *material, GPUProbe *probe, GPUSSR *ssr, GPUSSRSettings *ssr_settings, GPUBRDFSettings *brdf_settings) { if (material->pass) { GPUShader *shader = GPU_pass_shader(material->pass); + if (ssr) { + if (material->pbrbuiltins & GPU_SSR) { + material->bindedssr = ssr->tex; + GPU_texture_bind(material->bindedssr, 3); + GPU_shader_uniform_texture(shader, material->ssrloc, material->bindedssr); + } + if (material->pbrbuiltins & GPU_PIXEL_PROJ_MATRIX) { + GPU_shader_uniform_vector(shader, material->pixelprojmatloc, 16, 1, (float *)ssr->pixelprojmat); + } + if (material->pbrbuiltins & GPU_SSR_PARAMETERS) { + /* ssr_parameters + * x : thickness : Camera space thickness to ascribe to each pixel in the depth buffer + * y : nearz : Near plane distance (Negative number) + * z : stride : Step in horizontal or vertical pixels between samples. + * w : maxstep : Maximum number of iteration when raymarching */ + + float ssrparams[4]; + ssrparams[0] = ssr_settings->thickness; + ssrparams[1] = -ssr->clipsta; /* Negative */ + ssrparams[2] = ssr_settings->stride; + ssrparams[3] = (float)ssr_settings->steps; + + GPU_shader_uniform_vector(shader, material->ssrparamsloc, 4, 1, ssrparams); + } + if (material->pbrbuiltins & GPU_SSR_PARAMETERS2) { + /* ssr_parameters2 + * x : maxdistance : Maximum number of iteration when raymarching + * y : attenuation : Attenuation factor for screen edges and ray step fading */ + + float ssrparams2[2]; + ssrparams2[0] = ssr_settings->distance_max; + ssrparams2[1] = ssr_settings->attenuation; + + GPU_shader_uniform_vector(shader, material->ssrparams2loc, 2, 1, &ssr_settings->distance_max); + } + } if (probe) { /* handle per object probes */ - if (material->builtins & GPU_PBR_PROBE) { + if (material->pbrbuiltins & GPU_PROBE) { if (probe->type == GPU_PROBE_PLANAR) { GPUProbe *fallbackprobe = NULL; /* XXX : this should be moved elsewhere */ @@ -588,7 +642,7 @@ void GPU_material_bind_uniforms_probe(GPUMaterial *material, GPUProbe *probe) GPU_texture_bind(material->bindedcubeprobe, 0); GPU_shader_uniform_texture(shader, material->probeloc, material->bindedcubeprobe); } - if (material->builtins & GPU_PBR_PLANAR_REFLECT && probe->type == GPU_PROBE_PLANAR) { + if (material->pbrbuiltins & GPU_PLANAR_REFLECT && probe->type == GPU_PROBE_PLANAR) { /* XXX : save the reflection for unbinding */ material->bindedreflprobe = probe->texreflect; material->bindedrefrprobe = probe->texrefract; @@ -598,40 +652,39 @@ void GPU_material_bind_uniforms_probe(GPUMaterial *material, GPUProbe *probe) GPU_texture_bind(material->bindedrefrprobe, 2); GPU_shader_uniform_texture(shader, material->refractloc, material->bindedrefrprobe); } - if (material->builtins & GPU_PBR_PLANAR_RFL_MATRIX && probe->type == GPU_PROBE_PLANAR) { + if (material->pbrbuiltins & GPU_PLANAR_RFL_MATRIX && probe->type == GPU_PROBE_PLANAR) { GPU_shader_uniform_vector(shader, material->planarreflloc, 16, 1, (float *)probe->reflectionmat); } - if (material->builtins & GPU_PBR_LOD_FACTOR) { + if (material->pbrbuiltins & GPU_LOD_FACTOR) { float lodfactor; float samplenum = (float)(material->samplecount); //maxlod = log((float)probe->size) / log(2); lodfactor = 0.5f * log( ( (float)(probe->size * probe->size) / samplenum ) ) / log(2); + lodfactor -= brdf_settings->lodbias; - /* Biasing the factor to get more accurate sampling for higher sample count */ - lodfactor -= (samplenum - 16.0f) / 128.0f; GPU_shader_uniform_vector(shader, material->lodfactorloc, 1, 1, &lodfactor); } - if (material->builtins & GPU_PBR_SH0) { + if (material->pbrbuiltins & GPU_SH0) { int i; /* Making the asumption that we need all of them */ for (i = 0; i < 9; ++i) { GPU_shader_uniform_vector(shader, material->shloc[i], 3, 1, &probe->shcoefs[i*3]); } } - if (material->builtins & GPU_PBR_CORRECTION_MATRIX) { + if (material->pbrbuiltins & GPU_CORRECTION_MATRIX) { GPU_shader_uniform_vector(shader, material->correcmatloc, 16, 1, (float *)probe->correctionmat); } - if (material->builtins & GPU_PBR_PROBE_POSITION) { + if (material->pbrbuiltins & GPU_PROBE_POSITION) { GPU_shader_uniform_vector(shader, material->probecoloc, 3, 1, probe->co); } - if (material->builtins & GPU_PBR_PLANAR_VECTOR) { + if (material->pbrbuiltins & GPU_PLANAR_VECTOR) { GPU_shader_uniform_vector(shader, material->planarvecloc, 3, 1, probe->planevec); } } else { /* avoid objects with the same material and no probe attached to have the same SH binded */ - if (material->builtins & GPU_PBR_SH0) { + if (material->pbrbuiltins & GPU_SH0) { int i; float black[3] = {0.0f, 0.0f, 0.0f}; /* Making the asumption that we need all of them */ @@ -653,6 +706,8 @@ void GPU_material_unbind(GPUMaterial *material) GPU_texture_unbind(material->bindedreflprobe); if (material->bindedrefrprobe) GPU_texture_unbind(material->bindedrefrprobe); + if (material->bindedssr) + GPU_texture_unbind(material->bindedssr); material->bound = 0; GPU_pass_unbind(material->pass); @@ -2396,36 +2451,36 @@ static GPUNodeLink *brdf_sample_env(GPUBrdfInput *brdf) GPU_link(mat, "vec_math_negate", brdf->normal, &brdf->normal); switch (brdf->type) { case GPU_BRDF_GLOSSY_SHARP : - GPU_link(mat, "env_sampling_reflect_sharp", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, GPU_builtin(GPU_PBR_PROBE), GPU_builtin(GPU_PBR_PLANAR_REFLECT), GPU_builtin(GPU_PBR_PLANAR_REFRACT), GPU_builtin(GPU_PBR_CORRECTION_MATRIX), GPU_builtin(GPU_PBR_PLANAR_RFL_MATRIX), GPU_builtin(GPU_PBR_PROBE_POSITION), GPU_builtin(GPU_PBR_PLANAR_VECTOR), &envlight); + GPU_link(mat, "env_sampling_reflect_sharp", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, GPU_pbr_builtin(GPU_PROBE), GPU_pbr_builtin(GPU_SSR), GPU_pbr_builtin(GPU_SSR_PARAMETERS), GPU_pbr_builtin(GPU_SSR_PARAMETERS2), GPU_pbr_builtin(GPU_PIXEL_PROJ_MATRIX), GPU_pbr_builtin(GPU_PLANAR_REFLECT), GPU_pbr_builtin(GPU_PLANAR_REFRACT), GPU_pbr_builtin(GPU_CORRECTION_MATRIX), GPU_pbr_builtin(GPU_PLANAR_RFL_MATRIX), GPU_pbr_builtin(GPU_PROBE_POSITION), GPU_pbr_builtin(GPU_PLANAR_VECTOR), &envlight); break; case GPU_BRDF_GLOSSY_GGX : - GPU_link(mat, "env_sampling_reflect_glossy", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->roughness, GPU_builtin(GPU_PBR_LOD_FACTOR), GPU_builtin(GPU_PBR_PROBE), GPU_builtin(GPU_PBR_PLANAR_REFLECT), GPU_builtin(GPU_PBR_PLANAR_REFRACT), GPU_builtin(GPU_PBR_CORRECTION_MATRIX), GPU_builtin(GPU_PBR_PLANAR_RFL_MATRIX), GPU_builtin(GPU_PBR_PROBE_POSITION), GPU_builtin(GPU_PBR_PLANAR_VECTOR), &envlight); + GPU_link(mat, "env_sampling_reflect_glossy", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->roughness, GPU_pbr_builtin(GPU_LOD_FACTOR), GPU_pbr_builtin(GPU_PROBE), GPU_pbr_builtin(GPU_PLANAR_REFLECT), GPU_pbr_builtin(GPU_PLANAR_REFRACT), GPU_pbr_builtin(GPU_CORRECTION_MATRIX), GPU_pbr_builtin(GPU_PLANAR_RFL_MATRIX), GPU_pbr_builtin(GPU_PROBE_POSITION), GPU_pbr_builtin(GPU_PLANAR_VECTOR), &envlight); break; case GPU_BRDF_ANISO_GGX : - GPU_link(mat, "env_sampling_reflect_aniso", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->roughness, brdf->anisotropy, brdf->aniso_rotation, brdf->aniso_tangent, GPU_builtin(GPU_PBR_LOD_FACTOR), GPU_builtin(GPU_PBR_PROBE), GPU_builtin(GPU_PBR_PLANAR_REFLECT), GPU_builtin(GPU_PBR_PLANAR_REFRACT), GPU_builtin(GPU_PBR_CORRECTION_MATRIX), GPU_builtin(GPU_PBR_PLANAR_RFL_MATRIX), GPU_builtin(GPU_PBR_PROBE_POSITION), GPU_builtin(GPU_PBR_PLANAR_VECTOR), &envlight); + GPU_link(mat, "env_sampling_reflect_aniso", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->roughness, brdf->anisotropy, brdf->aniso_rotation, brdf->aniso_tangent, GPU_pbr_builtin(GPU_LOD_FACTOR), GPU_pbr_builtin(GPU_PROBE), GPU_pbr_builtin(GPU_PLANAR_REFLECT), GPU_pbr_builtin(GPU_PLANAR_REFRACT), GPU_pbr_builtin(GPU_CORRECTION_MATRIX), GPU_pbr_builtin(GPU_PLANAR_RFL_MATRIX), GPU_pbr_builtin(GPU_PROBE_POSITION), GPU_pbr_builtin(GPU_PLANAR_VECTOR), &envlight); break; case GPU_BRDF_REFRACT_SHARP : - GPU_link(mat, "env_sampling_refract_sharp", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->ior, GPU_builtin(GPU_PBR_PROBE), GPU_builtin(GPU_PBR_PLANAR_REFLECT), GPU_builtin(GPU_PBR_PLANAR_REFRACT), GPU_builtin(GPU_PBR_CORRECTION_MATRIX), GPU_builtin(GPU_PBR_PLANAR_RFL_MATRIX), GPU_builtin(GPU_PBR_PROBE_POSITION), GPU_builtin(GPU_PBR_PLANAR_VECTOR), &envlight); + GPU_link(mat, "env_sampling_refract_sharp", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->ior, GPU_pbr_builtin(GPU_PROBE), GPU_pbr_builtin(GPU_PLANAR_REFLECT), GPU_pbr_builtin(GPU_PLANAR_REFRACT), GPU_pbr_builtin(GPU_CORRECTION_MATRIX), GPU_pbr_builtin(GPU_PLANAR_RFL_MATRIX), GPU_pbr_builtin(GPU_PROBE_POSITION), GPU_pbr_builtin(GPU_PLANAR_VECTOR), &envlight); break; case GPU_BRDF_REFRACT_GGX : - GPU_link(mat, "env_sampling_refract_glossy", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->ior, brdf->roughness, GPU_builtin(GPU_PBR_LOD_FACTOR), GPU_builtin(GPU_PBR_PROBE), GPU_builtin(GPU_PBR_PLANAR_REFLECT), GPU_builtin(GPU_PBR_PLANAR_REFRACT), GPU_builtin(GPU_PBR_CORRECTION_MATRIX), GPU_builtin(GPU_PBR_PLANAR_RFL_MATRIX), GPU_builtin(GPU_PBR_PROBE_POSITION), GPU_builtin(GPU_PBR_PLANAR_VECTOR), &envlight); + GPU_link(mat, "env_sampling_refract_glossy", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->ior, brdf->roughness, GPU_pbr_builtin(GPU_LOD_FACTOR), GPU_pbr_builtin(GPU_PROBE), GPU_pbr_builtin(GPU_PLANAR_REFLECT), GPU_pbr_builtin(GPU_PLANAR_REFRACT), GPU_pbr_builtin(GPU_CORRECTION_MATRIX), GPU_pbr_builtin(GPU_PLANAR_RFL_MATRIX), GPU_pbr_builtin(GPU_PROBE_POSITION), GPU_pbr_builtin(GPU_PLANAR_VECTOR), &envlight); break; case GPU_BRDF_GLASS_SHARP : - GPU_link(mat, "env_sampling_glass_sharp", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->ior, GPU_builtin(GPU_PBR_PROBE), GPU_builtin(GPU_PBR_PLANAR_REFLECT), GPU_builtin(GPU_PBR_PLANAR_REFRACT), GPU_builtin(GPU_PBR_CORRECTION_MATRIX), GPU_builtin(GPU_PBR_PLANAR_RFL_MATRIX), GPU_builtin(GPU_PBR_PROBE_POSITION), GPU_builtin(GPU_PBR_PLANAR_VECTOR), &envlight); + GPU_link(mat, "env_sampling_glass_sharp", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->ior, GPU_pbr_builtin(GPU_PROBE), GPU_pbr_builtin(GPU_PLANAR_REFLECT), GPU_pbr_builtin(GPU_PLANAR_REFRACT), GPU_pbr_builtin(GPU_CORRECTION_MATRIX), GPU_pbr_builtin(GPU_PLANAR_RFL_MATRIX), GPU_pbr_builtin(GPU_PROBE_POSITION), GPU_pbr_builtin(GPU_PLANAR_VECTOR), &envlight); break; case GPU_BRDF_GLASS_GGX : - GPU_link(mat, "env_sampling_glass_glossy", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->ior, brdf->roughness, GPU_builtin(GPU_PBR_LOD_FACTOR), GPU_builtin(GPU_PBR_PROBE), GPU_builtin(GPU_PBR_PLANAR_REFLECT), GPU_builtin(GPU_PBR_PLANAR_REFRACT), GPU_builtin(GPU_PBR_CORRECTION_MATRIX), GPU_builtin(GPU_PBR_PLANAR_RFL_MATRIX), GPU_builtin(GPU_PBR_PROBE_POSITION), GPU_builtin(GPU_PBR_PLANAR_VECTOR), &envlight); + GPU_link(mat, "env_sampling_glass_glossy", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->ior, brdf->roughness, GPU_pbr_builtin(GPU_LOD_FACTOR), GPU_pbr_builtin(GPU_PROBE), GPU_pbr_builtin(GPU_PLANAR_REFLECT), GPU_pbr_builtin(GPU_PLANAR_REFRACT), GPU_pbr_builtin(GPU_CORRECTION_MATRIX), GPU_pbr_builtin(GPU_PLANAR_RFL_MATRIX), GPU_pbr_builtin(GPU_PROBE_POSITION), GPU_pbr_builtin(GPU_PLANAR_VECTOR), &envlight); break; case GPU_BRDF_TRANSPARENT : - GPU_link(mat, "env_sampling_transparent", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_PBR_PROBE), GPU_builtin(GPU_PBR_PLANAR_REFLECT), GPU_builtin(GPU_PBR_PLANAR_REFRACT), GPU_builtin(GPU_PBR_CORRECTION_MATRIX), GPU_builtin(GPU_PBR_PLANAR_RFL_MATRIX), GPU_builtin(GPU_PBR_PROBE_POSITION), GPU_builtin(GPU_PBR_PLANAR_VECTOR), &envlight); + GPU_link(mat, "env_sampling_transparent", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), GPU_pbr_builtin(GPU_PROBE), GPU_pbr_builtin(GPU_PLANAR_REFLECT), GPU_pbr_builtin(GPU_PLANAR_REFRACT), GPU_pbr_builtin(GPU_CORRECTION_MATRIX), GPU_pbr_builtin(GPU_PLANAR_RFL_MATRIX), GPU_pbr_builtin(GPU_PROBE_POSITION), GPU_pbr_builtin(GPU_PLANAR_VECTOR), &envlight); break; case GPU_BRDF_VELVET : - GPU_link(mat, "env_sampling_velvet", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->sigma, GPU_builtin(GPU_PBR_LOD_FACTOR), GPU_builtin(GPU_PBR_PROBE), GPU_builtin(GPU_PBR_PLANAR_REFLECT), GPU_builtin(GPU_PBR_PLANAR_REFRACT), GPU_builtin(GPU_PBR_CORRECTION_MATRIX), GPU_builtin(GPU_PBR_PLANAR_RFL_MATRIX), GPU_builtin(GPU_PBR_PROBE_POSITION), GPU_builtin(GPU_PBR_PLANAR_VECTOR), &envlight); + GPU_link(mat, "env_sampling_velvet", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->sigma, GPU_pbr_builtin(GPU_LOD_FACTOR), GPU_pbr_builtin(GPU_PROBE), GPU_pbr_builtin(GPU_PLANAR_REFLECT), GPU_pbr_builtin(GPU_PLANAR_REFRACT), GPU_pbr_builtin(GPU_CORRECTION_MATRIX), GPU_pbr_builtin(GPU_PLANAR_RFL_MATRIX), GPU_pbr_builtin(GPU_PROBE_POSITION), GPU_pbr_builtin(GPU_PLANAR_VECTOR), &envlight); break; case GPU_BRDF_DIFFUSE : case GPU_BRDF_TRANSLUCENT : default : - GPU_link(mat, "env_sampling_diffuse", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->roughness, GPU_builtin(GPU_PBR_LOD_FACTOR), GPU_builtin(GPU_PBR_PROBE), GPU_builtin(GPU_PBR_PLANAR_REFLECT), GPU_builtin(GPU_PBR_PLANAR_REFRACT), GPU_builtin(GPU_PBR_CORRECTION_MATRIX), GPU_builtin(GPU_PBR_PLANAR_RFL_MATRIX), GPU_builtin(GPU_PBR_PROBE_POSITION), GPU_builtin(GPU_PBR_PLANAR_VECTOR), GPU_builtin(GPU_PBR_SH0), GPU_builtin(GPU_PBR_SH1), GPU_builtin(GPU_PBR_SH2), GPU_builtin(GPU_PBR_SH3), GPU_builtin(GPU_PBR_SH4), GPU_builtin(GPU_PBR_SH5), GPU_builtin(GPU_PBR_SH6), GPU_builtin(GPU_PBR_SH7), GPU_builtin(GPU_PBR_SH8), &envlight); + GPU_link(mat, "env_sampling_diffuse", GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_VIEW_MATRIX), brdf->normal, brdf->roughness, GPU_pbr_builtin(GPU_LOD_FACTOR), GPU_pbr_builtin(GPU_PROBE), GPU_pbr_builtin(GPU_PLANAR_REFLECT), GPU_pbr_builtin(GPU_PLANAR_REFRACT), GPU_pbr_builtin(GPU_CORRECTION_MATRIX), GPU_pbr_builtin(GPU_PLANAR_RFL_MATRIX), GPU_pbr_builtin(GPU_PROBE_POSITION), GPU_pbr_builtin(GPU_PLANAR_VECTOR), GPU_pbr_builtin(GPU_SH0), GPU_pbr_builtin(GPU_SH1), GPU_pbr_builtin(GPU_SH2), GPU_pbr_builtin(GPU_SH3), GPU_pbr_builtin(GPU_SH4), GPU_pbr_builtin(GPU_SH5), GPU_pbr_builtin(GPU_SH6), GPU_pbr_builtin(GPU_SH7), GPU_pbr_builtin(GPU_SH8), &envlight); break; } @@ -2837,7 +2892,7 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) return mat; } -GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv, bool use_realistic_preview, bool use_planar_probe, bool use_alpha_as_depth, int samplecount, int parallax_correc) +GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv, bool use_realistic_preview, bool use_planar_probe, bool use_alpha_as_depth, bool use_ssr, int samplecount, int parallax_correc) { GPUMaterial *mat; GPUNodeLink *outlink; @@ -2852,6 +2907,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_open current_material->is_alpha_as_depth == use_alpha_as_depth && current_material->samplecount == samplecount && current_material->is_planar_probe == use_planar_probe && + current_material->use_ssr == use_ssr && current_material->parallax_correc == parallax_correc) { return current_material; @@ -2867,6 +2923,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_open mat->parallax_correc = parallax_correc; mat->is_planar_probe = use_planar_probe; mat->is_alpha_as_depth = use_alpha_as_depth; + mat->use_ssr = use_ssr; /* render pipeline option */ bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); @@ -3079,26 +3136,28 @@ static void gpu_probe_from_blender(Scene *scene, World *wo, Object *ob, GPUProbe return; } - /* Reflection */ - probe->texreflect = GPU_texture_create_planar_probe(probe->size, NULL); - if (!probe->texreflect) { + /* Refraction */ + probe->texrefract = GPU_texture_create_planar_probe(probe->size, NULL); + if (!probe->texrefract) { gpu_probe_buffers_free(probe); return; } - if (!GPU_framebuffer_texture_attach(probe->fb, probe->texreflect, 0, NULL)) { + if (!GPU_framebuffer_texture_attach(probe->fb, probe->texrefract, 0, NULL)) { gpu_probe_buffers_free(probe); return; } - /* Refraction */ - probe->texrefract = GPU_texture_create_planar_probe(probe->size, NULL); - if (!probe->texrefract) { + GPU_framebuffer_texture_detach(probe->texrefract); + + /* Reflection */ + probe->texreflect = GPU_texture_create_planar_probe(probe->size, NULL); + if (!probe->texreflect) { gpu_probe_buffers_free(probe); return; } - if (!GPU_framebuffer_texture_attach(probe->fb, probe->texrefract, 1, NULL)) { + if (!GPU_framebuffer_texture_attach(probe->fb, probe->texreflect, 0, NULL)) { gpu_probe_buffers_free(probe); return; } @@ -4049,7 +4108,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma) int liblen, fraglen; /* TODO(sergey): How to determine whether we need OSD or not here? */ - GPUMaterial *mat = GPU_material_from_blender(scene, ma, false, false, false, false, 0, 0); + GPUMaterial *mat = GPU_material_from_blender(scene, ma, false, false, false, false, false, 0, 0); GPUPass *pass = (mat) ? mat->pass : NULL; if (pass && pass->fragmentcode && pass->vertexcode) { @@ -4270,3 +4329,27 @@ void GPU_material_update_fvar_offset(GPUMaterial *gpu_material, GPU_shader_unbind(); } #endif + +static void GPU_pbr_init_brdf_settings(GPUBRDFSettings *brdf_settings) +{ + brdf_settings->lodbias = 0.0f; + brdf_settings->samples = 1; +} + +void GPU_pbr_settings_validate(GPUPBRSettings *pbr_settings) +{ + /* Setting all at once */ + if ((pbr_settings->brdf == NULL) && + (pbr_settings->pbr_flag & GPU_PBR_FLAG_ENABLE)) + { + GPUBRDFSettings *brdf_settings; + GPUSSRSettings *ssr_settings; + + brdf_settings = pbr_settings->brdf = MEM_callocN(sizeof(GPUBRDFSettings), __func__); + ssr_settings = pbr_settings->ssr = MEM_callocN(sizeof(GPUSSRSettings), __func__); + + GPU_pbr_init_brdf_settings(brdf_settings); + GPU_pbr_init_ssr_settings(ssr_settings); + } + +}
\ No newline at end of file diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 4e364b4a209..b347bae4555 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -203,6 +203,7 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], bool use_ellipsoid_correction, bool use_planar_probe, bool use_alpha_as_depth, + bool use_ssr, int importance_sample_count) { /* some useful defines to detect GPU type */ @@ -242,9 +243,8 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], UNUSED_VARS(use_opensubdiv); #endif - if (use_new_shading) { + if (use_new_shading) strcat(defines, "#define USE_NEW_SHADING\n"); - } if (use_box_correction) strcat(defines, "#define CORRECTION_BOX\n"); @@ -253,13 +253,14 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH], else strcat(defines, "#define CORRECTION_NONE\n"); - if (use_planar_probe) { + if (use_planar_probe) strcat(defines, "#define PLANAR_PROBE\n"); - } - if (use_alpha_as_depth) { + if (use_ssr && !use_planar_probe) + strcat(defines, "#define USE_SSR\n"); + + if (use_alpha_as_depth) strcat(defines, "#define ALPHA_AS_DEPTH\n"); - } if (!importance_sample_count) { importance_sample_count = 1; @@ -357,6 +358,7 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode, (flags & GPU_SHADER_FLAGS_PROBE_ELIPS_CORREC) != 0, (flags & GPU_SHADER_FLAGS_PROBE_PLANAR) != 0, (flags & GPU_SHADER_FLAGS_ALPHA_DEPTH) != 0, + (flags & GPU_SHADER_FLAGS_SSR) != 0, samplecount); gpu_shader_standard_extensions(standard_extensions, geocode != NULL); diff --git a/source/blender/gpu/intern/gpu_ssr.c b/source/blender/gpu/intern/gpu_ssr.c new file mode 100644 index 00000000000..bea7127fdc9 --- /dev/null +++ b/source/blender/gpu/intern/gpu_ssr.c @@ -0,0 +1,170 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gpu_ssr.c + * \ingroup gpu + * + * Manages Screen Space Reflections. + */ + + +#include <math.h> +#include <string.h> +#include "MEM_guardedalloc.h" + +#include "DNA_gpu_types.h" + +#include "BLI_math.h" + +#include "GPU_texture.h" +#include "GPU_framebuffer.h" +#include "GPU_ssr.h" + +#include "gpu_codegen.h" + +#include <string.h> + +/* Structs */ + + +/* Functions */ + +void GPU_ssr_free(GPUSSR *ssr) +{ + if (ssr->tex) { + GPU_texture_free(ssr->tex); + ssr->tex = NULL; + } + if (ssr->depth) { + GPU_texture_free(ssr->depth); + ssr->depth = NULL; + } + if (ssr->fb) { + GPU_framebuffer_free(ssr->fb); + ssr->fb = NULL; + } + + MEM_freeN(ssr); +} + +bool GPU_ssr_is_valid(GPUSSR *ssr, int w, int h) +{ + return (( ssr->w == w ) && ( ssr->h == h )); +} + +GPUSSR *GPU_ssr_create(int width, int height) +{ + GPUSSR *ssr = MEM_callocN(sizeof(GPUSSR), "GPUSSR"); + + ssr->w = width; + ssr->h = height; + + ssr->fb = GPU_framebuffer_create(); + if (!ssr->fb) { + GPU_ssr_free(ssr); + return NULL; + } + + ssr->depth = GPU_texture_create_depth(width, height, NULL); + if (!ssr->depth) { + GPU_ssr_free(ssr); + return NULL; + } + + if (!GPU_framebuffer_texture_attach(ssr->fb, ssr->depth, 0, NULL)) { + GPU_ssr_free(ssr); + return NULL; + } + + ssr->tex = GPU_texture_create_2D(width, height, NULL, 1, NULL); + if (!ssr->tex) { + GPU_ssr_free(ssr); + return NULL; + } + + if (!GPU_framebuffer_texture_attach(ssr->fb, ssr->tex, 0, NULL)) { + GPU_ssr_free(ssr); + return NULL; + } + + /* check validity at the very end! */ + if (!GPU_framebuffer_check_valid(ssr->fb, NULL)) { + GPU_ssr_free(ssr); + return NULL; + } + + GPU_framebuffer_restore(); + + return ssr; +} + +void GPU_ssr_buffer_bind(GPUSSR *ssr, float winmat[4][4], int winsize[2], float clipsta, float clipend) +{ + glDisable(GL_SCISSOR_TEST); + GPU_texture_bind_as_framebuffer(ssr->tex); + + winsize[0] = ssr->w; + winsize[1] = ssr->h; + + ssr->clipsta = clipsta; + ssr->clipend = clipend; + + { + float uvpix[4][4], ndcuv[4][4], tmp[4][4]; + + /* NDC to UVs */ + unit_m4(ndcuv); + ndcuv[0][0] = ndcuv[1][1] = ndcuv[3][0] = ndcuv[3][1] = 0.5f; + + /* UVs to pixels */ + unit_m4(uvpix); + uvpix[0][0] = ssr->w; + uvpix[1][1] = ssr->h; + + mul_m4_m4m4(tmp, uvpix, ndcuv); + mul_m4_m4m4(ssr->pixelprojmat, tmp, winmat); + } +} + +void GPU_ssr_buffer_unbind(GPUSSR *ssr) +{ + GPU_framebuffer_texture_unbind(ssr->fb, ssr->tex); + GPU_framebuffer_restore(); + glEnable(GL_SCISSOR_TEST); +} + +/* SSR Settings */ + +void GPU_pbr_init_ssr_settings(GPUSSRSettings *ssr_settings) +{ + ssr_settings->stride = 0.01f; + ssr_settings->distance_max = 100.0f; + ssr_settings->attenuation = 6.0f; + ssr_settings->thickness = 0.1f; + ssr_settings->steps = 32; + ssr_settings->downsampling = 0; +} diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 80b62e99f5c..03f183a10d1 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -4289,7 +4289,7 @@ void env_sampling_glass_glossy(vec3 viewpos, mat4 invviewmat, mat4 viewmat, vec3 void env_sampling_glass_sharp(vec3 viewpos, mat4 invviewmat, mat4 viewmat, vec3 N, float ior, samplerCube probe, sampler2D planar_reflection, sampler2D planar_refraction, mat4 correcmat, mat4 reflectmat, vec3 probevec, vec3 planarvec, out vec3 result); -void env_sampling_reflect_sharp(vec3 viewpos, mat4 invviewmat, mat4 viewmat, vec3 N, samplerCube probe, sampler2D planar_reflection, sampler2D planar_refraction, mat4 correcmat, mat4 reflectmat, vec3 probevec, vec3 planarvec, out vec3 result); +void env_sampling_reflect_sharp(vec3 viewpos, mat4 invviewmat, mat4 viewmat, vec3 N, samplerCube probe, sampler2D ssr_buffer, vec4 ssr_parameters, vec2 ssr_parameters2, mat4 pixelprojmat, sampler2D planar_reflection, sampler2D planar_refraction, mat4 correcmat, mat4 reflectmat, vec3 probevec, vec3 planarvec, out vec3 result); void env_sampling_refract_sharp(vec3 viewpos, mat4 invviewmat, mat4 viewmat, vec3 N, float eta, samplerCube probe, sampler2D planar_reflection, sampler2D planar_refraction, mat4 correcmat, mat4 reflectmat, vec3 probevec, vec3 planarvec, out vec3 result); diff --git a/source/blender/gpu/shaders/gpu_shader_material_bsdf_frag.glsl b/source/blender/gpu/shaders/gpu_shader_material_bsdf_frag.glsl index 0a574a05669..b65950fbdfa 100644 --- a/source/blender/gpu/shaders/gpu_shader_material_bsdf_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material_bsdf_frag.glsl @@ -29,7 +29,7 @@ void correct_ray(inout vec3 L, vec3 worldpos, mat4 correcmat, vec3 probevec) float b = dot(localray, localpos); float c = dot(localpos, localpos) - 1; - float dist = 1e15f; + float dist = 1e15; float determinant = b * b - a * c; if (determinant >= 0) dist = (sqrt(determinant) - b) / a; @@ -79,7 +79,7 @@ vec4 sampleProbeLod(samplerCube probe, sampler2D planarprobe, vec3 cubevec, vec3 { vec4 sample; correct_ray(cubevec, worldpos, correcmat, probevec); - sample = textureCubeLod(probe, cubevec, min(lod, 5.0)); + sample = textureCubeLod(probe, cubevec, lod); #ifdef PLANAR_PROBE vec4 sample_plane = vec4(0.0); @@ -305,8 +305,7 @@ void env_sampling_reflect_glossy(vec3 viewpos, mat4 invviewmat, mat4 viewmat, ve float Lod = precalc_lod_factor - 0.5 * log2(pdf); - out_radiance += sampleProbeLod(probe, planar_reflection, L, refpos, N, worldpos, viewmat, correcmat, planarfac, probevec, planarvec, Ht.xy, roughness, I, Lod); - weight++; + vec4 sample = sampleProbeLod(probe, planar_reflection, L, refpos, N, worldpos, viewmat, correcmat, planarfac, probevec, planarvec, Ht.xy, roughness, I, Lod); /* Step 2 : Integrating BRDF : this must be replace by a LUT */ float VH = max(1e-8, -dot(I, H)); @@ -315,12 +314,14 @@ void env_sampling_reflect_glossy(vec3 viewpos, mat4 invviewmat, mat4 viewmat, ve /* Li = SampleColor * NL * brdf = D*G / (4*NL*NV) [denominator canceled by G] * pdf = D * NH / (4 * VH) [D canceled later by D in brdf] - * out_radiance = Li * Spec / pdf; */ - brdf += NL * 4.0 * VH / (NH * G); + * out_radiance = Li * brdf / pdf; */ + float brdf = 4.0 * VH / (NH * G); + + out_radiance += NL * sample * brdf; } } - result = (out_radiance.rgb / weight) * (brdf / NUM_SAMPLE); + result = (out_radiance.rgb / NUM_SAMPLE); } void env_sampling_reflect_aniso(vec3 viewpos, mat4 invviewmat, mat4 viewmat, vec3 N, float roughness, float anisotropy, float rotation, vec3 T, @@ -639,6 +640,10 @@ void env_sampling_glass_sharp(vec3 viewpos, mat4 invviewmat, mat4 viewmat, vec3 void env_sampling_reflect_sharp(vec3 viewpos, mat4 invviewmat, mat4 viewmat, vec3 N, samplerCube probe, + sampler2D ssr_buffer, + vec4 ssr_parameters, + vec2 ssr_parameters2, + mat4 pixelprojmat, sampler2D planar_reflection, sampler2D planar_refraction, mat4 correcmat, @@ -651,8 +656,36 @@ void env_sampling_reflect_sharp(vec3 viewpos, mat4 invviewmat, mat4 viewmat, vec vec3 planarfac; vec3 I = vector_prepass(invviewmat, viewmat, reflectmat, viewpos, worldpos, refpos, planarvec, planarfac); vec3 L = reflect(I, N); + vec3 vL = (viewmat * vec4(L, 0.0)).xyz; + + /* Probe */ + vec4 sample_probe = sampleProbe(probe, planar_reflection, L, refpos, N, worldpos, viewmat, correcmat, planarfac, probevec, planarvec, vec2(0.0), 0.0, I); + + /* SSR */ +#ifdef USE_SSR + /* ssr_parameters */ + float thickness = ssr_parameters.x; /* Camera space thickness to ascribe to each pixel in the depth buffer */ + float nearz = ssr_parameters.y; /* Near plane distance (Negative number) */ + float stride = ssr_parameters.z; /* 2D : Step in horizontal or vertical pixels between samples. 3D : View space step between samples */ + float maxstep = ssr_parameters.w; /* Maximum number of iteration when raymarching */ + float maxdistance = ssr_parameters2.x; /* Maximum distance from ray origin */ + float attenuation = ssr_parameters2.y; /* Attenuation factor for screen edges and ray step fading */ - result = sampleProbe(probe, planar_reflection, L, refpos, N, worldpos, viewmat, correcmat, planarfac, probevec, planarvec, vec2(0.0), 0.0, I).rgb; + ivec2 c = ivec2(gl_FragCoord.xy); + float jitter = float((c.x+c.y)&1) * 0.5; // Number between 0 and 1 for how far to bump the ray in stride units to conceal banding artifacts + + vec2 hitpixel; vec3 hitco; float hitstep; + + bool hit = raycast(viewpos, vL, pixelprojmat, ssr_buffer, thickness, nearz, stride, jitter, maxstep, maxdistance, hitstep, hitpixel, hitco); + float contrib = ssr_contribution(viewpos, hitstep, maxstep, maxdistance, attenuation, hit, hitco); + + vec4 sample_ssr = texture2DLod(ssr_buffer, hitco.xy, 0); + srgb_to_linearrgb(sample_ssr, sample_ssr); + + result = mix(sample_probe.rgb, sample_ssr.rgb, contrib); +#else + result = sample_probe.rgb; +#endif } void env_sampling_refract_sharp(vec3 viewpos, mat4 invviewmat, mat4 viewmat, vec3 N, float eta, diff --git a/source/blender/gpu/shaders/gpu_shader_material_ssr_frag.glsl b/source/blender/gpu/shaders/gpu_shader_material_ssr_frag.glsl new file mode 100644 index 00000000000..6ce98cdd597 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_material_ssr_frag.glsl @@ -0,0 +1,204 @@ +#define MAX_SSR_STEPS 128 +#define MAX_SSR_REFINE_STEPS 16 + +#if 0 /* 2D raymarch (More efficient) */ + +/* By Morgan McGuire and Michael Mara at Williams College 2014 + * Released as open source under the BSD 2-Clause License + * http://opensource.org/licenses/BSD-2-Clause + * http://casual-effects.blogspot.fr/2014/08/screen-space-ray-tracing.html */ + +float distanceSquared(vec2 a, vec2 b) { a -= b; return dot(a, a); } + +void swapIfBigger(inout float a, inout float b) { + if (a > b) { + float temp = a; + a = b; + b = temp; + } +} + +/* 2D raycast : still have some bug that needs to be sorted out before being usable */ +bool raycast(vec3 ray_origin, vec3 ray_dir, mat4 projpixel, sampler2D ssr_buffer, float thickness, + float nearz, float stride, float jitter, float maxstep, float ray_length, + out float hitstep, out vec2 hitpixel, out vec3 hitco) +{ + /* Clip ray to a near plane in 3D */ + if ((ray_origin.z + ray_dir.z * ray_length) > nearz) + ray_length = (nearz - ray_origin.z) / ray_dir.z; + + vec3 ray_end = ray_dir * ray_length + ray_origin; + + /* Project into screen space */ + vec4 H0 = projpixel * vec4(ray_origin, 1.0); + vec4 H1 = projpixel * vec4(ray_end, 1.0); + + /* There are a lot of divisions by w that can be turned into multiplications + * at some minor precision loss...and we need to interpolate these 1/w values + * anyway. */ + float k0 = 1.0 / H0.w; + float k1 = 1.0 / H1.w; + + /* Switch the original points to values that interpolate linearly in 2D */ + vec3 Q0 = ray_origin * k0; + vec3 Q1 = ray_end * k1; + + /* Screen-space endpoints */ + vec2 P0 = H0.xy * k0; + vec2 P1 = H1.xy * k1; + + /* [Optional clipping to frustum sides here] */ + + /* Initialize to off screen */ + hitpixel = vec2(-1.0, -1.0); + + /* If the line is degenerate, make it cover at least one pixel + * to avoid handling zero-pixel extent as a special case later */ + P1 += vec2((distanceSquared(P0, P1) < 0.0001) ? 0.01 : 0.0); + + vec2 delta = P1 - P0; + + /* Permute so that the primary iteration is in x to reduce large branches later. + * After this, "x" is the primary iteration direction and "y" is the secondary one + * If it is a more-vertical line, create a permutation that swaps x and y in the output + * and directly swizzle the inputs. */ + bool permute = false; + if (abs(delta.x) < abs(delta.y)) { + permute = true; + delta = delta.yx; + P1 = P1.yx; + P0 = P0.yx; + } + + /* Track the derivatives */ + float step_sign = sign(delta.x); + float invdx = step_sign / delta.x; + vec2 dP = vec2(step_sign, invdx * delta.y); + vec3 dQ = (Q1 - Q0) * invdx; + float dk = (k1 - k0) * invdx; + + /* Calculate pixel stride based on distance of ray origin from camera. */ + // float stride_scale = 1.0 - min( 1.0, -ray_origin.z); + // stride = 1.0 + stride_scale * stride; + + /* Scale derivatives by the desired pixel stride */ + dP *= stride; dQ *= stride; dk *= stride; + + /* Offset the starting values by the jitter fraction */ + P0 += dP * jitter; Q0 += dQ * jitter; k0 += dk * jitter; + + /* Slide each value from the start of the ray to the end */ + vec3 Q = Q0; vec2 P = P0; float k = k0; + + /* We track the ray depth at +/- 1/2 pixel to treat pixels as clip-space solid + * voxels. Because the depth at -1/2 for a given pixel will be the same as at + * +1/2 for the previous iteration, we actually only have to compute one value + * per iteration. */ + float prev_zmax = ray_origin.z; + float zmax = prev_zmax, zmin = prev_zmax; + float scene_zmax = zmax + 1e4; + + /* P1.x is never modified after this point, so pre-scale it by + * the step direction for a signed comparison */ + float end = P1.x * step_sign; + + bool hit = false; + + for (hitstep = 0.0; hitstep < MAX_SSR_STEPS && !hit; hitstep++) + { + /* Ray finished & no hit*/ + if ((hitstep > maxstep) || ((P.x * step_sign) > end)) break; + + P += dP; Q.z += dQ.z; k += dk; + + hitpixel = permute ? P.yx : P; + zmin = prev_zmax; + zmax = (dQ.z * 0.5 + Q.z) / (dk * 0.5 + k); + prev_zmax = zmax; + swapIfBigger(zmin, zmax); + + scene_zmax = texelFetch(ssr_buffer, ivec2(hitpixel), 0).a; + + /* background case */ + if (scene_zmax == 1.0) scene_zmax = -1e16; + + hit = ((zmax >= scene_zmax - thickness) && (zmin <= scene_zmax)); + } + + hitco = (Q0 + dQ * hitstep) / k; + return hit; +} + +#else /* 3D raymarch */ + +float getDeltaDepth(sampler2D ssr_buffer, mat4 projpixel, vec3 hitco) { + vec4 co = projpixel * vec4(hitco, 1.0); + co.xy /= co.w; + float depth = texelFetch(ssr_buffer, ivec2(co.xy), 0).a; + + /* background case */ + if (depth == 1.0) depth = -1e16; + + return depth - hitco.z; +} + +void binary_search(vec3 ray_dir, sampler2D ssr_buffer, mat4 projpixel, inout vec3 hitco) { + for (int i = 0; i < MAX_SSR_REFINE_STEPS; i++) { + ray_dir *= 0.5; + hitco -= ray_dir; + float delta = getDeltaDepth(ssr_buffer, projpixel, hitco); + if (delta < 0.0) hitco += ray_dir; + } +} + +/* 3D raycast */ +bool raycast(vec3 ray_origin, vec3 ray_dir, mat4 projpixel, sampler2D ssr_buffer, float thickness, + float nearz, float ray_step, float jitter, float maxstep, float ray_length, + out float hitstep, out vec2 hitpixel, out vec3 hitco) +{ + ray_dir *= ray_step; + + //thickness = 2 * ray_step; + + hitco = ray_origin; + hitco += ray_dir * jitter; + hitpixel = vec2(0.0); + + for (hitstep = 0.0; hitstep < MAX_SSR_STEPS && hitstep < maxstep; hitstep++) { + hitco += ray_dir; + float delta = getDeltaDepth(ssr_buffer, projpixel, hitco); + if (delta > 0.0 && delta < thickness) { + /* Refine hit */ + binary_search(ray_dir, ssr_buffer, projpixel, hitco); + /* Find texel coord */ + vec4 pix = projpixel * vec4(hitco, 1.0); + hitpixel = pix.xy / pix.w; + + return true; + } + } + + /* No hit */ + return false; +} +#endif + +float saturate(float a) { return clamp(a, 0.0, 1.0); } + +float ssr_contribution(vec3 ray_origin, float hitstep, float maxstep, float maxdistance, float attenuation, bool hit, inout vec3 hitco) +{ + /* ray step fade */ + float stepfade = saturate((1.0 - hitstep / maxstep) * attenuation); + + /* ray length fade */ + float rayfade = saturate((1.0 - length(ray_origin - hitco) / maxdistance) * attenuation); + + /* screen edges fade */ + vec4 co = gl_ProjectionMatrix * vec4(hitco, 1.0); + co.xy /= co.w; + hitco.xy = co.xy * 0.5 + 0.5; + float maxdimension = saturate(max(abs(co.x), abs(co.y))); + float screenfade = saturate((0.999999 - maxdimension) * attenuation); + + return sqrt(rayfade * screenfade) * float(hit); +} |