Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Fukhaut <turjuque@gmail.com>2016-05-03 20:41:41 +0300
committerClément Fukhaut <turjuque@gmail.com>2016-05-03 20:41:41 +0300
commit655cfca4524fc8295cb7ead9f2ccaf4f79d3f221 (patch)
tree3e4557940e8683cccca2d3fa4852a26bb9249ca6 /source/blender/gpu
parent7c777fe0383304219ab47251e2fe437d0ba90a7f (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.txt4
-rw-r--r--source/blender/gpu/GPU_material.h49
-rw-r--r--source/blender/gpu/GPU_shader.h1
-rw-r--r--source/blender/gpu/GPU_ssr.h64
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c133
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h7
-rw-r--r--source/blender/gpu/intern/gpu_draw.c50
-rw-r--r--source/blender/gpu/intern/gpu_material.c219
-rw-r--r--source/blender/gpu/intern/gpu_shader.c14
-rw-r--r--source/blender/gpu/intern/gpu_ssr.c170
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material_bsdf_frag.glsl49
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material_ssr_frag.glsl204
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);
+}