1
1

Compare commits

...

68 Commits

Author SHA1 Message Date
bfbf0bb7f7 Merge remote-tracking branch 'origin/master' into temp-lanpr-review
# Conflicts:
#	release/datafiles/locale
#	release/scripts/addons
2020-06-04 18:57:28 +08:00
3b52dfe549 Merge remote-tracking branch 'origin/master' into temp-lanpr-review
# Conflicts:
#	release/datafiles/locale
#	release/scripts/addons
#	source/blender/blenkernel/intern/lib_query.c
2020-05-30 16:34:11 +08:00
cd54abd2c1 Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2020-05-16 23:08:40 +08:00
f7770cb97b Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2020-02-01 10:35:40 +08:00
b47883a990 Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2020-02-01 10:25:32 +08:00
b5abbc40a0 Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2019-12-13 13:42:27 +08:00
c2c6447229 Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2019-12-10 22:13:06 +08:00
191b890883 Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2019-12-09 14:04:57 +08:00
f83f168c92 LANPR: Typo "identity". 2019-12-04 20:47:39 +08:00
7804323e33 LANPR: CPU mode win_mat fix attempt. 2019-12-04 20:15:45 +08:00
89e01395a8 Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2019-12-04 20:15:33 +08:00
781c9f5206 LANPR: Grease pencil mode init code fix. 2019-12-03 20:23:43 +08:00
6f7f80775d LANPR: Warning messages for gpu cache overflow. 2019-12-03 13:48:48 +08:00
8b041081c3 LANPR: chaining vertex count fixed. 2019-12-03 13:44:05 +08:00
7f81bb4931 Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2019-12-03 13:30:50 +08:00
2243de9a90 LANPR: Don't use background intersection calculation for GPU mode. 2019-11-29 23:17:00 +08:00
798e93b634 Cleanup: Missing bracket. 2019-11-28 18:44:32 +08:00
ca43179932 LANPR: Camera shift value assign. 2019-11-28 14:50:46 +08:00
6967d60c4b Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2019-11-28 14:50:40 +08:00
1c2b864155 LANPR: Remove debug print in triangle clipping 2019-11-28 13:29:49 +08:00
cb47cc14cd LANPR: Removed camera references in RenderBuffer. Safe for thread ops. 2019-11-28 13:27:13 +08:00
352eb65a57 LANPR: Locking parent thread when loading scenes into lanpr. 2019-11-28 12:38:33 +08:00
8eb44bfb81 LANPR: Renderbuffer creation changed to re-init. 2019-11-28 11:48:59 +08:00
acd8fae2d8 LANPR: Const qualifiers for some of the functions 2019-11-28 11:39:21 +08:00
Julian Eisel
541fb672ec Always write LANPR data if set
Gerneral rule of thumb: Don't delete user data without permission.
Data-blocks are a whole different and difficult story. Users may have
disabled just for a render, reloading the file shouldn't make their
settings go lost.
2019-11-27 17:19:41 +01:00
Julian Eisel
6ccd672fee Fix crash on disabling collection LANPR
Also:
* Avoid duplicated copy code (copy code performed already and wouldn't actually run)
* Cleanup freeing
2019-11-27 17:10:27 +01:00
Julian Eisel
cf38c4d49f Fix NULL-ptr mem-copy 2019-11-27 16:03:21 +01:00
12bf6ee36c LANPR: Build option CMakeLists add LANPR. 2019-11-27 22:51:35 +08:00
Julian Eisel
4227b81826 Fix wrong dereferences 2019-11-27 15:38:31 +01:00
Julian Eisel
cf623d8e7b Address some minor warnings 2019-11-27 15:36:36 +01:00
Julian Eisel
692f20604c Run clang-format on all changed files 2019-11-27 15:35:17 +01:00
9f35ef219f LANPR: Collection visibility flags should be visible in all engines. 2019-11-27 22:21:31 +08:00
aa4ff9e5d3 LANPR: Fixing CollectionLANRP file r/w. 2019-11-27 22:09:35 +08:00
1e801df3ef LANPR: Use pointer to save collection LANPR config. 2019-11-27 21:10:38 +08:00
f8384c0d2d Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2019-11-27 19:41:17 +08:00
5aa70ac589 Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2019-11-27 10:18:09 +08:00
c2fbf7668d LANPR: Remove LANPR_LineLayerComponent struct as it's no more used. 2019-11-24 22:02:29 +08:00
365faddd79 LANPR: Fix chain point count error. 2019-11-24 20:55:16 +08:00
c508138e95 LANPR: CMake option in the RNA. 2019-11-24 20:48:47 +08:00
0476090983 Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2019-11-24 20:43:53 +08:00
7da7d97aff Cleanup: LANPR compilder flags, missing registers, and some other fixes. 2019-11-22 19:17:54 +08:00
9b27248c64 LANPR: Some comments on the occlusion function 2019-11-22 18:27:03 +08:00
b95f15862e Cleanup: Get rid of real/tmat/tnsvector stuff in LANPR internal code. 2019-11-22 18:10:20 +08:00
232e13d4cb Cleanup: variable capitalizations. 2019-11-22 18:02:25 +08:00
96d470c0e2 LANPR: Versioning code move to the latest. 2019-11-22 17:37:15 +08:00
7e577c4857 Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2019-11-22 17:29:36 +08:00
66aa0a2181 LANPR: dpix_shader_error type and rna definition fixes. 2019-11-20 21:32:54 +08:00
ba5c4414b0 Cleanup: Function logic and unused variables. 2019-11-20 21:30:13 +08:00
ec9cdd6e51 LANPR: Fix multisample texture functions and engine registering functions. 2019-11-20 20:56:56 +08:00
b3d226ffdb CLeanup: fix property context item descriptions. 2019-11-20 20:25:57 +08:00
bdd96da5eb Merge remote-tracking branch 'origin/master' into temp-lanpr-review 2019-11-20 20:20:38 +08:00
43419e4c32 LANPR: Removed unused DRW_texture_create_2d_multisample function. 2019-11-20 17:20:42 +08:00
dc9f9faff7 Merge remote-tracking branch 'origin/master' into arcpatch-D5442 2019-11-20 16:11:51 +08:00
f2f2f5f6c7 Cleanup: Code style and dead code stuff. 2019-11-20 16:11:10 +08:00
9c7f536251 LANPR: Fix cmake option in render to allow lanpr callback for gp updates. 2019-11-20 16:02:29 +08:00
a921c5f239 Cleanup: dead codes and commentaries. 2019-11-20 15:44:33 +08:00
bb38766ba6 LANPR: Clipping topology data error fixed.
Also cleaned up some dead code inside.
2019-11-20 15:01:04 +08:00
45eb04adc8 Merge remote-tracking branch 'origin/master' into arcpatch-D5442 2019-11-20 13:21:35 +08:00
ee7785510b Cleanup: TNS_THREAD_LINE_COUNT commenting. 2019-11-18 22:14:32 +08:00
db12505f51 Cleanup: Fix compiler warnings. 2019-11-18 22:08:48 +08:00
314439e652 Cleanup: Remove snake mode structures in ED_lanpr.h 2019-11-18 21:48:34 +08:00
9a9fa3a206 Merge remote-tracking branch 'origin/master' into arcpatch-D5442 2019-11-18 21:46:25 +08:00
c3799f1c31 LANPR: Fix various code issues. 2019-11-17 20:29:17 +08:00
ef1cd34e8d Merge remote-tracking branch 'origin/master' into arcpatch-D5442 2019-11-17 20:10:38 +08:00
dba890910d LANPR: Still enable auto update checkbox when no active camera is persent. 2019-11-15 20:37:20 +08:00
3bcdf06a54 Merge branch 'master' into arcpatch-D5442 2019-11-15 20:30:19 +08:00
1924e96f7d LANPR: Fix asset errors and material marking errors. 2019-11-15 20:06:36 +08:00
YimingWu
e9df7caf19 LANPR line rendering (summer of code)
LANPR Patch

This is the patch for soc-2019-npr branch. Now modified as containing only LANPR changes

This patch **doesn't include** the following:

- GPencil modifiers.
- Smooth contour modifier.
- SVG.
- Affected UI scripts.
- Freestyle changes.

Those above will be submitted in other diffs.

Differential Revision: https://developer.blender.org/D5442
2019-11-15 11:46:33 +08:00
81 changed files with 12224 additions and 63 deletions

View File

@@ -322,6 +322,9 @@ mark_as_advanced(WITH_SYSTEM_GLOG)
# Freestyle
option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON)
# LANPR
option(WITH_LANPR "Enable LANPR (more advanced edges rendering)" ON)
# New object types
option(WITH_NEW_OBJECT_TYPES "Enable new hair and pointcloud objects (use for development only, don't save in files)" OFF)
mark_as_advanced(WITH_NEW_OBJECT_TYPES)
@@ -1726,6 +1729,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_INPUT_NDOF)
info_cfg_option(WITH_CYCLES)
info_cfg_option(WITH_FREESTYLE)
info_cfg_option(WITH_LANPR)
info_cfg_option(WITH_OPENCOLORIO)
info_cfg_option(WITH_XR_OPENXR)
info_cfg_option(WITH_OPENIMAGEDENOISE)

View File

@@ -18,6 +18,7 @@ set(WITH_LIBMV ON CACHE BOOL "" FORCE)
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE)
set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
set(WITH_LANPR ON CACHE BOOL "" FORCE)
set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)

View File

@@ -23,6 +23,7 @@ set(WITH_LIBMV OFF CACHE BOOL "" FORCE)
set(WITH_LLVM OFF CACHE BOOL "" FORCE)
set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE)
set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE)
set(WITH_LANPR OFF CACHE BOOL "" FORCE)
set(WITH_IK_SOLVER OFF CACHE BOOL "" FORCE)
set(WITH_IK_ITASC OFF CACHE BOOL "" FORCE)
set(WITH_IMAGE_CINEON OFF CACHE BOOL "" FORCE)

View File

@@ -19,6 +19,7 @@ set(WITH_LIBMV ON CACHE BOOL "" FORCE)
set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE)
set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE)
set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
set(WITH_LANPR ON CACHE BOOL "" FORCE)
set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE)
set(WITH_IK_ITASC ON CACHE BOOL "" FORCE)
set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE)

View File

