Eevee: Add "uber" Shader Output Nodes.

Include Metallic and Specular workflow.
Clearcoat and are not implemented yet.
This commit is contained in:
Clément Foucault 2017-05-02 19:25:25 +02:00
parent 54bde82445
commit a740495814
13 changed files with 262 additions and 25 deletions

View File

@ -216,6 +216,8 @@ shader_node_categories = [
NodeItem("NodeGroupInput", poll=group_input_output_item_poll),
]),
ShaderNewNodeCategory("SH_NEW_OUTPUT", "Output", items=[
NodeItem("ShaderNodeOutputMetallic", poll=object_shader_nodes_poll),
NodeItem("ShaderNodeOutputSpecular", poll=object_shader_nodes_poll),
NodeItem("ShaderNodeOutputMaterial", poll=object_shader_nodes_poll),
NodeItem("ShaderNodeOutputLamp", poll=object_shader_nodes_poll),
NodeItem("ShaderNodeOutputWorld", poll=world_shader_nodes_poll),

View File

@ -794,6 +794,8 @@ struct ShadeResult;
#define SH_NODE_UVALONGSTROKE 191
#define SH_NODE_TEX_POINTDENSITY 192
#define SH_NODE_BSDF_PRINCIPLED 193
#define SH_NODE_OUTPUT_METALLIC 194
#define SH_NODE_OUTPUT_SPECULAR 195
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1

View File

@ -3588,6 +3588,8 @@ static void registerShaderNodes(void)
register_node_type_sh_output_lamp();
register_node_type_sh_output_material();
register_node_type_sh_output_metallic();
register_node_type_sh_output_specular();
register_node_type_sh_output_world();
register_node_type_sh_output_linestyle();

View File

@ -490,20 +490,8 @@ static void EEVEE_cache_init(void *vedata)
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL;
psl->material_pass = DRW_pass_create("Material Shader Pass", state);
/* NOTE : this shading grp does not contain any geom, it's just here to setup uniforms & textures. */
stl->g_data->material_lit_grp = DRW_shgroup_create(e_data.default_lit, psl->material_pass);
DRW_shgroup_uniform_block(stl->g_data->material_lit_grp, "light_block", stl->light_ubo, 0);
DRW_shgroup_uniform_block(stl->g_data->material_lit_grp, "shadow_block", stl->shadow_ubo, 1);
DRW_shgroup_uniform_int(stl->g_data->material_lit_grp, "light_count", &stl->lamps->num_light, 1);
DRW_shgroup_uniform_float(stl->g_data->material_lit_grp, "lodMax", &stl->probes->lodmax, 1);
DRW_shgroup_uniform_vec3(stl->g_data->material_lit_grp, "shCoefs[0]", (float *)stl->probes->shcoefs, 9);
DRW_shgroup_uniform_vec3(stl->g_data->material_lit_grp, "cameraPos", e_data.camera_pos, 1);
DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "ltcMat", e_data.ltc_mat, 0);
DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "brdfLut", e_data.brdf_lut, 1);
DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "probeFiltered", txl->probe_pool, 2);
/* NOTE : Adding Shadow Map textures uniform in EEVEE_cache_finish */
}
{
/* Final pass : Map HDR color to LDR color.
* Write result to the default color buffer */
@ -522,6 +510,7 @@ static void EEVEE_cache_init(void *vedata)
static void EEVEE_cache_populate(void *vedata, Object *ob)
{
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
struct Batch *geom = DRW_cache_object_surface_get(ob);
@ -558,6 +547,16 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
if (shgrp) {
DRW_shgroup_call_add(shgrp, mat_geom[i], ob->obmat);
DRW_shgroup_uniform_block(shgrp, "light_block", stl->light_ubo, 0);
DRW_shgroup_uniform_block(shgrp, "shadow_block", stl->shadow_ubo, 1);
DRW_shgroup_uniform_int(shgrp, "light_count", &stl->lamps->num_light, 1);
DRW_shgroup_uniform_float(shgrp, "lodMax", &stl->probes->lodmax, 1);
DRW_shgroup_uniform_vec3(shgrp, "shCoefs[0]", (float *)stl->probes->shcoefs, 9);
DRW_shgroup_uniform_vec3(shgrp, "cameraPos", e_data.camera_pos, 1);
DRW_shgroup_uniform_texture(shgrp, "ltcMat", e_data.ltc_mat, 0);
DRW_shgroup_uniform_texture(shgrp, "brdfLut", e_data.brdf_lut, 1);
DRW_shgroup_uniform_texture(shgrp, "probeFiltered", txl->probe_pool, 2);
}
else {
/* Shader failed : pink color */
@ -599,8 +598,23 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
}
}
typedef struct eevee_bind_shadow_data {
struct GPUTexture *shadow_depth_map_pool;
struct GPUTexture *shadow_depth_cube_pool;
struct GPUTexture *shadow_depth_cascade_pool;
} eevee_bind_shadow_data;
static void eevee_bind_shadow(void *data, DRWShadingGroup *shgrp)
{
eevee_bind_shadow_data *shdw_data = data;
DRW_shgroup_uniform_texture(shgrp, "shadowMaps", shdw_data->shadow_depth_map_pool, 3);
DRW_shgroup_uniform_texture(shgrp, "shadowCubes", shdw_data->shadow_depth_cube_pool, 4);
DRW_shgroup_uniform_texture(shgrp, "shadowCascades", shdw_data->shadow_depth_cascade_pool, 5);
}
static void EEVEE_cache_finish(void *vedata)
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
@ -608,13 +622,14 @@ static void EEVEE_cache_finish(void *vedata)
EEVEE_lights_cache_finish(stl, txl, fbl);
/* Shadows binding */
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "shadowMaps", txl->shadow_depth_map_pool, 4);
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "shadowCubes", txl->shadow_depth_cube_pool, 5);
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "shadowCascades", txl->shadow_depth_cascade_pool, 6);
eevee_bind_shadow_data data;
DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "shadowMaps", txl->shadow_depth_map_pool, 4);
DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "shadowCubes", txl->shadow_depth_cube_pool, 5);
DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "shadowCascades", txl->shadow_depth_cascade_pool, 6);
data.shadow_depth_map_pool = txl->shadow_depth_map_pool;
data.shadow_depth_cube_pool = txl->shadow_depth_cube_pool;
data.shadow_depth_cascade_pool = txl->shadow_depth_cascade_pool;
DRW_pass_foreach_shgroup(psl->default_pass, eevee_bind_shadow, &data);
DRW_pass_foreach_shgroup(psl->material_pass, eevee_bind_shadow, &data);
}
static void EEVEE_draw_scene(void *vedata)

