diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp index 5604c2989fd..39e49ac3478 100644 --- a/intern/cycles/blender/shader.cpp +++ b/intern/cycles/blender/shader.cpp @@ -689,6 +689,9 @@ static ShaderNode *add_node(Scene *scene, else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) { node = graph->create_node(); } + else if (b_node.is_a(&RNA_ShaderNodePointInfo)) { + node = graph->create_node(); + } else if (b_node.is_a(&RNA_ShaderNodeVolumeInfo)) { node = graph->create_node(); } diff --git a/intern/cycles/kernel/geom/curve.h b/intern/cycles/kernel/geom/curve.h index 8a63f01643b..48ee8226e89 100644 --- a/intern/cycles/kernel/geom/curve.h +++ b/intern/cycles/kernel/geom/curve.h @@ -226,6 +226,18 @@ ccl_device float curve_thickness(KernelGlobals kg, ccl_private const ShaderData return r * 2.0f; } +/* Curve random */ + +ccl_device float curve_random(KernelGlobals kg, ccl_private const ShaderData *sd) +{ + if (sd->type & PRIMITIVE_CURVE) { + const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_CURVE_RANDOM); + return (desc.offset != ATTR_STD_NOT_FOUND) ? curve_attribute_float(kg, sd, desc, NULL, NULL) : + 0.0f; + } + return 0.0f; +} + /* Curve location for motion pass, linear interpolation between keys and * ignoring radius because we do the same for the motion keys */ diff --git a/intern/cycles/kernel/geom/point.h b/intern/cycles/kernel/geom/point.h index 23764d49095..545b5c7fa43 100644 --- a/intern/cycles/kernel/geom/point.h +++ b/intern/cycles/kernel/geom/point.h @@ -109,17 +109,59 @@ ccl_device float4 point_attribute_float4(KernelGlobals kg, } } +/* Point position */ + +ccl_device float3 point_position(KernelGlobals kg, ccl_private const ShaderData *sd) +{ + if (sd->type & PRIMITIVE_POINT) { + /* World space center. */ + float3 P = (sd->type & PRIMITIVE_MOTION) ? + float4_to_float3(motion_point(kg, sd->object, sd->prim, sd->time)) : + float4_to_float3(kernel_tex_fetch(__points, sd->prim)); + + if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) { + object_position_transform(kg, sd, &P); + } + + return P; + } + + return zero_float3(); +} + /* Point radius */ ccl_device float point_radius(KernelGlobals kg, ccl_private const ShaderData *sd) { if (sd->type & PRIMITIVE_POINT) { - return kernel_tex_fetch(__points, sd->prim).w; + /* World space radius. */ + const float r = kernel_tex_fetch(__points, sd->prim).w; + + if (sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED) { + return r; + } + else { + float3 dir = make_float3(r, r, r); + object_dir_transform(kg, sd, &dir); + return average(dir); + } } return 0.0f; } +/* Point random */ + +ccl_device float point_random(KernelGlobals kg, ccl_private const ShaderData *sd) +{ + if (sd->type & PRIMITIVE_POINT) { + const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_POINT_RANDOM); + return (desc.offset != ATTR_STD_NOT_FOUND) ? point_attribute_float(kg, sd, desc, NULL, NULL) : + 0.0f; + } + return 0.0f; +} + /* Point location for motion pass, linear interpolation between keys and * ignoring radius because we do the same for the motion keys */ diff --git a/intern/cycles/kernel/osl/services.cpp b/intern/cycles/kernel/osl/services.cpp index a79fc323a13..d79e7dfa8a5 100644 --- a/intern/cycles/kernel/osl/services.cpp +++ b/intern/cycles/kernel/osl/services.cpp @@ -116,6 +116,8 @@ ustring OSLRenderServices::u_curve_tangent_normal("geom:curve_tangent_normal"); ustring OSLRenderServices::u_curve_random("geom:curve_random"); ustring OSLRenderServices::u_is_point("geom:is_point"); ustring OSLRenderServices::u_point_radius("geom:point_radius"); +ustring OSLRenderServices::u_point_position("geom:point_position"); +ustring OSLRenderServices::u_point_random("geom:point_random"); ustring OSLRenderServices::u_normal_map_normal("geom:normal_map_normal"); ustring OSLRenderServices::u_path_ray_length("path:ray_length"); ustring OSLRenderServices::u_path_ray_depth("path:ray_depth"); @@ -999,6 +1001,10 @@ bool OSLRenderServices::get_object_standard_attribute(const KernelGlobalsCPU *kg float3 f = curve_tangent_normal(kg, sd); return set_attribute_float3(f, type, derivatives, val); } + else if (name == u_curve_random) { + float f = curve_random(kg, sd); + return set_attribute_float(f, type, derivatives, val); + } /* point attributes */ else if (name == u_is_point) { float f = (sd->type & PRIMITIVE_POINT) != 0; @@ -1008,6 +1014,14 @@ bool OSLRenderServices::get_object_standard_attribute(const KernelGlobalsCPU *kg float f = point_radius(kg, sd); return set_attribute_float(f, type, derivatives, val); } + else if (name == u_point_position) { + float3 f = point_position(kg, sd); + return set_attribute_float3(f, type, derivatives, val); + } + else if (name == u_point_random) { + float f = point_random(kg, sd); + return set_attribute_float(f, type, derivatives, val); + } else if (name == u_normal_map_normal) { if (sd->type & PRIMITIVE_TRIANGLE) { float3 f = triangle_smooth_normal_unnormalized(kg, sd, sd->Ng, sd->prim, sd->u, sd->v); diff --git a/intern/cycles/kernel/osl/services.h b/intern/cycles/kernel/osl/services.h index 9526c92b8fb..96c71297186 100644 --- a/intern/cycles/kernel/osl/services.h +++ b/intern/cycles/kernel/osl/services.h @@ -298,7 +298,9 @@ class OSLRenderServices : public OSL::RendererServices { static ustring u_curve_tangent_normal; static ustring u_curve_random; static ustring u_is_point; + static ustring u_point_position; static ustring u_point_radius; + static ustring u_point_random; static ustring u_normal_map_normal; static ustring u_path_ray_length; static ustring u_path_ray_depth; diff --git a/intern/cycles/kernel/osl/shaders/CMakeLists.txt b/intern/cycles/kernel/osl/shaders/CMakeLists.txt index 4cafdb2a6d7..16a9b1cc012 100644 --- a/intern/cycles/kernel/osl/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/osl/shaders/CMakeLists.txt @@ -49,6 +49,7 @@ set(SRC_OSL node_glossy_bsdf.osl node_gradient_texture.osl node_hair_info.osl + node_point_info.osl node_scatter_volume.osl node_absorption_volume.osl node_principled_volume.osl diff --git a/intern/cycles/kernel/osl/shaders/node_point_info.osl b/intern/cycles/kernel/osl/shaders/node_point_info.osl new file mode 100644 index 00000000000..58d8acbf269 --- /dev/null +++ b/intern/cycles/kernel/osl/shaders/node_point_info.osl @@ -0,0 +1,26 @@ +/* + * Copyright 2011-2022 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stdcycles.h" + +shader node_point_info(output point Position = point(0.0, 0.0, 0.0), + output float Radius = 0.0, + output float Random = 0.0) +{ + getattribute("geom:point_position", Position); + getattribute("geom:point_radius", Radius); + getattribute("geom:point_random", Random); +} diff --git a/intern/cycles/kernel/svm/geometry.h b/intern/cycles/kernel/svm/geometry.h index 2bac58b0aa2..225348b1ac2 100644 --- a/intern/cycles/kernel/svm/geometry.h +++ b/intern/cycles/kernel/svm/geometry.h @@ -242,13 +242,6 @@ ccl_device_noinline void svm_node_hair_info(KernelGlobals kg, stack_store_float(stack, out_offset, data); break; } -# if 0 - case NODE_INFO_CURVE_FADE: { - data = sd->curve_transparency; - stack_store_float(stack, out_offset, data); - break; - } -# endif case NODE_INFO_CURVE_TANGENT_NORMAL: { data3 = curve_tangent_normal(kg, sd); stack_store_float3(stack, out_offset, data3); @@ -258,4 +251,28 @@ ccl_device_noinline void svm_node_hair_info(KernelGlobals kg, } #endif +#ifdef __POINTCLOUD__ + +/* Point Info */ + +ccl_device_noinline void svm_node_point_info(KernelGlobals kg, + ccl_private ShaderData *sd, + ccl_private float *stack, + uint type, + uint out_offset) +{ + switch (type) { + case NODE_INFO_POINT_POSITION: + stack_store_float3(stack, out_offset, point_position(kg, sd)); + break; + case NODE_INFO_POINT_RADIUS: + stack_store_float(stack, out_offset, point_radius(kg, sd)); + break; + case NODE_INFO_POINT_RANDOM: + break; /* handled as attribute */ + } +} + +#endif + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index b226bc66771..35d4c3f2055 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -454,13 +454,14 @@ ccl_device void svm_eval_nodes(KernelGlobals kg, break; #if defined(__HAIR__) case NODE_HAIR_INFO: - IF_KERNEL_NODES_FEATURE(HAIR) - { - svm_node_hair_info(kg, sd, stack, node.y, node.z); - } + svm_node_hair_info(kg, sd, stack, node.y, node.z); + break; +#endif +#if defined(__POINTCLOUD__) + case NODE_POINT_INFO: + svm_node_point_info(kg, sd, stack, node.y, node.z); break; #endif - case NODE_TEXTURE_MAPPING: offset = svm_node_texture_mapping(kg, sd, stack, node.y, node.z, offset); break; diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h index dd1b1f9bc28..16e9fd8862a 100644 --- a/intern/cycles/kernel/svm/types.h +++ b/intern/cycles/kernel/svm/types.h @@ -81,6 +81,7 @@ typedef enum ShaderNodeType { NODE_OBJECT_INFO, NODE_PARTICLE_INFO, NODE_HAIR_INFO, + NODE_POINT_INFO, NODE_TEXTURE_MAPPING, NODE_MAPPING, NODE_MIN_MAX, @@ -176,12 +177,16 @@ typedef enum NodeHairInfo { NODE_INFO_CURVE_INTERCEPT, NODE_INFO_CURVE_LENGTH, NODE_INFO_CURVE_THICKNESS, - /* Fade for minimum hair width transiency. */ - // NODE_INFO_CURVE_FADE, NODE_INFO_CURVE_TANGENT_NORMAL, NODE_INFO_CURVE_RANDOM, } NodeHairInfo; +typedef enum NodePointInfo { + NODE_INFO_POINT_POSITION, + NODE_INFO_POINT_RADIUS, + NODE_INFO_POINT_RANDOM, +} NodePointInfo; + typedef enum NodeLightPath { NODE_LP_camera = 0, NODE_LP_shadow, diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h index 5d41abb53c4..3d9a8b403ac 100644 --- a/intern/cycles/kernel/types.h +++ b/intern/cycles/kernel/types.h @@ -1565,21 +1565,21 @@ enum KernelFeatureFlag : uint32_t { KERNEL_FEATURE_NODE_BSDF = (1U << 0U), KERNEL_FEATURE_NODE_EMISSION = (1U << 1U), KERNEL_FEATURE_NODE_VOLUME = (1U << 2U), - KERNEL_FEATURE_NODE_HAIR = (1U << 3U), - KERNEL_FEATURE_NODE_BUMP = (1U << 4U), - KERNEL_FEATURE_NODE_BUMP_STATE = (1U << 5U), - KERNEL_FEATURE_NODE_VORONOI_EXTRA = (1U << 6U), - KERNEL_FEATURE_NODE_RAYTRACE = (1U << 7U), - KERNEL_FEATURE_NODE_AOV = (1U << 8U), - KERNEL_FEATURE_NODE_LIGHT_PATH = (1U << 9U), + KERNEL_FEATURE_NODE_BUMP = (1U << 3U), + KERNEL_FEATURE_NODE_BUMP_STATE = (1U << 4U), + KERNEL_FEATURE_NODE_VORONOI_EXTRA = (1U << 5U), + KERNEL_FEATURE_NODE_RAYTRACE = (1U << 6U), + KERNEL_FEATURE_NODE_AOV = (1U << 7U), + KERNEL_FEATURE_NODE_LIGHT_PATH = (1U << 8U), /* Use denoising kernels and output denoising passes. */ - KERNEL_FEATURE_DENOISING = (1U << 10U), + KERNEL_FEATURE_DENOISING = (1U << 9U), /* Use path tracing kernels. */ - KERNEL_FEATURE_PATH_TRACING = (1U << 11U), + KERNEL_FEATURE_PATH_TRACING = (1U << 10U), /* BVH/sampling kernel features. */ + KERNEL_FEATURE_POINTCLOUD = (1U << 11U), KERNEL_FEATURE_HAIR = (1U << 12U), KERNEL_FEATURE_HAIR_THICK = (1U << 13U), KERNEL_FEATURE_OBJECT_MOTION = (1U << 14U), @@ -1616,9 +1616,6 @@ enum KernelFeatureFlag : uint32_t { KERNEL_FEATURE_AO_PASS = (1U << 25U), KERNEL_FEATURE_AO_ADDITIVE = (1U << 26U), KERNEL_FEATURE_AO = (KERNEL_FEATURE_AO_PASS | KERNEL_FEATURE_AO_ADDITIVE), - - /* Point clouds. */ - KERNEL_FEATURE_POINTCLOUD = (1U << 27U), }; /* Shader node feature mask, to specialize shader evaluation for kernels. */ @@ -1628,7 +1625,7 @@ enum KernelFeatureFlag : uint32_t { KERNEL_FEATURE_NODE_LIGHT_PATH) #define KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW \ (KERNEL_FEATURE_NODE_BSDF | KERNEL_FEATURE_NODE_EMISSION | KERNEL_FEATURE_NODE_VOLUME | \ - KERNEL_FEATURE_NODE_HAIR | KERNEL_FEATURE_NODE_BUMP | KERNEL_FEATURE_NODE_BUMP_STATE | \ + KERNEL_FEATURE_NODE_BUMP | KERNEL_FEATURE_NODE_BUMP_STATE | \ KERNEL_FEATURE_NODE_VORONOI_EXTRA | KERNEL_FEATURE_NODE_LIGHT_PATH) #define KERNEL_FEATURE_NODE_MASK_SURFACE \ (KERNEL_FEATURE_NODE_MASK_SURFACE_SHADOW | KERNEL_FEATURE_NODE_RAYTRACE | \ diff --git a/intern/cycles/scene/scene.cpp b/intern/cycles/scene/scene.cpp index 1963ebbbb19..b5b8eee24a7 100644 --- a/intern/cycles/scene/scene.cpp +++ b/intern/cycles/scene/scene.cpp @@ -570,7 +570,6 @@ static void log_kernel_features(const uint features) << "\n"; VLOG(2) << "Use Emission " << string_from_bool(features & KERNEL_FEATURE_NODE_EMISSION) << "\n"; VLOG(2) << "Use Volume " << string_from_bool(features & KERNEL_FEATURE_NODE_VOLUME) << "\n"; - VLOG(2) << "Use Hair " << string_from_bool(features & KERNEL_FEATURE_NODE_HAIR) << "\n"; VLOG(2) << "Use Bump " << string_from_bool(features & KERNEL_FEATURE_NODE_BUMP) << "\n"; VLOG(2) << "Use Voronoi " << string_from_bool(features & KERNEL_FEATURE_NODE_VORONOI_EXTRA) << "\n"; diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp index e8316ad41b4..40d2e0ba814 100644 --- a/intern/cycles/scene/shader_nodes.cpp +++ b/intern/cycles/scene/shader_nodes.cpp @@ -4466,6 +4466,59 @@ void HairInfoNode::compile(OSLCompiler &compiler) compiler.add(this, "node_hair_info"); } +/* Point Info */ + +NODE_DEFINE(PointInfoNode) +{ + NodeType *type = NodeType::add("point_info", create, NodeType::SHADER); + + SOCKET_OUT_POINT(position, "Position"); + SOCKET_OUT_FLOAT(radius, "Radius"); + SOCKET_OUT_FLOAT(random, "Random"); + + return type; +} + +PointInfoNode::PointInfoNode() : ShaderNode(get_node_type()) +{ +} + +void PointInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes) +{ + if (shader->has_surface_link()) { + if (!output("Random")->links.empty()) + attributes->add(ATTR_STD_POINT_RANDOM); + } + + ShaderNode::attributes(shader, attributes); +} + +void PointInfoNode::compile(SVMCompiler &compiler) +{ + ShaderOutput *out; + + out = output("Position"); + if (!out->links.empty()) { + compiler.add_node(NODE_POINT_INFO, NODE_INFO_POINT_POSITION, compiler.stack_assign(out)); + } + + out = output("Radius"); + if (!out->links.empty()) { + compiler.add_node(NODE_POINT_INFO, NODE_INFO_POINT_RADIUS, compiler.stack_assign(out)); + } + + out = output("Random"); + if (!out->links.empty()) { + int attr = compiler.attribute(ATTR_STD_POINT_RANDOM); + compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT); + } +} + +void PointInfoNode::compile(OSLCompiler &compiler) +{ + compiler.add(this, "node_point_info"); +} + /* Volume Info */ NODE_DEFINE(VolumeInfoNode) diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h index 0faefd3041f..a8d5bdcf157 100644 --- a/intern/cycles/scene/shader_nodes.h +++ b/intern/cycles/scene/shader_nodes.h @@ -1005,9 +1005,20 @@ class HairInfoNode : public ShaderNode { { return true; } - virtual int get_feature() +}; + +class PointInfoNode : public ShaderNode { + public: + SHADER_NODE_CLASS(PointInfoNode) + + void attributes(Shader *shader, AttributeRequestSet *attributes); + bool has_attribute_dependency() { - return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_HAIR; + return true; + } + bool has_spatial_varying() + { + return true; } }; diff --git a/release/scripts/modules/rna_manual_reference.py b/release/scripts/modules/rna_manual_reference.py index 2983a326358..0467e7b5788 100644 --- a/release/scripts/modules/rna_manual_reference.py +++ b/release/scripts/modules/rna_manual_reference.py @@ -1860,6 +1860,7 @@ url_manual_mapping = ( ("bpy.types.shadernodeemission*", "render/shader_nodes/shader/emission.html#bpy-types-shadernodeemission"), ("bpy.types.shadernodegeometry*", "render/shader_nodes/input/geometry.html#bpy-types-shadernodegeometry"), ("bpy.types.shadernodehairinfo*", "render/shader_nodes/input/hair_info.html#bpy-types-shadernodehairinfo"), + ("bpy.types.shadernodepointinfo*", "render/shader_nodes/input/point_info.html#bpy-types-shadernodepointinfo"), ("bpy.types.shadernodemaprange*", "render/shader_nodes/converter/map_range.html#bpy-types-shadernodemaprange"), ("bpy.types.shadernodergbcurve*", "modeling/geometry_nodes/color/rgb_curves.html#bpy-types-shadernodergbcurve"), ("bpy.types.shadernodeseparate*", "render/shader_nodes/converter/combine_separate.html#bpy-types-shadernodeseparate"), diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 92e5eb91da6..d7bf5d82c6a 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -390,6 +390,7 @@ shader_node_categories = [ NodeItem("ShaderNodeAmbientOcclusion"), NodeItem("ShaderNodeObjectInfo"), NodeItem("ShaderNodeHairInfo"), + NodeItem("ShaderNodePointInfo"), NodeItem("ShaderNodeVolumeInfo"), NodeItem("ShaderNodeParticleInfo"), NodeItem("ShaderNodeCameraData"), diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index cd6d58f563a..b2c91fafe97 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1178,6 +1178,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #define SH_NODE_OUTPUT_AOV 707 #define SH_NODE_VECTOR_ROTATE 708 #define SH_NODE_CURVE_FLOAT 709 +#define SH_NODE_POINT_INFO 710 /** \} */ diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 8baffff9ecf..074e38dea87 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -4668,6 +4668,7 @@ static void registerTextureNodes() register_node_type_sh_tangent(); register_node_type_sh_normal_map(); register_node_type_sh_hair_info(); + register_node_type_sh_point_info(); register_node_type_sh_volume_info(); register_node_type_tex_checker(); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 996716d6def..766e721b1b8 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -176,7 +176,7 @@ enum { VAR_MAT_MESH = (1 << 0), VAR_MAT_VOLUME = (1 << 1), VAR_MAT_HAIR = (1 << 2), - /* VAR_MAT_PROBE = (1 << 3), UNUSED */ + VAR_MAT_POINTCLOUD = (1 << 3), VAR_MAT_BLEND = (1 << 4), VAR_MAT_LOOKDEV = (1 << 5), VAR_MAT_HOLDOUT = (1 << 6), diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c index adede7676d5..e56097df6b7 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders.c +++ b/source/blender/draw/engines/eevee/eevee_shaders.c @@ -1357,6 +1357,9 @@ static char *eevee_get_defines(int options) if ((options & VAR_MAT_HAIR) != 0) { BLI_dynstr_append(ds, "#define HAIR_SHADER\n"); } + if ((options & VAR_MAT_POINTCLOUD) != 0) { + BLI_dynstr_append(ds, "#define POINTCLOUD_SHADER\n"); + } if ((options & VAR_WORLD_PROBE) != 0) { BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n"); } diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl index 0e342938396..cbfa9737a84 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl @@ -26,6 +26,9 @@ void main() worldNormal = cross(hairTangent, binor); vec3 world_pos = pos; +#elif defined(POINTCLOUD_SHADER) + pointcloud_get_pos_and_radius(pointPosition, pointRadius); + pointID = gl_VertexID; #else vec3 world_pos = point_object_to_world(pos); #endif diff --git a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl index 7d016d57c46..d7fc5e0b52a 100644 --- a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl @@ -42,3 +42,13 @@ IN_OUT ShaderHairInterface flat int hairStrandID; }; #endif + +#ifdef POINTCLOUD_SHADER +IN_OUT ShaderPointCloudInterface +{ + /* world space */ + float pointRadius; + float pointPosition; + flat int pointID; +}; +#endif diff --git a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl index 0ad1393dd70..51e9eda6cc2 100644 --- a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl @@ -31,6 +31,9 @@ void main() hairThickTime); worldNormal = cross(hairTangent, binor); vec3 world_pos = pos; +#elif defined(POINTCLOUD_SHADER) + pointcloud_get_pos_and_radius(pointPosition, pointRadius); + pointID = gl_VertexID; #else vec3 world_pos = point_object_to_world(pos); #endif diff --git a/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl b/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl index 2da16d3f6a9..dd725ad327f 100644 --- a/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl +++ b/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl @@ -22,13 +22,22 @@ mat3 pointcloud_get_facing_matrix(vec3 p) return facing_mat; } +/* Returns world center position and radius. */ +void pointcloud_get_pos_and_radius(out vec3 outpos, out float outradius) +{ + outpos = point_object_to_world(pos.xyz); + outradius = dot(abs(mat3(ModelMatrix) * pos.www), vec3(1.0 / 3.0)); +} + /* Return world position and normal. */ void pointcloud_get_pos_and_nor(out vec3 outpos, out vec3 outnor) { - vec3 p = point_object_to_world(pos.xyz); + vec3 p; + float radius; + pointcloud_get_pos_and_radius(p, radius); + mat3 facing_mat = pointcloud_get_facing_matrix(p); - float radius = dot(abs(mat3(ModelMatrix) * pos.www), vec3(1.0 / 3.0)); /* TODO(fclem): remove multiplication here. Here only for keeping the size correct for now. */ radius *= 0.01; outpos = p + (facing_mat * pos_inst) * radius; diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 3e811caa14b..5be4352cffd 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -323,6 +323,7 @@ set(GLSL_SRC shaders/material/gpu_shader_material_output_material.glsl shaders/material/gpu_shader_material_output_world.glsl shaders/material/gpu_shader_material_particle_info.glsl + shaders/material/gpu_shader_material_point_info.glsl shaders/material/gpu_shader_material_principled.glsl shaders/material/gpu_shader_material_refraction.glsl shaders/material/gpu_shader_material_rgb_curves.glsl diff --git a/source/blender/gpu/intern/gpu_material_library.c b/source/blender/gpu/intern/gpu_material_library.c index 74e0270c42a..712ab44adb3 100644 --- a/source/blender/gpu/intern/gpu_material_library.c +++ b/source/blender/gpu/intern/gpu_material_library.c @@ -91,6 +91,7 @@ extern char datatoc_gpu_shader_material_output_aov_glsl[]; extern char datatoc_gpu_shader_material_output_material_glsl[]; extern char datatoc_gpu_shader_material_output_world_glsl[]; extern char datatoc_gpu_shader_material_particle_info_glsl[]; +extern char datatoc_gpu_shader_material_point_info_glsl[]; extern char datatoc_gpu_shader_material_principled_glsl[]; extern char datatoc_gpu_shader_material_refraction_glsl[]; extern char datatoc_gpu_shader_material_rgb_curves_glsl[]; @@ -295,7 +296,7 @@ static GPUMaterialLibrary gpu_shader_material_glass_library = { static GPUMaterialLibrary gpu_shader_material_hair_info_library = { .code = datatoc_gpu_shader_material_hair_info_glsl, - .dependencies = {NULL}, + .dependencies = {&gpu_shader_material_hash_library, NULL}, }; static GPUMaterialLibrary gpu_shader_material_holdout_library = { @@ -388,6 +389,11 @@ static GPUMaterialLibrary gpu_shader_material_particle_info_library = { .dependencies = {NULL}, }; +static GPUMaterialLibrary gpu_shader_material_point_info_library = { + .code = datatoc_gpu_shader_material_point_info_glsl, + .dependencies = {&gpu_shader_material_hash_library, NULL}, +}; + static GPUMaterialLibrary gpu_shader_material_principled_library = { .code = datatoc_gpu_shader_material_principled_glsl, .dependencies = {NULL}, @@ -644,6 +650,7 @@ static GPUMaterialLibrary *gpu_material_libraries[] = { &gpu_shader_material_output_material_library, &gpu_shader_material_output_world_library, &gpu_shader_material_particle_info_library, + &gpu_shader_material_point_info_library, &gpu_shader_material_principled_library, &gpu_shader_material_refraction_library, &gpu_shader_material_rgb_curves_library, diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl index 6ffa6b59572..59f0377869b 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl @@ -1,15 +1,4 @@ -float wang_hash_noise(uint s) -{ - s = (s ^ 61u) ^ (s >> 16u); - s *= 9u; - s = s ^ (s >> 4u); - s *= 0x27d4eb2du; - s = s ^ (s >> 15u); - - return fract(float(s) / 4294967296.0); -} - void node_hair_info(float hair_length, out float is_strand, out float intercept, diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl index 86191451e5f..cb798047791 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl @@ -215,3 +215,14 @@ float integer_noise(int n) nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; return 0.5 * (float(nn) / 1073741824.0); } + +float wang_hash_noise(uint s) +{ + s = (s ^ 61u) ^ (s >> 16u); + s *= 9u; + s = s ^ (s >> 4u); + s *= 0x27d4eb2du; + s = s ^ (s >> 15u); + + return fract(float(s) / 4294967296.0); +} diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_point_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_point_info.glsl new file mode 100644 index 00000000000..d717ac97b28 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_point_info.glsl @@ -0,0 +1,13 @@ + +void node_point_info(out vec3 position, out float radius, out float random) +{ +#ifdef POINTCLOUD_SHADER + position = pointPosition; + radius = pointRadius; + random = wang_hash_noise(uint(pointID)); +#else + position = vec3(0.0, 0.0, 0.0); + radius = 0.0; + random = 0.0; +#endif +} diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 65720fc119b..57740ce3ad9 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -85,6 +85,7 @@ void register_node_type_sh_layer_weight(void); void register_node_type_sh_tex_coord(void); void register_node_type_sh_particle_info(void); void register_node_type_sh_hair_info(void); +void register_node_type_sh_point_info(void); void register_node_type_sh_volume_info(void); void register_node_type_sh_script(void); void register_node_type_sh_normal_map(void); @@ -146,7 +147,6 @@ void register_node_type_sh_custom_group(bNodeType *ntype); struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree); void ntreeShaderEndExecTree(struct bNodeTreeExec *exec); - /** * Find an output node of the shader tree. * diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 66a2d3720ca..df820bf6dcf 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -96,6 +96,7 @@ DefNode(ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIG DefNode(ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" ) DefNode(ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" ) DefNode(ShaderNode, SH_NODE_HAIR_INFO, 0, "HAIR_INFO", HairInfo, "Hair Info", "" ) +DefNode(ShaderNode, SH_NODE_POINT_INFO, 0, "POINT_INFO", PointInfo, "Point Info", "" ) DefNode(ShaderNode, SH_NODE_VOLUME_INFO, 0, "VOLUME_INFO", VolumeInfo, "Volume Info", "" ) DefNode(ShaderNode, SH_NODE_WIREFRAME, def_sh_tex_wireframe, "WIREFRAME", Wireframe, "Wireframe", "" ) DefNode(ShaderNode, SH_NODE_WAVELENGTH, 0, "WAVELENGTH", Wavelength, "Wavelength", "" ) diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt index 4cf18429e0d..c8eb0b8d570 100644 --- a/source/blender/nodes/shader/CMakeLists.txt +++ b/source/blender/nodes/shader/CMakeLists.txt @@ -93,6 +93,7 @@ set(SRC nodes/node_shader_output_material.cc nodes/node_shader_output_world.cc nodes/node_shader_particle_info.cc + nodes/node_shader_point_info.cc nodes/node_shader_rgb.cc nodes/node_shader_rgb_to_bw.cc nodes/node_shader_script.cc diff --git a/source/blender/nodes/shader/nodes/node_shader_point_info.cc b/source/blender/nodes/shader/nodes/node_shader_point_info.cc new file mode 100644 index 00000000000..adc58ca065a --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_point_info.cc @@ -0,0 +1,54 @@ +/* + * 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_point_info_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_output(N_("Position")); + b.add_output(N_("Radius")); + b.add_output(N_("Random")); +} + +static int node_shader_gpu_point_info(GPUMaterial *mat, + bNode *node, + bNodeExecData *UNUSED(execdata), + GPUNodeStack *in, + GPUNodeStack *out) +{ + return GPU_stack_link(mat, node, "node_point_info", in, out); +} + +} // namespace blender::nodes::node_shader_point_info_cc + +/* node type definition */ +void register_node_type_sh_point_info() +{ + namespace file_ns = blender::nodes::node_shader_point_info_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_POINT_INFO, "Point Info", NODE_CLASS_INPUT); + ntype.declare = file_ns::node_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_point_info); + + nodeRegisterType(&ntype); +}