@@ -67,6 +67,7 @@ _modules = [
"properties_scene",
"properties_texture",
"properties_world",
"properties_collection",
# Generic Space Modules
#
@@ -103,6 +104,9 @@ import bpy
if bpy.app.build_options.freestyle:
_modules.append("properties_freestyle")
if bpy.app.build_options.lanpr:
_modules.append("properties_lanpr")
__import__(name=__name__, fromlist=_modules)
_namespace = globals()
_modules_loaded = [_namespace[name] for name in _modules]

View File

@@ -0,0 +1,125 @@
# ##### 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
class CollectionButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "collection"
COMPAT_ENGINES = { 'BLENDER_LANPR' }
@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 line_type.use and expand:
col.prop_search(line_type, "layer", search_from, "layers", icon='GREASEPENCIL')
col.prop_search(line_type, "material", search_from, "materials", icon='SHADING_TEXTURE')
class COLLECTION_PT_collection_flags(CollectionButtonsPanel, Panel):
bl_label = "Collection Flags"
COMPAT_ENGINES = { 'BLENDER_LANPR', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH', 'CYCLES' }
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")
class COLLECTION_PT_lanpr_collection(CollectionButtonsPanel, Panel):
bl_label = "Collection LANPR"
COMPAT_ENGINES = { 'BLENDER_LANPR' }
@classmethod
def poll(cls, context):
return context.scene.render.engine == 'BLENDER_LANPR' or context.scene.lanpr.enabled
def draw_header(self, context):
layout = self.layout
collection = context.collection
layout.prop(collection, "configure_lanpr", text="")
def draw(self,context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
collection = context.collection
if not collection.configure_lanpr:
return
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:
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

@@ -39,7 +39,7 @@ class CAMERA_PT_presets(PresetPanel, Panel):
preset_subdir = "camera"
preset_operator = "script.execute_preset"
preset_add_operator = "camera.preset_add"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
class SAFE_AREAS_PT_presets(PresetPanel, Panel):
@@ -47,13 +47,13 @@ class SAFE_AREAS_PT_presets(PresetPanel, Panel):
preset_subdir = "safe_areas"
preset_operator = "script.execute_preset"
preset_add_operator = "safe_areas.preset_add"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
class DATA_PT_context_camera(CameraButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
@@ -70,7 +70,7 @@ class DATA_PT_context_camera(CameraButtonsPanel, Panel):
class DATA_PT_lens(CameraButtonsPanel, Panel):
bl_label = "Lens"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
@@ -111,7 +111,7 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
sub = col.column(align=True)
sub.prop(ccam, "longitude_min", text="Longitude Min")
sub.prop(ccam, "longitude_max", text="Max")
elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}:
elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}:
if cam.lens_unit == 'MILLIMETERS':
col.prop(cam, "lens")
elif cam.lens_unit == 'FOV':
@@ -133,7 +133,7 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
bl_label = "Stereoscopy"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
@@ -182,7 +182,7 @@ class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
class DATA_PT_camera(CameraButtonsPanel, Panel):
bl_label = "Camera"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
def draw_header_preset(self, _context):
CAMERA_PT_presets.draw_panel_header(self.layout)
@@ -212,7 +212,7 @@ class DATA_PT_camera(CameraButtonsPanel, Panel):
class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
bl_label = "Depth of Field"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
def draw_header(self, context):
cam = context.camera
@@ -237,7 +237,7 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
class DATA_PT_camera_dof_aperture(CameraButtonsPanel, Panel):
bl_label = "Aperture"
bl_parent_id = "DATA_PT_camera_dof"
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
@@ -261,7 +261,7 @@ class DATA_PT_camera_dof_aperture(CameraButtonsPanel, Panel):
class DATA_PT_camera_background_image(CameraButtonsPanel, Panel):
bl_label = "Background Images"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
def draw_header(self, context):
cam = context.camera
@@ -368,7 +368,7 @@ class DATA_PT_camera_background_image(CameraButtonsPanel, Panel):
class DATA_PT_camera_display(CameraButtonsPanel, Panel):
bl_label = "Viewport Display"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
@@ -391,7 +391,7 @@ class DATA_PT_camera_display_composition_guides(CameraButtonsPanel, Panel):
bl_label = "Composition Guides"
bl_parent_id = "DATA_PT_camera_display"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
@@ -419,7 +419,7 @@ class DATA_PT_camera_display_passepartout(CameraButtonsPanel, Panel):
bl_label = "Passepartout"
bl_parent_id = "DATA_PT_camera_display"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
def draw_header(self, context):
cam = context.camera
@@ -439,7 +439,7 @@ class DATA_PT_camera_display_passepartout(CameraButtonsPanel, Panel):
class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
bl_label = "Safe Areas"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
def draw_header(self, context):
cam = context.camera
@@ -469,7 +469,7 @@ class DATA_PT_camera_safe_areas_center_cut(CameraButtonsPanel, Panel):
bl_label = "Center-Cut Safe Areas"
bl_parent_id = "DATA_PT_camera_safe_areas"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
def draw_header(self, context):
cam = context.camera
@@ -493,7 +493,7 @@ class DATA_PT_camera_safe_areas_center_cut(CameraButtonsPanel, Panel):
class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
_context_path = "object.data"
_property_type = bpy.types.Camera

View File

@@ -0,0 +1,100 @@
# ##### 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
class LanprButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "lanpr"
COMPAT_ENGINES = { 'BLENDER_LANPR' }
def lanpr_make_line_type_entry(col, line_type, text_disp, expand, search_from):
col.prop(line_type, "use", text=text_disp)
if line_type.use and expand:
col.prop_search(line_type, "layer", search_from, "layers", icon='GREASEPENCIL')
col.prop_search(line_type, "material", search_from, "materials", icon='SHADING_TEXTURE')
class OBJECT_PT_lanpr_settings(LanprButtonsPanel, Panel):
bl_label = "LANPR settings"
COMPAT_ENGINES = { 'BLENDER_LANPR' }
@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"
COMPAT_ENGINES = { 'BLENDER_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
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

@@ -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,
)
from bl_ui.properties_grease_pencil_common import GreasePencilSimplifyPanel
@@ -66,7 +69,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
@@ -99,7 +102,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):
@@ -463,7 +466,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):
@@ -686,6 +689,308 @@ class RENDER_PT_simplify_greasepencil(RenderButtonsPanel, Panel, GreasePencilSim
bl_options = {'DEFAULT_CLOSED'}
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'}
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)
col.prop(lanpr,'auto_update', text='Auto Update')
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":
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_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_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 scene.render.engine!='BLENDER_LANPR' or 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
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")
else:
layout.prop(lanpr, "chaining_geometry_threshold")
layout.prop(lanpr, "chaining_image_threshold")
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'}
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,
@@ -717,6 +1022,14 @@ 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_software_chain_styles,
RENDER_PT_lanpr_options,
LANPR_UL_linesets,
)
if __name__ == "__main__": # only for live edit.

View File

