Shader Node Editor: Add Closure to RGB convertion node.

Patch D3205 by Kanzaki Wataru

Only implemented in Eevee for now. Collapse a closure to RGBA so we can
do NPR stuff on the resulting color.

Use an emission shader to convert the color back to a closure.

Doing this will break PBR and will kill any SSR and SSS effects the shader
the shader rely on. That said screen space refraction and ambient occlusion
are supported due to the way they are implemented.
This commit is contained in:
Clément Foucault 2018-05-14 13:34:54 +02:00
parent e862bcd6c8
commit f1a5fd90ba
11 changed files with 132 additions and 41 deletions

View File

@ -253,6 +253,7 @@ shader_node_categories = [
NodeItem("ShaderNodeMath"),
NodeItem("ShaderNodeValToRGB"),
NodeItem("ShaderNodeRGBToBW"),
NodeItem("ShaderNodeShaderToRGB", poll=object_eevee_shader_nodes_poll),
NodeItem("ShaderNodeVectorMath"),
NodeItem("ShaderNodeSeparateRGB"),
NodeItem("ShaderNodeCombineRGB"),

View File

@ -714,6 +714,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, c
#define SH_NODE_MIX_RGB 103
#define SH_NODE_VALTORGB 104
#define SH_NODE_RGBTOBW 105
#define SH_NODE_SHADERTORGB 106
//#define SH_NODE_TEXTURE 106
#define SH_NODE_NORMAL 107
//#define SH_NODE_GEOMETRY 108

View File

@ -3473,6 +3473,7 @@ static void registerShaderNodes(void)
register_node_type_sh_mix_rgb();
register_node_type_sh_valtorgb();
register_node_type_sh_rgbtobw();
register_node_type_sh_shadertorgb();
register_node_type_sh_normal();
register_node_type_sh_mapping();
register_node_type_sh_curve_vec();

View File

@ -68,9 +68,9 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_bsdf_sampling_lib_glsl,
datatoc_ambient_occlusion_lib_glsl,
datatoc_octahedron_lib_glsl,
datatoc_lightprobe_lib_glsl,
datatoc_ambient_occlusion_lib_glsl,
datatoc_raytrace_lib_glsl,
datatoc_effect_ssr_frag_glsl);

View File

