Goal is to add the length attribute to the Hair Info node, for better control over color gradients or similar along the hair.
Eevee Render
Cycles Render (CPU)
Cycles Render (GPU)
Test-File:
Differential D10481
Hair Info Length Attribute Authored by Lasse Foster (LasseF) on Feb 20 2021, 5:15 PM.
Details Goal is to add the length attribute to the Hair Info node, for better control over color gradients or similar along the hair. Eevee Render Cycles Render (CPU) Cycles Render (GPU) Test-File:
Diff Detail
Event TimelineThere are a very large number of changes, so older changes are hidden. Show Older Changes Comment Actions It is my understanding that Cycles handles the data as vertex attributes, which is created during the generation of the hair particle meshes for rendering. I also think exposing this data to geometry nodes shouldn't be a problem, since adding the attribute to the object would automatically populate it during the next mesh generation. But dont quote me on this as i never looked at geometry nodes. I think handling as a vertex attribute is what @Clément Foucault (fclem) has in mind for this for eevee too, hence the gpu_attribute() but i cant quite figure out how the eevee attribute system is working and where to put my checks and how. The system doesnt allow me to use attributes the same simple way cycles does, but instead ties in very tightly with the shader codegen, which makes this more or less impossible for me to understand, as there are to many aspects of the eevee rendering code that i would need to understand first. And since i never really touched rendering code on this level before (my first time working with blender source, and my first time C as well, since i only really worked with C++) i'm not sure what exactly im doin here :D
Comment Actions
Comment Actions I am currently experiencing this bug caused by the codegen. Fixing this should in case my buffer allocation of C side of things is correct fix this issue for now. Comment Actions
Comment Actions
Comment Actions
Comment Actions Current patch doesn't compile for me. /home/jeroen/blender-git/blender/source/blender/draw/intern/draw_cache_impl_hair.c: In function ‘hair_batch_cache_ensure_procedural_pos’:
/home/jeroen/blender-git/blender/source/blender/draw/intern/draw_cache_impl_hair.c:198:3: error: too many arguments to function ‘GPU_vertbuf_data_alloc’
198 | GPU_vertbuf_data_alloc(cache->proc_length_buf, pos_id, &point_step);
| ^~~~~~~~~~~~~~~~~~~~~~
In file included from /home/jeroen/blender-git/blender/source/blender/gpu/GPU_batch.h:33,
from /home/jeroen/blender-git/blender/source/blender/draw/intern/draw_cache_impl_hair.c:39:
/home/jeroen/blender-git/blender/source/blender/gpu/GPU_vertex_buffer.h:96:6: note: declared here
96 | void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len);Comment Actions
Comment Actions It seems like the buffer containing the hairLengths isn't attached to the program. On my system it fallsback and reads the first element of the hairPointBuffer. The var0 column should be the hairLen. Next image shows the content of the hairPointBuffer. Do you know the application renderdoc? it can help finding these issues. When using you can start blender inside renderdoc with the --debug-gpu option There seems also be a memory leak: GLVertBuf len: 504 0x7fe17c2944b8 GPUNodeLink len: 24 0x7fe179bfdd78 GPUNodeLink len: 24 0x7fe17a0eaa18 Think the issue might be that the texture isn't created.
Comment Actions
Comment Actions Detected a memory leak Error: Not freed memory blocks: 2, total unfreed memory 0.000046 MB GPUNodeLink len: 24 0x7f9116615e38 GPUNodeLink len: 24 0x7f910d1b8f58
Comment Actions
CPU side data will always be allocated together with the proc_point_buf to simplify things and the texture only created and uploaded once needed. @Clément Foucault (fclem) Does this fit what you had in mind? Comment Actions This is exactly what I had in mind. If there is no more memory leak, I think we are good to go. Note that I did not test the patch personally yet.
Comment Actions @Clément Foucault (fclem) The memory leak @Jeroen Bakker (jbakker) found is still not dealt with and i also dont know what is causing it as i am, to my knowledge, not doing anything differently than elsewhere concerning the handling of gpu attributes. Do you have thoughts on this? Comment Actions
Comment Actions Memory leak: In node_shader_gpu_hair_info the length_link is created and passed to the GPU_stack_link. The GPU_stack_link cannot find any input parameter and doesn't link it to the graph. So the object isn't used in the final GPU shader. A solution is to add an input parameter to node_hair_info this input will contain a link to the length_link. void node_hair_info(
float hair_length
out float is_strand,
out float intercept,
out float length,
out float thickness,
out vec3 tangent,
out float random)Internally the hair_length parameter is directed to the length out parameter. return GPU_stack_link(
mat, node, "node_hair_info", in, out, length_link);This might need some additional tweaks so the generate the correct link in the fragment shader. (Currently hardcoded to hairLength) Comment Actions --- a/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl @@ -10,7 +10,8 @@ float wang_hash_noise(uint s) return fract(float(s) / 4294967296.0); } -void node_hair_info(out float is_strand, +void node_hair_info(float hair_length, + out float is_strand, out float intercept, out float length, out float thickness, @@ -20,7 +21,7 @@ void node_hair_info(out float is_strand, #ifdef HAIR_SHADER is_strand = 1.0; intercept = hairTime; - length = hairLength; + length = hair_length; thickness = hairThickness; tangent = normalize(worldNormal); random = wang_hash_noise( diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.c b/source/blender/nodes/shader/nodes/node_shader_hair_info.c index 79ec174a553..776e3e0d2f9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_hair_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.c @@ -39,7 +39,7 @@ static int node_shader_gpu_hair_info(GPUMaterial *mat, /* Length: don't request length if not needed. */ GPUNodeLink *length_link = (!out[2].hasoutput) ? GPU_constant(0) : GPU_attribute(mat, CD_HAIRLENGTH, ""); - return GPU_stack_link(mat, node, "node_hair_info", in, out, NULL, NULL, &length_link, NULL, NULL, NULL); + return GPU_stack_link(mat, node, "node_hair_info", in, out, length_link); } /* node type definition */ Seems to remove the memory leak. I haven't checked if the generated code is optimal. Comment Actions
Comment Actions
Comment Actions Just a minor code style. @Brecht Van Lommel (brecht) can you approve the cycles part.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||