@@ -37,7 +37,7 @@ class WorldButtonsPanel:
class WORLD_PT_context_world(WorldButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
@classmethod
def poll(cls, context):
@@ -83,7 +83,7 @@ class EEVEE_WORLD_PT_mist(WorldButtonsPanel, Panel):
class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_LANPR', 'BLENDER_WORKBENCH'}
_context_path = "world"
_property_type = bpy.types.World

View File

@@ -3775,9 +3775,9 @@ 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:
col.separator()
scene = context.scene
if render.use_freestyle or scene.lanpr.enabled or scene.render.engine=="BLENDER_LANPR":
layout.separator()
col.operator("mesh.mark_freestyle_edge").clear = False
col.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
@@ -3972,9 +3972,8 @@ class VIEW3D_MT_edit_mesh_edges_data(Menu):
props.use_verts = True
props.clear = True
if render.use_freestyle:
if render.use_freestyle or context.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
@@ -3982,7 +3981,7 @@ class VIEW3D_MT_edit_mesh_edges_data(Menu):
class VIEW3D_MT_edit_mesh_edges(Menu):
bl_label = "Edge"
def draw(self, _context):
def draw(self, context):
layout = self.layout
with_freestyle = bpy.app.build_options.freestyle
@@ -4030,9 +4029,9 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
props.use_verts = True
props.clear = True
if with_freestyle:
scene = context.scene
if with_freestyle or scene.lanpr.enabled or scene.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
@@ -4040,7 +4039,7 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
class VIEW3D_MT_edit_mesh_faces_data(Menu):
bl_label = "Face Data"
def draw(self, _context):
def draw(self, context):
layout = self.layout
with_freestyle = bpy.app.build_options.freestyle
@@ -4055,9 +4054,9 @@ class VIEW3D_MT_edit_mesh_faces_data(Menu):
layout.operator("mesh.uvs_rotate")
layout.operator("mesh.uvs_reverse")
layout.separator()
if with_freestyle:
scene = context.scene
if with_freestyle or scene.lanpr.enabled or scene.render.engine=="BLENDER_LANPR":
layout.separator()
layout.operator("mesh.mark_freestyle_face").clear = False
layout.operator("mesh.mark_freestyle_face", text="Clear Freestyle Face").clear = True

View File

@@ -195,6 +195,10 @@ void BKE_gpencil_layer_mask_sort(struct bGPdata *gpd, struct bGPDlayer *gpl);
void BKE_gpencil_layer_mask_sort_all(struct bGPdata *gpd);
void BKE_gpencil_layer_frames_sort(struct bGPDlayer *gpl, bool *r_has_duplicate_frames);
struct bGPDlayer *BKE_gpencil_layer_get_by_name(struct bGPdata *gpd,
char *name,
int first_if_not_found);
/* Brush */
struct Material *BKE_gpencil_brush_material_get(struct Brush *brush);
void BKE_gpencil_brush_material_set(struct Brush *brush, struct Material *material);
@@ -214,6 +218,7 @@ struct Material *BKE_gpencil_object_material_new(struct Main *bmain,
int *r_index);
int BKE_gpencil_object_material_index_get(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_from_brush_get(struct Object *ob,
struct Brush *brush);

View File

@@ -257,6 +257,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

@@ -632,6 +632,10 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
endif()
if(WITH_ALEMBIC)
list(APPEND INC
../io/alembic

View File

@@ -244,6 +244,9 @@ void BKE_collection_add_from_object(Main *bmain,
void BKE_collection_free(Collection *collection)
{
collection_free_data(&collection->id);
/* Remove LANPR configurations */
MEM_SAFE_FREE(collection->lanpr);
}
/**

View File

@@ -1176,6 +1176,31 @@ bGPDlayer *BKE_gpencil_layer_active_get(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_active_set(bGPdata *gpd, bGPDlayer *active)
{
@@ -1739,6 +1764,21 @@ int BKE_gpencil_object_material_index_get(Object *ob, Material *ma)
return -1;
}
int BKE_gpencil_object_material_get_index_name(Object *ob, char *name)
{
short *totcol = BKE_object_material_len_p(ob);
Material *read_ma = NULL;
for (short i = 0; i < *totcol; i++) {
read_ma = BKE_object_material_get(ob, i + 1);
/* Material names are like "MAMaterial.001" */
if (STREQ(name, &read_ma->id.name[2])) {
return i;
}
}
return -1;
}
/* Create a default palette */
void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
{

View File

@@ -101,6 +101,9 @@
#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_query.h"
/* lanpr scene cache free function needs this. */
#include "DRW_engine.h"
#include "RE_engine.h"
#include "engines/eevee/eevee_lightcache.h"
@@ -591,6 +594,7 @@ IDTypeInfo IDType_ID_SCE = {
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)
@@ -740,6 +744,144 @@ 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;
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));
new_ll->next = new_ll->prev = NULL;
new_ll->batch = NULL;
BLI_addtail(&to->lanpr.line_layers, new_ll);
}
/* render_buffer now only accessible from lanpr_share */
}
/**
* Only copy internal data of Scene ID from source
* to already allocated/initialized destination.
* You probably never want to use that directly,
* use #BKE_id_copy or #BKE_id_copy_ex for typical needs.
*
* WARNING! This function will not handle ID user count!
*
* \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
*/
void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, const int flag)
{
/* We never handle usercount here for own data. */
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
/* We always need allocation of our private ID data. */
const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE;
sce_dst->ed = NULL;
sce_dst->depsgraph_hash = NULL;
sce_dst->fps_info = NULL;
/* Master Collection */
if (sce_src->master_collection) {
BKE_id_copy_ex(bmain,
(ID *)sce_src->master_collection,
(ID **)&sce_dst->master_collection,
flag_private_id_data);
}
/* View Layers */
BLI_duplicatelist(&sce_dst->view_layers, &sce_src->view_layers);
for (ViewLayer *view_layer_src = sce_src->view_layers.first,
*view_layer_dst = sce_dst->view_layers.first;
view_layer_src;
view_layer_src = view_layer_src->next, view_layer_dst = view_layer_dst->next) {
BKE_view_layer_copy_data(sce_dst, sce_src, view_layer_dst, view_layer_src, flag_subdata);
}
BLI_duplicatelist(&(sce_dst->markers), &(sce_src->markers));
BLI_duplicatelist(&(sce_dst->transform_spaces), &(sce_src->transform_spaces));
BLI_duplicatelist(&(sce_dst->r.views), &(sce_src->r.views));
BKE_keyingsets_copy(&(sce_dst->keyingsets), &(sce_src->keyingsets));
if (sce_src->nodetree) {
BKE_id_copy_ex(
bmain, (ID *)sce_src->nodetree, (ID **)&sce_dst->nodetree, flag_private_id_data);
BKE_libblock_relink_ex(bmain,
sce_dst->nodetree,
(void *)(&sce_src->id),
&sce_dst->id,
ID_REMAP_SKIP_NEVER_NULL_USAGE);
}
if (sce_src->rigidbody_world) {
sce_dst->rigidbody_world = BKE_rigidbody_world_copy(sce_src->rigidbody_world, flag_subdata);
}
/* copy color management settings */
BKE_color_managed_display_settings_copy(&sce_dst->display_settings, &sce_src->display_settings);
BKE_color_managed_view_settings_copy(&sce_dst->view_settings, &sce_src->view_settings);
BKE_color_managed_colorspace_settings_copy(&sce_dst->sequencer_colorspace_settings,
&sce_src->sequencer_colorspace_settings);
BKE_color_managed_display_settings_copy(&sce_dst->r.im_format.display_settings,
&sce_src->r.im_format.display_settings);
BKE_color_managed_view_settings_copy(&sce_dst->r.im_format.view_settings,
&sce_src->r.im_format.view_settings);
BKE_color_managed_display_settings_copy(&sce_dst->r.bake.im_format.display_settings,
&sce_src->r.bake.im_format.display_settings);
BKE_color_managed_view_settings_copy(&sce_dst->r.bake.im_format.view_settings,
&sce_src->r.bake.im_format.view_settings);
BKE_curvemapping_copy_data(&sce_dst->r.mblur_shutter_curve, &sce_src->r.mblur_shutter_curve);
/* tool settings */
sce_dst->toolsettings = BKE_toolsettings_copy(sce_dst->toolsettings, flag_subdata);
/* make a private copy of the avicodecdata */
if (sce_src->r.avicodecdata) {
sce_dst->r.avicodecdata = MEM_dupallocN(sce_src->r.avicodecdata);
sce_dst->r.avicodecdata->lpFormat = MEM_dupallocN(sce_dst->r.avicodecdata->lpFormat);
sce_dst->r.avicodecdata->lpParms = MEM_dupallocN(sce_dst->r.avicodecdata->lpParms);
}
if (sce_src->r.ffcodecdata.properties) {
/* intentionally check sce_dst not sce_src. */ /* XXX ??? comment outdated... */
sce_dst->r.ffcodecdata.properties = IDP_CopyProperty_ex(sce_src->r.ffcodecdata.properties,
flag_subdata);
}
if (sce_src->display.shading.prop) {
sce_dst->display.shading.prop = IDP_CopyProperty(sce_src->display.shading.prop);
}
BKE_sound_reset_scene_runtime(sce_dst);
/* Copy sequencer, this is local data! */
if (sce_src->ed) {
sce_dst->ed = MEM_callocN(sizeof(*sce_dst->ed), __func__);
sce_dst->ed->seqbasep = &sce_dst->ed->seqbase;
BKE_sequence_base_dupli_recursive(sce_src,
sce_dst,
&sce_dst->ed->seqbase,
&sce_src->ed->seqbase,
SEQ_DUPE_ALL,
flag_subdata);
}
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
BKE_previewimg_id_copy(&sce_dst->id, &sce_src->id);
}
else {
sce_dst->preview = NULL;
}
BKE_scene_copy_data_eevee(sce_dst, sce_src);
}
void BKE_scene_copy_data_eevee(Scene *sce_dst, const Scene *sce_src)
{
/* Copy eevee data between scenes. */
@@ -747,6 +889,10 @@ void BKE_scene_copy_data_eevee(Scene *sce_dst, const Scene *sce_src)
sce_dst->eevee.light_cache_data = 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)
@@ -873,6 +1019,303 @@ void BKE_scene_groups_relink(Scene *sce)
}
}
void BKE_scene_make_local(Main *bmain, Scene *sce, const bool lib_local)
{
/* For now should work, may need more work though to support all possible corner cases
* (also scene_copy probably needs some love). */
BKE_lib_id_make_local(bmain, &sce->id, true, lib_local);
}
void BKE_lanpr_free_everything(Scene *s)
{
SceneLANPR *lanpr = &s->lanpr;
LANPR_LineLayer *ll;
#ifdef WITH_LANPR
DRW_scene_lanpr_freecache(s);
#endif
while ((ll = BLI_pophead(&lanpr->line_layers)) != NULL) {
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)
{
BKE_animdata_free((ID *)sce, false);
BKE_sequencer_editing_free(sce, do_id_user);
BKE_keyingsets_free(&sce->keyingsets);
/* is no lib link block, but scene extension */
if (sce->nodetree) {
ntreeFreeEmbeddedTree(sce->nodetree);
MEM_freeN(sce->nodetree);
sce->nodetree = NULL;
}
if (sce->rigidbody_world) {
BKE_rigidbody_free_world(sce);
}
if (sce->r.avicodecdata) {
free_avicodecdata(sce->r.avicodecdata);
MEM_freeN(sce->r.avicodecdata);
sce->r.avicodecdata = NULL;
}
if (sce->r.ffcodecdata.properties) {
IDP_FreeProperty(sce->r.ffcodecdata.properties);
sce->r.ffcodecdata.properties = NULL;
}
BLI_freelistN(&sce->markers);
BLI_freelistN(&sce->transform_spaces);
BLI_freelistN(&sce->r.views);
BKE_toolsettings_free(sce->toolsettings);
sce->toolsettings = NULL;
BKE_scene_free_depsgraph_hash(sce);
MEM_SAFE_FREE(sce->fps_info);
BKE_sound_destroy_scene(sce);
BKE_color_managed_view_settings_free(&sce->view_settings);
BKE_previewimg_free(&sce->preview);
BKE_curvemapping_free_data(&sce->r.mblur_shutter_curve);
for (ViewLayer *view_layer = sce->view_layers.first, *view_layer_next; view_layer;
view_layer = view_layer_next) {
view_layer_next = view_layer->next;
BLI_remlink(&sce->view_layers, view_layer);
BKE_view_layer_free_ex(view_layer, do_id_user);
}
/* Master Collection */
// TODO: what to do with do_id_user? it's also true when just
// closing the file which seems wrong? should decrement users
// for objects directly in the master collection? then other
// collections in the scene need to do it too?
if (sce->master_collection) {
BKE_collection_free(sce->master_collection);
MEM_freeN(sce->master_collection);
sce->master_collection = NULL;
}
if (sce->eevee.light_cache) {
EEVEE_lightcache_free(sce->eevee.light_cache);
sce->eevee.light_cache = NULL;
}
if (sce->display.shading.prop) {
IDP_FreeProperty(sce->display.shading.prop);
sce->display.shading.prop = NULL;
}
/* Copied and generated LANPR data. */
BKE_lanpr_free_everything(sce);
/* These are freed on doversion. */
BLI_assert(sce->layer_properties == NULL);
}
void BKE_scene_free(Scene *sce)
{
BKE_scene_free_ex(sce, true);
}
/**
* \note Use DNA_scene_defaults.h where possible.
*/
void BKE_scene_init(Scene *sce)
{
const char *colorspace_name;
SceneRenderView *srv;
CurveMapping *mblur_shutter_curve;
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(sce, id));
MEMCPY_STRUCT_AFTER(sce, DNA_struct_default_get(Scene), id);
BLI_strncpy(sce->r.bake.filepath, U.renderdir, sizeof(sce->r.bake.filepath));
mblur_shutter_curve = &sce->r.mblur_shutter_curve;
BKE_curvemapping_set_defaults(mblur_shutter_curve, 1, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemapping_initialize(mblur_shutter_curve);
BKE_curvemap_reset(mblur_shutter_curve->cm,
&mblur_shutter_curve->clipr,
CURVE_PRESET_MAX,
CURVEMAP_SLOPE_POS_NEG);
sce->toolsettings = DNA_struct_default_alloc(ToolSettings);
sce->toolsettings->autokey_mode = U.autokey_mode;
/* grease pencil multiframe falloff curve */
sce->toolsettings->gp_sculpt.cur_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
CurveMapping *gp_falloff_curve = sce->toolsettings->gp_sculpt.cur_falloff;
BKE_curvemapping_initialize(gp_falloff_curve);
BKE_curvemap_reset(
gp_falloff_curve->cm, &gp_falloff_curve->clipr, CURVE_PRESET_GAUSS, CURVEMAP_SLOPE_POSITIVE);
sce->toolsettings->gp_sculpt.cur_primitive = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
CurveMapping *gp_primitive_curve = sce->toolsettings->gp_sculpt.cur_primitive;
BKE_curvemapping_initialize(gp_primitive_curve);
BKE_curvemap_reset(gp_primitive_curve->cm,
&gp_primitive_curve->clipr,
CURVE_PRESET_BELL,
CURVEMAP_SLOPE_POSITIVE);
sce->unit.system = USER_UNIT_METRIC;
sce->unit.scale_length = 1.0f;
sce->unit.length_unit = bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_LENGTH);
sce->unit.mass_unit = bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_MASS);
sce->unit.time_unit = bUnit_GetBaseUnitOfType(USER_UNIT_METRIC, B_UNIT_TIME);
{
ParticleEditSettings *pset;
pset = &sce->toolsettings->particle;
for (int i = 1; i < ARRAY_SIZE(pset->brush); i++) {
pset->brush[i] = pset->brush[0];
}
pset->brush[PE_BRUSH_CUT].strength = 1.0f;
}
BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine));
BLI_strncpy(sce->r.pic, U.renderdir, sizeof(sce->r.pic));
/* Note; in header_info.c the scene copy happens...,
* if you add more to renderdata it has to be checked there. */
/* multiview - stereo */
BKE_scene_add_render_view(sce, STEREO_LEFT_NAME);
srv = sce->r.views.first;
BLI_strncpy(srv->suffix, STEREO_LEFT_SUFFIX, sizeof(srv->suffix));
BKE_scene_add_render_view(sce, STEREO_RIGHT_NAME);
srv = sce->r.views.last;
BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix));
BKE_sound_reset_scene_runtime(sce);
/* color management */
colorspace_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_SEQUENCER);
BKE_color_managed_display_settings_init(&sce->display_settings);
BKE_color_managed_view_settings_init_render(
&sce->view_settings, &sce->display_settings, "Filmic");
BLI_strncpy(sce->sequencer_colorspace_settings.name,
colorspace_name,
sizeof(sce->sequencer_colorspace_settings.name));
/* Those next two sets (render and baking settings) are not currently in use,
* but are exposed to RNA API and hence must have valid data. */
BKE_color_managed_display_settings_init(&sce->r.im_format.display_settings);
BKE_color_managed_view_settings_init_render(
&sce->r.im_format.view_settings, &sce->r.im_format.display_settings, "Filmic");
BKE_color_managed_display_settings_init(&sce->r.bake.im_format.display_settings);
BKE_color_managed_view_settings_init_render(
&sce->r.bake.im_format.view_settings, &sce->r.bake.im_format.display_settings, "Filmic");
/* GP Sculpt brushes */
{
GP_Sculpt_Settings *gset = &sce->toolsettings->gp_sculpt;
GP_Sculpt_Data *gp_brush;
float curcolor_add[3], curcolor_sub[3];
ARRAY_SET_ITEMS(curcolor_add, 1.0f, 0.6f, 0.6f);
ARRAY_SET_ITEMS(curcolor_sub, 0.6f, 0.6f, 1.0f);
gp_brush = &gset->brush[GP_SCULPT_TYPE_SMOOTH];
gp_brush->size = 25;
gp_brush->strength = 0.3f;
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_SMOOTH_PRESSURE |
GP_SCULPT_FLAG_ENABLE_CURSOR;
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_SCULPT_TYPE_THICKNESS];
gp_brush->size = 25;
gp_brush->strength = 0.5f;
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_SCULPT_TYPE_STRENGTH];
gp_brush->size = 25;
gp_brush->strength = 0.5f;
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_SCULPT_TYPE_GRAB];
gp_brush->size = 50;
gp_brush->strength = 0.3f;
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_SCULPT_TYPE_PUSH];
gp_brush->size = 25;
gp_brush->strength = 0.3f;
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_SCULPT_TYPE_TWIST];
gp_brush->size = 50;
gp_brush->strength = 0.3f;
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_SCULPT_TYPE_PINCH];
gp_brush->size = 50;
gp_brush->strength = 0.5f;
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
gp_brush = &gset->brush[GP_SCULPT_TYPE_RANDOMIZE];
gp_brush->size = 25;
gp_brush->strength = 0.5f;
gp_brush->flag = GP_SCULPT_FLAG_USE_FALLOFF | GP_SCULPT_FLAG_ENABLE_CURSOR;
copy_v3_v3(gp_brush->curcolor_add, curcolor_add);
copy_v3_v3(gp_brush->curcolor_sub, curcolor_sub);
}
/* Curve Profile */
sce->toolsettings->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE);
for (int i = 0; i < ARRAY_SIZE(sce->orientation_slots); i++) {
sce->orientation_slots[i].index_custom = -1;
}
/* Master Collection */
sce->master_collection = BKE_collection_master_add();
BKE_view_layer_add(sce, "View Layer", NULL, VIEWLAYER_ADD_NEW);
/* 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)
{
Scene *sce;

View File

@@ -62,6 +62,7 @@
#include "DNA_hair_types.h"
#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_lanpr_types.h"
#include "DNA_lattice_types.h"
#include "DNA_layer_types.h"
#include "DNA_light_types.h"
@@ -6463,6 +6464,8 @@ static void direct_link_collection(FileData *fd, Collection *collection)
direct_link_view_layer(fd, collection->view_layer);
}
#endif
collection->lanpr = newdataadr(fd, collection->lanpr);
}
static void lib_link_collection_data(FileData *fd, Library *lib, Collection *collection)
@@ -6480,6 +6483,10 @@ static void lib_link_collection_data(FileData *fd, Library *lib, Collection *col
child->collection = newlibadr(fd, lib, child->collection);
}
if (collection->lanpr) {
collection->lanpr->target = newlibadr(fd, lib, collection->lanpr->target);
}
BKE_collection_parent_relations_rebuild(collection);
}
@@ -6761,6 +6768,42 @@ static void lib_link_scene(FileData *fd, Main *UNUSED(bmain), Scene *sce)
}
}
if (sce->rigidbody_world) {
RigidBodyWorld *rbw = sce->rigidbody_world;
if (rbw->group) {
rbw->group = newlibadr(fd, sce->id.lib, rbw->group);
}
if (rbw->constraints) {
rbw->constraints = newlibadr(fd, sce->id.lib, rbw->constraints);
}
if (rbw->effector_weights) {
rbw->effector_weights->group = newlibadr(fd, sce->id.lib, rbw->effector_weights->group);
}
}
if (sce->nodetree) {
lib_link_ntree(fd, &sce->id, sce->nodetree);
sce->nodetree->id.lib = sce->id.lib;
composite_patch(sce->nodetree, sce);
}
for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
srl->mat_override = newlibadr(fd, sce->id.lib, srl->mat_override);
for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
fmc->script = newlibadr(fd, sce->id.lib, fmc->script);
}
for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
fls->linestyle = newlibadr(fd, sce->id.lib, fls->linestyle);
fls->group = newlibadr(fd, sce->id.lib, fls->group);
}
}
for (LANPR_LineLayer *ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
ll->normal_control_object = newlibadr(fd, sce->id.lib, ll->normal_control_object);
}
/* Motion Tracking */
sce->clip = newlibadr(fd, sce->id.lib, sce->clip);
if (sce->nodetree) {
composite_patch(sce->nodetree, sce);
}
@@ -7201,6 +7244,12 @@ static void direct_link_scene(FileData *fd, Scene *sce)
}
EEVEE_lightcache_info_update(&sce->eevee);
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) {
ll->batch = NULL;
ll->shgrp = NULL;
}
direct_link_view3dshading(fd, &sce->display.shading);
sce->layer_properties = newdataadr(fd, sce->layer_properties);
@@ -11030,6 +11079,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);
@@ -11449,6 +11500,12 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
}
}
for (LANPR_LineLayer *ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
if (ll->normal_control_object) {
expand_doit(fd, mainvar, ll->normal_control_object);
}
}
if (sce->gpd) {
expand_doit(fd, mainvar, sce->gpd);
}