@ -2,12 +2,6 @@
/* Based on Stochastic Screen Space Reflections
* https://www.ea.com/frostbite/news/stochastic-screen-space-reflections */
#ifndef UTIL_TEX
#define UTIL_TEX
uniform sampler2DArray utilTex;
#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
#define MAX_MIP 9.0
uniform ivec2 halfresOffset;
@ -183,40 +177,6 @@ const ivec2 neighbors[32] = ivec2[32](
out vec4 fragColor;
void fallback_cubemap(
vec3 N, vec3 V, vec3 W, vec3 viewPosition, float roughness, float roughnessSquared, inout vec4 spec_accum)
{
/* Specular probes */
vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
vec3 bent_normal;
#ifdef SSR_AO
float final_ao = occlusion_compute(N, viewPosition, 1.0, rand, bent_normal);
final_ao = specular_occlusion(dot(N, V), final_ao, roughness);
#else
const float final_ao = 1.0;
#endif
/* Starts at 1 because 0 is world probe */
for (int i = 1; i < MAX_PROBE && i < prbNumRenderCube && spec_accum.a < 0.999; ++i) {
CubeData cd = probes_data[i];
float fade = probe_attenuation_cube(cd, W);
if (fade > 0.0) {
vec3 spec = final_ao * probe_evaluate_cube(float(i), cd, W, spec_dir, roughness);
accumulate_light(spec, fade, spec_accum);
}
}
/* World Specular */
if (spec_accum.a < 0.999) {
vec3 spec = final_ao * probe_evaluate_world_spec(spec_dir, roughness);
accumulate_light(spec, 1.0, spec_accum);
}
}
#if 0 /* Finish reprojection with motion vectors */
vec3 get_motion_vector(vec3 pos)
{

View File

@ -72,6 +72,12 @@ struct GridData {
#define MAX_PLANAR 1
#endif
#ifndef UTIL_TEX
#define UTIL_TEX
uniform sampler2DArray utilTex;
#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
layout(std140) uniform probe_block {
CubeData probes_data[MAX_PROBE];
};
@ -196,6 +202,40 @@ vec3 probe_evaluate_planar(
return sample;
}
void fallback_cubemap(
vec3 N, vec3 V, vec3 W, vec3 viewPosition, float roughness, float roughnessSquared, inout vec4 spec_accum)
{
/* Specular probes */
vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
vec3 bent_normal;
#ifdef SSR_AO
float final_ao = occlusion_compute(N, viewPosition, 1.0, rand, bent_normal);
final_ao = specular_occlusion(dot(N, V), final_ao, roughness);
#else
const float final_ao = 1.0;
#endif
/* Starts at 1 because 0 is world probe */
for (int i = 1; i < MAX_PROBE && i < prbNumRenderCube && spec_accum.a < 0.999; ++i) {
CubeData cd = probes_data[i];
float fade = probe_attenuation_cube(cd, W);
if (fade > 0.0) {
vec3 spec = final_ao * probe_evaluate_cube(float(i), cd, W, spec_dir, roughness);
accumulate_light(spec, fade, spec_accum);
}
}
/* World Specular */
if (spec_accum.a < 0.999) {
vec3 spec = final_ao * probe_evaluate_world_spec(spec_dir, roughness);
accumulate_light(spec, 1.0, spec_accum);
}
}
#ifdef IRRADIANCE_LIB
vec3 probe_evaluate_grid(GridData gd, vec3 W, vec3 N, vec3 localpos)
{

View File

@ -2544,4 +2544,28 @@ void node_eevee_specular(
result.ssr_id = int(ssr_id);
}
void node_shadertorgb(Closure cl, out vec4 outcol, out float outalpha)
{
vec4 spec_accum = vec4(0.0);
if (ssrToggle && cl.ssr_id == outputSsrId) {
vec3 V = cameraVec;
vec3 vN = normal_decode(cl.ssr_normal, viewCameraVec);
vec3 N = transform_direction(ViewMatrixInverse, vN);
float roughness = cl.ssr_data.a;
float roughnessSquared = max(1e-3, roughness * roughness);
fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum);
}
outalpha = cl.opacity;
outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0);
# ifdef USE_SSS
# ifdef USE_SSS_ALBEDO
outcol += (cl.sss_data * cl.sss_albedo);
# else
outcol += cl.sss_data;
# endif
# endif
}
#endif /* VOLUMETRICS */

View File

@ -177,6 +177,7 @@ set(SRC
shader/nodes/node_shader_light_falloff.c
shader/nodes/node_shader_light_path.c
shader/nodes/node_shader_mix_shader.c
shader/nodes/node_shader_shaderToRgb.c
shader/nodes/node_shader_normal_map.c
shader/nodes/node_shader_object_info.c
shader/nodes/node_shader_hair_info.c

View File

@ -50,6 +50,7 @@ void register_node_type_sh_rgb(void);
void register_node_type_sh_mix_rgb(void);
void register_node_type_sh_valtorgb(void);
void register_node_type_sh_rgbtobw(void);
void register_node_type_sh_shadertorgb(void);
void register_node_type_sh_normal(void);
void register_node_type_sh_gamma(void);
void register_node_type_sh_brightcontrast(void);

View File

@ -45,6 +45,7 @@ DefNode( ShaderNode, SH_NODE_VALUE, 0, "VALUE
DefNode( ShaderNode, SH_NODE_MIX_RGB, def_mix_rgb, "MIX_RGB", MixRGB, "MixRGB", "" )
DefNode( ShaderNode, SH_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "ColorRamp", "" )
DefNode( ShaderNode, SH_NODE_RGBTOBW, 0, "RGBTOBW", RGBToBW, "RGB to BW", "" )
DefNode( ShaderNode, SH_NODE_SHADERTORGB, 0, "SHADERTORGB", ShaderToRGB, "Shader to RGB", "" )
DefNode( ShaderNode, SH_NODE_NORMAL, 0, "NORMAL", Normal, "Normal", "" )
DefNode( ShaderNode, SH_NODE_GAMMA, 0, "GAMMA", Gamma, "Gamma", "" )
DefNode( ShaderNode, SH_NODE_BRIGHTCONTRAST, 0, "BRIGHTCONTRAST", BrightContrast, "Bright Contrast", "" )

View File

@ -0,0 +1,61 @@
/*
* ***** 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): Kanzaki Wataru, Kinouti Takahiro
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "../node_shader_util.h"
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_shadertorgb_in[] = {
{ SOCK_SHADER, 1, N_("Shader")},
{ -1, 0, "" }
};
static bNodeSocketTemplate sh_node_shadertorgb_out[] = {
{ SOCK_RGBA, 0, N_("Color")},
{ SOCK_FLOAT, 0, N_("Alpha")},
{ -1, 0, "" }
};
static int node_shader_gpu_shadertorgb(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, node, "node_shadertorgb", in, out);
}
/* node type definition */
void register_node_type_sh_shadertorgb(void)
{
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_SHADERTORGB, "Shader to RGB", NODE_CLASS_CONVERTOR, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_shadertorgb_in, sh_node_shadertorgb_out);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_shadertorgb);
nodeRegisterType(&ntype);
}