View File

@ -175,7 +175,6 @@ typedef struct EEVEE_LampEngineData {
typedef struct EEVEE_PrivateData {
struct DRWShadingGroup *default_lit_grp;
struct DRWShadingGroup *material_lit_grp;
struct DRWShadingGroup *shadow_shgrp;
struct DRWShadingGroup *depth_shgrp;
struct DRWShadingGroup *depth_shgrp_cull;

View File

@ -9,5 +9,5 @@ void main()
{
float roughness = 1.0 - float(hardness) / 511.0;
roughness *= roughness;
FragColor = vec4(eevee_surface_lit(worldNormal, diffuse_col, specular_col, roughness), 1.0);
FragColor = vec4(eevee_surface_lit(worldNormal, diffuse_col, specular_col, roughness, 1.0), 1.0);
}

View File

@ -231,7 +231,7 @@ float light_common(inout LightData ld, inout ShadingData sd)
return vis;
}
vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness)
vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness, float ao)
{
ShadingData sd;
sd.N = normalize(world_normal);
@ -243,6 +243,7 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness)
sd.spec_dominant_dir = get_specular_dominant_dir(sd.N, sd.R, roughness);
vec3 radiance = vec3(0.0);
vec3 indirect_radiance = vec3(0.0);
/* Analitic Lights */
for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
@ -264,9 +265,9 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness)
vec2 uv = ltc_coords(dot(sd.N, sd.V), sqrt(roughness));
vec2 brdf_lut = texture(brdfLut, uv).rg;
vec3 Li = textureLod(probeFiltered, sd.spec_dominant_dir, roughness * lodMax).rgb;
radiance += Li * brdf_lut.y + f0 * Li * brdf_lut.x;
indirect_radiance += Li * brdf_lut.y + f0 * Li * brdf_lut.x;
radiance += spherical_harmonics(sd.N, shCoefs) * albedo;
indirect_radiance += spherical_harmonics(sd.N, shCoefs) * albedo;
return radiance;
return radiance + indirect_radiance * ao;
}