View File

@@ -4421,6 +4421,19 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
ToolSettings *ts = scene->toolsettings;
UnifiedPaintSettings *ups = &ts->unified_paint_settings;
ups->flag &= ~(UNIFIED_PAINT_FLAG_UNUSED_0 | UNIFIED_PAINT_FLAG_UNUSED_1);
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);
zero_v4(scene->lanpr.line_color);
scene->lanpr.line_color[3] = 1;
}
}
}
/* Set the default render pass in the viewport to Combined. */
@@ -5077,4 +5090,4 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
/* Keep this block, even when empty. */
}
}
}

View File

@@ -126,6 +126,8 @@
#include "DNA_object_types.h"
#include "DNA_packedFile_types.h"
#include "DNA_particle_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_lanpr_types.h"
#include "DNA_pointcloud_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -2501,6 +2503,10 @@ static void write_collection_nolib(WriteData *wd, Collection *collection)
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
writestruct(wd, DATA, CollectionChild, 1, child);
}
if (collection->lanpr != NULL) {
writestruct(wd, DATA, CollectionLANPR, 1, collection->lanpr);
}
}
static void write_collection(WriteData *wd, Collection *collection, const void *id_address)
@@ -2853,6 +2859,11 @@ static void write_scene(WriteData *wd, Scene *sce, const void *id_address)
write_lightcache(wd, sce->eevee.light_cache_data);
}
/* LANPR Line Layers */
for (LANPR_LineLayer *ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
writestruct(wd, DATA, LANPR_LineLayer, 1, ll);
}
write_view3dshading(wd, &sce->display.shading);
/* Freed on doversion. */

View File

@@ -185,6 +185,20 @@ set(LIB
bf_windowmanager
)
if(WITH_LANPR)
list(APPEND INC
engines/lanpr
)
list(APPEND SRC
engines/lanpr/lanpr_all.h
engines/lanpr/lanpr_dpix.c
engines/lanpr/lanpr_engine.c
engines/lanpr/lanpr_cpu.c
engines/lanpr/lanpr_chain_draw.c
)
add_definitions(-DWITH_LANPR)
endif()
data_to_c_simple(engines/eevee/shaders/ambient_occlusion_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/default_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/default_world_frag.glsl SRC)
@@ -307,6 +321,16 @@ data_to_c_simple(engines/basic/shaders/conservative_depth_geom.glsl SRC)
data_to_c_simple(engines/basic/shaders/depth_vert.glsl SRC)
data_to_c_simple(engines/basic/shaders/depth_frag.glsl SRC)
if(WITH_LANPR)
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_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)
endif()
data_to_c_simple(engines/overlay/shaders/antialiasing_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/antialiasing_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/armature_dof_vert.glsl SRC)

View File

@@ -133,6 +133,11 @@ void DRW_draw_select_id(struct Depsgraph *depsgraph,
bool DRW_render_check_grease_pencil(struct Depsgraph *depsgraph);
void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph);
/* LANPR calls */
#ifdef WITH_LANPR
void DRW_scene_lanpr_freecache(struct Scene *sce);
#endif
/* This is here because GPUViewport needs it */
struct DRWInstanceDataList *DRW_instance_data_list_create(void);
void DRW_instance_data_list_free(struct DRWInstanceDataList *idatalist);

View File

@@ -0,0 +1,247 @@
/*
* 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"
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;
/* 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 *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;
} 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,
const Object *ob,
const int begin_index);
int lanpr_feed_atlas_data_intersection_cache(void *vedata,
float *AtlasPointsL,
float *AtlasPointsR,
float *AtlasFaceNormalL,
float *AtlasFaceNormalR,
float *AtlasEdgeMask,
const int begin_index);
int lanpr_feed_atlas_trigger_preview_obj(void *vedata, Object *ob, const int begin_index);
void lanpr_create_atlas_intersection_preview(void *vedata, const 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_software_draw_scene(void *vedata, GPUFrameBuffer *dfb, const int is_render);
int lanpr_dpix_texture_size(const SceneLANPR *lanpr);
void lanpr_chain_generate_draw_command(struct LANPR_RenderBuffer *rb);
#endif

View File

@@ -0,0 +1,211 @@
/*
* 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 lanpr_compute_chain_length_draw(const LANPR_RenderLineChain *rlc,
float *lengths,
const 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(const 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;
}
}
/** Endpoint flag,
* use an unreasonably big value in lanpr but within float range.
* This value is used to determin endpoint in the shader.
* Keep in sync with the one in lanpr_software_chain_geom.glsl */
#define LANPR_CHAIN_ENDPOINT_FLAG 3e30f
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;
/* We don't need a dummy vert for the end point. Thus no "+1" here */
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 = 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 - 1, i, i + 1, vert_count - 1);
}
else {
GPU_indexbuf_add_line_adj_verts(&elb, vert_count - 1, 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 - 1);
}
else {
GPU_indexbuf_add_line_adj_verts(&elb, i - 1, i, i + 1, i + 2);
}
}
i++;
}
}
/* set end point flag value. */
length_target[0] = LANPR_CHAIN_ENDPOINT_FLAG;
length_target[1] = LANPR_CHAIN_ENDPOINT_FLAG;
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);
}
void ED_lanpr_render_buffer_cache_free(LANPR_RenderBuffer *rb)
{
if (rb->chain_draw_batch) {
GPU_BATCH_DISCARD_SAFE(rb->chain_draw_batch);
}
}

View File

