diff options
Diffstat (limited to 'source/blender/nodes/shader/nodes/node_shader_tex_environment.cc')
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_tex_environment.cc | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.cc b/source/blender/nodes/shader/nodes/node_shader_tex_environment.cc new file mode 100644 index 00000000000..24ecdee12d8 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.cc @@ -0,0 +1,148 @@ +/* + * 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. + */ + +#include "node_shader_util.hh" + +namespace blender::nodes::node_shader_tex_environment_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input<decl::Vector>(N_("Vector")).hide_value(); + b.add_output<decl::Color>(N_("Color")).no_muted_links(); +} + +static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeTexEnvironment *tex = MEM_cnew<NodeTexEnvironment>("NodeTexEnvironment"); + BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); + BKE_texture_colormapping_default(&tex->base.color_mapping); + tex->projection = SHD_PROJ_EQUIRECTANGULAR; + BKE_imageuser_default(&tex->iuser); + + node->storage = tex; +} + +static int node_shader_gpu_tex_environment(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + Image *ima = (Image *)node->id; + NodeTexEnvironment *tex = (NodeTexEnvironment *)node->storage; + + /* We get the image user from the original node, since GPU image keeps + * a pointer to it and the dependency refreshes the original. */ + bNode *node_original = node->original ? node->original : node; + NodeTexImage *tex_original = (NodeTexImage *)node_original->storage; + ImageUser *iuser = &tex_original->iuser; + eGPUSamplerState sampler = GPU_SAMPLER_REPEAT | GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER; + /* TODO(fclem): For now assume mipmap is always enabled. */ + if (true) { + sampler |= GPU_SAMPLER_MIPMAP; + } + + GPUNodeLink *outalpha; + + /* HACK(fclem): For lookdev mode: do not compile an empty environment and just create an empty + * texture entry point. We manually bind to it after DRW_shgroup_add_material_resources(). */ + if (!ima && !GPU_material_flag_get(mat, GPU_MATFLAG_LOOKDEV_HACK)) { + return GPU_stack_link(mat, node, "node_tex_environment_empty", in, out); + } + + node_shader_gpu_default_tex_coord(mat, node, &in[0].link); + node_shader_gpu_tex_mapping(mat, node, in, out); + + /* Compute texture coordinate. */ + if (tex->projection == SHD_PROJ_EQUIRECTANGULAR) { + GPU_link(mat, "node_tex_environment_equirectangular", in[0].link, &in[0].link); + /* To fix pole issue we clamp the v coordinate. */ + sampler &= ~GPU_SAMPLER_REPEAT_T; + /* Force the highest mipmap and don't do anisotropic filtering. + * This is to fix the artifact caused by derivatives discontinuity. */ + sampler &= ~(GPU_SAMPLER_MIPMAP | GPU_SAMPLER_ANISO); + } + else { + GPU_link(mat, "node_tex_environment_mirror_ball", in[0].link, &in[0].link); + /* Fix pole issue. */ + sampler &= ~GPU_SAMPLER_REPEAT; + } + + const char *gpu_fn; + static const char *names[] = { + "node_tex_image_linear", + "node_tex_image_cubic", + }; + + switch (tex->interpolation) { + case SHD_INTERP_LINEAR: + gpu_fn = names[0]; + break; + case SHD_INTERP_CLOSEST: + sampler &= ~(GPU_SAMPLER_FILTER | GPU_SAMPLER_MIPMAP); + gpu_fn = names[0]; + break; + default: + gpu_fn = names[1]; + break; + } + + /* Sample texture with correct interpolation. */ + GPU_link(mat, gpu_fn, in[0].link, GPU_image(mat, ima, iuser, sampler), &out[0].link, &outalpha); + + if (out[0].hasoutput && ima) { + if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) || + IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) { + /* Don't let alpha affect color output in these cases. */ + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); + } + else { + /* Always output with premultiplied alpha. */ + if (ima->alpha_mode == IMA_ALPHA_PREMUL) { + GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link); + } + else { + GPU_link(mat, "color_alpha_premultiply", out[0].link, &out[0].link); + } + } + } + + return true; +} + +} // namespace blender::nodes::node_shader_tex_environment_cc + +/* node type definition */ +void register_node_type_sh_tex_environment() +{ + namespace file_ns = blender::nodes::node_shader_tex_environment_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_TEX_ENVIRONMENT, "Environment Texture", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::node_declare; + node_type_init(&ntype, file_ns::node_shader_init_tex_environment); + node_type_storage( + &ntype, "NodeTexEnvironment", node_free_standard_storage, node_copy_standard_storage); + node_type_gpu(&ntype, file_ns::node_shader_gpu_tex_environment); + ntype.labelfunc = node_image_label; + node_type_size_preset(&ntype, NODE_SIZE_LARGE); + + nodeRegisterType(&ntype); +} |