View File

@ -3828,6 +3828,37 @@ void node_output_world(vec4 surface, vec4 volume, out vec4 result)
result = surface;
}
void convert_metallic_to_specular(vec4 basecol, float metallic, float specular_fac, out vec4 diffuse, out vec4 f0)
{
vec4 dielectric = vec4(0.034) * specular_fac * 2.0;
diffuse = mix(basecol, vec4(0.0), metallic);
f0 = mix(dielectric, basecol, metallic);
}
void world_normals_get(out vec3 N)
{
N = gl_FrontFacing ? worldNormal : -worldNormal;
}
void node_output_metallic(
vec4 basecol, float metallic, float specular, float roughness, vec4 emissive, float transp, vec3 normal,
float clearcoat, float clearcoat_roughness, vec3 clearcoat_normal,
float occlusion, out vec4 result)
{
vec4 diffuse, f0;
convert_metallic_to_specular(basecol, metallic, specular, diffuse, f0);
result = vec4(eevee_surface_lit(normal, diffuse.rgb, f0.rgb, roughness, occlusion) + emissive.rgb, 1.0 - transp);
}
void node_output_specular(
vec4 diffuse, vec4 specular, float roughness, vec4 emissive, float transp, vec3 normal,
float clearcoat, float clearcoat_roughness, vec3 clearcoat_normal,
float occlusion, out vec4 result)
{
result = vec4(eevee_surface_lit(normal, diffuse.rgb, specular.rgb, roughness, occlusion) + emissive.rgb, 1.0 - transp);
}
/* ********************** matcap style render ******************** */
void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result)

View File