@@ -0,0 +1,520 @@
/*
* 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_linklist.h"
#include "BLI_listbase.h"
#include "BLI_math_matrix.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_customdata.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_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_api.h"
#include "WM_types.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 vert_count;
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);
}
vert_count = count * 2;
if (!vert_count) {
return;
}
GPU_vertbuf_data_alloc(vbo, vert_count);
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 < vert_count; 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(Scene *s)
{
SceneLANPR *lanpr = &s->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_SAFE(ll->batch);
}
lanpr_rebuild_render_draw_command(lanpr_share.render_buffer_shared, ll);
}
}
DEG_id_tag_update(&s->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, const 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 identity_mat[4][4], win_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(scene);
}
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->dpix_viewport[2] = texw;
pd->dpix_viewport[3] = texh;
if (is_render) {
pd->output_viewport[2] = scene->r.xsch;
pd->output_viewport[3] = scene->r.ysch;
}
else {
pd->output_viewport[2] = texw;
pd->output_viewport[3] = texh;
}
unit_m4(identity_mat);
DRW_view_winmat_get(NULL, win_mat, false);
DRWView *view = DRW_view_create(identity_mat, win_mat, NULL, NULL, NULL);
if (is_render) {
DRW_view_set_active(view);
}
RegionView3D *rv3d = v3d ? draw_ctx->rv3d : NULL;
if ((!is_render) && (rv3d && rv3d->view == RV3D_CAMOB)) {
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->chain_shgrp = 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->chain_shgrp, "camdx", &camdx, 1);
DRW_shgroup_uniform_float(rb->chain_shgrp, "camdy", &camdy, 1);
DRW_shgroup_uniform_float(rb->chain_shgrp, "camzoom", &camzoom, 1);
DRW_shgroup_uniform_vec4(rb->chain_shgrp,
"color_contour",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color :
ll->contour.color,
1);
DRW_shgroup_uniform_vec4(rb->chain_shgrp,
"color_crease",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color :
ll->crease.color,
1);
DRW_shgroup_uniform_vec4(rb->chain_shgrp,
"color_material",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
ll->color :
ll->material_separate.color,
1);
DRW_shgroup_uniform_vec4(
rb->chain_shgrp,
"color_edge_mark",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->edge_mark.color,
1);
DRW_shgroup_uniform_vec4(
rb->chain_shgrp,
"color_intersection",
(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->chain_shgrp, "thickness", &ll->thickness, 1);
DRW_shgroup_uniform_float(rb->chain_shgrp,
"thickness_contour",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->contour.thickness,
1);
DRW_shgroup_uniform_float(rb->chain_shgrp,
"thickness_crease",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->crease.thickness,
1);
DRW_shgroup_uniform_float(rb->chain_shgrp,
"thickness_material",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->material_separate.thickness,
1);
DRW_shgroup_uniform_float(rb->chain_shgrp,
"thickness_edge_mark",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->edge_mark.thickness,
1);
DRW_shgroup_uniform_float(rb->chain_shgrp,
"thickness_intersection",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
&unit_thickness :
&ll->intersection.thickness,
1);
DRW_shgroup_uniform_int(rb->chain_shgrp, "use_contour", &ll->contour.use, 1);
DRW_shgroup_uniform_int(rb->chain_shgrp, "use_crease", &ll->crease.use, 1);
DRW_shgroup_uniform_int(rb->chain_shgrp, "use_material", &ll->material_separate.use, 1);
DRW_shgroup_uniform_int(rb->chain_shgrp, "use_edge_mark", &ll->edge_mark.use, 1);
DRW_shgroup_uniform_int(rb->chain_shgrp, "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->chain_shgrp,
"normal_mode",
(ll->flags & LANPR_LINE_LAYER_NORMAL_ENABLED) ? &ll->normal_mode :
&zero_value,
1);
DRW_shgroup_uniform_int(
rb->chain_shgrp, "normal_effect_inverse", &normal_effect_inverse, 1);
DRW_shgroup_uniform_float(rb->chain_shgrp, "normal_ramp_begin", &ll->normal_ramp_begin, 1);
DRW_shgroup_uniform_float(rb->chain_shgrp, "normal_ramp_end", &ll->normal_ramp_end, 1);
DRW_shgroup_uniform_float(
rb->chain_shgrp, "normal_thickness_start", &ll->normal_thickness_start, 1);
DRW_shgroup_uniform_float(
rb->chain_shgrp, "normal_thickness_end", &ll->normal_thickness_end, 1);
DRW_shgroup_uniform_vec3(rb->chain_shgrp, "normal_direction", normal_object_direction, 1);
DRW_shgroup_uniform_int(rb->chain_shgrp, "occlusion_level_start", &ll->level_start, 1);
DRW_shgroup_uniform_int(
rb->chain_shgrp,
"occlusion_level_end",
(ll->flags & LANPR_LINE_LAYER_USE_MULTIPLE_LEVELS) ? &ll->level_end : &ll->level_start,
1);
DRW_shgroup_uniform_vec4(
rb->chain_shgrp, "preview_viewport", stl->g_data->dpix_viewport, 1);
DRW_shgroup_uniform_vec4(
rb->chain_shgrp, "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->chain_shgrp, "taper_l_dist", tld, 1);
DRW_shgroup_uniform_float(rb->chain_shgrp, "taper_l_strength", tls, 1);
DRW_shgroup_uniform_float(
rb->chain_shgrp, "taper_r_dist", (lanpr->flags & LANPR_SAME_TAPER) ? tld : trd, 1);
DRW_shgroup_uniform_float(
rb->chain_shgrp, "taper_r_strength", (lanpr->flags & LANPR_SAME_TAPER) ? tls : trs, 1);
/* need to add component enable/disable option. */
DRW_shgroup_call(
rb->chain_shgrp, 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,
"color_contour",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->contour.color,
1);
DRW_shgroup_uniform_vec4(
ll->shgrp,
"color_crease",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->crease.color,
1);
DRW_shgroup_uniform_vec4(ll->shgrp,
"color_material",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ?
ll->color :
ll->material_separate.color,
1);
DRW_shgroup_uniform_vec4(
ll->shgrp,
"color_edge_mark",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color : ll->edge_mark.color,
1);
DRW_shgroup_uniform_vec4(
ll->shgrp,
"color_intersection",
(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,558 @@
/*
* 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 "bmesh.h"
#include "lanpr_all.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(const 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;
case LANPR_GPU_CACHE_SIZE_8K:
return 8192;
case LANPR_GPU_CACHE_SIZE_16K:
return 16384;
}
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 == NULL) {
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 == NULL) {
lanpr_share.dpix_shader_error = true;
printf("LANPR: DPIX transform shader compile error.");
}
}
if (lanpr_share.dpix_preview_shader == NULL) {
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 == NULL) {
lanpr_share.dpix_shader_error = true;
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,
const Object *ob,
const 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)) {
WM_report(RPT_WARNING, "LANPR: GPU Cache too small for displaying some of the objects.");
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,
const int begin_index)
{
LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared;
LinkData *lip;
LANPR_RenderLine *rl;
int i, idx;
i = 0;
if (rb == NULL) {
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)) {
WM_report(RPT_WARNING, "LANPR: GPU Cache too small for displaying intersections.");
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(const 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, const 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), const int begin_index)
{
LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared;
float co[2];
int i;
if (rb == NULL) {
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 == NULL) {
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 == NULL) {
camera = scene->camera;
if (v3d == NULL) {
is_persp = ((Camera *)camera->data)->type == CAM_PERSP ? 1 : 0;
}
}
if (is_render && !camera) {
return;
}
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; /* This value works okay with default camera. */
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,799 @@
/*
* 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_linklist.h"
#include "BLI_listbase.h"
#include "BLI_math_matrix.h"
#include "BLI_rect.h"
#include "BLI_task.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_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[];
extern char datatoc_gpu_shader_colorspace_lib_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);
}
DRW_texture_ensure_fullscreen_2d(&txl->depth, GPU_DEPTH_COMPONENT32F, 0);
DRW_texture_ensure_fullscreen_2d(&txl->color, GPU_RGBA32F, 0);
DRW_texture_ensure_fullscreen_2d(&txl->normal, GPU_RGBA32F, 0);
DRW_texture_ensure_fullscreen_2d(&txl->edge_intermediate, GPU_RGBA32F, 0);
DRW_texture_ensure_fullscreen_2d(&txl->ms_resolve_depth, GPU_DEPTH_COMPONENT32F, 0);
DRW_texture_ensure_fullscreen_2d(&txl->ms_resolve_color, GPU_RGBA32F, 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 == NULL) {
lanpr_share.multichannel_shader = GPU_shader_create_from_arrays({
.vert = (const char *[]){datatoc_gpu_shader_3D_smooth_color_vert_glsl, NULL},
.geom = (const char *[]){NULL},
.frag = (const char *[]){datatoc_gpu_shader_colorspace_lib_glsl,
datatoc_gpu_shader_3D_smooth_color_frag_glsl,
NULL},
.defs = (const char *[]){NULL},
});
}
/* DPIX */
lanpr_init_atlas_inputs(ved);
/* SOFTWARE */
if (lanpr_share.software_shader == NULL) {
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 == NULL) {
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)});
if (!(lanpr_share.init_complete & LANPR_INIT_LOCKS)) {
BLI_spin_init(&lanpr_share.lock_loader);
BLI_spin_init(&lanpr_share.lock_render_status);
lanpr_share.init_complete |= LANPR_INIT_LOCKS;
}
lanpr_share.init_complete |= LANPR_INIT_ENGINE;
}
void DRW_scene_lanpr_freecache(Scene *sce)
{
LANPR_LineLayer *ll;
for (ll = sce->lanpr.line_layers.first; ll; ll = ll->next) {
if (ll->batch) {
GPU_batch_discard(ll->batch);
ll->batch = NULL;
}
}
}
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_chain_batch_free(void)
{
LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared;
if (rb) {
if (rb->chain_draw_batch) {
GPU_BATCH_DISCARD_SAFE(rb->DPIXIntersectionBatch);
}
}
}
static void lanpr_engine_free(void)
{
DRW_SHADER_FREE_SAFE(lanpr_share.multichannel_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.software_shader);
lanpr_dpix_batch_free();
lanpr_chain_batch_free();
BLI_spin_end(&lanpr_share.lock_loader);
BLI_spin_end(&lanpr_share.lock_render_status);
if (lanpr_share.render_buffer_shared) {
LANPR_RenderBuffer *rb = lanpr_share.render_buffer_shared;
ED_lanpr_destroy_render_data(rb);
if (lanpr_share.background_render_task) {
BLI_task_pool_free(lanpr_share.background_render_task);
}
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;
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 == NULL) {
/* Alloc transient pointers */
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
if (lanpr_share.mp_batch_list == NULL) {
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;
View3D *v3d = draw_ctx->v3d;
RegionView3D *rv3d = v3d ? draw_ctx->rv3d : NULL;
bool is_render = (lanpr_share.viewport_camera_override < 0);
BLI_spin_lock(&lanpr_share.lock_render_status);
if (rv3d && lanpr_share.viewport_camera_override >= 0) {
copy_v3_v3(lanpr_share.camera_pos, rv3d->viewinv[3]);
copy_m4_m4(lanpr_share.viewinv, rv3d->viewinv);
copy_m4_m4(lanpr_share.persp, rv3d->persmat);
copy_v4_v4(lanpr_share.viewquat, rv3d->viewquat);
lanpr_share.near_clip = v3d->clip_start;
lanpr_share.far_clip = v3d->clip_end;
lanpr_share.viewport_camera_override = 1;
lanpr_share.camera_is_persp = rv3d->is_persp;
}
else {
lanpr_share.viewport_camera_override = 0;
}
BLI_spin_unlock(&lanpr_share.lock_render_status);
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_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, "tex_vert0", &txl->dpix_in_pl);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_transform_shgrp, "tex_vert1", &txl->dpix_in_pr);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_transform_shgrp, "tex_fnormal0", &txl->dpix_in_nl);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_transform_shgrp, "tex_fnormal1", &txl->dpix_in_nr);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_transform_shgrp, "tex_edge_mask", &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, "tex_vert0", &txl->dpix_out_pl);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_preview_shgrp, "tex_vert1", &txl->dpix_out_pr);
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_preview_shgrp, "tex_fnormal0", &txl->dpix_in_nl);
DRW_shgroup_uniform_texture_ref(stl->g_data->dpix_preview_shgrp,
"tex_fnormal1",
&txl->dpix_in_nr); /* these are for normal shading */
DRW_shgroup_uniform_texture_ref(
stl->g_data->dpix_preview_shgrp, "tex_edge_mask", &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,
"color_contour",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color :
ll->contour.color,
1);
DRW_shgroup_uniform_vec4(stl->g_data->dpix_preview_shgrp,
"color_crease",
(ll->flags & LANPR_LINE_LAYER_USE_SAME_STYLE) ? ll->color :
ll->crease.color,
1);
DRW_shgroup_uniform_vec4(
stl->g_data->dpix_preview_shgrp,
"color_material",
(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,
"color_edge_mark",
(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,
"color_intersection",
(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,
"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,
"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,
"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,
"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,
"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. */
if (draw_ctx->scene->lanpr.flags & LANPR_AUTO_UPDATE) {
/** This will be released by compute function when loading is finished. */
BLI_spin_lock(&lanpr_share.lock_loader);
if (draw_ctx->scene->lanpr.master_mode == LANPR_MASTER_MODE_SOFTWARE) {
if (is_render) {
ED_lanpr_compute_feature_lines_internal(draw_ctx->depsgraph, 0);
}
else {
ED_lanpr_compute_feature_lines_background(draw_ctx->depsgraph, 0);
}
}
else if (draw_ctx->scene->lanpr.master_mode == LANPR_MASTER_MODE_DPIX) {
/* Don't do threaded intersection calculation. It's pointless in GPU mode anyway. */
ED_lanpr_compute_feature_lines_internal(draw_ctx->depsgraph, 1);
}
}
/** Important: This ensures we don't proceed beyond this point until everything is loaded. */
BLI_spin_lock(&lanpr_share.lock_loader);
BLI_spin_unlock(&lanpr_share.lock_loader);
if (ED_lanpr_calculation_flag_check(LANPR_RENDER_FINISHED) ||
ED_lanpr_calculation_flag_check(LANPR_RENDER_IDLE)) {
ED_lanpr_rebuild_all_command(draw_ctx->scene);
ED_lanpr_calculation_set_flag(LANPR_RENDER_IDLE);
}
else if (!is_render) {
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);
if (idx != pd->begin_index) { /* Which means we are actually able to feed object data */
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, 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);
}
else if (lanpr->master_mode == LANPR_MASTER_MODE_SOFTWARE) {
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, 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();
lanpr_share.re_render = engine;
RE_engine_update_stats(engine, NULL, "LANPR: Initializing");
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);
/* force dpix batch to re-create */
lanpr_share.dpix_reloaded_deg = 1;
/* force use actual camera instead of viewport camera. */
/* Do this before creating render buffer. */
lanpr_share.viewport_camera_override = -1;
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,6 @@
in vec4 color_out;
void main()
{
gl_FragData[0] = vec4(color_out.rgb, 1);
}

View File

@@ -0,0 +1,193 @@
layout(points) in;
layout(triangle_strip, max_vertices = 6) out;
uniform sampler2D tex_vert0; // L
uniform sampler2D tex_vert1; // R
uniform sampler2D tex_fnormal0;
uniform sampler2D tex_fnormal1; // caution: these are face normals!
uniform sampler2D tex_edge_mask;
// 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 color_contour;
uniform vec4 color_crease;
uniform vec4 color_material;
uniform vec4 color_edge_mark;
uniform vec4 color_intersection;
uniform float thickness_contour;
uniform float thickness_crease;
uniform float thickness_material;
uniform float thickness_edge_mark;
uniform float 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 color_out;
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
color_out = 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(tex_vert0, ivec2(gl_in[0].gl_Position.xy), 0);
vec4 p2 = texelFetch(tex_vert1, ivec2(gl_in[0].gl_Position.xy), 0);
vec4 n1 = texelFetch(tex_fnormal0, ivec2(gl_in[0].gl_Position.xy), 0);
vec4 n2 = texelFetch(tex_fnormal1, 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(tex_edge_mask, 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 = color_edge_mark;
use_thickness = th * thickness_edge_mark;
}
else if (edge_mask.r > 0) {
use_color = color_material;
use_thickness = th * thickness_material;
}
else if (edge_mask.b > 0) {
use_color = color_intersection;
use_thickness = th * thickness_intersection;
}
else if (p2.w != p1.w) {
use_color = color_crease;
use_thickness = th * thickness_crease;
is_crease = 1;
}
else {
use_color = color_contour;
use_thickness = th * thickness_contour;
}
draw_line(p1, p2, is_crease);
}

View File

@@ -0,0 +1,469 @@
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 tex_vert0;
uniform sampler2D tex_vert1;
uniform sampler2D tex_fnormal0;
uniform sampler2D tex_fnormal1;
uniform sampler2D tex_edge_mask;
// 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(tex_fnormal0, texcoord, 0).xyz;
vec3 face_normal_1 = mat3(nm) * texelFetch(tex_fnormal1, 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(tex_edge_mask, 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(tex_vert0, texcoord, 0);
vec4 v1_world_pos = texelFetch(tex_vert1, 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);
}
}
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;
float segment_screen_length = length(v0_screen - v1_screen);
// 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;
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);
}

View File

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

View File

@@ -0,0 +1,293 @@
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 color_contour;
uniform vec4 color_crease;
uniform vec4 color_material;
uniform vec4 color_edge_mark;
uniform vec4 color_intersection;
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 color_out;
float use_thickness;
#define M_PI 3.1415926535897932384626433832795
#define LANPR_CHAIN_ENDPOINT_FLAG 3e30f
vec4 END_POINT = vec4(vec2(LANPR_CHAIN_ENDPOINT_FLAG), 0, 1);
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) {
color_out = color_contour;
use_thickness = th * thickness_contour * use_contour;
return;
}
if (component_id == 1) {
color_out = color_crease;
use_thickness = th * thickness_crease * use_crease;
return;
}
if (component_id == 2) {
color_out = color_material;
use_thickness = th * thickness_material * use_material;
return;
}
if (component_id == 3) {
color_out = color_edge_mark;
use_thickness = th * thickness_edge_mark * use_edge_mark;
return;
}
if (component_id == 4) {
color_out = color_intersection;
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 color_contour;
uniform vec4 color_crease;
uniform vec4 color_material;
uniform vec4 color_edge_mark;
uniform vec4 color_intersection;
// for line width correction
uniform vec4 output_viewport;
uniform vec4 preview_viewport;
uniform float camdx;
uniform float camdy;
uniform float camzoom;
out vec4 color_out;
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) {
color_out = color_contour;
use_thickness = th * thickness_contour;
return;
}
if (component_id < 2.5) {
color_out = color_crease;
use_thickness = th * thickness_crease;
return;
}
if (component_id < 3.5) {
color_out = color_material;
use_thickness = th * thickness_material;
return;
}
if (component_id < 4.5) {
color_out = color_edge_mark;
use_thickness = th * thickness_edge_mark;
return;
}
if (component_id < 5.5) {
color_out = color_intersection;
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

@@ -175,6 +175,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

@@ -97,6 +97,10 @@
#include "engines/select/select_engine.h"
#include "engines/workbench/workbench_engine.h"
#ifdef WITH_LANPR
# include "engines/lanpr/lanpr_all.h"
#endif
#include "GPU_context.h"
#include "DEG_depsgraph.h"
@@ -2653,6 +2657,9 @@ void DRW_engines_register(void)
{
RE_engines_register(&DRW_engine_viewport_eevee_type);
RE_engines_register(&DRW_engine_viewport_workbench_type);
#ifdef WITH_LANPR
RE_engines_register(&DRW_engine_viewport_lanpr_type);
#endif
DRW_engine_register(&draw_engine_gpencil_type);

View File

@@ -168,6 +168,30 @@ void DRW_texture_ensure_2d(
}
}
void DRW_texture_ensure_fullscreen_2D_multisample(GPUTexture **tex,
eGPUTextureFormat format,
int samples,
DRWTextureFlag UNUSED(flags))
{
if (*(tex) == NULL) {
const float *size = DRW_viewport_size_get();
*(tex) = GPU_texture_create_2d_multisample(
(int)size[0], (int)size[1], format, NULL, samples, NULL);
}
}
void DRW_texture_ensure_2D_multisample(GPUTexture **tex,
int w,
int h,
eGPUTextureFormat format,
int samples,
DRWTextureFlag UNUSED(flags))
{
if (*(tex) == NULL) {
*(tex) = GPU_texture_create_2d_multisample(w, h, format, NULL, samples, NULL);
}
}
void DRW_texture_generate_mipmaps(GPUTexture *tex)
{
GPU_texture_bind(tex, 0);

View File

@@ -64,3 +64,8 @@ if(WITH_BLENDER)
endif()
add_subdirectory(datafiles)
if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
add_subdirectory(lanpr)
endif()

View File

@@ -0,0 +1,625 @@
/*
* 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__
#ifndef WITH_LANPR
# error LANPR code included in non-LANPR-enabled build
#endif
#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 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_RenderTriangle {
struct LANPR_RenderTriangle *next, *prev;
struct LANPR_RenderVert *v[3];
struct LANPR_RenderLine *rl[3];
double gn[3];
double 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) */
double at;
/** 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;
double gloc[4];
double 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;
/** This will used in future acceleration for intersection processing. */
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;
double 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 */
double 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 *chain_shgrp;
/** For managing calculation tasks for multiple threads. */
SpinLock lock_task;
/* settings */
int max_occlusion_level;
double crease_angle;
double crease_cos;
int thread_count;
int draw_material_preview;
double material_transparency;
int show_line;
int show_fast;
int show_material;
int override_display;
int use_intersections;
int _pad;
/** Keep an copy of these data so the scene can be freed when lanpr is runnning. */
char cam_is_persp;
float cam_obmat[4][4];
double camera_pos[3];
double near_clip, far_clip;
double shift_x, shift_y;
double chaining_image_threshold;
double chaining_geometry_threshold;
} 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 enum LANPR_INIT_STATUS {
LANPR_INIT_ENGINE = (1 << 0),
LANPR_INIT_LOCKS = (1 << 1),
} LANPR_INIT_STATUS;
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;
/* Shared */
struct GPUShader *multichannel_shader;
/* GPU */
struct GPUShader *dpix_transform_shader;
struct GPUShader *dpix_preview_shader;
bool 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;
struct TaskPool *background_render_task;
void *ved_viewport;
void *ved_render;
LANPR_INIT_STATUS init_complete;
/** To bypass or cancel rendering.
* This status flag should be kept in lanpr_share not render_buffer,
* because render_buffer will get re-initialized every frame.
*/
SpinLock lock_render_status;
LANPR_RenderStatus flag_render_status;
/** Geometry loading is done in the worker thread,
* Lock the render thread until loading is done, so that
* we can avoid depsgrapgh deleting the scene before
* LANPR finishes loading. Also keep this in lanpr_share.
*/
SpinLock lock_loader;
/** Set before rendering and cleared upon finish! */
struct RenderEngine *re_render;
/** When drawing in the viewport, use the following values. */
/** Set to override to -1 before creating lanpr render buffer to use scene camera. */
int viewport_camera_override;
char camera_is_persp;
float camera_pos[3];
float near_clip, far_clip;
float viewinv[4][4];
float persp[4][4];
float viewquat[4];
} 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;
/** Controls how many lines a worker thread is processing at one request.
* There's no significant performance impact on choosing different values.
* Don't make it too small so that the worker thread won't request too many times. */
#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;
/** Bounding area diagram:
*
* +----+ <----U (Upper edge Y value)
* | |
* +----+ <----B (Bottom edge Y value)
* ^ ^
* L R (Left/Right edge X value)
*
* Example structure when subdividing 1 bounding areas:
* 1 area can be divided into 4 smaller children to
* accomodate image areas with denser triangle distribution.
* +--+--+-----+
* +--+--+ |
* +--+--+-----+
* | | |
* +-----+-----+
* lp/rp/up/bp is the list for
* storing pointers to adjacent bounding areas.
*/
typedef struct LANPR_BoundingArea {
double l, r, u, b;
double 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 tmat_get_linear_ratio(double l, double r, double from_l);
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 x_diff = (a2[0] - a1[0]);
double x_diff2 = (b2[0] - b1[0]);
if (x_diff == 0) {
if (x_diff2 == 0) {
*aRatio = 0;
return 0;
}
double r2 = tmat_get_linear_ratio(b1[0], b2[0], a1[0]);
x = interpd(b2[0], b1[0], r2);
y = interpd(b2[1], b1[1], r2);
*aRatio = ratio = tmat_get_linear_ratio(a1[1], a2[1], y);
}
else {
if (x_diff2 == 0) {
ratio = tmat_get_linear_ratio(a1[0], a2[0], b1[0]);
x = interpd(a2[0], a1[0], ratio);
*aRatio = ratio;
}
else {
k1 = (a2[1] - a1[1]) / x_diff;
k2 = (b2[1] - b1[1]) / x_diff2;
if ((k1 == k2))
return 0;
x = (a1[1] - b1[1] - k1 * a1[0] + k2 * b1[0]) / (k2 - k1);
ratio = (x - a1[0]) / x_diff;
*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 tmat_get_linear_ratio(double l, double r, double from_l)
{
double ra = (from_l - l) / (r - l);
return ra;
}
int ED_lanpr_point_inside_triangled(double v[2], double v0[2], double v1[2], double v2[2]);
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, const int do_geometry_space);
void ED_lanpr_discard_short_chains(LANPR_RenderBuffer *rb, const float threshold);
int ED_lanpr_count_chain(const LANPR_RenderLineChain *rlc);
void ED_lanpr_chain_clear_picked_flag(struct LANPR_RenderBuffer *rb);
int ED_lanpr_count_leveled_edge_segment_count(const ListBase *line_list,
const struct LANPR_LineLayer *ll);
void *ED_lanpr_make_leveled_edge_vertex_array(struct LANPR_RenderBuffer *rb,
const ListBase *line_list,
float *vertex_array,
float *normal_array,
float **next_normal,
const LANPR_LineLayer *ll,
const 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,
const int instersections_only);
void ED_lanpr_compute_feature_lines_background(struct Depsgraph *dg, const int intersection_only);
struct Scene;
LANPR_RenderBuffer *ED_lanpr_create_render_buffer(struct Scene *s);
void ED_lanpr_destroy_render_data(struct LANPR_RenderBuffer *rb);
bool ED_lanpr_dpix_shader_error(void);
void ED_lanpr_render_buffer_cache_free(struct LANPR_RenderBuffer *rb);
int ED_lanpr_max_occlusion_in_line_layers(struct SceneLANPR *lanpr);
LANPR_LineLayer *ED_lanpr_new_line_layer(struct SceneLANPR *lanpr);
LANPR_BoundingArea *ED_lanpr_get_point_bounding_area(LANPR_RenderBuffer *rb, double x, double y);
LANPR_BoundingArea *ED_lanpr_get_point_bounding_area_deep(LANPR_RenderBuffer *rb,
double x,
double y);
void ED_lanpr_post_frame_update_external(struct Scene *s, struct Depsgraph *dg);
struct SceneLANPR;
void ED_lanpr_rebuild_all_command(struct Scene *s);
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_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,759 @@
/*
* 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;
}
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 == NULL) {
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 == NULL) {
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 == NULL) {
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;
}
}
/* this only does head-tail connection. */
/* overlapping / tiny isolated segment / loop reduction not implemented here yet. */
void ED_lanpr_connect_chains(LANPR_RenderBuffer *rb, const 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->chaining_image_threshold < 0.0001) ||
(do_geometry_space && rb->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->chaining_geometry_threshold : rb->chaining_image_threshold;
closest_cre = NULL;
if (ba->linked_chains.first == NULL) {
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->chaining_geometry_threshold : rb->chaining_image_threshold;
closest_cre = NULL;
if (ba->linked_chains.first == NULL) {
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, const 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(const 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 == NULL) {
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,48 @@
/*
* 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_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,191 @@
/*
* 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 == NULL) {
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 == NULL) {
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 == NULL) {
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 == NULL) {
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] */
void tmat_make_perspective_matrix_44d(
double (*mProjection)[4], double fFov_rad, double fAspect, double zMin, double zMax)
{
double yMax;
double yMin;
double xMin;
double 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],
double xMin,
double xMax,
double yMin,
double yMax,
double zMin,
double 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

@@ -89,6 +89,10 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
endif()
if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()

View File

@@ -7676,7 +7676,7 @@ void MESH_OT_symmetry_snap(struct wmOperatorType *ot)
/** \} */
#ifdef WITH_FREESTYLE
#if (defined(WITH_FREESTYLE) || defined(WITH_LANPR))
/* -------------------------------------------------------------------- */
/** \name Mark Edge (Freestyle) Operator
@@ -7836,7 +7836,7 @@ void MESH_OT_mark_freestyle_face(wmOperatorType *ot)
/** \} */
#endif /* WITH_FREESTYLE */
#endif /* WITH_FREESTYLE || WITH_LANPR */
/* -------------------------------------------------------------------- */
/** \name Loop Normals Editing Tools Modal Map

View File

@@ -257,7 +257,7 @@ void MESH_OT_paint_mask_slice(struct wmOperatorType *ot);
struct wmKeyMap *point_normals_modal_keymap(wmKeyConfig *keyconf);
#ifdef WITH_FREESTYLE
#if (defined(WITH_FREESTYLE) || defined(WITH_LANPR))
void MESH_OT_mark_freestyle_edge(struct wmOperatorType *ot);
void MESH_OT_mark_freestyle_face(struct wmOperatorType *ot);
#endif

View File

@@ -133,7 +133,7 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_loop_multi_select);
WM_operatortype_append(MESH_OT_mark_seam);
WM_operatortype_append(MESH_OT_mark_sharp);
#ifdef WITH_FREESTYLE
#if (defined(WITH_FREESTYLE) || defined(WITH_LANPR))
WM_operatortype_append(MESH_OT_mark_freestyle_edge);
#endif
WM_operatortype_append(MESH_OT_vertices_smooth);

View File

@@ -70,6 +70,10 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
endif()
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()

View File

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

View File

@@ -55,4 +55,8 @@ set(LIB
bf_editor_space_view3d
)
if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
endif()
blender_add_lib(bf_editor_space_api "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@@ -64,6 +64,10 @@
#include "ED_userpref.h"
#include "ED_uvedit.h"
#ifdef WITH_LANPR
# include "ED_lanpr.h"
#endif
#include "io_ops.h"
/* only call once on startup, storage is global in BKE kernel listbase */
@@ -123,6 +127,10 @@ void ED_spacetypes_init(void)
ED_operatortypes_view2d();
ED_operatortypes_ui();
#ifdef WITH_LANPR
ED_operatortypes_lanpr();
#endif
ED_screen_user_menu_register();
/* gizmo types */

View File

@@ -54,6 +54,10 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
endif()
if(WITH_NEW_OBJECT_TYPES)
add_definitions(-DWITH_NEW_OBJECT_TYPES)
endif()

View File

@@ -164,6 +164,29 @@ static int buttons_context_path_world(ButsContextPath *path)
return 0;
}
static int buttons_context_path_collection(ButsContextPath *path, wmWindow *window)
{
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;
@@ -595,6 +618,26 @@ 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: /* This is for LANPR collection flags */
#ifdef WITH_LANPR
found = buttons_context_path_collection(path, window);
#else
BLI_assert(!"'WITH_LANPR' disabled - should not possible to access 'BCONTEXT_COLLECTION'");
#endif
break;
case BCONTEXT_LANPR: /* This is for LANPR object flags */
#ifdef WITH_LANPR
if (scene &&
((scene->lanpr.flags & LANPR_ENABLED) || !strcmp(scene->r.engine, "BLENDER_LANPR"))) {
found = buttons_context_path_object(path);
}
else {
found = 0;
}
#else
BLI_assert(!"'WITH_LANPR' disabled - should not possible to access 'BCONTEXT_LANPR'");
#endif
break;
case BCONTEXT_TOOL:
found = true;
break;

View File

@@ -160,6 +160,21 @@ static void buttons_main_region_layout_properties(const bContext *C,
case BCONTEXT_WORLD:
contexts[0] = "world";
break;
case BCONTEXT_COLLECTION:
#ifdef WITH_LANPR
contexts[0] = "collection";
#else
BLI_assert(!"'WITH_LANPR' disabled - should not possible to access 'BCONTEXT_COLLECTION'");
#endif
break;
case BCONTEXT_LANPR:
#ifdef WITH_LANPR
contexts[0] = "lanpr";
#else
BLI_assert(!"'WITH_LANPR' disabled - should not possible to access 'BCONTEXT_COLLECTION'");
#endif
break;
case BCONTEXT_OBJECT:
contexts[0] = "object";
break;

View File

@@ -95,6 +95,10 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
endif()
if(WITH_XR_OPENXR)
add_definitions(-DWITH_XR_OPENXR)
endif()

View File

@@ -1058,6 +1058,11 @@ 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);
#ifdef WITH_LANPR
WM_msg_subscribe_rna_anon_type(mbus, SceneLANPR, &msg_sub_value_region_tag_redraw);
#endif
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

@@ -62,6 +62,7 @@ set(SRC
../include/ED_keyframes_draw.h
../include/ED_keyframes_edit.h
../include/ED_keyframing.h
../include/ED_lanpr.h
../include/ED_lattice.h
../include/ED_logic.h
../include/ED_markers.h
@@ -112,6 +113,10 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
endif()
if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
list(APPEND INC

View File

@@ -352,14 +352,24 @@ typedef enum eGp_Vertex_Mode {
GPPAINT_MODE_BOTH = 2,
} eGp_Vertex_Mode;
/* sculpt_flag */
/* GP_Sculpt_Data.flag */
typedef enum eGP_Sculpt_Flag {
/* invert the effect of the brush */
GP_SCULPT_FLAG_INVERT = (1 << 0),
/* adjust strength using pen pressure */
GP_SCULPT_FLAG_USE_PRESSURE = (1 << 1),
/* strength of brush falls off with distance from cursor */
GP_SCULPT_FLAG_USE_FALLOFF = (1 << 2),
/* smooth brush affects pressure values as well */
GP_SCULPT_FLAG_SMOOTH_PRESSURE = (1 << 2),
GP_SCULPT_FLAG_SMOOTH_PRESSURE = (1 << 3),
/* enable screen cursor */
GP_SCULPT_FLAG_ENABLE_CURSOR = (1 << 4),
/* temporary invert action */
GP_SCULPT_FLAG_TMP_INVERT = (1 << 3),
GP_SCULPT_FLAG_TMP_INVERT = (1 << 5),
/* adjust radius using pen pressure */
GP_SCULPT_FLAG_PRESSURE_RADIUS = (1 << 6),
} eGP_Sculpt_Flag;
/* sculpt_mode_flag */

View File

@@ -28,6 +28,7 @@
#include "DNA_ID.h"
#include "DNA_defs.h"
#include "DNA_lanpr_types.h"
#include "DNA_listBase.h"
struct Collection;
@@ -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
@@ -78,12 +115,13 @@ typedef struct Collection {
/* Collection->flag */
enum {
COLLECTION_RESTRICT_VIEWPORT = (1 << 0), /* Disable in viewports. */
COLLECTION_RESTRICT_SELECT = (1 << 1), /* Not selectable in viewport. */
/* COLLECTION_DISABLED_DEPRECATED = (1 << 2), */ /* Not used anymore */
COLLECTION_RESTRICT_RENDER = (1 << 3), /* Disable in renders. */
COLLECTION_HAS_OBJECT_CACHE = (1 << 4), /* Runtime: object_cache is populated. */
COLLECTION_IS_MASTER = (1 << 5), /* Is master collection embedded in the scene. */
COLLECTION_RESTRICT_VIEWPORT = (1 << 0), /* Disable in viewports. */
COLLECTION_RESTRICT_SELECT = (1 << 1), /* Not selectable in viewport. */
COLLECTION_DISABLED_DEPRECATED = (1 << 2), /* Not used anymore */
COLLECTION_RESTRICT_RENDER = (1 << 3), /* Disable in renders. */
COLLECTION_HAS_OBJECT_CACHE = (1 << 4), /* Runtime: object_cache is populated. */
COLLECTION_IS_MASTER = (1 << 5), /* Is master collection embedded in the scene. */
COLLECTION_CONFIGURED_FOR_LANPR = (1 << 6), /* Configurations saved to collection->lanpr. */
};
/* Collection->tag */

View File

@@ -335,6 +335,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,126 @@
/*
* ***** 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_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;
struct DRWShadingGroup *shgrp;
struct GPUBatch *batch;
} LANPR_LineLayer;
#endif

View File

@@ -27,6 +27,11 @@
#include "DNA_object_enums.h"
#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 */
#include "DNA_customdata_types.h"
@@ -191,6 +196,40 @@ typedef struct Object_Runtime {
short _pad2[3];
} 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). */
@@ -400,6 +439,8 @@ typedef struct Object {
struct PreviewImage *preview;
ObjectLANPR lanpr;
/** Runtime evaluation data (keep last). */
Object_Runtime runtime;
} Object;

View File

@@ -29,8 +29,10 @@
/* XXX, temp feature - campbell */
#define DURIAN_CAMERA_SWITCH
#include "DNA_ID.h"
#include "DNA_collection_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "DNA_color_types.h" /* color management */
#include "DNA_curveprofile_types.h"
#include "DNA_customdata_types.h" /* Scene's runtime cddata masks. */
@@ -42,10 +44,6 @@
#include "DNA_vec_types.h"
#include "DNA_view3d_types.h"
#ifdef __cplusplus
extern "C" {
#endif
struct AnimData;
struct Brush;
struct Collection;
@@ -999,7 +997,8 @@ typedef struct UvSculpt {
/* grease pencil drawing brushes */
typedef struct GpPaint {
Paint paint;
int flag;
int flag; /* LANPR stuff */
/*struct SceneLANPR lanpr; XXX: Why this ended up here? */
/* Mode of paint (Materials or Vertex Color). */
int mode;
} GpPaint;
@@ -1061,6 +1060,27 @@ typedef enum eGP_Lockaxis_Types {
GP_LOCKAXIS_CURSOR = 4,
} eGP_Lockaxis_Types;
/* GP_Sculpt_Settings.brushtype */
typedef enum eGP_Sculpt_Types {
GP_SCULPT_TYPE_SMOOTH = 0,
GP_SCULPT_TYPE_THICKNESS = 1,
GP_SCULPT_TYPE_STRENGTH = 2,
GP_SCULPT_TYPE_GRAB = 3,
GP_SCULPT_TYPE_PUSH = 4,
GP_SCULPT_TYPE_TWIST = 5,
GP_SCULPT_TYPE_PINCH = 6,
GP_SCULPT_TYPE_RANDOMIZE = 7,
GP_SCULPT_TYPE_CLONE = 8,
GP_SCULPT_TYPE_SUBDIVIDE = 9,
GP_SCULPT_TYPE_SIMPLIFY = 10,
/* add any sculpt brush above this value */
GP_SCULPT_TYPE_WEIGHT = 11,
/* add any weight paint brush below this value. Do no mix brushes */
/* !!! Update GP_Sculpt_Data brush[###]; below !!! */
GP_SCULPT_TYPE_MAX,
} eGP_Sculpt_Types;
/* Settings for a GPencil Speed Guide */
typedef struct GP_Sculpt_Guide {
char use_guide;
@@ -1075,17 +1095,43 @@ typedef struct GP_Sculpt_Guide {
struct Object *reference_object;
} GP_Sculpt_Guide;
/* GPencil Stroke Sculpting Settings */
typedef struct GP_Sculpt_Settings {
typedef struct GP_Sculpt_Data {
/** Radius of brush. */
short size;
/** EGP_Sculpt_Flag. */
short flag;
/** Strength of effect. */
float strength;
/** Cursor color for add. */
float curcolor_add[3];
/** Cursor color for sub. */
float curcolor_sub[3];
/** Target weight. */
float weight;
char _pad[4];
} GP_Sculpt_Data;
/* GPencil Stroke Sculpting Settings */ typedef struct GP_Sculpt_Settings {
/** GP_SCULPT_TYPE_MAX. */
GP_Sculpt_Data brush[12];
/** Runtime. */
void *paintcursor;
/** #eGP_Sculpt_Types (sculpt). */
int brushtype;
/** #eGP_Sculpt_SettingsFlag. */
int flag;
/** #eGP_Lockaxis_Types lock drawing to one axis. */
int lock_axis;
/** Threshold for intersections */
float isect_threshold;
char _pad_[4];
/* weight paint is a submode of sculpt but use its own index. All weight paint
* brushes must be defined at the end of the brush array.
*/
/** #eGP_Sculpt_Types (weight paint). */
int weighttype;
char _pad[4];
/** Multiframe edit falloff effect by frame. */
struct CurveMapping *cur_falloff;
/** Curve used for primitive tools. */
@@ -1643,6 +1689,76 @@ 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_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! */
/* CPU mode */
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,
LANPR_GPU_CACHE_SIZE_8K = 4,
LANPR_GPU_CACHE_SIZE_16K = 5,
};
typedef struct SceneGpencil {
float smaa_threshold;
char _pad[4];
@@ -1779,7 +1895,11 @@ typedef struct Scene {
struct SceneDisplay display;
struct SceneEEVEE eevee;
struct SceneGpencil grease_pencil_settings;
/* LANPR stuff */
struct SceneLANPR lanpr;
} Scene;
/* **************** RENDERDATA ********************* */

View File

@@ -211,6 +211,8 @@ typedef enum eSpaceButtons_Context {
BCONTEXT_TOOL = 14,
BCONTEXT_SHADERFX = 15,
BCONTEXT_OUTPUT = 16,
BCONTEXT_COLLECTION = 17,
BCONTEXT_LANPR = 18,
/* Keep 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",
@@ -1575,6 +1576,10 @@ int main(int argc, char **argv)
#include "DNA_meshdata_types.h"
#include "DNA_meta_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"
#include "DNA_movieclip_types.h"
#include "DNA_nla_types.h"
#include "DNA_node_types.h"

View File

@@ -106,6 +106,7 @@ extern StructRNA RNA_ClothSettings;
extern StructRNA RNA_CloudsTexture;
extern StructRNA RNA_Collection;
extern StructRNA RNA_CollectionProperty;
extern StructRNA RNA_CollectionLANPR;
extern StructRNA RNA_CollisionModifier;
extern StructRNA RNA_CollisionSettings;
extern StructRNA RNA_ColorGpencilModifier;
@@ -431,6 +432,7 @@ extern StructRNA RNA_NormalEditModifier;
extern StructRNA RNA_Object;
extern StructRNA RNA_ObjectBase;
extern StructRNA RNA_ObjectDisplay;
extern StructRNA RNA_ObjectLANPR;
extern StructRNA RNA_OceanModifier;
extern StructRNA RNA_OceanTexData;
extern StructRNA RNA_OffsetGpencilModifier;
@@ -491,6 +493,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

@@ -54,6 +54,7 @@ set(DEFSRC
rna_light.c
rna_lightprobe.c
rna_linestyle.c
rna_lanpr.c
rna_main.c
rna_mask.c
rna_material.c
@@ -322,6 +323,10 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
endif()
if(WITH_OPENSUBDIV)
list(APPEND INC
../../../../intern/opensubdiv
@@ -440,6 +445,12 @@ set(LIB
bf_editor_undo
)
if(WITH_LANPR)
list(APPEND LIB
bf_editor_lanpr
)
endif()
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_rna "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@@ -4278,6 +4278,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_fluid.c", NULL, RNA_def_fluid},
{"rna_material.c", "rna_material_api.c", RNA_def_material},

View File

@@ -22,8 +22,12 @@
#include "DNA_collection_types.h"
#include "DNA_lanpr_types.h"
#include "BLI_utildefines.h"
#include "MEM_guardedalloc.h"
#include "RNA_define.h"
#include "rna_internal.h"
@@ -326,6 +330,31 @@ static void rna_Collection_flag_update(Main *bmain, Scene *scene, PointerRNA *pt
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
}
/* LANPR */
static bool rna_Collection_lanpr_configure_get(PointerRNA *ptr)
{
Collection *c = (Collection *)ptr->owner_id;
return (c->flag & COLLECTION_CONFIGURED_FOR_LANPR);
}
static void rna_Collection_lanpr_configure_set(PointerRNA *ptr, const bool value)
{
Collection *c = (Collection *)ptr->owner_id;
CollectionLANPR *lanpr = c->lanpr;
if (value) {
c->flag |= COLLECTION_CONFIGURED_FOR_LANPR;
if (!lanpr) {
lanpr = MEM_callocN(sizeof(CollectionLANPR), "CollectionLANPR");
c->lanpr = lanpr;
}
}
else { /* !value */
c->flag &= ~COLLECTION_CONFIGURED_FOR_LANPR;
/* CollectionLANPR will be deleted when collection is deleted. */
}
}
#else
/* collection.objects */
@@ -382,6 +411,131 @@ 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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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);
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
}
void RNA_def_collections(BlenderRNA *brna)
{
StructRNA *srna;
@@ -475,6 +629,18 @@ 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");
prop = RNA_def_property(srna, "configure_lanpr", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
prop, "rna_Collection_lanpr_configure_get", "rna_Collection_lanpr_configure_set");
RNA_def_property_ui_text(prop, "Configure", "Configure this collection for LANPR");
RNA_def_property_update(prop, NC_SCENE, NULL);
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

@@ -172,6 +172,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,192 @@
/*
* ***** 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);
}
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");
}
void RNA_def_lanpr(BlenderRNA *brna)
{
rna_def_lanpr_line_type(brna);
rna_def_lanpr_line_layer(brna);
}
#endif

View File

@@ -2527,6 +2527,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)
{
@@ -3286,6 +3390,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);
}
@@ -3298,6 +3407,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

@@ -32,6 +32,8 @@
#include "DNA_screen_types.h" /* TransformOrientation */
#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"
#include "DNA_screen_types.h" /* TransformOrientation */
#include "DNA_lanpr_types.h"
#include "DNA_world_types.h"
#include "IMB_imbuf_types.h"
@@ -46,6 +48,7 @@
#include "BKE_paint.h"
#include "ED_gpencil.h"
#include "ED_lanpr.h"
#include "ED_object.h"
#include "DRW_engine.h"
@@ -2579,6 +2582,66 @@ 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;
}
static bool rna_lanpr_shader_error_get(PointerRNA *UNUSED(ptr))
{
# ifdef WITH_LANPR
return ED_lanpr_dpix_shader_error();
# else
return false;
# endif
}
static char *rna_FFmpegSettings_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("render.ffmpeg");
@@ -7242,6 +7305,218 @@ static void rna_def_scene_gpencil(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
}
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"},
{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"},
{LANPR_GPU_CACHE_SIZE_8K, "S8K", 0, "8K", "8K px texture as cache"},
{LANPR_GPU_CACHE_SIZE_16K, "S16K", 0, "16K", "16K 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.1f, 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.05f, 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.1f, 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.1f, 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.1f, 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.1f, 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.1f, 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.1f, 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.01f, 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.01f, 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");
RNA_def_property_update(prop, NC_SCENE, NULL);
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");
RNA_def_property_update(prop, NC_SCENE, NULL);
/* 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", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(
prop, "DPIX Shader Error", "Can't compile DPIX transform shader on your GPU");
RNA_def_property_update(prop, NC_SCENE, NULL);
/* Below these two are only for grease pencil, thus no viewport updates. */
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.01f, 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.001f, 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");
RNA_def_property_update(prop, NC_SCENE, NULL);
/* 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", "");
RNA_def_property_update(prop, NC_SCENE, NULL);
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, 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, NULL);
}
void RNA_def_scene(BlenderRNA *brna)
{
StructRNA *srna;
@@ -7715,6 +7990,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");
/* Grease Pencil */
prop = RNA_def_property(srna, "grease_pencil_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "SceneGpencil");
@@ -7737,6 +8017,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_def_view_layer_eevee(brna);
rna_def_scene_gpencil(brna);
RNA_define_animate_sdna(true);

View File

@@ -428,13 +428,14 @@ static const EnumPropertyItem buttons_context_items[] = {
{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_COLLECTION, "COLLECTION", ICON_GROUP, "Collection", "Collection 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"},
"Object Constraints Properties"},
{BCONTEXT_MODIFIER, "MODIFIER", ICON_MODIFIER, "Modifiers", "Modifiers Properties"},
{BCONTEXT_DATA, "DATA", ICON_NONE, "Data", "Object Data Properties"},
{BCONTEXT_BONE, "BONE", ICON_BONE_DATA, "Bone", "Bone Properties"},
{BCONTEXT_BONE_CONSTRAINT,
@@ -443,6 +444,7 @@ static const EnumPropertyItem buttons_context_items[] = {
"Bone Constraints",
"Bone Constraint Properties"},
{BCONTEXT_MATERIAL, "MATERIAL", ICON_MATERIAL, "Material", "Material Properties"},
{BCONTEXT_LANPR, "LANPR", ICON_SHADING_RENDERED, "LANPR", "LANPR Properties"},
{BCONTEXT_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture Properties"},
{BCONTEXT_PARTICLE, "PARTICLES", ICON_PARTICLES, "Particles", "Particle Properties"},
{BCONTEXT_PHYSICS, "PHYSICS", ICON_PHYSICS, "Physics", "Physics Properties"},
@@ -1810,6 +1812,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);
}
@@ -1851,6 +1861,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);
}

View File

@@ -202,6 +202,10 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
if(WITH_LANPR)
add_definitions(-DWITH_LANPR)
endif()
if(WITH_IMAGE_CINEON)
add_definitions(-DWITH_CINEON)
endif()

View File

@@ -36,6 +36,7 @@ static PyStructSequence_Field app_builtopts_info_fields[] = {
{"cycles", NULL},
{"cycles_osl", NULL},
{"freestyle", NULL},
{"lanpr", NULL},
{"image_cineon", NULL},
{"image_dds", NULL},
{"image_hdr", NULL},
@@ -132,6 +133,12 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
#ifdef WITH_LANPR
SetObjIncref(Py_True);
#else
SetObjIncref(Py_False);
#endif
#ifdef WITH_CINEON
SetObjIncref(Py_True);
#else