Files
test2/intern/opensubdiv/internal/evaluator/gpu_patch_table.hh
Clément Foucault ba4589e894 DRW: New Curve Drawing
Implementation of the design task #142969.

This adds the following:
- Exact GPU interpolation of curves of all types.
- Radius attribute support.
- Cyclic curve support.
- Resolution attribute support.
- New Cylinder hair shape type.
![image.png](/attachments/a8e7aea0-b0e5-4694-b660-89fb3df1ddcd)

What changed:
- EEVEE doesn't compute random normals for strand hairs anymore. These are considered legacy now.
- EEVEE now have an internal shadow bias to avoid self shadowing on hair.
- Workbench Curves Strip display option is no longer flat and has better shading.
- Legacy Hair particle system evaluates radius at control points before applying additional subdivision. This now matches Cycles.
- Color Attribute Node without a name do not fetch the active color attribute anymore. This now matches Cycles.

Notes:
- This is not 100% matching the CPU implementation for interpolation (see the epsilons in the tests).
- Legacy Hair Particle points is now stored in local space after interpolation.

The new cylinder shape allows for more correct hair shading in workbench and better intersection in EEVEE.

|      | Strand | Strip | Cylinder |
| ---- | --- | --- | --- |
| Main | ![main_strand.png](/attachments/67d3b792-962c-4272-a92c-1c0c7c6cf8de) | ![main_strip.png](/attachments/f2aa3575-368e-4fbb-b888-74df845918f1) | N/A |
| PR   | ![pr_strand.png](/attachments/cc012483-25f0-491f-a06e-ad3029981d47) | ![pr_strip.png](/attachments/73fa2f5c-5252-4b30-a334-e935ed0fb938) | ![pr_cylinder.png](/attachments/3133b2d4-a6f2-41ee-8e2d-f6fd00db0c8d) |

|      | Strand | Strip | Cylinder |
| ---- | --- | --- | --- |
| Main | ![main_strand_closeup.png](/attachments/730bd79c-6762-446d-819b-3ea47961ff9f) |![main_strip_closeup.png](/attachments/d9ace578-cfeb-4895-9896-3625b6ad7a02) | N/A |
| PR   | ![pr_strand_closeup.png](/attachments/ac8f3b0c-6ef6-4d54-b714-6322f9865036)|![pr_strip_closeup.png](/attachments/8504711a-955b-4ab2-aa3d-c2d114baf9d4)| ![pr_cylinder_closeup.png](/attachments/1e2899a8-0a5c-431f-ac6c-5184d87e9598) |

Cyclic Curve, Mixed curve type, and proper radius support:
![image.png](/attachments/7f0bf05e-62ee-4ae9-aef9-a5599249b8d7)

Test file for attribute lookup: [test_attribute_lookup.blend](/attachments/1d54dd06-379b-4480-a1c5-96adc1953f77)

Follow Up Tasks:
- Correct full tube segments orientation based on tangent and normal attributes
- Correct V resolution property per object
- More attribute type support (currently only color)

TODO:
- [x] Attribute Loading Changes
  - [x] Generic Attributes
  - [x] Length Attribute
  - [x] Intercept Attribute
  - [x] Original Coordinate Attribute
- [x] Cyclic Curves
- [x] Legacy Hair Particle conversion
  - [x] Attribute Loading
  - [x] Additional Subdivision
- [x] Move some function to generic headers (VertBuf, OffsetIndices)
- [x] Fix default UV/Color attribute assignment

Pull Request: https://projects.blender.org/blender/blender/pulls/143180
2025-08-27 09:49:43 +02:00

101 lines
2.6 KiB
C++

/* SPDX-FileCopyrightText: 2025 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "GPU_storage_buffer.hh"
#include <opensubdiv/version.h>
#include <opensubdiv/osd/nonCopyable.h>
#include <opensubdiv/osd/types.h>
using OpenSubdiv::Far::PatchTable;
using OpenSubdiv::Osd::NonCopyable;
using OpenSubdiv::Osd::PatchArrayVector;
namespace blender::opensubdiv {
// TODO: use Blenlib NonCopyable.
class GPUPatchTable : private OpenSubdiv::Osd::NonCopyable<GPUPatchTable> {
public:
~GPUPatchTable();
static GPUPatchTable *Create(PatchTable const *farPatchTable, void *deviceContext = NULL);
/// Returns the patch arrays for vertex index buffer data
PatchArrayVector const &GetPatchArrays() const
{
return _patchArrays;
}
/// Returns the GL index buffer containing the patch control vertices
gpu::StorageBuf *GetPatchIndexBuffer() const
{
return _patchIndexBuffer;
}
/// Returns the GL index buffer containing the patch parameter
gpu::StorageBuf *GetPatchParamBuffer() const
{
return _patchParamBuffer;
}
/// Returns the patch arrays for varying index buffer data
PatchArrayVector const &GetVaryingPatchArrays() const
{
return _varyingPatchArrays;
}
/// Returns the GL index buffer containing the varying control vertices
gpu::StorageBuf *GetVaryingPatchIndexBuffer() const
{
return _varyingIndexBuffer;
}
/// Returns the number of face-varying channel buffers
int GetNumFVarChannels() const
{
return (int)_fvarPatchArrays.size();
}
/// Returns the patch arrays for face-varying index buffer data
PatchArrayVector const &GetFVarPatchArrays(int fvarChannel = 0) const
{
return _fvarPatchArrays[fvarChannel];
}
/// Returns the GL index buffer containing face-varying control vertices
gpu::StorageBuf *GetFVarPatchIndexBuffer(int fvarChannel = 0) const
{
return _fvarIndexBuffers[fvarChannel];
}
/// Returns the GL index buffer containing face-varying patch params
gpu::StorageBuf *GetFVarPatchParamBuffer(int fvarChannel = 0) const
{
return _fvarParamBuffers[fvarChannel];
}
protected:
GPUPatchTable() {}
// allocate buffers from patchTable
bool allocate(PatchTable const *farPatchTable);
PatchArrayVector _patchArrays;
gpu::StorageBuf *_patchIndexBuffer = nullptr;
gpu::StorageBuf *_patchParamBuffer = nullptr;
PatchArrayVector _varyingPatchArrays;
gpu::StorageBuf *_varyingIndexBuffer = nullptr;
std::vector<PatchArrayVector> _fvarPatchArrays;
std::vector<gpu::StorageBuf *> _fvarIndexBuffers;
std::vector<gpu::StorageBuf *> _fvarParamBuffers;
};
} // namespace blender::opensubdiv