1
1

Compare commits

...

199 Commits

Author SHA1 Message Date
a2cb7ffa66 LANPR: Apply cleanup branch result. 2019-09-12 17:09:50 +08:00
af0378aa4a Cleanup: Make format. 2019-09-12 15:06:03 +08:00
d1b7ab3333 LANPR: target multiple material functionality. 2019-09-12 14:43:17 +08:00
a2caf8297a LANPR: Fix merge errors. 2019-09-12 12:58:28 +08:00
8757454fbc Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-09-12 12:48:08 +08:00
ea253238ac LANPR: Multiple target materials and layers for collection. 2019-09-12 12:31:21 +08:00
11416446ba LANPR: Different materials and layers for object targets. 2019-09-12 11:47:31 +08:00
aebaf3c88c LANPR: Use selector instead of numbers for targets 2019-09-12 10:29:01 +08:00
9e6351076c LANPR: fix merge errors. 2019-09-12 09:33:48 +08:00
f8e255759f Buildbot: enable tests to run again
These will not stop the build on failure yet, first step is to get them passing
more reliably.
2019-09-12 09:15:36 +08:00
e5c30df7d5 Depsgraph: Free user code from worry about updates flush 2019-09-12 09:14:21 +08:00
e064aa2560 Depsgraph: Pass bmain to evaluation function
Currently unused, makes code ready for an upcoming change.
2019-09-12 09:14:21 +08:00
6b1771645e Python: don't include distutils Windows installer executables for Linux/macOS
They were detected as (false positive) malware with ClamAV. It's unlikely
someone would need these files, and e.g. the Debian Python package also
excludes them with a custom patch.
2019-09-12 09:13:42 +08:00
b64fca4cd0 Fix assert hiding selected particles
was trying to get a boolean with RNA_enum_get (instead of
RNA_boolean_get)

Spotted while looking into T69680, T69432
2019-09-12 09:13:42 +08:00
911450be0e Fix (unreported) crash after new mapping node commit.
Blatant obvious usage of freed memory in rBbaaa89a0bc54.

And also fix a memleak in same code/commit...
2019-09-12 09:13:42 +08:00
c42a6b77b5 Cleanup: trailing space, remove tabs, pep8 2019-09-12 09:13:42 +08:00
9bfccd1854 Fix T69686: Cycles OpenCL build error after recent changes 2019-09-12 09:13:42 +08:00
36f81b54de Fix T67637: Selected edges hard to see with wireframe
Always show selected edges in wire/xray modes.
2019-09-12 09:13:42 +08:00
OmarSquircleArt
6c6211a99d Shading: Extend Musgrave node to other dimensions.
This patch extends Musgrave noise to operate in 1D, 2D, 3D, and 4D
space. The Color output was also removed because it was identical
to the Fac output.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5566
2019-09-12 09:13:42 +08:00
bc97c0d8b9 Fix T69633: weird behavior of operator_menu_enum tooltips.
For operators with dynamic tooltips the tooltip calculation is
deferred until the moment it is actually shown for performance
reasons, with the tooltip field left blank for the time being.
Enum menu code shouldn't jump in and assign a tooltip either.

The menu button itself can't show a dynamic tooltip because it
does not actually call the operator, and has no reference to it.

As a side change, allow returning None from the python callback
as the most natural way to fall back to the default tooltip.
2019-09-12 09:13:42 +08:00
e5513dfe04 Added function to calculate the total area of a mesh. 2019-09-12 09:13:42 +08:00
1c6dd9fe99 DNA: use defaults for Object, Mesh, Material 2019-09-12 09:13:42 +08:00
2e101de47f DNA: add theme & preferences to defaults
Use existing theme & preferences for defaults.
2019-09-12 09:13:42 +08:00
7d0a55fb7c Cleanup: fix compiler warnings 2019-09-12 09:13:42 +08:00
196effe82c Fix crashing mask brush after recent changes 2019-09-12 09:13:42 +08:00
a586114402 Fix build error after DNA defaults changing
dna_type_offsets.h must be generated before we use it in blenkernel,
similar to what we already do for blenloader.
2019-09-12 09:13:42 +08:00
d918becba1 Sculpt: Pose Brush
This brush lets the user pose a model simulating an armature-like deformation. The pivot point for rotation is calculated automatically based on the radius of the brush and the topology of the model.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5647
2019-09-12 09:13:42 +08:00
ae078c265b Fix (unreported) non-official X3D add-on enabled in factory startup.
Forgot to remove it from there when I moved it to community-supported
status last week.

Also raising subversion.
2019-09-12 09:13:42 +08:00
4421598fca I18n: dirty workaround for PITA ghost classes remaining after unregister.
Spent again a whole day trying to understand what happens here, with no
luck. For some reasons, OperatorProperties children of unregistered
operator classes remain accessible, with their `bl_rna` member, although
that one is 100% invalid (freed memory, crashes with ASAN builds).

Funny thing is, I cannot reproduce that situation when disabling the
add-on from the py console of a Blender-with-UI.

Note: issue revealed by X3D add-on, which is still enabled in factory
settings, while not being officially supported any more, this has to be
fixed in a separate commit.
2019-09-12 09:13:42 +08:00
71d482bdee UI: Format Memory Strings in Binary
Show all memory-related byte size strings calculated with a base of 1024.

Differential Revision: https://developer.blender.org/D5714

Reviewed by Brecht Van Lommel
2019-09-12 09:13:42 +08:00
5334b0439c UI: File Browser Sizes in Binary for Windows
This adds per-platform change so Windows users will see file sizes calculated with a base of 1024.

Differential Revision: https://developer.blender.org/D5714

Reviewed by Brecht Van Lommel
2019-09-12 09:13:42 +08:00
49e9d7d8f3 Sculpt: Topology automasking
The sculpt automasking feature assigns a factor to each vertex before starting the stroke. This can be used for isolating disconnected meshes, masking cavities, mesh boundary edges or creating topological falloffs.

This commit implements automasking in all brushes and topology automasking without topology falloff.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5645
2019-09-12 09:13:42 +08:00
bb3dac4634 Cleanup: unused functions 2019-09-12 09:13:42 +08:00
Julian Eisel
6ff42dbffa UI: Add superimposed + and - icons for file number
Brings back + and - icons to the file name button, but now as
superimposed icons.
2019-09-12 09:13:42 +08:00
Julian Eisel
f8233e05f5 UI: Refactor and improve buttton extra icons
Without this patch there could only be one superimposed icon
and the operators were hard coded for the button types.
This keeps the previous, sort of predefined extra icons working in a
rather generic way, but allows adding specific ones for specific case
through `UI_but_extra_operator_icon_set()`.

Reviewed by: Campbell Barton

Differential Revision: https://developer.blender.org/D5730
2019-09-12 09:13:42 +08:00
c1c27a2c39 Partial revert "Edit Mesh: Change color behavior"
Using a lighter color for faces than edges makes edges hard to see
in wire-frame display mode. See T67637.

This partially reverts commit 203f9a49e2.
2019-09-12 09:13:41 +08:00
10f70ea73a Fix T69382: Crash - Regression - GPU Intel HD 4000
Workarounds were not being enabled for drivers like `10.18.10.5069`.
2019-09-12 09:13:41 +08:00
e24cb83e31 Sculpt: Mask Filter and Dirty Mask generator
The mask filter operator modifies the whole paint mask. In includes multiple operations like smooth, grow or contrast accessible from a pie menu.
The dirty mask generator is similar to Dirty Vertex Colors, but it generates a paint mask. It can be used to mask cavities in the sculpt.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5496
2019-09-12 09:13:41 +08:00
2700d8dafd Cleanup: GPencil small improvements in comparison
As the function `gpencil_onion_active()` has a loop, if some condition is false before we can avoid the loop.
2019-09-12 09:13:41 +08:00
86d6d3595a GPencil: Fix unreported problem when main Onion switch is disabled
The main switch was not checked and the function was doing all calculations, but the data was not used. This makes all slower than expected because the user had the Onion Skinning disabled, but internally was running.
2019-09-12 09:13:41 +08:00
d1cfd94423 Cleanup: expand tabs 2019-09-12 09:13:41 +08:00
62a9e414dc Cleanup: missing break & shadowing warnings 2019-09-12 09:13:41 +08:00
20d86c8c6c Sculpt: Mesh Filter Tool
The mesh filter tool applies a deformation to all vertices in the mesh at the same time. It includes multiple deformation modes and the option to lock the deformation axis.
This commit also includes the FilterCache, which is needed in some new operators and tools.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5513
2019-09-12 09:13:41 +08:00
d183e2ffc9 Fix compiler error in Windows introduced in 322c03f13c 2019-09-12 09:13:41 +08:00
d0b0bc2a0b GPencil: Fade layer using background color
Now the fade layer uses the same logic used to fade objects and also is available in all modes.

Reviewers: mendio, pepeland

Reviewed By: mendio, pepeland

Differential Revision: https://developer.blender.org/D5707
2019-09-12 09:13:41 +08:00
3f2ae8f4bd Sculpt: Elastic Deform Brush
This patch implements the paper "Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity" https://graphics.pixar.com/library/Kelvinlets/paper.pdf

It includes grab, biscale grab, triscale grab, scale and twist.
All deformation modes are accessible under the same tool. This helps to keep the code organized and it should not make any difference to the user when a better brush management system is implemented.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5634
2019-09-12 09:13:41 +08:00
2d39de7922 Cleanup: clang-format 2019-09-12 09:13:41 +08:00
2da63c0405 Fix T69663: 2.81 Cant open/append/link a blend file but 2.8 can
Was a problem in the versioning code from rBbaaa89a0bc54, since the
TexMapping struct could already be freed and node->storage could already
be set to NULL (if a file with the new mapping node [saved from (2, 81,
8) or newer] is opened in a blender version prior to (2, 81, 8) and
saved from there again).

Reviewers: brecht

Maniphest Tasks: T69663

Differential Revision: https://developer.blender.org/D5723
2019-09-12 09:13:41 +08:00
7af75482c6 DNA: initial DNA defaults support
This provides an API to access structs
with their members set to default values:

- DNA_struct_default_get(name)
- DNA_struct_default_alloc(name)

Currently this is only used for scene & view shading initialization,
eventually it can be used for RNA defaults and initializing
DNA struct members on file reading.
2019-09-12 09:13:41 +08:00
9987170ab3 GPencil: Change Arrange Strokes menu order
Before: Bring Forward, Send Backward, Bring to Front, Send to Back.

After: Bring to Front, Bring Forward, Send Backward,  Send to Back.
2019-09-12 09:13:04 +08:00
59c608a665 Sculpt: Draw Sharp Brush
This brush is similar to the draw brush but it deforms the mesh from the original coordinates. When used with the sharper curve presets it has a much more pleasant crease/cut behavior than any of the other brushes. This is useful for creating cloth wrinkles, stylized hair or hard surface edges.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5530
2019-09-12 09:13:04 +08:00
0e448678ee Cleanup: remove unused scene struct members 2019-09-12 09:13:04 +08:00
e708e4cfeb Move callbacks API from BLI to BKE
Preparing for the bigger changes which will be related on passing
dependency graph to various callbacks which need it.

Differential Revision: https://developer.blender.org/D5725
2019-09-12 09:13:04 +08:00
9207169175 Timer: Use explicit re-initialization on file load
Before this the timer API was relying on using a callback API to do
initialization when new file is loaded. This isn't how rest of Blender
works and it gets in a way because callbacks API is to be move to the
BKE level.

Use explicit call to timer API from where the file is loaded.
2019-09-12 09:13:03 +08:00
fb4ae7c229 Cleanup: sort struct, file lists 2019-09-12 09:13:03 +08:00
86d18527e2 Fix (unreported) Freestyle modifiers element-wise multiplication error 2019-09-12 09:13:03 +08:00
3a0789b3fb Fix T69653: Freestyle modifiers "Distance from ..." python error
Was a wrong rename in rBaeb8e81f2741
2019-09-12 09:13:03 +08:00
542885a2c4 Batch Rename: Rename Title Caps to Title Case 2019-09-12 09:13:03 +08:00
Julian Eisel
2c7adb2c4d UI: Allow context menu in all file browser regions 2019-09-12 09:13:03 +08:00
Julian Eisel
8573045404 UI: Allow file number shortcuts ouside main region
Makes the numpad + and - type of shortcuts to increase/decrease the file
number suffix work in the upper and lower bar of the file browser.

Had to add keymap handlers to the execute region for this to work.
2019-09-12 09:13:03 +08:00
b9252e63fa Fix T69640: make update not working with Python older than 3.7 2019-09-12 09:13:03 +08:00
d5a484a1fe Edit Mesh: select interior faces now detects regions
The previous method only worked in simple cases where faces were
surrounded by non-manifold edges.

Now face regions surrounded by non-manifold edges are marked as interior.
Starting with regions most perpendicular to the surrounding geometry.

Resolves T68401
2019-09-12 09:13:03 +08:00
Julian Eisel
775ff3b20d Fix T67756: File drag starts on file browser open
When the file browser was opened (from a temporary window since the file
browser redesign) using a button in the UI, under certain conditions
moving the mouse would trigger files to be dragged.

Note that this has been an issue before the new file browser design was
introduced, although under slightly different conditions.

Steps to reproduce:
* With factory settings, press F12
* Open a different image in the appearing Image Editor (not Render
  Result)
* Make sure the window is not maximized
* Press N to open the side bar, open Image tab
* Click the folder icon there to change the image
* Change to thumbnail display type in the appearing file browser
* Cancel, click the folder icon again
Moving the mouse now would start dragging files in most cases.

The same issue could be reproduced in a similar way when installing
lights/MatCaps or HDRIs through Preferences -> Lights -> Install...
2019-09-12 09:13:03 +08:00
4442e060ba Fix T69634: GPencil:Cutter Tool removes unexpected strokes on another layer
The function was not checking the locked flag.
2019-09-12 09:13:03 +08:00
b12aaf1262 Cycles: add bump map shadow terminator softening term for diffuse BSDFs
This avoids artifacts for bump mapping and diffuse BSDFs, where the bump
normal deviates far from the actual normal.

Differential Revision: https://developer.blender.org/D5399
2019-09-12 09:13:03 +08:00
cf6f3d120e Fix script_load_modules test failure in power sequencer 2019-09-12 09:13:03 +08:00
aa7dfd73bd Build: skip Blender repository pull in "make update" when not possible
This prints a more informative message, and is convenient when working with
local changes or in a branch where you only need to update submodules or tests.
2019-09-12 09:13:03 +08:00
Julian Eisel
c1cc9f94ed Fix crash closing stacked file browser window
Caused by ab823176d3.
Steps to reproduce were:
* Open Preferences
* Open file browser through Lights -> Install (doesn't matter which)
* Close browser through the window controlls

The window was freed earlier, but still referenced by new handler
context storage.
2019-09-12 09:13:03 +08:00
afcbcc0e29 Update RNA Manual References 2019-09-12 09:13:03 +08:00
2113c01da2 Fix GTests failing on Windows buildbot
Run these tests from the install directory so they can find dlls.
2019-09-12 09:13:03 +08:00
daa295fc5f Partially revert "Cleanup: use post increment/decrement"
This partially reverts commit 0b2d1badec

Post increment can deep-copy for C++ iterators, while in my own checks
GCC was able to optimize this to get the same output,
better follow C++ best practice and use pre-increment for iterators.
2019-09-12 09:13:03 +08:00
eeb91051f6 Fix buildbot not reporting error when tests fail 2019-09-12 09:13:03 +08:00
ba1527f827 Tests: run tests from install path
Blender can only be run correctly from the install path since it requires Python
scripts, dynamic libraries and other files to be present. By default the install
path is the same as the build path, so it works anyway. But on the buildbot it
isn't. There was a workaround but it failed on Windows and macOS.

Now tests run from the install path. Detecting that path for ctest is more
complicated than I would like, but I couldn't find a better solution.

Ref T69541.
2019-09-12 09:13:03 +08:00
edc7c3bc33 Fix buildbot error building release on macOS 2019-09-12 09:13:03 +08:00
d1353c8a52 Fix missing LLVM include directories on macOS
These are not used in master yet, but they are needed for the functions branch.
2019-09-12 09:13:03 +08:00
b4f92d9707 Fix redo panel button alignment
Menu's in the redo panel left a space for decorators.
2019-09-12 09:13:03 +08:00
59794a82cc Fix two bugs in delaunay blenlib function.
Bugs were: (1) needed an epsilon test in CCW test in order to
handle new costraint edge that intersects an existing point
but only within epsilon; (2) the "valid bmesh" output mode
sometimes left a face that included outside frame point.
2019-09-12 09:13:03 +08:00
74c447d9d7 Cleanup: use post increment/decrement
When the result isn't used, prefer post increment/decrement
(already used nearly everywhere in Blender).
2019-09-12 09:13:03 +08:00
Julian Eisel
95d9ec6a37 Fix saving images from temp Image Editor failing
Steps to reproduce were:
* Ensure //Render//->//Display Mode// is //New Window//
* F12
* In the opened Image Editor, Alt+S to save the image
* Save the image
The saving would fail silently.

Issue was that wm_handler_op_context() would fail to find the correct
area to activate, as the wrong window was active in context. So allow
overriding this window and do so when creating the file-select handler.
2019-09-12 09:13:02 +08:00
f5d493dd48 Cleanup: includes in headers
Forward declare structs where possible.
2019-09-12 09:13:02 +08:00
4afacf55f6 Cleanup: style, spelling 2019-09-12 09:13:02 +08:00
a15de692a7 EEVEE: Shadows: Fix correlation issue between Shadows and Anti-Aliasing
To fix this, we just scramble the halton sequence by multiplying by a large
prime number.

It seems to work fine in practice.

We also tried Sobol sequence but it has a less uniform pattern for low
number of sample.

Fix T68594 Eevee: Soft shadows causing flickering in animation and temporal AA in scenes
2019-09-12 09:13:02 +08:00
b27eb93ea7 EEVEE: Fix tests crashing if file is in edit mode 2019-09-12 09:13:02 +08:00
a49481a93a EEVEE: Shadows: Fix incorrect shadowing near point lights source 2019-09-12 09:13:02 +08:00
Jean First
db9428c9ae Fix T68843: wireframe node in Eevee fails on macOS
Differential Revision: https://developer.blender.org/D5712
2019-09-12 09:13:02 +08:00
33e1fe12f5 Fix node_shader_utils problems with new mapping node
Since rBbaaa89a0bc54 we have to access the mapping node differently.
This doesnt take actual linkage of the new sockets into account (but
this wasnt done for most sockets on the Principled BSDF node either)

Also the min/max of the mapping node was removed entirely.
It was decided upon removing this from node_shader_utils as well (and
replace this by existing access to the Extension parameter of the
Texture node).

Part of solving T69526.

Differential Revision: https://developer.blender.org/D5693
2019-09-12 09:13:02 +08:00
7abf095e6c Fix T69597: Changing Grease Pencil Layer in Dopesheet unlocks all layers
The Dopesheet was unlocked all layers because it was using the same logic used in UI panel, but this was wrong.
2019-09-12 09:13:02 +08:00
de525a249d Python API: implement an Operator callback for dynamic description.
Blender UI Layout API allows supplying parameters to operators via
button definitions. If an operator behavior strongly depends on its
parameters, it may be difficult to write a tooltip that covers all
of its operation modes. Thus it is useful to provide a way for the
operator to produce different descriptions based on the input info.

Reviewers: campbellbarton

Differential Revision: https://developer.blender.org/D5709
2019-09-12 09:13:02 +08:00
a9816ec802 Fix T68796: stereo side-by-side and pageflip not drawing correctly 2019-09-12 09:13:02 +08:00
2b36ebb457 EEVEE: Fix Ambient Occlusion on backfaces
N is already the Facing normal! Dummy!
2019-09-12 09:13:02 +08:00
f02e64556f UI: File Browser Preview Outlines
File Browser image thumbnails get just a contrasting outline and no shadow.

Differential Revision: https://developer.blender.org/D5708

Reviewed by Brecht Van Lommel
2019-09-12 09:13:02 +08:00
57ac8fed67 EEVEE: Fix bump mapping
Fix issue in latest patch and assure derivatives calculation is correct on
all GPU.
2019-09-12 09:13:02 +08:00
0f21360520 Eevee: Improve Test setup
- Remove use_screen_refraction as it conflict with SSR and SSS
- Increase GTAO distance
- Add a simple lightprobe setup that works well in most cases
- Enable soft shadows

Baking the lightprobes adds some overhead to the test time (+33%).

Reviewers: brecht

Differential Revision: https://developer.blender.org/D5507
2019-09-12 09:13:02 +08:00
3a8184dc8f GPencil: New option to fade not selected objects
Before, it was only possible to fade the active object. The new option allows to fade all non gpencil selected object. This is a common request by artists.

{F7719513}

Reviewers: mendio, pepeland

Reviewed By: mendio

Differential Revision: https://developer.blender.org/D5704
2019-09-12 09:13:02 +08:00
2c73c78820 Fix T69548: Sculpt scene spacing breaks when object pivot not at origin
Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5699
2019-09-12 09:13:02 +08:00
Huseyin Karakullukcu
cfc345c31e Fix T68950: Adding lots of edge loops to cylinder produces a crash
Instead of fixed size, `IMM_BUFFER_SIZE` is adjustable now. The internal buffer can expand if there is a need a bigger buffer. All other behaviors are still the same.

Reviewed By: fclem, #gpu_viewport

Differential Revision: https://developer.blender.org/D5570
2019-09-12 09:13:02 +08:00
023a7fada8 Eevee: Use manual derivatives for better quality bump.
We basically duplicate the height map branch plugged into the bump node,
and tag each node in each branch as dx/dy/ref using `branch_tag`.

Then we add a one pixel offset on the texture coordinates if the node is
tagged as dx or dy.

The dx/dy branches are plugged into (new) hidden sockets on the bump node.

This match cycles bump better but have a performance impact. Also, complex
nodetrees can now become instruction limited and not compile anymore.

Reviewers: brecht

Differential Revision: https://developer.blender.org/D5531
2019-09-12 09:13:02 +08:00
Julian Eisel
13194fc36a Fix: File browser report popups not showing up
Popup would be closed immediately after creating, because of incorrect
mouse coordinates stored in window (popup is set to close if mouse is
some distance away from it).

Completes fix for T69581.
2019-09-12 09:13:02 +08:00
1a0aa336cb UI: File Browser Large Icon Update
Replaces the large icons used in the File Browser with updated versions by Andrzej Ambroz (jendrzych).

Differential Revision: https://developer.blender.org/D5698

Reviewed by Brecht Van Lommel
2019-09-12 09:13:02 +08:00
OmarSquircleArt
7e14b9807b Fix: Rename the dimensions property in Noise nodes.
The `dimensions` property of the noise nodes has been renamed to
`noise_dimensions` because it conflicted with and overwrote the
`dimensions` property of the base node.

Reviewers: brecht, JacquesLucke

Differential Revision: https://developer.blender.org/D5705
2019-09-12 09:13:02 +08:00
a4d4673892 WM: batch rename support for regex groups
Optionally use regular expressions for the destination name,
allows re-ordering words while renaming.

Initial patch by @jmztn with error handling and UI changes.
2019-09-12 09:13:02 +08:00
6226f299be GPencil: Guides: Refactor and add new ISO option
+ Simplify code, move into own function and run once rather than on every point
+ Improved snapping when a stroke is between increments
+ Added ISO grid option for lines specified by Angle under guide settings
+ Radial snapping mode uses Angle as an offset

Differential Revision: https://developer.blender.org/D5668
2019-09-12 09:13:02 +08:00
Julian Eisel
4ac9c3e135 Fix: File browser errors not reported in the UI
This is a partial fix, in that it only brings back the banner reports in
the status bar. The popups still don't show up but I need to investigate
more.
It's really ugly that reports rely on wmWindowManager.winactive, but
that's how it is...

Partialy fixes T69581.
2019-09-12 09:13:02 +08:00
c5de8120c0 Fix T69536: Setting dimensions for parented objects fails
Parenting/constraints/delta-scaled all caused setting dimensions to fail.

Take the difference between the input scale and final scale into
account when applying the dimensions.
2019-09-12 09:13:02 +08:00
93f940db25 Transformation Constraint: implement a Mix Mode option.
Allow selecting how the new location/rotation/scale is combined with
the existing transformation. This is most useful for rotation, which
has multiple options, and scale, which previously could only replace.
2019-09-12 09:13:02 +08:00
cdf5891cca Transformation Constraint: initialize scale range values to 1 instead of 0. 2019-09-12 09:13:01 +08:00
Julian Eisel
760841c293 Fix failing assert on directory auto-creation
The failing assert was there before the recent file browser design
overhaul. Might have been in there for quite a while in fact.

Auto-creation in this case means that the file path would be created if
a non-existent path was entered in the file browser path button.
2019-09-12 09:13:01 +08:00
Julian Eisel
e5ae229649 UI: Confirmation prompt for file path auto-create
This confirmation prompt was there earlier, we removed the prompts for
creating new directories all together, but in this case it's reasonable.
Without it, it's simply too easy to create new directories by accident.
2019-09-12 09:13:01 +08:00
f6c0ae9ae5 Cleanup: function grouping
Also rename widget color blending functions more clearly.

- color_blend_v3_v3, was widget_state_blend
- color_blend_v4_v4v4, was round_box_shade_col4_r
- color_ensure_contrast_v3, was rgb_ensure_contrast
2019-09-12 09:13:01 +08:00
9b9f99fa41 Cleanup: use doxy sections 2019-09-12 09:13:01 +08:00
9942470466 Viewport Shading: StudioLight Intensity
Add option to change the Intensity of the HDRI in the 3d viewport. This works for both EEVEE and Cycles

Reviewed By: brecht, fclem

Differential Revision: https://developer.blender.org/D5674
2019-09-12 09:13:01 +08:00
c92c753a2f Copy Transforms: add a mixing mode option.
Allow combining location, rotation and scale at the same time,
using one constraint. The mixing modes are based on matrix
multiplication, but handle scale in a way that avoids creating
shear.

Reviewers: brecht

Differential Revision: https://developer.blender.org/D5640
2019-09-12 09:13:01 +08:00
610c11e33a Copy Rotation: implement new mixing modes that actually work.
Upon close inspection, the way the Offset mode works in the
Copy Rotation constraint makes no sense, and in fact, destroys
the rotation of its owner unless either it's single axis, or
the order is set specifically to `ZYX Euler`.

Since it can't simply be changed because of backward compatibility
concerns, replace the checkbox with a dropdown that provides a set
of new modes that actually make sense.

Specifically, add a mode that simply adds Euler components together,
and two options that use matrix multiplication in different order.

The Python use_offset property is replaced with compatibility stubs.

Reviewers: brecht

Differential Revision: https://developer.blender.org/D5640
2019-09-12 09:13:01 +08:00
Julian Eisel
50db4b3801 UI: Bring back features for file path button
Adds back auto-completion and auto-creation (inserting a non-existing
file-path would create it) for the file path button. The second feature
was left out knowingly, but seems there are reasonable use cases for it.

We can't add these features to the button in the Python script, we have
to call into C. So using a template to do that.
Note that this is based on the old file browser code, I've copied over
the TODO comment.
2019-09-12 09:13:01 +08:00
Julian Eisel
627b07ad7c Fix T69498: Crash on export UV Layout
Ensure there's a drawable context after the file browser window is
destroyed.
2019-09-12 09:13:01 +08:00
Julian Eisel
c1ad518d56 Fix T69495: Crash changing action in file browser
We need to ensure the file browser window doesn't manage the handlers
for itself.
The special file browser closing code that we used previously isn't
needed anymore, wm_window_open_temp() and the handling of
EVT_FILESELECT_FULL_OPEN  already manage it fine.
2019-09-12 09:13:01 +08:00
f3553ff144 UI: tweak 3D view space between navigation gizmo & buttons
Align the lower side of the navigation gizmo with the top of the icons.
2019-09-12 09:13:01 +08:00
f8cbace82e Revert "UI: Add Dimensions to Object Transform panel"
This reverts commit 82fc9d778e.

This doesn't use the workaround from v3d_object_dimension_buts
needed for dimensions properly update.

Doing this would require moving the panel to C.

Issues from T69536 should be resolved before adding this back.
2019-09-12 09:13:01 +08:00
9a2e290c1f LibOverride: Initial attempt to ignore missing place-holders IDs.
Ideally, when a reference linked ID is missing (and replaced by linking
code with an empty place-holder), we should just keep the local
overriding datablocks as-is, until broken links are fixed.

Not really working yet though, needs more work here...
2019-09-12 09:13:01 +08:00
8650f854ef LibOverride: add a generic macro to check whetehr an ID is overridable.
...and use it in code generating library overrides.
2019-09-12 09:13:01 +08:00
6cde30681c LibOverride: give more remapping control to BKE_override_library_create_from_id() too.
Similar change to the one done for tagged IDs overriding some days ago.
We do not always want to remap all local usages of a linked data-block
to its new local overriding copy.
2019-09-12 09:13:01 +08:00
0380f37746 Fix T63653: Industry Compatible Keymap can't be saved & loaded
Replace keymap specific operator.
2019-09-12 09:13:01 +08:00
2e2f68c6b3 Fix keymap export of enum-flag properties 2019-09-12 09:13:01 +08:00
b92acee177 Object: Mode switching operator
Remove unused OBJECT_OT_mode_set_or_submode, add
OBJECT_OT_mode_set_with_submode which can switch to edit mode as well
as a sub-mode - currently only mesh select mode is supported
(others may be added later).
2019-09-12 09:13:01 +08:00
f80b47e715 Cleanup: reuse mesh select mode enum 2019-09-12 09:13:01 +08:00
5e5dbcfcd2 Cleanup: Cmake submodule checks
It is a pain if the subfile we are checking if it exists gets
renamed/removed.

Instead we can check if the directory is empty.

Reviewers: mont29

Reviewed By: mont29

Differential Revision: https://developer.blender.org/D5653
2019-09-12 09:13:01 +08:00
1b3014f2f4 Fix unreported: snapping to 3d tracking markers sometimes fails 2019-09-12 09:13:01 +08:00
e21939965a Transform: Split transform_conversions into multiple files.
Part of T68836

`transform conversions.c` is a file that is getting too big (almost 10,000 lines).
So it's a good idea to split it into smaller files.

differential revision: https://developer.blender.org/D5677
2019-09-12 09:13:01 +08:00
c5f28aa0d7 Fix T69513: Grease Pencil Fade Layers Overlay only works in Material and Texture Shading
The overlay factor was not used in other modes.
2019-09-12 09:13:01 +08:00
Erik Abrahamsson
a98d38b688 Improve some textures UI properties click-drag precision
When click-dragging to change values in textures (for example Musgrave-
>Size to give an example) the step size is too big.

Reviewers: brecht, lichtwerk

Reviewed By: brecht, lichtwerk

Differential Revision: https://developer.blender.org/D5661
2019-09-12 09:13:01 +08:00
aedb784407 Fix T68840: Metaballs update 'NEVER' method not working
Was always evaluating due to typo in rB34ab90f546f0.

Reviewers: brecht

Maniphest Tasks: T68840

Differential Revision: https://developer.blender.org/D5695
2019-09-12 09:13:00 +08:00
7795cfead6 Eevee: Shadow map refactor
Reviewed By: brecht

Differential Revision: http://developer.blender.org/D5659
2019-09-12 09:13:00 +08:00
53459c7889 Cleanup: de-duplicate code 2019-09-12 09:10:19 +08:00
73e4648477 Depsgraph: Ensure it's fully evaluated after POST callbacks
It is possible that POST callbacks will modify objects or relations.
This change makes it so an extra update pass is done if needed.

Reviewers: brecht

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5690
2019-09-12 09:10:19 +08:00
bd4f3a1449 UI: use boolean for sequencer reverse frames
Revert part of 04b86c21bf

The option to reverse frames is used elsewhere as a boolean
which makes sense since reversing playback is a special case.
2019-09-12 09:10:19 +08:00
a41f20ec79 GPencil: New Operator to set the active object material based on the selected stroke material
The operator set as active object material the material used in the selected stroke.

Access to the operator were added in the stroke menu and context stroke menu.

Reviewers: antoniov, pepeland

Tags: #bf_blender, #grease_pencil

Differential Revision: https://developer.blender.org/D5692
2019-09-12 09:10:19 +08:00
OmarSquircleArt
d8fbeeb8e7 Fix T69532: Wave texture fails with a compile error.
`noise_turbulence` was renamed to `fractal_noise`.

Reviewers: brecht

Differential Revision: https://developer.blender.org/D5691
2019-09-12 09:10:19 +08:00
OmarSquircleArt
086a206ddc Fix: Compile error due to undefined isinf function.
Some implementations of the standard c++ library doesn't define its
functions in the global namespace. So the `isinf` function might
fail in some systems. To fix this, we use the `ensure_finite`
function instead.

Reviewers: brecht

Differential Revision: https://developer.blender.org/D5687
2019-09-12 09:10:19 +08:00
2a7388c491 Buildbot: enable tests to run again
These will not stop the build on failure yet, first step is to get them passing
more reliably.
2019-09-12 09:10:19 +08:00
Sebastian Koenig
322fa8e200 Tracking: Enable "Render Undistorted" only if there is actual distortion
Applies to "Setup Tracking Scene" operator which configures background
images for the viewport.

Solves unnecessary slowdown and higher memory usage when camera's model
does not have any effective distortion.

Differential Revision: https://developer.blender.org/D5520
2019-09-12 09:10:19 +08:00
989557c9d5 Depsgraph: Free user code from worry about updates flush 2019-09-12 09:10:19 +08:00
abdfdf400a Depsgraph: Pass bmain to evaluation function
Currently unused, makes code ready for an upcoming change.
2019-09-12 09:10:19 +08:00
9f71529e4f Industry Compat keymap: Add Batch Rename to Alt-Return 2019-09-12 09:10:19 +08:00
d4dbbf4f6f File Browser UI: Use 'Install' instead of ''Install Add-on from File...' as the name of the execute button
The old name didn't fit inside the button, and this fits with simpler Open/Save labels too.
2019-09-12 09:10:19 +08:00
dcd66e79f7 Fix T69522: Render Region not refreshing Output Properties
setting/clearing render region uses ND_RENDER_OPTIONS notifier, but
listener was only refreshing RENDER and VIEWLAYER tabs in that case,
whereas the render region buttons are located in OUTPUT tab.

Reviewers: billreynish

Maniphest Tasks: T69522

Differential Revision: https://developer.blender.org/D5685
2019-09-12 09:10:19 +08:00
5fb93df76f Mesh Batch Cache: Fix threading issue
I believed the crash I experienced happened because:
1. The `extract_pos_nor_init` function is called.
2. Tasks are added to the task pool for `extract_pos_nor`.
3. The tasks begin to be executed while more tasks are added.
4. In some rare cases, all existing tasks are finished, but not all have been added yet.
5. This let the task-counter go down to zero.
6. This triggered a call to `extract_pos_nor_finish`.
7. Then more tasks are added and in the end `extract_pos_nor_finish` is called again.

A solution is to use a task pool that is suspended when created.
Unfortunately, there was an outdated comment, that was probably the root cause of the issue.

Reviewers: fclem, sergey

Differential Revision: https://developer.blender.org/D5680
2019-09-12 09:10:19 +08:00
Sebastian Koenig
a1a7fc91c1 MovieClip: Make name of Active Clip consistent in UI
Using the currently active movie clip had different names in the interface:
In scene context it was "Active Movie Clip", in Camera Background Images it was "Camera Clip", in Constraints it was "ActiveClip".
I made all those instances use "Active Clip", which is descriptive enough and also the shortest of the three.

Reviewed By: billreynish

Differential Revision: https://developer.blender.org/D5400
2019-09-12 09:10:19 +08:00
7dc87257d6 LANPR: Restore normal line weight panel in GPU. 2019-09-05 16:09:28 +08:00
e151c8e6f4 LANPR: Fix DPIX line thickness bug & format. 2019-09-05 15:59:43 +08:00
615e11d8b9 LANPR: Move object LANPR tab under material tab. 2019-09-05 15:22:00 +08:00
5396e17fb8 Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-09-05 15:06:33 +08:00
4f1928c2ae LANPR: Use private header in editor module. 2019-09-05 11:54:02 +08:00
7fb8ff3b27 Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-09-05 11:36:05 +08:00
e80480ad41 LANPR: qi_begin/end => level_start/end 2019-09-04 15:16:09 +08:00
d4561c2468 Cleanup: Make format. 2019-09-04 15:10:22 +08:00
8b9131bd75 LANPR: LANPR_LineType::enabled => use. 2019-09-04 15:03:56 +08:00
eefab053f2 LANPR: Line component description use "filter". 2019-09-04 14:53:45 +08:00
2752870406 LANPR: Fix definitions in LANPR_LineType. 2019-09-04 14:52:01 +08:00
ebce8d65d4 LANPR: Header inclusion order fixes. 2019-09-04 14:46:44 +08:00
7206254d92 LANPR: Remove "ignore_lanpr" in edge split modifier. 2019-09-04 14:27:22 +08:00
b8cb26eff9 LANPR: Fix some code style based on recommendations. 2019-09-04 14:13:49 +08:00
f601a0e4b5 LANPR: python cleanups. 2019-09-04 13:52:36 +08:00
1d43f5b5f2 LANPR: Add licence header in all files. 2019-09-04 13:45:12 +08:00
dc5389f514 LANPR: Fix flag usages. Removed custom types. 2019-09-04 13:36:25 +08:00
c122d1b818 LANPR: Use flags for SceneLANPR. Make format. 2019-09-04 11:21:58 +08:00
628fe8b635 LANPR: Use flags for struct LANPR_LineLayer. 2019-09-04 11:04:59 +08:00
72c0abbd28 Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-09-04 09:53:45 +08:00
d543acbdf7 Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-09-01 22:38:02 +08:00
88fc7e401a Merge branch 'master' into temp-lanpr-staging 2019-08-20 21:10:51 +08:00
9fe7a6035f Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-08-20 21:09:12 +08:00
e7a21545ee Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-08-19 20:27:57 +08:00
49640c7881 LANPR: Fix render status enum value. 2019-08-18 21:33:21 +08:00
a7bab3bd22 LANPR: Bypass thread redraw viewport on complete. 2019-08-18 21:31:55 +08:00
686ddc842c LANPR: Bypass thread for LANPR calculations. 2019-08-18 21:22:36 +08:00
c676b74c84 Fix lock variable. 2019-08-18 19:46:16 +08:00
4bdac5da75 Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-08-18 19:39:45 +08:00
b13f8aa442 LANPR: Threaded render status flag. 2019-08-18 17:35:07 +08:00
da74aa3973 LANPR: Typo lanpr_compute_view_vector. 2019-08-18 16:42:32 +08:00
2c9dc87fc1 LANPR: Missed a transpose when apply rotation. 2019-08-18 16:31:54 +08:00
58d2a01f6f BLI: Remove SIMD for double version for mul_m4db_. 2019-08-18 15:47:30 +08:00
de8b4ef217 BLI: SSE2 support for double version matrix. 2019-08-18 14:26:28 +08:00
5fd4af1589 Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-08-18 14:08:52 +08:00
f7e3efa4a2 LANPR: Fix wrong function for clearing list base. 2019-08-16 13:54:05 +08:00
9ec72374c3 Cleanup: make format. 2019-08-16 11:12:28 +08:00
60f5cdaee9 LANPR: Use BLI math functions. 2019-08-16 11:11:04 +08:00
d515b4e205 Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-08-16 09:42:46 +08:00
ccc113deba Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-08-14 15:46:31 +08:00
33d3dcdb00 View3D: Circle Select optimization
Don't recreate `select_bitmap` for each edited object.
2019-08-14 15:35:26 +08:00
255048842f Cleanup: Remove tnsLinearItp(). 2019-08-12 10:24:09 +08:00
b790e32ded LANPR: Use BLI math functions. Some added. 2019-08-12 09:58:24 +08:00
875beb5f92 Merge remote-tracking branch 'origin/master' into temp-lanpr-staging 2019-08-12 09:13:20 +08:00
17656a6e1f LANPR: Use flag for enable field. 2019-08-12 09:12:09 +08:00
ddb78ea43b Cleanup: Remove material LANPR settings for future integration. 2019-08-11 17:49:28 +08:00
01369f1400 Cleanup: make format. 2019-08-11 17:40:06 +08:00
cfd060147b Cleanup: Use "normal_thickness_start". 2019-08-11 17:25:05 +08:00
e21a36b69a Cleanup: Use "level_start". 2019-08-11 17:22:43 +08:00
05b54a99ef Cleanup: if brackets. 2019-08-11 17:20:16 +08:00
6bd4ea0c2f Cleanup: New line at EOF. 2019-08-11 16:30:43 +08:00
f04a173d7b Diff for adding LANPR only. 2019-08-11 16:12:04 +08:00
72 changed files with 13179 additions and 40 deletions

View File

@@ -32,6 +32,7 @@ _modules = [
"constraint",
"file",
"image",
"lanpr",
"mask",
"mesh",
"node",

View File

@@ -0,0 +1,41 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
import string
class LANPR_reset_object_transfromations(bpy.types.Operator):
"""Reset Transformations"""
bl_idname = "lanpr.reset_object_transfromations"
bl_label = "Reset Transformations"
obj = bpy.props.StringProperty(name="Target Object")
def execute(self, context):
print(self.obj)
ob = bpy.data.objects[self.obj]
ob.location.zero()
ob.rotation_euler.zero()
ob.scale.xyz=[1,1,1]
return {'FINISHED'}
classes=(
LANPR_reset_object_transfromations,
)

View File

@@ -65,6 +65,8 @@ _modules = [
"properties_scene",
"properties_texture",
"properties_world",
"properties_collection",
"properties_lanpr",
# Generic Space Modules
#

View File

@@ -0,0 +1,129 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
from bpy.types import Panel
from bpy import data
from mathutils import Vector
class CollectionButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "collection"
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
@classmethod
def poll(cls, context):
return (context.engine in cls.COMPAT_ENGINES)
def lanpr_make_line_type_entry(col, line_type, text_disp, expand, search_from):
col.prop(line_type, "use", text=text_disp)
if expand:
col.prop_search(line_type, "layer", search_from, "layers")
col.prop_search(line_type, "material", search_from, "materials")
class COLLECTION_PT_collection_flags(CollectionButtonsPanel, Panel):
bl_label = "Collection Flags"
def draw(self, context):
layout=self.layout
collection=context.collection
vl = context.view_layer
vlc = vl.active_layer_collection
if vlc.name == 'Master Collection':
row = layout.row()
row.label(text="This is the master collection")
return
row = layout.row()
col = row.column(align=True)
col.prop(vlc,"hide_viewport")
col.prop(vlc,"holdout")
col.prop(vlc,"indirect_only")
row = layout.row()
col = row.column(align=True)
col.prop(collection,"hide_select")
col.prop(collection,"hide_viewport")
col.prop(collection,"hide_render")
def is_unit_transformation(ob):
if ob.scale.xyz==Vector((1,1,1)) and ob.location.xyz==Vector((0,0,0)) and \
ob.rotation_euler.x == 0.0 and ob.rotation_euler.y == 0.0 and ob.rotation_euler.z == 0.0:
return True
return False
class COLLECTION_PT_lanpr_collection(CollectionButtonsPanel, Panel):
bl_label = "Collection LANPR"
@classmethod
def poll(cls, context):
return context.scene.render.engine == 'BLENDER_LANPR' or context.scene.lanpr.enabled
def draw(self,context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
collection = context.collection
lanpr = collection.lanpr
row = layout.row()
row.prop(lanpr,"usage")
if lanpr.usage!='INCLUDE':
layout.prop(lanpr,"force")
else:
layout.prop(lanpr,"target")
if lanpr.target:
if not is_unit_transformation(lanpr.target):
layout.label(text = "Target GP has self transformations.")
layout.operator("lanpr.reset_object_transfromations").obj=lanpr.target.name
layout.prop(lanpr,'use_multiple_levels', text="Multiple Levels")
if lanpr.use_multiple_levels:
col = layout.column(align=True)
col.prop(lanpr,'level_start',text="Level Begin")
col.prop(lanpr,'level_end',text="End")
else:
layout.prop(lanpr,'level_start',text="Level")
layout.prop(lanpr, "use_same_style")
if lanpr.use_same_style:
layout.prop_search(lanpr, 'target_layer', lanpr.target.data, "layers", icon='GREASEPENCIL')
layout.prop_search(lanpr, 'target_material', lanpr.target.data, "materials", icon='SHADING_TEXTURE')
expand = not lanpr.use_same_style
lanpr_make_line_type_entry(layout, lanpr.contour, "Contour", expand, lanpr.target.data)
lanpr_make_line_type_entry(layout, lanpr.crease, "Crease", expand, lanpr.target.data)
lanpr_make_line_type_entry(layout, lanpr.material, "Material", expand, lanpr.target.data)
lanpr_make_line_type_entry(layout, lanpr.edge_mark, "Edge Mark", expand, lanpr.target.data)
lanpr_make_line_type_entry(layout, lanpr.intersection, "Intersection", expand, lanpr.target.data)
classes = (
COLLECTION_PT_collection_flags,
COLLECTION_PT_lanpr_collection,
)
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
for cls in classes:
register_class(cls)

View File

@@ -0,0 +1,105 @@
# ##### 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.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
from bpy.types import Panel
from bpy import data
from mathutils import Vector
class LanprButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "lanpr"
# COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
@classmethod
def poll(cls, context):
return True
def lanpr_make_line_type_entry(col, line_type, text_disp, expand, search_from):
col.prop(line_type, "use", text=text_disp)
if expand:
col.prop_search(line_type, "layer", search_from, "layers")
col.prop_search(line_type, "material", search_from, "materials")
class OBJECT_PT_lanpr_settings(LanprButtonsPanel, Panel):
bl_label = "LANPR settings"
@classmethod
def poll(cls, context):
ob = context.object
obl = ob.lanpr
return (context.scene.render.engine == 'BLENDER_LANPR' or context.scene.lanpr.enabled) and\
obl.usage == 'INCLUDE' and obl.target
def draw(self,context):
collection = context.collection
lanpr = collection.lanpr
ob = context.object
obl = ob.lanpr
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
layout.prop(obl,'use_multiple_levels', text="Multiple Levels")
if obl.use_multiple_levels:
col = layout.column(align=True)
col.prop(obl,'level_start')
col.prop(obl,'level_end', text="End")
else:
layout.prop(obl,'level_start', text="Level")
layout.prop(obl,'use_same_style')
if obl.use_same_style:
layout.prop_search(obl, 'target_layer', obl.target.data, "layers", icon='GREASEPENCIL')
layout.prop_search(obl, 'target_material', obl.target.data, "materials", icon='SHADING_TEXTURE')
expand = not obl.use_same_style
lanpr_make_line_type_entry(layout, obl.contour, "Contour", expand, obl.target.data)
lanpr_make_line_type_entry(layout, obl.crease, "Crease", expand, obl.target.data)
lanpr_make_line_type_entry(layout, obl.material, "Material", expand, obl.target.data)
lanpr_make_line_type_entry(layout, obl.edge_mark, "Edge Mark", expand, obl.target.data)
class OBJECT_PT_lanpr(LanprButtonsPanel, Panel):
bl_label = "Usage"
@classmethod
def poll(cls, context):
return context.scene.render.engine == 'BLENDER_LANPR' or context.scene.lanpr.enabled
def draw(self, context):
layout=self.layout
lanpr = context.object.lanpr
if context.object.type == 'MESH':
layout.prop(lanpr,'usage')
if lanpr.usage == 'INCLUDE':
layout.prop(lanpr, "target")
classes = (
OBJECT_PT_lanpr,
OBJECT_PT_lanpr_settings,
)
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
for cls in classes:
register_class(cls)

View File

@@ -67,14 +67,14 @@ class MaterialButtonsPanel:
class MATERIAL_PT_preview(MaterialButtonsPanel, Panel):
bl_label = "Preview"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_EEVEE'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_LANPR'}
def draw(self, context):
self.layout.template_preview(context.material)
class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_LANPR'}
_context_path = "material"
_property_type = bpy.types.Material
@@ -83,7 +83,7 @@ class EEVEE_MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
bl_label = ""
bl_context = "material"
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_LANPR'}
@classmethod
def poll(cls, context):
@@ -162,7 +162,7 @@ def panel_node_draw(layout, ntree, _output_type, input_name):
class EEVEE_MATERIAL_PT_surface(MaterialButtonsPanel, Panel):
bl_label = "Surface"
bl_context = "material"
COMPAT_ENGINES = {'BLENDER_EEVEE'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_LANPR'}
def draw(self, context):
layout = self.layout

View File

@@ -18,12 +18,15 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
from bpy.types import Panel
from bl_ui.space_view3d import (
VIEW3D_PT_shading_lighting,
VIEW3D_PT_shading_color,
VIEW3D_PT_shading_options,
)
from bpy.types import (
Panel,
UIList,
)
class RenderButtonsPanel:
@@ -64,7 +67,7 @@ class RENDER_PT_color_management(RenderButtonsPanel, Panel):
bl_label = "Color Management"
bl_options = {'DEFAULT_CLOSED'}
bl_order = 100
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_LANPR'}
def draw(self, context):
layout = self.layout
@@ -97,7 +100,7 @@ class RENDER_PT_color_management_curves(RenderButtonsPanel, Panel):
bl_label = "Use Curves"
bl_parent_id = "RENDER_PT_color_management"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'BLENDER_LANPR'}
def draw_header(self, context):
@@ -461,7 +464,7 @@ class RENDER_PT_eevee_indirect_lighting_display(RenderButtonsPanel, Panel):
class RENDER_PT_eevee_film(RenderButtonsPanel, Panel):
bl_label = "Film"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_EEVEE'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_LANPR'}
@classmethod
def poll(cls, context):
@@ -685,6 +688,435 @@ class RENDER_PT_simplify_greasepencil(RenderButtonsPanel, Panel):
sub.prop(rd, "simplify_gpencil_remove_lines", text="Lines")
class LANPR_UL_linesets(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
layout.prop(item,"name", text="", emboss=False)
class RENDER_PT_lanpr(RenderButtonsPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL', 'BLENDER_EEVEE'}
bl_label = "LANPR"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return True
def draw_header(self, context):
if context.scene.render.engine != 'BLENDER_LANPR':
self.layout.prop(context.scene.lanpr, "enabled", text="")
def draw(self, context):
scene = context.scene
lanpr = scene.lanpr
active_layer = lanpr.layers.active_layer
mode = lanpr.master_mode
layout = self.layout
layout.active = scene.render.engine=="BLENDER_LANPR" or lanpr.enabled
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
col = layout.column()
if scene.render.engine=="BLENDER_LANPR":
col.prop(lanpr, "master_mode")
else:
mode = "SOFTWARE"
if mode == "DPIX" and lanpr.shader_error:
layout.label(text="DPIX transform shader compile error!")
return
layout.prop(lanpr, "crease_threshold", slider=True)
if not scene.camera:
has_camera=False
col.label(text="No active camera.")
else:
has_camera=True
c=col.column()
c.enabled = has_camera
if scene.render.engine=="BLENDER_LANPR":
c.prop(lanpr,'auto_update', text='Auto Update')
txt = "Update" if mode == "SOFTWARE" else "Intersection Cache"
if not lanpr.auto_update:
c.operator("scene.lanpr_calculate", icon='FILE_REFRESH', text=txt)
if mode == "DPIX" and len(lanpr.layers)==0:
layout.label(text="You don't have a layer to display.")
layout.operator("scene.lanpr_add_line_layer");
if scene.render.engine=="BLENDER_LANPR" and mode == "SOFTWARE":
layout.operator("scene.lanpr_auto_create_line_layer", text = "Default", icon = "ADD")
row=layout.row()
row.template_list("LANPR_UL_linesets", "", lanpr, "layers", lanpr.layers, "active_layer_index", rows=4)
col=row.column(align=True)
if active_layer:
col.operator("scene.lanpr_add_line_layer", icon="ADD", text='')
col.operator("scene.lanpr_delete_line_layer", icon="REMOVE", text='')
col.separator()
col.operator("scene.lanpr_move_line_layer",icon='TRIA_UP', text='').direction = "UP"
col.operator("scene.lanpr_move_line_layer",icon='TRIA_DOWN', text='').direction = "DOWN"
col.separator()
col.operator("scene.lanpr_rebuild_all_commands",icon="FILE_REFRESH", text='')
else:
col.operator("scene.lanpr_add_line_layer", icon="ADD", text='')
def lanpr_make_line_type(expand,layout,line_type,label):
layout.prop(line_type, "use", text=label)
if expand and line_type.use:
c = layout.column(align=True)
c.prop(line_type, "color", text="Color")
c.prop(line_type, "thickness", slider=True)
class RENDER_PT_lanpr_layer_settings(RenderButtonsPanel, Panel):
bl_label = "Layer Settings"
bl_parent_id = "RENDER_PT_lanpr"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
scene = context.scene
lanpr = scene.lanpr
active_layer = lanpr.layers.active_layer
return scene.render.engine=="BLENDER_LANPR" and active_layer
def draw(self, context):
scene = context.scene
lanpr = scene.lanpr
active_layer = lanpr.layers.active_layer
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
mode = lanpr.master_mode
if scene.render.engine!="BLENDER_LANPR" and mode != "SOFTWARE":
mode = "SOFTWARE"
if active_layer and mode == "DPIX":
active_layer = lanpr.layers[0]
if mode == "SOFTWARE":
layout.prop(active_layer, "use_multiple_levels", text="Multiple Levels")
col = layout.column(align=True)
col.prop(active_layer, "level_start", text='Level Start')
if active_layer.use_multiple_levels:
col.prop(active_layer, "level_end", text='End')
layout.prop(active_layer,"use_same_style")
expand = not active_layer.use_same_style
col = layout.column(align=True)
if not expand:
col.prop(active_layer, "color")
col.prop(active_layer, "thickness", text="Main Thickness")
lanpr_make_line_type(expand,layout,active_layer.contour,"Contour")
lanpr_make_line_type(expand,layout,active_layer.crease,"Crease")
lanpr_make_line_type(expand,layout,active_layer.edge_mark,"EdgeMark")
lanpr_make_line_type(expand,layout,active_layer.material_separate,"Material")
if lanpr.use_intersections:
lanpr_make_line_type(expand,layout,active_layer.intersection,"Intersection")
else:
layout.label(text= "Intersection calculation disabled.")
class RENDER_PT_lanpr_line_components(RenderButtonsPanel, Panel):
bl_label = "Including"
bl_parent_id = "RENDER_PT_lanpr"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
scene = context.scene
lanpr = scene.lanpr
active_layer = lanpr.layers.active_layer
return scene.render.engine=="BLENDER_LANPR" and active_layer and not lanpr.enable_chaining
def draw(self, context):
layout = self.layout
scene = context.scene
lanpr = scene.lanpr
active_layer = lanpr.layers.active_layer
layout.operator("scene.lanpr_add_line_component")#, icon = "ZOOMIN")
i=0
for c in active_layer.components:
split = layout.split(factor=0.85)
col = split.column()
sp2 = col.split(factor=0.4)
cl = sp2.column()
cl.prop(c,"component_mode", text = "")
cl = sp2.column()
if c.component_mode == "OBJECT":
cl.prop(c,"object_select", text = "")
elif c.component_mode == "MATERIAL":
cl.prop(c,"material_select", text = "")
elif c.component_mode == "COLLECTION":
cl.prop(c,"collection_select", text = "")
col = split.column()
col.operator("scene.lanpr_delete_line_component", text="").index=i
i=i+1
class RENDER_PT_lanpr_line_normal_effects(RenderButtonsPanel, Panel):
bl_label = "Normal Based Line Weight"
bl_parent_id = "RENDER_PT_lanpr"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
scene = context.scene
lanpr = scene.lanpr
active_layer = lanpr.layers.active_layer
return scene.render.engine=="BLENDER_LANPR" and active_layer
def draw_header(self, context):
active_layer = context.scene.lanpr.layers.active_layer
self.layout.prop(active_layer, "normal_enabled", text="")
def draw(self, context):
scene = context.scene
lanpr = scene.lanpr
active_layer = lanpr.layers.active_layer
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
layout.prop(active_layer,"normal_mode", text="Mode")
if active_layer.normal_mode != "DISABLED":
layout.prop(active_layer,"normal_control_object")
layout.prop(active_layer,"normal_effect_inverse")
col = layout.column(align=True)
col.prop(active_layer,"normal_ramp_begin")
col.prop(active_layer,"normal_ramp_end", text="End")
col = layout.column(align=True)
col.prop(active_layer,"normal_thickness_start", slider=True)
col.prop(active_layer,"normal_thickness_end", slider=True, text="End")
class RENDER_PT_lanpr_line_gpu_effects(RenderButtonsPanel, Panel):
bl_label = "Effects"
bl_parent_id = "RENDER_PT_lanpr"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
scene = context.scene
lanpr = scene.lanpr
active_layer = lanpr.layers.active_layer
return scene.render.engine=="BLENDER_LANPR" and active_layer and lanpr.master_mode == "DPIX"
def draw(self, context):
scene = context.scene
lanpr = scene.lanpr
active_layer = lanpr.layers.active_layer
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
col = layout.column(align = True)
col.prop(lanpr, "crease_threshold")
col.prop(lanpr, "crease_fade_threshold", text="Fade")
col = layout.column(align = True)
col.prop(lanpr, "depth_width_influence")
col.prop(lanpr, "depth_width_curve", text="Curve")
col = layout.column(align = True)
col.prop(lanpr, "depth_alpha_influence")
col.prop(lanpr, "depth_alpha_curve", text="Curve")
class RENDER_PT_lanpr_snake_sobel_parameters(RenderButtonsPanel, Panel):
bl_label = "Sobel Parameters"
bl_parent_id = "RENDER_PT_lanpr"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
scene = context.scene
lanpr = scene.lanpr
return scene.render.engine=="BLENDER_LANPR" and lanpr.master_mode == "SNAKE"
def draw(self, context):
layout = self.layout
scene = context.scene
lanpr = scene.lanpr
layout.prop(lanpr, "depth_clamp")
layout.prop(lanpr, "depth_strength")
layout.prop(lanpr, "normal_clamp")
layout.prop(lanpr, "normal_strength")
if lanpr.enable_vector_trace == "DISABLED":
layout.prop(lanpr, "display_thinning_result")
class RENDER_PT_lanpr_snake_settings(RenderButtonsPanel, Panel):
bl_label = "Snake Settings"
bl_parent_id = "RENDER_PT_lanpr"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
scene = context.scene
lanpr = scene.lanpr
return scene.render.engine=="BLENDER_LANPR" and lanpr.master_mode == "SNAKE" and lanpr.enable_vector_trace == "ENABLED"
def draw(self, context):
layout = self.layout
scene = context.scene
lanpr = scene.lanpr
split = layout.split()
col = split.column()
col.prop(lanpr, "background_color")
col = split.column()
col.prop(lanpr, "line_color")
layout.prop(lanpr, "line_thickness")
split = layout.split()
col = split.column()
col.prop(lanpr, "depth_width_influence")
col.prop(lanpr, "depth_alpha_influence")
col = split.column()
col.prop(lanpr, "depth_width_curve")
col.prop(lanpr, "depth_alpha_curve")
layout.label(text="Taper:")
layout.prop(lanpr, "use_same_taper", expand = True)
if lanpr.use_same_taper == "DISABLED":
split = layout.split()
col = split.column(align = True)
col.label(text="Left:")
col.prop(lanpr,"taper_left_distance")
col.prop(lanpr,"taper_left_strength", text="Strength")
col = split.column(align = True)
col.label(text="Right:")
col.prop(lanpr,"taper_right_distance")
col.prop(lanpr,"taper_right_strength", text="Strength")
else:
split = layout.split()
col = split.column(align = True)
col.prop(lanpr,"taper_left_distance")
col.prop(lanpr,"taper_left_strength")
layout.label(text="Tip Extend:")
layout.prop(lanpr, "enable_tip_extend", expand = True)
if lanpr.enable_tip_extend == "ENABLED":
layout.label(text="---INOP---")
layout.prop(lanpr,"extend_length")
class RENDER_PT_lanpr_gpencil(RenderButtonsPanel, Panel):
bl_label = "Grease Pencil"
bl_parent_id = "RENDER_PT_lanpr"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
scene = context.scene
lanpr = scene.lanpr
return scene.render.engine!='BLENDER_LANPR'
def draw(self, context):
scene = context.scene
lanpr = scene.lanpr
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
if not scene.camera:
has_camera=False
layout.label(text="No active camera.")
else:
has_camera=True
layout.enabled=has_camera
layout.prop(lanpr,"auto_update", text='Auto Update')
layout.prop(lanpr,"gpencil_overwrite", text='Overwrite')
if not lanpr.auto_update:
layout.operator("scene.lanpr_update_gp_strokes", icon='FILE_REFRESH', text='Update Grease Pencil Targets')
layout.operator("scene.lanpr_bake_gp_strokes", icon='RENDER_ANIMATION', text='Bake All Frames')
class RENDER_PT_lanpr_software_chain_styles(RenderButtonsPanel, Panel):
bl_label = "Chaining"
bl_parent_id = "RENDER_PT_lanpr"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
scene = context.scene
lanpr = scene.lanpr
return lanpr.enable_chaining and not (scene.render.engine=='BLENDER_LANPR' and lanpr.master_mode=='DPIX')
def draw(self, context):
scene = context.scene
lanpr = scene.lanpr
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
layout.prop(lanpr, "chaining_geometry_threshold")
layout.prop(lanpr, "chaining_image_threshold")
if scene.render.engine=="BLENDER_LANPR":
layout.prop(lanpr, "use_same_taper", text="Taper Tips")
if lanpr.use_same_taper == "DISABLED":
col = layout.column(align = True)
col.prop(lanpr,"taper_left_distance")
col.prop(lanpr,"taper_left_strength", text="Strength")
col = layout.column(align = True)
col.prop(lanpr,"taper_right_distance")
col.prop(lanpr,"taper_right_strength", text="Strength")
else:
col = layout.column(align = True)
col.prop(lanpr,"taper_left_distance", text="Distance")
col.prop(lanpr,"taper_left_strength", text="Strength")
class RENDER_PT_lanpr_options(RenderButtonsPanel, Panel):
bl_label = "Settings"
bl_parent_id = "RENDER_PT_lanpr"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_LANPR', 'BLENDER_OPENGL', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
return True
def draw(self, context):
scene = context.scene
lanpr = scene.lanpr
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
mode = lanpr.master_mode
if scene.render.engine!="BLENDER_LANPR":
mode = "SOFTWARE"
if mode == "DPIX":
layout.prop(lanpr,"gpu_cache_size")
layout.prop(lanpr,"use_intersections")
if scene.render.engine=='BLENDER_LANPR' and lanpr.master_mode=='SOFTWARE':
layout.prop(lanpr,"enable_chaining", text = "Chained Lines")
classes = (
RENDER_PT_context,
RENDER_PT_eevee_sampling,
@@ -714,6 +1146,16 @@ classes = (
RENDER_PT_simplify_viewport,
RENDER_PT_simplify_render,
RENDER_PT_simplify_greasepencil,
RENDER_PT_lanpr,
RENDER_PT_lanpr_layer_settings,
RENDER_PT_lanpr_gpencil,
RENDER_PT_lanpr_line_normal_effects,
RENDER_PT_lanpr_line_gpu_effects,
RENDER_PT_lanpr_snake_sobel_parameters,
RENDER_PT_lanpr_snake_settings,
RENDER_PT_lanpr_software_chain_styles,
RENDER_PT_lanpr_options,
LANPR_UL_linesets,
)
if __name__ == "__main__": # only for live edit.

View File

@@ -3462,7 +3462,7 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu):
col.operator("mesh.mark_sharp")
col.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
if render.use_freestyle:
if render.use_freestyle or scene.lanpr.enabled or render.engine=="BLENDER_LANPR":
col.separator()
col.operator("mesh.mark_freestyle_edge").clear = False
@@ -3653,11 +3653,11 @@ class VIEW3D_MT_edit_mesh_edges_data(Menu):
props.use_verts = True
props.clear = True
if render.use_freestyle:
if scene.lanpr.enabled or render.engine=="BLENDER_LANPR":
layout.separator()
layout.operator("mesh.mark_freestyle_edge").clear = False
layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
layout.operator("mesh.mark_lanpr_edge").clear = False
layout.operator("mesh.mark_lanpr_edge", text="Clear Freestyle Edge").clear = True
class VIEW3D_MT_edit_mesh_edges(Menu):
@@ -3713,8 +3713,8 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
if with_freestyle:
layout.separator()
layout.operator("mesh.mark_freestyle_edge").clear = False
layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
layout.operator("mesh.mark_lanpr_edge").clear = False
layout.operator("mesh.mark_lanpr_edge", text="Clear Freestyle Edge").clear = True
class VIEW3D_MT_edit_mesh_faces_data(Menu):
@@ -3735,11 +3735,11 @@ class VIEW3D_MT_edit_mesh_faces_data(Menu):
layout.operator("mesh.uvs_rotate")
layout.operator("mesh.uvs_reverse")
layout.separator()
if scene.lanpr.enabled or render.engine=="BLENDER_LANPR":
layout.separator()
if with_freestyle:
layout.operator("mesh.mark_freestyle_face").clear = False
layout.operator("mesh.mark_freestyle_face", text="Clear Freestyle Face").clear = True
layout.operator("mesh.mark_lanpr_face").clear = False
layout.operator("mesh.mark_lanpr_cface", text="Clear Freestyle Face").clear = True
class VIEW3D_MT_edit_mesh_faces(Menu):

View File

@@ -149,6 +149,10 @@ struct bGPDframe *BKE_gpencil_layer_getframe(struct bGPDlayer *gpl,
struct bGPDframe *BKE_gpencil_layer_find_frame(struct bGPDlayer *gpl, int cframe);
bool BKE_gpencil_layer_delframe(struct bGPDlayer *gpl, struct bGPDframe *gpf);
struct bGPDlayer *BKE_gpencil_layer_get_by_name(struct bGPdata *gpd,
char *name,
int first_if_not_found);
struct bGPDlayer *BKE_gpencil_layer_getactive(struct bGPdata *gpd);
void BKE_gpencil_layer_setactive(struct bGPdata *gpd, struct bGPDlayer *active);
void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl);
@@ -174,6 +178,8 @@ struct Material *BKE_gpencil_object_material_new(struct Main *bmain,
int BKE_gpencil_object_material_get_index(struct Object *ob, struct Material *ma);
int BKE_gpencil_object_material_get_index_name(struct Object *ob, char *name);
struct Material *BKE_gpencil_object_material_get_from_brush(struct Object *ob,
struct Brush *brush);
int BKE_gpencil_object_material_get_index_from_brush(struct Object *ob, struct Brush *brush);

View File

@@ -255,6 +255,11 @@ void BKE_scene_cursor_from_mat4(struct View3DCursor *cursor,
*/
void BKE_scene_eval_sequencer_sequences(struct Depsgraph *depsgraph, struct Scene *scene);
/* LANPR */
void BKE_lanpr_copy_data(const struct Scene *from, struct Scene *to);
void BKE_lanpr_free_everything(struct Scene *s);
#ifdef __cplusplus
}
#endif

View File

@@ -991,6 +991,31 @@ bGPDlayer *BKE_gpencil_layer_getactive(bGPdata *gpd)
return NULL;
}
bGPDlayer *BKE_gpencil_layer_get_by_name(bGPdata *gpd, char *name, int first_if_not_found)
{
bGPDlayer *gpl;
int i = 0;
/* error checking */
if (ELEM(NULL, gpd, gpd->layers.first)) {
return NULL;
}
/* loop over layers until found (assume only one active) */
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if (STREQ(name, gpl->info)) {
return gpl;
}
i++;
}
/* no such layer */
if (first_if_not_found) {
return gpd->layers.first;
}
return NULL;
}
/* set the active gp-layer */
void BKE_gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
{
@@ -2125,6 +2150,21 @@ int BKE_gpencil_object_material_get_index(Object *ob, Material *ma)
return -1;
}
int BKE_gpencil_object_material_get_index_name(Object *ob, char *name)
{
short *totcol = give_totcolp(ob);
Material *read_ma = NULL;
for (short i = 0; i < *totcol; i++) {
read_ma = give_current_material(ob, i + 1);
/* Material names are like "MAMaterial.001" */
if (STREQ(name, &read_ma->id.name[2])) {
return i;
}
}
return -1;
}
/* Get points of stroke always flat to view not affected by camera view or view position */
void BKE_gpencil_stroke_2d_flat(const bGPDspoint *points,
int totpoints,

View File

@@ -493,6 +493,8 @@ static void library_foreach_ID_link(Main *bmain,
CALLBACK_INVOKE(child->collection, IDWALK_CB_USER);
}
CALLBACK_INVOKE(scene->master_collection->lanpr.target, IDWALK_CB_USER);
ViewLayer *view_layer;
for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
CALLBACK_INVOKE(view_layer->mat_override, IDWALK_CB_USER);

View File

@@ -107,6 +107,7 @@
const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE";
const char *RE_engine_id_BLENDER_WORKBENCH = "BLENDER_WORKBENCH";
const char *RE_engine_id_BLENDER_LANPR = "BLENDER_LANPR";
const char *RE_engine_id_CYCLES = "CYCLES";
void free_avicodecdata(AviCodecData *acd)
@@ -227,6 +228,32 @@ void BKE_toolsettings_free(ToolSettings *toolsettings)
MEM_freeN(toolsettings);
}
void BKE_lanpr_copy_data(const Scene *from, Scene *to)
{
const SceneLANPR *lanpr = &from->lanpr;
LANPR_LineLayer *ll, *new_ll;
LANPR_LineLayerComponent *llc, *new_llc;
to->lanpr.line_layers.first = to->lanpr.line_layers.last = NULL;
memset(&to->lanpr.line_layers, 0, sizeof(ListBase));
for (ll = lanpr->line_layers.first; ll; ll = ll->next) {
new_ll = MEM_callocN(sizeof(LANPR_LineLayer), "Copied Line Layer");
memcpy(new_ll, ll, sizeof(LANPR_LineLayer));
memset(&new_ll->components, 0, sizeof(ListBase));
new_ll->next = new_ll->prev = NULL;
BLI_addtail(&to->lanpr.line_layers, new_ll);
for (llc = ll->components.first; llc; llc = llc->next) {
new_llc = MEM_callocN(sizeof(LANPR_LineLayerComponent), "Copied Line Layer Component");
memcpy(new_llc, llc, sizeof(LANPR_LineLayerComponent));
new_llc->next = new_llc->prev = NULL;
BLI_addtail(&new_ll->components, new_llc);
}
}
/* render_buffer now only accessible from lanpr_share */
}
/**
* Only copy internal data of Scene ID from source
* to already allocated/initialized destination.
@@ -342,6 +369,10 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
sce_dst->eevee.light_cache = NULL;
sce_dst->eevee.light_cache_info[0] = '\0';
/* TODO Copy the cache. */
/* lanpr data */
BKE_lanpr_copy_data(sce_src, sce_dst);
}
Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
@@ -478,6 +509,20 @@ void BKE_scene_make_local(Main *bmain, Scene *sce, const bool lib_local)
BKE_id_make_local_generic(bmain, &sce->id, true, lib_local);
}
void BKE_lanpr_free_everything(Scene *s)
{
SceneLANPR *lanpr = &s->lanpr;
LANPR_LineLayer *ll;
LANPR_LineLayerComponent *llc;
while ((ll = BLI_pophead(&lanpr->line_layers)) != NULL) {
while ((llc = BLI_pophead(&ll->components)) != NULL) {
MEM_freeN(llc);
}
MEM_freeN(ll);
}
}
/** Free (or release) any data used by this scene (does not free the scene itself). */
void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
{
@@ -733,6 +778,19 @@ void BKE_scene_init(Scene *sce)
sce->master_collection = BKE_collection_master_add();
BKE_view_layer_add(sce, "View Layer");
/* SceneLANPR */
sce->lanpr.crease_threshold = 0.7;
sce->lanpr.line_color[0] = 1;
sce->lanpr.line_color[1] = 1;
sce->lanpr.line_color[2] = 1;
sce->lanpr.line_color[3] = 1;
sce->lanpr.flags |= (LANPR_USE_CHAINING | LANPR_USE_INTERSECTIONS);
sce->lanpr.chaining_image_threshold = 0.01;
sce->lanpr.chaining_geometry_threshold = 0.1;
}
Scene *BKE_scene_add(Main *bmain, const char *name)

View File

@@ -78,6 +78,7 @@
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_lanpr_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_text_types.h"
#include "DNA_view3d_types.h"
@@ -6246,6 +6247,8 @@ static void lib_link_collection_data(FileData *fd, Library *lib, Collection *col
child->collection = newlibadr_us(fd, lib, child->collection);
}
collection->lanpr.target = newlibadr_us(fd, lib, collection->lanpr.target);
BKE_collection_parent_relations_rebuild(collection);
}
@@ -6558,6 +6561,16 @@ static void lib_link_scene(FileData *fd, Main *main)
fls->group = newlibadr_us(fd, sce->id.lib, fls->group);
}
}
for (LANPR_LineLayer *ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
for (LANPR_LineLayerComponent *llc = ll->components.first; llc; llc = llc->next) {
llc->object_select = newlibadr_us(fd, sce->id.lib, llc->object_select);
llc->material_select = newlibadr_us(fd, sce->id.lib, llc->material_select);
llc->collection_select = newlibadr_us(fd, sce->id.lib, llc->collection_select);
}
ll->normal_control_object = newlibadr_us(fd, sce->id.lib, ll->normal_control_object);
}
/* Motion Tracking */
sce->clip = newlibadr_us(fd, sce->id.lib, sce->clip);
@@ -6995,6 +7008,21 @@ static void direct_link_scene(FileData *fd, Scene *sce)
}
}
/* LANPR things */
sce->lanpr.active_layer = newdataadr(fd, sce->lanpr.active_layer);
link_list(fd, &sce->lanpr.line_layers);
for (LANPR_LineLayer *ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
link_list(fd, &ll->components);
for (LANPR_LineLayerComponent *llc = ll->components.first; llc; llc = llc->next) {
// llc->object_select = newlibadr(fd, sce->id.lib, llc->object_select);
// llc->material_select = newlibadr(fd, sce->id.lib, llc->material_select);
// llc->collection_select = newlibadr(fd, sce->id.lib, llc->collection_select);
}
ll->batch = NULL;
ll->shgrp = NULL;
// ll->normal_control_object = newlibadr(fd, sce->id.lib, ll->normal_control_object);
}
direct_link_view3dshading(fd, &sce->display.shading);
sce->layer_properties = newdataadr(fd, sce->layer_properties);
@@ -10323,6 +10351,8 @@ static void expand_collection(FileData *fd, Main *mainvar, Collection *collectio
expand_doit(fd, mainvar, child->collection);
}
expand_doit(fd, mainvar, collection->lanpr.target);
#ifdef USE_COLLECTION_COMPAT_28
if (collection->collection != NULL) {
expand_scene_collection(fd, mainvar, collection->collection);
@@ -10780,10 +10810,22 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
}
}
if (sce->gpd) {
expand_doit(fd, mainvar, sce->gpd);
for (LANPR_LineLayer *ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
for (LANPR_LineLayerComponent *llc = ll->components.first; llc; llc = llc->next) {
if (llc->object_select)
expand_doit(fd, mainvar, llc->object_select);
if (llc->material_select)
expand_doit(fd, mainvar, llc->material_select);
if (llc->collection_select)
expand_doit(fd, mainvar, llc->collection_select);
}
if (ll->normal_control_object)
expand_doit(fd, mainvar, ll->normal_control_object);
}
if (sce->gpd)
expand_doit(fd, mainvar, sce->gpd);
if (sce->ed) {
Sequence *seq;

View File

@@ -1799,7 +1799,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
scene->eevee.flag = SCE_EEVEE_VOLUMETRIC_LIGHTS | SCE_EEVEE_GTAO_BENT_NORMALS |
SCE_EEVEE_GTAO_BOUNCE | SCE_EEVEE_TAA_REPROJECTION |
SCE_EEVEE_SSR_HALF_RESOLUTION;
SCE_EEVEE_SSR_HALF_RESOLUTION | SCE_EEVEE_SHADOW_SOFT;
/* If the file is pre-2.80 move on. */
if (scene->layer_properties == NULL) {
@@ -1928,6 +1928,20 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
if (!DNA_struct_find(fd->filesdna, "SceneLANPR")) {
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
scene->lanpr.crease_threshold = 0.7;
scene->lanpr.flags |= (LANPR_USE_CHAINING | LANPR_USE_INTERSECTIONS);
scene->lanpr.line_color[0] = 0.39;
scene->lanpr.line_color[1] = 0.12;
scene->lanpr.line_color[2] = 0.04;
scene->lanpr.line_color[3] = 1;
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 280, 15)) {
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
scene->display.matcap_ssao_distance = 0.2f;
@@ -3630,6 +3644,22 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
do_versions_seq_alloc_transform_and_crop(&scene->ed->seqbase);
}
}
for (Scene *sce = bmain->scenes.first; sce; sce = sce->id.next) {
sce->lanpr.crease_threshold = 0.7;
zero_v4(sce->lanpr.line_color);
sce->lanpr.flags |= (LANPR_USE_CHAINING | LANPR_USE_INTERSECTIONS);
sce->lanpr.chaining_image_threshold = 0.01f;
sce->lanpr.chaining_geometry_threshold = 0.0f;
}
for (Collection *co = bmain->collections.first; co; co = co->id.next) {
co->lanpr.contour.use = 1;
co->lanpr.crease.use = 1;
co->lanpr.material.use = 1;
co->lanpr.edge_mark.use = 1;
co->lanpr.intersection.use = 1;
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 280, 75)) {

View File

@@ -121,6 +121,7 @@
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_lanpr_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_sdna_types.h"
@@ -2691,6 +2692,14 @@ static void write_scene(WriteData *wd, Scene *sce)
write_lightcache(wd, sce->eevee.light_cache);
}
/* LANPR Line Layers */
for (LANPR_LineLayer *ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
writestruct(wd, DATA, LANPR_LineLayer, 1, ll);
for (LANPR_LineLayerComponent *llc = ll->components.first; llc; llc = llc->next) {
writestruct(wd, DATA, LANPR_LineLayerComponent, 1, llc);
}
}
write_view3dshading(wd, &sce->display.shading);
/* Freed on doversion. */

View File

@@ -133,6 +133,10 @@ set(SRC
engines/gpencil/gpencil_engine.h
engines/gpencil/gpencil_render.c
engines/gpencil/gpencil_shader_fx.c
engines/lanpr/lanpr_dpix.c
engines/lanpr/lanpr_engine.c
engines/lanpr/lanpr_cpu.c
engines/lanpr/lanpr_chain_draw.c
engines/select/select_draw_utils.c
engines/select/select_engine.c
@@ -161,6 +165,7 @@ set(SRC
engines/external/external_engine.h
engines/workbench/workbench_engine.h
engines/workbench/workbench_private.h
engines/lanpr/lanpr_all.h
engines/select/select_engine.h
engines/select/select_private.h
)
@@ -259,6 +264,21 @@ data_to_c_simple(engines/workbench/shaders/workbench_volume_vert.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_volume_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_world_light_lib.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_dpix_preview_geom.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_dpix_preview_frag.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_dpix_project_clip_frag.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_dpix_project_passthrough_vert.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_snake_image_peel_frag.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_snake_line_connection_vert.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_snake_line_connection_geom.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_snake_line_connection_frag.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_snake_edge_frag.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_snake_multichannel_frag.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_software_line_chain_geom.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_software_passthrough_vert.glsl SRC)
data_to_c_simple(engines/lanpr/shaders/lanpr_software_chain_geom.glsl SRC)
data_to_c_simple(modes/shaders/common_colormanagement_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_hair_lib.glsl SRC)

View File

@@ -0,0 +1,266 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*
*/
/** \file
* \ingroup draw
*/
#ifndef __LANPR_ALL_H__
#define __LANPR_ALL_H__
#include "BLI_mempool.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BKE_customdata.h"
#include "BKE_object.h"
#include "DEG_depsgraph_query.h"
#include "DNA_camera_types.h"
#include "DNA_listBase.h"
#include "DNA_lanpr_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DRW_render.h"
#include "ED_lanpr.h"
#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_framebuffer.h"
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "GPU_uniformbuffer.h"
#include "GPU_viewport.h"
#include "WM_types.h"
#include "WM_api.h"
#include "bmesh.h"
#define LANPR_ENGINE "BLENDER_LANPR"
#define deg(r) r / M_PI * 180.0
#define rad(d) d *M_PI / 180.0
#define tMatDist2v(p1, p2) \
sqrt(((p1)[0] - (p2)[0]) * ((p1)[0] - (p2)[0]) + ((p1)[1] - (p2)[1]) * ((p1)[1] - (p2)[1]))
extern struct RenderEngineType DRW_engine_viewport_lanpr_type;
extern struct DrawEngineType draw_engine_lanpr_type;
typedef struct LANPR_RenderBuffer LANPR_RenderBuffer;
typedef struct LANPR_PassList {
/* Image filtering */
struct DRWPass *depth_pass;
struct DRWPass *color_pass;
struct DRWPass *normal_pass;
struct DRWPass *edge_intermediate;
struct DRWPass *edge_thinning;
struct DRWPass *snake_pass;
/* GPU */
struct DRWPass *dpix_transform_pass;
struct DRWPass *dpix_preview_pass;
/* SOFTWARE */
struct DRWPass *software_pass;
} LANPR_PassList;
typedef struct LANPR_FramebufferList {
/* CPU */
struct GPUFrameBuffer *passes;
struct GPUFrameBuffer *edge_intermediate;
struct GPUFrameBuffer *edge_thinning;
/* GPU */
struct GPUFrameBuffer *dpix_transform;
struct GPUFrameBuffer *dpix_preview;
/* Image filtering */
struct GPUFrameBuffer *software_ms;
} LANPR_FramebufferList;
typedef struct LANPR_TextureList {
struct GPUTexture *color;
struct GPUTexture *normal;
struct GPUTexture *depth;
struct GPUTexture *edge_intermediate;
struct GPUTexture *dpix_in_pl;
struct GPUTexture *dpix_in_pr;
struct GPUTexture *dpix_in_nl;
struct GPUTexture *dpix_in_nr;
/** RGBA texture format,
* R:Material, G: Freestyle Edge Mark,
* BA:Reserved for future usages */
struct GPUTexture *dpix_in_edge_mask;
struct GPUTexture *dpix_out_pl;
struct GPUTexture *dpix_out_pr;
struct GPUTexture *dpix_out_length;
/** Multisample resolve */
struct GPUTexture *ms_resolve_depth;
struct GPUTexture *ms_resolve_color;
} LANPR_TextureList;
typedef struct LANPR_PrivateData {
DRWShadingGroup *multipass_shgrp;
DRWShadingGroup *edge_detect_shgrp;
DRWShadingGroup *edge_thinning_shgrp;
DRWShadingGroup *snake_shgrp;
DRWShadingGroup *dpix_transform_shgrp;
DRWShadingGroup *dpix_preview_shgrp;
DRWShadingGroup *debug_shgrp;
/* Image filtering */
float normal_clamp;
float normal_strength;
float depth_clamp;
float depth_strength;
float zfar;
float znear;
/** Thinning stage */
int stage;
float *line_result;
unsigned char *line_result_8bit;
/** If not match then recreate buffer. */
int width, height;
void **sample_table;
ListBase pending_samples;
ListBase erased_samples;
ListBase line_strips;
/* dpix data */
void *atlas_pl;
void *atlas_pr;
void *atlas_nl;
void *atlas_nr;
void *atlas_edge_mask;
int begin_index;
int dpix_sample_step;
int dpix_is_perspective;
float dpix_viewport[4];
float output_viewport[4];
int dpix_buffer_width;
float dpix_depth_offset;
float dpix_znear;
float dpix_zfar;
/* drawing */
unsigned v_buf;
unsigned i_buf;
unsigned l_buf;
GPUVertFormat snake_gwn_format;
GPUBatch *snake_batch;
} LANPR_PrivateData;
typedef struct LANPR_StorageList {
LANPR_PrivateData *g_data;
} LANPR_StorageList;
typedef struct LANPR_BatchItem {
Link item;
GPUBatch *dpix_transform_batch;
GPUBatch *dpix_preview_batch;
Object *ob;
} LANPR_BatchItem;
typedef struct LANPR_Data {
void *engine_type;
LANPR_FramebufferList *fbl;
LANPR_TextureList *txl;
LANPR_PassList *psl;
LANPR_StorageList *stl;
} LANPR_Data;
/* functions */
void lanpr_init_atlas_inputs(void *ved);
void lanpr_destroy_atlas(void *ved);
int lanpr_feed_atlas_data_obj(void *vedata,
float *AtlasPointsL,
float *AtlasPointsR,
float *AtlasFaceNormalL,
float *AtlasFaceNormalR,
float *AtlasEdgeMask,
Object *ob,
int begin_index);
int lanpr_feed_atlas_data_intersection_cache(void *vedata,
float *AtlasPointsL,
float *AtlasPointsR,
float *AtlasFaceNormalL,
float *AtlasFaceNormalR,
float *AtlasEdgeMask,
int begin_index);
int lanpr_feed_atlas_trigger_preview_obj(void *vedata, Object *ob, int begin_index);
void lanpr_create_atlas_intersection_preview(void *vedata, int begin_index);
void lanpr_dpix_draw_scene(LANPR_TextureList *txl,
LANPR_FramebufferList *fbl,
LANPR_PassList *psl,
LANPR_PrivateData *pd,
SceneLANPR *lanpr,
GPUFrameBuffer *DefaultFB,
int is_render);
void lanpr_snake_draw_scene(LANPR_TextureList *txl,
LANPR_FramebufferList *fbl,
LANPR_PassList *psl,
LANPR_PrivateData *pd,
SceneLANPR *lanpr,
GPUFrameBuffer *DefaultFB,
int is_render);
void lanpr_software_draw_scene(void *vedata, GPUFrameBuffer *dfb, int is_render);
int lanpr_dpix_texture_size(SceneLANPR *lanpr);
void lanpr_chain_generate_draw_command(struct LANPR_RenderBuffer *rb);
#endif

View File

@@ -0,0 +1,196 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*
*/
/** \file
* \ingroup draw
*/
#include "BKE_customdata.h"
#include "BKE_object.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "DEG_depsgraph_query.h"
#include "DNA_camera_types.h"
#include "DNA_lanpr_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DRW_engine.h"
#include "DRW_render.h"
#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_shader.h"
#include "GPU_uniformbuffer.h"
#include "GPU_viewport.h"
#include "lanpr_all.h"
#include "bmesh.h"
#include <math.h>
static float ED_lanpr_compute_chain_length_draw(LANPR_RenderLineChain *rlc,
float *lengths,
int begin_index)
{
LANPR_RenderLineChainItem *rlci;
int i = 0;
float offset_accum = 0;
float dist;
float last_point[2];
rlci = rlc->chain.first;
copy_v2_v2(last_point, rlci->pos);
for (rlci = rlc->chain.first; rlci; rlci = rlci->next) {
dist = len_v2v2(rlci->pos, last_point);
offset_accum += dist;
lengths[begin_index + i] = offset_accum;
copy_v2_v2(last_point, rlci->pos);
i++;
}
return offset_accum;
}
static int lanpr_get_gpu_line_type(LANPR_RenderLineChainItem *rlci)
{
switch (rlci->line_type) {
case LANPR_EDGE_FLAG_CONTOUR:
return 0;
case LANPR_EDGE_FLAG_CREASE:
return 1;
case LANPR_EDGE_FLAG_MATERIAL:
return 2;
case LANPR_EDGE_FLAG_EDGE_MARK:
return 3;
case LANPR_EDGE_FLAG_INTERSECTION:
return 4;
default:
return 0;
}
}
void lanpr_chain_generate_draw_command(LANPR_RenderBuffer *rb)
{
LANPR_RenderLineChain *rlc;
LANPR_RenderLineChainItem *rlci;
int vert_count = 0;
int i = 0;
int arg;
float total_length;
float *lengths;
float length_target[2];
static GPUVertFormat format = {0};
static struct {
uint pos, uvs, normal, type, level;
} attr_id;
if (format.attr_len == 0) {
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
attr_id.uvs = GPU_vertformat_attr_add(&format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
attr_id.normal = GPU_vertformat_attr_add(&format, "normal", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
attr_id.type = GPU_vertformat_attr_add(&format, "type", GPU_COMP_I32, 1, GPU_FETCH_INT);
attr_id.level = GPU_vertformat_attr_add(&format, "level", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
for (rlc = rb->chains.first; rlc; rlc = rlc->next) {
int count = ED_lanpr_count_chain(rlc);
/* printf("seg contains %d verts\n", count); */
vert_count += count;
}
GPU_vertbuf_data_alloc(vbo, vert_count + 1); /* serve as end point's adj. */
lengths = MEM_callocN(sizeof(float) * vert_count, "chain lengths");
GPUIndexBufBuilder elb;
GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINES_ADJ, vert_count * 4, vert_count);
for (rlc = rb->chains.first; rlc; rlc = rlc->next) {
total_length = ED_lanpr_compute_chain_length_draw(rlc, lengths, i);
for (rlci = rlc->chain.first; rlci; rlci = rlci->next) {
length_target[0] = lengths[i];
length_target[1] = total_length - lengths[i];
GPU_vertbuf_attr_set(vbo, attr_id.pos, i, rlci->pos);
GPU_vertbuf_attr_set(vbo, attr_id.normal, i, rlci->normal);
GPU_vertbuf_attr_set(vbo, attr_id.uvs, i, length_target);
arg = lanpr_get_gpu_line_type(rlci);
GPU_vertbuf_attr_set(vbo, attr_id.type, i, &arg);
arg = (int)rlci->occlusion;
GPU_vertbuf_attr_set(vbo, attr_id.level, i, &arg);
if (rlci == rlc->chain.last) {
if (rlci->prev == rlc->chain.first) {
length_target[1] = total_length;
GPU_vertbuf_attr_set(vbo, attr_id.uvs, i, length_target);
}
i++;
continue;
}
if (rlci == rlc->chain.first) {
if (rlci->next == rlc->chain.last) {
GPU_indexbuf_add_line_adj_verts(&elb, vert_count, i, i + 1, vert_count);
}
else {
GPU_indexbuf_add_line_adj_verts(&elb, vert_count, i, i + 1, i + 2);
}
}
else {
if (rlci->next == rlc->chain.last) {
GPU_indexbuf_add_line_adj_verts(&elb, i - 1, i, i + 1, vert_count);
}
else {
GPU_indexbuf_add_line_adj_verts(&elb, i - 1, i, i + 1, i + 2);
}
}
i++;
}
}
/* set end point flag value. */
length_target[0] = 3e30f;
length_target[1] = 3e30f;
GPU_vertbuf_attr_set(vbo, attr_id.pos, vert_count, length_target);
MEM_freeN(lengths);
if (rb->chain_draw_batch) {
GPU_BATCH_DISCARD_SAFE(rb->chain_draw_batch);
}
rb->chain_draw_batch = GPU_batch_create_ex(GPU_PRIM_LINES_ADJ,
vbo,
GPU_indexbuf_build(&elb),
GPU_USAGE_DYNAMIC | GPU_BATCH_OWNS_VBO |
GPU_BATCH_OWNS_INDEX);
}

View File

@@ -0,0 +1,514 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*
*/
/** \file
* \ingroup draw
*/
#include "DNA_camera_types.h"
#include "DNA_lanpr_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_text_types.h"
#include "DRW_engine.h"
#include "DRW_render.h"
#include "DEG_depsgraph_query.h"
#include "ED_lanpr.h"
#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "BLI_math_matrix.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_camera.h"
#include "BKE_customdata.h"
#include "BKE_collection.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_text.h"
#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_framebuffer.h"
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_shader.h"
#include "GPU_uniformbuffer.h"
#include "GPU_viewport.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_types.h"
#include "WM_api.h"
#include "bmesh.h"
#include "bmesh_class.h"
#include "bmesh_tools.h"
#include "lanpr_all.h"
#include <math.h>
extern LANPR_SharedResource lanpr_share;
extern const char *RE_engine_id_BLENDER_LANPR;
static void lanpr_rebuild_render_draw_command(LANPR_RenderBuffer *rb, LANPR_LineLayer *ll)
{
int Count = 0;
float *v, *tv, *N, *tn;
int i;
int vertCount;
static GPUVertFormat format = {0};
static struct {
uint pos, normal;
} attr_id;
if (format.attr_len == 0) {
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
attr_id.normal = GPU_vertformat_attr_add(&format, "normal", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
if (ll->contour.use) {
Count += ED_lanpr_count_leveled_edge_segment_count(&rb->contours, ll);
}
if (ll->crease.use) {
Count += ED_lanpr_count_leveled_edge_segment_count(&rb->crease_lines, ll);
}
if (ll->intersection.use) {
Count += ED_lanpr_count_leveled_edge_segment_count(&rb->intersection_lines, ll);
}
if (ll->edge_mark.use) {
Count += ED_lanpr_count_leveled_edge_segment_count(&rb->edge_marks, ll);
}
if (ll->material_separate.use) {
Count += ED_lanpr_count_leveled_edge_segment_count(&rb->material_lines, ll);
}
vertCount = Count * 2;
if (!vertCount) {
return;
}
GPU_vertbuf_data_alloc(vbo, vertCount);
tv = v = MEM_callocN(sizeof(float) * 6 * Count, "temp v data");
tn = N = MEM_callocN(sizeof(float) * 6 * Count, "temp n data");
if (ll->contour.use) {
tv = ED_lanpr_make_leveled_edge_vertex_array(rb, &rb->contours, tv, tn, &tn, ll, 1.0f);
}
if (ll->crease.use) {
tv = ED_lanpr_make_leveled_edge_vertex_array(rb, &rb->crease_lines, tv, tn, &tn, ll, 2.0f);
}
if (ll->material_separate.use) {
tv = ED_lanpr_make_leveled_edge_vertex_array(rb, &rb->material_lines, tv, tn, &tn, ll, 3.0f);
}
if (ll->edge_mark.use) {
tv = ED_lanpr_make_leveled_edge_vertex_array(rb, &rb->edge_marks, tv, tn, &tn, ll, 4.0f);
}
if (ll->intersection.use) {
tv = ED_lanpr_make_leveled_edge_vertex_array(
rb, &rb->intersection_lines, tv, tn, &tn, ll, 5.0f);
}
for (i = 0; i < vertCount; i++) {
GPU_vertbuf_attr_set(vbo, attr_id.pos, i, &v[i * 3]);
GPU_vertbuf_attr_set(vbo, attr_id.normal, i, &N[i * 3]);
}
MEM_freeN(v);
MEM_freeN(N);
ll->batch = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, 0, GPU_USAGE_DYNAMIC | GPU_BATCH_OWNS_VBO);
}
void ED_lanpr_rebuild_all_command(SceneLANPR *lanpr)
{
LANPR_LineLayer *ll;
if (!lanpr || !lanpr_share.render_buffer_shared) {
return;
}
if (lanpr->flags & LANPR_USE_CHAINING) {
lanpr_chain_generate_draw_command(lanpr_share.render_buffer_shared);
}
else {
for (ll = lanpr->line_layers.first; ll; ll = ll->next) {
if (ll->batch) {
GPU_batch_discard(ll->batch);
}
lanpr_rebuild_render_draw_command(lanpr_share.render_buffer_shared, ll);
}
}
DEG_id_tag_update(&lanpr_share.render_buffer_shared->scene->id, ID_RECALC_COPY_ON_WRITE);
}
void ED_lanpr_calculate_normal_object_vector(LANPR_LineLayer *ll, float *normal_object_direction)
{
Object *ob;
if (!(ll->flags & LANPR_LINE_LAYER_NORMAL_ENABLED)) {
return;
}
switch (ll->normal_mode) {
case LANPR_NORMAL_DIRECTIONAL:
if (!(ob = ll->normal_control_object)) {
normal_object_direction[0] = 0;
normal_object_direction[1] = 0;
normal_object_direction[2] = 1; /* default z up direction */
}
else {
float dir[3] = {0, 0, 1};
float mat[3][3];
copy_m3_m4(mat, ob->obmat);
mul_v3_m3v3(normal_object_direction, mat, dir);
normalize_v3(normal_object_direction);
}
return;
case LANPR_NORMAL_POINT:
if (!(ob = ll->normal_control_object)) {
normal_object_direction[0] = 0;
normal_object_direction[1] = 0;
normal_object_direction[2] = 0; /* default origin position */
}
else {
normal_object_direction[0] = ob->obmat[3][0];
normal_object_direction[1] = ob->obmat[3][1];
normal_object_direction[2] = ob->obmat[3][2];
}
return;
}
}
void lanpr_software_draw_scene(void *vedata, GPUFrameBuffer *dfb, int is_render)
{
LANPR_LineLayer *ll;
LANPR_PassList *psl = ((LANPR_Data *)vedata)->psl;
LANPR_TextureList *txl = ((LANPR_Data *)vedata)->txl;
LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
LANPR_FramebufferList *fbl = ((LANPR_Data *)vedata)->fbl;
LANPR_PrivateData *pd = stl->g_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
SceneLANPR *lanpr = &scene->lanpr;
View3D *v3d = draw_ctx->v3d;
float indentity_mat[4][4];
static float normal_object_direction[3] = {0, 0, 1};
float use_background_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
static float camdx, camdy, camzoom;
if (is_render) {
ED_lanpr_rebuild_all_command(lanpr);
}
float clear_depth = 1.0f;
uint clear_stencil = 0xFF;
eGPUFrameBufferBits clear_bits = GPU_DEPTH_BIT | GPU_COLOR_BIT;
static int zero_value = 0;
copy_v3_v3(use_background_color, &scene->world->horr);
use_background_color[3] = scene->r.alphamode ? 0.0f : 1.0f;
GPU_framebuffer_bind(fbl->software_ms);
GPU_framebuffer_clear(
fbl->software_ms, clear_bits, use_background_color, clear_depth, clear_stencil);
if (lanpr_share.render_buffer_shared) {
int texw = GPU_texture_width(txl->ms_resolve_color),
texh = GPU_texture_height(txl->ms_resolve_color);
;
pd->output_viewport[2] = scene->r.xsch;
pd->output_viewport[3] = scene->r.ysch;
pd->dpix_viewport[2] = texw;
pd->dpix_viewport[3] = texh;
unit_m4(indentity_mat);
DRWView *view = DRW_view_create(indentity_mat, indentity_mat, NULL, NULL, NULL);
if (is_render) {
DRW_view_default_set(view);
}
else {
DRW_view_set_active(view);
}
RegionView3D *rv3d = v3d ? draw_ctx->rv3d : NULL;
if (rv3d) {
camdx = rv3d->camdx;
camdy = rv3d->camdy;
camzoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
}
else {
camdx = camdy = 0.0f;
camzoom = 1.0f;
}
if ((lanpr->flags & LANPR_USE_CHAINING) &&
lanpr_share.render_buffer_shared->chain_draw_batch) {
for (ll = lanpr->line_layers.last; ll; ll = ll->prev) {
LANPR_RenderBuffer *rb;
psl->software_pass = DRW_pass_create("Software Render Preview",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
DRW_STATE_DEPTH_LESS_EQUAL);
rb = lanpr_share.render_buffer_shared;
rb->ChainShgrp = DRW_shgroup_create(lanpr_share.software_chaining_shader,
psl->software_pass);
ED_lanpr_calculate_normal_object_vector(ll, normal_object_direction);
DRW_shgroup_uniform_float(rb->ChainShgrp, "camdx", &camdx, 1);
DRW_shgroup_uniform_float(rb->ChainShgrp, "camdy", &camdy, 1);
DRW_shgroup_uniform_float(rb->ChainShgrp, "camzoom", &camzoom, 1);
DRW_shgroup_uniform_vec4(rb->ChainShgrp,
"contour_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color :
ll->contour.color,
1);
DRW_shgroup_uniform_vec4(rb->ChainShgrp,
"crease_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color :
ll->crease.color,
1);
DRW_shgroup_uniform_vec4(rb->ChainShgrp,
"material_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
ll->color :
ll->material_separate.color,
1);
DRW_shgroup_uniform_vec4(
rb->ChainShgrp,
"edge_mark_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->edge_mark.color,
1);
DRW_shgroup_uniform_vec4(
rb->ChainShgrp,
"intersection_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->intersection.color,
1);
static float unit_thickness = 1.0f;
DRW_shgroup_uniform_float(rb->ChainShgrp, "thickness", &ll->thickness, 1);
DRW_shgroup_uniform_float(rb->ChainShgrp,
"thickness_contour",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->contour.thickness,
1);
DRW_shgroup_uniform_float(rb->ChainShgrp,
"thickness_crease",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->crease.thickness,
1);
DRW_shgroup_uniform_float(rb->ChainShgrp,
"thickness_material",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->material_separate.thickness,
1);
DRW_shgroup_uniform_float(rb->ChainShgrp,
"thickness_edge_mark",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->edge_mark.thickness,
1);
DRW_shgroup_uniform_float(rb->ChainShgrp,
"thickness_intersection",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->intersection.thickness,
1);
DRW_shgroup_uniform_int(rb->ChainShgrp, "use_contour", &ll->contour.use, 1);
DRW_shgroup_uniform_int(rb->ChainShgrp, "use_crease", &ll->crease.use, 1);
DRW_shgroup_uniform_int(rb->ChainShgrp, "use_material", &ll->material_separate.use, 1);
DRW_shgroup_uniform_int(rb->ChainShgrp, "use_edge_mark", &ll->edge_mark.use, 1);
DRW_shgroup_uniform_int(rb->ChainShgrp, "use_intersection", &ll->intersection.use, 1);
static int normal_effect_inverse;
normal_effect_inverse = (ll->flags & LANPR_LINE_LAYER_NORMAL_INVERSE) ? 1 : 0;
DRW_shgroup_uniform_int(rb->ChainShgrp,
"normal_mode",
(ll->flags & LANPR_LINE_LAYER_NORMAL_ENABLED) ? &ll->normal_mode :
&zero_value,
1);
DRW_shgroup_uniform_int(
rb->ChainShgrp, "normal_effect_inverse", &normal_effect_inverse, 1);
DRW_shgroup_uniform_float(rb->ChainShgrp, "normal_ramp_begin", &ll->normal_ramp_begin, 1);
DRW_shgroup_uniform_float(rb->ChainShgrp, "normal_ramp_end", &ll->normal_ramp_end, 1);
DRW_shgroup_uniform_float(
rb->ChainShgrp, "normal_thickness_start", &ll->normal_thickness_start, 1);
DRW_shgroup_uniform_float(
rb->ChainShgrp, "normal_thickness_end", &ll->normal_thickness_end, 1);
DRW_shgroup_uniform_vec3(rb->ChainShgrp, "normal_direction", normal_object_direction, 1);
DRW_shgroup_uniform_int(rb->ChainShgrp, "occlusion_level_start", &ll->level_start, 1);
DRW_shgroup_uniform_int(
rb->ChainShgrp,
"occlusion_level_end",
(ll->flags & LANPR_LINE_LAYER_USE_MULTIPLE_LEVELS) ? &ll->level_end : &ll->level_start,
1);
DRW_shgroup_uniform_vec4(
rb->ChainShgrp, "preview_viewport", stl->g_data->dpix_viewport, 1);
DRW_shgroup_uniform_vec4(
rb->ChainShgrp, "output_viewport", stl->g_data->output_viewport, 1);
float *tld = &lanpr->taper_left_distance, *tls = &lanpr->taper_left_strength,
*trd = &lanpr->taper_right_distance, *trs = &lanpr->taper_right_strength;
DRW_shgroup_uniform_float(rb->ChainShgrp, "taper_l_dist", tld, 1);
DRW_shgroup_uniform_float(rb->ChainShgrp, "taper_l_strength", tls, 1);
DRW_shgroup_uniform_float(
rb->ChainShgrp, "taper_r_dist", (lanpr->flags & LANPR_SAME_TAPER) ? tld : trd, 1);
DRW_shgroup_uniform_float(
rb->ChainShgrp, "taper_r_strength", (lanpr->flags & LANPR_SAME_TAPER) ? tls : trs, 1);
/* need to add component enable/disable option. */
DRW_shgroup_call(rb->ChainShgrp, lanpr_share.render_buffer_shared->chain_draw_batch, NULL);
/* debug purpose */
/* DRW_draw_pass(psl->color_pass); */
/* DRW_draw_pass(psl->color_pass); */
DRW_draw_pass(psl->software_pass);
}
}
else if (!(lanpr->flags & LANPR_USE_CHAINING)) {
for (ll = lanpr->line_layers.last; ll; ll = ll->prev) {
if (ll->batch) {
psl->software_pass = DRW_pass_create("Software Render Preview",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
DRW_STATE_DEPTH_LESS_EQUAL);
ll->shgrp = DRW_shgroup_create(lanpr_share.software_shader, psl->software_pass);
ED_lanpr_calculate_normal_object_vector(ll, normal_object_direction);
DRW_shgroup_uniform_float(ll->shgrp, "camdx", &camdx, 1);
DRW_shgroup_uniform_float(ll->shgrp, "camdy", &camdy, 1);
DRW_shgroup_uniform_float(ll->shgrp, "camzoom", &camzoom, 1);
DRW_shgroup_uniform_vec4(
ll->shgrp,
"contour_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->contour.color,
1);
DRW_shgroup_uniform_vec4(
ll->shgrp,
"crease_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->crease.color,
1);
DRW_shgroup_uniform_vec4(ll->shgrp,
"material_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
ll->color :
ll->material_separate.color,
1);
DRW_shgroup_uniform_vec4(
ll->shgrp,
"edge_mark_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->edge_mark.color,
1);
DRW_shgroup_uniform_vec4(
ll->shgrp,
"intersection_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->intersection.color,
1);
static float uniform_thickness = 1.0f;
DRW_shgroup_uniform_float(ll->shgrp, "thickness", &ll->thickness, 1);
DRW_shgroup_uniform_float(ll->shgrp,
"thickness_contour",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&uniform_thickness :
&ll->contour.thickness,
1);
DRW_shgroup_uniform_float(ll->shgrp,
"thickness_crease",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&uniform_thickness :
&ll->crease.thickness,
1);
DRW_shgroup_uniform_float(ll->shgrp,
"thickness_material",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&uniform_thickness :
&ll->material_separate.thickness,
1);
DRW_shgroup_uniform_float(ll->shgrp,
"thickness_edge_mark",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&uniform_thickness :
&ll->edge_mark.thickness,
1);
DRW_shgroup_uniform_float(ll->shgrp,
"thickness_intersection",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&uniform_thickness :
&ll->intersection.thickness,
1);
DRW_shgroup_uniform_vec4(ll->shgrp, "preview_viewport", stl->g_data->dpix_viewport, 1);
DRW_shgroup_uniform_vec4(ll->shgrp, "output_viewport", stl->g_data->output_viewport, 1);
static int normal_effect_inverse;
normal_effect_inverse = (ll->flags & LANPR_LINE_LAYER_NORMAL_INVERSE) ? 1 : 0;
DRW_shgroup_uniform_int(
ll->shgrp,
"normal_mode",
(ll->flags & LANPR_LINE_LAYER_NORMAL_ENABLED) ? &ll->normal_mode : &zero_value,
1);
DRW_shgroup_uniform_int(ll->shgrp, "normal_effect_inverse", &normal_effect_inverse, 1);
DRW_shgroup_uniform_float(ll->shgrp, "normal_ramp_begin", &ll->normal_ramp_begin, 1);
DRW_shgroup_uniform_float(ll->shgrp, "normal_ramp_end", &ll->normal_ramp_end, 1);
DRW_shgroup_uniform_float(
ll->shgrp, "normal_thickness_start", &ll->normal_thickness_start, 1);
DRW_shgroup_uniform_float(
ll->shgrp, "normal_thickness_end", &ll->normal_thickness_end, 1);
DRW_shgroup_uniform_vec3(ll->shgrp, "normal_direction", normal_object_direction, 1);
DRW_shgroup_call(ll->shgrp, ll->batch, NULL);
DRW_draw_pass(psl->software_pass);
}
}
}
}
GPU_framebuffer_blit(fbl->software_ms, 0, dfb, 0, GPU_COLOR_BIT);
if (!is_render) {
DRW_view_set_active(NULL);
}
}
void ED_lanpr_update_render_progress(const char *text)
{
if (lanpr_share.re_render) {
RE_engine_update_stats(lanpr_share.re_render, NULL, text);
}
}

View File

@@ -0,0 +1,553 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*
*/
/** \file
* \ingroup draw
*/
#include "BKE_customdata.h"
#include "BKE_object.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "DEG_depsgraph_query.h"
#include "DNA_camera_types.h"
#include "DNA_lanpr_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DRW_engine.h"
#include "DRW_render.h"
#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_shader.h"
#include "GPU_uniformbuffer.h"
#include "GPU_viewport.h"
#include "lanpr_all.h"
#include "bmesh.h"
#include <math.h>
extern LANPR_SharedResource lanpr_share;
extern char datatoc_lanpr_dpix_project_passthrough_vert_glsl[];
extern char datatoc_lanpr_dpix_project_clip_frag_glsl[];
extern char datatoc_lanpr_dpix_preview_geom_glsl[];
extern char datatoc_lanpr_dpix_preview_frag_glsl[];
int lanpr_dpix_texture_size(SceneLANPR *lanpr)
{
switch (lanpr->gpu_cache_size) {
case LANPR_GPU_CACHE_SIZE_512:
return 512;
case LANPR_GPU_CACHE_SIZE_1K:
return 1024;
case LANPR_GPU_CACHE_SIZE_2K:
return 2048;
case LANPR_GPU_CACHE_SIZE_4K:
return 4096;
}
return 512;
}
void lanpr_init_atlas_inputs(void *ved)
{
lanpr_share.ved_viewport = ved;
LANPR_Data *vedata = (LANPR_Data *)ved;
LANPR_TextureList *txl = vedata->txl;
LANPR_FramebufferList *fbl = vedata->fbl;
const DRWContextState *draw_ctx = DRW_context_state_get();
SceneLANPR *lanpr = &draw_ctx->scene->lanpr;
int texture_size = lanpr_dpix_texture_size(lanpr);
lanpr_share.texture_size = texture_size;
if (txl->dpix_in_pl && GPU_texture_width(txl->dpix_in_pl) != texture_size) {
DRW_texture_free(txl->dpix_in_pl);
txl->dpix_in_pl = NULL;
DRW_texture_free(txl->dpix_in_pr);
txl->dpix_in_pr = NULL;
DRW_texture_free(txl->dpix_in_nl);
txl->dpix_in_nl = NULL;
DRW_texture_free(txl->dpix_in_nr);
txl->dpix_in_nr = NULL;
DRW_texture_free(txl->dpix_out_pl);
txl->dpix_out_pl = NULL;
DRW_texture_free(txl->dpix_out_pr);
txl->dpix_out_pr = NULL;
DRW_texture_free(txl->dpix_out_length);
txl->dpix_out_length = NULL;
}
if (lanpr_share.dpix_reloaded || !txl->dpix_in_pl) {
DRW_texture_ensure_2d(&txl->dpix_in_pl, texture_size, texture_size, GPU_RGBA32F, 0);
DRW_texture_ensure_2d(&txl->dpix_in_pr, texture_size, texture_size, GPU_RGBA32F, 0);
DRW_texture_ensure_2d(&txl->dpix_in_nl, texture_size, texture_size, GPU_RGBA32F, 0);
DRW_texture_ensure_2d(&txl->dpix_in_nr, texture_size, texture_size, GPU_RGBA32F, 0);
DRW_texture_ensure_2d(&txl->dpix_in_edge_mask, texture_size, texture_size, GPU_RGBA8, 0);
DRW_texture_ensure_2d(&txl->dpix_out_pl, texture_size, texture_size, GPU_RGBA32F, 0);
DRW_texture_ensure_2d(&txl->dpix_out_pr, texture_size, texture_size, GPU_RGBA32F, 0);
DRW_texture_ensure_2d(&txl->dpix_out_length, texture_size, texture_size, GPU_RGBA32F, 0);
}
GPU_framebuffer_ensure_config(&fbl->dpix_transform,
{GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_TEXTURE(txl->dpix_out_pl),
GPU_ATTACHMENT_TEXTURE(txl->dpix_out_pr),
GPU_ATTACHMENT_TEXTURE(txl->dpix_out_length),
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE});
GPU_framebuffer_ensure_config(&fbl->dpix_preview,
{GPU_ATTACHMENT_TEXTURE(txl->depth),
GPU_ATTACHMENT_TEXTURE(txl->color),
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_LEAVE});
if (!lanpr_share.dpix_transform_shader) {
lanpr_share.dpix_transform_shader = DRW_shader_create(
datatoc_lanpr_dpix_project_passthrough_vert_glsl,
NULL,
datatoc_lanpr_dpix_project_clip_frag_glsl,
NULL);
if (!lanpr_share.dpix_transform_shader) {
lanpr_share.dpix_shader_error = 1;
printf("LANPR: DPIX transform shader compile error.");
}
}
if (!lanpr_share.dpix_preview_shader) {
lanpr_share.dpix_preview_shader = DRW_shader_create(
datatoc_lanpr_dpix_project_passthrough_vert_glsl,
datatoc_lanpr_dpix_preview_geom_glsl,
datatoc_lanpr_dpix_preview_frag_glsl,
NULL);
if (!lanpr_share.dpix_transform_shader) {
lanpr_share.dpix_shader_error = 1;
printf("LANPR: DPIX transform shader compile error.");
}
}
}
void lanpr_destroy_atlas(void *UNUSED(ved))
{
/* no need to free things, no custom data. */
}
int lanpr_feed_atlas_data_obj(void *UNUSED(vedata),
float *AtlasPointsL,
float *AtlasPointsR,
float *AtlasFaceNormalL,
float *AtlasFaceNormalR,
float *AtlasEdgeMask,
Object *ob,
int begin_index)
{
if (!DRW_object_is_renderable(ob)) {
return begin_index;
}
const DRWContextState *draw_ctx = DRW_context_state_get();
if (ob == draw_ctx->object_edit) {
return begin_index;
}
if (ob->type != OB_MESH) {
return begin_index;
}
Mesh *me = ob->data;
BMesh *bm;
struct BMFace *f1, *f2;
struct BMVert *v1, *v2;
struct BMEdge *e;
struct BMLoop *l1, *l2;
FreestyleEdge *fe;
int CanFindFreestyle = 0;
int edge_count = me->totedge;
int i, idx;
int cache_total = lanpr_share.texture_size * lanpr_share.texture_size;
/* Don't overflow the cache. */
if ((edge_count + begin_index) > (cache_total - 1)) {
return begin_index;
}
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
bm = BM_mesh_create(&allocsize,
&((struct BMeshCreateParams){
.use_toolflags = true,
}));
BM_mesh_bm_from_me(bm,
me,
&((struct BMeshFromMeshParams){
.calc_face_normal = true,
}));
BM_mesh_elem_table_ensure(bm, BM_VERT | BM_EDGE | BM_FACE);
if (CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE)) {
CanFindFreestyle = 1;
}
for (i = 0; i < edge_count; i++) {
f1 = 0;
f2 = 0;
e = BM_edge_at_index(bm, i);
v1 = e->v1;
v2 = e->v2;
l1 = e->l;
l2 = e->l ? e->l->radial_next : 0;
if (l1) {
f1 = l1->f;
}
if (l2) {
f2 = l2->f;
}
idx = (begin_index + i) * 4;
AtlasPointsL[idx + 0] = v1->co[0];
AtlasPointsL[idx + 1] = v1->co[1];
AtlasPointsL[idx + 2] = v1->co[2];
AtlasPointsL[idx + 3] = 1;
AtlasPointsR[idx + 0] = v2->co[0];
AtlasPointsR[idx + 1] = v2->co[1];
AtlasPointsR[idx + 2] = v2->co[2];
AtlasPointsR[idx + 3] = 1;
if (CanFindFreestyle) {
fe = CustomData_bmesh_get(&bm->edata, e->head.data, FREESTYLE_EDGE_MARK);
if (fe->flag & FREESTYLE_EDGE_MARK) {
AtlasEdgeMask[idx + 1] = 1; /* channel G */
}
}
if (f1) {
AtlasFaceNormalL[idx + 0] = f1->no[0];
AtlasFaceNormalL[idx + 1] = f1->no[1];
AtlasFaceNormalL[idx + 2] = f1->no[2];
AtlasFaceNormalL[idx + 3] = 1;
}
else {
AtlasFaceNormalL[idx + 0] = 0;
AtlasFaceNormalL[idx + 1] = 0;
AtlasFaceNormalL[idx + 2] = 0;
AtlasFaceNormalL[idx + 3] = 0;
}
if (f2 && f2 != f1) { /* this is for edge condition */
AtlasFaceNormalR[idx + 0] = f2->no[0];
AtlasFaceNormalR[idx + 1] = f2->no[1];
AtlasFaceNormalR[idx + 2] = f2->no[2];
AtlasFaceNormalR[idx + 3] = 1;
if (f2->mat_nr != f1->mat_nr) {
AtlasEdgeMask[idx] = 1; /* channel r */
}
}
else {
AtlasFaceNormalR[idx + 0] = 0;
AtlasFaceNormalR[idx + 1] = 0;
AtlasFaceNormalR[idx + 2] = 0;
AtlasFaceNormalR[idx + 3] = 0;
}
}
BM_mesh_free(bm);
return begin_index + edge_count;
}
int lanpr_feed_atlas_data_intersection_cache(void *UNUSED(vedata),
float *AtlasPointsL,
float *AtlasPointsR,
float *AtlasFaceNormalL,
float *AtlasFaceNormalR,
float *AtlasEdgeMask,
int begin_index)
{
LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared;
LinkData *lip;
LANPR_RenderLine *rl;
int i, idx;
i = 0;
if (!rb) {
return 0;
}
int cache_total = lanpr_share.texture_size * lanpr_share.texture_size;
/* Don't overflow the cache. */
if ((rb->intersection_count + begin_index) > (cache_total - 1)) {
return 0;
}
for (lip = rb->intersection_lines.first; lip; lip = lip->next) {
rl = lip->data;
idx = (begin_index + i) * 4;
AtlasEdgeMask[idx + 2] = 1; /* channel B */
AtlasPointsL[idx + 0] = rl->l->gloc[0];
AtlasPointsL[idx + 1] = rl->l->gloc[1];
AtlasPointsL[idx + 2] = rl->l->gloc[2];
AtlasPointsL[idx + 3] = 1;
AtlasPointsR[idx + 0] = rl->r->gloc[0];
AtlasPointsR[idx + 1] = rl->r->gloc[1];
AtlasPointsR[idx + 2] = rl->r->gloc[2];
AtlasPointsR[idx + 3] = 1;
AtlasFaceNormalL[idx + 0] = 0;
AtlasFaceNormalL[idx + 1] = 0;
AtlasFaceNormalL[idx + 2] = 1;
AtlasFaceNormalL[idx + 3] = 0;
AtlasFaceNormalR[idx + 0] = 0;
AtlasFaceNormalR[idx + 1] = 0;
AtlasFaceNormalR[idx + 2] = 1;
AtlasFaceNormalR[idx + 3] = 0;
i++;
}
return begin_index + i;
}
static void lanpr_dpix_index_to_coord(int index, float *x, float *y)
{
int texture_size = lanpr_share.texture_size;
(*x) = interpf(1, -1, (float)(index % texture_size + 0.5) / (float)texture_size);
(*y) = interpf(1, -1, (float)(index / texture_size + 0.5) / (float)texture_size);
}
static void lanpr_dpix_index_to_coord_absolute(int index, float *x, float *y)
{
int texture_size = lanpr_share.texture_size;
(*x) = (float)(index % texture_size) + 0.5;
(*y) = (float)(index / texture_size) + 0.5;
}
int lanpr_feed_atlas_trigger_preview_obj(void *UNUSED(vedata), Object *ob, int begin_index)
{
Mesh *me = ob->data;
if (ob->type != OB_MESH) {
return begin_index;
}
int edge_count = me->totedge;
int i;
float co[2];
int cache_total = lanpr_share.texture_size * lanpr_share.texture_size;
/* Don't overflow the cache. */
if ((edge_count + begin_index) > (cache_total - 1)) {
return begin_index;
}
static GPUVertFormat format = {0};
static struct {
uint pos, uvs;
} attr_id;
if (format.attr_len == 0) {
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
static GPUVertFormat format2 = {0};
static struct {
uint pos, uvs;
} attr_id2;
if (format2.attr_len == 0) {
attr_id2.pos = GPU_vertformat_attr_add(&format2, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
GPUVertBuf *vbo2 = GPU_vertbuf_create_with_format(&format2);
GPU_vertbuf_data_alloc(vbo, edge_count);
GPU_vertbuf_data_alloc(vbo2, edge_count);
for (i = 0; i < edge_count; i++) {
lanpr_dpix_index_to_coord(i + begin_index, &co[0], &co[1]);
GPU_vertbuf_attr_set(vbo, attr_id.pos, i, co);
lanpr_dpix_index_to_coord_absolute(i + begin_index, &co[0], &co[1]);
GPU_vertbuf_attr_set(vbo2, attr_id2.pos, i, co);
}
GPUBatch *gb = GPU_batch_create_ex(
GPU_PRIM_POINTS, vbo, 0, GPU_USAGE_DYNAMIC | GPU_BATCH_OWNS_VBO);
GPUBatch *gb2 = GPU_batch_create_ex(
GPU_PRIM_POINTS, vbo2, 0, GPU_USAGE_DYNAMIC | GPU_BATCH_OWNS_VBO);
LANPR_BatchItem *bi = BLI_mempool_alloc(lanpr_share.mp_batch_list);
BLI_addtail(&lanpr_share.dpix_batch_list, bi);
bi->dpix_transform_batch = gb;
bi->dpix_preview_batch = gb2;
bi->ob = ob;
return begin_index + edge_count;
}
void lanpr_create_atlas_intersection_preview(void *UNUSED(vedata), int begin_index)
{
LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared;
float co[2];
int i;
if (!rb) {
return;
}
if (rb->DPIXIntersectionBatch) {
GPU_BATCH_DISCARD_SAFE(rb->DPIXIntersectionBatch);
}
rb->DPIXIntersectionBatch = 0;
if (!rb->intersection_count) {
return;
}
int cache_total = lanpr_share.texture_size * lanpr_share.texture_size;
/* Don't overflow the cache. */
if ((rb->intersection_count + begin_index) > (cache_total - 1)) {
return;
}
static GPUVertFormat format = {0};
static struct {
uint pos, uvs;
} attr_id;
if (format.attr_len == 0) {
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
static GPUVertFormat format2 = {0};
static struct {
uint pos, uvs;
} attr_id2;
if (format2.attr_len == 0) {
attr_id2.pos = GPU_vertformat_attr_add(&format2, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
GPU_vertbuf_data_alloc(vbo, rb->intersection_count);
GPUVertBuf *vbo2 = GPU_vertbuf_create_with_format(&format2);
GPU_vertbuf_data_alloc(vbo2, rb->intersection_count);
for (i = 0; i < rb->intersection_count; i++) {
lanpr_dpix_index_to_coord(i + begin_index, &co[0], &co[1]);
GPU_vertbuf_attr_set(vbo, attr_id.pos, i, co);
lanpr_dpix_index_to_coord_absolute(i + begin_index, &co[0], &co[1]);
GPU_vertbuf_attr_set(vbo2, attr_id2.pos, i, co);
}
rb->DPIXIntersectionTransformBatch = GPU_batch_create_ex(
GPU_PRIM_POINTS, vbo, 0, GPU_USAGE_DYNAMIC | GPU_BATCH_OWNS_VBO);
rb->DPIXIntersectionBatch = GPU_batch_create_ex(
GPU_PRIM_POINTS, vbo2, 0, GPU_USAGE_DYNAMIC | GPU_BATCH_OWNS_VBO);
}
void lanpr_dpix_draw_scene(LANPR_TextureList *txl,
LANPR_FramebufferList *fbl,
LANPR_PassList *psl,
LANPR_PrivateData *pd,
SceneLANPR *lanpr,
GPUFrameBuffer *DefaultFB,
int is_render)
{
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float clear_depth = 1.0f;
uint clear_stencil = 0xFF;
int is_persp = 1;
float use_background_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
;
if (!lanpr->active_layer) {
return; /* return early in case we don't have line layers. DPIX only use the first layer. */
}
int texw = GPU_texture_width(txl->edge_intermediate),
texh = GPU_texture_height(txl->edge_intermediate);
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
View3D *v3d = draw_ctx->v3d;
Object *camera = 0;
if (v3d) {
RegionView3D *rv3d = draw_ctx->rv3d;
camera = (rv3d && rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL;
is_persp = rv3d->is_persp;
}
if (!camera) {
camera = scene->camera;
if (!v3d) {
is_persp = ((Camera *)camera->data)->type == CAM_PERSP ? 1 : 0;
}
}
if (is_render && !camera) {
return;
}
/* XXX: should implement view angle functions for ortho camera. */
int texture_size = lanpr_share.texture_size;
pd->dpix_viewport[2] = texw;
pd->dpix_viewport[3] = texh;
pd->dpix_is_perspective = is_persp;
pd->dpix_sample_step = 1;
pd->dpix_buffer_width = texture_size;
pd->dpix_depth_offset = 0.0001;
pd->dpix_znear = camera ? ((Camera *)camera->data)->clip_start : v3d->clip_start;
pd->dpix_zfar = camera ? ((Camera *)camera->data)->clip_end : v3d->clip_end;
copy_v3_v3(use_background_color, &scene->world->horr);
use_background_color[3] = scene->r.alphamode ? 0.0f : 1.0f;
GPU_point_size(1);
/* GPU_line_width(2); */
GPU_framebuffer_bind(fbl->dpix_transform);
DRW_draw_pass(psl->dpix_transform_pass);
GPU_framebuffer_bind(fbl->dpix_preview);
eGPUFrameBufferBits clear_bits = GPU_COLOR_BIT;
GPU_framebuffer_clear(fbl->dpix_preview, clear_bits, clear_col, clear_depth, clear_stencil);
DRW_draw_pass(psl->dpix_preview_pass);
if (is_render) {
mul_v3_v3fl(clear_col, use_background_color, use_background_color[3]);
clear_col[3] = use_background_color[3];
}
else {
copy_v4_v4(clear_col, use_background_color);
}
GPU_framebuffer_bind(DefaultFB);
GPU_framebuffer_clear(DefaultFB, clear_bits, clear_col, clear_depth, clear_stencil);
DRW_multisamples_resolve(txl->depth, txl->color, 0);
}

View File

@@ -0,0 +1,815 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*
*/
/** \file
* \ingroup draw
*/
#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "BLI_math_matrix.h"
#include "BLI_rect.h"
#include "BKE_object.h"
#include "DEG_depsgraph_query.h"
#include "DNA_camera_types.h"
#include "DNA_lanpr_types.h"
#include "DNA_mesh_types.h"
#include "DRW_engine.h"
#include "DRW_render.h"
#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_shader.h"
#include "GPU_uniformbuffer.h"
#include "GPU_viewport.h"
#include "RE_pipeline.h"
#include "bmesh.h"
#include "lanpr_all.h"
#include <math.h>
extern char datatoc_common_fullscreen_vert_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
extern char datatoc_lanpr_snake_multichannel_frag_glsl[];
extern char datatoc_lanpr_snake_edge_frag_glsl[];
extern char datatoc_lanpr_snake_image_peel_frag_glsl[];
extern char datatoc_lanpr_snake_line_connection_vert_glsl[];
extern char datatoc_lanpr_snake_line_connection_frag_glsl[];
extern char datatoc_lanpr_snake_line_connection_geom_glsl[];
extern char datatoc_lanpr_software_line_chain_geom_glsl[];
extern char datatoc_lanpr_software_chain_geom_glsl[];
extern char datatoc_lanpr_dpix_project_passthrough_vert_glsl[];
extern char datatoc_lanpr_dpix_project_clip_frag_glsl[];
extern char datatoc_lanpr_dpix_preview_frag_glsl[];
extern char datatoc_lanpr_software_passthrough_vert_glsl[];
extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[];
extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[];
LANPR_SharedResource lanpr_share;
static void lanpr_engine_init(void *ved)
{
lanpr_share.ved_viewport = ved;
LANPR_Data *vedata = (LANPR_Data *)ved;
LANPR_TextureList *txl = vedata->txl;
LANPR_FramebufferList *fbl = vedata->fbl;
if (!lanpr_share.init_complete) {
BLI_spin_init(&lanpr_share.lock_render_status);
}
#if 0 /* Deprecated: snake mode */
GPU_framebuffer_ensure_config(&fbl->edge_thinning,
{GPU_ATTACHMENT_LEAVE,
GPU_ATTACHMENT_TEXTURE(txl->color)});
if (!lanpr_share.edge_detect_shader) {
lanpr_share.edge_detect_shader = DRW_shader_create(
datatoc_common_fullscreen_vert_glsl, NULL, datatoc_lanpr_snake_edge_frag_glsl, NULL);
}
if (!lanpr_share.edge_thinning_shader) {
lanpr_share.edge_thinning_shader = DRW_shader_create(
datatoc_common_fullscreen_vert_glsl, NULL, datatoc_lanpr_snake_image_peel_frag_glsl, NULL);
}
if (!lanpr_share.snake_connection_shader) {
lanpr_share.snake_connection_shader = DRW_shader_create(
datatoc_lanpr_snake_line_connection_vert_glsl,
datatoc_lanpr_snake_line_connection_geom_glsl,
datatoc_lanpr_snake_line_connection_frag_glsl,
NULL);
}
#endif
DRW_texture_ensure_fullscreen_2D_multisample(&txl->depth, GPU_DEPTH_COMPONENT32F, 8, 0);
DRW_texture_ensure_fullscreen_2D_multisample(&txl->color, GPU_RGBA32F, 8, 0);
DRW_texture_ensure_fullscreen_2D_multisample(&txl->normal, GPU_RGBA32F, 8, 0);
DRW_texture_ensure_fullscreen_2D_multisample(&txl->edge_intermediate, GPU_RGBA32F, 8, 0);
DRW_texture_ensure_fullscreen_2D_multisample(
&txl->ms_resolve_depth, GPU_DEPTH_COMPONENT32F, 8, 0);
DRW_texture_ensure_fullscreen_2D_multisample(&txl->ms_resolve_color, GPU_RGBA32F, 8, 0);
GPU_framebuffer_ensure_config(&fbl->passes,
{GPU_ATTACHMENT_TEXTURE(txl->depth),
GPU_ATTACHMENT_TEXTURE(txl->color),
GPU_ATTACHMENT_TEXTURE(txl->normal)});
GPU_framebuffer_ensure_config(
&fbl->edge_intermediate,
{GPU_ATTACHMENT_TEXTURE(txl->depth), GPU_ATTACHMENT_TEXTURE(txl->edge_intermediate)});
if (!lanpr_share.multichannel_shader) {
lanpr_share.multichannel_shader = DRW_shader_create(
datatoc_gpu_shader_3D_smooth_color_vert_glsl,
NULL,
datatoc_gpu_shader_3D_smooth_color_frag_glsl,
NULL);
}
/* DPIX */
lanpr_init_atlas_inputs(ved);
/* SOFTWARE */
if (!lanpr_share.software_shader) {
lanpr_share.software_shader = DRW_shader_create(datatoc_lanpr_software_passthrough_vert_glsl,
datatoc_lanpr_software_line_chain_geom_glsl,
datatoc_lanpr_dpix_preview_frag_glsl,
NULL);
}
if (!lanpr_share.software_chaining_shader) {
lanpr_share.software_chaining_shader = DRW_shader_create(
datatoc_lanpr_software_passthrough_vert_glsl,
datatoc_lanpr_software_chain_geom_glsl,
datatoc_lanpr_dpix_preview_frag_glsl,
NULL);
}
GPU_framebuffer_ensure_config(&fbl->software_ms,
{GPU_ATTACHMENT_TEXTURE(txl->ms_resolve_depth),
GPU_ATTACHMENT_TEXTURE(txl->ms_resolve_color)});
lanpr_share.init_complete = 1;
}
static void lanpr_dpix_batch_free(void)
{
LANPR_BatchItem *dpbi;
while ((dpbi = BLI_pophead(&lanpr_share.dpix_batch_list)) != NULL) {
GPU_BATCH_DISCARD_SAFE(dpbi->dpix_preview_batch);
GPU_BATCH_DISCARD_SAFE(dpbi->dpix_transform_batch);
}
LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared;
if (rb) {
if (rb->DPIXIntersectionBatch) {
GPU_BATCH_DISCARD_SAFE(rb->DPIXIntersectionBatch);
}
if (rb->DPIXIntersectionTransformBatch) {
GPU_BATCH_DISCARD_SAFE(rb->DPIXIntersectionTransformBatch);
}
}
}
static void lanpr_engine_free(void)
{
DRW_SHADER_FREE_SAFE(lanpr_share.multichannel_shader);
DRW_SHADER_FREE_SAFE(lanpr_share.snake_connection_shader);
DRW_SHADER_FREE_SAFE(lanpr_share.software_chaining_shader);
DRW_SHADER_FREE_SAFE(lanpr_share.dpix_preview_shader);
DRW_SHADER_FREE_SAFE(lanpr_share.dpix_transform_shader);
DRW_SHADER_FREE_SAFE(lanpr_share.edge_detect_shader);
DRW_SHADER_FREE_SAFE(lanpr_share.edge_thinning_shader);
DRW_SHADER_FREE_SAFE(lanpr_share.software_shader);
lanpr_dpix_batch_free();
if (lanpr_share.render_buffer_shared) {
LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared;
ED_lanpr_destroy_render_data(rb);
GPU_BATCH_DISCARD_SAFE(rb->chain_draw_batch);
MEM_freeN(rb);
lanpr_share.render_buffer_shared = NULL;
}
BLI_mempool *mp = lanpr_share.mp_batch_list;
if (mp) {
BLI_mempool_destroy(mp);
}
}
static void lanpr_cache_init(void *vedata)
{
LANPR_PassList *psl = ((LANPR_Data *)vedata)->psl;
LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
LANPR_TextureList *txl = ((LANPR_Data *)vedata)->txl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
static float normal_object_direction[3] = {0, 0, 1};
/* Transfer reload state */
lanpr_share.dpix_reloaded = lanpr_share.dpix_reloaded_deg;
if (!stl->g_data) {
/* Alloc transient pointers */
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
if (!lanpr_share.mp_batch_list) {
lanpr_share.mp_batch_list = BLI_mempool_create(
sizeof(LANPR_BatchItem), 0, 128, BLI_MEMPOOL_NOP);
}
LANPR_PrivateData *pd = stl->g_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
SceneLANPR *lanpr = &scene->lanpr;
int texture_size = lanpr_dpix_texture_size(lanpr);
lanpr_share.texture_size = texture_size;
psl->color_pass = DRW_pass_create(
"color Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH);
stl->g_data->multipass_shgrp = DRW_shgroup_create(lanpr_share.multichannel_shader,
psl->color_pass);
if (lanpr->master_mode == LANPR_MASTER_MODE_SNAKE) {
struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
psl->edge_intermediate = DRW_pass_create("Edge Detection", DRW_STATE_WRITE_COLOR);
stl->g_data->edge_detect_shgrp = DRW_shgroup_create(lanpr_share.edge_detect_shader,
psl->edge_intermediate);
DRW_shgroup_uniform_texture_ref(stl->g_data->edge_detect_shgrp, "tex_sample_0", &txl->depth);
DRW_shgroup_uniform_texture_ref(stl->g_data->edge_detect_shgrp, "tex_sample_1", &txl->color);
DRW_shgroup_uniform_texture_ref(stl->g_data->edge_detect_shgrp, "tex_sample_2", &txl->normal);
DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp, "z_near", &stl->g_data->znear, 1);
DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp, "z_far", &stl->g_data->zfar, 1);
DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp,
"normal_clamp",
&stl->g_data->normal_clamp,
1); /* normal clamp */
DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp,
"normal_strength",
&stl->g_data->normal_strength,
1); /* normal strength */
DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp,
"depth_clamp",
&stl->g_data->depth_clamp,
1); /* depth clamp */
DRW_shgroup_uniform_float(stl->g_data->edge_detect_shgrp,
"depth_strength",
&stl->g_data->depth_strength,
1); /* depth strength */
DRW_shgroup_call(stl->g_data->edge_detect_shgrp, quad, NULL);
psl->edge_thinning = DRW_pass_create("Edge Thinning Stage 1", DRW_STATE_WRITE_COLOR);
stl->g_data->edge_thinning_shgrp = DRW_shgroup_create(lanpr_share.edge_thinning_shader,
psl->edge_thinning);
DRW_shgroup_uniform_texture_ref(
stl->g_data->edge_thinning_shgrp, "tex_sample_0", &dtxl->color);
DRW_shgroup_uniform_int(stl->g_data->edge_thinning_shgrp, "stage", &stl->g_data->stage, 1);
DRW_shgroup_call(stl->g_data->edge_thinning_shgrp, quad, NULL);
}
else if (lanpr->master_mode == LANPR_MASTER_MODE_DPIX && lanpr->active_layer &&
!lanpr_share.dpix_shader_error) {
LANPR_LineLayer *ll = lanpr->line_layers.first;
psl->dpix_transform_pass = DRW_pass_create("DPIX Transform Stage", DRW_STATE_WRITE_COLOR);
stl->g_data->dpix_transform_shgrp = DRW_shgroup_create(lanpr_share.dpix_transform_shader,
psl->dpix_transform_pass);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_transform_shgrp, "vert0_tex", &txl->dpix_in_pl);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_transform_shgrp, "vert1_tex", &txl->dpix_in_pr);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_transform_shgrp, "face_normal0_tex", &txl->dpix_in_nl);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_transform_shgrp, "face_normal1_tex", &txl->dpix_in_nr);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_transform_shgrp, "edge_mask_tex", &txl->dpix_in_edge_mask);
DRW_shgroup_uniform_int(
stl->g_data->dpix_transform_shgrp, "sample_step", &stl->g_data->dpix_sample_step, 1);
DRW_shgroup_uniform_int(
stl->g_data->dpix_transform_shgrp, "is_perspective", &stl->g_data->dpix_is_perspective, 1);
DRW_shgroup_uniform_vec4(
stl->g_data->dpix_transform_shgrp, "viewport", stl->g_data->dpix_viewport, 1);
DRW_shgroup_uniform_int(
stl->g_data->dpix_transform_shgrp, "buffer_width", &stl->g_data->dpix_buffer_width, 1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_transform_shgrp, "crease_threshold", &lanpr->crease_threshold, 1);
DRW_shgroup_uniform_float(stl->g_data->dpix_transform_shgrp,
"crease_fade_threshold",
&lanpr->crease_fade_threshold,
1);
DRW_shgroup_uniform_int(stl->g_data->dpix_transform_shgrp, "use_contour", &ll->contour.use, 1);
DRW_shgroup_uniform_int(stl->g_data->dpix_transform_shgrp, "use_crease", &ll->crease.use, 1);
DRW_shgroup_uniform_int(
stl->g_data->dpix_transform_shgrp, "use_material", &ll->material_separate.use, 1);
DRW_shgroup_uniform_int(
stl->g_data->dpix_transform_shgrp, "use_edge_mark", &ll->edge_mark.use, 1);
DRW_shgroup_uniform_int(
stl->g_data->dpix_transform_shgrp, "use_intersection", &ll->intersection.use, 1);
psl->dpix_preview_pass = DRW_pass_create("DPIX Preview",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
DRW_STATE_DEPTH_LESS_EQUAL);
stl->g_data->dpix_preview_shgrp = DRW_shgroup_create(lanpr_share.dpix_preview_shader,
psl->dpix_preview_pass);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_preview_shgrp, "vert0_tex", &txl->dpix_out_pl);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_preview_shgrp, "vert1_tex", &txl->dpix_out_pr);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_preview_shgrp, "face_normal0_tex", &txl->dpix_in_nl);
DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_preview_shgrp,
"face_normal1_tex",
&txl->dpix_in_nr); /* these are for normal shading */
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_preview_shgrp, "edge_mask_tex", &txl->dpix_in_edge_mask);
DRW_shgroup_uniform_vec4(
stl->g_data->dpix_preview_shgrp, "viewport", stl->g_data->dpix_viewport, 1);
DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp,
"contour_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color :
ll->contour.color,
1);
DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp,
"crease_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color :
ll->crease.color,
1);
DRW_shgroup_uniform_vec4(
stl->g_data->dpix_preview_shgrp,
"material_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->material_separate.color,
1);
DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp,
"edge_mark_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color :
ll->edge_mark.color,
1);
DRW_shgroup_uniform_vec4(
stl->g_data->dpix_preview_shgrp,
"intersection_color",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->intersection.color,
1);
static float use_background_color[4];
copy_v3_v3(use_background_color, &scene->world->horr);
use_background_color[3] = scene->r.alphamode ? 0.0f : 1.0f;
DRW_shgroup_uniform_vec4(
stl->g_data->dpix_preview_shgrp, "background_color", use_background_color, 1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp, "depth_offset", &stl->g_data->dpix_depth_offset, 1);
DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp,
"depth_width_influence",
&lanpr->depth_width_influence,
1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp, "depth_width_curve", &lanpr->depth_width_curve, 1);
DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp,
"depth_alpha_influence",
&lanpr->depth_alpha_influence,
1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp, "depth_alpha_curve", &lanpr->depth_alpha_curve, 1);
static float unit_thickness = 1.0f;
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp, "line_thickness", &ll->thickness, 1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp,
"line_thickness_contour",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? &unit_thickness : &ll->contour.thickness,
1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp,
"line_thickness_crease",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? &unit_thickness : &ll->crease.thickness,
1);
DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp,
"line_thickness_material",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->material_separate.thickness,
1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp,
"line_thickness_edge_mark",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? &unit_thickness : &ll->edge_mark.thickness,
1);
DRW_shgroup_uniform_float(stl->g_data->dpix_preview_shgrp,
"line_thickness_intersection",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->intersection.thickness,
1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp, "z_near", &stl->g_data->dpix_znear, 1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp, "z_far", &stl->g_data->dpix_zfar, 1);
ED_lanpr_calculate_normal_object_vector(ll, normal_object_direction);
static int normal_effect_inverse;
static int zero_value = 0;
normal_effect_inverse = (ll->flags & LANPR_LINE_LAYER_NORMAL_INVERSE);
DRW_shgroup_uniform_int(stl->g_data->dpix_preview_shgrp,
"normal_mode",
(ll->flags & LANPR_LINE_LAYER_NORMAL_ENABLED) ? &ll->normal_mode :
&zero_value,
1);
DRW_shgroup_uniform_int(
stl->g_data->dpix_preview_shgrp, "normal_effect_inverse", &normal_effect_inverse, 1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp, "normal_ramp_begin", &ll->normal_ramp_begin, 1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp, "normal_ramp_end", &ll->normal_ramp_end, 1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp, "normal_thickness_start", &ll->normal_thickness_start, 1);
DRW_shgroup_uniform_float(
stl->g_data->dpix_preview_shgrp, "normal_thickness_end", &ll->normal_thickness_end, 1);
DRW_shgroup_uniform_vec3(
stl->g_data->dpix_preview_shgrp, "normal_direction", normal_object_direction, 1);
pd->begin_index = 0;
int fsize = sizeof(float) * 4 * texture_size * texture_size;
if (lanpr_share.dpix_reloaded) {
pd->atlas_pl = MEM_callocN(fsize, "atlas_point_l");
pd->atlas_pr = MEM_callocN(fsize, "atlas_point_r");
pd->atlas_nl = MEM_callocN(fsize, "atlas_normal_l");
pd->atlas_nr = MEM_callocN(fsize, "atlas_normal_l");
pd->atlas_edge_mask = MEM_callocN(fsize, "atlas_edge_mask"); /* should always be float */
lanpr_dpix_batch_free();
BLI_mempool_clear(lanpr_share.mp_batch_list);
}
}
else if (lanpr->master_mode == LANPR_MASTER_MODE_SOFTWARE) {
;
}
/* Intersection cache must be calculated before drawing. */
int updated = 0;
if ((draw_ctx->scene->lanpr.flags & LANPR_AUTO_UPDATE) &&
(!lanpr_share.render_buffer_shared ||
lanpr_share.render_buffer_shared->cached_for_frame != draw_ctx->scene->r.cfra)) {
if (draw_ctx->scene->lanpr.master_mode == LANPR_MASTER_MODE_SOFTWARE) {
ED_lanpr_compute_feature_lines_background(draw_ctx->depsgraph, 0);
}
else if (draw_ctx->scene->lanpr.master_mode == LANPR_MASTER_MODE_DPIX) {
ED_lanpr_compute_feature_lines_background(draw_ctx->depsgraph, 1);
}
}
if (ED_lanpr_calculation_flag_check(LANPR_RENDER_FINISHED)) {
ED_lanpr_rebuild_all_command(&draw_ctx->scene->lanpr);
ED_lanpr_calculation_set_flag(LANPR_RENDER_IDLE);
}
else {
DRW_viewport_request_redraw();
}
}
static void lanpr_cache_populate(void *vedata, Object *ob)
{
LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
LANPR_PrivateData *pd = stl->g_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
SceneLANPR *lanpr = &draw_ctx->scene->lanpr;
int usage = OBJECT_FEATURE_LINE_INHERENT, dpix_ok = 0;
if (!DRW_object_is_renderable(ob)) {
return;
}
if (ob == draw_ctx->object_edit) {
return;
}
if (ob->type != OB_MESH) {
return;
}
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
if ((dpix_ok = (lanpr->master_mode == LANPR_MASTER_MODE_DPIX && lanpr->active_layer &&
!lanpr_share.dpix_shader_error)) != 0) {
usage = ED_lanpr_object_collection_usage_check(draw_ctx->scene->master_collection, ob);
if (usage == OBJECT_FEATURE_LINE_EXCLUDE) {
return;
}
}
DRW_shgroup_call_no_cull(stl->g_data->multipass_shgrp, geom, ob);
}
if (dpix_ok) {
/* usage already set */
if (usage == OBJECT_FEATURE_LINE_OCCLUSION_ONLY) {
return;
}
int idx = pd->begin_index;
if (lanpr_share.dpix_reloaded) {
pd->begin_index = lanpr_feed_atlas_data_obj(vedata,
pd->atlas_pl,
pd->atlas_pr,
pd->atlas_nl,
pd->atlas_nr,
pd->atlas_edge_mask,
ob,
idx);
lanpr_feed_atlas_trigger_preview_obj(vedata, ob, idx);
}
}
}
static void lanpr_cache_finish(void *vedata)
{
LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
LANPR_PrivateData *pd = stl->g_data;
LANPR_TextureList *txl = ((LANPR_Data *)vedata)->txl;
const DRWContextState *draw_ctx = DRW_context_state_get();
SceneLANPR *lanpr = &draw_ctx->scene->lanpr;
float mat[4][4];
unit_m4(mat);
if (lanpr->master_mode == LANPR_MASTER_MODE_DPIX && lanpr->active_layer &&
!lanpr_share.dpix_shader_error) {
if (lanpr_share.dpix_reloaded) {
if (lanpr_share.render_buffer_shared) {
lanpr_feed_atlas_data_intersection_cache(vedata,
pd->atlas_pl,
pd->atlas_pr,
pd->atlas_nl,
pd->atlas_nr,
pd->atlas_edge_mask,
pd->begin_index);
lanpr_create_atlas_intersection_preview(vedata, pd->begin_index);
}
GPU_texture_update(txl->dpix_in_pl, GPU_DATA_FLOAT, pd->atlas_pl);
GPU_texture_update(txl->dpix_in_pr, GPU_DATA_FLOAT, pd->atlas_pr);
GPU_texture_update(txl->dpix_in_nl, GPU_DATA_FLOAT, pd->atlas_nl);
GPU_texture_update(txl->dpix_in_nr, GPU_DATA_FLOAT, pd->atlas_nr);
GPU_texture_update(txl->dpix_in_edge_mask, GPU_DATA_FLOAT, pd->atlas_edge_mask);
MEM_freeN(pd->atlas_pl);
MEM_freeN(pd->atlas_pr);
MEM_freeN(pd->atlas_nl);
MEM_freeN(pd->atlas_nr);
MEM_freeN(pd->atlas_edge_mask);
pd->atlas_pl = 0;
lanpr_share.dpix_reloaded = 0;
}
LANPR_BatchItem *bi;
for (bi = lanpr_share.dpix_batch_list.first; bi; bi = (void *)bi->item.next) {
DRW_shgroup_call_ex(
pd->dpix_transform_shgrp, 0, bi->ob->obmat, bi->dpix_transform_batch, 0, 0, true, NULL);
DRW_shgroup_call(pd->dpix_preview_shgrp, bi->dpix_preview_batch, 0);
}
if (lanpr_share.render_buffer_shared &&
lanpr_share.render_buffer_shared->DPIXIntersectionBatch) {
DRW_shgroup_call(pd->dpix_transform_shgrp,
lanpr_share.render_buffer_shared->DPIXIntersectionTransformBatch,
0);
DRW_shgroup_call(
pd->dpix_preview_shgrp, lanpr_share.render_buffer_shared->DPIXIntersectionBatch, 0);
}
}
}
static void lanpr_draw_scene_exec(void *vedata, GPUFrameBuffer *dfb, int is_render)
{
LANPR_PassList *psl = ((LANPR_Data *)vedata)->psl;
LANPR_TextureList *txl = ((LANPR_Data *)vedata)->txl;
LANPR_StorageList *stl = ((LANPR_Data *)vedata)->stl;
LANPR_FramebufferList *fbl = ((LANPR_Data *)vedata)->fbl;
float clear_col[4] = {1.0f, 0.0f, 0.0f, 1.0f};
float clear_depth = 1.0f;
uint clear_stencil = 0xFF;
GPU_framebuffer_bind(fbl->passes);
eGPUFrameBufferBits clear_bits = GPU_DEPTH_BIT | GPU_COLOR_BIT;
GPU_framebuffer_clear(fbl->passes, clear_bits, clear_col, clear_depth, clear_stencil);
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
SceneLANPR *lanpr = &scene->lanpr;
if (lanpr->master_mode == LANPR_MASTER_MODE_DPIX && !lanpr_share.dpix_shader_error) {
DRW_draw_pass(psl->color_pass);
lanpr_dpix_draw_scene(txl, fbl, psl, stl->g_data, lanpr, dfb, is_render);
}
/* Deprecated
else if (lanpr->master_mode == LANPR_MASTER_MODE_SNAKE) {
DRW_draw_pass(psl->color_pass);
lanpr_snake_draw_scene(txl, fbl, psl, stl->g_data, lanpr, dfb, is_render);
}
*/
else if (lanpr->master_mode == LANPR_MASTER_MODE_SOFTWARE) {
/* should isolate these into a seperate function. */
lanpr_software_draw_scene(vedata, dfb, is_render);
}
}
static void lanpr_draw_scene(void *vedata)
{
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
lanpr_draw_scene_exec(vedata, dfbl->default_fb, 0);
}
static void lanpr_render_cache(void *vedata,
struct Object *ob,
struct RenderEngine *UNUSED(engine),
struct Depsgraph *UNUSED(depsgraph))
{
lanpr_cache_populate(vedata, ob);
}
static void lanpr_render_matrices_init(RenderEngine *engine, Depsgraph *depsgraph)
{
/* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
Scene *scene = DEG_get_evaluated_scene(depsgraph);
struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
float frame = BKE_scene_frame_get(scene);
/* Set the persective, view and window matrix. */
float winmat[4][4], wininv[4][4];
float viewmat[4][4], viewinv[4][4];
float persmat[4][4], persinv[4][4];
float unitmat[4][4];
RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat);
RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv);
invert_m4_m4(viewmat, viewinv);
mul_m4_m4m4(persmat, winmat, viewmat);
invert_m4_m4(persinv, persmat);
invert_m4_m4(wininv, winmat);
unit_m4(unitmat);
DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
DRW_view_default_set(view);
DRW_view_set_active(view);
}
static int LANPR_GLOBAL_update_tag;
static void lanpr_id_update(void *UNUSED(vedata), ID *id)
{
/* if (vedata->engine_type != &draw_engine_lanpr_type) return; */
/* Handle updates based on ID type. */
switch (GS(id->name)) {
case ID_WO:
case ID_OB:
case ID_ME:
LANPR_GLOBAL_update_tag = 1;
default:
/* pass */
break;
}
}
static void lanpr_render_to_image(void *vedata,
RenderEngine *engine,
struct RenderLayer *render_layer,
const rcti *rect)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
/* int update_mark = DEG_id_type_any_updated(draw_ctx->depsgraph); */
Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
SceneLANPR *lanpr = &scene->lanpr;
lanpr_share.re_render = engine;
RE_engine_update_stats(engine, NULL, "LANPR: Initializing");
if (lanpr->master_mode == LANPR_MASTER_MODE_SOFTWARE ||
(lanpr->master_mode == LANPR_MASTER_MODE_DPIX && (lanpr->flags & LANPR_USE_INTERSECTIONS))) {
if (!lanpr_share.render_buffer_shared) {
ED_lanpr_create_render_buffer();
}
if (lanpr_share.render_buffer_shared->cached_for_frame != scene->r.cfra ||
LANPR_GLOBAL_update_tag) {
int intersections_only = (lanpr->master_mode != LANPR_MASTER_MODE_SOFTWARE);
ED_lanpr_compute_feature_lines_internal(draw_ctx->depsgraph, intersections_only);
}
}
lanpr_render_matrices_init(engine, draw_ctx->depsgraph);
/* refered to eevee's code */
/* Init default FB and render targets:
* In render mode the default framebuffer is not generated
* because there is no viewport. So we need to manually create it or
* not use it. For code clarity we just allocate it make use of it. */
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
DRW_texture_ensure_fullscreen_2d(&dtxl->depth, GPU_DEPTH_COMPONENT32F, 0);
DRW_texture_ensure_fullscreen_2d(&dtxl->color, GPU_RGBA32F, 0);
GPU_framebuffer_ensure_config(
&dfbl->default_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
lanpr_engine_init(vedata);
lanpr_share.dpix_reloaded_deg = 1; /* force dpix batch to re-create */
lanpr_cache_init(vedata);
DRW_render_object_iter(vedata, engine, draw_ctx->depsgraph, lanpr_render_cache);
lanpr_cache_finish(vedata);
/* get ref for destroy data */
/* lanpr_share.rb_ref = lanpr->render_buffer; */
DRW_render_instance_buffer_finish();
float clear_col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
float clear_depth = 1.0f;
uint clear_stencil = 0xFF;
eGPUFrameBufferBits clear_bits = GPU_DEPTH_BIT | GPU_COLOR_BIT;
GPU_framebuffer_bind(dfbl->default_fb);
GPU_framebuffer_clear(dfbl->default_fb, clear_bits, clear_col, clear_depth, clear_stencil);
lanpr_draw_scene_exec(vedata, dfbl->default_fb, 1);
/* read it back so we can again display and save it. */
const char *viewname = RE_GetActiveRenderView(engine->re);
RenderPass *rp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
GPU_framebuffer_bind(dfbl->default_fb);
GPU_framebuffer_read_color(dfbl->default_fb,
rect->xmin,
rect->ymin,
BLI_rcti_size_x(rect),
BLI_rcti_size_y(rect),
4,
0,
rp->rect);
/* Must clear to avoid other problems. */
lanpr_share.re_render = NULL;
}
static void lanpr_view_update(void *UNUSED(vedata))
{
lanpr_share.dpix_reloaded_deg = 1; /* very bad solution, this will slow down animation. */
}
static const DrawEngineDataSize lanpr_data_size = DRW_VIEWPORT_DATA_SIZE(LANPR_Data);
DrawEngineType draw_engine_lanpr_type = {
NULL,
NULL,
N_("LANPR"),
&lanpr_data_size,
&lanpr_engine_init,
&lanpr_engine_free,
&lanpr_cache_init,
&lanpr_cache_populate,
&lanpr_cache_finish,
NULL, /* draw background */
&lanpr_draw_scene, /* draw scene */
&lanpr_view_update,
&lanpr_id_update,
&lanpr_render_to_image,
};
RenderEngineType DRW_engine_viewport_lanpr_type = {NULL,
NULL,
LANPR_ENGINE,
N_("LANPR"),
RE_INTERNAL,
NULL, /* update */
&DRW_render_to_image, /* render to img */
NULL, /* bake */
NULL, /* view update */
NULL, /* render to view */
NULL, /* update in script */
NULL, /* update in render pass */
&draw_engine_lanpr_type,
{NULL, NULL, NULL}};

View File

@@ -0,0 +1,623 @@
/*
* 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.
*
* Copyright 2019, Blender Foundation.
*
*/
/** \file
* \ingroup draw
*/
#include "DRW_engine.h"
#include "DRW_render.h"
#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "lanpr_all.h"
#include "DRW_render.h"
#include "BKE_object.h"
#include "DNA_mesh_types.h"
#include "DNA_camera_types.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_framebuffer.h"
#include "DNA_lanpr_types.h"
#include "DEG_depsgraph_query.h"
#include "GPU_draw.h"
#include "GPU_batch.h"
#include "GPU_framebuffer.h"
#include "GPU_shader.h"
#include "GPU_uniformbuffer.h"
#include "GPU_viewport.h"
#include "bmesh.h"
extern struct LANPR_SharedResource lanpr_share;
int _TNS_colOffsets[] = {-1, 0, 1, 1, 1, 0, -1, -1};
int _TNS_rowOffsets[] = {-1, -1, -1, 0, 1, 1, 1, 0};
int _TNS_Deviates[8][8] = {{0, 1, 2, 3, 4, 3, 2, 1},
{1, 0, 1, 2, 3, 4, 3, 2},
{2, 1, 0, 1, 2, 3, 4, 3},
{3, 2, 1, 0, 1, 2, 3, 4},
{4, 3, 2, 1, 0, 1, 2, 3},
{3, 4, 3, 2, 1, 0, 1, 2},
{2, 3, 4, 3, 2, 1, 0, 1},
{1, 2, 3, 4, 3, 2, 1, 0}};
#define TNS_CLAMP_TEXTURE_W(t, col) \
{ \
if (col >= t->width) \
col = t->width - 1; \
if (col < 0) \
col = 0; \
}
#define TNS_CLAMP_TEXTURE_H(t, row) \
{ \
if (row >= t->height) \
row = t->height - 1; \
if (row < 0) \
row = 0; \
}
#define TNS_CLAMP_TEXTURE_CONTINUE(t, col, row) \
{ \
if (col >= t->width) \
continue; \
if (col < 0) \
continue; \
if (row >= t->height) \
continue; \
if (row < 0) \
continue; \
}
static LANPR_TextureSample *lanpr_any_uncovered_samples(LANPR_PrivateData *pd)
{
return BLI_pophead(&pd->pending_samples);
}
int lanpr_direction_deviate(int From, int To)
{
return _TNS_Deviates[From - 1][To - 1];
}
int lanpr_detect_direction(LANPR_PrivateData *pd, int col, int row, int LastDirection)
{
int Deviate[9] = {100};
int MinDeviate = 0;
int i;
LANPR_TextureSample *ts;
for (i = 0; i < 8; i++) {
TNS_CLAMP_TEXTURE_CONTINUE(pd, (_TNS_colOffsets[i] + col), (_TNS_rowOffsets[i] + row));
if (ts = pd->sample_table[(_TNS_colOffsets[i] + col) +
(_TNS_rowOffsets[i] + row) * pd->width]) {
if (!LastDirection) {
return i + 1;
}
Deviate[i + 1] = lanpr_direction_deviate(i, LastDirection);
if (!MinDeviate || Deviate[MinDeviate] > Deviate[i + 1]) {
MinDeviate = i + 1;
}
}
}
return MinDeviate;
}
LANPR_LineStrip *lanpr_create_line_strip(LANPR_PrivateData *pd)
{
LANPR_LineStrip *ls = BLI_mempool_calloc(lanpr_share.mp_line_strip);
return ls;
}
LANPR_LineStripPoint *lanpr_append_point(
LANPR_PrivateData *pd, LANPR_LineStrip *ls, real X, real Y, real Z)
{
LANPR_LineStripPoint *lsp = BLI_mempool_calloc(lanpr_share.mp_line_strip_point);
lsp->P[0] = X;
lsp->P[1] = Y;
lsp->P[2] = Z;
BLI_addtail(&ls->points, lsp);
ls->point_count++;
return lsp;
}
LANPR_LineStripPoint *lanpr_push_point(
LANPR_PrivateData *pd, LANPR_LineStrip *ls, real X, real Y, real Z)
{
LANPR_LineStripPoint *lsp = BLI_mempool_calloc(lanpr_share.mp_line_strip_point);
lsp->P[0] = X;
lsp->P[1] = Y;
lsp->P[2] = Z;
BLI_addhead(&ls->points, lsp);
ls->point_count++;
return lsp;
}
void lanpr_destroy_line_strip(LANPR_PrivateData *pd, LANPR_LineStrip *ls)
{
LANPR_LineStripPoint *lsp;
while (lsp = BLI_pophead(&ls->points)) {
BLI_mempool_free(lanpr_share.mp_line_strip_point, lsp);
}
BLI_mempool_free(lanpr_share.mp_line_strip, ls);
}
void lanpr_remove_sample(LANPR_PrivateData *pd, int row, int col)
{
LANPR_TextureSample *ts;
ts = pd->sample_table[row * pd->width + col];
pd->sample_table[row * pd->width + col] = NULL;
BLI_remlink(&pd->pending_samples, ts);
ts->prev = NULL;
ts->next = NULL;
BLI_addtail(&pd->erased_samples, ts);
}
void lanpr_grow_snake_r(LANPR_PrivateData *pd,
LANPR_LineStrip *ls,
LANPR_LineStripPoint *ThisP,
int Direction)
{
LANPR_LineStripPoint *NewP = ThisP, *p2;
int Length = 5;
int l = 0;
int Deviate, Dir = Direction, NewDir;
int AddPoint;
int TX = NewP->P[0], TY = NewP->P[1];
while (NewDir = lanpr_detect_direction(pd, TX, TY, Dir)) {
AddPoint = 0;
Deviate = lanpr_direction_deviate(NewDir, Dir);
Dir = NewDir;
l++;
TX += _TNS_colOffsets[NewDir - 1];
TY += _TNS_rowOffsets[NewDir - 1];
if (Deviate < 2) {
lanpr_remove_sample(pd, TY, TX);
}
else if (Deviate < 3) {
lanpr_remove_sample(pd, TY, TX);
AddPoint = 1;
}
else {
lanpr_remove_sample(pd, TY, TX);
return;
}
if (AddPoint || l == Length) {
p2 = lanpr_append_point(pd, ls, TX, TY, 0);
NewP = p2;
l = 0;
}
}
if (TX != ThisP->P[0] || TY != ThisP->P[1]) {
lanpr_append_point(pd, ls, TX, TY, 0);
}
}
void lanpr_grow_snake_l(LANPR_PrivateData *pd,
LANPR_LineStrip *ls,
LANPR_LineStripPoint *ThisP,
int Direction)
{
LANPR_LineStripPoint *NewP = ThisP, *p2;
int Length = 5;
int l = 0;
int Deviate, Dir = Direction, NewDir;
int AddPoint;
int TX = NewP->P[0], TY = NewP->P[1];
while (NewDir = lanpr_detect_direction(pd, TX, TY, Dir)) {
AddPoint = 0;
Deviate = lanpr_direction_deviate(NewDir, Dir);
Dir = NewDir;
l++;
TX += _TNS_colOffsets[NewDir - 1];
TY += _TNS_rowOffsets[NewDir - 1];
if (Deviate < 2) {
lanpr_remove_sample(pd, TY, TX);
}
else if (Deviate < 4) {
lanpr_remove_sample(pd, TY, TX);
AddPoint = 1;
}
else {
lanpr_remove_sample(pd, TY, TX);
return;
}
if (AddPoint || l == Length) {
p2 = lanpr_push_point(pd, ls, TX, TY, 0);
NewP = p2;
l = 0;
}
}
if (TX != ThisP->P[0] || TY != ThisP->P[1]) {
lanpr_push_point(pd, ls, TX, TY, 0);
}
}
int lanpr_reverse_direction(int From)
{
From -= 4;
if (From <= 0) {
From += 8;
}
return From;
}
void lanpr_texture_to_ndc(int x, int y, int w, int h, float *x_ndc, float *y_ndc)
{
*x_ndc = interpf(1, -1, (float)x / (float)w);
*y_ndc = interpf(1, -1, (float)y / (float)h);
}
void lanpr_count_drawing_elements(LANPR_PrivateData *pd,
int *vert_count,
int *index_adjacent_count)
{
int v_count = 0;
int e_count = 0;
LANPR_LineStrip *ls;
for (ls = (LANPR_LineStrip *)(pd->line_strips.first); ls; ls = (ls->next)) {
v_count += (ls->point_count);
e_count += ((ls->point_count - 1) * 4);
}
*vert_count = v_count;
*index_adjacent_count = e_count;
}
GPUBatch *lanpr_get_snake_batch(LANPR_PrivateData *pd)
{
LANPR_LineStrip *ls;
LANPR_LineStripPoint *lsp, *plsp;
int i;
float *Verts;
float *Lengths;
float TotalLength = 0;
int v_count, e_count;
lanpr_count_drawing_elements(pd, &v_count, &e_count);
Verts = MEM_callocN(sizeof(float) * v_count * 2, "Verts buffer pre alloc");
Lengths = MEM_callocN(sizeof(float) * v_count * 2, "Length buffer pre alloc");
GPUIndexBufBuilder elb;
GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINES_ADJ, e_count, v_count);
int vert_offset = 0;
for (ls = (LANPR_LineStrip *)(pd->line_strips.first); ls; ls = (ls->next)) {
for (i = 0; i < ls->point_count - 1; i++) {
int v1 = i + vert_offset - 1;
int v2 = i + vert_offset;
int v3 = i + vert_offset + 1;
int v4 = i + vert_offset + 2;
if (v1 < 0) {
v1 = 0;
}
if (v4 >= v_count) {
v4 = v_count - 1;
}
GPU_indexbuf_add_line_adj_verts(&elb, v1, v2, v3, v4);
}
i = 0;
float xf, yf;
TotalLength = 0;
for (lsp = (LANPR_LineStripPoint *)(ls->points.first); lsp; lsp = (lsp->next)) {
lanpr_texture_to_ndc(lsp->P[0], lsp->P[1], pd->width, pd->height, &xf, &yf);
Verts[vert_offset * 2 + i * 2 + 0] = xf;
Verts[vert_offset * 2 + i * 2 + 1] = yf;
if (plsp = (LANPR_LineStripPoint *)(lsp->prev)) {
TotalLength += tMatDist2v(plsp->P, lsp->P);
Lengths[(vert_offset + i) * 2] = TotalLength;
}
i++;
}
ls->total_length = TotalLength;
i = 0;
for (lsp = (LANPR_LineStripPoint *)(ls->points.first); lsp; lsp = (lsp->next)) {
if (plsp = (LANPR_LineStripPoint *)(lsp->prev)) {
Lengths[(vert_offset + i) * 2 + 1] = ls->total_length - Lengths[(vert_offset + i) * 2];
}
i++;
}
vert_offset += (ls->point_count);
}
static GPUVertFormat format = {0};
static struct {
uint pos, uvs;
} attr_id;
if (format.attr_len == 0) {
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
attr_id.uvs = GPU_vertformat_attr_add(&format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
}
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
GPU_vertbuf_data_alloc(vbo, v_count);
for (int i = 0; i < v_count; ++i) {
GPU_vertbuf_attr_set(vbo, attr_id.pos, i, &Verts[i * 2]);
GPU_vertbuf_attr_set(vbo, attr_id.uvs, i, &Lengths[i * 2]);
}
MEM_freeN(Verts);
MEM_freeN(Lengths);
return GPU_batch_create_ex(
GPU_PRIM_LINES_ADJ, vbo, GPU_indexbuf_build(&elb), GPU_USAGE_STATIC | GPU_BATCH_OWNS_VBO);
}
void lanpr_snake_prepare_cache(LANPR_PrivateData *pd)
{
if (pd->line_result_8bit) {
MEM_freeN(pd->line_result_8bit);
}
pd->line_result_8bit = 0;
if (pd->line_result) {
MEM_freeN(pd->line_result);
}
pd->line_result = 0;
lanpr_share.mp_sample = BLI_mempool_create(sizeof(LANPR_TextureSample), 0, 512, BLI_MEMPOOL_NOP);
lanpr_share.mp_line_strip = BLI_mempool_create(sizeof(LANPR_LineStrip), 0, 512, BLI_MEMPOOL_NOP);
lanpr_share.mp_line_strip_point = BLI_mempool_create(
sizeof(LANPR_LineStripPoint), 0, 1024, BLI_MEMPOOL_NOP);
}
void lanpe_sanke_free_cache(LANPR_PrivateData *pd)
{
if (pd->line_result_8bit) {
MEM_freeN(pd->line_result_8bit);
}
pd->line_result_8bit = 0;
if (pd->line_result) {
MEM_freeN(pd->line_result);
}
pd->line_result = 0;
BLI_mempool_destroy(lanpr_share.mp_line_strip);
BLI_mempool_destroy(lanpr_share.mp_line_strip_point);
BLI_mempool_destroy(lanpr_share.mp_sample);
}
void lanpr_snake_free_readback_data(LANPR_PrivateData *pd)
{
if (pd->line_result_8bit) {
MEM_freeN(pd->line_result_8bit);
}
pd->line_result_8bit = 0;
if (pd->line_result) {
MEM_freeN(pd->line_result);
}
pd->line_result = 0;
}
void lanpr_snake_draw_scene(LANPR_TextureList *txl,
LANPR_FramebufferList *fbl,
LANPR_PassList *psl,
LANPR_PrivateData *pd,
SceneLANPR *lanpr,
GPUFrameBuffer *DefaultFB,
int is_render)
{
eGPUFrameBufferBits clear_bits = GPU_COLOR_BIT | GPU_DEPTH_BIT;
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float clear_depth = 1.0f;
uint clear_stencil = 0xFF;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = DEG_get_evaluated_scene(draw_ctx->depsgraph);
View3D *v3d = draw_ctx->v3d;
Object *camera;
if (v3d) {
RegionView3D *rv3d = draw_ctx->rv3d;
camera = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL;
}
else {
camera = scene->camera;
}
pd->znear = camera ? ((Camera *)camera->data)->clip_start : 0.1;
pd->zfar = camera ? ((Camera *)camera->data)->clip_end : 100;
pd->normal_clamp = lanpr->normal_clamp;
pd->normal_strength = lanpr->normal_strength;
pd->depth_clamp = lanpr->depth_clamp;
pd->depth_strength = lanpr->depth_strength;
GPU_framebuffer_bind(fbl->edge_intermediate);
DRW_draw_pass(psl->edge_intermediate);
if ((!lanpr->enable_vector_trace) && (!lanpr->display_thinning_result)) {
GPU_framebuffer_bind(DefaultFB);
DRW_multisamples_resolve(txl->depth, txl->edge_intermediate, 1);
return;
}
if (lanpr->display_thinning_result || lanpr->enable_vector_trace) {
pd->stage = 0;
GPU_framebuffer_bind(DefaultFB);
DRW_multisamples_resolve(txl->depth, txl->edge_intermediate, 1);
GPU_framebuffer_bind(fbl->edge_thinning);
DRW_draw_pass(psl->edge_thinning);
GPU_framebuffer_bind(DefaultFB);
DRW_multisamples_resolve(txl->depth, txl->color, 1);
pd->stage = 1;
GPU_framebuffer_bind(fbl->edge_thinning);
DRW_draw_pass(psl->edge_thinning);
GPU_framebuffer_bind(DefaultFB);
DRW_multisamples_resolve(txl->depth, txl->color, 1);
pd->stage = 0;
GPU_framebuffer_bind(fbl->edge_thinning);
DRW_draw_pass(psl->edge_thinning);
GPU_framebuffer_bind(DefaultFB);
DRW_multisamples_resolve(txl->depth, txl->color, 1);
pd->stage = 1;
GPU_framebuffer_bind(fbl->edge_thinning);
DRW_draw_pass(psl->edge_thinning);
GPU_framebuffer_bind(DefaultFB);
DRW_multisamples_resolve(txl->depth, txl->color, 1);
if (!lanpr->enable_vector_trace) {
return;
}
}
int texw = GPU_texture_width(txl->edge_intermediate),
texh = GPU_texture_height(txl->edge_intermediate);
;
int tsize = texw * texh;
int recreate = 0;
if (tsize != pd->width * pd->height) {
recreate = 1;
}
if (recreate || !pd->line_result) {
if (pd->line_result) {
MEM_freeN(pd->line_result);
}
pd->line_result = MEM_callocN(sizeof(float) * tsize, "Texture readback buffer");
if (pd->line_result_8bit) {
MEM_freeN(pd->line_result_8bit);
}
pd->line_result_8bit = MEM_callocN(sizeof(unsigned char) * tsize,
"Texture readback buffer 8bit");
if (pd->sample_table) {
MEM_freeN(pd->sample_table);
}
pd->sample_table = MEM_callocN(sizeof(void *) * tsize, "Texture readback buffer 8bit");
pd->width = texw;
pd->height = texh;
}
GPU_framebuffer_bind(DefaultFB);
GPU_framebuffer_read_color(DefaultFB, 0, 0, texw, texh, 1, 0, pd->line_result);
float sample;
int h, w;
for (h = 0; h < texh; h++) {
for (w = 0; w < texw; w++) {
int index = h * texw + w;
if ((sample = pd->line_result[index]) > 0.9) {
pd->line_result_8bit[index] = 255;
LANPR_TextureSample *ts = BLI_mempool_calloc(lanpr_share.mp_sample);
BLI_addtail(&pd->pending_samples, ts);
pd->sample_table[index] = ts;
ts->X = w;
ts->Y = h;
}
else {
pd->sample_table[index] = 0;
}
}
}
LANPR_TextureSample *ts;
LANPR_LineStrip *ls;
LANPR_LineStripPoint *lsp;
while (ts = lanpr_any_uncovered_samples(pd)) {
int Direction = 0;
LANPR_LineStripPoint tlsp = {0};
tlsp.P[0] = ts->X;
tlsp.P[1] = ts->Y;
if (Direction = lanpr_detect_direction(pd, ts->X, ts->Y, Direction)) {
BLI_addtail(&pd->line_strips, (ls = lanpr_create_line_strip(pd)));
lsp = lanpr_append_point(pd, ls, ts->X, ts->Y, 0);
lanpr_remove_sample(pd, ts->Y, ts->X);
lanpr_grow_snake_r(pd, ls, lsp, Direction);
lanpr_grow_snake_l(pd, ls, lsp, lanpr_reverse_direction(Direction));
}
}
float use_background_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
copy_v3_v3(use_background_color, &scene->world->horr);
use_background_color[3] = scene->r.alphamode ? 0.0f : 1.0f;
GPU_framebuffer_bind(DefaultFB);
GPU_framebuffer_clear(DefaultFB, clear_bits, use_background_color, clear_depth, clear_stencil);
GPU_framebuffer_bind(fbl->edge_intermediate);
clear_bits = GPU_COLOR_BIT;
GPU_framebuffer_clear(
fbl->edge_intermediate, clear_bits, use_background_color, clear_depth, clear_stencil);
float *tld = &lanpr->taper_left_distance, *tls = &lanpr->taper_left_strength,
*trd = &lanpr->taper_right_distance, *trs = &lanpr->taper_right_strength;
GPUBatch *snake_batch = lanpr_get_snake_batch(pd);
lanpr_snake_prepare_cache(pd);
psl->snake_pass = DRW_pass_create("Snake Visualization Pass",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
DRW_STATE_DEPTH_ALWAYS);
pd->snake_shgrp = DRW_shgroup_create(lanpr_share.snake_connection_shader, psl->snake_pass);
DRW_shgroup_uniform_float(pd->snake_shgrp, "line_width", &lanpr->line_thickness, 1);
DRW_shgroup_uniform_float(pd->snake_shgrp, "taper_l_dist", tld, 1);
DRW_shgroup_uniform_float(pd->snake_shgrp, "taper_r_dist", tls, 1);
DRW_shgroup_uniform_float(
pd->snake_shgrp, "taper_l_strength", (lanpr->flags & LANPR_SAME_TAPER) ? tld : trd, 1);
DRW_shgroup_uniform_float(
pd->snake_shgrp, "taper_r_strength", (lanpr->flags & LANPR_SAME_TAPER) ? tls : trs, 1);
DRW_shgroup_uniform_vec4(pd->snake_shgrp, "line_color", lanpr->line_color, 1);
DRW_shgroup_call(pd->snake_shgrp, snake_batch, NULL);
GPU_framebuffer_bind(fbl->edge_intermediate);
DRW_draw_pass(psl->snake_pass);
GPU_BATCH_DISCARD_SAFE(snake_batch);
BLI_mempool_clear(lanpr_share.mp_sample);
BLI_mempool_clear(lanpr_share.mp_line_strip);
BLI_mempool_clear(lanpr_share.mp_line_strip_point);
pd->pending_samples.first = pd->pending_samples.last = 0;
pd->erased_samples.first = pd->erased_samples.last = 0;
pd->line_strips.first = pd->line_strips.last = 0;
GPU_framebuffer_bind(DefaultFB);
DRW_multisamples_resolve(txl->depth, txl->edge_intermediate, 1);
lanpe_sanke_free_cache(pd);
}

View File

@@ -0,0 +1,6 @@
in vec4 out_color;
void main()
{
gl_FragData[0] = vec4(out_color.rgb, 1);
}

View File

@@ -0,0 +1,193 @@
layout(points) in;
layout(triangle_strip, max_vertices = 6) out;
uniform sampler2D vert0_tex; // L
uniform sampler2D vert1_tex; // R
uniform sampler2D face_normal0_tex;
uniform sampler2D face_normal1_tex; // caution: these are face normals!
uniform sampler2D edge_mask_tex;
// uniform float uValue0; // buffer_w
uniform vec4 viewport; // viewport
uniform float depth_offset;
// these are for depth related thickness control;
uniform float line_thickness;
uniform float depth_width_influence;
uniform float depth_width_curve;
uniform float depth_alpha_influence;
uniform float depth_alpha_curve;
uniform float z_near;
uniform float z_far;
uniform vec4 background_color;
uniform vec4 contour_color;
uniform vec4 crease_color;
uniform vec4 material_color;
uniform vec4 edge_mark_color;
uniform vec4 intersection_color;
uniform float line_thickness_contour;
uniform float line_thickness_crease;
uniform float line_thickness_material;
uniform float line_thickness_edge_mark;
uniform float line_thickness_intersection;
// the same as software mode
uniform int normal_mode;
uniform int normal_effect_inverse;
uniform vec3 normal_direction; // also used as point position
uniform float normal_ramp_begin;
uniform float normal_ramp_end;
uniform float normal_thickness_start;
uniform float normal_thickness_end;
float use_thickness;
out vec4 out_color;
vec4 use_color;
float get_linear_depth(float z)
{
float ze = 2.0 * z_near * z_far / (z_far + z_near - z * (z_far - z_near));
return (ze - z_near) / (z_far - z_near);
}
float curve_01(float z, float factor)
{
return pow(z, 1 - factor); // factor is -inf~1-eps
}
vec4 apply_scale(vec4 center, vec4 a)
{
float lz = get_linear_depth(center.z);
float depth_factor = mix(0, curve_01(lz, depth_width_curve), depth_width_influence);
return mix(a, center, depth_factor);
}
void emit_color_and_alpha(vec4 a, int is_crease, float crease_fading)
{
float lz = get_linear_depth(a.z);
float alpha_factor = mix(0, curve_01(lz, depth_alpha_curve), depth_alpha_influence);
float alpha_crease_fading = alpha_factor;
if (is_crease > 0)
alpha_crease_fading = mix(alpha_factor, 1, crease_fading * 2); // fading=0.5 -> fade all
out_color = vec4(use_color.rgb, mix(1, 0, alpha_crease_fading));
}
void draw_line(vec4 p1, vec4 p2, int is_crease)
{
vec4 Line = p2 - p1;
vec4 Normal = normalize(vec4(-Line.y, Line.x, 0, 0));
vec4 a, b, c, d;
vec4 offset = Normal * use_thickness * 0.001;
// correct thickness
offset.x *= viewport.w / viewport.z;
a = p1 + offset;
b = p1 - offset;
c = p2 + offset;
d = p2 - offset;
a = apply_scale(p1, a);
b = apply_scale(p1, b);
c = apply_scale(p2, c);
d = apply_scale(p2, d);
gl_Position = vec4(a.xy, a.z - depth_offset, 1);
emit_color_and_alpha(a, is_crease, p2.w);
EmitVertex();
gl_Position = vec4(b.xy, b.z - depth_offset, 1);
emit_color_and_alpha(b, is_crease, p2.w);
EmitVertex();
gl_Position = vec4(c.xy, c.z - depth_offset, 1);
emit_color_and_alpha(c, is_crease, p2.w);
EmitVertex();
gl_Position = vec4(b.xy, b.z - depth_offset, 1);
emit_color_and_alpha(b, is_crease, p2.w);
EmitVertex();
gl_Position = vec4(c.xy, c.z - depth_offset, 1);
emit_color_and_alpha(c, is_crease, p2.w);
EmitVertex();
gl_Position = vec4(d.xy, d.z - depth_offset, 1);
emit_color_and_alpha(d, is_crease, p2.w);
EmitVertex();
EndPrimitive();
}
float factor_to_thickness(float factor)
{
float r = (factor - normal_ramp_begin) / (normal_ramp_end - normal_ramp_begin);
if (r > 1)
r = 1;
if (r < 0)
r = 0;
float thickness = normal_effect_inverse == 1 ?
mix(normal_thickness_start, normal_thickness_end, r) :
mix(normal_thickness_end, normal_thickness_start, r);
return thickness;
}
void main()
{
vec4 p1 = texelFetch(vert0_tex, ivec2(gl_in[0].gl_Position.xy), 0);
vec4 p2 = texelFetch(vert1_tex, ivec2(gl_in[0].gl_Position.xy), 0);
vec4 n1 = texelFetch(face_normal0_tex, ivec2(gl_in[0].gl_Position.xy), 0);
vec4 n2 = texelFetch(face_normal1_tex, ivec2(gl_in[0].gl_Position.xy), 0);
vec3 use_normal = normalize(mix(n1, n2, 0.5).xyz);
if (p1.w == 0 && p2.w == 0)
return;
vec4 edge_mask = texelFetch(edge_mask_tex, ivec2(gl_in[0].gl_Position.xy), 0);
int is_crease = 0;
float th = line_thickness;
if (normal_mode == 0) {
th = line_thickness;
}
else if (normal_mode == 1) {
float factor = dot(use_normal, normal_direction);
th = factor_to_thickness(factor);
}
else if (normal_mode == 2) {
float factor = dot(use_normal, normal_direction);
th = factor_to_thickness(factor);
}
if (edge_mask.g > 0) {
use_color = edge_mark_color;
use_thickness = th * line_thickness_edge_mark;
}
else if (edge_mask.r > 0) {
use_color = material_color;
use_thickness = th * line_thickness_material;
}
else if (edge_mask.b > 0) {
use_color = intersection_color;
use_thickness = th * line_thickness_intersection;
}
else if (p2.w != p1.w) {
use_color = crease_color;
use_thickness = th * line_thickness_crease;
is_crease = 1;
}
else {
use_color = contour_color;
use_thickness = th * line_thickness_contour;
}
draw_line(p1, p2, is_crease);
}

View File

@@ -0,0 +1,495 @@
uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ViewMatrixInverse;
uniform mat4 ProjectionMatrix;
uniform mat4 ProjectionMatrixInverse;
uniform int use_contour;
uniform int use_crease;
uniform int use_material;
uniform int use_edge_mark;
uniform int use_intersection;
uniform float crease_threshold;
uniform float crease_fade_threshold;
uniform int is_perspective; // persp and orth use different crease line determin method
// uniform float sample_step; // length calculation unused now.
// uniform int buffer_width;
uniform vec4 viewport;
uniform sampler2D vert0_tex;
uniform sampler2D vert1_tex;
uniform sampler2D face_normal0_tex;
uniform sampler2D face_normal1_tex;
uniform sampler2D edge_mask_tex;
// uniform sampler2D TexSample4;
//#define path_start_end_ptrs TexSample4 // edge adjacent data
// calculate in shader
vec3 view_pos;
vec3 view_dir;
int is_crease; // we calculate crease in GPU because it's faster and we have normal data anyway.
// and we need to indicate crease test success result using p1.w==1 && p2.w==0
float crease_strength;
// these are for adapting argument names...
#define modelview (ViewMatrix * ModelMatrix)
#define projection ProjectionMatrix
#define inverse_projection ProjectionMatrixInverse
// ivec2 getTexturePix(vec2 fb_coord){
// vec2 n = ((fb_coord+vec2(1,1))/2).xy;
// return ivec2(n.x*buffer_width,n.y*buffer_width);
//}
// Amount of padding around a segment in the segment atlas.
// The amount of padding rolls off to zero for short segments,
// and is zero for segments in the middle of paths.
vec2 segmentPadding(float num_samples, float index, float start_index, float end_index)
{
const float MAX_PADDING = 10.0;
float amount = floor(clamp((num_samples - 2.0) * 0.5, 0.0, MAX_PADDING));
float left = amount * max(1.0 + start_index - index, 0.0);
float right = amount * max(1.0 + index - end_index, 0.0);
return vec2(left, right);
}
// Converting from linear indices to 2D coordinates and back:
float coordinateToIndex(vec2 coord, float buf_size)
{
vec2 floor_coord = floor(coord);
return floor_coord.x + floor_coord.y * buf_size;
}
vec2 indexToCoordinate(float index, float buf_size)
{
return vec2(mod(index, buf_size), floor(index / buf_size));
}
// Packing and unpacking values in the segment atlas offset texture:
float unpackNumSamples(vec4 offset_texel)
{
return offset_texel.b;
}
float unpackArcLength(vec4 offset_texel)
{
return offset_texel.a;
}
float unpackSampleOffset(vec4 offset_texel)
{
return offset_texel.r;
}
float unpackArcLengthOffset(vec4 offset_texel)
{
return offset_texel.g;
}
vec4 packOffsetTexel(float num_samples, float arc_length)
{
return vec4(num_samples, arc_length, num_samples, arc_length);
}
vec4 packOffsetTexel(float num_samples,
float arc_length,
float num_samples_offset,
float arc_length_offset)
{
return vec4(num_samples_offset, arc_length_offset, num_samples, arc_length);
}
// Packing and unpacking values in the 3D vertex positions:
float unpackPathStart(vec4 texel)
{
return texel.r;
}
float unpackPathEnd(vec4 texel)
{
return texel.g;
}
float unpackPathLength(vec4 texel)
{
return texel.b;
}
// Projecting and unprojecting:
vec2 clipToWindow(sampler2D clip_positions, vec4 viewport, ivec2 coordinate)
{
vec4 clip = texelFetch(clip_positions, coordinate, 0);
vec3 post_div = clip.xyz / clip.w;
return (post_div.xy + vec2(1.0, 1.0)) * 0.5 * viewport.zw;
}
vec2 clipToWindow(vec4 clip, vec4 viewport)
{
vec3 post_div = clip.xyz / clip.w;
return (post_div.xy + vec2(1.0, 1.0)) * 0.5 * viewport.zw;
}
// Path id encoding and decoding.
bool idEqualGreaterThan(vec3 a, vec3 b)
{
float ida = a.b * 256.0 * 256.0 + a.g * 256.0 + a.r;
float idb = b.b * 256.0 * 256.0 + b.g * 256.0 + b.r;
const float small = 0.001;
return ida - idb > -small;
}
bool idsEqual(vec3 a, vec3 b)
{
float ida = a.b * 256.0 * 256.0 + a.g * 256.0 + a.r;
float idb = b.b * 256.0 * 256.0 + b.g * 256.0 + b.r;
const float small = 0.001;
return abs(ida - idb) < small;
}
vec3 idToColor(float id)
{
id = id + 1.0;
float blue = floor(id / (256.0 * 256.0));
float green = floor(id / 256.0) - blue * 256.0;
float red = id - green * 256.0 - blue * 256.0 * 256.0;
return vec3(red, green, blue) / 255.0;
}
struct segment {
vec3 p1;
vec3 p2;
bool on_screen;
};
float epsilon = 0.00001;
float xmin = -1.1;
float xmax = 1.1;
float ymin = -1.1;
float ymax = 1.1;
// this is a conservative offscreen rejection test ... catches most cases
bool segmentOffScreen(vec3 p0, vec3 p1)
{
return ((p0[0] < xmin && p1[0] < xmin) || (p0[0] > xmax && p1[0] > xmax) ||
(p0[1] < ymin && p1[1] < ymin) || (p0[1] > ymax && p1[1] > ymax));
}
bool pointOffScreen(vec3 p)
{
return (p[0] < xmin || p[0] > xmax || p[1] < ymin || p[1] > ymax);
}
vec3 clipMinMaxX(vec3 outv, vec3 inv)
{
vec3 ret = outv;
if (outv.x < xmin) {
float t = (xmin - outv.x) / (inv.x - outv.x);
ret = t * inv + (1.0 - t) * outv;
}
else if (outv.x > xmax) {
float t = (xmax - inv.x) / (outv.x - inv.x);
ret = t * outv + (1.0 - t) * inv;
}
return ret;
}
vec3 clipMinMaxY(vec3 outv, vec3 inv)
{
vec3 ret = outv;
if (outv.y < ymin) {
float t = (ymin - outv.y) / (inv.y - outv.y);
ret = t * inv + (1.0 - t) * outv;
}
else if (outv.y > ymax) {
float t = (ymax - inv.y) / (outv.y - inv.y);
ret = t * outv + (1.0 - t) * inv;
}
return ret;
}
vec3 clipSegmentOneOut(vec3 off_screen, vec3 on_screen)
{
vec3 outv = off_screen;
// first clip against the x coords
outv = clipMinMaxX(outv, on_screen);
// now clip against the y coords using the newly clipped point
outv = clipMinMaxY(outv, on_screen);
return outv;
}
segment clipToMin(float min, segment inseg, float p1val, float p2val)
{
float minPos = min + epsilon;
float minNeg = min - epsilon;
segment outseg = segment(inseg.p1, inseg.p2, inseg.on_screen);
// trivial reject
if ((p1val < minPos && p2val < minPos) || inseg.on_screen == false) {
outseg.on_screen = false;
}
// cut at min
if (p1val < minPos) {
float t = (min - p1val) / (p2val - p1val);
outseg.p1 = t * inseg.p2 + (1.0 - t) * inseg.p1;
}
else if (p2val < minPos) {
float t = (min - p2val) / (p1val - p2val);
outseg.p2 = t * inseg.p1 + (1.0 - t) * inseg.p2;
}
return outseg;
}
segment clipToMax(float max, segment inseg, float p1val, float p2val)
{
float maxPos = max + epsilon;
float maxNeg = max - epsilon;
segment outseg = segment(inseg.p1, inseg.p2, inseg.on_screen);
// trivial reject
if ((p1val > maxNeg && p2val > maxNeg) || inseg.on_screen == false) {
outseg.on_screen = false;
}
// cut at max
if (p1val > maxNeg) {
float t = (max - p2val) / (p1val - p2val);
outseg.p1 = t * inseg.p1 + (1.0 - t) * inseg.p2;
}
else if (p2val > maxNeg) {
float t = (max - p1val) / (p2val - p1val);
outseg.p2 = t * inseg.p2 + (1.0 - t) * inseg.p1;
}
return outseg;
}
segment clipSegmentBothOut(vec3 p1, vec3 p2)
{
segment seg = segment(p1, p2, true);
seg = clipToMin(xmin, seg, seg.p1.x, seg.p2.x);
seg = clipToMax(xmax, seg, seg.p1.x, seg.p2.x);
seg = clipToMin(ymin, seg, seg.p1.y, seg.p2.y);
seg = clipToMax(ymax, seg, seg.p1.y, seg.p2.y);
return seg;
}
vec3 clipSegmentToNear(vec3 off_screen, vec3 on_screen)
{
// see http://members.tripod.com/~Paul_Kirby/vector/Vplanelineint.html
vec3 a = off_screen;
vec3 b = on_screen;
vec3 c = view_pos + view_dir;
vec3 n = view_dir;
float t = dot((c - a), n) / dot((b - a), n);
vec3 clipped = a + (b - a) * t;
return clipped;
}
bool pointBeyondNear(vec3 p)
{
vec3 offset = p - view_pos;
bool beyond = dot(offset, view_dir) > 0.0;
return beyond;
}
// 1 for contour 2 for others
int testProfileEdge(ivec2 texcoord, vec3 world_position)
{
// This should really be the inverse transpose of the modelview matrix, but
// that only matters if the camera has a weird anisotropic scale or skew.
mat3 nm = mat3(transpose(inverse(ModelMatrix)));
vec3 face_normal_0 = mat3(nm) * texelFetch(face_normal0_tex, texcoord, 0).xyz;
vec3 face_normal_1 = mat3(nm) * texelFetch(face_normal1_tex, texcoord, 0).xyz;
vec3 camera_to_line = is_perspective == 1 ? world_position - view_pos :
view_dir; // modelview * vec4(world_position, 1.0);
vec4 edge_mask = texelFetch(edge_mask_tex, texcoord, 0);
float dot0 = dot(camera_to_line.xyz, vec3(face_normal_0.xyz));
float dot1 = dot(camera_to_line.xyz, vec3(face_normal_1.xyz));
float dot2 = dot(normalize(vec3(face_normal_0.xyz)), normalize(vec3(face_normal_1.xyz)));
bool contour = (dot0 >= 0.0 && dot1 <= 0.0) || (dot0 <= 0.0 && dot1 >= 0.0);
is_crease = (((use_contour > 0 && !contour) || use_contour == 0) &&
((dot2 < crease_threshold) || (dot2 < crease_fade_threshold))) ?
1 :
0;
crease_strength = (is_crease > 0 && dot2 > crease_threshold) ?
((dot2 - crease_threshold) / (crease_fade_threshold - crease_threshold) /
2) :
0;
// use 0 to 0.5 to repesent the range, because 1 will represent another meaning
if (use_contour > 0 && contour)
return 1;
if (((use_crease > 0) && (is_crease > 0)) || ((use_material > 0) && (edge_mask.r > 0)) ||
((use_edge_mark > 0) && (edge_mask.g > 0)) ||
((use_intersection > 0) && (edge_mask.b > 0)) || false)
return 2;
return 0;
}
void main()
{
view_dir = -mat3(ViewMatrixInverse) * vec3(0, 0, 1);
view_pos = (ViewMatrixInverse)[3].xyz;
xmin *= viewport.z / viewport.w;
xmax *= viewport.z / viewport.w;
// look up the world positions of the segment vertices
ivec2 texcoord = ivec2(gl_FragCoord.xy);
vec4 v0_world_pos = texelFetch(vert0_tex, texcoord, 0);
vec4 v1_world_pos = texelFetch(vert1_tex, texcoord, 0);
v0_world_pos = ModelMatrix * vec4(v0_world_pos.xyz, 1);
v1_world_pos = ModelMatrix * vec4(v1_world_pos.xyz, 1);
// early exit if there are no vertices here to process
if (v0_world_pos.w < 0.5) {
// no vertex data to process
gl_FragData[0] = vec4(0.5, 0.0, 0.0, 0.0);
gl_FragData[1] = vec4(0.5, 0.5, 0.0, 0.0);
// must write something into fragdata[2] to prevent
// buffer 2 from getting filled with garbage? (very weird)
gl_FragData[2] = vec4(0.0, 1.0, 0.0, 0.0);
return;
}
vec3 v0_clipped_near = v0_world_pos.xyz;
vec3 v1_clipped_near = v1_world_pos.xyz;
if (is_perspective == 1) {
// clip to the near plane
bool v0_beyond_near = pointBeyondNear(v0_world_pos.xyz);
bool v1_beyond_near = pointBeyondNear(v1_world_pos.xyz);
if (!v0_beyond_near && !v1_beyond_near) {
// segment entirely behind the camera
gl_FragData[0] = vec4(0.0, 1.0, 0.0, 0.0);
gl_FragData[1] = vec4(0.0, 0.0, 1.0, 0.0);
gl_FragData[2] = vec4(0.0, 1.0, 0.0, 0.0);
return;
}
else if (!v0_beyond_near) {
v0_clipped_near = clipSegmentToNear(v0_world_pos.xyz, v1_clipped_near);
}
else if (!v1_beyond_near) {
v1_clipped_near = clipSegmentToNear(v1_world_pos.xyz, v0_clipped_near);
}
}
// If this segment is a profile edge, test to see if it should be turned on.
// if (v1_world_pos.w > 0.5)
//{
int profile_on = testProfileEdge(texcoord, v0_clipped_near);
if (profile_on == 0) {
// Profile edge should be off.
gl_FragData[0] = vec4(0.0, 1.0, 0.5, 0.0);
gl_FragData[1] = vec4(0.0, 0.5, 1.0, 0.0);
gl_FragData[2] = vec4(0.0, 1.0, 0.0, 0.0);
return;
}
//}
// project
vec4 v0_pre_div = projection * ViewMatrix * vec4(v0_clipped_near, 1.0);
vec4 v1_pre_div = projection * ViewMatrix * vec4(v1_clipped_near, 1.0);
// perspective divide
vec3 v0_clip_pos = v0_pre_div.xyz;
vec3 v1_clip_pos = v1_pre_div.xyz;
if (is_perspective == 1) {
v0_clip_pos /= v0_pre_div.w;
v1_clip_pos /= v1_pre_div.w;
}
// clip to frustum
bool v0_on_screen = !pointOffScreen(v0_clip_pos);
bool v1_on_screen = !pointOffScreen(v1_clip_pos);
if (!v0_on_screen && !v1_on_screen) {
segment ret = clipSegmentBothOut(v0_clip_pos, v1_clip_pos);
if (ret.on_screen == false) {
// segment entirely off screen: BLUE / MAGENTA / BLACK
gl_FragData[0] = vec4(0.0, 0.0, 1.0, 0.0);
gl_FragData[1] = vec4(1.0, 0.0, 1.0, 0.0);
gl_FragData[2] = vec4(0.0, 0.0, 0.0, 0.0);
return;
}
v0_clip_pos = ret.p1;
v1_clip_pos = ret.p2;
}
else if (!v0_on_screen) {
v0_clip_pos = clipSegmentOneOut(v0_clip_pos, v1_clip_pos);
}
else if (!v1_on_screen) {
v1_clip_pos = clipSegmentOneOut(v1_clip_pos, v0_clip_pos);
}
// convert to window coordinates
vec2 v0_screen = (v0_clip_pos.xy + vec2(1.0, 1.0)) * 0.5 * viewport.zw;
vec2 v1_screen = (v1_clip_pos.xy + vec2(1.0, 1.0)) * 0.5 * viewport.zw;
// if(v1_screen == v0_screen){ gl_FragData[0] = vec4(1,0,0,1); return; }
float segment_screen_length = length(v0_screen - v1_screen);
// scale the length by sample_step to get the number of samples
// float num_samples = segment_screen_length / sample_step;
// num_samples = ceil(num_samples);
// Unproject and reproject the final clipped positions
// so that interpolation is perspective correct later on.
vec4 v0_world = inverse_projection * vec4(v0_clip_pos, 1.0);
vec4 v1_world = inverse_projection * vec4(v1_clip_pos, 1.0);
vec4 v0_clipped_pre_div = projection * v0_world;
vec4 v1_clipped_pre_div = projection * v1_world;
// Add some padding to the number of samples so that filters
// that work along the segment length (such as overshoot)
// have some room to work with at the end of each segment.
// vec4 path_texel = texelFetch(path_start_end_ptrs, texcoord,0);
// vec2 padding = segmentPadding(num_samples,
// coordinateToIndex(texcoord, buffer_width),
// unpackPathStart(path_texel),
// unpackPathEnd(path_texel));
// float total_padding = padding.x + padding.y;
// if(v0_clipped_pre_div == v1_clipped_pre_div)gl_FragData[0] =vec4(1);
// else gl_FragData[0] = vec4(v0_clipped_pre_div.xyz,1);
gl_FragData[0] = vec4(v0_clipped_pre_div.xyz,
1); // contour has priority, modification cause trouble
gl_FragData[1] = vec4(v1_clipped_pre_div.xyz, is_crease > 0 ? crease_strength : 1);
// gl_FragData[2] = packOffsetTexel(num_samples, segment_screen_length,
// num_samples, segment_screen_length);
// num_samples + total_padding, segment_screen_length);
}

View File

@@ -0,0 +1,6 @@
in vec4 pos;
void main()
{
gl_Position = pos;
}

View File

@@ -0,0 +1,88 @@
in vec4 uvcoordsvar;
uniform sampler2DMS tex_sampe_0; // depth
uniform sampler2DMS tex_sample_1; // color
uniform sampler2DMS tex_sample_2; // normal
uniform float normal_clamp; // normal clamp
uniform float normal_strength; // normal strength
uniform float depth_clamp; // depth clamp
uniform float depth_strength; // depth strength
uniform float z_near; // z_near
uniform float z_far; // z_far
mat3 sx = mat3(1.0, 2.0, 1.0, 0.0, 0.0, 0.0, -1.0, -2.0, -1.0);
mat3 sy = mat3(1.0, 0.0, -1.0, 2.0, 0.0, -2.0, 1.0, 0.0, -1.0);
vec3 rgb2hsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
float linearDepth(float depthSample)
{
float d = 2.0 * depthSample - 1.0;
float zLinear = 2.0 * z_near * z_far / (z_far + z_near - d * (z_far - z_near));
return zLinear;
}
vec4 DetectEdge(sampler2DMS tex, float clamp, float strength)
{
mat3 I = mat3(0);
mat3 J = mat3(0);
mat3 K = mat3(0);
ivec2 texSize = textureSize(tex);
ivec2 sp = ivec2(uvcoordsvar.xy * texSize);
vec4 cs = vec4(0);
// sample hardcoded (8) now
for (int s = 0; s < 8; s++) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
vec4 col = texelFetch(tex, sp + ivec2(i - 1, j - 1), s);
vec3 sample1 = vec3((col.r));
vec3 sample2 = vec3((col.g));
vec3 sample3 = vec3((col.b));
I[i][j] += length(sample1) / 8;
J[i][j] += length(sample2) / 8;
K[i][j] += length(sample3) / 8;
}
}
cs += texelFetch(tex_sample_1, sp, s) / 8;
}
float gx1 = dot(sx[0], I[0]) + dot(sx[1], I[1]) + dot(sx[2], I[2]);
float gy1 = dot(sy[0], I[0]) + dot(sy[1], I[1]) + dot(sy[2], I[2]);
float g1 = sqrt(pow(gx1, 2.0) + pow(gy1, 2.0));
float gx2 = dot(sx[0], J[0]) + dot(sx[1], J[1]) + dot(sx[2], J[2]);
float gy2 = dot(sy[0], J[0]) + dot(sy[1], J[1]) + dot(sy[2], J[2]);
float g2 = sqrt(pow(gx2, 2.0) + pow(gy2, 2.0));
float gx3 = dot(sx[0], K[0]) + dot(sx[1], K[1]) + dot(sx[2], K[2]);
float gy3 = dot(sy[0], K[0]) + dot(sy[1], K[1]) + dot(sy[2], K[2]);
float g3 = sqrt(pow(gx3, 2.0) + pow(gy3, 2.0));
float value = max(max(g1, g2), g3);
value = value > clamp ? value : 0;
return vec4(vec3(value * strength), 1);
// if(value<clamp) value=0;
// return vec4(pow(value,strength));
}
void main()
{
float nc = normal_clamp; //(normal_clamp==0? 0.01:normal_clamp);
float ns = normal_strength; //(normal_strength==0? 5: normal_strength);
float dc = depth_clamp; //(depth_clamp==0? 0.2: depth_clamp);
float ds = depth_strength; //(depth_strength==0? 2.5: depth_strength);
vec4 diffuse = vec4(1, 1, 1, 1);
vec4 color = (DetectEdge(tex_sampe_0, dc, ds) + DetectEdge(tex_sample_2, nc, ns));
gl_FragColor = color;
};

View File

@@ -0,0 +1,329 @@
in vec4 uvcoordsvar;
uniform sampler2D tex_sample_0;
uniform int stage;
int decisions[256] = int[](0,
0,
1,
1,
0,
0,
1,
1,
1,
1,
0,
1,
1,
1,
0,
1,
1,
1,
0,
0,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
1,
1,
0,
0,
1,
1,
1,
1,
0,
1,
1,
1,
0,
1,
1,
1,
0,
0,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
1,
1,
1,
0,
0,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
0,
1,
1,
0,
0,
1,
1,
0,
1,
1,
1,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
0,
1,
1,
1,
1,
0,
1,
1,
1,
0,
1,
1,
1,
0,
0,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
1,
1,
0,
0,
1,
1,
1,
1,
0,
1,
1,
1,
0,
1,
1,
1,
0,
0,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
0,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
0,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
0,
1,
1,
0,
0,
1,
1,
0,
1,
1,
1,
0,
0,
1,
1,
0,
0,
1,
1,
1,
0,
1,
1,
0,
0,
1,
0,
0,
0);
int PickPixel(ivec2 sp)
{
vec4 accum = vec4(0);
// for(int i=0;i<4;i++){
accum += texelFetch(tex_sample_0, sp, 0);
//}
return (accum.r > 0.9) ? 1 : 0;
}
// MZS Thinning method, implemented by YimingWu
void main()
{
ivec2 texSize = textureSize(tex_sample_0, 0);
ivec2 sp = ivec2(uvcoordsvar.xy * texSize);
vec4 OriginalColor = texelFetch(tex_sample_0, sp, 0);
int p2 = PickPixel(sp + ivec2(0, +1));
int p3 = PickPixel(sp + ivec2(+1, +1));
int p4 = PickPixel(sp + ivec2(+1, 0));
int p5 = PickPixel(sp + ivec2(+1, -1));
int p6 = PickPixel(sp + ivec2(0, -1));
int p7 = PickPixel(sp + ivec2(-1, -1));
int p8 = PickPixel(sp + ivec2(-1, 0));
int p9 = PickPixel(sp + ivec2(-1, +1));
int Bp1 = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9;
bool bp2 = bool(p2);
bool bp3 = bool(p3);
bool bp4 = bool(p4);
bool bp5 = bool(p5);
bool bp6 = bool(p6);
bool bp7 = bool(p7);
bool bp8 = bool(p8);
bool bp9 = bool(p9);
int Cp1 = int(!bp2 && (bp3 || bp4)) + int(!bp4 && (bp5 || bp6)) + int(!bp6 && (bp7 || bp8)) +
int(!bp8 && (bp9 || bp2));
if (stage == 0) {
if (((sp.x + sp.y) % 2 == 0) && (Cp1 == 1) && (Bp1 >= 2 && Bp1 <= 7) && (p2 * p4 * p6 == 0) &&
(p4 * p6 * p8 == 0)) {
gl_FragColor = vec4(0, 0, 0, 1);
return;
}
gl_FragColor = OriginalColor;
}
else {
if (((sp.x + sp.y) % 2 != 0) && (Cp1 == 1) && (Bp1 >= 1 && Bp1 <= 7) && (p2 * p4 * p8 == 0) &&
(p2 * p6 * p8 == 0)) {
gl_FragColor = vec4(0, 0, 0, 1);
return;
}
gl_FragColor = OriginalColor;
}
// int test = PickPixel(sp+ivec2(-1,-1))*1 + PickPixel(sp+ivec2(0 ,-1))*2 +
// PickPixel(sp+ivec2(+1,-1))*4
// + PickPixel(sp+ivec2(-1, 0))*8 + PickPixel(sp+ivec2(+1, 0))*16
// + PickPixel(sp+ivec2(-1,+1))*32 + PickPixel(sp+ivec2( 0,+1))*64 +
// PickPixel(sp+ivec2(+1,+1))*128;
// if(decisions[test]==1) gl_FragColor=vec4(1,0,0,1);
// else gl_FragColor=texelFetch(tex_sample_0, sp, 0);//vec4(1,1,1,1);
}

View File

@@ -0,0 +1,6 @@
uniform vec4 line_color;
void main()
{
gl_FragColor = line_color;
}

View File

@@ -0,0 +1,114 @@
layout(lines_adjacency) in;
layout(triangle_strip, max_vertices = 6) out;
in vec2 gOffset[];
uniform float line_width;
uniform float taper_l_dist;
uniform float taper_r_dist;
uniform float taper_l_strength;
uniform float taper_r_strength;
#define M_PI 3.1415926535897932384626433832795
vec4 MakeLeftTaperLinear(vec4 L, vec4 a, float offset)
{
if (offset >= taper_l_dist)
return a;
a = mix(mix(a, L, taper_l_strength), a, offset / taper_l_dist);
return a;
}
vec4 MakeRightTaperLinear(vec4 R, vec4 c, float offset)
{
if (offset >= taper_r_dist)
return c;
c = mix(mix(c, R, taper_r_strength), c, offset / taper_r_dist);
return c;
}
void main()
{
float LAngle, RAngle;
vec4 LL = gl_in[0].gl_Position, L = gl_in[1].gl_Position, R = gl_in[2].gl_Position,
RR = gl_in[3].gl_Position;
float OffsetL = gOffset[1].x;
float OffsetR = gOffset[2].x;
float OffsetL2 = gOffset[1].y;
float OffsetR2 = gOffset[2].y;
if (L == R || L == LL || R == RR || LL == RR || L == RR || R == LL)
return;
vec4 a;
vec4 b;
vec4 c;
vec4 d;
vec4 Line = R - L;
vec4 Normal = normalize(vec4(-Line.y, Line.x, 0, 0));
a = L - line_width * Normal * 0.001;
b = L + line_width * Normal * 0.001;
c = R - line_width * Normal * 0.001;
d = R + line_width * Normal * 0.001;
float lim = line_width * 0.002;
{
vec4 Tangent = normalize(normalize(L - LL) + normalize(R - L));
vec4 Minter = normalize(vec4(-Tangent.y, Tangent.x, 0, 0));
float length = line_width / (dot(Minter, Normal)) * 0.001;
a = L - length * Minter;
b = L + length * Minter;
if (distance(a, b) > 2 * lim) {
a = L - lim * Minter;
b = L + lim * Minter;
}
}
{
vec4 Tangent = normalize(normalize(RR - R) + normalize(R - L));
vec4 Minter = normalize(vec4(-Tangent.y, Tangent.x, 0, 0));
float length = line_width / (dot(Minter, Normal)) * 0.001;
c = R - length * Minter;
d = R + length * Minter;
if (distance(c, d) > 2 * lim) {
c = R - lim * Minter;
d = R + lim * Minter;
}
}
a = MakeLeftTaperLinear(L, a, OffsetL);
b = MakeLeftTaperLinear(L, b, OffsetL);
c = MakeLeftTaperLinear(R, c, OffsetR);
d = MakeLeftTaperLinear(R, d, OffsetR);
a = MakeRightTaperLinear(L, a, OffsetL2);
b = MakeRightTaperLinear(L, b, OffsetL2);
c = MakeRightTaperLinear(R, c, OffsetR2);
d = MakeRightTaperLinear(R, d, OffsetR2);
a.w = 1;
b.w = 1;
c.w = 1;
d.w = 1;
gl_Position = a;
EmitVertex();
gl_Position = b;
EmitVertex();
gl_Position = c;
EmitVertex();
EndPrimitive();
gl_Position = c;
EmitVertex();
gl_Position = d;
EmitVertex();
gl_Position = b;
EmitVertex();
EndPrimitive();
}

View File

@@ -0,0 +1,10 @@
in vec2 pos;
in vec2 uvs;
out vec2 gOffset;
void main()
{
gl_Position = vec4(pos, 0.0, 1.0);
gOffset = uvs;
}

View File

@@ -0,0 +1,19 @@
in vec3 normal;
in vec4 finalColor;
float Interpolate(float between1, float between2, float value1, float value2, float key)
{
float i = (key - between1) / (between2 - between1);
return value1 * (1 - i) + value2 * i;
}
void main()
{
float value = dot(vec3(0, 0, 1), normal);
// if(value<0.65) value=0.15;
// else if(value>=0.65 && value<0.85) value=Interpolate(0.65,0.85,0.15,0.75,value);
// else if(value>=0.85 && value<0.95) value=0.75;
// else if(value>=0.95) value=0.9;
gl_FragData[0] = vec4(finalColor.rgb * value, 1);
gl_FragData[1] = vec4(normal, 1); // vec4((normal+vec3(1))*0.5,1);
}

View File

@@ -0,0 +1,291 @@
layout(lines_adjacency) in;
layout(triangle_strip, max_vertices = 6) out;
in vec2 gOffset[];
in int gType[];
in int gLevel[];
in vec3 gNormal[];
uniform int normal_mode;
uniform int normal_effect_inverse;
uniform vec3 normal_direction; // also used as point position
uniform float normal_ramp_begin;
uniform float normal_ramp_end;
uniform float normal_thickness_start;
uniform float normal_thickness_end;
uniform float thickness;
uniform float thickness_contour;
uniform float thickness_crease;
uniform float thickness_material;
uniform float thickness_edge_mark;
uniform float thickness_intersection;
uniform int use_contour;
uniform int use_crease;
uniform int use_material;
uniform int use_edge_mark;
uniform int use_intersection;
uniform int occlusion_level_start;
uniform int occlusion_level_end;
// implement these later.
// uniform float depth_width_influence;
// uniform float depth_width_curve;
// uniform float depth_alpha_influence;
// uniform float depth_alpha_curve;
// uniform float zNear;
// uniform float zFar;
uniform vec4 contour_color;
uniform vec4 crease_color;
uniform vec4 material_color;
uniform vec4 edge_mark_color;
uniform vec4 intersection_color;
uniform float taper_l_dist;
uniform float taper_r_dist;
uniform float taper_l_strength;
uniform float taper_r_strength;
// for line width correction
uniform vec4 output_viewport;
uniform vec4 preview_viewport;
uniform float camdx;
uniform float camdy;
uniform float camzoom;
out vec4 out_color;
float use_thickness;
#define M_PI 3.1415926535897932384626433832795
vec4 END_POINT = vec4(vec2(3e30f), 0, 1); // end point flag
vec4 MakeLeftTaperLinear(vec4 L, vec4 a, float offset)
{
if (offset >= taper_l_dist)
return a;
a = mix(mix(a, L, taper_l_strength), a, offset / taper_l_dist);
return a;
}
vec4 MakeRightTaperLinear(vec4 R, vec4 c, float offset)
{
if (offset >= taper_r_dist)
return c;
c = mix(mix(c, R, taper_r_strength), c, offset / taper_r_dist);
return c;
}
void draw_line(vec4 LL, vec4 L, vec4 R, vec4 RR)
{
float LAngle, RAngle;
float OffsetL = gOffset[1].x;
float OffsetR = gOffset[2].x;
float OffsetL2 = gOffset[1].y;
float OffsetR2 = gOffset[2].y;
if (L == R)
return;
vec4 a;
vec4 b;
vec4 c;
vec4 d;
vec4 Line = R - L;
vec4 Normal = normalize(vec4(-Line.y, Line.x, 0, 0));
a = L - use_thickness * Normal * 0.001;
b = L + use_thickness * Normal * 0.001;
c = R - use_thickness * Normal * 0.001;
d = R + use_thickness * Normal * 0.001;
float lim = use_thickness * 0.002;
float x_scale = preview_viewport.w / preview_viewport.z;
if (LL.x < 3e20) {
vec4 avg = normalize(L - LL) + normalize(R - L);
if (length(avg) > 0.001) {
vec4 Tangent = normalize(avg);
vec4 Minter = normalize(vec4(-Tangent.y, Tangent.x, 0, 0));
float length = use_thickness / (dot(Minter, Normal)) * 0.001;
if (length < 4 * lim) {
Minter.x *= x_scale;
a = L - length * Minter;
b = L + length * Minter;
}
}
}
if (RR.x < 3e20) {
vec4 avg = normalize(RR - R) + normalize(R - L);
if (length(avg) > 0.001) {
vec4 Tangent = normalize(avg);
vec4 Minter = normalize(vec4(-Tangent.y, Tangent.x, 0, 0));
float length = use_thickness / (dot(Minter, Normal)) * 0.001;
if (length < 4 * lim) {
Minter.x *= x_scale;
c = R - length * Minter;
d = R + length * Minter;
}
}
}
a = MakeLeftTaperLinear(L, a, OffsetL);
b = MakeLeftTaperLinear(L, b, OffsetL);
c = MakeLeftTaperLinear(R, c, OffsetR);
d = MakeLeftTaperLinear(R, d, OffsetR);
a = MakeRightTaperLinear(L, a, OffsetL2);
b = MakeRightTaperLinear(L, b, OffsetL2);
c = MakeRightTaperLinear(R, c, OffsetR2);
d = MakeRightTaperLinear(R, d, OffsetR2);
a.w = 1;
b.w = 1;
c.w = 1;
d.w = 1;
gl_Position = a;
EmitVertex();
gl_Position = b;
EmitVertex();
gl_Position = c;
EmitVertex();
EndPrimitive();
gl_Position = c;
EmitVertex();
gl_Position = d;
EmitVertex();
gl_Position = b;
EmitVertex();
EndPrimitive();
}
float factor_to_thickness(float factor)
{
float r = (factor - normal_ramp_begin) / (normal_ramp_end - normal_ramp_begin);
if (r > 1)
r = 1;
if (r < 0)
r = 0;
float thickness = normal_effect_inverse == 1 ?
mix(normal_thickness_start, normal_thickness_end, r) :
mix(normal_thickness_end, normal_thickness_start, r);
return thickness;
}
void decide_line_style(int component_id)
{
float th = thickness;
if (normal_mode == 0) {
th = thickness;
}
else if (normal_mode == 1) {
float factor = dot(gNormal[0], normal_direction);
th = factor_to_thickness(factor);
}
else if (normal_mode == 2) {
float factor = dot(gNormal[0], normal_direction);
th = factor_to_thickness(factor);
}
if (component_id == 0) {
out_color = contour_color;
use_thickness = th * thickness_contour * use_contour;
return;
}
if (component_id == 1) {
out_color = crease_color;
use_thickness = th * thickness_crease * use_crease;
return;
}
if (component_id == 2) {
out_color = material_color;
use_thickness = th * thickness_material * use_material;
return;
}
if (component_id == 3) {
out_color = edge_mark_color;
use_thickness = th * thickness_edge_mark * use_edge_mark;
return;
}
if (component_id == 4) {
out_color = intersection_color;
use_thickness = th * thickness_intersection * use_intersection;
return;
}
}
vec4 correct_camera_scale(vec4 p)
{
p.x -= camdx * 4;
p.y -= camdy * 4;
p.xy *= camzoom;
return p;
}
void main()
{
int level = gLevel[1];
if (occlusion_level_start > level || occlusion_level_end < level)
return;
float asp1 = output_viewport.z / output_viewport.w;
float asp2 = preview_viewport.z / preview_viewport.w;
float x_scale;
float y_scale;
if (asp1 > 1) {
if (asp2 < 1) {
x_scale = 1 / asp2;
y_scale = 1 / asp1;
}
else {
x_scale = 1;
y_scale = asp2 / asp1;
}
}
else {
if (asp2 < 1) {
x_scale = asp1 / asp2;
y_scale = 1;
}
else {
x_scale = asp1;
y_scale = asp2;
}
}
vec4 LL = vec4(gl_in[0].gl_Position.xy, 0, 1), L = vec4(gl_in[1].gl_Position.xy, 0, 1),
R = vec4(gl_in[2].gl_Position.xy, 0, 1), RR = vec4(gl_in[3].gl_Position.xy, 0, 1);
LL.x *= x_scale;
LL.y *= y_scale;
L.x *= x_scale;
L.y *= y_scale;
R.x *= x_scale;
R.y *= y_scale;
RR.x *= x_scale;
RR.y *= y_scale;
LL = correct_camera_scale(LL);
L = correct_camera_scale(L);
R = correct_camera_scale(R);
RR = correct_camera_scale(RR);
int type = gType[1];
decide_line_style(type);
draw_line(LL, L, R, RR);
}

View File

@@ -0,0 +1,185 @@
layout(lines) in;
layout(triangle_strip, max_vertices = 6) out;
in vec3 gNormal[];
uniform int normal_mode;
uniform int normal_effect_inverse;
uniform vec3 normal_direction; // also used as point position
uniform float normal_ramp_begin;
uniform float normal_ramp_end;
uniform float normal_thickness_start;
uniform float normal_thickness_end;
uniform float thickness;
uniform float thickness_contour;
uniform float thickness_crease;
uniform float thickness_material;
uniform float thickness_edge_mark;
uniform float thickness_intersection;
// implement these later.
// uniform float depth_width_influence;
// uniform float depth_width_curve;
// uniform float depth_alpha_influence;
// uniform float depth_alpha_curve;
// uniform float zNear;
// uniform float zFar;
uniform vec4 contour_color;
uniform vec4 crease_color;
uniform vec4 material_color;
uniform vec4 edge_mark_color;
uniform vec4 intersection_color;
// for line width correction
uniform vec4 output_viewport;
uniform vec4 preview_viewport;
uniform float camdx;
uniform float camdy;
uniform float camzoom;
out vec4 out_color;
float use_thickness;
void draw_line(vec4 p1, vec4 p2)
{
vec4 Line = p2 - p1;
vec4 Normal = normalize(vec4(-Line.y, Line.x, 0, 0));
vec4 a, b, c, d;
float x_scale = preview_viewport.w / preview_viewport.z;
Normal.x *= x_scale;
vec4 offset = Normal * use_thickness * 0.001;
a = p1 + offset;
b = p1 - offset;
c = p2 + offset;
d = p2 - offset;
gl_Position = vec4(a.xy, 0, 1);
EmitVertex();
gl_Position = vec4(b.xy, 0, 1);
EmitVertex();
gl_Position = vec4(c.xy, 0, 1);
EmitVertex();
gl_Position = vec4(b.xy, 0, 1);
EmitVertex();
gl_Position = vec4(c.xy, 0, 1);
EmitVertex();
gl_Position = vec4(d.xy, 0, 1);
EmitVertex();
EndPrimitive();
}
float factor_to_thickness(float factor)
{
float r = (factor - normal_ramp_begin) / (normal_ramp_end - normal_ramp_begin);
if (r > 1)
r = 1;
if (r < 0)
r = 0;
float thickness = normal_effect_inverse == 1 ?
mix(normal_thickness_start, normal_thickness_end, r) :
mix(normal_thickness_end, normal_thickness_start, r);
return thickness;
}
void decide_color_and_thickness(float component_id)
{
float th = thickness;
if (normal_mode == 0) {
th = thickness;
}
else if (normal_mode == 1) {
float factor = dot(gNormal[0], normal_direction);
th = factor_to_thickness(factor);
}
else if (normal_mode == 2) {
float factor = dot(gNormal[0], normal_direction);
th = factor_to_thickness(factor);
}
if (component_id < 1.5) {
out_color = contour_color;
use_thickness = th * thickness_contour;
return;
}
if (component_id < 2.5) {
out_color = crease_color;
use_thickness = th * thickness_crease;
return;
}
if (component_id < 3.5) {
out_color = material_color;
use_thickness = th * thickness_material;
return;
}
if (component_id < 4.5) {
out_color = edge_mark_color;
use_thickness = th * thickness_edge_mark;
return;
}
if (component_id < 5.5) {
out_color = intersection_color;
use_thickness = th * thickness_intersection;
return;
}
}
vec4 correct_camera_scale(vec4 p)
{
p.x -= camdx * 4;
p.y -= camdy * 4;
p.xy *= camzoom;
return p;
}
void main()
{
float asp1 = output_viewport.z / output_viewport.w;
float asp2 = preview_viewport.z / preview_viewport.w;
float x_scale;
float y_scale;
if (asp1 > 1) {
if (asp2 < 1) {
x_scale = 1 / asp2;
y_scale = 1 / asp1;
}
else {
x_scale = 1;
y_scale = asp2 / asp1;
}
}
else {
if (asp2 < 1) {
x_scale = asp1 / asp2;
y_scale = 1;
}
else {
x_scale = asp1;
y_scale = asp2;
}
}
vec4 p1 = vec4(gl_in[0].gl_Position.xy, 0, 1);
vec4 p2 = vec4(gl_in[1].gl_Position.xy, 0, 1);
p1.x *= x_scale;
p2.x *= x_scale;
p1.y *= y_scale;
p2.y *= y_scale;
p1 = correct_camera_scale(p1);
p2 = correct_camera_scale(p2);
decide_color_and_thickness(gl_in[0].gl_Position.z);
draw_line(p1, p2);
}

View File

@@ -0,0 +1,21 @@
in vec4 pos;
in vec2 uvs;
in vec3 normal;
in int type;
in int level;
out vec2 gOffset;
out int gType;
out int gLevel;
out vec3 gNormal;
void main()
{
vec4 p = pos;
gOffset = uvs;
gType = type;
gLevel = level;
gNormal = normal;
gl_Position = vec4(vec3(p), 1);
}

View File

@@ -225,6 +225,17 @@ void DRW_texture_ensure_fullscreen_2d(struct GPUTexture **tex,
void DRW_texture_ensure_2d(
struct GPUTexture **tex, int w, int h, eGPUTextureFormat format, DRWTextureFlag flags);
void DRW_texture_ensure_fullscreen_2D_multisample(struct GPUTexture **tex,
eGPUTextureFormat format,
int samples,
DRWTextureFlag flags);
void DRW_texture_ensure_2D_multisample(struct GPUTexture **tex,
int w,
int h,
eGPUTextureFormat format,
int samples,
DRWTextureFlag flags);
void DRW_texture_generate_mipmaps(struct GPUTexture *tex);
void DRW_texture_free(struct GPUTexture *tex);
#define DRW_TEXTURE_FREE_SAFE(tex) \

View File

@@ -90,6 +90,7 @@
#include "engines/basic/basic_engine.h"
#include "engines/workbench/workbench_engine.h"
#include "engines/external/external_engine.h"
#include "engines/lanpr/lanpr_all.h"
#include "engines/gpencil/gpencil_engine.h"
#include "engines/select/select_engine.h"
@@ -2848,7 +2849,9 @@ void DRW_engine_register(DrawEngineType *draw_engine_type)
void DRW_engines_register(void)
{
RE_engines_register(&DRW_engine_viewport_eevee_type);
RE_engines_register(&DRW_engine_viewport_workbench_type);
// RE_engines_register(&DRW_engine_viewport_workbench_type); //registered as two DRW_engines
// below.
RE_engines_register(&DRW_engine_viewport_lanpr_type);
DRW_engine_register(&draw_engine_workbench_solid);
DRW_engine_register(&draw_engine_workbench_transparent);

View File

@@ -103,6 +103,19 @@ GPUTexture *DRW_texture_create_2d_array(
return tex;
}
GPUTexture *DRW_texture_create_2d_multisample(int w,
int h,
eGPUTextureFormat format,
int samples,
DRWTextureFlag flags,
const float *fpixels)
{
GPUTexture *tex = GPU_texture_create_2d_multisample(w, h, format, fpixels, samples, NULL);
drw_texture_set_parameters(tex, flags);
return tex;
}
GPUTexture *DRW_texture_create_3d(
int w, int h, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
{
@@ -152,6 +165,26 @@ void DRW_texture_ensure_2d(
}
}
void DRW_texture_ensure_fullscreen_2D_multisample(GPUTexture **tex,
eGPUTextureFormat format,
int samples,
DRWTextureFlag flags)
{
if (*(tex) == NULL) {
const float *size = DRW_viewport_size_get();
*(tex) = DRW_texture_create_2d_multisample(
(int)size[0], (int)size[1], format, samples, flags, NULL);
}
}
void DRW_texture_ensure_2D_multisample(
GPUTexture **tex, int w, int h, eGPUTextureFormat format, int samples, DRWTextureFlag flags)
{
if (*(tex) == NULL) {
*(tex) = DRW_texture_create_2d_multisample(w, h, format, samples, flags, NULL);
}
}
void DRW_texture_generate_mipmaps(GPUTexture *tex)
{
GPU_texture_bind(tex, 0);

View File

@@ -27,6 +27,7 @@ if(WITH_BLENDER)
add_subdirectory(interface)
add_subdirectory(io)
add_subdirectory(lattice)
add_subdirectory(lanpr)
add_subdirectory(gizmo_library)
add_subdirectory(mask)
add_subdirectory(mesh)

View File

@@ -0,0 +1,622 @@
/*
* 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) 2008 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup editors
*/
#ifndef __ED_LANPR_H__
#define __ED_LANPR_H__
#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_threads.h"
#include "DNA_lanpr_types.h"
#include <math.h>
#include <string.h>
typedef double real;
typedef real tnsVector2d[2];
typedef real tnsVector3d[3];
typedef real tnsVector4d[4];
typedef float tnsVector3f[3];
typedef float tnsVector4f[4];
typedef int tnsVector2i[2];
typedef struct LANPR_StaticMemPoolNode {
Link item;
int used_byte;
/* User memory starts here */
} LANPR_StaticMemPoolNode;
typedef struct LANPR_StaticMemPool {
int each_size;
ListBase pools;
SpinLock lock_mem;
} LANPR_StaticMemPool;
typedef struct LANPR_TextureSample {
struct LANPR_TextureSample *next, *prev;
int X, Y;
/** For future usage */
float Z;
} LANPR_TextureSample;
typedef struct LANPR_LineStripPoint {
struct LANPR_LineStripPoint *next, *prev;
float P[3];
} LANPR_LineStripPoint;
typedef struct LANPR_LineStrip {
struct LANPR_LineStrip *next, *prev;
ListBase points;
int point_count;
float total_length;
} LANPR_LineStrip;
typedef struct LANPR_RenderTriangle {
struct LANPR_RenderTriangle *next, *prev;
struct LANPR_RenderVert *v[3];
struct LANPR_RenderLine *rl[3];
real gn[3];
real gc[3];
/* struct BMFace *F; */
short material_id;
ListBase intersecting_verts;
char cull_status;
/** Should be testing** , Use testing[NumOfThreads] to access. */
struct LANPR_RenderTriangle *testing;
} LANPR_RenderTriangle;
typedef struct LANPR_RenderTriangleThread {
struct LANPR_RenderTriangle base;
struct LANPR_RenderLine *testing[127];
} LANPR_RenderTriangleThread;
typedef struct LANPR_RenderElementLinkNode {
struct LANPR_RenderElementLinkNode *next, *prev;
void *pointer;
int element_count;
void *object_ref;
char additional;
} LANPR_RenderElementLinkNode;
typedef struct LANPR_RenderLineSegment {
struct LANPR_RenderLineSegment *next, *prev;
/** at==0: left at==1: right (this is in 2D projected space) */
real at;
/** This is used to reconstruct 3d stroke (TODO: implement global space?) */
real at_global;
/** Occlusion level after "at" point */
unsigned char occlusion;
/** For determining lines beind a glass window material. (TODO: implement this) */
short material_mask_mark;
} LANPR_RenderLineSegment;
typedef struct LANPR_RenderVert {
struct LANPR_RenderVert *next, *prev;
real gloc[4];
real fbcoord[4];
int fbcoordi[2];
/** Used as "r" when intersecting */
struct BMVert *v;
struct LANPR_RenderLine *intersecting_line;
struct LANPR_RenderLine *intersecting_line2;
struct LANPR_RenderTriangle *intersecting_with;
/** positive 1 Negative 0
* <| |>
* l---->|----->r l---->|----->r
* <| |>
* this means dot(r-l,face_normal)<0 then 1 otherwise 0
*/
char positive;
char edge_used;
} LANPR_RenderVert;
typedef enum LANPR_EdgeFlag {
LANPR_EDGE_FLAG_EDGE_MARK = (1 << 0),
LANPR_EDGE_FLAG_CONTOUR = (1 << 1),
LANPR_EDGE_FLAG_CREASE = (1 << 2),
LANPR_EDGE_FLAG_MATERIAL = (1 << 3),
LANPR_EDGE_FLAG_INTERSECTION = (1 << 4),
/** floating edge, unimplemented yet */
LANPR_EDGE_FLAG_FLOATING = (1 << 5),
LANPR_EDGE_FLAG_CHAIN_PICKED = (1 << 6),
} LANPR_EdgeFlag;
#define LANPR_EDGE_FLAG_ALL_TYPE 0x3f
typedef struct LANPR_RenderLine {
struct LANPR_RenderLine *next, *prev;
struct LANPR_RenderVert *l, *r;
struct LANPR_RenderTriangle *tl, *tr;
ListBase segments;
char min_occ;
/** Also for line type determination on chainning */
char flags;
/** Still need this entry because culled lines will not add to object reln node */
struct Object *object_ref;
/** For gpencil stroke modifier */
int edge_idx;
} LANPR_RenderLine;
typedef struct LANPR_RenderLineChain {
struct LANPR_RenderLineChain *next, *prev;
ListBase chain;
/** Calculated before draw cmd. */
float length;
/** Used when re-connecting and gp stroke generation */
char picked;
char level;
/** Chain now only contains one type of segments */
int type;
struct Object *object_ref;
} LANPR_RenderLineChain;
typedef struct LANPR_RenderLineChainItem {
struct LANPR_RenderLineChainItem *next, *prev;
/** Need z value for fading */
float pos[3];
/** For restoring position to 3d space */
float gpos[3];
float normal[3];
char line_type;
char occlusion;
} LANPR_RenderLineChainItem;
typedef struct LANPR_ChainRegisterEntry {
struct LANPR_ChainRegisterEntry *next, *prev;
LANPR_RenderLineChain *rlc;
LANPR_RenderLineChainItem *rlci;
char picked;
/** left/right mark.
* Because we revert list in chaining so we need the flag. */
char is_left;
} LANPR_ChainRegisterEntry;
typedef struct LANPR_RenderBuffer {
struct LANPR_RenderBuffer *prev, *next;
/** For render. */
int is_copied;
int w, h;
int tile_size_w, tile_size_h;
int tile_count_x, tile_count_y;
real width_per_tile, height_per_tile;
double view_projection[4][4];
int output_mode;
int output_aa_level;
struct LANPR_BoundingArea *initial_bounding_areas;
unsigned int bounding_area_count;
ListBase vertex_buffer_pointers;
ListBase line_buffer_pointers;
ListBase triangle_buffer_pointers;
ListBase all_render_lines;
ListBase intersecting_vertex_buffer;
struct GPUBatch *DPIXIntersectionTransformBatch;
struct GPUBatch *DPIXIntersectionBatch;
/** Use the one comes with LANPR. */
LANPR_StaticMemPool render_data_pool;
struct Material *material_pointers[2048];
/* Render status */
int cached_for_frame;
real view_vector[3];
int triangle_size;
unsigned int contour_count;
unsigned int contour_processed;
LinkData *contour_managed;
ListBase contours;
unsigned int intersection_count;
unsigned int intersection_processed;
LinkData *intersection_managed;
ListBase intersection_lines;
unsigned int crease_count;
unsigned int crease_processed;
LinkData *crease_managed;
ListBase crease_lines;
unsigned int material_line_count;
unsigned int material_processed;
LinkData *material_managed;
ListBase material_lines;
unsigned int edge_mark_count;
unsigned int edge_mark_processed;
LinkData *edge_mark_managed;
ListBase edge_marks;
ListBase chains;
struct GPUBatch *chain_draw_batch;
struct DRWShadingGroup *ChainShgrp;
/** For managing calculation tasks for multiple threads. */
SpinLock lock_task;
/* settings */
int max_occlusion_level;
real crease_angle;
real crease_cos;
int thread_count;
int draw_material_preview;
real material_transparency;
int show_line;
int show_fast;
int show_material;
int override_display;
struct Scene *scene;
struct Object *camera;
int use_intersections;
int _pad;
} LANPR_RenderBuffer;
typedef enum LANPR_RenderStatus {
LANPR_RENDER_IDLE = 0,
LANPR_RENDER_RUNNING = 1,
LANPR_RENDER_INCOMPELTE = 2,
LANPR_RENDER_FINISHED = 3,
} LANPR_RenderStatus;
typedef struct LANPR_SharedResource {
/* We only allocate once for all */
LANPR_RenderBuffer *render_buffer_shared;
/* cache */
struct BLI_mempool *mp_sample;
struct BLI_mempool *mp_line_strip;
struct BLI_mempool *mp_line_strip_point;
struct BLI_mempool *mp_batch_list;
/* Image filtering */
struct GPUShader *multichannel_shader;
struct GPUShader *edge_detect_shader;
struct GPUShader *edge_thinning_shader;
struct GPUShader *snake_connection_shader;
/* GPU */
struct GPUShader *dpix_transform_shader;
struct GPUShader *dpix_preview_shader;
int dpix_shader_error;
int texture_size;
ListBase dpix_batch_list;
int dpix_reloaded;
int dpix_reloaded_deg;
/* CPU */
struct GPUShader *software_shader;
struct GPUShader *software_chaining_shader;
void *ved_viewport;
void *ved_render;
int init_complete;
/** To bypass or cancel rendering. */
SpinLock lock_render_status;
LANPR_RenderStatus flag_render_status;
/** Set before rendering and cleared upon finish! */
struct RenderEngine *re_render;
} LANPR_SharedResource;
#define DBL_TRIANGLE_LIM 1e-8
#define DBL_EDGE_LIM 1e-9
#define LANPR_MEMORY_POOL_1MB 1048576
#define LANPR_MEMORY_POOL_128MB 134217728
#define LANPR_MEMORY_POOL_256MB 268435456
#define LANPR_MEMORY_POOL_512MB 536870912
typedef enum LANPR_CullState {
LANPR_CULL_DONT_CARE = 0,
LANPR_CULL_USED = 1,
LANPR_CULL_DISCARD = 2,
} LANPR_CullState;
#define TNS_THREAD_LINE_COUNT 10000
typedef struct LANPR_RenderTaskInfo {
int thread_id;
LinkData *contour;
ListBase contour_pointers;
LinkData *intersection;
ListBase intersection_pointers;
LinkData *crease;
ListBase crease_pointers;
LinkData *material;
ListBase material_pointers;
LinkData *edge_mark;
ListBase edge_mark_pointers;
} LANPR_RenderTaskInfo;
typedef struct LANPR_BoundingArea {
real l, r, u, b;
real cx, cy;
/** 1,2,3,4 quadrant */
struct LANPR_BoundingArea *child;
ListBase lp;
ListBase rp;
ListBase up;
ListBase bp;
int triangle_count;
ListBase linked_triangles;
ListBase linked_lines;
/** Reserved for image space reduction && multithread chainning */
ListBase linked_chains;
} LANPR_BoundingArea;
#define TNS_COMMAND_LINE 0
#define TNS_COMMAND_MATERIAL 1
#define TNS_COMMAND_EDGE 2
#define TNS_TRANSPARENCY_DRAW_SIMPLE 0
#define TNS_TRANSPARENCY_DRAW_LAYERED 1
#define TNS_OVERRIDE_ONLY 0
#define TNS_OVERRIDE_EXCLUDE 1
/* #define TNS_OVERRIDE_ALL_OTHERS_OUTSIDE_GROUP 2 */
/* #define TNS_OVERRIDE_ALL_OTHERS_IN_GROUP 3 */
/* #define TNS_OVERRIDE_ALL_OTHERS 4 */
#define TNS_TILE(tile, r, c, CCount) tile[r * CCount + c]
#define TNS_CLAMP(a, Min, Max) a = a < Min ? Min : (a > Max ? Max : a)
#define TNS_MAX3_INDEX(a, b, c) (a > b ? (a > c ? 0 : (b > c ? 1 : 2)) : (b > c ? 1 : 2))
#define TNS_MIN3_INDEX(a, b, c) (a < b ? (a < c ? 0 : (b < c ? 1 : 2)) : (b < c ? 1 : 2))
#define TNS_MAX3_INDEX_ABC(x, y, z) (x > y ? (x > z ? a : (y > z ? b : c)) : (y > z ? b : c))
#define TNS_MIN3_INDEX_ABC(x, y, z) (x < y ? (x < z ? a : (y < z ? b : c)) : (y < z ? b : c))
#define TNS_ABC(index) (index == 0 ? a : (index == 1 ? b : c))
#define TNS_DOUBLE_CLOSE_ENOUGH(a, b) (((a) + DBL_EDGE_LIM) >= (b) && ((a)-DBL_EDGE_LIM) <= (b))
/* #define TNS_DOUBLE_CLOSE_ENOUGH(a,b)\ */
/* //(((a)+0.00000000001)>=(b) && ((a)-0.0000000001)<=(b)) */
#define TNS_FLOAT_CLOSE_ENOUGH_WIDER(a, b) (((a) + 0.0000001) >= (b) && ((a)-0.0000001) <= (b))
#define TNS_IN_TILE_X(RenderTile, Fx) (RenderTile->FX <= Fx && RenderTile->FXLim >= Fx)
#define TNS_IN_TILE_Y(RenderTile, Fy) (RenderTile->FY <= Fy && RenderTile->FYLim >= Fy)
#define TNS_IN_TILE(RenderTile, Fx, Fy) \
(TNS_IN_TILE_X(RenderTile, Fx) && TNS_IN_TILE_Y(RenderTile, Fy))
BLI_INLINE int lanpr_TrangleLineBoundBoxTest(LANPR_RenderTriangle *rt, LANPR_RenderLine *rl)
{
if (MAX3(rt->v[0]->fbcoord[2], rt->v[1]->fbcoord[2], rt->v[2]->fbcoord[2]) >
MIN2(rl->l->fbcoord[2], rl->r->fbcoord[2]))
return 0;
if (MAX3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]) <
MIN2(rl->l->fbcoord[0], rl->r->fbcoord[0]))
return 0;
if (MIN3(rt->v[0]->fbcoord[0], rt->v[1]->fbcoord[0], rt->v[2]->fbcoord[0]) >
MAX2(rl->l->fbcoord[0], rl->r->fbcoord[0]))
return 0;
if (MAX3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]) <
MIN2(rl->l->fbcoord[1], rl->r->fbcoord[1]))
return 0;
if (MIN3(rt->v[0]->fbcoord[1], rt->v[1]->fbcoord[1], rt->v[2]->fbcoord[1]) >
MAX2(rl->l->fbcoord[1], rl->r->fbcoord[1]))
return 0;
return 1;
}
BLI_INLINE double tMatGetLinearRatio(real l, real r, real FromL);
BLI_INLINE int lanpr_LineIntersectTest2d(
const double *a1, const double *a2, const double *b1, const double *b2, double *aRatio)
{
double k1, k2;
double x;
double y;
double Ratio;
double xDiff = (a2[0] - a1[0]); /* +DBL_EPSILON; */
double xDiff2 = (b2[0] - b1[0]);
if (xDiff == 0) {
if (xDiff2 == 0) {
*aRatio = 0;
return 0;
}
double r2 = tMatGetLinearRatio(b1[0], b2[0], a1[0]);
x = interpd(b2[0], b1[0], r2);
y = interpd(b2[1], b1[1], r2);
*aRatio = Ratio = tMatGetLinearRatio(a1[1], a2[1], y);
}
else {
if (xDiff2 == 0) {
Ratio = tMatGetLinearRatio(a1[0], a2[0], b1[0]);
x = interpd(a2[0], a1[0], Ratio);
*aRatio = Ratio;
}
else {
k1 = (a2[1] - a1[1]) / xDiff;
k2 = (b2[1] - b1[1]) / xDiff2;
if ((k1 == k2))
return 0;
x = (a1[1] - b1[1] - k1 * a1[0] + k2 * b1[0]) / (k2 - k1);
Ratio = (x - a1[0]) / xDiff;
*aRatio = Ratio;
}
}
if (b1[0] == b2[0]) {
y = interpd(a2[1], a1[1], Ratio);
if (y > MAX2(b1[1], b2[1]) || y < MIN2(b1[1], b2[1]))
return 0;
}
else if (Ratio <= 0 || Ratio > 1 || (b1[0] > b2[0] && x > b1[0]) ||
(b1[0] < b2[0] && x < b1[0]) || (b2[0] > b1[0] && x > b2[0]) ||
(b2[0] < b1[0] && x < b2[0]))
return 0;
return 1;
}
BLI_INLINE double lanpr_GetLineZ(tnsVector3d l, tnsVector3d r, real Ratio)
{
double z = interpd(r[2], l[2], Ratio);
return z;
}
BLI_INLINE double lanpr_GetLineZPoint(tnsVector3d l, tnsVector3d r, tnsVector3d FromL)
{
double ra = (FromL[0] - l[0]) / (r[0] - l[0]);
return interpd(r[2], l[2], ra);
}
BLI_INLINE double lanpr_GetLinearRatio(tnsVector3d l, tnsVector3d r, tnsVector3d FromL)
{
double ra = (FromL[0] - l[0]) / (r[0] - l[0]);
return ra;
}
BLI_INLINE double tMatGetLinearRatio(real l, real r, real FromL)
{
double ra = (FromL - l) / (r - l);
return ra;
}
int ED_lanpr_point_inside_triangled(tnsVector2d v, tnsVector2d v0, tnsVector2d v1, tnsVector2d v2);
struct Depsgraph;
struct SceneLANPR;
int ED_lanpr_object_collection_usage_check(struct Collection *c, struct Object *o);
void ED_lanpr_NO_THREAD_chain_feature_lines(LANPR_RenderBuffer *rb);
void ED_lanpr_split_chains_for_fixed_occlusion(LANPR_RenderBuffer *rb);
void ED_lanpr_connect_chains(LANPR_RenderBuffer *rb, int do_geometry_space);
void ED_lanpr_discard_short_chains(LANPR_RenderBuffer *rb, float threshold);
int ED_lanpr_count_chain(LANPR_RenderLineChain *rlc);
void ED_lanpr_chain_clear_picked_flag(struct LANPR_RenderBuffer *rb);
int ED_lanpr_count_leveled_edge_segment_count(ListBase *LineList, struct LANPR_LineLayer *ll);
void *ED_lanpr_make_leveled_edge_vertex_array(struct LANPR_RenderBuffer *rb,
ListBase *LineList,
float *vertexArray,
float *NormalArray,
float **NextNormal,
LANPR_LineLayer *ll,
float componet_id);
void ED_lanpr_calculation_set_flag(LANPR_RenderStatus flag);
bool ED_lanpr_calculation_flag_check(LANPR_RenderStatus flag);
int ED_lanpr_compute_feature_lines_internal(struct Depsgraph *depsgraph, int instersections_only);
void ED_lanpr_compute_feature_lines_background(struct Depsgraph *dg, int intersection_only);
LANPR_RenderBuffer *ED_lanpr_create_render_buffer(void);
void ED_lanpr_destroy_render_data(struct LANPR_RenderBuffer *rb);
void ED_lanpr_calculation_set_flag(LANPR_RenderStatus flag);
bool ED_lanpr_calculation_flag_check(LANPR_RenderStatus flag);
bool ED_lanpr_dpix_shader_error(void);
int ED_lanpr_max_occlusion_in_line_layers(struct SceneLANPR *lanpr);
LANPR_LineLayer *ED_lanpr_new_line_layer(struct SceneLANPR *lanpr);
LANPR_LineLayerComponent *ED_lanpr_new_line_component(struct SceneLANPR *lanpr);
LANPR_BoundingArea *ED_lanpr_get_point_bounding_area(LANPR_RenderBuffer *rb, real x, real y);
LANPR_BoundingArea *ED_lanpr_get_point_bounding_area_deep(LANPR_RenderBuffer *rb, real x, real y);
void ED_lanpr_post_frame_update_external(struct Scene *s, struct Depsgraph *dg);
struct SceneLANPR;
void ED_lanpr_rebuild_all_command(struct SceneLANPR *lanpr);
void ED_lanpr_update_render_progress(const char *text);
void ED_lanpr_calculate_normal_object_vector(LANPR_LineLayer *ll, float *normal_object_direction);
float ED_lanpr_compute_chain_length(LANPR_RenderLineChain *rlc);
struct wmOperatorType;
/* Operator types */
void SCENE_OT_lanpr_calculate_feature_lines(struct wmOperatorType *ot);
void SCENE_OT_lanpr_add_line_layer(struct wmOperatorType *ot);
void SCENE_OT_lanpr_delete_line_layer(struct wmOperatorType *ot);
void SCENE_OT_lanpr_rebuild_all_commands(struct wmOperatorType *ot);
void SCENE_OT_lanpr_auto_create_line_layer(struct wmOperatorType *ot);
void SCENE_OT_lanpr_move_line_layer(struct wmOperatorType *ot);
void SCENE_OT_lanpr_add_line_component(struct wmOperatorType *ot);
void SCENE_OT_lanpr_delete_line_component(struct wmOperatorType *ot);
void SCENE_OT_lanpr_enable_all_line_types(struct wmOperatorType *ot);
void SCENE_OT_lanpr_update_gp_strokes(struct wmOperatorType *ot);
void SCENE_OT_lanpr_bake_gp_strokes(struct wmOperatorType *ot);
void OBJECT_OT_lanpr_update_gp_target(struct wmOperatorType *ot);
void OBJECT_OT_lanpr_update_gp_source(struct wmOperatorType *ot);
void ED_operatortypes_lanpr(void);
#endif /* __ED_LANPR_H__ */

View File

@@ -0,0 +1,46 @@
# ***** 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.
# ***** END GPL LICENSE BLOCK *****
set(INC
../include
../../blenkernel
../../blenlib
../../bmesh
../../depsgraph
../../makesdna
../../makesrna
../../windowmanager
../../../../intern/guardedalloc
)
set(INC_SYS
)
set(SRC
lanpr_ops.c
lanpr_cpu.c
lanpr_chain.c
lanpr_util.c
lanpr_intern.h
)
set(LIB
)
blender_add_lib(bf_editor_lanpr "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@@ -0,0 +1,817 @@
/*
* 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) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup editors
*/
#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BKE_customdata.h"
#include "BKE_object.h"
#include "DEG_depsgraph_query.h"
#include "DNA_camera_types.h"
#include "DNA_lanpr_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_scene_types.h"
#include "ED_lanpr.h"
#include "bmesh.h"
#include "lanpr_intern.h"
#include <math.h>
#define LANPR_OTHER_RV(rl, rv) ((rv) == (rl)->l ? (rl)->r : (rl)->l)
static LANPR_RenderLine *lanpr_get_connected_render_line(LANPR_BoundingArea *ba,
LANPR_RenderVert *rv,
LANPR_RenderVert **new_rv,
int match_flag)
{
LinkData *lip;
LANPR_RenderLine *nrl;
for (lip = ba->linked_lines.first; lip; lip = lip->next) {
nrl = lip->data;
if ((!(nrl->flags & LANPR_EDGE_FLAG_ALL_TYPE)) ||
(nrl->flags & LANPR_EDGE_FLAG_CHAIN_PICKED)) {
continue;
}
if (match_flag && ((nrl->flags & LANPR_EDGE_FLAG_ALL_TYPE) & match_flag) == 0) {
continue;
}
/* always chain connected lines for now. */
/* simplification will take care of the sharp points. */
/* if(cosine whatever) continue; */
if (rv != nrl->l && rv != nrl->r) {
if (nrl->flags & LANPR_EDGE_FLAG_INTERSECTION) {
if (rv->fbcoord[0] == nrl->l->fbcoord[0] && rv->fbcoord[1] == nrl->l->fbcoord[1]) {
*new_rv = LANPR_OTHER_RV(nrl, nrl->l);
return nrl;
}
else {
if (rv->fbcoord[0] == nrl->r->fbcoord[0] && rv->fbcoord[1] == nrl->r->fbcoord[1]) {
*new_rv = LANPR_OTHER_RV(nrl, nrl->r);
return nrl;
}
}
}
continue;
}
*new_rv = LANPR_OTHER_RV(nrl, rv);
return nrl;
}
return 0;
}
static LANPR_RenderLineChain *lanpr_create_render_line_chain(LANPR_RenderBuffer *rb)
{
LANPR_RenderLineChain *rlc;
rlc = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineChain));
BLI_addtail(&rb->chains, rlc);
return rlc;
}
static LANPR_RenderLineChainItem *lanpr_append_render_line_chain_point(LANPR_RenderBuffer *rb,
LANPR_RenderLineChain *rlc,
float x,
float y,
float gx,
float gy,
float gz,
float *normal,
char type,
int level)
{
LANPR_RenderLineChainItem *rlci;
rlci = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineChainItem));
rlci->pos[0] = x;
rlci->pos[1] = y;
rlci->gpos[0] = gx;
rlci->gpos[1] = gy;
rlci->gpos[2] = gz;
copy_v3_v3(rlci->normal, normal);
rlci->line_type = type & LANPR_EDGE_FLAG_ALL_TYPE;
rlci->occlusion = level;
BLI_addtail(&rlc->chain, rlci);
/* printf("a %f,%f %d\n", x, y, level); */
return rlci;
}
static LANPR_RenderLineChainItem *lanpr_push_render_line_chain_point(LANPR_RenderBuffer *rb,
LANPR_RenderLineChain *rlc,
float x,
float y,
float gx,
float gy,
float gz,
float *normal,
char type,
int level)
{
LANPR_RenderLineChainItem *rlci;
rlci = mem_static_aquire(&rb->render_data_pool, sizeof(LANPR_RenderLineChainItem));
rlci->pos[0] = x;
rlci->pos[1] = y;
rlci->gpos[0] = gx;
rlci->gpos[1] = gy;
rlci->gpos[2] = gz;
copy_v3_v3(rlci->normal, normal);
rlci->line_type = type & LANPR_EDGE_FLAG_ALL_TYPE;
rlci->occlusion = level;
BLI_addhead(&rlc->chain, rlci);
/* printf("data %f,%f %d\n", x, y, level); */
return rlci;
}
/* refer to http://karthaus.nl/rdp/ for description */
static void lanpr_reduce_render_line_chain_recursive(LANPR_RenderLineChain *rlc,
LANPR_RenderLineChainItem *from,
LANPR_RenderLineChainItem *to,
float dist_threshold)
{
LANPR_RenderLineChainItem *rlci, *next_rlci;
float max_dist = 0;
LANPR_RenderLineChainItem *max_rlci = 0;
/* find the max distance item */
for (rlci = from->next; rlci != to; rlci = next_rlci) {
next_rlci = rlci->next;
if (next_rlci &&
(next_rlci->occlusion != rlci->occlusion || next_rlci->line_type != rlci->line_type)) {
continue;
}
float dist = dist_to_line_segment_v2(rlci->pos, from->pos, to->pos);
if (dist > dist_threshold && dist > max_dist) {
max_dist = dist;
max_rlci = rlci;
}
/* if (dist <= dist_threshold) BLI_remlink(&rlc->chain, (void*)rlci); */
}
if (!max_rlci) {
if (from->next == to) {
return;
}
for (rlci = from->next; rlci != to; rlci = next_rlci) {
next_rlci = rlci->next;
if (next_rlci &&
(next_rlci->occlusion != rlci->occlusion || next_rlci->line_type != rlci->line_type)) {
continue;
}
BLI_remlink(&rlc->chain, (void *)rlci);
}
}
else {
if (from->next != max_rlci) {
lanpr_reduce_render_line_chain_recursive(rlc, from, max_rlci, dist_threshold);
}
if (to->prev != max_rlci) {
lanpr_reduce_render_line_chain_recursive(rlc, max_rlci, to, dist_threshold);
}
}
}
void ED_lanpr_NO_THREAD_chain_feature_lines(LANPR_RenderBuffer *rb)
{
LANPR_RenderLineChain *rlc;
LANPR_RenderLineChainItem *rlci;
LANPR_RenderLine *rl;
LANPR_BoundingArea *ba;
LANPR_RenderLineSegment *rls;
int last_occlusion;
for (rl = rb->all_render_lines.first; rl; rl = rl->next) {
if ((!(rl->flags & LANPR_EDGE_FLAG_ALL_TYPE)) || (rl->flags & LANPR_EDGE_FLAG_CHAIN_PICKED)) {
continue;
}
rl->flags |= LANPR_EDGE_FLAG_CHAIN_PICKED;
rlc = lanpr_create_render_line_chain(rb);
rlc->object_ref = rl->object_ref; /* can only be the same object in a chain. */
rlc->type = (rl->flags & LANPR_EDGE_FLAG_ALL_TYPE);
LANPR_RenderLine *new_rl = rl;
LANPR_RenderVert *new_rv;
float N[3] = {0};
if (rl->tl) {
N[0] += rl->tl->gn[0];
N[1] += rl->tl->gn[1];
N[2] += rl->tl->gn[2];
}
if (rl->tr) {
N[0] += rl->tr->gn[0];
N[1] += rl->tr->gn[1];
N[2] += rl->tr->gn[2];
}
if (rl->tl || rl->tr) {
normalize_v3(N);
}
/* step 1: grow left */
ba = ED_lanpr_get_point_bounding_area_deep(rb, rl->l->fbcoord[0], rl->l->fbcoord[1]);
new_rv = rl->l;
rls = rl->segments.first;
lanpr_push_render_line_chain_point(rb,
rlc,
new_rv->fbcoord[0],
new_rv->fbcoord[1],
new_rv->gloc[0],
new_rv->gloc[1],
new_rv->gloc[2],
N,
rl->flags,
rls->occlusion);
while (ba && (new_rl = lanpr_get_connected_render_line(ba, new_rv, &new_rv, rl->flags))) {
new_rl->flags |= LANPR_EDGE_FLAG_CHAIN_PICKED;
if (new_rl->tl || new_rl->tr) {
zero_v3(N);
if (new_rl->tl) {
N[0] += new_rl->tl->gn[0];
N[1] += new_rl->tl->gn[1];
N[2] += new_rl->tl->gn[2];
}
if (new_rl->tr) {
N[0] += new_rl->tr->gn[0];
N[1] += new_rl->tr->gn[1];
N[2] += new_rl->tr->gn[2];
}
normalize_v3(N);
}
if (new_rv == new_rl->l) {
for (rls = new_rl->segments.last; rls; rls = rls->prev) {
double gpos[3], lpos[3];
interp_v3_v3v3_db(lpos, new_rl->l->fbcoord, new_rl->r->fbcoord, rls->at);
interp_v3_v3v3_db(gpos, new_rl->l->gloc, new_rl->r->gloc, rls->at);
lanpr_push_render_line_chain_point(rb,
rlc,
lpos[0],
lpos[1],
gpos[0],
gpos[1],
gpos[2],
N,
new_rl->flags,
rls->occlusion);
last_occlusion = rls->occlusion;
}
}
else if (new_rv == new_rl->r) {
rls = new_rl->segments.first;
last_occlusion = rls->occlusion;
rls = rls->next;
for (; rls; rls = rls->next) {
double gpos[3], lpos[3];
interp_v3_v3v3_db(lpos, new_rl->l->fbcoord, new_rl->r->fbcoord, rls->at);
interp_v3_v3v3_db(gpos, new_rl->l->gloc, new_rl->r->gloc, rls->at);
lanpr_push_render_line_chain_point(rb,
rlc,
lpos[0],
lpos[1],
gpos[0],
gpos[1],
gpos[2],
N,
new_rl->flags,
last_occlusion);
last_occlusion = rls->occlusion;
}
lanpr_push_render_line_chain_point(rb,
rlc,
new_rl->r->fbcoord[0],
new_rl->r->fbcoord[1],
new_rl->r->gloc[0],
new_rl->r->gloc[1],
new_rl->r->gloc[2],
N,
new_rl->flags,
last_occlusion);
}
ba = ED_lanpr_get_point_bounding_area_deep(rb, new_rv->fbcoord[0], new_rv->fbcoord[1]);
}
/* Restore normal value */
if (rl->tl || rl->tr) {
zero_v3(N);
if (rl->tl) {
N[0] += rl->tl->gn[0];
N[1] += rl->tl->gn[1];
N[2] += rl->tl->gn[2];
}
if (rl->tr) {
N[0] += rl->tr->gn[0];
N[1] += rl->tr->gn[1];
N[2] += rl->tr->gn[2];
}
normalize_v3(N);
}
/* step 2: this line */
rls = rl->segments.first;
last_occlusion = ((LANPR_RenderLineSegment *)rls)->occlusion;
for (rls = rls->next; rls; rls = rls->next) {
double gpos[3], lpos[3];
interp_v3_v3v3_db(lpos, rl->l->fbcoord, rl->r->fbcoord, rls->at);
interp_v3_v3v3_db(gpos, rl->l->gloc, rl->r->gloc, rls->at);
lanpr_append_render_line_chain_point(
rb, rlc, lpos[0], lpos[1], gpos[0], gpos[1], gpos[2], N, rl->flags, rls->occlusion);
last_occlusion = rls->occlusion;
}
lanpr_append_render_line_chain_point(rb,
rlc,
rl->r->fbcoord[0],
rl->r->fbcoord[1],
rl->r->gloc[0],
rl->r->gloc[1],
rl->r->gloc[2],
N,
rl->flags,
last_occlusion);
/* step 3: grow right */
ba = ED_lanpr_get_point_bounding_area_deep(rb, rl->r->fbcoord[0], rl->r->fbcoord[1]);
new_rv = rl->r;
/* below already done in step 2 */
/* lanpr_push_render_line_chain_point(rb,rlc,new_rv->fbcoord[0],new_rv->fbcoord[1],rl->flags,0);
*/
while (ba && (new_rl = lanpr_get_connected_render_line(ba, new_rv, &new_rv, rl->flags))) {
new_rl->flags |= LANPR_EDGE_FLAG_CHAIN_PICKED;
if (new_rl->tl || new_rl->tr) {
zero_v3(N);
if (new_rl->tl) {
N[0] += new_rl->tl->gn[0];
N[1] += new_rl->tl->gn[1];
N[2] += new_rl->tl->gn[2];
}
if (new_rl->tr) {
N[0] += new_rl->tr->gn[0];
N[1] += new_rl->tr->gn[1];
N[2] += new_rl->tr->gn[2];
}
normalize_v3(N);
}
/* fix leading vertex type */
rlci = rlc->chain.last;
rlci->line_type = new_rl->flags & LANPR_EDGE_FLAG_ALL_TYPE;
if (new_rv == new_rl->l) {
rls = new_rl->segments.last;
last_occlusion = rls->occlusion;
rlci->occlusion = last_occlusion; /* fix leading vertex occlusion */
for (rls = new_rl->segments.last; rls; rls = rls->prev) {
double gpos[3], lpos[3];
interp_v3_v3v3_db(lpos, new_rl->l->fbcoord, new_rl->r->fbcoord, rls->at);
interp_v3_v3v3_db(gpos, new_rl->l->gloc, new_rl->r->gloc, rls->at);
last_occlusion = rls->prev ? rls->prev->occlusion : last_occlusion;
lanpr_append_render_line_chain_point(rb,
rlc,
lpos[0],
lpos[1],
gpos[0],
gpos[1],
gpos[2],
N,
new_rl->flags,
last_occlusion);
}
}
else if (new_rv == new_rl->r) {
rls = new_rl->segments.first;
last_occlusion = rls->occlusion;
rlci->occlusion = last_occlusion;
rls = rls->next;
for (; rls; rls = rls->next) {
double gpos[3], lpos[3];
interp_v3_v3v3_db(lpos, new_rl->l->fbcoord, new_rl->r->fbcoord, rls->at);
interp_v3_v3v3_db(gpos, new_rl->l->gloc, new_rl->r->gloc, rls->at);
lanpr_append_render_line_chain_point(rb,
rlc,
lpos[0],
lpos[1],
gpos[0],
gpos[1],
gpos[2],
N,
new_rl->flags,
rls->occlusion);
last_occlusion = rls->occlusion;
}
lanpr_append_render_line_chain_point(rb,
rlc,
new_rl->r->fbcoord[0],
new_rl->r->fbcoord[1],
new_rl->r->gloc[0],
new_rl->r->gloc[1],
new_rl->r->gloc[2],
N,
new_rl->flags,
last_occlusion);
}
ba = ED_lanpr_get_point_bounding_area_deep(rb, new_rv->fbcoord[0], new_rv->fbcoord[1]);
}
}
}
static LANPR_BoundingArea *lanpr_get_rlci_bounding_area_recursive(LANPR_RenderBuffer *rb,
LANPR_BoundingArea *root,
LANPR_RenderLineChainItem *rlci)
{
if (!root->child) {
return root;
}
else {
LANPR_BoundingArea *ch = root->child;
#define IN_BOUND(ba, rlci) \
ba.l <= rlci->pos[0] && ba.r >= rlci->pos[0] && ba.b <= rlci->pos[1] && ba.u >= rlci->pos[1]
if (IN_BOUND(ch[0], rlci)) {
return lanpr_get_rlci_bounding_area_recursive(rb, &ch[0], rlci);
}
else if (IN_BOUND(ch[1], rlci)) {
return lanpr_get_rlci_bounding_area_recursive(rb, &ch[1], rlci);
}
else if (IN_BOUND(ch[2], rlci)) {
return lanpr_get_rlci_bounding_area_recursive(rb, &ch[2], rlci);
}
else if (IN_BOUND(ch[3], rlci)) {
return lanpr_get_rlci_bounding_area_recursive(rb, &ch[3], rlci);
}
#undef IN_BOUND
}
return NULL;
}
static LANPR_BoundingArea *lanpr_get_end_point_bounding_area(LANPR_RenderBuffer *rb,
LANPR_RenderLineChainItem *rlci)
{
LANPR_BoundingArea *root = ED_lanpr_get_point_bounding_area(rb, rlci->pos[0], rlci->pos[1]);
if (!root) {
return NULL;
}
return lanpr_get_rlci_bounding_area_recursive(rb, root, rlci);
}
/* if reduction threshold is even larger than a small bounding area, */
/* then 1) geometry is simply too dense. */
/* 2) probably need to add it to root bounding area which has larger surface area then it
* will */
/* cover typical threshold values. */
static void lanpr_link_point_with_bounding_area_recursive(LANPR_RenderBuffer *rb,
LANPR_BoundingArea *root,
LANPR_RenderLineChain *rlc,
LANPR_RenderLineChainItem *rlci)
{
if (!root->child) {
LANPR_ChainRegisterEntry *cre = list_append_pointer_static_sized(
&root->linked_chains, &rb->render_data_pool, rlc, sizeof(LANPR_ChainRegisterEntry));
cre->rlci = rlci;
if (rlci == rlc->chain.first) {
cre->is_left = 1;
}
}
else {
LANPR_BoundingArea *ch = root->child;
#define IN_BOUND(ba, rlci) \
ba.l <= rlci->pos[0] && ba.r >= rlci->pos[0] && ba.b <= rlci->pos[1] && ba.u >= rlci->pos[1]
if (IN_BOUND(ch[0], rlci)) {
lanpr_link_point_with_bounding_area_recursive(rb, &ch[0], rlc, rlci);
}
else if (IN_BOUND(ch[1], rlci)) {
lanpr_link_point_with_bounding_area_recursive(rb, &ch[1], rlc, rlci);
}
else if (IN_BOUND(ch[2], rlci)) {
lanpr_link_point_with_bounding_area_recursive(rb, &ch[2], rlc, rlci);
}
else if (IN_BOUND(ch[3], rlci)) {
lanpr_link_point_with_bounding_area_recursive(rb, &ch[3], rlc, rlci);
}
#undef IN_BOUND
}
}
static void lanpr_link_chain_with_bounding_areas(LANPR_RenderBuffer *rb,
LANPR_RenderLineChain *rlc)
{
LANPR_RenderLineChainItem *pl = rlc->chain.first;
LANPR_RenderLineChainItem *pr = rlc->chain.last;
LANPR_BoundingArea *ba1 = ED_lanpr_get_point_bounding_area(rb, pl->pos[0], pl->pos[1]);
LANPR_BoundingArea *ba2 = ED_lanpr_get_point_bounding_area(rb, pr->pos[0], pr->pos[1]);
if (ba1) {
lanpr_link_point_with_bounding_area_recursive(rb, ba1, rlc, pl);
}
if (ba2) {
lanpr_link_point_with_bounding_area_recursive(rb, ba2, rlc, pr);
}
}
void ED_lanpr_split_chains_for_fixed_occlusion(LANPR_RenderBuffer *rb)
{
LANPR_RenderLineChain *rlc, *new_rlc;
LANPR_RenderLineChainItem *rlci, *next_rlci;
ListBase swap = {0};
swap.first = rb->chains.first;
swap.last = rb->chains.last;
rb->chains.last = rb->chains.first = NULL;
while ((rlc = BLI_pophead(&swap)) != NULL) {
rlc->next = rlc->prev = NULL;
BLI_addtail(&rb->chains, rlc);
LANPR_RenderLineChainItem *first_rlci = (LANPR_RenderLineChainItem *)rlc->chain.first;
int fixed_occ = first_rlci->occlusion;
rlc->level = fixed_occ;
for (rlci = first_rlci->next; rlci; rlci = next_rlci) {
next_rlci = rlci->next;
if (rlci->occlusion != fixed_occ) {
new_rlc = lanpr_create_render_line_chain(rb);
new_rlc->chain.first = rlci;
new_rlc->chain.last = rlc->chain.last;
rlc->chain.last = rlci->prev;
((LANPR_RenderLineChainItem *)rlc->chain.last)->next = 0;
rlci->prev = 0;
/* end the previous one */
lanpr_append_render_line_chain_point(rb,
rlc,
rlci->pos[0],
rlci->pos[1],
rlci->gpos[0],
rlci->gpos[1],
rlci->gpos[2],
rlci->normal,
rlci->line_type,
fixed_occ);
new_rlc->object_ref = rlc->object_ref;
new_rlc->type = rlc->type;
rlc = new_rlc;
fixed_occ = rlci->occlusion;
rlc->level = fixed_occ;
}
}
}
for (rlc = rb->chains.first; rlc; rlc = rlc->next) {
lanpr_link_chain_with_bounding_areas(rb, rlc);
}
}
/* note: segment type (crease/material/contour...) is ambiguous after this. */
static void lanpr_connect_two_chains(LANPR_RenderBuffer *UNUSED(rb),
LANPR_RenderLineChain *onto,
LANPR_RenderLineChain *sub,
int reverse_1,
int reverse_2)
{
if (!reverse_1) { /* L--R L-R */
if (reverse_2) { /* L--R R-L */
BLI_listbase_reverse(&sub->chain);
}
((LANPR_RenderLineChainItem *)onto->chain.last)->next = sub->chain.first;
((LANPR_RenderLineChainItem *)sub->chain.first)->prev = onto->chain.last;
onto->chain.last = sub->chain.last;
}
else { /* L-R L--R */
if (!reverse_2) { /* R-L L--R */
BLI_listbase_reverse(&sub->chain);
}
((LANPR_RenderLineChainItem *)sub->chain.last)->next = onto->chain.first;
((LANPR_RenderLineChainItem *)onto->chain.first)->prev = sub->chain.last;
onto->chain.first = sub->chain.first;
}
/* ((LANPR_RenderLineChainItem*)sub->chain.first)->occlusion = */
/* ((LANPR_RenderLineChainItem*)onto->chain.first)->occlusion; */
/* ((LANPR_RenderLineChainItem*)onto->chain.last)->occlusion = */
/* ((LANPR_RenderLineChainItem*)onto->chain.first)->occlusion; */
/* ((LANPR_RenderLineChainItem*)sub->chain.last)->occlusion = */
/* ((LANPR_RenderLineChainItem*)onto->chain.first)->occlusion; */
}
/* this only does head-tail connection. */
/* overlapping / tiny isolated segment / loop reduction not implemented here yet. */
void ED_lanpr_connect_chains(LANPR_RenderBuffer *rb, int do_geometry_space)
{
LANPR_RenderLineChain *rlc;
LANPR_RenderLineChainItem *rlci;
LANPR_BoundingArea *ba;
LANPR_ChainRegisterEntry *cre, *next_cre, *closest_cre;
float dist;
int occlusion;
ListBase swap = {0};
if ((!do_geometry_space && rb->scene->lanpr.chaining_image_threshold < 0.0001) ||
(do_geometry_space && rb->scene->lanpr.chaining_geometry_threshold < 0.0001)) {
return;
}
swap.first = rb->chains.first;
swap.last = rb->chains.last;
rb->chains.last = rb->chains.first = NULL;
while ((rlc = BLI_pophead(&swap)) != NULL) {
rlc->next = rlc->prev = NULL;
BLI_addtail(&rb->chains, rlc);
if (rlc->picked) {
continue;
}
rlc->picked = 1;
occlusion = ((LANPR_RenderLineChainItem *)rlc->chain.first)->occlusion;
rlci = rlc->chain.last;
while ((ba = lanpr_get_end_point_bounding_area(rb, rlci)) != NULL) {
dist = do_geometry_space ? rb->scene->lanpr.chaining_geometry_threshold :
rb->scene->lanpr.chaining_image_threshold;
closest_cre = NULL;
if (!ba->linked_chains.first) {
break;
}
for (cre = ba->linked_chains.first; cre; cre = next_cre) {
next_cre = cre->next;
if (cre->rlc->object_ref != rlc->object_ref) {
continue;
}
if (cre->rlc == rlc ||
((LANPR_RenderLineChainItem *)cre->rlc->chain.first)->occlusion != occlusion ||
(cre->rlc->type != rlc->type)) {
continue;
}
if (cre->rlc->picked) {
BLI_remlink(&ba->linked_chains, cre);
continue;
}
float new_len = do_geometry_space ? len_v3v3(cre->rlci->gpos, rlci->gpos) :
len_v2v2(cre->rlci->pos, rlci->pos);
if (new_len < dist) {
closest_cre = cre;
dist = new_len;
}
}
if (closest_cre) {
closest_cre->picked = 1;
closest_cre->rlc->picked = 1;
BLI_remlink(&ba->linked_chains, cre);
if (closest_cre->is_left) {
lanpr_connect_two_chains(rb, rlc, closest_cre->rlc, 0, 0);
}
else {
lanpr_connect_two_chains(rb, rlc, closest_cre->rlc, 0, 1);
}
BLI_remlink(&swap, closest_cre->rlc);
}
else {
break;
}
rlci = rlc->chain.last;
}
rlci = rlc->chain.first;
while ((ba = lanpr_get_end_point_bounding_area(rb, rlci)) != NULL) {
dist = do_geometry_space ? rb->scene->lanpr.chaining_geometry_threshold :
rb->scene->lanpr.chaining_image_threshold;
closest_cre = NULL;
if (!ba->linked_chains.first) {
break;
}
for (cre = ba->linked_chains.first; cre; cre = next_cre) {
next_cre = cre->next;
if (cre->rlc->object_ref != rlc->object_ref) {
continue;
}
if (cre->rlc == rlc ||
((LANPR_RenderLineChainItem *)cre->rlc->chain.first)->occlusion != occlusion ||
(cre->rlc->type != rlc->type)) {
continue;
}
if (cre->rlc->picked) {
BLI_remlink(&ba->linked_chains, cre);
continue;
}
float new_len = do_geometry_space ? len_v3v3(cre->rlci->gpos, rlci->gpos) :
len_v2v2(cre->rlci->pos, rlci->pos);
if (new_len < dist) {
closest_cre = cre;
dist = new_len;
}
}
if (closest_cre) {
closest_cre->picked = 1;
closest_cre->rlc->picked = 1;
BLI_remlink(&ba->linked_chains, cre);
if (closest_cre->is_left) {
lanpr_connect_two_chains(rb, rlc, closest_cre->rlc, 1, 0);
}
else {
lanpr_connect_two_chains(rb, rlc, closest_cre->rlc, 1, 1);
}
BLI_remlink(&swap, closest_cre->rlc);
}
else {
break;
}
rlci = rlc->chain.first;
}
}
}
/* length is in image space */
float ED_lanpr_compute_chain_length(LANPR_RenderLineChain *rlc)
{
LANPR_RenderLineChainItem *rlci;
float offset_accum = 0;
float dist;
float last_point[2];
rlci = rlc->chain.first;
copy_v2_v2(last_point, rlci->pos);
for (rlci = rlc->chain.first; rlci; rlci = rlci->next) {
dist = len_v2v2(rlci->pos, last_point);
offset_accum += dist;
copy_v2_v2(last_point, rlci->pos);
}
return offset_accum;
}
void ED_lanpr_discard_short_chains(LANPR_RenderBuffer *rb, float threshold)
{
LANPR_RenderLineChain *rlc, *next_rlc;
for (rlc = rb->chains.first; rlc; rlc = next_rlc) {
next_rlc = rlc->next;
if (ED_lanpr_compute_chain_length(rlc) < threshold) {
BLI_remlink(&rb->chains, rlc);
}
}
}
int ED_lanpr_count_chain(LANPR_RenderLineChain *rlc)
{
LANPR_RenderLineChainItem *rlci;
int Count = 0;
for (rlci = rlc->chain.first; rlci; rlci = rlci->next) {
Count++;
}
return Count;
}
void ED_lanpr_chain_clear_picked_flag(LANPR_RenderBuffer *rb)
{
LANPR_RenderLineChain *rlc;
if (!rb) {
return;
}
for (rlc = rb->chains.first; rlc; rlc = rlc->next) {
rlc->picked = 0;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
/*
* 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) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup editors
*/
#ifndef __LANPR_INTERN_H__
#define __LANPR_INTERN_H__
#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_threads.h"
#include "DNA_lanpr_types.h"
#include <math.h>
#include <string.h>
struct LANPR_StaticMemPoolNode;
struct LANPR_RenderLine;
struct LANPR_RenderBuffer;
void *list_append_pointer_static(ListBase *h, struct LANPR_StaticMemPool *smp, void *p);
void *list_append_pointer_static_sized(ListBase *h,
struct LANPR_StaticMemPool *smp,
void *p,
int size);
void *list_push_pointer_static(ListBase *h, struct LANPR_StaticMemPool *smp, void *p);
void *list_push_pointer_static_sized(ListBase *h,
struct LANPR_StaticMemPool *smp,
void *p,
int size);
void *list_append_pointer_static_pool(struct LANPR_StaticMemPool *mph, ListBase *h, void *p);
void *list_pop_pointer_no_free(ListBase *h);
void list_remove_pointer_item_no_free(ListBase *h, LinkData *lip);
LANPR_StaticMemPoolNode *mem_new_static_pool(struct LANPR_StaticMemPool *smp);
void *mem_static_aquire(struct LANPR_StaticMemPool *smp, int size);
void *mem_static_aquire_thread(struct LANPR_StaticMemPool *smp, int size);
void *mem_static_destroy(LANPR_StaticMemPool *smp);
void tmat_make_ortho_matrix_44d(double (*mProjection)[4],
double xMin,
double xMax,
double yMin,
double yMax,
double zMin,
double zMax);
void tmat_make_perspective_matrix_44d(
double (*mProjection)[4], double fFov_rad, double fAspect, double zMin, double zMax);
int lanpr_count_this_line(struct LANPR_RenderLine *rl, struct LANPR_LineLayer *ll);
int lanpr_count_intersection_segment_count(struct LANPR_RenderBuffer *rb);
#endif

View File

@@ -0,0 +1,50 @@
/*
* 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) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup editors
*/
#include <stdlib.h>
#include "BLI_utildefines.h"
#include "WM_api.h"
#include "ED_lanpr.h"
void ED_operatortypes_lanpr(void)
{
/* lanpr: */
WM_operatortype_append(SCENE_OT_lanpr_calculate_feature_lines);
WM_operatortype_append(SCENE_OT_lanpr_add_line_layer);
WM_operatortype_append(SCENE_OT_lanpr_delete_line_layer);
WM_operatortype_append(SCENE_OT_lanpr_rebuild_all_commands);
WM_operatortype_append(SCENE_OT_lanpr_auto_create_line_layer);
WM_operatortype_append(SCENE_OT_lanpr_move_line_layer);
WM_operatortype_append(SCENE_OT_lanpr_add_line_component);
WM_operatortype_append(SCENE_OT_lanpr_delete_line_component);
WM_operatortype_append(SCENE_OT_lanpr_enable_all_line_types);
WM_operatortype_append(SCENE_OT_lanpr_update_gp_strokes);
WM_operatortype_append(SCENE_OT_lanpr_bake_gp_strokes);
WM_operatortype_append(OBJECT_OT_lanpr_update_gp_target);
/* Not working */
/* WM_operatortype_append(OBJECT_OT_lanpr_update_gp_source); */
}

View File

@@ -0,0 +1,197 @@
/*
* 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) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup editors
*/
#include <stdlib.h>
#include <stdio.h>
/* #include <time.h> */
#include "ED_lanpr.h"
#include "MEM_guardedalloc.h"
#include <math.h>
#include "lanpr_intern.h"
/* ===================================================================[slt] */
void *list_append_pointer_static(ListBase *h, LANPR_StaticMemPool *smp, void *data)
{
LinkData *lip;
if (!h) {
return 0;
}
lip = mem_static_aquire(smp, sizeof(LinkData));
lip->data = data;
BLI_addtail(h, lip);
return lip;
}
void *list_append_pointer_static_sized(ListBase *h, LANPR_StaticMemPool *smp, void *data, int size)
{
LinkData *lip;
if (!h) {
return 0;
}
lip = mem_static_aquire(smp, size);
lip->data = data;
BLI_addtail(h, lip);
return lip;
}
void *list_append_pointer_static_pool(LANPR_StaticMemPool *mph, ListBase *h, void *data)
{
LinkData *lip;
if (!h) {
return 0;
}
lip = mem_static_aquire(mph, sizeof(LinkData));
lip->data = data;
BLI_addtail(h, lip);
return lip;
}
void *list_pop_pointer_no_free(ListBase *h)
{
LinkData *lip;
void *rev = 0;
if (!h) {
return 0;
}
lip = BLI_pophead(h);
rev = lip ? lip->data : 0;
return rev;
}
void list_remove_pointer_item_no_free(ListBase *h, LinkData *lip)
{
BLI_remlink(h, (void *)lip);
}
LANPR_StaticMemPoolNode *mem_new_static_pool(LANPR_StaticMemPool *smp)
{
LANPR_StaticMemPoolNode *smpn = MEM_callocN(LANPR_MEMORY_POOL_128MB, "mempool");
smpn->used_byte = sizeof(LANPR_StaticMemPoolNode);
BLI_addhead(&smp->pools, smpn);
return smpn;
}
void *mem_static_aquire(LANPR_StaticMemPool *smp, int size)
{
LANPR_StaticMemPoolNode *smpn = smp->pools.first;
void *ret;
if (!smpn || (smpn->used_byte + size) > LANPR_MEMORY_POOL_128MB) {
smpn = mem_new_static_pool(smp);
}
ret = ((unsigned char *)smpn) + smpn->used_byte;
smpn->used_byte += size;
return ret;
}
void *mem_static_aquire_thread(LANPR_StaticMemPool *smp, int size)
{
LANPR_StaticMemPoolNode *smpn = smp->pools.first;
void *ret;
BLI_spin_lock(&smp->lock_mem);
if (!smpn || (smpn->used_byte + size) > LANPR_MEMORY_POOL_128MB) {
smpn = mem_new_static_pool(smp);
}
ret = ((unsigned char *)smpn) + smpn->used_byte;
smpn->used_byte += size;
BLI_spin_unlock(&smp->lock_mem);
return ret;
}
void *mem_static_destroy(LANPR_StaticMemPool *smp)
{
LANPR_StaticMemPoolNode *smpn;
void *ret = 0;
while ((smpn = BLI_pophead(&smp->pools)) != NULL) {
MEM_freeN(smpn);
}
smp->each_size = 0;
return ret;
}
/* =======================================================================[str] */
real tmat_length_3d(tnsVector3d l)
{
return (sqrt(l[0] * l[0] + l[1] * l[1] + l[2] * l[2]));
}
real tmat_vector_cross_3d(tnsVector3d result, tnsVector3d l, tnsVector3d r)
{
result[0] = l[1] * r[2] - l[2] * r[1];
result[1] = l[2] * r[0] - l[0] * r[2];
result[2] = l[0] * r[1] - l[1] * r[0];
return tmat_length_3d(result);
}
void tmat_make_perspective_matrix_44d(
double (*mProjection)[4], real fFov_rad, real fAspect, real zMin, real zMax)
{
real yMax;
real yMin;
real xMin;
real xMax;
if (fAspect < 1) {
yMax = zMin * tan(fFov_rad * 0.5f);
yMin = -yMax;
xMin = yMin * fAspect;
xMax = -xMin;
}
else {
xMax = zMin * tan(fFov_rad * 0.5f);
xMin = -xMax;
yMin = xMin / fAspect;
yMax = -yMin;
}
unit_m4_db(mProjection);
mProjection[0][0] = (2.0f * zMin) / (xMax - xMin);
mProjection[1][1] = (2.0f * zMin) / (yMax - yMin);
mProjection[2][0] = (xMax + xMin) / (xMax - xMin);
mProjection[2][1] = (yMax + yMin) / (yMax - yMin);
mProjection[2][2] = -((zMax + zMin) / (zMax - zMin));
mProjection[2][3] = -1.0f;
mProjection[3][2] = -((2.0f * (zMax * zMin)) / (zMax - zMin));
mProjection[3][3] = 0.0f;
}
void tmat_make_ortho_matrix_44d(
double (*mProjection)[4], real xMin, real xMax, real yMin, real yMax, real zMin, real zMax)
{
unit_m4_db(mProjection);
mProjection[0][0] = 2.0f / (xMax - xMin);
mProjection[1][1] = 2.0f / (yMax - yMin);
mProjection[2][2] = -2.0f / (zMax - zMin);
mProjection[3][0] = -((xMax + xMin) / (xMax - xMin));
mProjection[3][1] = -((yMax + yMin) / (yMax - yMin));
mProjection[3][2] = -((zMax + zMin) / (zMax - zMin));
mProjection[3][3] = 1.0f;
}

View File

@@ -59,6 +59,8 @@
#include "ED_render.h"
#include "ED_view3d.h"
#include "ED_lanpr.h"
#include "DEG_depsgraph.h"
#include "WM_api.h"
@@ -95,6 +97,9 @@ void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int update
return;
}
/* Temporary solution for updating LANPR GPencil targets. */
ED_lanpr_post_frame_update_external(scene, update_ctx->depsgraph);
recursive_check = true;
C = CTX_create();

View File

@@ -64,6 +64,8 @@
#include "ED_gizmo_library.h"
#include "ED_transform.h"
#include "ED_lanpr.h"
#include "io_ops.h"
/* only call once on startup, storage is global in BKE kernel listbase */
@@ -123,6 +125,8 @@ void ED_spacetypes_init(void)
ED_operatortypes_view2d();
ED_operatortypes_ui();
ED_operatortypes_lanpr();
ED_screen_user_menu_register();
/* gizmo types */

View File

@@ -164,6 +164,31 @@ static int buttons_context_path_world(ButsContextPath *path)
return 0;
}
static int buttons_context_path_collection(ButsContextPath *path, wmWindow *window)
{
Scene *scene;
World *world;
PointerRNA *ptr = &path->ptr[path->len - 1];
/* if we already have a (pinned) collection, we're done */
if (RNA_struct_is_a(ptr->type, &RNA_Collection)) {
return 1;
}
/* if we have a view layer, use the view layer's active collection */
else if (buttons_context_path_view_layer(path, window)) {
ViewLayer *view_layer = path->ptr[path->len - 1].data;
Collection *c = view_layer->active_collection->collection;
if (c) {
RNA_id_pointer_create(&c->id, &path->ptr[path->len]);
path->len++;
return 1;
}
}
/* no path to a collection possible */
return 0;
}
static int buttons_context_path_linestyle(ButsContextPath *path, wmWindow *window)
{
FreestyleLineStyle *linestyle;
@@ -575,6 +600,18 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
case BCONTEXT_WORLD:
found = buttons_context_path_world(path);
break;
case BCONTEXT_COLLECTION:
found = buttons_context_path_collection(path, window);
break;
case BCONTEXT_LANPR:
if (scene &&
((scene->lanpr.flags & LANPR_ENABLED) || !strcmp(scene->r.engine, "BLENDER_LANPR"))) {
found = buttons_context_path_object(path);
}
else {
found = 0;
}
break;
case BCONTEXT_TOOL:
found = true;
break;

View File

@@ -160,6 +160,12 @@ static void buttons_main_region_layout_properties(const bContext *C,
case BCONTEXT_WORLD:
contexts[0] = "world";
break;
case BCONTEXT_COLLECTION:
contexts[0] = "collection";
break;
case BCONTEXT_LANPR:
contexts[0] = "lanpr";
break;
case BCONTEXT_OBJECT:
contexts[0] = "object";
break;

View File

@@ -1005,6 +1005,7 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
}
WM_msg_subscribe_rna_anon_type(mbus, SceneEEVEE, &msg_sub_value_region_tag_redraw);
WM_msg_subscribe_rna_anon_type(mbus, SceneLANPR, &msg_sub_value_region_tag_redraw);
WM_msg_subscribe_rna_anon_type(mbus, SceneDisplay, &msg_sub_value_region_tag_redraw);
WM_msg_subscribe_rna_anon_type(mbus, ObjectDisplay, &msg_sub_value_region_tag_redraw);

View File

@@ -27,6 +27,7 @@
#define __DNA_COLLECTION_TYPES_H__
#include "DNA_defs.h"
#include "DNA_lanpr_types.h"
#include "DNA_listBase.h"
#include "DNA_ID.h"
@@ -43,6 +44,39 @@ typedef struct CollectionChild {
struct Collection *collection;
} CollectionChild;
enum CollectionFeatureLine_Usage {
COLLECTION_FEATURE_LINE_INCLUDE = 0,
COLLECTION_FEATURE_LINE_OCCLUSION_ONLY = (1 << 0),
COLLECTION_FEATURE_LINE_EXCLUDE = (1 << 1),
};
typedef struct CollectionLANPRLineType {
int use;
char _pad[4];
char target_layer[128];
char target_material[128];
} CollectionLANPRLineType;
typedef struct CollectionLANPR {
int usage;
/* Separate flags for LANPR shared flag values. */
int flags;
struct Object *target;
char target_layer[128];
char target_material[128];
struct CollectionLANPRLineType contour;
struct CollectionLANPRLineType crease;
struct CollectionLANPRLineType material;
struct CollectionLANPRLineType edge_mark;
struct CollectionLANPRLineType intersection;
int level_start;
int level_end;
} CollectionLANPR;
typedef struct Collection {
ID id;
@@ -61,6 +95,9 @@ typedef struct Collection {
short tag;
char _pad[4];
/** LANPR engine specific */
CollectionLANPR lanpr;
/* Runtime. Cache of objects in this collection and all its
* children. This is created on demand when e.g. some physics
* simulation needs it, we don't want to have it for every

View File

@@ -294,6 +294,8 @@ typedef enum eGPDframe_Flag {
GP_FRAME_PAINT = (1 << 0),
/* for editing in Action Editor */
GP_FRAME_SELECT = (1 << 1),
/* LANPR generation */
GP_FRAME_LANPR_CLEARED = (1 << 2),
} eGPDframe_Flag;
/* ***************************************** */

View File

@@ -0,0 +1,140 @@
/*
* ***** 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) 2010 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __DNA_LANPR_TYPES_H__
#define __DNA_LANPR_TYPES_H__
/** \file DNA_lanpr_types.h
* \ingroup DNA
*/
#include "DNA_listBase.h"
#include "DNA_ID.h"
#include "DNA_collection_types.h"
struct Object;
struct Material;
struct Collection;
typedef enum LANPR_TaperSettings {
LANPR_USE_DIFFERENT_TAPER = 0,
LANPR_USE_SAME_TAPER = 1,
} LANPR_TaperSettings;
typedef enum LANPR_NomalEffect {
/* Shouldn't have access to zero value. */
/* Enable/disable is another flag. */
LANPR_NORMAL_DIRECTIONAL = 1,
LANPR_NORMAL_POINT = 2,
} LANPR_NomalEffect;
typedef enum LANPR_ComponentMode {
LANPR_COMPONENT_MODE_ALL = 0,
LANPR_COMPONENT_MODE_OBJECT = 1,
LANPR_COMPONENT_MODE_MATERIAL = 2,
LANPR_COMPONENT_MODE_COLLECTION = 3,
} LANPR_ComponentMode;
typedef enum LANPR_ComponentUsage {
LANPR_COMPONENT_INCLUSIVE = 0,
LANPR_COMPONENT_EXCLUSIVE = 1,
} LANPR_ComponentUsage;
typedef enum LANPR_ComponentLogic {
LANPR_COMPONENT_LOGIG_OR = 0,
LANPR_COMPONENT_LOGIC_AND = 1,
} LANPR_ComponentLogic;
struct DRWShadingGroup;
typedef struct LANPR_LineLayerComponent {
struct LANPR_LineLayerComponent *next, *prev;
struct Object *object_select;
struct Material *material_select;
struct Collection *collection_select;
int component_mode;
int what;
} LANPR_LineLayerComponent;
typedef struct LANPR_LineType {
int use;
float thickness;
float color[4];
} LANPR_LineType;
typedef enum LANPR_LineLayerFlags {
LANPR_LINE_LAYER_USE_SAME_STYLE = (1 << 0), /* Share with object lanpr flags */
LANPR_LINE_LAYER_USE_MULTIPLE_LEVELS = (1 << 1), /* Share with object lanpr flags */
LANPR_LINE_LAYER_NORMAL_ENABLED = (1 << 2),
LANPR_LINE_LAYER_NORMAL_INVERSE = (1 << 3),
LANPR_LINE_LAYER_REPLACE_STROKES = (1 << 4),
LANPR_LINE_LAYER_COLLECTION_FORCE = (1 << 5),
} LANPR_LineLayerFlags;
typedef struct LANPR_LineLayer {
struct LANPR_LineLayer *next, *prev;
int flags;
int _pad1;
int level_start;
int level_end;
/** To be displayed on the list */
char name[64];
LANPR_LineType contour;
LANPR_LineType crease;
LANPR_LineType edge_mark;
LANPR_LineType material_separate;
LANPR_LineType intersection;
float thickness;
float color[4];
int normal_mode;
float normal_ramp_begin;
float normal_ramp_end;
float normal_thickness_start;
float normal_thickness_end;
struct Object *normal_control_object;
/** For component evaluation */
int logic_mode;
int _pad3;
ListBase components;
struct DRWShadingGroup *shgrp;
struct GPUBatch *batch;
} LANPR_LineLayer;
#endif

View File

@@ -29,6 +29,7 @@
#include "DNA_defs.h"
#include "DNA_customdata_types.h"
#include "DNA_lanpr_types.h"
#include "DNA_listBase.h"
#include "DNA_ID.h"
#include "DNA_action_types.h" /* bAnimVizSettings */
@@ -186,6 +187,40 @@ typedef struct Object_Runtime {
void *_pad2; /* Padding is here for win32s unconventional struct alignment rules. */
} Object_Runtime;
typedef struct ObjectLANPRLineType {
int use;
char _pad[4];
char target_layer[128];
char target_material[128];
} ObjectLANPRLineType;
typedef struct ObjectLANPR {
int usage;
/* Separate flags for LANPR shared flag values. */
int flags;
struct Object *target;
char target_layer[128];
char target_material[128];
ObjectLANPRLineType crease;
ObjectLANPRLineType contour;
ObjectLANPRLineType material;
ObjectLANPRLineType edge_mark;
/* Intersection not implemented as per-object */
int level_start;
int level_end;
} ObjectLANPR;
enum ObjectFeatureLine_Usage {
OBJECT_FEATURE_LINE_INHERENT = 0,
OBJECT_FEATURE_LINE_INCLUDE = (1 << 0),
OBJECT_FEATURE_LINE_OCCLUSION_ONLY = (1 << 1),
OBJECT_FEATURE_LINE_EXCLUDE = (1 << 2),
};
typedef struct Object {
ID id;
/** Animation data (must be immediately after id for utilities to use it). */
@@ -396,6 +431,8 @@ typedef struct Object {
struct PreviewImage *preview;
ObjectLANPR lanpr;
/** Runtime evaluation data (keep last). */
Object_Runtime runtime;
} Object;

View File

@@ -1647,6 +1647,79 @@ typedef struct SceneEEVEE {
float light_threshold;
} SceneEEVEE;
/* LANPR Global Config */
struct LANPR_RenderBuffer;
struct LANPR_LineLayer;
typedef enum LANPR_MasterMode {
LANPR_MASTER_MODE_SOFTWARE = 0,
LANPR_MASTER_MODE_DPIX = 1,
LANPR_MASTER_MODE_SNAKE = 2,
} LANPR_MasterMode;
typedef enum LANPR_PostProcessingStatus {
LANPR_POST_PROCESSING_DISABLED = 0,
LANPR_POST_PROCESSING_ENABLED = 1,
} LANPR_PostProcessingStatus;
typedef enum LANPR_MainFlags {
LANPR_ENABLED = (1 << 0),
/* For LANPR->GP and viewport to update automatically. */
LANPR_AUTO_UPDATE = (1 << 1),
LANPR_SAME_TAPER = (1 << 2),
/* Edge split modifier will cause problems in LANPR. */
LANPR_DISABLE_EDGE_SPLITS = (1 << 3),
LANPR_USE_CHAINING = (1 << 4),
LANPR_USE_INTERSECTIONS = (1 << 5),
/* Overwrite existing strokes in this frame. */
LANPR_GPENCIL_OVERWRITE = (1 << 6),
} LANPR_MainFlags;
typedef struct SceneLANPR {
int flags;
int master_mode; /* LANPR_MasterMode */
float taper_left_distance;
float taper_left_strength;
float taper_right_distance;
float taper_right_strength;
/* shared */
float contour_fade; /* for dpix contour fading,reserved for future usage */
float crease_threshold; /* 0-1 range for cosine angle */
float crease_fade_threshold; /* for dpix crease fading */
float line_color[4];
float depth_width_influence;
float depth_width_curve;
float depth_alpha_influence;
float depth_alpha_curve;
int gpu_cache_size; /* enum! */
int _pad;
int enable_chain_connection;
/* offline render */
ListBase line_layers;
struct LANPR_LineLayer *active_layer;
float chaining_geometry_threshold;
float chaining_image_threshold;
} SceneLANPR;
enum {
LANPR_GPU_CACHE_SIZE_512 = 0,
LANPR_GPU_CACHE_SIZE_1K = 1, /* default */
LANPR_GPU_CACHE_SIZE_2K = 2,
LANPR_GPU_CACHE_SIZE_4K = 3,
};
/* *************************************************************** */
/* Scene ID-Block */
@@ -1777,6 +1850,9 @@ typedef struct Scene {
struct SceneDisplay display;
struct SceneEEVEE eevee;
/* LANPR stuff */
struct SceneLANPR lanpr;
} Scene;
/* **************** RENDERDATA ********************* */

View File

@@ -195,6 +195,8 @@ typedef enum eSpaceButtons_Context {
BCONTEXT_TOOL = 14,
BCONTEXT_SHADERFX = 15,
BCONTEXT_OUTPUT = 16,
BCONTEXT_COLLECTION = 17,
BCONTEXT_LANPR = 18,
/* always as last... */
BCONTEXT_TOT,

View File

@@ -84,6 +84,7 @@ static const char *includefiles[] = {
"DNA_mesh_types.h",
"DNA_meshdata_types.h",
"DNA_modifier_types.h",
"DNA_lanpr_types.h",
"DNA_lattice_types.h",
"DNA_object_types.h",
"DNA_object_force_types.h",
@@ -1543,6 +1544,7 @@ int main(int argc, char **argv)
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_lanpr_types.h"
#include "DNA_lattice_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force_types.h"

View File

@@ -109,6 +109,7 @@ extern StructRNA RNA_CloudsTexture;
extern StructRNA RNA_Collection;
extern StructRNA RNA_CollectionEngineSettings;
extern StructRNA RNA_CollectionProperty;
extern StructRNA RNA_CollectionLANPR;
extern StructRNA RNA_CollisionModifier;
extern StructRNA RNA_CollisionSensor;
extern StructRNA RNA_CollisionSettings;
@@ -451,6 +452,7 @@ extern StructRNA RNA_NormalEditModifier;
extern StructRNA RNA_Object;
extern StructRNA RNA_ObjectBase;
extern StructRNA RNA_ObjectDisplay;
extern StructRNA RNA_ObjectLANPR;
extern StructRNA RNA_ObstacleFluidSettings;
extern StructRNA RNA_OceanModifier;
extern StructRNA RNA_OceanTexData;
@@ -523,6 +525,7 @@ extern StructRNA RNA_SPHFluidSettings;
extern StructRNA RNA_Scene;
extern StructRNA RNA_SceneDisplay;
extern StructRNA RNA_SceneEEVEE;
extern StructRNA RNA_SceneLANPR;
extern StructRNA RNA_SceneObjects;
extern StructRNA RNA_SceneRenderLayer;
extern StructRNA RNA_SceneSequence;

View File

@@ -53,6 +53,7 @@ set(DEFSRC
rna_light.c
rna_lightprobe.c
rna_linestyle.c
rna_lanpr.c
rna_main.c
rna_mask.c
rna_material.c
@@ -393,6 +394,7 @@ set(LIB
bf_editor_object
bf_editor_physics
bf_editor_render
bf_editor_lanpr
bf_editor_scene
bf_editor_sculpt_paint
bf_editor_space_clip

View File

@@ -4233,6 +4233,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_lattice.c", "rna_lattice_api.c", RNA_def_lattice},
{"rna_layer.c", NULL, RNA_def_view_layer},
{"rna_linestyle.c", NULL, RNA_def_linestyle},
{"rna_lanpr.c", NULL, RNA_def_lanpr},
{"rna_main.c", "rna_main_api.c", RNA_def_main},
{"rna_material.c", "rna_material_api.c", RNA_def_material},
{"rna_mesh.c", "rna_mesh_api.c", RNA_def_mesh},

View File

@@ -22,6 +22,8 @@
#include "DNA_collection_types.h"
#include "DNA_lanpr_types.h"
#include "BLI_utildefines.h"
#include "RNA_define.h"
@@ -365,6 +367,115 @@ static void rna_def_collection_children(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
}
static void rna_def_collection_lanpr(BlenderRNA *brna)
{
PropertyRNA *prop;
StructRNA *srna;
srna = RNA_def_struct(brna, "CollectionLANPRLineType", NULL);
RNA_def_struct_ui_text(srna, "Collection LANPR Line Type", "Collection lanpr line type");
RNA_def_struct_sdna(srna, "CollectionLANPRLineType");
prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(prop, "Use", "Use this line type");
prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "target_layer");
RNA_def_property_ui_text(prop, "Layer", "Grease Pencil layer to put the results into");
prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "target_material");
RNA_def_property_ui_text(
prop, "Material", "Grease Pencil material to use to generate the results");
static const EnumPropertyItem rna_collection_lanpr_usage[] = {
{COLLECTION_FEATURE_LINE_INCLUDE,
"INCLUDE",
0,
"Include",
"Collection will produce feature lines"},
{COLLECTION_FEATURE_LINE_OCCLUSION_ONLY,
"OCCLUSION_ONLY",
0,
"Occlusion Only",
"Only use the collection to produce occlusion"},
{COLLECTION_FEATURE_LINE_EXCLUDE,
"EXCLUDE",
0,
"Exclude",
"Don't use this collection in LANPR"},
{0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "CollectionLANPR", NULL);
RNA_def_struct_sdna(srna, "CollectionLANPR");
RNA_def_struct_ui_text(srna, "Collection LANPR Usage", "LANPR usage for this collection");
prop = RNA_def_property(srna, "usage", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_collection_lanpr_usage);
RNA_def_property_ui_text(prop, "Usage", "How to use this collection in LANPR");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "force", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_LINE_LAYER_COLLECTION_FORCE);
RNA_def_property_ui_text(
prop, "Force", "Force object that has LANPR modifiers to follow collection usage flag");
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "target");
RNA_def_property_ui_text(prop, "Target", "Grease Pencil object to put the stroke result");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_GPencil_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
prop = RNA_def_property(srna, "replace", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_LINE_LAYER_REPLACE_STROKES);
RNA_def_property_ui_text(prop, "Replace", "Replace existing GP frames");
prop = RNA_def_property(srna, "target_layer", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Layer", "Grease Pencil layer to put the results into");
prop = RNA_def_property(srna, "target_material", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(
prop, "Material", "Grease Pencil material to use to generate the results");
prop = RNA_def_property(srna, "use_same_style", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_LINE_LAYER_USE_SAME_STYLE);
RNA_def_property_ui_text(prop, "Same Style", "Use same style for different types");
prop = RNA_def_property(srna, "contour", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "CollectionLANPRLineType");
RNA_def_property_ui_text(prop, "Contour", "Contour line type");
prop = RNA_def_property(srna, "crease", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "CollectionLANPRLineType");
RNA_def_property_ui_text(prop, "Crease", "Creaseline type");
prop = RNA_def_property(srna, "edge_mark", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "CollectionLANPRLineType");
RNA_def_property_ui_text(prop, "Edge Mark", "Edge mark line type");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "CollectionLANPRLineType");
RNA_def_property_ui_text(prop, "Material", "Material separate line type");
prop = RNA_def_property(srna, "intersection", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "CollectionLANPRLineType");
RNA_def_property_ui_text(prop, "Intersection", "Intersection line type");
prop = RNA_def_property(srna, "use_multiple_levels", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_LINE_LAYER_USE_MULTIPLE_LEVELS);
RNA_def_property_ui_text(prop, "Multiple Levels", "Use multiple occlusion levels");
prop = RNA_def_property(srna, "level_start", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 255);
RNA_def_property_ui_range(prop, 0, 255, 1, -1);
RNA_def_property_ui_text(prop, "Level Start", "Occlusion level start");
prop = RNA_def_property(srna, "level_end", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 255);
RNA_def_property_ui_range(prop, 0, 255, 1, -1);
RNA_def_property_ui_text(prop, "Level End", "Occlusion level end");
}
void RNA_def_collections(BlenderRNA *brna)
{
StructRNA *srna;
@@ -458,6 +569,11 @@ void RNA_def_collections(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1);
RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
rna_def_collection_lanpr(brna);
prop = RNA_def_property(srna, "lanpr", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "CollectionLANPR");
RNA_def_property_ui_text(prop, "LANPR", "LANPR settings for the collection");
}
#endif

View File

@@ -165,6 +165,7 @@ void RNA_def_key(struct BlenderRNA *brna);
void RNA_def_light(struct BlenderRNA *brna);
void RNA_def_lattice(struct BlenderRNA *brna);
void RNA_def_linestyle(struct BlenderRNA *brna);
void RNA_def_lanpr(struct BlenderRNA *brna);
void RNA_def_main(struct BlenderRNA *brna);
void RNA_def_material(struct BlenderRNA *brna);
void RNA_def_mesh(struct BlenderRNA *brna);

View File

@@ -0,0 +1,235 @@
/*
* ***** 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.
*
* Contributor(s): Blender Foundation (2008).
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/makesrna/intern/rna_lanpr.c
* \ingroup RNA
*/
#include <stdio.h>
#include <stdlib.h>
#include "BLI_utildefines.h"
#include "BLI_string_utils.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "rna_internal.h"
#include "DNA_lanpr_types.h"
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
#include "WM_types.h"
#include "WM_api.h"
#ifdef RNA_RUNTIME
#else
static void rna_def_lanpr_line_layer(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem rna_enum_lanpr_normal_mode[] = {
{LANPR_NORMAL_DIRECTIONAL,
"DIRECTIONAL",
0,
"Directional",
"Use directional vector to control line width"},
/* Seems working... */
{LANPR_NORMAL_POINT, "POINT", 0, "Point", "Use Point Light Style"},
{0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "LANPR_LineLayer", NULL);
RNA_def_struct_sdna(srna, "LANPR_LineLayer");
RNA_def_struct_ui_text(srna, "Line Layer", "LANPR_LineLayer");
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Name", "Name of this layer");
prop = RNA_def_property(srna, "normal_enabled", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_LINE_LAYER_NORMAL_ENABLED);
RNA_def_property_ui_text(prop, "Enabled", "Enable normal controlled line weight");
prop = RNA_def_property(srna, "normal_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_lanpr_normal_mode);
RNA_def_property_ui_text(prop, "Normal", "Normal controlled line weight");
prop = RNA_def_property(srna, "normal_effect_inverse", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_LINE_LAYER_NORMAL_INVERSE);
RNA_def_property_ui_text(prop, "Inverse", "Inverse normal effect");
prop = RNA_def_property(
srna, "normal_ramp_begin", PROP_FLOAT, PROP_FACTOR); /* begin is least strength */
RNA_def_property_float_default(prop, 0.0f);
RNA_def_property_ui_text(prop, "Ramp Begin", "Normal ramp begin value");
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.05, 2);
prop = RNA_def_property(srna, "normal_ramp_end", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Ramp End", "Normal ramp end value");
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.05, 2);
prop = RNA_def_property(
srna, "normal_thickness_start", PROP_FLOAT, PROP_NONE); /* begin is least strength */
RNA_def_property_float_default(prop, 0.2f);
RNA_def_property_ui_text(prop, "Thickness Begin", "Normal thickness begin value");
RNA_def_property_ui_range(prop, 0.0f, 5.0f, 0.05, 2);
prop = RNA_def_property(srna, "normal_thickness_end", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 1.5f);
RNA_def_property_ui_text(prop, "Thickness End", "Normal thickness end value");
RNA_def_property_ui_range(prop, 0.0f, 5.0f, 0.05, 2);
prop = RNA_def_property(srna, "normal_control_object", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Object", "Normal style control object");
prop = RNA_def_property(srna, "use_same_style", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_LINE_LAYER_USE_SAME_STYLE);
RNA_def_property_boolean_default(prop, true);
RNA_def_property_ui_text(prop, "Same Style", "Use same styles for multiple line types.");
prop = RNA_def_property(srna, "use_multiple_levels", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_LINE_LAYER_USE_MULTIPLE_LEVELS);
RNA_def_property_ui_text(
prop, "Use Multiple Levels", "Select lines from multiple occlusion levels");
/* types */
prop = RNA_def_property(srna, "contour", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "LANPR_LineType");
RNA_def_property_ui_text(prop, "Contour", "Contour line type");
prop = RNA_def_property(srna, "crease", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "LANPR_LineType");
RNA_def_property_ui_text(prop, "Crease", "Creaseline type");
prop = RNA_def_property(srna, "edge_mark", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "LANPR_LineType");
RNA_def_property_ui_text(prop, "Edge Mark", "Edge mark line type");
prop = RNA_def_property(srna, "material_separate", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "LANPR_LineType");
RNA_def_property_ui_text(prop, "Material Separate", "Material separate line type");
prop = RNA_def_property(srna, "intersection", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "LANPR_LineType");
RNA_def_property_ui_text(prop, "Intersection", "Intersection line type");
prop = RNA_def_property(srna, "level_start", PROP_INT, PROP_NONE);
RNA_def_property_int_default(prop, 0);
RNA_def_property_ui_text(prop, "Level Start", "Occlusion level start");
RNA_def_property_range(prop, 0, 128);
prop = RNA_def_property(srna, "level_end", PROP_INT, PROP_NONE);
RNA_def_property_int_default(prop, 0);
RNA_def_property_ui_text(prop, "Level End", "Occlusion level end");
RNA_def_property_range(prop, 0, 128);
prop = RNA_def_property(srna, "thickness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Thickness", "Master Thickness");
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 0.1, 2);
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Color", "Master Color");
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 2);
prop = RNA_def_property(srna, "components", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "components", NULL);
RNA_def_property_struct_type(prop, "LANPR_LineLayerComponent");
RNA_def_property_ui_text(prop, "Components", "Line Layer Components");
}
static void rna_def_lanpr_line_type(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "LANPR_LineType", NULL);
RNA_def_struct_sdna(srna, "LANPR_LineType");
RNA_def_struct_ui_text(srna, "Line Type", "LANPR_LineType");
prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(prop, "Use", "This line type is enabled");
prop = RNA_def_property(srna, "thickness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Thickness", "Relative thickness to master");
RNA_def_property_ui_range(prop, 0.0f, 2.0f, 0.01, 2);
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Color", "Color of this line type");
}
static void rna_def_lanpr_line_component(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem lanpr_line_component_modes[] = {
{0, "ALL", 0, "All", "Show all lines, lines are already selected are not affected"},
{1, "OBJECT", 0, "Object", "Filter lines for selected object"},
{2, "MATERIAL", 0, "Material", "Filter lines that touches specific material"},
{3, "COLLECTION", 0, "Collection", "Filter lines in specific collections"},
{0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "LANPR_LineLayerComponent", NULL);
RNA_def_struct_sdna(srna, "LANPR_LineLayerComponent");
RNA_def_struct_ui_text(srna, "Line Layer Component", "LANPR_LineLayerComponent");
prop = RNA_def_property(srna, "component_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, lanpr_line_component_modes);
RNA_def_property_enum_default(prop, 0);
RNA_def_property_ui_text(prop, "Mode", "Limit the range of displayed lines");
prop = RNA_def_property(srna, "object_select", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Object", "Display lines for selected object");
prop = RNA_def_property(srna, "material_select", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Material");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Material", "Display lines that touches specific material");
prop = RNA_def_property(srna, "collection_select", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Collection", "Display lines in specific collections");
}
void RNA_def_lanpr(BlenderRNA *brna)
{
rna_def_lanpr_line_component(brna);
rna_def_lanpr_line_type(brna);
rna_def_lanpr_line_layer(brna);
}
#endif

View File

@@ -2371,6 +2371,110 @@ static void rna_def_object_display(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Shadow", "Object cast shadows in the 3d viewport");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
}
static void rna_def_object_lanpr(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "ObjectLANPRLineType", NULL);
RNA_def_struct_ui_text(srna, "Object LANPR Line Type", "Object lanpr line type");
RNA_def_struct_sdna(srna, "ObjectLANPRLineType");
prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(prop, "Use", "Use this line type");
prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "target_layer");
RNA_def_property_ui_text(prop, "Layer", "Grease Pencil layer to put the results into");
prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "target_material");
RNA_def_property_ui_text(
prop, "Material", "Grease Pencil material to use to generate the results");
static EnumPropertyItem prop_feature_line_usage_items[] = {
{OBJECT_FEATURE_LINE_INHERENT,
"INHEREIT",
0,
"Inhereit",
"Follow settings from the parent collection"},
{OBJECT_FEATURE_LINE_INCLUDE,
"INCLUDE",
0,
"Include",
"Include this object into LANPR calculation"},
{OBJECT_FEATURE_LINE_OCCLUSION_ONLY,
"OCCLUSION_ONLY",
0,
"Occlusion Only",
"Don't produce lines, only used as occlusion object"},
{OBJECT_FEATURE_LINE_EXCLUDE,
"EXCLUDE",
0,
"Exclude",
"Don't use this object for LANPR rendering"},
{0, NULL, 0, NULL, NULL},
};
srna = RNA_def_struct(brna, "ObjectLANPR", NULL);
RNA_def_struct_ui_text(srna, "Object LANPR", "Object lanpr settings");
RNA_def_struct_sdna(srna, "ObjectLANPR");
prop = RNA_def_property(srna, "usage", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_feature_line_usage_items);
RNA_def_property_ui_text(prop, "Usage", "How to use this object");
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "target");
RNA_def_property_ui_text(prop, "Target", "GPencil object to put the stroke result");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_GPencil_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
prop = RNA_def_property(srna, "replace", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_LINE_LAYER_REPLACE_STROKES);
RNA_def_property_ui_text(prop, "Replace", "Replace existing GP frames");
prop = RNA_def_property(srna, "target_layer", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Layer", "Grease Pencil layer to put the results into");
prop = RNA_def_property(srna, "target_material", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(
prop, "Material", "Grease Pencil material to use to generate the results");
prop = RNA_def_property(srna, "use_same_style", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_LINE_LAYER_USE_SAME_STYLE);
RNA_def_property_ui_text(prop, "Same Style", "Use same style for different line types");
prop = RNA_def_property(srna, "contour", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ObjectLANPRLineType");
RNA_def_property_ui_text(prop, "Contour", "Contour line type");
prop = RNA_def_property(srna, "crease", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ObjectLANPRLineType");
RNA_def_property_ui_text(prop, "Crease", "Creaseline type");
prop = RNA_def_property(srna, "edge_mark", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ObjectLANPRLineType");
RNA_def_property_ui_text(prop, "Edge Mark", "Edge mark line type");
prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ObjectLANPRLineType");
RNA_def_property_ui_text(prop, "Material", "Material separate line type");
prop = RNA_def_property(srna, "use_multiple_levels", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_LINE_LAYER_USE_MULTIPLE_LEVELS);
RNA_def_property_ui_text(prop, "Multiple Levels", "Use multiple occlusion levels");
prop = RNA_def_property(srna, "level_start", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 255);
RNA_def_property_ui_range(prop, 0, 255, 1, -1);
RNA_def_property_ui_text(prop, "Level Start", "Occlusion level start");
prop = RNA_def_property(srna, "level_end", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 255);
RNA_def_property_ui_range(prop, 0, 255, 1, -1);
RNA_def_property_ui_text(prop, "Level End", "Occlusion level end");
}
static void rna_def_object(BlenderRNA *brna)
{
@@ -3116,6 +3220,11 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, "rna_Object_display_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Object Display", "Object display settings for 3d viewport");
/* LANPR */
prop = RNA_def_property(srna, "lanpr", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ObjectLANPR");
RNA_def_property_ui_text(prop, "LANPR", "LANPR settings for the object");
RNA_api_object(srna);
}
@@ -3128,6 +3237,7 @@ void RNA_def_object(BlenderRNA *brna)
rna_def_face_map(brna);
rna_def_material_slot(brna);
rna_def_object_display(brna);
rna_def_object_lanpr(brna);
RNA_define_animate_sdna(true);
}

View File

@@ -33,6 +33,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_view3d_types.h"
#include "DNA_screen_types.h" /* TransformOrientation */
#include "DNA_lanpr_types.h"
#include "IMB_imbuf_types.h"
@@ -2494,6 +2495,64 @@ static char *rna_UnitSettings_path(PointerRNA *UNUSED(ptr))
return BLI_strdup("unit_settings");
}
/* lanpr */
void rna_lanpr_active_line_layer_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
SceneLANPR *lanpr = (SceneLANPR *)ptr->data;
*min = 0;
*max = max_ii(0, BLI_listbase_count(&lanpr->line_layers) - 1);
}
int rna_lanpr_active_line_layer_index_get(PointerRNA *ptr)
{
SceneLANPR *lanpr = (SceneLANPR *)ptr->data;
LANPR_LineLayer *ls;
int i = 0;
for (ls = lanpr->line_layers.first; ls; ls = ls->next) {
if (ls == lanpr->active_layer)
return i;
i++;
}
return 0;
}
void rna_lanpr_active_line_layer_index_set(PointerRNA *ptr, int value)
{
SceneLANPR *lanpr = (SceneLANPR *)ptr->data;
LANPR_LineLayer *ls;
int i = 0;
for (ls = lanpr->line_layers.first; ls; ls = ls->next) {
if (i == value) {
lanpr->active_layer = ls;
return;
}
i++;
}
lanpr->active_layer = 0;
}
PointerRNA rna_lanpr_active_line_layer_get(PointerRNA *ptr)
{
SceneLANPR *lanpr = (SceneLANPR *)ptr->data;
LANPR_LineLayer *ls = lanpr->active_layer;
return rna_pointer_inherit_refine(ptr, &RNA_LANPR_LineLayer, ls);
}
void rna_lanpr_active_line_layer_set(PointerRNA *ptr, PointerRNA value)
{
SceneLANPR *lanpr = (SceneLANPR *)ptr->data;
lanpr->active_layer = value.data;
}
extern bool ED_lanpr_dpix_shader_error(void);
static bool rna_lanpr_shader_error_get(PointerRNA *UNUSED(ptr))
{
return ED_lanpr_dpix_shader_error();
}
#else
/* Grease Pencil Interpolation tool settings */
@@ -7078,6 +7137,225 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
}
static void rna_def_scene_lanpr(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static const EnumPropertyItem rna_enum_lanpr_master_mode[] = {
{LANPR_MASTER_MODE_SOFTWARE, "SOFTWARE", 0, "CPU", "Software edge calculation"},
{LANPR_MASTER_MODE_DPIX, "DPIX", 0, "GPU", "DPIX GPU edge extraction"},
/* Temporally remove image filter mode. */
/* {LANPR_MASTER_MODE_SNAKE, "SNAKE", 0, "Edge Detection", "Edge detection filter and
tracing"}, */
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem rna_enum_lanpr_use_same_taper[] = {
{LANPR_USE_DIFFERENT_TAPER, "DISABLED", 0, "Different", "Use different taper value"},
{LANPR_USE_SAME_TAPER,
"ENABLED",
0,
"Same",
"Use same taper value for both sides of the line"},
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem rna_enum_lanpr_gpu_cache_size[] = {
{LANPR_GPU_CACHE_SIZE_512, "S512", 0, "512", "512px texture as cache"},
{LANPR_GPU_CACHE_SIZE_1K, "S1K", 0, "1K", "1K px texture as cache"},
{LANPR_GPU_CACHE_SIZE_2K, "S2K", 0, "2K", "2K px texture as cache"},
{LANPR_GPU_CACHE_SIZE_4K, "S4K", 0, "4K", "4K px texture as cache"},
{0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "SceneLANPR", NULL);
RNA_def_struct_sdna(srna, "SceneLANPR");
RNA_def_struct_ui_text(srna, "Scene LANPR Config", "LANPR global config");
prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_default(prop, 0);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_ENABLED);
RNA_def_property_ui_text(prop, "Enabled", "Is LANPR enabled");
RNA_def_property_update(prop, NC_WINDOW, NULL);
prop = RNA_def_property(srna, "auto_update", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_AUTO_UPDATE);
RNA_def_property_boolean_default(prop, 0);
RNA_def_property_ui_text(
prop, "Auto Update", "Automatically update LANPR cache when frame changes");
prop = RNA_def_property(srna, "gpencil_overwrite", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_GPENCIL_OVERWRITE);
RNA_def_property_boolean_default(prop, 0);
RNA_def_property_ui_text(prop,
"GPencil Overwrite",
"Overwrite existing strokes in the current frame of target GP objects");
prop = RNA_def_property(srna, "master_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_lanpr_master_mode);
RNA_def_property_enum_default(prop, LANPR_MASTER_MODE_DPIX);
RNA_def_property_ui_text(prop, "Master Mode", "Choose calculation mode for NPR Line");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "gpu_cache_size", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_lanpr_gpu_cache_size);
RNA_def_property_enum_default(prop, LANPR_GPU_CACHE_SIZE_512);
RNA_def_property_ui_text(prop, "GPU Cache Size", "Texture cache size for DPIX algorithm");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "depth_width_influence", PROP_FLOAT, PROP_PERCENTAGE);
RNA_def_property_float_default(prop, 0.3f);
RNA_def_property_ui_text(prop, "Width Influence", "Use camera distance to control line width.");
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.05, 2);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "depth_width_curve", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 0.3f);
RNA_def_property_ui_text(prop, "Width Curve", "Width curve");
RNA_def_property_ui_range(prop, -5.0f, 0.90f, 0.1, 1);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "depth_alpha_influence", PROP_FLOAT, PROP_PERCENTAGE);
RNA_def_property_float_default(prop, 0.3f);
RNA_def_property_ui_text(prop, "Alpha Influence", "Use camera distance to control line alpha.");
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.05, 2);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "depth_alpha_curve", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 0.3f);
RNA_def_property_ui_text(prop, "Alpha Curve", "alpha curve");
RNA_def_property_ui_range(prop, -5.0f, 0.90f, 0.1, 1);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "taper_left_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 20.0f);
RNA_def_property_ui_text(prop, "Left Distance", "Left side taper distance");
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 0.1, 2);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "taper_right_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 20.0f);
RNA_def_property_ui_text(prop, "Right Distance", "Right side taper distance");
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 0.1, 2);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "taper_left_strength", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Left Strength", "Left side taper strength");
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 2);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "taper_right_strength", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Right Strength", "Right side taper strength");
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 2);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "use_same_taper", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_default(prop, 0);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_SAME_TAPER);
RNA_def_property_ui_text(prop, "Same Taper", "Same/Different taper value");
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "line_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Line Color", "Drawing lines using this color");
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 2);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "crease_threshold", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_ui_text(prop, "Crease Threshold", "cosine value of face angle");
RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.01, 2);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "crease_fade_threshold", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_ui_text(prop, "Crease Fade", "cosine value of face angle");
RNA_def_property_ui_range(prop, -1.0f, 1.0f, 0.01, 2);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_SCENE, NULL);
prop = RNA_def_property(srna, "use_intersections", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_USE_INTERSECTIONS);
RNA_def_property_boolean_default(prop, 1);
RNA_def_property_ui_text(prop, "Calculate Intersections", "Calculate Intersections or not");
prop = RNA_def_property(srna, "enable_chaining", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", LANPR_USE_CHAINING);
RNA_def_property_boolean_default(prop, 1);
RNA_def_property_ui_text(prop, "Enable Chaining", "Chain Feature Lines After Occlusion Test");
prop = RNA_def_property(srna, "enable_chain_connection", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_default(prop, 1);
RNA_def_property_ui_text(prop,
"Enable Chain Connection",
"Connect short chains in the image space into one longer chain");
/* should be read-only */
prop = RNA_def_property(srna, "shader_error", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_default(prop, 0);
RNA_def_property_boolean_funcs(prop, "rna_lanpr_shader_error_get", "");
RNA_def_property_ui_text(
prop, "DPIX Shader Error", "Can't compile DPIX transform shader on your GPU.");
prop = RNA_def_property(srna, "chaining_geometry_threshold", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 0.1f);
RNA_def_property_ui_text(prop,
"Geometry Threshold",
"Segments where their geometric distance between them lower than this "
"will be chained together");
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 3);
RNA_def_property_range(prop, 0.0f, 1.0f);
prop = RNA_def_property(srna, "chaining_image_threshold", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, 0.01f);
RNA_def_property_ui_text(
prop,
"Image Threshold",
"Segments where their image distance between them lower than this will be chained together");
RNA_def_property_ui_range(prop, 0.0f, 0.3f, 0.001, 4);
RNA_def_property_range(prop, 0.0f, 0.3f);
/* here's the collection stuff.... */
prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "line_layers", NULL);
RNA_def_property_struct_type(prop, "LANPR_LineLayer");
RNA_def_property_ui_text(prop, "Line Layers", "LANPR Line Layers");
/* this part I refered to gpencil's and freestyle's and it seems that there's no difference */
RNA_def_property_srna(prop, "LineLayers");
srna = RNA_def_struct(brna, "LineLayers", NULL);
RNA_def_struct_sdna(srna, "SceneLANPR");
RNA_def_struct_ui_text(srna, "LANPR Line Layers", "");
prop = RNA_def_property(srna, "active_layer", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "LANPR_LineLayer");
RNA_def_property_pointer_funcs(
prop, "rna_lanpr_active_line_layer_get", "rna_lanpr_active_line_layer_set", NULL, NULL);
RNA_def_property_ui_text(prop, "Active Line Layer", "Active line layer being displayed");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
prop = RNA_def_property(srna, "active_layer_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop,
"rna_lanpr_active_line_layer_index_get",
"rna_lanpr_active_line_layer_index_set",
"rna_lanpr_active_line_layer_index_range");
RNA_def_property_ui_text(prop, "Active Line Layer Index", "Index of active line layer slot");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
}
void RNA_def_scene(BlenderRNA *brna)
{
StructRNA *srna;
@@ -7551,6 +7829,11 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "SceneEEVEE");
RNA_def_property_ui_text(prop, "EEVEE", "EEVEE settings for the scene");
/* LANPR */
prop = RNA_def_property(srna, "lanpr", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "SceneLANPR");
RNA_def_property_ui_text(prop, "LANPR", "LANPR settings for the scene");
/* Nestled Data */
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
@@ -7568,6 +7851,7 @@ void RNA_def_scene(BlenderRNA *brna)
rna_def_display_safe_areas(brna);
rna_def_scene_display(brna);
rna_def_scene_eevee(brna);
rna_def_scene_lanpr(brna);
RNA_define_animate_sdna(true);
/* *** Animated *** */
rna_def_scene_render_data(brna);

View File

@@ -384,26 +384,24 @@ const EnumPropertyItem rna_enum_clip_editor_mode_items[] = {
* but helps for context-less access (e.g. doc, i18n...). */
static const EnumPropertyItem buttons_context_items[] = {
{BCONTEXT_TOOL, "TOOL", ICON_TOOL_SETTINGS, "Tool", "Active Tool and Workspace settings"},
{BCONTEXT_SCENE, "SCENE", ICON_SCENE_DATA, "Scene", "Scene Properties"},
{BCONTEXT_RENDER, "RENDER", ICON_SCENE, "Render", "Render Properties"},
{BCONTEXT_OUTPUT, "OUTPUT", ICON_OUTPUT, "Output", "Output Properties"},
{BCONTEXT_VIEW_LAYER, "VIEW_LAYER", ICON_RENDER_RESULT, "View Layer", "View Layer Properties"},
{BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World Properties"},
{BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object Properties"},
{BCONTEXT_CONSTRAINT,
"CONSTRAINT",
ICON_CONSTRAINT,
"Constraints",
"Object Constraint Properties"},
{BCONTEXT_MODIFIER, "MODIFIER", ICON_MODIFIER, "Modifiers", "Modifier Properties"},
{BCONTEXT_DATA, "DATA", ICON_NONE, "Data", "Object Data Properties"},
{BCONTEXT_BONE, "BONE", ICON_BONE_DATA, "Bone", "Bone Properties"},
{BCONTEXT_SCENE, "SCENE", ICON_SCENE_DATA, "Scene", "Scene"},
{BCONTEXT_RENDER, "RENDER", ICON_SCENE, "Render", "Render"},
{BCONTEXT_OUTPUT, "OUTPUT", ICON_OUTPUT, "Output", "Output"},
{BCONTEXT_VIEW_LAYER, "VIEW_LAYER", ICON_RENDER_RESULT, "View Layer", "View Layer"},
{BCONTEXT_WORLD, "WORLD", ICON_WORLD, "World", "World"},
{BCONTEXT_COLLECTION, "COLLECTION", ICON_GROUP, "Collection", "Collection"},
{BCONTEXT_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Object"},
{BCONTEXT_CONSTRAINT, "CONSTRAINT", ICON_CONSTRAINT, "Constraints", "Object Constraints"},
{BCONTEXT_MODIFIER, "MODIFIER", ICON_MODIFIER, "Modifiers", "Modifiers"},
{BCONTEXT_DATA, "DATA", ICON_NONE, "Data", "Object Data"},
{BCONTEXT_BONE, "BONE", ICON_BONE_DATA, "Bone", "Bone"},
{BCONTEXT_BONE_CONSTRAINT,
"BONE_CONSTRAINT",
ICON_CONSTRAINT_BONE,
"Bone Constraints",
"Bone Constraint Properties"},
{BCONTEXT_MATERIAL, "MATERIAL", ICON_MATERIAL, "Material", "Material Properties"},
{BCONTEXT_LANPR, "LANPR", ICON_SHADING_RENDERED, "LANPR", "LANPR Data"},
{BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture Properties"},
{BCONTEXT_PARTICLE, "PARTICLES", ICON_PARTICLES, "Particles", "Particle Properties"},
{BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics Properties"},
@@ -1655,6 +1653,14 @@ static const EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSE
RNA_enum_item_add_separator(&item, &totitem);
}
if (sbuts->pathflag & (1 << BCONTEXT_COLLECTION)) {
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_COLLECTION);
}
if (totitem) {
RNA_enum_item_add_separator(&item, &totitem);
}
if (sbuts->pathflag & (1 << BCONTEXT_OBJECT)) {
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_OBJECT);
}
@@ -1696,6 +1702,10 @@ static const EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSE
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_MATERIAL);
}
if (sbuts->pathflag & (1 << BCONTEXT_LANPR)) {
RNA_enum_items_add_value(&item, &totitem, buttons_context_items, BCONTEXT_LANPR);
}
if (totitem) {
RNA_enum_item_add_separator(&item, &totitem);
}