@ -186,6 +186,8 @@ set(SRC
shader/nodes/node_shader_hair_info.c
shader/nodes/node_shader_output_lamp.c
shader/nodes/node_shader_output_material.c
shader/nodes/node_shader_output_metallic.c
shader/nodes/node_shader_output_specular.c
shader/nodes/node_shader_output_world.c
shader/nodes/node_shader_output_linestyle.c
shader/nodes/node_shader_particle_info.c

View File

@ -120,6 +120,8 @@ void register_node_type_sh_uvalongstroke(void);
void register_node_type_sh_output_lamp(void);
void register_node_type_sh_output_material(void);
void register_node_type_sh_output_metallic(void);
void register_node_type_sh_output_specular(void);
void register_node_type_sh_output_world(void);
void register_node_type_sh_output_linestyle(void);

View File

@ -67,6 +67,8 @@ DefNode( ShaderNode, SH_NODE_COMBRGB, 0, "COMBR
DefNode( ShaderNode, SH_NODE_HUE_SAT, 0, "HUE_SAT", HueSaturation, "Hue/Saturation", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_MATERIAL, def_sh_output, "OUTPUT_MATERIAL", OutputMaterial, "Material Output", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_METALLIC, def_sh_output, "OUTPUT_METALLIC", OutputMetallic, "Material Metallic Output", "")
DefNode( ShaderNode, SH_NODE_OUTPUT_SPECULAR, def_sh_output, "OUTPUT_SPECULAR", OutputSpecular, "Material Specular Output", "")
DefNode( ShaderNode, SH_NODE_OUTPUT_LAMP, def_sh_output, "OUTPUT_LAMP", OutputLamp, "Lamp Output", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_WORLD, def_sh_output, "OUTPUT_WORLD", OutputWorld, "World Output", "" )
DefNode( ShaderNode, SH_NODE_OUTPUT_LINESTYLE, def_sh_output_linestyle,"OUTPUT_LINESTYLE", OutputLineStyle, "Line Style Output", "" )

View File

@ -0,0 +1,90 @@
/*
* ***** 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): Clément Foucault.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "../node_shader_util.h"
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_output_metallic_in[] = {
{ SOCK_RGBA, 1, N_("Base Color"), 0.8f, 0.8f, 0.8f, 1.0f},
{ SOCK_FLOAT, 1, N_("Metallic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("Specular"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_RGBA, 1, N_("Emissive Color"), 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Transparency"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ SOCK_FLOAT, 1, N_("Clear Coat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("Clear Coat Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_VECTOR, 1, N_("Clear Coat Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ SOCK_FLOAT, 1, N_("Ambient Occlusion"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" }
};
static int node_shader_gpu_output_metallic(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *outlink;
static float one = 1.0f;
/* Normals */
if (!in[6].link) {
GPU_link(mat, "world_normals_get", &in[6].link);
}
/* Clearcoat Normals */
if (!in[9].link) {
GPU_link(mat, "world_normals_get", &in[9].link);
}
/* Occlusion */
if (!in[10].link) {
GPU_link(mat, "set_value", GPU_uniform(&one), &in[10].link);
}
GPU_stack_link(mat, "node_output_metallic", in, out, &outlink);
GPU_material_output_link(mat, outlink);
return true;
}
/* node type definition */
void register_node_type_sh_output_metallic(void)
{
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_OUTPUT_METALLIC, "Metallic Material Output", NODE_CLASS_OUTPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_output_metallic_in, NULL);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_output_metallic);
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
nodeRegisterType(&ntype);
}

View File

@ -0,0 +1,89 @@
/*
* ***** 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): Clément Foucault.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "../node_shader_util.h"
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_output_specular_in[] = {
{ SOCK_RGBA, 1, N_("Base Color"), 0.8f, 0.8f, 0.8f, 1.0f},
{ SOCK_RGBA, 1, N_("Specular"), 0.03f, 0.03f, 0.03f, 1.0f},
{ SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_RGBA, 1, N_("Emissive Color"), 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Transparency"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ SOCK_FLOAT, 1, N_("Clear Coat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_FLOAT, 1, N_("Clear Coat Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{ SOCK_VECTOR, 1, N_("Clear Coat Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ SOCK_FLOAT, 1, N_("Ambient Occlusion"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" }
};
static int node_shader_gpu_output_specular(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
GPUNodeLink *outlink;
static float one = 1.0f;
/* Normals */
if (!in[5].link) {
GPU_link(mat, "world_normals_get", &in[5].link);
}
/* Clearcoat Normals */
if (!in[8].link) {
GPU_link(mat, "world_normals_get", &in[8].link);
}
/* Occlusion */
if (!in[9].link) {
GPU_link(mat, "set_value", GPU_uniform(&one), &in[9].link);
}
GPU_stack_link(mat, "node_output_specular", in, out, &outlink);
GPU_material_output_link(mat, outlink);
return true;
}
/* node type definition */
void register_node_type_sh_output_specular(void)
{
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_OUTPUT_SPECULAR, "Specular Material Output", NODE_CLASS_OUTPUT, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_output_specular_in, NULL);
node_type_init(&ntype, NULL);
node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_output_specular);
/* Do not allow muting output node. */
node_type_internal_links(&ntype, NULL);
nodeRegisterType(&ntype);
}