1
1

Compare commits

...

129 Commits

Author SHA1 Message Date
2da005902f Draw: Cleanup the GLSL intersection code 2023-01-20 20:23:03 +01:00
693dffb7b7 Use smaller ObjectBounds
Only store center and size. Skip resource finalize computation.
2023-01-20 20:23:02 +01:00
aef43d1461 Merge branch 'tmp-workbench-rewrite2' into tmp-worbench-rewrite2-optimizations 2023-01-20 17:50:21 +01:00
2c432baad0 Add texture mirror extension type support (see D16432) 2023-01-19 21:00:11 +01:00
99e5f4000c Add texture usage flags 2023-01-19 21:00:11 +01:00
1b5a594a05 Fix textures after D14365
UVs are now stored as generic attributes.
2023-01-19 16:11:09 +01:00
a9d716fa0f Optimization: Draw: Avoid runtime.bb allocation for DupliObjects 2023-01-18 15:26:11 +01:00
6f28259ea3 Merge branch 'tmp-workbench-rewrite2' into tmp-worbench-rewrite2-optimizations 2023-01-17 16:14:57 +01:00
a6b383bd69 Revert "Skip bbox allocation by retrieving bounds min/max"
This reverts commit c2022d6d36.
2023-01-17 16:13:25 +01:00
c2022d6d36 Skip bbox allocation by retrieving bounds min/max 2023-01-17 16:13:17 +01:00
15f8b6bbef Don't override local variable 2023-01-17 16:08:49 +01:00
3a06bb5e45 Add Freeze Culling support 2023-01-17 16:03:02 +01:00
2c547fc7b1 Merge branch 'master' into tmp-workbench-rewrite2 2023-01-17 15:13:45 +01:00
15b2caab21 Don't create an extra handle for shadows 2023-01-16 19:23:39 +01:00
0ea4baa94d Revert "Experimental bbox cache"
This reverts commit 49e9d105f0.
2023-01-11 17:28:29 +01:00
49e9d105f0 Experimental bbox cache 2023-01-11 17:19:45 +01:00
89e114fa70 Merge branch 'tmp-workbench-rewrite2' into tmp-worbench-rewrite2-optimizations 2023-01-11 15:27:31 +01:00
b061ace748 Add explicit initializations to all classes/structs 2023-01-10 17:40:29 +01:00
f1a90deb13 Remove UNUSED macros (Needed after D16828) 2023-01-10 17:08:27 +01:00
47a629b972 Merge branch 'master' into tmp-workbench-rewrite2 2023-01-10 16:02:00 +01:00
0b013d8873 Code standards 2023-01-10 13:48:28 +01:00
8cbbfa8c29 Fix MSL compilation 2023-01-10 13:48:28 +01:00
ee51f6b3e9 Use functional type casting 2023-01-10 13:48:27 +01:00
b17578a943 Use std::swap 2023-01-10 13:48:27 +01:00
128d4104bf Remove blender:: namespace 2023-01-10 13:48:13 +01:00
8f165c390d Fix Clang compilation 2023-01-10 13:48:13 +01:00
b87ae86e3c Class separators 2023-01-10 13:48:13 +01:00
f8eb85d910 Split render output writing into their own functions 2023-01-10 13:48:13 +01:00
ed69fbadf7 Move get_dummy_gpu_materials to Instance 2023-01-10 13:48:13 +01:00
5627c8acea Replace sinf/cosf with math::sin/cos 2023-01-10 13:47:58 +01:00
9594be5eef Remove commented-out code 2023-01-09 17:46:27 +01:00
fdb4abc36d Fix workbench_next_merge depth 2023-01-09 17:46:27 +01:00
8213d1735d Fix comments style 2023-01-09 17:46:26 +01:00
4aec99931b Clarify TODO comments 2023-01-09 16:36:06 +01:00
a53e560ca5 GPU Debug Groups profiling (WIP) 2022-12-30 22:42:03 +01:00
64b87737d6 Allow disabling gpu logs when --gpu-debug is enabled (for profiling) 2022-12-30 20:07:47 +01:00
b33634f8fa Optimization: Remove unused random computation
This is most likely removed in release builds, but not on debug.
2022-12-30 17:22:03 +01:00
1b20a9d383 Optimization: Don't use glClearTexImage 2022-12-30 17:18:47 +01:00
c6ce4eed5e Optimization: Convert composite compute shader to fragment 2022-12-29 19:18:53 +01:00
5c4a5c637c MeshPass replace sub_pass_get() with draw() 2022-12-29 17:21:04 +01:00
646613c23d Optimize Workbench Next Shadows
Don't use push constants. Use the same object handle for all passes.
2022-12-29 15:48:10 +01:00
45103e3a88 Merge branch 'master' into tmp-workbench-rewrite2 2022-12-20 17:12:43 +01:00
87482b8a9e Fix GPU debug names 2022-12-20 16:38:07 +01:00
6b7160ed3b Fix GPU debug groups 2022-12-20 16:30:05 +01:00
c76d4ddf0b Cleanup comments 2022-12-19 16:27:29 +01:00
c38bdceb68 Merge branch 'master' into tmp-workbench-rewrite2 2022-12-19 15:35:22 +01:00
7bc00aeabf Workbench Next: Shadows: In front integration 2022-12-19 12:53:42 +01:00
dcdf29d936 Workbench Next: Shadows: Compute based culling
fix 1
2022-12-19 12:53:13 +01:00
97b0719f7d WIP: Compute based culling for workbench shadows 2022-12-12 12:33:50 +01:00
bc73c1cd16 add TODO 2022-12-05 19:12:58 +01:00
8cbd045a82 wbench next: fix shadows fail pass 2022-12-05 18:04:40 +01:00
6fd43f10d7 wbench next: shadows (w.i.p.) 2022-12-02 18:39:21 +01:00
d20b672e01 wbench next: render to image 2022-11-30 18:06:55 +01:00
b81e6ab2f0 Link to Workbench Next Task in user prefs 2022-11-28 21:22:00 +01:00
eec714350f Merge branch 'master' into tmp-workbench-rewrite2
# Conflicts:
#	release/scripts/startup/bl_ui/space_userpref.py
#	source/blender/draw/CMakeLists.txt
#	source/blender/draw/engines/workbench/workbench_materials.cc
#	source/blender/makesdna/DNA_userdef_types.h
2022-11-28 21:18:56 +01:00
c5ef9fc5ec Ensure the camera object is of camera type
Avoids issues when DoF is enabled. (See T101533)
2022-11-07 16:22:01 +01:00
179eadc91f clean-up and formatting 2022-11-03 20:50:39 +01:00
ae192ececd Merge branch 'master' into tmp-workbench-rewrite2 2022-11-03 19:49:20 +01:00
31cdeed916 Border Clipping 2022-11-03 19:31:16 +01:00
cf1863d990 Merge branch 'master' into tmp-workbench-rewrite2 2022-11-03 17:25:14 +01:00
77d3cd35b9 fixes after merge 2022-11-03 17:08:33 +01:00
58b26198d2 Merge branch 'master' into tmp-workbench-rewrite2 2022-11-03 16:47:28 +01:00
13573fd22c Border Clipping (wip) 2022-11-03 16:44:49 +01:00
d4cfdc6c2c split samples_len/draw_aa 2022-11-03 13:14:11 +01:00
cfc730e612 rename enum types 2022-11-02 23:39:53 +01:00
c394ad246d Move jitter_tx to SceneResources 2022-11-02 23:39:53 +01:00
2ea0ba8854 move samples and samples_len to scene_state 2022-11-02 23:39:53 +01:00
9fd51e16ed Move the outline pass to its own class and file 2022-11-02 13:11:14 +01:00
657d36c8b7 remove static GPUShaders 2022-10-31 17:53:59 +01:00
0b33068a2f remove underscores 2022-10-31 17:42:14 +01:00
4e0076daca Remove COC WIP code 2022-10-31 17:35:02 +01:00
739b3abc47 Use lowercase for static const properties 2022-10-31 17:32:39 +01:00
c69b304129 update TODO info 2022-10-31 17:19:37 +01:00
862fbf1ab2 update TODOs 2022-10-31 16:25:15 +01:00
dc0300178f use _ suffix for private variables 2022-10-31 16:02:07 +01:00
c6e42a5723 Move ObjectState out of SceneState 2022-10-31 13:31:35 +01:00
9fdf1074d9 Rename DrawConfig > SceneState, ObjectConfig > ObjectState 2022-10-31 13:04:19 +01:00
429bb7a4fd Always pass DrawConfig by referece 2022-10-31 12:28:49 +01:00
7a56cb0e8a fix crash 2022-10-28 19:32:45 +02:00
9725b83415 fix cavity + taa 2022-10-28 19:32:35 +02:00
109b1a717a DrawConfig refactor 2022-10-28 18:48:33 +02:00
d518dc411e TAA 2022-10-28 15:10:17 +02:00
2a1ad72d20 TaaSamples 2022-10-26 16:23:03 +02:00
cd67fde848 Optimize out depth_in_front_tx when possible 2022-10-26 13:24:01 +02:00
5be7f872c4 dof 2022-10-25 17:12:12 +02:00
f1038bb8ea Remove unneeded Frequency::PASS specifiers 2022-10-25 13:07:47 +02:00
114ccbccf9 Use UniformArrayBuffer for cavity_samples 2022-10-24 16:04:03 +02:00
aa3a485e9d tidier draw_mesh 2022-10-24 12:54:28 +02:00
97874b0f41 Rename TODOs 2022-10-24 12:53:18 +02:00
a3055b75fb cavity & outline (needs refactor) 2022-10-21 21:09:28 +02:00
5abcd8c8fb transparency/xray mode 2022-10-18 20:05:31 +02:00
a29d9debe4 viewport_size/viewport_size_inv 2022-10-18 12:03:20 +02:00
f90272b650 clip planes (w.i.p.) 2022-10-17 13:05:53 +02:00
af447def21 fix composite alpha 2022-10-14 18:30:00 +02:00
b6dd660903 enable workbench next on wire/solid mode too
Only if Workbench Next is the scene render engine.
(Needed for testing some features. like clip planes)
2022-10-14 17:48:38 +02:00
695ce56e06 Use stencil buffer for Opaque In Front 2022-10-14 16:24:41 +02:00
47e8fc113b Fix: Draw: Initialize StencilSet in the correct order
tmp
2022-10-14 16:24:41 +02:00
562783a9a9 Revert "Use stencil buffer for Opaque in_front"
This reverts commit 7e754023a7.
2022-10-14 12:53:07 +02:00
7e754023a7 Use stencil buffer for Opaque in_front 2022-10-14 12:51:01 +02:00
ef836b2222 OpaquePass in_front support 2022-10-14 12:24:01 +02:00
4b4ae0900d formatting 2022-10-14 12:19:43 +02:00
bb0d1781cb add roughness/metallic support for texture materials 2022-10-14 12:17:52 +02:00
6c1647a96e fix matcap normals 2022-10-14 12:14:28 +02:00
2e6c5b3075 cleanup 2022-10-13 20:44:24 +02:00
4e895f0a3a vertex and texture paint modes 2022-10-13 17:38:35 +02:00
dc5fb28c27 texture mode 2022-10-13 12:34:06 +02:00
71c1266921 improve draw mode selection 2022-10-13 12:33:50 +02:00
40945fc283 matcaps: avoid the extra copy 2022-10-11 22:50:09 +02:00
439dfabaeb matcaps 2022-10-11 21:32:30 +02:00
70a39f484f textures 2022-10-11 19:37:15 +02:00
1f64fa75e1 cleanup 2022-10-10 20:40:20 +02:00
5a10182a70 port of workbench_data.c is now complete 2022-10-10 18:08:08 +02:00
7c59b0b836 Allow passing View3DShading directly to XRAY macros
Prevents code duplication by handling View3D.shading and SceneDisplay.shading in the same code path.
2022-10-10 18:06:50 +02:00
4b65c0ad54 world orientation 2022-10-10 15:38:10 +02:00
8501e93dea Refactor
Split workbench_engine.cc into multiple files.
Move all the SceneResources loading logic directly into Instance.
2022-10-10 13:45:45 +02:00
219d5a9530 Basic vertex colors 2022-10-07 16:20:46 +02:00
ce54a09cdd Fix: Use 16F texture target for gbuffer_material
Needed for fitting the roughness/metalness using the current encoding
2022-10-07 16:10:30 +02:00
65a069b539 Revert "Fix workbench_float_pair encode/decode"
This reverts commit 79f15f68c5.
2022-10-07 16:06:04 +02:00
79f15f68c5 Fix workbench_float_pair encode/decode
Set them into the 0-1 range so they fit in unorm textures.
2022-10-07 15:49:14 +02:00
dfd61be20e Keep WorldData and WORKBENCH_UBO_World in sync 2022-10-07 13:52:31 +02:00
cde0faf4dd add support for background color 2022-10-06 20:09:18 +02:00
106c6db1b5 fix ssbo binding 2022-10-06 20:08:47 +02:00
2739e186b6 Workbench Next: Add color modes, flat shading and backface culling
Adds support for Material, Random, Single and Object color modes.
Adds flat shading support.
Adds backaface culling support.
prepass_shader_cache_ is actually used now.
2022-10-06 16:50:08 +02:00
f1851fa35c Workbench next: Render the same UI as the regular Workbench engine
Register as compat engine in the UI code.
2022-10-05 16:11:26 +02:00
71c9746ec6 Fix several bug in order to draw simple scene correctly 2022-10-05 12:39:42 +02:00
d6457310d8 Fix: Compilation issue on msvc
Since smaa_textures.h is now included in cpp compilation units, areaTexBytes and searchTexBytes must be declared as extern "C".
2022-10-05 12:32:00 +02:00
db6665813b Fix compilation and rendering errors
Now displays white canvas
2022-10-03 23:59:47 +02:00
bc28bf3681 Fix experimental option and add SMAA 2022-10-03 16:46:24 +02:00
43dad4d9b1 WORKBENCH: Rewrite using the new Draw Manager API
This adds a new experimental option for testing the new rewrite.

This is a full rewrite using C++ and using the new DRW API.
This tries to simplify each aspect of the engine:
- Materials are put in SSBOs.
- Only one shader per pass.

The goal is to leverage the new DRW capabilities in term of GPU culling
and drawcall batching.
2022-10-03 13:33:20 +02:00
96 changed files with 5041 additions and 724 deletions

View File

@@ -248,7 +248,7 @@ class DATA_PT_motion_paths_display(MotionPathButtonsPanel_display, Panel):
class DATA_PT_custom_props_arm(ArmatureButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.data"
_property_type = bpy.types.Armature

View File

@@ -444,7 +444,7 @@ class BONE_PT_deform(BoneButtonsPanel, Panel):
class BONE_PT_custom_props(BoneButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_property_type = bpy.types.Bone, bpy.types.EditBone, bpy.types.PoseBone
@property

View File

@@ -21,7 +21,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
class SAFE_AREAS_PT_presets(PresetPanel, Panel):
@@ -29,13 +29,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
class DATA_PT_context_camera(CameraButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -52,7 +52,7 @@ class DATA_PT_context_camera(CameraButtonsPanel, Panel):
class DATA_PT_lens(CameraButtonsPanel, Panel):
bl_label = "Lens"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -100,7 +100,7 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
col.prop(ccam, "fisheye_polynomial_k3", text="K3")
col.prop(ccam, "fisheye_polynomial_k4", text="K4")
elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}:
elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}:
if cam.lens_unit == 'MILLIMETERS':
col.prop(cam, "lens")
elif cam.lens_unit == 'FOV':
@@ -122,7 +122,7 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
bl_label = "Stereoscopy"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -171,7 +171,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header_preset(self, _context):
CAMERA_PT_presets.draw_panel_header(self.layout)
@@ -201,7 +201,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
cam = context.camera
@@ -228,7 +228,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -252,7 +252,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
cam = context.camera
@@ -359,7 +359,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -392,7 +392,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -419,7 +419,7 @@ class DATA_PT_camera_display_composition_guides(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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
cam = context.camera
@@ -449,7 +449,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
cam = context.camera
@@ -473,7 +473,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.data"
_property_type = bpy.types.Camera

View File

@@ -116,7 +116,7 @@ class DATA_PT_shape_curve(CurveButtonsPanel, Panel):
class DATA_PT_curve_texture_space(CurveButtonsPanel, Panel):
bl_label = "Texture Space"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -475,7 +475,7 @@ class DATA_PT_text_boxes(CurveButtonsPanelText, Panel):
class DATA_PT_custom_props_curve(CurveButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.data"
_property_type = bpy.types.Curve

View File

@@ -18,7 +18,7 @@ class DataButtonsPanel:
class DATA_PT_context_curves(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -35,7 +35,7 @@ class DATA_PT_context_curves(DataButtonsPanel, Panel):
class DATA_PT_curves_surface(DataButtonsPanel, Panel):
bl_label = "Surface"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -118,7 +118,7 @@ class CURVES_UL_attributes(UIList):
class DATA_PT_CURVES_attributes(DataButtonsPanel, Panel):
bl_label = "Attributes"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
curves = context.curves
@@ -143,7 +143,7 @@ class DATA_PT_CURVES_attributes(DataButtonsPanel, Panel):
class DATA_PT_custom_props_curves(DataButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.data"
_property_type = bpy.types.Curves if hasattr(bpy.types, "Curves") else None

View File

@@ -64,7 +64,7 @@ class DATA_PT_lattice(DataButtonsPanel, Panel):
class DATA_PT_custom_props_lattice(DataButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.data"
_property_type = bpy.types.Lattice

View File

@@ -18,7 +18,7 @@ class DataButtonsPanel:
class DATA_PT_context_light(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE_NEXT', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE_NEXT', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -44,7 +44,7 @@ class DATA_PT_preview(DataButtonsPanel, Panel):
class DATA_PT_light(DataButtonsPanel, Panel):
bl_label = "Light"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -230,7 +230,7 @@ class DATA_PT_EEVEE_shadow_contact(DataButtonsPanel, Panel):
class DATA_PT_spot(DataButtonsPanel, Panel):
bl_label = "Spot Shape"
bl_parent_id = "DATA_PT_EEVEE_light"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE_NEXT', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE_NEXT', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -275,7 +275,7 @@ class DATA_PT_falloff_curve(DataButtonsPanel, Panel):
class DATA_PT_custom_props_light(DataButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE_NEXT', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE_NEXT', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.data"
_property_type = bpy.types.Light

View File

@@ -171,7 +171,7 @@ class MeshButtonsPanel:
class DATA_PT_context_mesh(MeshButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -189,7 +189,7 @@ class DATA_PT_context_mesh(MeshButtonsPanel, Panel):
class DATA_PT_normals(MeshButtonsPanel, Panel):
bl_label = "Normals"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -211,7 +211,7 @@ class DATA_PT_normals(MeshButtonsPanel, Panel):
class DATA_PT_texture_space(MeshButtonsPanel, Panel):
bl_label = "Texture Space"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -231,7 +231,7 @@ class DATA_PT_texture_space(MeshButtonsPanel, Panel):
class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
bl_label = "Vertex Groups"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -288,7 +288,7 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
class DATA_PT_face_maps(MeshButtonsPanel, Panel):
bl_label = "Face Maps"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -331,7 +331,7 @@ class DATA_PT_face_maps(MeshButtonsPanel, Panel):
class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
bl_label = "Shape Keys"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -428,7 +428,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
bl_label = "UV Maps"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -448,7 +448,7 @@ class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
class DATA_PT_remesh(MeshButtonsPanel, Panel):
bl_label = "Remesh"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -478,7 +478,7 @@ class DATA_PT_remesh(MeshButtonsPanel, Panel):
class DATA_PT_customdata(MeshButtonsPanel, Panel):
bl_label = "Geometry Data"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -519,7 +519,7 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.data"
_property_type = bpy.types.Mesh
@@ -568,7 +568,7 @@ class MESH_UL_attributes(UIList):
class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
bl_label = "Attributes"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
mesh = context.mesh
@@ -692,7 +692,7 @@ class MESH_UL_color_attributes_selector(UIList, ColorAttributesListBase):
class DATA_PT_vertex_colors(DATA_PT_mesh_attributes, Panel):
bl_label = "Color Attributes"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
mesh = context.mesh

View File

@@ -56,7 +56,7 @@ class DATA_PT_metaball(DataButtonsPanel, Panel):
class DATA_PT_mball_texture_space(DataButtonsPanel, Panel):
bl_label = "Texture Space"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -111,7 +111,7 @@ class DATA_PT_metaball_element(DataButtonsPanel, Panel):
class DATA_PT_custom_props_metaball(DataButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.data"
_property_type = bpy.types.MetaBall

View File

@@ -18,7 +18,7 @@ class DataButtonsPanel:
class DATA_PT_context_pointcloud(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -97,7 +97,7 @@ class POINTCLOUD_UL_attributes(UIList):
class DATA_PT_pointcloud_attributes(DataButtonsPanel, Panel):
bl_label = "Attributes"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
pointcloud = context.pointcloud
@@ -122,7 +122,7 @@ class DATA_PT_pointcloud_attributes(DataButtonsPanel, Panel):
class DATA_PT_custom_props_pointcloud(DataButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.data"
_property_type = bpy.types.PointCloud if hasattr(bpy.types, "PointCloud") else None

View File

@@ -18,7 +18,7 @@ class DataButtonsPanel:
class DATA_PT_context_speaker(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -35,7 +35,7 @@ class DATA_PT_context_speaker(DataButtonsPanel, Panel):
class DATA_PT_speaker(DataButtonsPanel, Panel):
bl_label = "Sound"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -57,7 +57,7 @@ class DATA_PT_speaker(DataButtonsPanel, Panel):
class DATA_PT_distance(DataButtonsPanel, Panel):
bl_label = "Distance"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -81,7 +81,7 @@ class DATA_PT_distance(DataButtonsPanel, Panel):
class DATA_PT_cone(DataButtonsPanel, Panel):
bl_label = "Cone"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -103,7 +103,7 @@ class DATA_PT_cone(DataButtonsPanel, Panel):
class DATA_PT_custom_props_speaker(DataButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.data"
_property_type = bpy.types.Speaker

View File

@@ -18,7 +18,7 @@ class DataButtonsPanel:
class DATA_PT_context_volume(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -35,7 +35,7 @@ class DATA_PT_context_volume(DataButtonsPanel, Panel):
class DATA_PT_volume_file(DataButtonsPanel, Panel):
bl_label = "OpenVDB File"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -80,7 +80,7 @@ class VOLUME_UL_grids(UIList):
class DATA_PT_volume_grids(DataButtonsPanel, Panel):
bl_label = "Grids"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -93,7 +93,7 @@ class DATA_PT_volume_grids(DataButtonsPanel, Panel):
class DATA_PT_volume_render(DataButtonsPanel, Panel):
bl_label = "Render"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -125,7 +125,7 @@ class DATA_PT_volume_render(DataButtonsPanel, Panel):
class DATA_PT_volume_viewport_display(DataButtonsPanel, Panel):
bl_label = "Viewport Display"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -149,7 +149,7 @@ class DATA_PT_volume_viewport_display(DataButtonsPanel, Panel):
class DATA_PT_volume_viewport_display_slicing(DataButtonsPanel, Panel):
bl_label = ""
bl_parent_id = 'DATA_PT_volume_viewport_display'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
layout = self.layout
@@ -175,7 +175,7 @@ class DATA_PT_volume_viewport_display_slicing(DataButtonsPanel, Panel):
class DATA_PT_custom_props_volume(DataButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.data"
_property_type = bpy.types.Volume

View File

@@ -21,7 +21,7 @@ class RENDER_PT_freestyle(RenderFreestyleButtonsPanel, Panel):
bl_label = "Freestyle"
bl_options = {'DEFAULT_CLOSED'}
bl_order = 10
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
rd = context.scene.render
@@ -79,7 +79,7 @@ class ViewLayerFreestyleEditorButtonsPanel(ViewLayerFreestyleButtonsPanel):
class ViewLayerFreestyleLineStyle(ViewLayerFreestyleEditorButtonsPanel):
# Freestyle Linestyle Panels
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -123,7 +123,7 @@ class RENDER_MT_lineset_context_menu(Menu):
class VIEWLAYER_PT_freestyle(ViewLayerFreestyleButtonsPanel, Panel):
bl_label = "Freestyle"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
view_layer = context.view_layer
@@ -153,7 +153,7 @@ class VIEWLAYER_PT_freestyle(ViewLayerFreestyleButtonsPanel, Panel):
class VIEWLAYER_PT_freestyle_edge_detection(ViewLayerFreestyleButtonsPanel, Panel):
bl_label = "Edge Detection"
bl_parent_id = "VIEWLAYER_PT_freestyle"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -183,7 +183,7 @@ class VIEWLAYER_PT_freestyle_edge_detection(ViewLayerFreestyleButtonsPanel, Pane
class VIEWLAYER_PT_freestyle_style_modules(ViewLayerFreestyleButtonsPanel, Panel):
bl_label = "Style Modules"
bl_parent_id = "VIEWLAYER_PT_freestyle"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -219,7 +219,7 @@ class VIEWLAYER_PT_freestyle_style_modules(ViewLayerFreestyleButtonsPanel, Panel
class VIEWLAYER_PT_freestyle_lineset(ViewLayerFreestyleEditorButtonsPanel, Panel):
bl_label = "Freestyle Line Set"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_edge_type_buttons(self, box, lineset, edge_type):
# property names
@@ -282,7 +282,7 @@ class VIEWLAYER_PT_freestyle_lineset(ViewLayerFreestyleEditorButtonsPanel, Panel
class VIEWLAYER_PT_freestyle_lineset_visibilty(ViewLayerFreestyleLineStyle, Panel):
bl_label = "Visibility"
bl_parent_id = "VIEWLAYER_PT_freestyle_lineset"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
layout = self.layout
@@ -316,7 +316,7 @@ class VIEWLAYER_PT_freestyle_lineset_visibilty(ViewLayerFreestyleLineStyle, Pane
class VIEWLAYER_PT_freestyle_lineset_edgetype(ViewLayerFreestyleLineStyle, Panel):
bl_label = "Edge Type"
bl_parent_id = "VIEWLAYER_PT_freestyle_lineset"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
layout = self.layout
@@ -366,7 +366,7 @@ class VIEWLAYER_PT_freestyle_lineset_edgetype(ViewLayerFreestyleLineStyle, Panel
class VIEWLAYER_PT_freestyle_lineset_facemarks(ViewLayerFreestyleLineStyle, Panel):
bl_label = "Face Marks"
bl_parent_id = "VIEWLAYER_PT_freestyle_lineset"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
@@ -395,7 +395,7 @@ class VIEWLAYER_PT_freestyle_lineset_facemarks(ViewLayerFreestyleLineStyle, Pane
class VIEWLAYER_PT_freestyle_lineset_collection(ViewLayerFreestyleLineStyle, Panel):
bl_label = "Collection"
bl_parent_id = "VIEWLAYER_PT_freestyle_lineset"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
@@ -1236,7 +1236,7 @@ class MaterialFreestyleButtonsPanel:
class MATERIAL_PT_freestyle_line(MaterialFreestyleButtonsPanel, Panel):
bl_label = "Freestyle Line"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout

View File

@@ -60,7 +60,7 @@ class MATERIAL_PT_preview(MaterialButtonsPanel, Panel):
class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "material"
_property_type = bpy.types.Material
@@ -69,7 +69,7 @@ class EEVEE_MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
bl_label = ""
bl_context = "material"
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):

View File

@@ -228,7 +228,7 @@ class MATERIAL_PT_gpencil_preview(GPMaterialButtonsPanel, Panel):
class MATERIAL_PT_gpencil_custom_props(GPMaterialButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object.active_material"
_property_type = bpy.types.Material

View File

@@ -366,7 +366,7 @@ class OBJECT_PT_motion_paths_display(MotionPathButtonsPanel_display, Panel):
class OBJECT_PT_visibility(ObjectButtonsPanel, Panel):
bl_label = "Visibility"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -395,7 +395,7 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel):
class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "object"
_property_type = bpy.types.Object

View File

@@ -42,7 +42,7 @@ class RenderOutputButtonsPanel:
class RENDER_PT_format(RenderOutputButtonsPanel, Panel):
bl_label = "Format"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_frame_rate_args_prev = None
_preset_class = None
@@ -120,7 +120,7 @@ class RENDER_PT_format(RenderOutputButtonsPanel, Panel):
class RENDER_PT_frame_range(RenderOutputButtonsPanel, Panel):
bl_label = "Frame Range"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -139,7 +139,7 @@ class RENDER_PT_time_stretching(RenderOutputButtonsPanel, Panel):
bl_label = "Time Stretching"
bl_parent_id = "RENDER_PT_frame_range"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -156,7 +156,7 @@ class RENDER_PT_time_stretching(RenderOutputButtonsPanel, Panel):
class RENDER_PT_post_processing(RenderOutputButtonsPanel, Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -174,7 +174,7 @@ class RENDER_PT_post_processing(RenderOutputButtonsPanel, Panel):
class RENDER_PT_stamp(RenderOutputButtonsPanel, Panel):
bl_label = "Metadata"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -208,7 +208,7 @@ class RENDER_PT_stamp_note(RenderOutputButtonsPanel, Panel):
bl_label = "Note"
bl_parent_id = "RENDER_PT_stamp"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
rd = context.scene.render
@@ -228,7 +228,7 @@ class RENDER_PT_stamp_burn(RenderOutputButtonsPanel, Panel):
bl_label = "Burn Into Image"
bl_parent_id = "RENDER_PT_stamp"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
rd = context.scene.render
@@ -252,7 +252,7 @@ class RENDER_PT_stamp_burn(RenderOutputButtonsPanel, Panel):
class RENDER_PT_output(RenderOutputButtonsPanel, Panel):
bl_label = "Output"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -281,7 +281,7 @@ class RENDER_PT_output(RenderOutputButtonsPanel, Panel):
class RENDER_PT_output_views(RenderOutputButtonsPanel, Panel):
bl_label = "Views"
bl_parent_id = "RENDER_PT_output"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -301,7 +301,7 @@ class RENDER_PT_output_color_management(RenderOutputButtonsPanel, Panel):
bl_label = "Color Management"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "RENDER_PT_output"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
scene = context.scene
@@ -336,7 +336,7 @@ class RENDER_PT_encoding(RenderOutputButtonsPanel, Panel):
bl_label = "Encoding"
bl_parent_id = "RENDER_PT_output"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header_preset(self, _context):
RENDER_PT_ffmpeg_presets.draw_panel_header(self.layout)
@@ -361,7 +361,7 @@ class RENDER_PT_encoding(RenderOutputButtonsPanel, Panel):
class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel):
bl_label = "Video"
bl_parent_id = "RENDER_PT_encoding"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -437,7 +437,7 @@ class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel):
class RENDER_PT_encoding_audio(RenderOutputButtonsPanel, Panel):
bl_label = "Audio"
bl_parent_id = "RENDER_PT_encoding"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -479,7 +479,7 @@ class RENDER_UL_renderviews(UIList):
class RENDER_PT_stereoscopy(RenderOutputButtonsPanel, Panel):
bl_label = "Stereoscopy"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):

View File

@@ -52,7 +52,7 @@ def particle_get_settings(context):
class PARTICLE_MT_context_menu(Menu):
bl_label = "Particle Specials"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -92,7 +92,7 @@ class PARTICLE_PT_hair_dynamics_presets(PresetPanel, Panel):
preset_subdir = "hair_dynamics"
preset_operator = "script.execute_preset"
preset_add_operator = "particle.hair_dynamics_preset_add"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
class ParticleButtonsPanel:
@@ -146,7 +146,7 @@ class PARTICLE_UL_particle_systems(bpy.types.UIList):
class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -240,7 +240,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
bl_label = "Emission"
bl_translation_context = i18n_contexts.id_particlesettings
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -292,7 +292,7 @@ class PARTICLE_PT_emission_source(ParticleButtonsPanel, Panel):
bl_label = "Source"
bl_parent_id = "PARTICLE_PT_emission"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -329,7 +329,7 @@ class PARTICLE_PT_emission_source(ParticleButtonsPanel, Panel):
class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
bl_label = "Hair Dynamics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -412,7 +412,7 @@ class PARTICLE_PT_hair_dynamics_collision(ParticleButtonsPanel, Panel):
bl_label = "Collisions"
bl_parent_id = "PARTICLE_PT_hair_dynamics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -444,7 +444,7 @@ class PARTICLE_PT_hair_dynamics_structure(ParticleButtonsPanel, Panel):
bl_label = "Structure"
bl_parent_id = "PARTICLE_PT_hair_dynamics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -475,7 +475,7 @@ class PARTICLE_PT_hair_dynamics_volume(ParticleButtonsPanel, Panel):
bl_label = "Volume"
bl_parent_id = "PARTICLE_PT_hair_dynamics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -506,7 +506,7 @@ class PARTICLE_PT_hair_dynamics_volume(ParticleButtonsPanel, Panel):
class PARTICLE_PT_cache(ParticleButtonsPanel, Panel):
bl_label = "Cache"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -539,7 +539,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel, Panel):
class PARTICLE_PT_velocity(ParticleButtonsPanel, Panel):
bl_label = "Velocity"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -588,7 +588,7 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel, Panel):
class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel):
bl_label = "Rotation"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -643,7 +643,7 @@ class PARTICLE_PT_rotation_angular_velocity(ParticleButtonsPanel, Panel):
bl_label = "Angular Velocity"
bl_parent_id = "PARTICLE_PT_rotation"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -668,7 +668,7 @@ class PARTICLE_PT_rotation_angular_velocity(ParticleButtonsPanel, Panel):
class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
bl_label = "Physics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -721,7 +721,7 @@ class PARTICLE_PT_physics_fluid_advanced(ParticleButtonsPanel, Panel):
bl_label = "Advanced"
bl_parent_id = "PARTICLE_PT_physics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -766,7 +766,7 @@ class PARTICLE_PT_physics_fluid_springs(ParticleButtonsPanel, Panel):
bl_label = "Springs"
bl_parent_id = "PARTICLE_PT_physics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -790,7 +790,7 @@ class PARTICLE_PT_physics_fluid_springs_viscoelastic(ParticleButtonsPanel, Panel
bl_label = "Viscoelastic Springs"
bl_parent_id = "PARTICLE_PT_physics_fluid_springs"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -826,7 +826,7 @@ class PARTICLE_PT_physics_fluid_springs_advanced(ParticleButtonsPanel, Panel):
bl_label = "Advanced"
bl_parent_id = "PARTICLE_PT_physics_fluid_springs"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -850,7 +850,7 @@ class PARTICLE_PT_physics_boids_movement(ParticleButtonsPanel, Panel):
bl_label = "Movement"
bl_parent_id = "PARTICLE_PT_physics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -903,7 +903,7 @@ class PARTICLE_PT_physics_boids_battle(ParticleButtonsPanel, Panel):
bl_label = "Battle"
bl_parent_id = "PARTICLE_PT_physics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -930,7 +930,7 @@ class PARTICLE_PT_physics_boids_misc(ParticleButtonsPanel, Panel):
bl_label = "Misc"
bl_parent_id = "PARTICLE_PT_physics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -955,7 +955,7 @@ class PARTICLE_PT_physics_relations(ParticleButtonsPanel, Panel):
bl_label = "Relations"
bl_parent_id = "PARTICLE_PT_physics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1010,7 +1010,7 @@ class PARTICLE_PT_physics_fluid_interaction(ParticleButtonsPanel, Panel):
bl_label = "Fluid Interaction"
bl_parent_id = "PARTICLE_PT_physics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1051,7 +1051,7 @@ class PARTICLE_PT_physics_deflection(ParticleButtonsPanel, Panel):
bl_label = "Deflection"
bl_parent_id = "PARTICLE_PT_physics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1077,7 +1077,7 @@ class PARTICLE_PT_physics_deflection(ParticleButtonsPanel, Panel):
class PARTICLE_PT_physics_forces(ParticleButtonsPanel, Panel):
bl_label = "Forces"
bl_parent_id = "PARTICLE_PT_physics"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1104,7 +1104,7 @@ class PARTICLE_PT_physics_integration(ParticleButtonsPanel, Panel):
bl_label = "Integration"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "PARTICLE_PT_physics"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1138,7 +1138,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "PARTICLE_PT_physics"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1236,7 +1236,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
bl_label = "Render"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1283,7 +1283,7 @@ class PARTICLE_PT_render_extra(ParticleButtonsPanel, Panel):
bl_label = "Extra"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1307,7 +1307,7 @@ class PARTICLE_PT_render_extra(ParticleButtonsPanel, Panel):
class PARTICLE_PT_render_path(ParticleButtonsPanel, Panel):
bl_label = "Path"
bl_parent_id = "PARTICLE_PT_render"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1329,7 +1329,7 @@ class PARTICLE_PT_render_path_timing(ParticleButtonsPanel, Panel):
bl_label = "Timing"
bl_parent_id = "PARTICLE_PT_render"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1357,7 +1357,7 @@ class PARTICLE_PT_render_path_timing(ParticleButtonsPanel, Panel):
class PARTICLE_PT_render_object(ParticleButtonsPanel, Panel):
bl_label = "Object"
bl_parent_id = "PARTICLE_PT_render"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1382,7 +1382,7 @@ class PARTICLE_PT_render_object(ParticleButtonsPanel, Panel):
class PARTICLE_PT_render_collection(ParticleButtonsPanel, Panel):
bl_label = "Collection"
bl_parent_id = "PARTICLE_PT_render"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1412,7 +1412,7 @@ class PARTICLE_PT_render_collection_use_count(ParticleButtonsPanel, Panel):
bl_label = "Use Count"
bl_parent_id = "PARTICLE_PT_render_collection"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1460,7 +1460,7 @@ class PARTICLE_PT_render_collection_use_count(ParticleButtonsPanel, Panel):
class PARTICLE_PT_draw(ParticleButtonsPanel, Panel):
bl_label = "Viewport Display"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1519,7 +1519,7 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
bl_label = "Children"
bl_translation_context = i18n_contexts.id_particlesettings
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1572,7 +1572,7 @@ class PARTICLE_PT_children_parting(ParticleButtonsPanel, Panel):
bl_label = "Parting"
bl_parent_id = "PARTICLE_PT_children"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1603,7 +1603,7 @@ class PARTICLE_PT_children_clumping(ParticleButtonsPanel, Panel):
bl_label = "Clumping"
bl_parent_id = "PARTICLE_PT_children"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1639,7 +1639,7 @@ class PARTICLE_PT_children_clumping_noise(ParticleButtonsPanel, Panel):
bl_label = "Clump Noise"
bl_parent_id = "PARTICLE_PT_children_clumping"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
@@ -1663,7 +1663,7 @@ class PARTICLE_PT_children_roughness(ParticleButtonsPanel, Panel):
bl_translation_context = i18n_contexts.id_particlesettings
bl_parent_id = "PARTICLE_PT_children"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1704,7 +1704,7 @@ class PARTICLE_PT_children_kink(ParticleButtonsPanel, Panel):
bl_label = "Kink"
bl_parent_id = "PARTICLE_PT_children"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1754,7 +1754,7 @@ class PARTICLE_PT_children_kink(ParticleButtonsPanel, Panel):
class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel):
bl_label = "Field Weights"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1775,7 +1775,7 @@ class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel):
class PARTICLE_PT_force_fields(ParticleButtonsPanel, Panel):
bl_label = "Force Field Settings"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -1791,7 +1791,7 @@ class PARTICLE_PT_force_fields(ParticleButtonsPanel, Panel):
class PARTICLE_PT_force_fields_type1(ParticleButtonsPanel, Panel):
bl_label = "Type 1"
bl_parent_id = "PARTICLE_PT_force_fields"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -1808,7 +1808,7 @@ class PARTICLE_PT_force_fields_type1(ParticleButtonsPanel, Panel):
class PARTICLE_PT_force_fields_type2(ParticleButtonsPanel, Panel):
bl_label = "Type 2"
bl_parent_id = "PARTICLE_PT_force_fields"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -1826,7 +1826,7 @@ class PARTICLE_PT_force_fields_type1_falloff(ParticleButtonsPanel, Panel):
bl_label = "Falloff"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "PARTICLE_PT_force_fields_type1"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -1842,7 +1842,7 @@ class PARTICLE_PT_force_fields_type2_falloff(ParticleButtonsPanel, Panel):
bl_label = "Falloff"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "PARTICLE_PT_force_fields_type2"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -1857,7 +1857,7 @@ class PARTICLE_PT_force_fields_type2_falloff(ParticleButtonsPanel, Panel):
class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel):
bl_label = "Vertex Groups"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1946,7 +1946,7 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel):
class PARTICLE_PT_textures(ParticleButtonsPanel, Panel):
bl_label = "Textures"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1978,7 +1978,7 @@ class PARTICLE_PT_textures(ParticleButtonsPanel, Panel):
class PARTICLE_PT_hair_shape(ParticleButtonsPanel, Panel):
bl_label = "Hair Shape"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -2006,7 +2006,7 @@ class PARTICLE_PT_hair_shape(ParticleButtonsPanel, Panel):
class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "particle_system.settings"
_property_type = bpy.types.ParticleSettings

View File

@@ -35,7 +35,7 @@ class PhysicButtonsPanel:
class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
bl_label = "Cloth"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header_preset(self, _context):
CLOTH_PT_presets.draw_panel_header(self.layout)
@@ -60,7 +60,7 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_physical_properties(PhysicButtonsPanel, Panel):
bl_label = "Physical Properties"
bl_parent_id = 'PHYSICS_PT_cloth'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -84,7 +84,7 @@ class PHYSICS_PT_cloth_physical_properties(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
bl_label = "Stiffness"
bl_parent_id = 'PHYSICS_PT_cloth_physical_properties'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -115,7 +115,7 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_damping(PhysicButtonsPanel, Panel):
bl_label = "Damping"
bl_parent_id = 'PHYSICS_PT_cloth_physical_properties'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -146,7 +146,7 @@ class PHYSICS_PT_cloth_damping(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_internal_springs(PhysicButtonsPanel, Panel):
bl_label = "Internal Springs"
bl_parent_id = 'PHYSICS_PT_cloth_physical_properties'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
cloth = context.cloth.settings
@@ -188,7 +188,7 @@ class PHYSICS_PT_cloth_internal_springs(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_pressure(PhysicButtonsPanel, Panel):
bl_label = "Pressure"
bl_parent_id = 'PHYSICS_PT_cloth_physical_properties'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
cloth = context.cloth.settings
@@ -232,7 +232,7 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel):
bl_label = "Cache"
bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
md = context.cloth
@@ -243,7 +243,7 @@ class PHYSICS_PT_cloth_shape(PhysicButtonsPanel, Panel):
bl_label = "Shape"
bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -293,7 +293,7 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
bl_label = "Collisions"
bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -313,7 +313,7 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_object_collision(PhysicButtonsPanel, Panel):
bl_label = "Object Collisions"
bl_parent_id = 'PHYSICS_PT_cloth_collision'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
cloth = context.cloth.collision_settings
@@ -349,7 +349,7 @@ class PHYSICS_PT_cloth_object_collision(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cloth_self_collision(PhysicButtonsPanel, Panel):
bl_label = "Self Collisions"
bl_parent_id = 'PHYSICS_PT_cloth_collision'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
cloth = context.cloth.collision_settings
@@ -386,7 +386,7 @@ class PHYSICS_PT_cloth_property_weights(PhysicButtonsPanel, Panel):
bl_label = "Property Weights"
bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -440,7 +440,7 @@ class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel):
bl_label = "Field Weights"
bl_parent_id = 'PHYSICS_PT_cloth'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
cloth = context.cloth.settings

View File

@@ -50,7 +50,7 @@ def physics_add_special(layout, data, name, addop, removeop, typeicon):
class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout

View File

@@ -83,7 +83,7 @@ class PhysicButtonsPanel:
class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
bl_label = "Dynamic Paint"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -104,7 +104,7 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
class PHYSICS_PT_dynamic_paint_settings(PhysicButtonsPanel, Panel):
bl_label = "Settings"
bl_parent_id = 'PHYSICS_PT_dynamic_paint'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -188,7 +188,7 @@ class PHYSICS_PT_dynamic_paint_settings(PhysicButtonsPanel, Panel):
class PHYSICS_PT_dp_surface_canvas(PhysicButtonsPanel, Panel):
bl_label = "Surface"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -251,7 +251,7 @@ class PHYSICS_PT_dp_surface_canvas_paint_dry(PhysicButtonsPanel, Panel):
bl_label = "Dry"
bl_parent_id = "PHYSICS_PT_dp_surface_canvas"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -287,7 +287,7 @@ class PHYSICS_PT_dp_surface_canvas_paint_dissolve(PhysicButtonsPanel, Panel):
bl_label = "Dissolve"
bl_parent_id = "PHYSICS_PT_dp_surface_canvas"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -324,7 +324,7 @@ class PHYSICS_PT_dp_canvas_output(PhysicButtonsPanel, Panel):
bl_label = "Output"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -400,7 +400,7 @@ class PHYSICS_PT_dp_canvas_output_paintmaps(PhysicButtonsPanel, Panel):
bl_label = "Paintmaps"
bl_parent_id = "PHYSICS_PT_dp_canvas_output"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -430,7 +430,7 @@ class PHYSICS_PT_dp_canvas_output_wetmaps(PhysicButtonsPanel, Panel):
bl_label = "Wetmaps"
bl_parent_id = "PHYSICS_PT_dp_canvas_output"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -460,7 +460,7 @@ class PHYSICS_PT_dp_canvas_initial_color(PhysicButtonsPanel, Panel):
bl_label = "Initial Color"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -500,7 +500,7 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel):
bl_label = "Effects"
bl_parent_id = 'PHYSICS_PT_dynamic_paint'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -517,7 +517,7 @@ class PHYSICS_PT_dp_effects_spread(PhysicButtonsPanel, Panel):
bl_label = "Spread"
bl_parent_id = "PHYSICS_PT_dp_effects"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -552,7 +552,7 @@ class PHYSICS_PT_dp_effects_drip(PhysicButtonsPanel, Panel):
bl_label = "Drip"
bl_parent_id = "PHYSICS_PT_dp_effects"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -588,7 +588,7 @@ class PHYSICS_PT_dp_effects_drip_weights(PhysicButtonsPanel, Panel):
bl_label = "Weights"
bl_parent_id = "PHYSICS_PT_dp_effects_drip"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -612,7 +612,7 @@ class PHYSICS_PT_dp_effects_shrink(PhysicButtonsPanel, Panel):
bl_label = "Shrink"
bl_parent_id = "PHYSICS_PT_dp_effects"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -642,7 +642,7 @@ class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel):
bl_label = "Cache"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -662,7 +662,7 @@ class PHYSICS_PT_dp_cache(PhysicButtonsPanel, Panel):
class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
bl_label = "Source"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -725,7 +725,7 @@ class PHYSICS_PT_dp_brush_source(PhysicButtonsPanel, Panel):
class PHYSICS_PT_dp_brush_source_color_ramp(PhysicButtonsPanel, Panel):
bl_label = "Falloff Ramp"
bl_parent_id = "PHYSICS_PT_dp_brush_source"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -752,7 +752,7 @@ class PHYSICS_PT_dp_brush_velocity(PhysicButtonsPanel, Panel):
bl_label = "Velocity"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -783,7 +783,7 @@ class PHYSICS_PT_dp_brush_velocity_color_ramp(PhysicButtonsPanel, Panel):
bl_label = "Ramp"
bl_parent_id = "PHYSICS_PT_dp_brush_velocity"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -804,7 +804,7 @@ class PHYSICS_PT_dp_brush_velocity_smudge(PhysicButtonsPanel, Panel):
bl_label = "Smudge"
bl_parent_id = "PHYSICS_PT_dp_brush_velocity"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -832,7 +832,7 @@ class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, Panel):
bl_label = "Waves"
bl_parent_id = "PHYSICS_PT_dynamic_paint"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):

View File

@@ -27,7 +27,7 @@ class PhysicButtonsPanel:
class PHYSICS_PT_field(PhysicButtonsPanel, Panel):
bl_label = "Force Fields"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -49,7 +49,7 @@ class PHYSICS_PT_field(PhysicButtonsPanel, Panel):
class PHYSICS_PT_field_settings(PhysicButtonsPanel, Panel):
bl_label = "Settings"
bl_parent_id = 'PHYSICS_PT_field'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -136,7 +136,7 @@ class PHYSICS_PT_field_settings(PhysicButtonsPanel, Panel):
class PHYSICS_PT_field_settings_kink(PhysicButtonsPanel, Panel):
bl_label = "Kink"
bl_parent_id = 'PHYSICS_PT_field_settings'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -170,7 +170,7 @@ class PHYSICS_PT_field_settings_kink(PhysicButtonsPanel, Panel):
class PHYSICS_PT_field_settings_texture_select(PhysicButtonsPanel, Panel):
bl_label = "Texture"
bl_parent_id = 'PHYSICS_PT_field_settings'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -192,7 +192,7 @@ class PHYSICS_PT_field_settings_texture_select(PhysicButtonsPanel, Panel):
class PHYSICS_PT_field_falloff(PhysicButtonsPanel, Panel):
bl_label = "Falloff"
bl_parent_id = "PHYSICS_PT_field"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -217,7 +217,7 @@ class PHYSICS_PT_field_falloff(PhysicButtonsPanel, Panel):
class PHYSICS_PT_field_falloff_angular(PhysicButtonsPanel, Panel):
bl_label = "Angular"
bl_parent_id = "PHYSICS_PT_field_falloff"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -256,7 +256,7 @@ class PHYSICS_PT_field_falloff_angular(PhysicButtonsPanel, Panel):
class PHYSICS_PT_field_falloff_radial(PhysicButtonsPanel, Panel):
bl_label = "Radial"
bl_parent_id = "PHYSICS_PT_field_falloff"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -300,7 +300,7 @@ def collision_warning(layout):
class PHYSICS_PT_collision(PhysicButtonsPanel, Panel):
bl_label = "Collision"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -331,7 +331,7 @@ class PHYSICS_PT_collision(PhysicButtonsPanel, Panel):
class PHYSICS_PT_collision_particle(PhysicButtonsPanel, Panel):
bl_label = "Particle"
bl_parent_id = "PHYSICS_PT_collision"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -377,7 +377,7 @@ class PHYSICS_PT_collision_particle(PhysicButtonsPanel, Panel):
class PHYSICS_PT_collision_softbody(PhysicButtonsPanel, Panel):
bl_label = "Softbody & Cloth"
bl_parent_id = "PHYSICS_PT_collision"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):

View File

@@ -98,7 +98,7 @@ class PhysicButtonsPanel:
class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
bl_label = "Fluid"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -122,7 +122,7 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
bl_label = "Settings"
bl_parent_id = 'PHYSICS_PT_fluid'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -285,7 +285,7 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
class PHYSICS_PT_borders(PhysicButtonsPanel, Panel):
bl_label = "Border Collisions"
bl_parent_id = 'PHYSICS_PT_settings'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -318,7 +318,7 @@ class PHYSICS_PT_borders(PhysicButtonsPanel, Panel):
class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
bl_label = "Gas"
bl_parent_id = 'PHYSICS_PT_fluid'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -351,7 +351,7 @@ class PHYSICS_PT_smoke_dissolve(PhysicButtonsPanel, Panel):
bl_label = "Dissolve"
bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -395,7 +395,7 @@ class PHYSICS_PT_fire(PhysicButtonsPanel, Panel):
bl_label = "Fire"
bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -434,7 +434,7 @@ class PHYSICS_PT_fire(PhysicButtonsPanel, Panel):
class PHYSICS_PT_liquid(PhysicButtonsPanel, Panel):
bl_label = "Liquid"
bl_parent_id = 'PHYSICS_PT_fluid'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -497,7 +497,7 @@ class PHYSICS_PT_flow_source(PhysicButtonsPanel, Panel):
bl_label = "Flow Source"
bl_parent_id = 'PHYSICS_PT_settings'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -538,7 +538,7 @@ class PHYSICS_PT_flow_source(PhysicButtonsPanel, Panel):
class PHYSICS_PT_flow_initial_velocity(PhysicButtonsPanel, Panel):
bl_label = "Initial Velocity"
bl_parent_id = 'PHYSICS_PT_settings'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -580,7 +580,7 @@ class PHYSICS_PT_flow_texture(PhysicButtonsPanel, Panel):
bl_label = "Texture"
bl_parent_id = 'PHYSICS_PT_settings'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -631,7 +631,7 @@ class PHYSICS_PT_adaptive_domain(PhysicButtonsPanel, Panel):
bl_label = "Adaptive Domain"
bl_parent_id = 'PHYSICS_PT_settings'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -683,7 +683,7 @@ class PHYSICS_PT_noise(PhysicButtonsPanel, Panel):
bl_label = "Noise"
bl_parent_id = 'PHYSICS_PT_smoke'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -763,7 +763,7 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
bl_label = "Mesh"
bl_parent_id = 'PHYSICS_PT_liquid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -858,7 +858,7 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
bl_label = "Particles"
bl_parent_id = 'PHYSICS_PT_liquid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -989,7 +989,7 @@ class PHYSICS_PT_viscosity(PhysicButtonsPanel, Panel):
bl_label = "Viscosity"
bl_parent_id = 'PHYSICS_PT_liquid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1029,7 +1029,7 @@ class PHYSICS_PT_diffusion(PhysicButtonsPanel, Panel):
bl_label = "Diffusion"
bl_parent_id = 'PHYSICS_PT_liquid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1076,7 +1076,7 @@ class PHYSICS_PT_guide(PhysicButtonsPanel, Panel):
bl_label = "Guides"
bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1142,7 +1142,7 @@ class PHYSICS_PT_collections(PhysicButtonsPanel, Panel):
bl_label = "Collections"
bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1169,7 +1169,7 @@ class PHYSICS_PT_collections(PhysicButtonsPanel, Panel):
class PHYSICS_PT_cache(PhysicButtonsPanel, Panel):
bl_label = "Cache"
bl_parent_id = 'PHYSICS_PT_fluid'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1253,7 +1253,7 @@ class PHYSICS_PT_export(PhysicButtonsPanel, Panel):
bl_label = "Advanced"
bl_parent_id = 'PHYSICS_PT_cache'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1298,7 +1298,7 @@ class PHYSICS_PT_field_weights(PhysicButtonsPanel, Panel):
bl_label = "Field Weights"
bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -1487,7 +1487,7 @@ class PHYSICS_PT_fluid_domain_render(PhysicButtonsPanel, Panel):
bl_label = "Render"
bl_parent_id = 'PHYSICS_PT_fluid'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):

View File

@@ -19,7 +19,7 @@ class PHYSICS_PT_rigidbody_panel:
class PHYSICS_PT_rigid_body(PHYSICS_PT_rigidbody_panel, Panel):
bl_label = "Rigid Body"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -54,7 +54,7 @@ class PHYSICS_PT_rigid_body(PHYSICS_PT_rigidbody_panel, Panel):
class PHYSICS_PT_rigid_body_settings(PHYSICS_PT_rigidbody_panel, Panel):
bl_label = "Settings"
bl_parent_id = 'PHYSICS_PT_rigid_body'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -86,7 +86,7 @@ class PHYSICS_PT_rigid_body_settings(PHYSICS_PT_rigidbody_panel, Panel):
class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
bl_label = "Collisions"
bl_parent_id = 'PHYSICS_PT_rigid_body'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -136,7 +136,7 @@ class PHYSICS_PT_rigid_body_collisions_surface(PHYSICS_PT_rigidbody_panel, Panel
bl_label = "Surface Response"
bl_parent_id = 'PHYSICS_PT_rigid_body_collisions'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -164,7 +164,7 @@ class PHYSICS_PT_rigid_body_collisions_sensitivity(PHYSICS_PT_rigidbody_panel, P
bl_label = "Sensitivity"
bl_parent_id = 'PHYSICS_PT_rigid_body_collisions'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -201,7 +201,7 @@ class PHYSICS_PT_rigid_body_collisions_collections(PHYSICS_PT_rigidbody_panel, P
bl_label = "Collections"
bl_parent_id = 'PHYSICS_PT_rigid_body_collisions'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -223,7 +223,7 @@ class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel):
bl_label = "Dynamics"
bl_parent_id = 'PHYSICS_PT_rigid_body'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -256,7 +256,7 @@ class PHYSICS_PT_rigid_body_dynamics_deactivation(PHYSICS_PT_rigidbody_panel, Pa
bl_label = "Deactivation"
bl_parent_id = 'PHYSICS_PT_rigid_body_dynamics'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):

View File

@@ -13,7 +13,7 @@ class PHYSICS_PT_rigidbody_constraint_panel:
class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Rigid Body Constraint"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -33,7 +33,7 @@ class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Pa
class PHYSICS_PT_rigid_body_constraint_settings(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Settings"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -64,7 +64,7 @@ class PHYSICS_PT_rigid_body_constraint_settings(PHYSICS_PT_rigidbody_constraint_
class PHYSICS_PT_rigid_body_constraint_objects(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Objects"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -85,7 +85,7 @@ class PHYSICS_PT_rigid_body_constraint_objects(PHYSICS_PT_rigidbody_constraint_p
class PHYSICS_PT_rigid_body_constraint_override_iterations(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Override Iterations"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -111,7 +111,7 @@ class PHYSICS_PT_rigid_body_constraint_override_iterations(PHYSICS_PT_rigidbody_
class PHYSICS_PT_rigid_body_constraint_limits(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Limits"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -128,7 +128,7 @@ class PHYSICS_PT_rigid_body_constraint_limits(PHYSICS_PT_rigidbody_constraint_pa
class PHYSICS_PT_rigid_body_constraint_limits_linear(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Linear"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint_limits'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -185,7 +185,7 @@ class PHYSICS_PT_rigid_body_constraint_limits_linear(PHYSICS_PT_rigidbody_constr
class PHYSICS_PT_rigid_body_constraint_limits_angular(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Angular"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint_limits'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -251,7 +251,7 @@ class PHYSICS_PT_rigid_body_constraint_limits_angular(PHYSICS_PT_rigidbody_const
class PHYSICS_PT_rigid_body_constraint_motor(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Motor"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -268,7 +268,7 @@ class PHYSICS_PT_rigid_body_constraint_motor(PHYSICS_PT_rigidbody_constraint_pan
class PHYSICS_PT_rigid_body_constraint_motor_angular(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Angular"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint_motor'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -304,7 +304,7 @@ class PHYSICS_PT_rigid_body_constraint_motor_angular(PHYSICS_PT_rigidbody_constr
class PHYSICS_PT_rigid_body_constraint_motor_linear(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Linear"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint_motor'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -340,7 +340,7 @@ class PHYSICS_PT_rigid_body_constraint_motor_linear(PHYSICS_PT_rigidbody_constra
class PHYSICS_PT_rigid_body_constraint_springs(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Springs"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -364,7 +364,7 @@ class PHYSICS_PT_rigid_body_constraint_springs(PHYSICS_PT_rigidbody_constraint_p
class PHYSICS_PT_rigid_body_constraint_springs_angular(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Angular"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint_springs'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -412,7 +412,7 @@ class PHYSICS_PT_rigid_body_constraint_springs_angular(PHYSICS_PT_rigidbody_cons
class PHYSICS_PT_rigid_body_constraint_springs_linear(PHYSICS_PT_rigidbody_constraint_panel, Panel):
bl_label = "Linear"
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint_springs'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):

View File

@@ -28,7 +28,7 @@ class PhysicButtonsPanel:
class PHYSICS_PT_softbody(PhysicButtonsPanel, Panel):
bl_label = "Soft Body"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -44,7 +44,7 @@ class PHYSICS_PT_softbody_object(PhysicButtonsPanel, Panel):
bl_label = "Object"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -72,7 +72,7 @@ class PHYSICS_PT_softbody_simulation(PhysicButtonsPanel, Panel):
bl_label = "Simulation"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -90,7 +90,7 @@ class PHYSICS_PT_softbody_cache(PhysicButtonsPanel, Panel):
bl_label = "Cache"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
md = context.soft_body
@@ -101,7 +101,7 @@ class PHYSICS_PT_softbody_goal(PhysicButtonsPanel, Panel):
bl_label = "Goal"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
softbody = context.soft_body.settings
@@ -126,7 +126,7 @@ class PHYSICS_PT_softbody_goal_strengths(PhysicButtonsPanel, Panel):
bl_label = "Strengths"
bl_parent_id = 'PHYSICS_PT_softbody_goal'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -152,7 +152,7 @@ class PHYSICS_PT_softbody_goal_settings(PhysicButtonsPanel, Panel):
bl_label = "Settings"
bl_parent_id = 'PHYSICS_PT_softbody_goal'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -175,7 +175,7 @@ class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, Panel):
bl_label = "Edges"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
softbody = context.soft_body.settings
@@ -226,7 +226,7 @@ class PHYSICS_PT_softbody_edge_aerodynamics(PhysicButtonsPanel, Panel):
bl_label = "Aerodynamics"
bl_parent_id = 'PHYSICS_PT_softbody_edge'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -249,7 +249,7 @@ class PHYSICS_PT_softbody_edge_stiffness(PhysicButtonsPanel, Panel):
bl_label = "Stiffness"
bl_parent_id = 'PHYSICS_PT_softbody_edge'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
softbody = context.soft_body.settings
@@ -273,7 +273,7 @@ class PHYSICS_PT_softbody_collision(PhysicButtonsPanel, Panel):
bl_label = "Self Collision"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
softbody = context.soft_body.settings
@@ -308,7 +308,7 @@ class PHYSICS_PT_softbody_solver(PhysicButtonsPanel, Panel):
bl_label = "Solver"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -333,7 +333,7 @@ class PHYSICS_PT_softbody_solver_diagnostics(PhysicButtonsPanel, Panel):
bl_label = "Diagnostics"
bl_parent_id = 'PHYSICS_PT_softbody_solver'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -352,7 +352,7 @@ class PHYSICS_PT_softbody_solver_helpers(PhysicButtonsPanel, Panel):
bl_label = "Helpers"
bl_parent_id = 'PHYSICS_PT_softbody_solver'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -375,7 +375,7 @@ class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, Panel):
bl_label = "Field Weights"
bl_parent_id = 'PHYSICS_PT_softbody'
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
md = context.soft_body

View File

@@ -47,7 +47,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -80,7 +80,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_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
@@ -640,7 +640,7 @@ class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
class RENDER_PT_eevee_performance(RenderButtonsPanel, Panel):
bl_label = "Performance"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -661,7 +661,7 @@ class RENDER_PT_gpencil(RenderButtonsPanel, Panel):
bl_label = "Grease Pencil"
bl_options = {'DEFAULT_CLOSED'}
bl_order = 10
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -677,7 +677,7 @@ class RENDER_PT_gpencil(RenderButtonsPanel, Panel):
class RENDER_PT_opengl_sampling(RenderButtonsPanel, Panel):
bl_label = "Sampling"
COMPAT_ENGINES = {'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -699,7 +699,7 @@ class RENDER_PT_opengl_sampling(RenderButtonsPanel, Panel):
class RENDER_PT_opengl_film(RenderButtonsPanel, Panel):
bl_label = "Film"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -712,7 +712,7 @@ class RENDER_PT_opengl_film(RenderButtonsPanel, Panel):
class RENDER_PT_opengl_lighting(RenderButtonsPanel, Panel):
bl_label = "Lighting"
COMPAT_ENGINES = {'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -724,7 +724,7 @@ class RENDER_PT_opengl_lighting(RenderButtonsPanel, Panel):
class RENDER_PT_opengl_color(RenderButtonsPanel, Panel):
bl_label = "Color"
COMPAT_ENGINES = {'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -736,7 +736,7 @@ class RENDER_PT_opengl_color(RenderButtonsPanel, Panel):
class RENDER_PT_opengl_options(RenderButtonsPanel, Panel):
bl_label = "Options"
COMPAT_ENGINES = {'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -749,7 +749,7 @@ class RENDER_PT_opengl_options(RenderButtonsPanel, Panel):
class RENDER_PT_simplify(RenderButtonsPanel, Panel):
bl_label = "Simplify"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
rd = context.scene.render
@@ -762,7 +762,7 @@ class RENDER_PT_simplify(RenderButtonsPanel, Panel):
class RENDER_PT_simplify_viewport(RenderButtonsPanel, Panel):
bl_label = "Viewport"
bl_parent_id = "RENDER_PT_simplify"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -787,7 +787,7 @@ class RENDER_PT_simplify_viewport(RenderButtonsPanel, Panel):
class RENDER_PT_simplify_render(RenderButtonsPanel, Panel):
bl_label = "Render"
bl_parent_id = "RENDER_PT_simplify"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -815,7 +815,7 @@ class RENDER_PT_simplify_greasepencil(RenderButtonsPanel, Panel, GreasePencilSim
'BLENDER_CLAY',
'BLENDER_EEVEE',
'BLENDER_EEVEE_NEXT',
'BLENDER_WORKBENCH',
'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT',
}
bl_options = {'DEFAULT_CLOSED'}

View File

@@ -67,7 +67,7 @@ class TextureButtonsPanel:
class TEXTURE_PT_preview(TextureButtonsPanel, Panel):
bl_label = "Preview"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -96,7 +96,7 @@ class TEXTURE_PT_context(TextureButtonsPanel, Panel):
bl_label = ""
bl_context = "texture"
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -135,7 +135,7 @@ class TEXTURE_PT_context(TextureButtonsPanel, Panel):
class TEXTURE_PT_node(TextureButtonsPanel, Panel):
bl_label = "Node"
bl_context = "texture"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -164,7 +164,7 @@ class TextureTypePanel(TextureButtonsPanel):
class TEXTURE_PT_clouds(TextureTypePanel, Panel):
bl_label = "Clouds"
tex_type = 'CLOUDS'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -196,7 +196,7 @@ class TEXTURE_PT_clouds(TextureTypePanel, Panel):
class TEXTURE_PT_wood(TextureTypePanel, Panel):
bl_label = "Wood"
tex_type = 'WOOD'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -233,7 +233,7 @@ class TEXTURE_PT_wood(TextureTypePanel, Panel):
class TEXTURE_PT_marble(TextureTypePanel, Panel):
bl_label = "Marble"
tex_type = 'MARBLE'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -267,7 +267,7 @@ class TEXTURE_PT_marble(TextureTypePanel, Panel):
class TEXTURE_PT_magic(TextureTypePanel, Panel):
bl_label = "Magic"
tex_type = 'MAGIC'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -286,7 +286,7 @@ class TEXTURE_PT_magic(TextureTypePanel, Panel):
class TEXTURE_PT_blend(TextureTypePanel, Panel):
bl_label = "Blend"
tex_type = 'BLEND'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -308,7 +308,7 @@ class TEXTURE_PT_blend(TextureTypePanel, Panel):
class TEXTURE_PT_stucci(TextureTypePanel, Panel):
bl_label = "Stucci"
tex_type = 'STUCCI'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -339,7 +339,7 @@ class TEXTURE_PT_stucci(TextureTypePanel, Panel):
class TEXTURE_PT_image(TextureTypePanel, Panel):
bl_label = "Image"
tex_type = 'IMAGE'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, _context):
# TODO: maybe expose the template_ID from the template image here.
@@ -351,7 +351,7 @@ class TEXTURE_PT_image_settings(TextureTypePanel, Panel):
bl_label = "Settings"
bl_parent_id = 'TEXTURE_PT_image'
tex_type = 'IMAGE'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -506,7 +506,7 @@ class TEXTURE_PT_image_mapping_crop(TextureTypePanel, Panel):
class TEXTURE_PT_musgrave(TextureTypePanel, Panel):
bl_label = "Musgrave"
tex_type = 'MUSGRAVE'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -551,7 +551,7 @@ class TEXTURE_PT_musgrave(TextureTypePanel, Panel):
class TEXTURE_PT_voronoi(TextureTypePanel, Panel):
bl_label = "Voronoi"
tex_type = 'VORONOI'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -584,7 +584,7 @@ class TEXTURE_PT_voronoi_feature_weights(TextureTypePanel, Panel):
bl_label = "Feature Weights"
bl_parent_id = "TEXTURE_PT_voronoi"
tex_type = 'VORONOI'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -605,7 +605,7 @@ class TEXTURE_PT_voronoi_feature_weights(TextureTypePanel, Panel):
class TEXTURE_PT_distortednoise(TextureTypePanel, Panel):
bl_label = "Distorted Noise"
tex_type = 'DISTORTED_NOISE'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -630,7 +630,7 @@ class TEXTURE_PT_distortednoise(TextureTypePanel, Panel):
class TextureSlotPanel(TextureButtonsPanel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -642,7 +642,7 @@ class TextureSlotPanel(TextureButtonsPanel):
class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
bl_label = "Mapping"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -710,7 +710,7 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
class TEXTURE_PT_influence(TextureSlotPanel, Panel):
bl_label = "Influence"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):
@@ -792,7 +792,7 @@ class TextureColorsPoll:
class TEXTURE_PT_colors(TextureButtonsPanel, TextureColorsPoll, Panel):
bl_label = "Colors"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -821,7 +821,7 @@ class TEXTURE_PT_colors_ramp(TextureButtonsPanel, TextureColorsPoll, Panel):
bl_label = "Color Ramp"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = 'TEXTURE_PT_colors'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw_header(self, context):
tex = context.texture
@@ -842,7 +842,7 @@ class TEXTURE_PT_colors_ramp(TextureButtonsPanel, TextureColorsPoll, Panel):
class TEXTURE_PT_custom_props(TextureButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "texture"
_property_type = Texture

View File

@@ -26,7 +26,7 @@ class ViewLayerButtonsPanel:
class VIEWLAYER_PT_layer(ViewLayerButtonsPanel, Panel):
bl_label = "View Layer"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
@@ -44,7 +44,7 @@ class VIEWLAYER_PT_layer(ViewLayerButtonsPanel, Panel):
class VIEWLAYER_PT_layer_passes(ViewLayerButtonsPanel, Panel):
bl_label = "Passes"
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
pass
@@ -94,6 +94,23 @@ class VIEWLAYER_PT_eevee_next_layer_passes_data(ViewLayerButtonsPanel, Panel):
sub.active = not scene.eevee.use_motion_blur
sub.prop(view_layer, "use_pass_vector")
class VIEWLAYER_PT_eevee_next_layer_passes_data(ViewLayerButtonsPanel, Panel):
bl_label = "Data"
bl_parent_id = "VIEWLAYER_PT_layer_passes"
COMPAT_ENGINES = {'BLENDER_WORKBENCH_NEXT'}
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
view_layer = context.view_layer
col = layout.column()
col.prop(view_layer, "use_pass_combined")
col.prop(view_layer, "use_pass_z")
class VIEWLAYER_PT_eevee_layer_passes_light(ViewLayerButtonsPanel, Panel):
bl_label = "Light"

View File

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

View File

@@ -670,7 +670,7 @@ class NODE_PT_texture_mapping(Panel):
bl_category = "Node"
bl_label = "Texture Mapping"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
@classmethod
def poll(cls, context):

View File

@@ -2607,7 +2607,7 @@ class SEQUENCER_PT_annotation_onion(AnnotationOnionSkin, SequencerButtonsPanel_O
class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH','BLENDER_WORKBENCH_NEXT'}
_context_path = "active_sequence_strip"
_property_type = (bpy.types.Sequence,)
bl_category = "Strip"

View File

@@ -2339,6 +2339,7 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
({"property": "use_sculpt_texture_paint"}, "T96225"),
({"property": "use_full_frame_compositor"}, "T88150"),
({"property": "enable_eevee_next"}, "T93220"),
({"property": "enable_workbench_next"}, "T101619"),
),
)

View File

@@ -158,15 +158,26 @@ set(SRC
engines/eevee_next/eevee_world.cc
engines/workbench/workbench_data.c
engines/workbench/workbench_effect_antialiasing.c
engines/workbench/workbench_effect_antialiasing.cc
engines/workbench/workbench_effect_cavity.c
engines/workbench/workbench_effect_cavity.cc
engines/workbench/workbench_effect_dof.c
engines/workbench/workbench_effect_dof.cc
engines/workbench/workbench_effect_outline.c
engines/workbench/workbench_effect_outline.cc
engines/workbench/workbench_engine.c
engines/workbench/workbench_engine.cc
engines/workbench/workbench_materials.cc
engines/workbench/workbench_materials_next.cc
engines/workbench/workbench_mesh_passes.cc
engines/workbench/workbench_opaque.c
engines/workbench/workbench_render.c
engines/workbench/workbench_resources.cc
engines/workbench/workbench_shader.cc
engines/workbench/workbench_shader_cache.cc
engines/workbench/workbench_shadow.c
engines/workbench/workbench_shadow.cc
engines/workbench/workbench_state.cc
engines/workbench/workbench_transparent.c
engines/workbench/workbench_volume.c
engines/external/external_engine.c
@@ -290,8 +301,11 @@ set(SRC
engines/image/image_space_node.hh
engines/image/image_texture_info.hh
engines/image/image_usage.hh
engines/workbench/workbench_defines.hh
engines/workbench/workbench_engine.h
engines/workbench/workbench_enums.hh
engines/workbench/workbench_private.h
engines/workbench/workbench_private.hh
engines/workbench/workbench_shader_shared.h
engines/select/select_engine.h
engines/select/select_private.h
@@ -462,6 +476,7 @@ set(GLSL_SRC
engines/workbench/shaders/workbench_cavity_lib.glsl
engines/workbench/shaders/workbench_common_lib.glsl
engines/workbench/shaders/workbench_composite_frag.glsl
engines/workbench/shaders/workbench_next_composite_frag.glsl
engines/workbench/shaders/workbench_curvature_lib.glsl
engines/workbench/shaders/workbench_effect_cavity_frag.glsl
engines/workbench/shaders/workbench_effect_dof_frag.glsl
@@ -473,6 +488,7 @@ set(GLSL_SRC
engines/workbench/shaders/workbench_matcap_lib.glsl
engines/workbench/shaders/workbench_material_lib.glsl
engines/workbench/shaders/workbench_merge_infront_frag.glsl
engines/workbench/shaders/workbench_next_merge_depth_frag.glsl
engines/workbench/shaders/workbench_prepass_frag.glsl
engines/workbench/shaders/workbench_prepass_hair_vert.glsl
engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl
@@ -482,6 +498,7 @@ set(GLSL_SRC
engines/workbench/shaders/workbench_shadow_debug_frag.glsl
engines/workbench/shaders/workbench_shadow_geom.glsl
engines/workbench/shaders/workbench_shadow_vert.glsl
engines/workbench/shaders/workbench_shadow_visibility_comp.glsl
engines/workbench/shaders/workbench_shadow_vert_no_geom.glsl
engines/workbench/shaders/workbench_transparent_accum_frag.glsl
engines/workbench/shaders/workbench_transparent_resolve_frag.glsl
@@ -689,6 +706,7 @@ set(GLSL_SRC
)
set(GLSL_C)
foreach(GLSL_FILE ${GLSL_SRC})
data_to_c_simple(${GLSL_FILE} GLSL_C)
endforeach()
@@ -700,6 +718,7 @@ list(APPEND LIB
)
set(GLSL_SOURCE_CONTENT "")
foreach(GLSL_FILE ${GLSL_SRC})
get_filename_component(GLSL_FILE_NAME ${GLSL_FILE} NAME)
string(REPLACE "." "_" GLSL_FILE_NAME_UNDERSCORES ${GLSL_FILE_NAME})
@@ -746,11 +765,13 @@ endif()
if(WITH_TBB)
add_definitions(-DWITH_TBB)
if(WIN32)
# TBB includes Windows.h which will define min/max macros
# that will collide with the stl versions.
add_definitions(-DNOMINMAX)
endif()
list(APPEND INC_SYS
${TBB_INCLUDE_DIRS}
)

View File

@@ -1,15 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "gpu_shader_create_info.hh"
#include "workbench_defines.hh"
/* -------------------------------------------------------------------- */
/** \name Base Composite
* \{ */
GPU_SHADER_CREATE_INFO(workbench_composite)
.sampler(0, ImageType::FLOAT_2D, "normalBuffer", Frequency::PASS)
.sampler(1, ImageType::FLOAT_2D, "materialBuffer", Frequency::PASS)
.uniform_buf(4, "WorldData", "world_data", Frequency::PASS)
.sampler(0, ImageType::FLOAT_2D, "normalBuffer")
.sampler(1, ImageType::FLOAT_2D, "materialBuffer")
.uniform_buf(WB_WORLD_SLOT, "WorldData", "world_data")
.push_constant(Type::BOOL, "forceShadowing")
.fragment_out(0, Type::VEC4, "fragColor")
.typedef_source("workbench_shader_shared.h")
@@ -23,20 +24,88 @@ GPU_SHADER_CREATE_INFO(workbench_composite)
* \{ */
GPU_SHADER_CREATE_INFO(workbench_composite_studio)
.define("V3D_LIGHTING_STUDIO")
.define("WORKBENCH_LIGHTING_STUDIO")
.additional_info("workbench_composite")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(workbench_composite_matcap)
.define("V3D_LIGHTING_MATCAP")
.sampler(2, ImageType::FLOAT_2D, "matcap_diffuse_tx", Frequency::PASS)
.sampler(3, ImageType::FLOAT_2D, "matcap_specular_tx", Frequency::PASS)
.define("WORKBENCH_LIGHTING_MATCAP")
.sampler(2, ImageType::FLOAT_2D, "matcap_diffuse_tx")
.sampler(3, ImageType::FLOAT_2D, "matcap_specular_tx")
.additional_info("workbench_composite")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(workbench_composite_flat)
.define("V3D_LIGHTING_FLAT")
.define("WORKBENCH_LIGHTING_FLAT")
.additional_info("workbench_composite")
.do_static_compilation(true);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Workbench Next
* \{ */
GPU_SHADER_CREATE_INFO(workbench_next_composite)
.sampler(3, ImageType::FLOAT_2D, "normal_tx")
.sampler(4, ImageType::FLOAT_2D, "material_tx")
.sampler(5, ImageType::DEPTH_2D, "depth_tx")
.sampler(6, ImageType::UINT_2D, "stencil_tx")
.uniform_buf(WB_WORLD_SLOT, "WorldData", "world_data")
.typedef_source("workbench_shader_shared.h")
.push_constant(Type::BOOL, "forceShadowing")
.fragment_out(0, Type::VEC4, "fragColor")
.fragment_source("workbench_next_composite_frag.glsl")
.additional_info("draw_fullscreen", "draw_view");
/* Lighting */
GPU_SHADER_CREATE_INFO(workbench_next_resolve_opaque_studio).define("WORKBENCH_LIGHTING_STUDIO");
GPU_SHADER_CREATE_INFO(workbench_next_resolve_opaque_matcap)
.define("WORKBENCH_LIGHTING_MATCAP")
.sampler(WB_MATCAP_SLOT, ImageType::FLOAT_2D_ARRAY, "matcap_tx");
GPU_SHADER_CREATE_INFO(workbench_next_resolve_opaque_flat).define("WORKBENCH_LIGHTING_FLAT");
/* Effects */
GPU_SHADER_CREATE_INFO(workbench_next_resolve_curvature)
.define("WORKBENCH_CURVATURE")
.sampler(7, ImageType::UINT_2D, "object_id_tx");
GPU_SHADER_CREATE_INFO(workbench_next_resolve_cavity)
.define("WORKBENCH_CAVITY")
.sampler(8, ImageType::FLOAT_2D, "jitter_tx") /* TODO(Miguel Pozo): GPU_SAMPLER_REPEAT is set
in CavityEffect, it doesn't work here ? */
.uniform_buf(5, "vec4", "cavity_samples[512]");
/* Variations */
#define WORKBENCH_FINAL_VARIATION(name, ...) \
GPU_SHADER_CREATE_INFO(name).additional_info(__VA_ARGS__).do_static_compilation(true);
#define WORKBENCH_CURVATURE_VARIATIONS(prefix, ...) \
WORKBENCH_FINAL_VARIATION(prefix##_curvature, "workbench_next_resolve_curvature", __VA_ARGS__) \
WORKBENCH_FINAL_VARIATION(prefix##_no_curvature, __VA_ARGS__)
#define WORKBENCH_CAVITY_VARIATIONS(prefix, ...) \
WORKBENCH_CURVATURE_VARIATIONS(prefix##_cavity, "workbench_next_resolve_cavity", __VA_ARGS__) \
WORKBENCH_CURVATURE_VARIATIONS(prefix##_no_cavity, __VA_ARGS__)
#define WORKBENCH_LIGHTING_VARIATIONS(prefix, ...) \
WORKBENCH_CAVITY_VARIATIONS( \
prefix##_opaque_studio, "workbench_next_resolve_opaque_studio", __VA_ARGS__) \
WORKBENCH_CAVITY_VARIATIONS( \
prefix##_opaque_matcap, "workbench_next_resolve_opaque_matcap", __VA_ARGS__) \
WORKBENCH_CAVITY_VARIATIONS( \
prefix##_opaque_flat, "workbench_next_resolve_opaque_flat", __VA_ARGS__)
WORKBENCH_LIGHTING_VARIATIONS(workbench_next_resolve, "workbench_next_composite");
#undef WORKBENCH_FINAL_VARIATION
#undef WORKBENCH_CURVATURE_VARIATIONS
#undef WORKBENCH_CAVITY_VARIATIONS
#undef WORKBENCH_LIGHTING_VARIATIONS
/** \} */

View File

@@ -5,7 +5,7 @@
GPU_SHADER_CREATE_INFO(workbench_effect_cavity_common)
.fragment_out(0, Type::VEC4, "fragColor")
.sampler(0, ImageType::FLOAT_2D, "normalBuffer")
.uniform_buf(4, "WorldData", "world_data", Frequency::PASS)
.uniform_buf(WB_WORLD_SLOT, "WorldData", "world_data")
.typedef_source("workbench_shader_shared.h")
.fragment_source("workbench_effect_cavity_frag.glsl")
.additional_info("draw_fullscreen")

View File

@@ -6,7 +6,7 @@ GPU_SHADER_CREATE_INFO(workbench_effect_outline)
.typedef_source("workbench_shader_shared.h")
.fragment_source("workbench_effect_outline_frag.glsl")
.sampler(0, ImageType::UINT_2D, "objectIdBuffer")
.uniform_buf(4, "WorldData", "world_data", Frequency::PASS)
.uniform_buf(WB_WORLD_SLOT, "WorldData", "world_data")
.fragment_out(0, Type::VEC4, "fragColor")
.additional_info("draw_fullscreen")
.do_static_compilation(true);

View File

@@ -9,3 +9,10 @@ GPU_SHADER_CREATE_INFO(workbench_merge_infront)
.additional_info("draw_fullscreen")
.depth_write(DepthWrite::ANY)
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(workbench_next_merge_depth)
.sampler(0, ImageType::DEPTH_2D, "depth_tx")
.fragment_source("workbench_next_merge_depth_frag.glsl")
.additional_info("draw_fullscreen")
.depth_write(DepthWrite::ANY)
.do_static_compilation(true);

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "gpu_shader_create_info.hh"
#include "workbench_defines.hh"
/* -------------------------------------------------------------------- */
/** \name Object Type
@@ -29,6 +30,29 @@ GPU_SHADER_CREATE_INFO(workbench_pointcloud)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Object Type
* \{ */
GPU_SHADER_CREATE_INFO(workbench_next_mesh)
.vertex_in(0, Type::VEC3, "pos")
.vertex_in(1, Type::VEC3, "nor")
.vertex_in(2, Type::VEC4, "ac")
.vertex_in(3, Type::VEC2, "au")
.vertex_source("workbench_prepass_vert.glsl")
.additional_info("draw_modelmat_new")
.additional_info("draw_resource_handle_new");
GPU_SHADER_CREATE_INFO(workbench_next_curves)
/* TODO Adding workbench_next_mesh to avoid shader compilation errors */
.additional_info("workbench_next_mesh");
GPU_SHADER_CREATE_INFO(workbench_next_pointcloud)
/* TODO Adding workbench_next_mesh to avoid shader compilation errors */
.additional_info("workbench_next_mesh");
/** \} */
/* -------------------------------------------------------------------- */
/** \name Texture Type
* \{ */
@@ -39,15 +63,15 @@ GPU_SHADER_CREATE_INFO(workbench_texture_single)
.sampler(2, ImageType::FLOAT_2D, "imageTexture", Frequency::BATCH)
.push_constant(Type::BOOL, "imagePremult")
.push_constant(Type::FLOAT, "imageTransparencyCutoff")
.define("V3D_SHADING_TEXTURE_COLOR");
.define("WORKBENCH_COLOR_TEXTURE");
GPU_SHADER_CREATE_INFO(workbench_texture_tile)
.sampler(2, ImageType::FLOAT_2D_ARRAY, "imageTileArray", Frequency::BATCH)
.sampler(3, ImageType::FLOAT_1D_ARRAY, "imageTileData", Frequency::BATCH)
.push_constant(Type::BOOL, "imagePremult")
.push_constant(Type::FLOAT, "imageTransparencyCutoff")
.define("V3D_SHADING_TEXTURE_COLOR")
.define("TEXTURE_IMAGE_ARRAY");
.define("WORKBENCH_COLOR_TEXTURE")
.define("WORKBENCH_TEXTURE_IMAGE_ARRAY");
/** \} */
@@ -55,12 +79,16 @@ GPU_SHADER_CREATE_INFO(workbench_texture_tile)
/** \name Lighting Type (only for transparent)
* \{ */
GPU_SHADER_CREATE_INFO(workbench_lighting_flat).define("V3D_LIGHTING_FLAT");
GPU_SHADER_CREATE_INFO(workbench_lighting_studio).define("V3D_LIGHTING_STUDIO");
GPU_SHADER_CREATE_INFO(workbench_lighting_flat).define("WORKBENCH_LIGHTING_FLAT");
GPU_SHADER_CREATE_INFO(workbench_lighting_studio).define("WORKBENCH_LIGHTING_STUDIO");
GPU_SHADER_CREATE_INFO(workbench_lighting_matcap)
.define("V3D_LIGHTING_MATCAP")
.sampler(4, ImageType::FLOAT_2D, "matcap_diffuse_tx", Frequency::PASS)
.sampler(5, ImageType::FLOAT_2D, "matcap_specular_tx", Frequency::PASS);
.define("WORKBENCH_LIGHTING_MATCAP")
.sampler(4, ImageType::FLOAT_2D, "matcap_diffuse_tx")
.sampler(5, ImageType::FLOAT_2D, "matcap_specular_tx");
GPU_SHADER_CREATE_INFO(workbench_next_lighting_matcap)
.define("WORKBENCH_LIGHTING_MATCAP")
.sampler(WB_MATCAP_SLOT, ImageType::FLOAT_2D_ARRAY, "matcap_tx");
/** \} */
@@ -78,12 +106,42 @@ GPU_SHADER_INTERFACE_INFO(workbench_material_iface, "")
.flat(Type::FLOAT, "metallic");
GPU_SHADER_CREATE_INFO(workbench_material)
.uniform_buf(4, "WorldData", "world_data", Frequency::PASS)
.uniform_buf(5, "vec4", "materials_data[4096]", Frequency::PASS)
.uniform_buf(WB_WORLD_SLOT, "WorldData", "world_data")
.uniform_buf(5, "vec4", "materials_data[4096]")
.push_constant(Type::INT, "materialIndex")
.push_constant(Type::BOOL, "useMatcap")
.vertex_out(workbench_material_iface);
GPU_SHADER_CREATE_INFO(workbench_next_prepass)
.define("WORKBENCH_NEXT")
.uniform_buf(WB_WORLD_SLOT, "WorldData", "world_data")
.vertex_out(workbench_material_iface)
.additional_info("draw_view");
/** \} */
/* -------------------------------------------------------------------- */
/** \name Material Interface
* \{ */
GPU_SHADER_CREATE_INFO(workbench_color_material)
.define("WORKBENCH_COLOR_MATERIAL")
.storage_buf(WB_MATERIAL_SLOT, Qualifier::READ, "vec4", "materials_data[]");
GPU_SHADER_CREATE_INFO(workbench_color_texture)
.define("WORKBENCH_COLOR_TEXTURE")
.define("WORKBENCH_TEXTURE_IMAGE_ARRAY")
.define("WORKBENCH_COLOR_MATERIAL")
.storage_buf(WB_MATERIAL_SLOT, Qualifier::READ, "vec4", "materials_data[]")
.sampler(1, ImageType::FLOAT_2D, "imageTexture", Frequency::BATCH)
.sampler(2, ImageType::FLOAT_2D_ARRAY, "imageTileArray", Frequency::BATCH)
.sampler(3, ImageType::FLOAT_1D_ARRAY, "imageTileData", Frequency::BATCH)
.push_constant(Type::BOOL, "isImageTile")
.push_constant(Type::BOOL, "imagePremult")
.push_constant(Type::FLOAT, "imageTransparencyCutoff");
GPU_SHADER_CREATE_INFO(workbench_color_vertex).define("WORKBENCH_COLOR_VERTEX");
/** \} */
/* -------------------------------------------------------------------- */
@@ -93,17 +151,17 @@ GPU_SHADER_CREATE_INFO(workbench_material)
GPU_SHADER_CREATE_INFO(workbench_transparent_accum)
/* NOTE: Blending will be skipped on objectId because output is a
* non-normalized integer buffer. */
.fragment_out(0, Type::VEC4, "transparentAccum")
.fragment_out(1, Type::VEC4, "revealageAccum")
.fragment_out(2, Type::UINT, "objectId")
.fragment_out(0, Type::VEC4, "out_transparent_accum")
.fragment_out(1, Type::VEC4, "out_revealage_accum")
.fragment_out(2, Type::UINT, "out_object_id")
.push_constant(Type::BOOL, "forceShadowing")
.typedef_source("workbench_shader_shared.h")
.fragment_source("workbench_transparent_accum_frag.glsl");
GPU_SHADER_CREATE_INFO(workbench_opaque)
.fragment_out(0, Type::VEC4, "materialData")
.fragment_out(1, Type::VEC2, "normalData")
.fragment_out(2, Type::UINT, "objectId")
.fragment_out(0, Type::VEC4, "out_material")
.fragment_out(1, Type::VEC2, "out_normal")
.fragment_out(2, Type::UINT, "out_object_id")
.typedef_source("workbench_shader_shared.h")
.fragment_source("workbench_prepass_frag.glsl");
@@ -147,4 +205,54 @@ GPU_SHADER_CREATE_INFO(workbench_opaque)
WORKBENCH_PIPELINE_VARIATIONS(workbench, "workbench_material");
#undef WORKBENCH_FINAL_VARIATION
#undef WORKBENCH_CLIPPING_VARIATIONS
#undef WORKBENCH_TEXTURE_VARIATIONS
#undef WORKBENCH_DATATYPE_VARIATIONS
#undef WORKBENCH_PIPELINE_VARIATIONS
/** \} */
/* -------------------------------------------------------------------- */
/** \name Variations Declaration
* \{ */
GPU_SHADER_CREATE_INFO(workbench_flat).define("WORKBENCH_SHADING_FLAT");
GPU_SHADER_CREATE_INFO(workbench_studio).define("WORKBENCH_SHADING_STUDIO");
GPU_SHADER_CREATE_INFO(workbench_matcap).define("WORKBENCH_SHADING_MATCAP");
#define WORKBENCH_FINAL_VARIATION(name, ...) \
GPU_SHADER_CREATE_INFO(name).additional_info(__VA_ARGS__).do_static_compilation(true);
#define WORKBENCH_CLIPPING_VARIATIONS(prefix, ...) \
WORKBENCH_FINAL_VARIATION(prefix##_clip, "drw_clipped", __VA_ARGS__) \
WORKBENCH_FINAL_VARIATION(prefix##_no_clip, __VA_ARGS__)
#define WORKBENCH_COLOR_VARIATIONS(prefix, ...) \
WORKBENCH_CLIPPING_VARIATIONS(prefix##_material, "workbench_color_material", __VA_ARGS__) \
WORKBENCH_CLIPPING_VARIATIONS(prefix##_texture, "workbench_color_texture", __VA_ARGS__) \
WORKBENCH_CLIPPING_VARIATIONS(prefix##_vertex, "workbench_color_vertex", __VA_ARGS__)
#define WORKBENCH_SHADING_VARIATIONS(prefix, ...) \
WORKBENCH_COLOR_VARIATIONS(prefix##_flat, "workbench_lighting_flat", __VA_ARGS__) \
WORKBENCH_COLOR_VARIATIONS(prefix##_studio, "workbench_lighting_studio", __VA_ARGS__) \
WORKBENCH_COLOR_VARIATIONS(prefix##_matcap, "workbench_next_lighting_matcap", __VA_ARGS__)
#define WORKBENCH_PIPELINE_VARIATIONS(prefix, ...) \
WORKBENCH_SHADING_VARIATIONS(prefix##_transparent, "workbench_transparent_accum", __VA_ARGS__) \
WORKBENCH_SHADING_VARIATIONS(prefix##_opaque, "workbench_opaque", __VA_ARGS__)
#define WORKBENCH_GEOMETRY_VARIATIONS(prefix, ...) \
WORKBENCH_PIPELINE_VARIATIONS(prefix##_mesh, "workbench_next_mesh", __VA_ARGS__) \
WORKBENCH_PIPELINE_VARIATIONS(prefix##_curves, "workbench_next_curves", __VA_ARGS__) \
WORKBENCH_PIPELINE_VARIATIONS(prefix##_ptcloud, "workbench_next_pointcloud", __VA_ARGS__)
WORKBENCH_GEOMETRY_VARIATIONS(workbench_next_prepass, "workbench_next_prepass");
#undef WORKBENCH_FINAL_VARIATION
#undef WORKBENCH_CLIPPING_VARIATIONS
#undef WORKBENCH_TEXTURE_VARIATIONS
#undef WORKBENCH_DATATYPE_VARIATIONS
#undef WORKBENCH_PIPELINE_VARIATIONS
/** \} */

View File

@@ -1,5 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "draw_defines.h"
#include "gpu_shader_create_info.hh"
/* -------------------------------------------------------------------- */
@@ -9,7 +11,8 @@
GPU_SHADER_INTERFACE_INFO(workbench_shadow_iface, "vData")
.smooth(Type::VEC3, "pos")
.smooth(Type::VEC4, "frontPosition")
.smooth(Type::VEC4, "backPosition");
.smooth(Type::VEC4, "backPosition")
.flat(Type::VEC3, "light_direction_os"); /*Workbench Next*/
GPU_SHADER_CREATE_INFO(workbench_shadow_common)
.vertex_in(0, Type::VEC3, "pos")
@@ -24,6 +27,43 @@ GPU_SHADER_CREATE_INFO(workbench_shadow_common_geom)
.vertex_out(workbench_shadow_iface)
.vertex_source("workbench_shadow_vert.glsl");
GPU_SHADER_CREATE_INFO(workbench_next_shadow_common)
.vertex_in(0, Type::VEC3, "pos")
.vertex_out(workbench_shadow_iface)
.define("WORKBENCH_NEXT")
.uniform_buf(1, "ShadowPassData", "pass_data")
.define("lightDirection", "vData[0].light_direction_os")
.typedef_source("workbench_shader_shared.h")
.additional_info("draw_view")
.additional_info("draw_modelmat_new")
.additional_info("draw_resource_handle_new");
GPU_SHADER_CREATE_INFO(workbench_next_shadow_visibility_compute_common)
.local_group_size(DRW_VISIBILITY_GROUP_SIZE)
.define("DRW_VIEW_LEN", "64")
.storage_buf(0, Qualifier::READ, "ObjectBounds", "bounds_buf[]")
.uniform_buf(2, "ExtrudedFrustum", "extruded_frustum")
.push_constant(Type::INT, "resource_len")
.push_constant(Type::INT, "view_len")
.push_constant(Type::INT, "visibility_word_per_draw")
.push_constant(Type::BOOL, "force_fail_method")
.push_constant(Type::VEC3, "shadow_direction")
.typedef_source("workbench_shader_shared.h")
.compute_source("workbench_shadow_visibility_comp.glsl")
.additional_info("draw_view", "draw_view_culling");
GPU_SHADER_CREATE_INFO(workbench_next_shadow_visibility_compute_dynamic_pass_type)
.additional_info("workbench_next_shadow_visibility_compute_common")
.define("DYNAMIC_PASS_SELECTION")
.storage_buf(1, Qualifier::READ_WRITE, "uint", "pass_visibility_buf[]")
.storage_buf(2, Qualifier::READ_WRITE, "uint", "fail_visibility_buf[]")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(workbench_next_shadow_visibility_compute_static_pass_type)
.additional_info("workbench_next_shadow_visibility_compute_common")
.storage_buf(1, Qualifier::READ_WRITE, "uint", "visibility_buf[]")
.do_static_compilation(true);
/** \} */
/* -------------------------------------------------------------------- */
@@ -79,42 +119,64 @@ GPU_SHADER_CREATE_INFO(workbench_shadow_debug)
.fragment_out(2, Type::UINT, "objectId")
.fragment_source("workbench_shadow_debug_frag.glsl");
GPU_SHADER_CREATE_INFO(workbench_next_shadow_no_debug)
.additional_info("workbench_shadow_no_debug");
GPU_SHADER_CREATE_INFO(workbench_next_shadow_debug).additional_info("workbench_shadow_debug");
/** \} */
/* -------------------------------------------------------------------- */
/** \name Variations Declaration
* \{ */
#define WORKBENCH_SHADOW_VARIATIONS(suffix, ...) \
GPU_SHADER_CREATE_INFO(workbench_shadow_pass_manifold_no_caps##suffix) \
#define WORKBENCH_SHADOW_VARIATIONS(common, prefix, suffix, ...) \
GPU_SHADER_CREATE_INFO(prefix##_pass_manifold_no_caps##suffix) \
.define("SHADOW_PASS") \
.additional_info("workbench_shadow_common", "workbench_shadow_manifold", __VA_ARGS__) \
.additional_info(common, "workbench_shadow_manifold", __VA_ARGS__) \
.do_static_compilation(true); \
GPU_SHADER_CREATE_INFO(workbench_shadow_pass_no_manifold_no_caps##suffix) \
GPU_SHADER_CREATE_INFO(prefix##_pass_no_manifold_no_caps##suffix) \
.define("SHADOW_PASS") \
.define("DOUBLE_MANIFOLD") \
.additional_info("workbench_shadow_common", "workbench_shadow_no_manifold", __VA_ARGS__) \
.additional_info(common, "workbench_shadow_no_manifold", __VA_ARGS__) \
.do_static_compilation(true); \
GPU_SHADER_CREATE_INFO(workbench_shadow_fail_manifold_caps##suffix) \
GPU_SHADER_CREATE_INFO(prefix##_fail_manifold_caps##suffix) \
.define("SHADOW_FAIL") \
.additional_info("workbench_shadow_common", "workbench_shadow_caps", __VA_ARGS__) \
.additional_info(common, "workbench_shadow_caps", __VA_ARGS__) \
.do_static_compilation(true); \
GPU_SHADER_CREATE_INFO(workbench_shadow_fail_manifold_no_caps##suffix) \
GPU_SHADER_CREATE_INFO(prefix##_fail_manifold_no_caps##suffix) \
.define("SHADOW_FAIL") \
.additional_info("workbench_shadow_common", "workbench_shadow_manifold", __VA_ARGS__) \
.additional_info(common, "workbench_shadow_manifold", __VA_ARGS__) \
.do_static_compilation(true); \
GPU_SHADER_CREATE_INFO(workbench_shadow_fail_no_manifold_caps##suffix) \
GPU_SHADER_CREATE_INFO(prefix##_fail_no_manifold_caps##suffix) \
.define("SHADOW_FAIL") \
.define("DOUBLE_MANIFOLD") \
.additional_info("workbench_shadow_common", "workbench_shadow_caps", __VA_ARGS__) \
.additional_info(common, "workbench_shadow_caps", __VA_ARGS__) \
.do_static_compilation(true); \
GPU_SHADER_CREATE_INFO(workbench_shadow_fail_no_manifold_no_caps##suffix) \
GPU_SHADER_CREATE_INFO(prefix##_fail_no_manifold_no_caps##suffix) \
.define("SHADOW_FAIL") \
.define("DOUBLE_MANIFOLD") \
.additional_info("workbench_shadow_common", "workbench_shadow_no_manifold", __VA_ARGS__) \
.additional_info(common, "workbench_shadow_no_manifold", __VA_ARGS__) \
.do_static_compilation(true);
WORKBENCH_SHADOW_VARIATIONS(, "workbench_shadow_no_debug")
WORKBENCH_SHADOW_VARIATIONS(_debug, "workbench_shadow_debug")
WORKBENCH_SHADOW_VARIATIONS("workbench_shadow_common",
workbench_shadow,
,
"workbench_shadow_no_debug")
WORKBENCH_SHADOW_VARIATIONS("workbench_shadow_common",
workbench_shadow,
_debug,
"workbench_shadow_debug")
WORKBENCH_SHADOW_VARIATIONS("workbench_next_shadow_common",
workbench_next_shadow,
,
"workbench_next_shadow_no_debug")
WORKBENCH_SHADOW_VARIATIONS("workbench_next_shadow_common",
workbench_next_shadow,
_debug,
"workbench_next_shadow_debug")
/** \} */

View File

@@ -5,6 +5,12 @@
/* From The Alchemy screen-space ambient obscurance algorithm
* http://graphics.cs.williams.edu/papers/AlchemyHPG11/VV11AlchemyAO.pdf */
#ifdef WORKBENCH_CAVITY
# define USE_CAVITY
# define cavityJitter jitter_tx
# define samples_coords cavity_samples
#endif
#ifdef USE_CAVITY
void cavity_compute(vec2 screenco,

View File

@@ -16,18 +16,18 @@ void main()
float roughness, metallic;
workbench_float_pair_decode(mat_data.a, roughness, metallic);
#ifdef V3D_LIGHTING_MATCAP
#ifdef WORKBENCH_LIGHTING_MATCAP
/* When using matcaps, mat_data.a is the back-face sign. */
N = (mat_data.a > 0.0) ? N : -N;
fragColor.rgb = get_matcap_lighting(matcap_diffuse_tx, matcap_specular_tx, base_color, N, I);
#endif
#ifdef V3D_LIGHTING_STUDIO
#ifdef WORKBENCH_LIGHTING_STUDIO
fragColor.rgb = get_world_lighting(base_color, roughness, metallic, N, I);
#endif
#ifdef V3D_LIGHTING_FLAT
#ifdef WORKBENCH_LIGHTING_FLAT
fragColor.rgb = base_color;
#endif

View File

@@ -1,6 +1,10 @@
#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
#ifdef WORKBENCH_CURVATURE
# define USE_CURVATURE
#endif
#ifdef USE_CURVATURE
float curvature_soft_clamp(float curvature, float control)

View File

@@ -27,10 +27,27 @@ bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map)
vec3 workbench_image_color(vec2 uvs)
{
#ifdef V3D_SHADING_TEXTURE_COLOR
#ifdef WORKBENCH_COLOR_TEXTURE
vec4 color;
# ifdef TEXTURE_IMAGE_ARRAY
# ifdef WORKBENCH_NEXT
vec3 co = vec3(uvs, 0.0);
if (isImageTile) {
if (node_tex_tile_lookup(co, imageTileArray, imageTileData)) {
color = texture(imageTileArray, co);
}
else {
color = vec4(1.0, 0.0, 1.0, 1.0);
}
}
else {
color = texture(imageTexture, uvs);
}
# else // WORKBENCH_NEXT
# ifdef WORKBENCH_TEXTURE_IMAGE_ARRAY
vec3 co = vec3(uvs, 0.0);
if (node_tex_tile_lookup(co, imageTileArray, imageTileData)) {
color = texture(imageTileArray, co);
@@ -38,10 +55,12 @@ vec3 workbench_image_color(vec2 uvs)
else {
color = vec4(1.0, 0.0, 1.0, 1.0);
}
# else
# else
color = texture(imageTexture, uvs);
# endif
# endif
# endif // WORKBENCH_NEXT
/* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
if (imagePremult && !(color.a == 0.0 || color.a == 1.0)) {

View File

@@ -24,3 +24,14 @@ vec3 get_matcap_lighting(
return diffuse * base_color + specular * float(world_data.use_specular);
}
vec3 get_matcap_lighting(sampler2DArray matcap, vec3 base_color, vec3 N, vec3 I)
{
bool flipped = world_data.matcap_orientation != 0;
vec2 uv = matcap_uv_compute(I, N, flipped);
vec3 diffuse = textureLod(matcap, vec3(uv, 0.0), 0.0).rgb;
vec3 specular = textureLod(matcap, vec3(uv, 1.0), 0.0).rgb;
return diffuse * base_color + specular * float(world_data.use_specular);
}

View File

@@ -1,10 +1,28 @@
void workbench_material_data_get(
int handle, out vec3 color, out float alpha, out float roughness, out float metallic)
void workbench_material_data_get(int handle,
vec3 vertex_color,
out vec3 color,
out float alpha,
out float roughness,
out float metallic)
{
#ifndef WORKBENCH_NEXT
handle = (materialIndex != -1) ? materialIndex : handle;
vec4 data = materials_data[uint(handle) & 0xFFFu];
color = data.rgb;
if (materialIndex == 0) {
color_interp = vertex_color;
}
#else
# ifdef WORKBENCH_COLOR_MATERIAL
vec4 data = materials_data[handle];
# else
vec4 data = vec4(0.0);
# endif
color = (data.r == -1) ? vertex_color : data.rgb;
#endif
uint encoded_data = floatBitsToUint(data.w);
alpha = float((encoded_data >> 16u) & 0xFFu) * (1.0 / 255.0);

View File

@@ -0,0 +1,81 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
#pragma BLENDER_REQUIRE(workbench_matcap_lib.glsl)
#pragma BLENDER_REQUIRE(workbench_world_light_lib.glsl)
#pragma BLENDER_REQUIRE(workbench_cavity_lib.glsl)
#pragma BLENDER_REQUIRE(workbench_curvature_lib.glsl)
void main()
{
vec2 uv = uvcoordsvar.st;
/* Normal and Incident vector are in viewspace. Lighting is evaluated in viewspace. */
vec3 V = get_view_vector_from_screen_uv(uv);
vec3 N = workbench_normal_decode(texture(normal_tx, uv));
vec4 mat_data = texture(material_tx, uv);
float depth = texture(depth_tx, uv).r;
vec3 base_color = mat_data.rgb;
vec4 color = world_data.background_color;
/* Background pixels. */
if (depth != 1.0) {
#ifdef WORKBENCH_LIGHTING_MATCAP
/* When using matcaps, mat_data.a is the back-face sign. */
N = (mat_data.a > 0.0) ? N : -N;
color.rgb = get_matcap_lighting(matcap_tx, base_color, N, V);
#endif
#ifdef WORKBENCH_LIGHTING_STUDIO
float roughness, metallic;
workbench_float_pair_decode(mat_data.a, roughness, metallic);
color.rgb = get_world_lighting(base_color, roughness, metallic, N, V);
#endif
#ifdef WORKBENCH_LIGHTING_FLAT
color.rgb = base_color;
#endif
#if defined(WORKBENCH_CAVITY) || defined(WORKBENCH_CURVATURE)
float cavity = 0.0, edges = 0.0, curvature = 0.0;
# ifdef WORKBENCH_CAVITY
cavity_compute(uv, depth_tx, normal_tx, cavity, edges);
# endif
# ifdef WORKBENCH_CURVATURE
curvature_compute(uv, object_id_tx, normal_tx, curvature);
# endif
float final_cavity_factor = clamp(
(1.0 - cavity) * (1.0 + edges) * (1.0 + curvature), 0.0, 4.0);
color.rgb *= final_cavity_factor;
#endif
bool shadow = texture(stencil_tx, uv).r != 0;
color.rgb *= get_shadow(N, shadow);
color.a = 1.0f;
}
#ifdef WORKBENCH_OUTLINE
vec3 offset = vec3(world_data.viewport_size_inv, 0.0) * world_data.ui_scale;
uint center_id = texture(object_id_tx, uv).r;
uvec4 adjacent_ids = uvec4(texture(object_id_tx, uv + offset.zy).r,
texture(object_id_tx, uv - offset.zy).r,
texture(object_id_tx, uv + offset.xz).r,
texture(object_id_tx, uv - offset.xz).r);
float outline_opacity = 1.0 - dot(vec4(equal(uvec4(center_id), adjacent_ids)), vec4(0.25));
color = mix(color, world_data.object_outline_color, outline_opacity);
#endif
if (all(equal(color, world_data.background_color))) {
discard;
}
else {
fragColor = color;
}
}

View File

@@ -0,0 +1,11 @@
void main()
{
float depth = texture(depth_tx, uvcoordsvar.xy).r;
if (depth != 1.0) {
gl_FragDepth = depth;
}
else {
discard;
}
}

View File

@@ -3,20 +3,43 @@
#pragma BLENDER_REQUIRE(workbench_common_lib.glsl)
#pragma BLENDER_REQUIRE(workbench_image_lib.glsl)
#ifdef WORKBENCH_NEXT
void main()
{
normalData = workbench_normal_encode(gl_FrontFacing, normal_interp);
out_object_id = uint(object_id);
out_normal = workbench_normal_encode(gl_FrontFacing, normal_interp);
materialData = vec4(color_interp, workbench_float_pair_encode(_roughness, metallic));
out_material = vec4(color_interp, workbench_float_pair_encode(_roughness, metallic));
objectId = uint(object_id);
# ifdef WORKBENCH_COLOR_TEXTURE
out_material.rgb = workbench_image_color(uv_interp);
# endif
# ifdef WORKBENCH_LIGHTING_MATCAP
/* For matcaps, save front facing in alpha channel. */
out_material.a = float(gl_FrontFacing);
# endif
}
#else
void main()
{
out_normal = workbench_normal_encode(gl_FrontFacing, normal_interp);
out_material = vec4(color_interp, workbench_float_pair_encode(_roughness, metallic));
out_object_id = uint(object_id);
if (useMatcap) {
/* For matcaps, save front facing in alpha channel. */
materialData.a = float(gl_FrontFacing);
out_material.a = float(gl_FrontFacing);
}
#ifdef V3D_SHADING_TEXTURE_COLOR
materialData.rgb = workbench_image_color(uv_interp);
#endif
# ifdef WORKBENCH_COLOR_TEXTURE
out_material.rgb = workbench_image_color(uv_interp);
# endif
}
#endif

View File

@@ -68,11 +68,12 @@ void main()
normal_interp = normalize(normal_world_to_view(nor));
workbench_material_data_get(resource_handle, color_interp, alpha_interp, _roughness, metallic);
if (materialIndex == 0) {
color_interp = hair_get_customdata_vec3(ac);
}
workbench_material_data_get(resource_handle,
hair_get_customdata_vec3(ac),
color_interp,
alpha_interp,
_roughness,
metallic);
/* Hairs have lots of layer and can rapidly become the most prominent surface.
* So we lower their alpha artificially. */

View File

@@ -19,11 +19,8 @@ void main()
uv_interp = vec2(0.0);
workbench_material_data_get(resource_handle, color_interp, alpha_interp, _roughness, metallic);
if (materialIndex == 0) {
color_interp = vec3(1.0);
}
workbench_material_data_get(
resource_handle, vec3(1.0), color_interp, alpha_interp, _roughness, metallic);
object_id = int(uint(resource_handle) & 0xFFFFu) + 1;
}

View File

@@ -16,11 +16,8 @@ void main()
normal_interp = normalize(normal_object_to_view(nor));
workbench_material_data_get(resource_handle, color_interp, alpha_interp, _roughness, metallic);
if (materialIndex == 0) {
color_interp = ac.rgb;
}
workbench_material_data_get(
resource_handle, ac.rgb, color_interp, alpha_interp, _roughness, metallic);
object_id = int(uint(resource_handle) & 0xFFFFu) + 1;
}

View File

@@ -5,6 +5,18 @@ void main()
{
vData.pos = pos;
vData.frontPosition = point_object_to_ndc(pos);
vec3 back_pos = pos + lightDirection * lightDistance;
vData.backPosition = point_object_to_ndc(back_pos);
#ifdef WORKBENCH_NEXT
vData.light_direction_os = normal_world_to_object(pass_data.light_direction_ws);
vec3 pos_ws = point_object_to_world(pos);
float extrude_distance = 1e5f;
float LDoFP = dot(pass_data.light_direction_ws, pass_data.far_plane.xyz);
if (LDoFP > 0) {
float signed_distance = dot(pass_data.far_plane.xyz, pos_ws) - pass_data.far_plane.w;
extrude_distance = -signed_distance / LDoFP;
}
vData.backPosition = point_world_to_ndc(pos_ws +
pass_data.light_direction_ws * extrude_distance);
#else
vData.backPosition = point_object_to_ndc(pos + lightDirection * lightDistance);
#endif
}

View File

@@ -0,0 +1,93 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_intersect_lib.glsl)
shared uint shared_result;
#ifdef DYNAMIC_PASS_SELECTION
void set_visibility(bool pass, bool fail)
{
if (!pass) {
atomicAnd(pass_visibility_buf[gl_WorkGroupID.x], ~(1u << gl_LocalInvocationID.x));
}
if (!fail) {
atomicAnd(fail_visibility_buf[gl_WorkGroupID.x], ~(1u << gl_LocalInvocationID.x));
}
}
#else
void set_visibility(bool visibility)
{
if (!visibility) {
atomicAnd(visibility_buf[gl_WorkGroupID.x], ~(1u << gl_LocalInvocationID.x));
}
}
#endif
bool is_visible(IsectBox box)
{
for (int i_plane = 0; i_plane < extruded_frustum.planes_count; i_plane++) {
vec4 plane = extruded_frustum.planes[i_plane];
bool separating_axis = true;
for (int i_corner = 0; i_corner < 8; i_corner++) {
float signed_distance = dot(box.corners[i_corner], plane.xyz) - plane.w;
if (signed_distance <= 0) {
separating_axis = false;
break;
}
}
if (separating_axis) {
return false;
}
}
return true;
}
bool intersects_near_plane(IsectBox box)
{
vec4 near_plane = drw_view_culling.planes[4];
bool on_positive_side = false;
bool on_negative_side = false;
for (int i_corner = 0; i_corner < 8; i_corner++) {
for (int i_displace = 0; i_displace < 2; i_displace++) {
vec3 corner = box.corners[i_corner] + (shadow_direction * 1e5f * i_displace);
float signed_distance = dot(corner, -near_plane.xyz) - near_plane.w;
if (signed_distance <= 0) {
on_negative_side = true;
}
else {
on_positive_side = true;
}
if (on_negative_side && on_positive_side) {
return true;
}
}
}
return false;
}
void main()
{
if (gl_GlobalInvocationID.x >= resource_len) {
return;
}
ObjectBounds bounds = bounds_buf[gl_GlobalInvocationID.x];
IsectBox box = isect_data_setup(bounds.bounding_corners[0].xyz,
bounds.bounding_corners[1].xyz,
bounds.bounding_corners[2].xyz,
bounds.bounding_corners[3].xyz);
#ifdef DYNAMIC_PASS_SELECTION
if (is_visible(box)) {
bool use_fail_pass = force_fail_method || intersects_near_plane(box);
set_visibility(!use_fail_pass, use_fail_pass);
}
else {
set_visibility(false, false);
}
#else
set_visibility(is_visible(box));
#endif
}

View File

@@ -45,6 +45,8 @@ float calculate_transparent_weight(void)
return clamp(w, 1e-2, 3e2);
}
#ifdef WORKBENCH_NEXT
void main()
{
/* Normal and Incident vector are in viewspace. Lighting is evaluated in viewspace. */
@@ -54,28 +56,68 @@ void main()
vec3 color = color_interp;
#ifdef V3D_SHADING_TEXTURE_COLOR
# ifdef WORKBENCH_COLOR_TEXTURE
color = workbench_image_color(uv_interp);
#endif
# endif
#ifdef V3D_LIGHTING_MATCAP
vec3 shaded_color = get_matcap_lighting(matcap_diffuse_tx, matcap_specular_tx, color, N, I);
#endif
# ifdef WORKBENCH_LIGHTING_MATCAP
vec3 shaded_color = get_matcap_lighting(matcap_tx, color, N, I);
# endif
#ifdef V3D_LIGHTING_STUDIO
# ifdef WORKBENCH_LIGHTING_STUDIO
vec3 shaded_color = get_world_lighting(color, _roughness, metallic, N, I);
#endif
# endif
#ifdef V3D_LIGHTING_FLAT
# ifdef WORKBENCH_LIGHTING_FLAT
vec3 shaded_color = color;
#endif
# endif
shaded_color *= get_shadow(N, forceShadowing);
/* Listing 4 */
float alpha = alpha_interp * world_data.xray_alpha;
float weight = calculate_transparent_weight() * alpha;
out_transparent_accum = vec4(shaded_color * weight, alpha);
out_revealage_accum = vec4(weight);
out_object_id = uint(object_id);
}
#else
void main()
{
/* Normal and Incident vector are in viewspace. Lighting is evaluated in viewspace. */
vec2 uv_viewport = gl_FragCoord.xy * world_data.viewport_size_inv;
vec3 I = get_view_vector_from_screen_uv(uv_viewport);
vec3 N = normalize(normal_interp);
vec3 color = color_interp;
# ifdef WORKBENCH_COLOR_TEXTURE
color = workbench_image_color(uv_interp);
# endif
# ifdef WORKBENCH_LIGHTING_MATCAP
vec3 shaded_color = get_matcap_lighting(matcap_diffuse_tx, matcap_specular_tx, color, N, I);
# endif
# ifdef WORKBENCH_LIGHTING_STUDIO
vec3 shaded_color = get_world_lighting(color, _roughness, metallic, N, I);
# endif
# ifdef WORKBENCH_LIGHTING_FLAT
vec3 shaded_color = color;
# endif
shaded_color *= get_shadow(N, forceShadowing);
/* Listing 4 */
float weight = calculate_transparent_weight() * alpha_interp;
transparentAccum = vec4(shaded_color * weight, alpha_interp);
revealageAccum = vec4(weight);
out_transparent_accum = vec4(shaded_color * weight, alpha_interp);
out_revealage_accum = vec4(weight);
objectId = uint(object_id);
out_object_id = uint(object_id);
}
#endif

View File

@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#define WB_MATCAP_SLOT 0
#define WB_TEXTURE_SLOT 1
#define WB_TILE_ARRAY_SLOT 2
#define WB_TILE_DATA_SLOT 3
#define WB_MATERIAL_SLOT 0
#define WB_WORLD_SLOT 4
#define WB_RESOLVE_GROUP_SIZE 8

View File

@@ -0,0 +1,311 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "workbench_private.hh"
#include "BLI_jitter_2d.h"
#include "smaa_textures.h"
namespace blender::workbench {
class TaaSamples {
void init_samples(Array<float2> &samples, const int size)
{
samples = Array<float2>(size);
BLI_jitter_init((float(*)[2])samples.begin(), size);
/* Find closest element to center */
int closest_index = 0;
float closest_squared_distance = 1.0f;
for (int i : samples.index_range()) {
float2 sample = samples[i];
const float squared_dist = len_squared_v2(sample);
if (squared_dist < closest_squared_distance) {
closest_squared_distance = squared_dist;
closest_index = i;
}
}
float2 closest_sample = samples[closest_index];
for (float2 &sample : samples) {
/* Move jitter samples so that closest sample is in center */
sample -= closest_sample;
/* Avoid samples outside range (wrap around). */
sample = {fmodf(sample.x + 0.5f, 1.0f), fmodf(sample.y + 0.5f, 1.0f)};
/* Recenter the distribution[-1..1]. */
sample = (sample * 2.0f) - 1.0f;
}
/* Swap center sample to the start of the array */
if (closest_index != 0) {
std::swap(samples[0], samples[closest_index]);
}
/* Sort list based on farthest distance with previous. */
for (int i = 0; i < size - 2; i++) {
float squared_dist = 0.0;
int index = i;
for (int j = i + 1; j < size; j++) {
const float _squared_dist = len_squared_v2(samples[i] - samples[j]);
if (_squared_dist > squared_dist) {
squared_dist = _squared_dist;
index = j;
}
}
std::swap(samples[i + 1], samples[index]);
}
}
public:
Array<float2> x5;
Array<float2> x8;
Array<float2> x11;
Array<float2> x16;
Array<float2> x32;
TaaSamples()
{
init_samples(x5, 5);
init_samples(x8, 8);
init_samples(x11, 11);
init_samples(x16, 16);
init_samples(x32, 32);
}
};
static TaaSamples TAA_SAMPLES = TaaSamples();
static float filter_blackman_harris(float x, const float width)
{
if (x > width * 0.5f) {
return 0.0f;
}
x = 2.0f * M_PI * clamp_f((x / width + 0.5f), 0.0f, 1.0f);
return 0.35875f - 0.48829f * math::cos(x) + 0.14128f * math::cos(2.0f * x) -
0.01168f * math::cos(3.0f * x);
}
/* Compute weights for the 3x3 neighborhood using a 1.5px filter. */
static void setup_taa_weights(const float2 offset, float r_weights[9], float &r_weight_sum)
{
/* NOTE: If filter width is bigger than 2.0f, then we need to sample more neighborhood. */
const float filter_width = 2.0f;
r_weight_sum = 0.0f;
int i = 0;
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++, i++) {
float2 sample_co = float2(x, y) - offset;
float r = len_v2(sample_co);
/* fclem: Is radial distance ok here? */
float weight = filter_blackman_harris(r, filter_width);
r_weight_sum += weight;
r_weights[i] = weight;
}
}
}
AntiAliasingPass::AntiAliasingPass()
{
taa_accumulation_sh_ = GPU_shader_create_from_info_name("workbench_taa");
smaa_edge_detect_sh_ = GPU_shader_create_from_info_name("workbench_smaa_stage_0");
smaa_aa_weight_sh_ = GPU_shader_create_from_info_name("workbench_smaa_stage_1");
smaa_resolve_sh_ = GPU_shader_create_from_info_name("workbench_smaa_stage_2");
smaa_search_tx_.ensure_2d(
GPU_R8, {SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}, GPU_TEXTURE_USAGE_SHADER_READ);
GPU_texture_update(smaa_search_tx_, GPU_DATA_UBYTE, searchTexBytes);
GPU_texture_filter_mode(smaa_search_tx_, true);
smaa_area_tx_.ensure_2d(GPU_RG8, {AREATEX_WIDTH, AREATEX_HEIGHT}, GPU_TEXTURE_USAGE_SHADER_READ);
GPU_texture_update(smaa_area_tx_, GPU_DATA_UBYTE, areaTexBytes);
GPU_texture_filter_mode(smaa_area_tx_, true);
}
AntiAliasingPass::~AntiAliasingPass()
{
DRW_SHADER_FREE_SAFE(taa_accumulation_sh_);
DRW_SHADER_FREE_SAFE(smaa_edge_detect_sh_);
DRW_SHADER_FREE_SAFE(smaa_aa_weight_sh_);
DRW_SHADER_FREE_SAFE(smaa_resolve_sh_);
}
void AntiAliasingPass::init(const SceneState &scene_state)
{
enabled_ = scene_state.draw_aa;
sample_ = scene_state.sample;
samples_len_ = scene_state.samples_len;
}
void AntiAliasingPass::sync(SceneResources &resources, int2 resolution)
{
if (!enabled_) {
taa_accumulation_tx_.free();
sample0_depth_tx_.free();
return;
}
taa_accumulation_tx_.ensure_2d(
GPU_RGBA16F, resolution, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT);
sample0_depth_tx_.ensure_2d(GPU_DEPTH24_STENCIL8,
resolution,
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT);
taa_accumulation_ps_.init();
taa_accumulation_ps_.state_set(sample_ == 0 ? DRW_STATE_WRITE_COLOR :
DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL);
taa_accumulation_ps_.shader_set(taa_accumulation_sh_);
taa_accumulation_ps_.bind_texture("colorBuffer", &resources.color_tx);
taa_accumulation_ps_.push_constant("samplesWeights", weights_, 9);
taa_accumulation_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
smaa_edge_detect_ps_.init();
smaa_edge_detect_ps_.state_set(DRW_STATE_WRITE_COLOR);
smaa_edge_detect_ps_.shader_set(smaa_edge_detect_sh_);
smaa_edge_detect_ps_.bind_texture("colorTex", &taa_accumulation_tx_);
smaa_edge_detect_ps_.push_constant("viewportMetrics", &smaa_viewport_metrics_, 1);
smaa_edge_detect_ps_.clear_color(float4(0.0f));
smaa_edge_detect_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
smaa_aa_weight_ps_.init();
smaa_aa_weight_ps_.state_set(DRW_STATE_WRITE_COLOR);
smaa_aa_weight_ps_.shader_set(smaa_aa_weight_sh_);
smaa_aa_weight_ps_.bind_texture("edgesTex", &smaa_edge_tx_);
smaa_aa_weight_ps_.bind_texture("areaTex", smaa_area_tx_);
smaa_aa_weight_ps_.bind_texture("searchTex", smaa_search_tx_);
smaa_aa_weight_ps_.push_constant("viewportMetrics", &smaa_viewport_metrics_, 1);
smaa_aa_weight_ps_.clear_color(float4(0.0f));
smaa_aa_weight_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
smaa_resolve_ps_.init();
smaa_resolve_ps_.state_set(DRW_STATE_WRITE_COLOR);
smaa_resolve_ps_.shader_set(smaa_resolve_sh_);
smaa_resolve_ps_.bind_texture("blendTex", &smaa_weight_tx_);
smaa_resolve_ps_.bind_texture("colorTex", &taa_accumulation_tx_);
smaa_resolve_ps_.push_constant("viewportMetrics", &smaa_viewport_metrics_, 1);
smaa_resolve_ps_.push_constant("mixFactor", &smaa_mix_factor_, 1);
smaa_resolve_ps_.push_constant("taaAccumulatedWeight", &weight_accum_, 1);
smaa_resolve_ps_.clear_color(float4(0.0f));
smaa_resolve_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
void AntiAliasingPass::setup_view(View &view, int2 resolution)
{
if (!enabled_) {
return;
}
float2 sample_offset;
switch (samples_len_) {
default:
case 5:
sample_offset = TAA_SAMPLES.x5[sample_];
break;
case 8:
sample_offset = TAA_SAMPLES.x8[sample_];
break;
case 11:
sample_offset = TAA_SAMPLES.x11[sample_];
break;
case 16:
sample_offset = TAA_SAMPLES.x16[sample_];
break;
case 32:
sample_offset = TAA_SAMPLES.x32[sample_];
break;
}
setup_taa_weights(sample_offset, weights_, weights_sum_);
/* TODO(Miguel Pozo): New API equivalent? */
const DRWView *default_view = DRW_view_default_get();
float4x4 winmat, viewmat, persmat;
/* Construct new matrices from transform delta */
DRW_view_winmat_get(default_view, winmat.ptr(), false);
DRW_view_viewmat_get(default_view, viewmat.ptr(), false);
DRW_view_persmat_get(default_view, persmat.ptr(), false);
window_translate_m4(
winmat.ptr(), persmat.ptr(), sample_offset.x / resolution.x, sample_offset.y / resolution.y);
view.sync(viewmat, winmat);
}
void AntiAliasingPass::draw(Manager &manager,
View &view,
SceneResources &resources,
int2 resolution,
GPUTexture *depth_tx,
GPUTexture *color_tx)
{
if (!enabled_) {
/* TODO(Miguel Pozo): Should render to the input color_tx and depth_tx in the first place.
* This requires the use of TextureRefs with stencil_view() support,
* but whether TextureRef will stay is still TBD. */
GPU_texture_copy(color_tx, resources.color_tx);
GPU_texture_copy(depth_tx, resources.depth_tx);
return;
}
/**
* We always do SMAA on top of TAA accumulation, unless the number of samples of TAA is already
* high. This ensure a smoother transition.
* If TAA accumulation is finished, we only blit the result.
*/
const bool last_sample = sample_ + 1 == samples_len_;
const bool taa_finished = sample_ >= samples_len_;
if (!taa_finished) {
if (sample_ == 0) {
weight_accum_ = 0;
}
/* Accumulate result to the TAA buffer. */
taa_accumulation_fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(taa_accumulation_tx_));
taa_accumulation_fb_.bind();
manager.submit(taa_accumulation_ps_, view);
weight_accum_ += weights_sum_;
}
if (sample_ == 0) {
if (sample0_depth_tx_.is_valid()) {
GPU_texture_copy(sample0_depth_tx_, resources.depth_tx);
}
/* TODO(Miguel Pozo): Should render to the input depth_tx in the first place
* This requires the use of TextureRef with stencil_view() support,
* but whether TextureRef will stay is still TBD. */
/* Copy back the saved depth buffer for correct overlays. */
GPU_texture_copy(depth_tx, resources.depth_tx);
}
else {
/* Copy back the saved depth buffer for correct overlays. */
GPU_texture_copy(depth_tx, sample0_depth_tx_);
}
if (!DRW_state_is_image_render() || last_sample) {
smaa_weight_tx_.acquire(
resolution, GPU_RGBA8, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT);
smaa_mix_factor_ = 1.0f - clamp_f(sample_ / 4.0f, 0.0f, 1.0f);
smaa_viewport_metrics_ = float4(float2(1.0f / float2(resolution)), resolution);
/* After a certain point SMAA is no longer necessary. */
if (smaa_mix_factor_ > 0.0f) {
smaa_edge_tx_.acquire(
resolution, GPU_RG8, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT);
smaa_edge_fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(smaa_edge_tx_));
smaa_edge_fb_.bind();
manager.submit(smaa_edge_detect_ps_, view);
smaa_weight_fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(smaa_weight_tx_));
smaa_weight_fb_.bind();
manager.submit(smaa_aa_weight_ps_, view);
smaa_edge_tx_.release();
}
smaa_resolve_fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(color_tx));
smaa_resolve_fb_.bind();
manager.submit(smaa_resolve_ps_, view);
smaa_weight_tx_.release();
}
}
} // namespace blender::workbench

View File

@@ -0,0 +1,89 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup draw_engine
*
* Cavity Effect:
*
* We use Screen Space Ambient Occlusion (SSAO) to enhance geometric details of the surfaces.
* We also use a Curvature effect computed only using the surface normals.
*
* This is done as part of the opaque resolve pass. It only affects the opaque surfaces.
*/
#include "BLI_rand.h"
#include "workbench_private.hh"
namespace blender::workbench {
void CavityEffect::init(const SceneState &scene_state, SceneResources &resources)
{
cavity_enabled_ = scene_state.draw_cavity;
curvature_enabled_ = scene_state.draw_curvature;
const int ssao_samples = scene_state.scene->display.matcap_ssao_samples;
int sample_count = min_ii(scene_state.samples_len * ssao_samples, max_samples_);
const int max_iter_count = sample_count / ssao_samples;
sample_ = scene_state.sample % max_iter_count;
UniformBuffer<WorldData> &world_buf = resources.world_buf;
world_buf.cavity_sample_start = ssao_samples * sample_;
world_buf.cavity_sample_end = ssao_samples * (sample_ + 1);
world_buf.cavity_sample_count_inv = 1.0f / (world_buf.cavity_sample_end -
world_buf.cavity_sample_start);
world_buf.cavity_jitter_scale = 1.0f / 64.0f;
world_buf.cavity_valley_factor = scene_state.shading.cavity_valley_factor;
world_buf.cavity_ridge_factor = scene_state.shading.cavity_ridge_factor;
world_buf.cavity_attenuation = scene_state.scene->display.matcap_ssao_attenuation;
world_buf.cavity_distance = scene_state.scene->display.matcap_ssao_distance;
world_buf.curvature_ridge = 0.5f /
max_ff(square_f(scene_state.shading.curvature_ridge_factor), 1e-4f);
world_buf.curvature_valley = 0.7f / max_ff(square_f(scene_state.shading.curvature_valley_factor),
1e-4f);
if (cavity_enabled_ && sample_count_ != sample_count) {
sample_count_ = sample_count;
load_samples_buf(ssao_samples);
resources.load_jitter_tx(sample_count_);
}
}
void CavityEffect::load_samples_buf(int ssao_samples)
{
const float iteration_samples_inv = 1.0f / ssao_samples;
/* Create disk samples using Hammersley distribution */
for (int i : IndexRange(sample_count_)) {
float it_add = (i / ssao_samples) * 0.499f;
float r = fmodf((i + 0.5f + it_add) * iteration_samples_inv, 1.0f);
double dphi;
BLI_hammersley_1d(i, &dphi);
float phi = float(dphi) * 2.0f * M_PI + it_add;
samples_buf[i].x = math::cos(phi);
samples_buf[i].y = math::sin(phi);
/* This deliberately distribute more samples
* at the center of the disk (and thus the shadow). */
samples_buf[i].z = r;
}
samples_buf.push_update();
}
void CavityEffect::setup_resolve_pass(PassSimple &pass, SceneResources &resources)
{
if (cavity_enabled_) {
pass.bind_ubo("cavity_samples", samples_buf);
pass.bind_texture("jitter_tx", &resources.jitter_tx, eGPUSamplerState::GPU_SAMPLER_REPEAT);
}
if (curvature_enabled_) {
pass.bind_texture("object_id_tx", &resources.object_id_tx);
}
}
} // namespace blender::workbench

View File

@@ -0,0 +1,271 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup draw_engine
*
* Depth of Field Effect:
*
* We use a gather approach by sampling a lowres version of the color buffer.
* The process can be summarized like this:
* - down-sample the color buffer using a COC (Circle of Confusion) aware down-sample algorithm.
* - do a gather pass using the COC computed in the previous pass.
* - do a median filter to reduce noise amount.
* - composite on top of main color buffer.
*
* This is done after all passes and affects every surfaces.
*/
#include "workbench_private.hh"
#include "BKE_camera.h"
#include "DEG_depsgraph_query.h"
namespace blender::workbench {
/**
* Transform [-1..1] square to unit circle.
*/
static void square_to_circle(float x, float y, float &r, float &T)
{
if (x > -y) {
if (x > y) {
r = x;
T = M_PI_4 * (y / x);
}
else {
r = y;
T = M_PI_4 * (2 - (x / y));
}
}
else {
if (x < y) {
r = -x;
T = M_PI_4 * (4 + (y / x));
}
else {
r = -y;
if (y != 0) {
T = M_PI_4 * (6 - (x / y));
}
else {
T = 0.0f;
}
}
}
}
void DofPass::setup_samples()
{
float4 *sample = samples_buf_.begin();
for (int i = 0; i <= kernel_radius_; i++) {
for (int j = -kernel_radius_; j <= kernel_radius_; j++) {
for (int k = -kernel_radius_; k <= kernel_radius_; k++) {
if (abs(j) > i || abs(k) > i) {
continue;
}
if (abs(j) < i && abs(k) < i) {
continue;
}
float2 coord = float2(j, k) / float2(kernel_radius_);
float r = 0;
float T = 0;
square_to_circle(coord.x, coord.y, r, T);
sample->z = r;
/* Bokeh shape parameterization. */
if (blades_ > 1.0f) {
float denom = T - (2.0 * M_PI / blades_) * floorf((blades_ * T + M_PI) / (2.0 * M_PI));
r *= math::cos(M_PI / blades_) / math::cos(denom);
}
T += rotation_;
sample->x = r * math::cos(T) * ratio_;
sample->y = r * math::sin(T);
sample->w = 0;
sample++;
}
}
}
samples_buf_.push_update();
}
void DofPass::init(const SceneState &scene_state)
{
enabled_ = scene_state.draw_dof;
if (!enabled_) {
source_tx_.free();
coc_halfres_tx_.free();
return;
}
if (prepare_sh_ == nullptr) {
prepare_sh_ = GPU_shader_create_from_info_name("workbench_effect_dof_prepare");
downsample_sh_ = GPU_shader_create_from_info_name("workbench_effect_dof_downsample");
blur1_sh_ = GPU_shader_create_from_info_name("workbench_effect_dof_blur1");
blur2_sh_ = GPU_shader_create_from_info_name("workbench_effect_dof_blur2");
resolve_sh_ = GPU_shader_create_from_info_name("workbench_effect_dof_resolve");
}
offset_ = scene_state.sample / float(scene_state.samples_len);
int2 half_res = scene_state.resolution / 2;
half_res = {max_ii(half_res.x, 1), max_ii(half_res.y, 1)};
source_tx_.ensure_2d(GPU_RGBA16F, half_res, GPU_TEXTURE_USAGE_SHADER_READ, nullptr, 3);
source_tx_.ensure_mip_views();
source_tx_.filter_mode(true);
coc_halfres_tx_.ensure_2d(GPU_RG8, half_res, GPU_TEXTURE_USAGE_SHADER_READ, nullptr, 3);
coc_halfres_tx_.ensure_mip_views();
coc_halfres_tx_.filter_mode(true);
Camera *camera = scene_state.camera;
/* Parameters */
float fstop = camera->dof.aperture_fstop;
float sensor = BKE_camera_sensor_size(camera->sensor_fit, camera->sensor_x, camera->sensor_y);
float focus_dist = BKE_camera_object_dof_distance(scene_state.camera_object);
float focal_len = camera->lens;
/* TODO(fclem): De-duplicate with EEVEE. */
const float scale_camera = 0.001f;
/* We want radius here for the aperture number. */
float aperture = 0.5f * scale_camera * focal_len / fstop;
float focal_len_scaled = scale_camera * focal_len;
float sensor_scaled = scale_camera * sensor;
if (RegionView3D *rv3d = DRW_context_state_get()->rv3d) {
sensor_scaled *= rv3d->viewcamtexcofac[0];
}
aperture_size_ = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled));
distance_ = -focus_dist;
invsensor_size_ = scene_state.resolution.x / sensor_scaled;
near_ = -camera->clip_start;
far_ = -camera->clip_end;
float blades = camera->dof.aperture_blades;
float rotation = camera->dof.aperture_rotation;
float ratio = 1.0f / camera->dof.aperture_ratio;
if (blades_ != blades || rotation_ != rotation || ratio_ != ratio) {
blades_ = blades;
rotation_ = rotation;
ratio_ = ratio;
setup_samples();
}
}
void DofPass::sync(SceneResources &resources)
{
if (!enabled_) {
return;
}
eGPUSamplerState sampler_state = GPU_SAMPLER_FILTER | GPU_SAMPLER_MIPMAP;
down_ps_.init();
down_ps_.state_set(DRW_STATE_WRITE_COLOR);
down_ps_.shader_set(prepare_sh_);
down_ps_.bind_texture("sceneColorTex", &resources.color_tx);
down_ps_.bind_texture("sceneDepthTex", &resources.depth_tx);
down_ps_.push_constant("invertedViewportSize", float2(DRW_viewport_invert_size_get()));
down_ps_.push_constant("dofParams", float3(aperture_size_, distance_, invsensor_size_));
down_ps_.push_constant("nearFar", float2(near_, far_));
down_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
down2_ps_.init();
down2_ps_.state_set(DRW_STATE_WRITE_COLOR);
down2_ps_.shader_set(downsample_sh_);
down2_ps_.bind_texture("sceneColorTex", &source_tx_, sampler_state);
down2_ps_.bind_texture("inputCocTex", &coc_halfres_tx_, sampler_state);
down2_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
blur_ps_.init();
blur_ps_.state_set(DRW_STATE_WRITE_COLOR);
blur_ps_.shader_set(blur1_sh_);
blur_ps_.bind_ubo("samples", samples_buf_);
blur_ps_.bind_texture("noiseTex", resources.jitter_tx);
blur_ps_.bind_texture("inputCocTex", &coc_halfres_tx_, sampler_state);
blur_ps_.bind_texture("halfResColorTex", &source_tx_, sampler_state);
blur_ps_.push_constant("invertedViewportSize", float2(DRW_viewport_invert_size_get()));
blur_ps_.push_constant("noiseOffset", offset_);
blur_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
blur2_ps_.init();
blur2_ps_.state_set(DRW_STATE_WRITE_COLOR);
blur2_ps_.shader_set(blur2_sh_);
blur2_ps_.bind_texture("inputCocTex", &coc_halfres_tx_, sampler_state);
blur2_ps_.bind_texture("blurTex", &blur_tx_);
blur2_ps_.push_constant("invertedViewportSize", float2(DRW_viewport_invert_size_get()));
blur2_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
resolve_ps_.init();
resolve_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM);
resolve_ps_.shader_set(resolve_sh_);
resolve_ps_.bind_texture("halfResColorTex", &source_tx_, sampler_state);
resolve_ps_.bind_texture("sceneDepthTex", &resources.depth_tx);
resolve_ps_.push_constant("invertedViewportSize", float2(DRW_viewport_invert_size_get()));
resolve_ps_.push_constant("dofParams", float3(aperture_size_, distance_, invsensor_size_));
resolve_ps_.push_constant("nearFar", float2(near_, far_));
resolve_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
void DofPass::draw(Manager &manager, View &view, SceneResources &resources, int2 resolution)
{
if (!enabled_) {
return;
}
DRW_stats_group_start("Depth Of Field");
int2 half_res = {max_ii(resolution.x / 2, 1), max_ii(resolution.y / 2, 1)};
blur_tx_.acquire(
half_res, GPU_RGBA16F, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT);
downsample_fb_.ensure(GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(source_tx_),
GPU_ATTACHMENT_TEXTURE(coc_halfres_tx_));
downsample_fb_.bind();
manager.submit(down_ps_, view);
struct CallbackData {
Manager &manager;
View &view;
PassSimple &pass;
};
CallbackData callback_data = {manager, view, down2_ps_};
auto downsample_level = [](void *callback_data, int /*level*/) {
CallbackData *cd = static_cast<CallbackData *>(callback_data);
cd->manager.submit(cd->pass, cd->view);
};
GPU_framebuffer_recursive_downsample(
downsample_fb_, 2, downsample_level, static_cast<void *>(&callback_data));
blur1_fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(blur_tx_));
blur1_fb_.bind();
manager.submit(blur_ps_, view);
blur2_fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(source_tx_));
blur2_fb_.bind();
manager.submit(blur2_ps_, view);
resolve_fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(resources.color_tx));
resolve_fb_.bind();
manager.submit(resolve_ps_, view);
blur_tx_.release();
DRW_stats_group_end();
}
bool DofPass::is_enabled()
{
return enabled_;
}
} // namespace blender::workbench

View File

@@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup draw_engine
*
* Outline Effect:
*
* Simple effect that just samples an object id buffer to detect objects outlines.
*/
#include "workbench_private.hh"
namespace blender::workbench {
void OutlinePass::init(const SceneState &scene_state)
{
enabled_ = scene_state.draw_outline;
if (!enabled_) {
return;
}
if (sh_ == nullptr) {
sh_ = GPU_shader_create_from_info_name("workbench_effect_outline");
}
}
void OutlinePass::sync(SceneResources &resources)
{
if (!enabled_) {
return;
}
ps_.init();
ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL);
ps_.shader_set(sh_);
ps_.bind_ubo("world_data", resources.world_buf);
ps_.bind_texture("objectIdBuffer", &resources.object_id_tx);
ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
void OutlinePass::draw(Manager &manager, View &view, SceneResources &resources, int2 resolution)
{
if (!enabled_) {
return;
}
fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(resources.color_tx));
fb_.bind();
manager.submit(ps_);
}
} // namespace blender::workbench

View File

@@ -0,0 +1,739 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_editmesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pbvh.h"
#include "BKE_report.h"
#include "DEG_depsgraph_query.h"
#include "DNA_fluid_types.h"
#include "ED_paint.h"
#include "ED_view3d.h"
#include "GPU_capabilities.h"
#include "workbench_private.hh"
namespace blender::workbench {
using namespace draw;
class Instance {
public:
View view = {"DefaultView"};
SceneState scene_state;
SceneResources resources;
OpaquePass opaque_ps;
TransparentPass transparent_ps;
TransparentDepthPass transparent_depth_ps;
ShadowPass shadow_ps;
OutlinePass outline_ps;
DofPass dof_ps;
AntiAliasingPass anti_aliasing_ps;
/* An array of nullptr GPUMaterial pointers so we can call DRW_cache_object_surface_material_get.
* They never get actually used. */
Vector<GPUMaterial *> dummy_gpu_materials = {1, nullptr, {}};
GPUMaterial **get_dummy_gpu_materials(int material_count)
{
if (material_count > dummy_gpu_materials.size()) {
dummy_gpu_materials.resize(material_count, nullptr);
}
return dummy_gpu_materials.begin();
};
void init(Object *camera_ob = nullptr)
{
scene_state.init(camera_ob);
shadow_ps.init(scene_state, resources);
resources.init(scene_state);
outline_ps.init(scene_state);
dof_ps.init(scene_state);
anti_aliasing_ps.init(scene_state);
}
void begin_sync()
{
const float2 viewport_size = DRW_viewport_size_get();
const int2 resolution = {int(viewport_size.x), int(viewport_size.y)};
resources.depth_tx.ensure_2d(GPU_DEPTH24_STENCIL8,
resolution,
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT |
GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW);
opaque_ps.sync(scene_state, resources);
transparent_ps.sync(scene_state, resources);
transparent_depth_ps.sync(scene_state, resources);
shadow_ps.sync();
outline_ps.sync(resources);
dof_ps.sync(resources);
anti_aliasing_ps.sync(resources, scene_state.resolution);
}
void end_sync()
{
resources.material_buf.push_update();
}
void object_sync(Manager &manager, ObjectRef &ob_ref)
{
if (scene_state.render_finished) {
return;
}
Object *ob = ob_ref.object;
if (!DRW_object_is_renderable(ob)) {
return;
}
const ObjectState object_state = ObjectState(scene_state, ob);
/* Needed for mesh cache validation, to prevent two copies of
* of vertex color arrays from being sent to the GPU (e.g.
* when switching from eevee to workbench).
*/
if (ob_ref.object->sculpt && ob_ref.object->sculpt->pbvh) {
BKE_pbvh_is_drawing_set(ob_ref.object->sculpt->pbvh, object_state.sculpt_pbvh);
}
if (ob->type == OB_MESH && ob->modifiers.first != nullptr) {
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
if (md->type != eModifierType_ParticleSystem) {
continue;
}
ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) {
continue;
}
ParticleSettings *part = psys->part;
const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
if (draw_as == PART_DRAW_PATH) {
/* TODO(Miguel Pozo):
workbench_cache_hair_populate(
wpd, ob, psys, md, object_state.color_type, object_state.texture_paint_mode,
part->omat);
*/
}
}
}
if (!(ob->base_flag & BASE_FROM_DUPLI)) {
ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluid);
if (md && BKE_modifier_is_enabled(scene_state.scene, md, eModifierMode_Realtime)) {
FluidModifierData *fmd = (FluidModifierData *)md;
if (fmd->domain) {
/* TODO(Miguel Pozo):
workbench_volume_cache_populate(vedata, wpd->scene, ob, md, V3D_SHADING_SINGLE_COLOR);
*/
if (fmd->domain->type == FLUID_DOMAIN_TYPE_GAS) {
return; /* Do not draw solid in this case. */
}
}
}
}
if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) {
return;
}
if ((ob->dt < OB_SOLID) && !DRW_state_is_scene_render()) {
return;
}
if (ELEM(ob->type, OB_MESH, OB_POINTCLOUD)) {
mesh_sync(manager, ob_ref, object_state);
}
else if (ob->type == OB_CURVES) {
/* TODO(Miguel Pozo):
DRWShadingGroup *grp = workbench_material_hair_setup(
wpd, ob, CURVES_MATERIAL_NR, object_state.color_type);
DRW_shgroup_curves_create_sub(ob, grp, NULL);
*/
}
else if (ob->type == OB_VOLUME) {
if (scene_state.shading.type != OB_WIRE) {
/* TODO(Miguel Pozo):
workbench_volume_cache_populate(vedata, wpd->scene, ob, NULL, object_state.color_type);
*/
}
}
}
void mesh_sync(Manager &manager, ObjectRef &ob_ref, const ObjectState &object_state)
{
ResourceHandle handle = manager.resource_handle(ob_ref);
bool has_transparent_material = false;
if (object_state.sculpt_pbvh) {
/* TODO(Miguel Pozo):
workbench_cache_sculpt_populate(wpd, ob, object_state.color_type);
*/
}
else {
if (object_state.use_per_material_batches) {
const int material_count = DRW_cache_object_material_count_get(ob_ref.object);
struct GPUBatch **batches;
if (object_state.color_type == V3D_SHADING_TEXTURE_COLOR) {
batches = DRW_cache_mesh_surface_texpaint_get(ob_ref.object);
}
else {
batches = DRW_cache_object_surface_material_get(
ob_ref.object, get_dummy_gpu_materials(material_count), material_count);
}
if (batches) {
for (auto i : IndexRange(material_count)) {
if (batches[i] == nullptr) {
continue;
}
/* TODO(fclem): This create a cull-able instance for each sub-object. This is done
* for simplicity to reduce complexity. But this increase the overhead per object.
* Instead, we should use an indirection buffer to the material buffer. */
ResourceHandle _handle = i == 0 ? handle : manager.resource_handle(ob_ref);
Material &mat = resources.material_buf.get_or_resize(_handle.resource_index());
if (::Material *_mat = BKE_object_material_get_eval(ob_ref.object, i + 1)) {
mat = Material(*_mat);
}
else {
mat = Material(*BKE_material_default_empty());
}
has_transparent_material = has_transparent_material || mat.is_transparent();
::Image *image = nullptr;
ImageUser *iuser = nullptr;
eGPUSamplerState sampler_state = eGPUSamplerState::GPU_SAMPLER_DEFAULT;
if (object_state.color_type == V3D_SHADING_TEXTURE_COLOR) {
get_material_image(ob_ref.object, i + 1, image, iuser, sampler_state);
}
draw_mesh(ob_ref, mat, batches[i], _handle, image, sampler_state, iuser);
}
}
}
else {
struct GPUBatch *batch;
if (object_state.color_type == V3D_SHADING_TEXTURE_COLOR) {
batch = DRW_cache_mesh_surface_texpaint_single_get(ob_ref.object);
}
else if (object_state.color_type == V3D_SHADING_VERTEX_COLOR) {
if (ob_ref.object->mode & OB_MODE_VERTEX_PAINT) {
batch = DRW_cache_mesh_surface_vertpaint_get(ob_ref.object);
}
else {
batch = DRW_cache_mesh_surface_sculptcolors_get(ob_ref.object);
}
}
else {
batch = DRW_cache_object_surface_get(ob_ref.object);
}
if (batch) {
Material &mat = resources.material_buf.get_or_resize(handle.resource_index());
if (object_state.color_type == V3D_SHADING_OBJECT_COLOR) {
mat = Material(*ob_ref.object);
}
else if (object_state.color_type == V3D_SHADING_RANDOM_COLOR) {
mat = Material(*ob_ref.object, true);
}
else if (object_state.color_type == V3D_SHADING_SINGLE_COLOR) {
mat = scene_state.material_override;
}
else if (object_state.color_type == V3D_SHADING_VERTEX_COLOR) {
mat = scene_state.material_attribute_color;
}
else {
mat = Material(*BKE_material_default_empty());
}
has_transparent_material = has_transparent_material || mat.is_transparent();
draw_mesh(ob_ref,
mat,
batch,
handle,
object_state.image_paint_override,
object_state.override_sampler_state);
}
}
}
if (object_state.draw_shadow) {
shadow_ps.object_sync(manager, scene_state, ob_ref, handle, has_transparent_material);
}
}
void draw_mesh(ObjectRef &ob_ref,
Material &material,
GPUBatch *batch,
ResourceHandle handle,
::Image *image = nullptr,
eGPUSamplerState sampler_state = GPU_SAMPLER_DEFAULT,
ImageUser *iuser = nullptr)
{
const bool in_front = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0;
auto draw = [&](MeshPass &pass) {
pass.draw(ob_ref, batch, handle, image, sampler_state, iuser);
};
if (scene_state.xray_mode || material.is_transparent()) {
if (in_front) {
draw(transparent_ps.accumulation_in_front_ps_);
if (scene_state.draw_transparent_depth) {
draw(transparent_depth_ps.in_front_ps_);
}
}
else {
draw(transparent_ps.accumulation_ps_);
if (scene_state.draw_transparent_depth) {
draw(transparent_depth_ps.main_ps_);
}
}
}
else {
if (in_front) {
draw(opaque_ps.gbuffer_in_front_ps_);
}
else {
draw(opaque_ps.gbuffer_ps_);
}
}
}
void draw(Manager &manager, GPUTexture *depth_tx, GPUTexture *color_tx)
{
view.sync(DRW_view_default_get());
int2 resolution = scene_state.resolution;
if (scene_state.render_finished) {
/* Just copy back the already rendered result */
anti_aliasing_ps.draw(manager, view, resources, resolution, depth_tx, color_tx);
return;
}
anti_aliasing_ps.setup_view(view, resolution);
resources.color_tx.acquire(
resolution, GPU_RGBA16F, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT);
resources.color_tx.clear(resources.world_buf.background_color);
if (scene_state.draw_object_id) {
resources.object_id_tx.acquire(
resolution, GPU_R16UI, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT);
resources.object_id_tx.clear(uint4(0));
}
Framebuffer fb = Framebuffer("Workbench.Clear");
fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx));
fb.bind();
GPU_framebuffer_clear_depth_stencil(fb, 1.0f, 0x00);
if (!transparent_ps.accumulation_in_front_ps_.is_empty()) {
resources.depth_in_front_tx.acquire(resolution,
GPU_DEPTH24_STENCIL8,
GPU_TEXTURE_USAGE_SHADER_READ |
GPU_TEXTURE_USAGE_ATTACHMENT);
if (opaque_ps.gbuffer_in_front_ps_.is_empty()) {
/* Clear only if it wont be overwitten by opaque_ps */
Framebuffer fb = Framebuffer("Workbench.Clear");
fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_in_front_tx));
fb.bind();
GPU_framebuffer_clear_depth_stencil(fb, 1.0f, 0x00);
}
}
opaque_ps.draw(manager,
view,
resources,
resolution,
&shadow_ps,
transparent_ps.accumulation_ps_.is_empty());
transparent_ps.draw(manager, view, resources, resolution);
transparent_depth_ps.draw(manager, view, resources, resolution);
// volume_ps.draw_prepass(manager, view, resources.depth_tx);
outline_ps.draw(manager, view, resources, resolution);
dof_ps.draw(manager, view, resources, resolution);
anti_aliasing_ps.draw(manager, view, resources, resolution, depth_tx, color_tx);
resources.color_tx.release();
resources.object_id_tx.release();
resources.depth_in_front_tx.release();
}
void draw_viewport(Manager &manager, GPUTexture *depth_tx, GPUTexture *color_tx)
{
this->draw(manager, depth_tx, color_tx);
if (scene_state.sample + 1 < scene_state.samples_len) {
DRW_viewport_request_redraw();
}
}
};
} // namespace blender::workbench
/* -------------------------------------------------------------------- */
/** \name Interface with legacy C DRW manager
* \{ */
using namespace blender;
struct WORKBENCH_Data {
DrawEngineType *engine_type;
DRWViewportEmptyList *fbl;
DRWViewportEmptyList *txl;
DRWViewportEmptyList *psl;
DRWViewportEmptyList *stl;
workbench::Instance *instance;
draw::View *view;
char info[GPU_INFO_SIZE];
};
static void workbench_engine_init(void *vedata)
{
/* TODO(fclem): Remove once it is minimum required. */
if (!GPU_shader_storage_buffer_objects_support()) {
return;
}
WORKBENCH_Data *ved = reinterpret_cast<WORKBENCH_Data *>(vedata);
if (ved->instance == nullptr) {
ved->instance = new workbench::Instance();
ved->view = new draw::View("Default View");
}
ved->instance->init();
}
static void workbench_cache_init(void *vedata)
{
if (!GPU_shader_storage_buffer_objects_support()) {
return;
}
reinterpret_cast<WORKBENCH_Data *>(vedata)->instance->begin_sync();
}
static void workbench_cache_populate(void *vedata, Object *object)
{
if (!GPU_shader_storage_buffer_objects_support()) {
return;
}
draw::Manager *manager = DRW_manager_get();
draw::ObjectRef ref;
ref.object = object;
ref.dupli_object = DRW_object_get_dupli(object);
ref.dupli_parent = DRW_object_get_dupli_parent(object);
reinterpret_cast<WORKBENCH_Data *>(vedata)->instance->object_sync(*manager, ref);
}
static void workbench_cache_finish(void *vedata)
{
if (!GPU_shader_storage_buffer_objects_support()) {
return;
}
reinterpret_cast<WORKBENCH_Data *>(vedata)->instance->end_sync();
}
static void workbench_draw_scene(void *vedata)
{
WORKBENCH_Data *ved = reinterpret_cast<WORKBENCH_Data *>(vedata);
if (!GPU_shader_storage_buffer_objects_support()) {
STRNCPY(ved->info, "Error: No shader storage buffer support");
return;
}
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
draw::Manager *manager = DRW_manager_get();
ved->instance->draw_viewport(*manager, dtxl->depth, dtxl->color);
}
static void workbench_instance_free(void *instance)
{
if (!GPU_shader_storage_buffer_objects_support()) {
return;
}
delete reinterpret_cast<workbench::Instance *>(instance);
}
static void workbench_view_update(void *vedata)
{
WORKBENCH_Data *ved = reinterpret_cast<WORKBENCH_Data *>(vedata);
if (ved->instance) {
ved->instance->scene_state.reset_taa_next_sample = true;
}
}
static void workbench_id_update(void *vedata, struct ID *id)
{
UNUSED_VARS(vedata, id);
}
/* RENDER */
static bool workbench_render_framebuffers_init(void)
{
/* For image render, allocate own buffers because we don't have a viewport. */
const float2 viewport_size = DRW_viewport_size_get();
const int2 size = {int(viewport_size.x), int(viewport_size.y)};
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
/* When doing a multi view rendering the first view will allocate the buffers
* the other views will reuse these buffers */
if (dtxl->color == nullptr) {
BLI_assert(dtxl->depth == nullptr);
dtxl->color = GPU_texture_create_2d("txl.color", size.x, size.y, 1, GPU_RGBA16F, nullptr);
dtxl->depth = GPU_texture_create_2d(
"txl.depth", size.x, size.y, 1, GPU_DEPTH24_STENCIL8, nullptr);
}
if (!(dtxl->depth && dtxl->color)) {
return false;
}
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
GPU_framebuffer_ensure_config(
&dfbl->default_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
GPU_framebuffer_ensure_config(&dfbl->depth_only_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_NONE});
GPU_framebuffer_ensure_config(&dfbl->color_only_fb,
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(dtxl->color)});
return GPU_framebuffer_check_valid(dfbl->default_fb, nullptr) &&
GPU_framebuffer_check_valid(dfbl->color_only_fb, nullptr) &&
GPU_framebuffer_check_valid(dfbl->depth_only_fb, nullptr);
}
#ifdef DEBUG
/* This is just to ease GPU debugging when the frame delimiter is set to Finish */
# define GPU_FINISH_DELIMITER() GPU_finish()
#else
# define GPU_FINISH_DELIMITER()
#endif
static void write_render_color_output(struct RenderLayer *layer,
const char *viewname,
GPUFrameBuffer *fb,
const struct rcti *rect)
{
RenderPass *rp = RE_pass_find_by_name(layer, RE_PASSNAME_COMBINED, viewname);
if (rp) {
GPU_framebuffer_bind(fb);
GPU_framebuffer_read_color(fb,
rect->xmin,
rect->ymin,
BLI_rcti_size_x(rect),
BLI_rcti_size_y(rect),
4,
0,
GPU_DATA_FLOAT,
rp->rect);
}
}
static void write_render_z_output(struct RenderLayer *layer,
const char *viewname,
GPUFrameBuffer *fb,
const struct rcti *rect,
float4x4 winmat)
{
RenderPass *rp = RE_pass_find_by_name(layer, RE_PASSNAME_Z, viewname);
if (rp) {
GPU_framebuffer_bind(fb);
GPU_framebuffer_read_depth(fb,
rect->xmin,
rect->ymin,
BLI_rcti_size_x(rect),
BLI_rcti_size_y(rect),
GPU_DATA_FLOAT,
rp->rect);
int pix_num = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
/* Convert ogl depth [0..1] to view Z [near..far] */
if (DRW_view_is_persp_get(nullptr)) {
for (float &z : MutableSpan(rp->rect, pix_num)) {
if (z == 1.0f) {
z = 1e10f; /* Background */
}
else {
z = z * 2.0f - 1.0f;
z = winmat[3][2] / (z + winmat[2][2]);
}
}
}
else {
/* Keep in mind, near and far distance are negatives. */
float near = DRW_view_near_distance_get(nullptr);
float far = DRW_view_far_distance_get(nullptr);
float range = fabsf(far - near);
for (float &z : MutableSpan(rp->rect, pix_num)) {
if (z == 1.0f) {
z = 1e10f; /* Background */
}
else {
z = z * range - near;
}
}
}
}
}
static void workbench_render_to_image(void *vedata,
struct RenderEngine *engine,
struct RenderLayer *layer,
const struct rcti *rect)
{
/* TODO(fclem): Remove once it is minimum required. */
if (!GPU_shader_storage_buffer_objects_support()) {
return;
}
if (!workbench_render_framebuffers_init()) {
RE_engine_report(engine, RPT_ERROR, "Failed to allocate GPU buffers");
return;
}
GPU_FINISH_DELIMITER();
/* Setup */
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
const DRWContextState *draw_ctx = DRW_context_state_get();
Depsgraph *depsgraph = draw_ctx->depsgraph;
WORKBENCH_Data *ved = reinterpret_cast<WORKBENCH_Data *>(vedata);
if (ved->instance == nullptr) {
ved->instance = new workbench::Instance();
}
/* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
Object *camera_ob = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
/* Set the perspective, view and window matrix. */
float4x4 winmat, viewmat, viewinv;
RE_GetCameraWindow(engine->re, camera_ob, winmat.ptr());
RE_GetCameraModelMatrix(engine->re, camera_ob, viewinv.ptr());
viewmat = viewinv.inverted();
DRWView *view = DRW_view_create(viewmat.ptr(), winmat.ptr(), nullptr, nullptr, nullptr);
DRW_view_default_set(view);
DRW_view_set_active(view);
/* Render */
do {
if (RE_engine_test_break(engine)) {
break;
}
ved->instance->init(camera_ob);
DRW_manager_get()->begin_sync();
workbench_cache_init(vedata);
auto workbench_render_cache = [](void *vedata,
struct Object *ob,
struct RenderEngine * /*engine*/,
struct Depsgraph * /*depsgraph*/) {
workbench_cache_populate(vedata, ob);
};
DRW_render_object_iter(vedata, engine, depsgraph, workbench_render_cache);
workbench_cache_finish(vedata);
DRW_manager_get()->end_sync();
/* Also we weed to have a correct FBO bound for #DRW_curves_update */
// GPU_framebuffer_bind(dfbl->default_fb);
// DRW_curves_update(); /* TODO(Miguel Pozo): Check this once curves are implemented */
workbench_draw_scene(vedata);
/* Perform render step between samples to allow
* flushing of freed GPUBackend resources. */
GPU_render_step();
GPU_FINISH_DELIMITER();
} while (ved->instance->scene_state.sample + 1 < ved->instance->scene_state.samples_len);
const char *viewname = RE_GetActiveRenderView(engine->re);
write_render_color_output(layer, viewname, dfbl->default_fb, rect);
write_render_z_output(layer, viewname, dfbl->default_fb, rect, winmat);
}
static void workbench_render_update_passes(RenderEngine *engine,
Scene *scene,
ViewLayer *view_layer)
{
if (view_layer->passflag & SCE_PASS_COMBINED) {
RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
}
if (view_layer->passflag & SCE_PASS_Z) {
RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_Z, 1, "Z", SOCK_FLOAT);
}
}
extern "C" {
static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data);
DrawEngineType draw_engine_workbench_next = {
nullptr,
nullptr,
N_("Workbench"),
&workbench_data_size,
&workbench_engine_init,
nullptr,
&workbench_instance_free,
&workbench_cache_init,
&workbench_cache_populate,
&workbench_cache_finish,
&workbench_draw_scene,
&workbench_view_update,
&workbench_id_update,
&workbench_render_to_image,
nullptr,
};
RenderEngineType DRW_engine_viewport_workbench_next_type = {
nullptr,
nullptr,
"BLENDER_WORKBENCH_NEXT",
N_("Workbench Next"),
RE_INTERNAL | RE_USE_STEREO_VIEWPORT | RE_USE_GPU_CONTEXT,
nullptr,
&DRW_render_to_image,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
&workbench_render_update_passes,
&draw_engine_workbench_next,
{nullptr, nullptr, nullptr},
};
}
/** \} */

View File

@@ -8,3 +8,4 @@
#pragma once
extern RenderEngineType DRW_engine_viewport_workbench_type;
extern RenderEngineType DRW_engine_viewport_workbench_next_type;

View File

@@ -0,0 +1,96 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_assert.h"
#include "DNA_object_types.h"
#include "DNA_view3d_enums.h"
namespace blender::workbench {
enum class eGeometryType {
MESH = 0,
CURVES,
POINTCLOUD,
};
static constexpr int geometry_type_len = static_cast<int>(eGeometryType::POINTCLOUD) + 1;
static inline const char *get_name(eGeometryType type)
{
switch (type) {
case eGeometryType::MESH:
return "Mesh";
case eGeometryType::CURVES:
return "Curves";
case eGeometryType::POINTCLOUD:
return "PointCloud";
default:
BLI_assert_unreachable();
return "";
}
}
static inline eGeometryType geometry_type_from_object(Object *ob)
{
switch (ob->type) {
case OB_CURVES:
return eGeometryType::CURVES;
case OB_POINTCLOUD:
return eGeometryType::POINTCLOUD;
default:
return eGeometryType::MESH;
}
}
enum class ePipelineType {
OPAQUE = 0,
TRANSPARENT,
SHADOW,
};
static constexpr int pipeline_type_len = static_cast<int>(ePipelineType::SHADOW) + 1;
enum class eLightingType {
FLAT = 0,
STUDIO,
MATCAP,
};
static constexpr int lighting_type_len = static_cast<int>(eLightingType::MATCAP) + 1;
static inline eLightingType lighting_type_from_v3d_lighting(char lighting)
{
switch (lighting) {
case V3D_LIGHTING_FLAT:
return eLightingType::FLAT;
case V3D_LIGHTING_MATCAP:
return eLightingType::MATCAP;
case V3D_LIGHTING_STUDIO:
return eLightingType::STUDIO;
default:
BLI_assert_unreachable();
return static_cast<eLightingType>(-1);
}
}
enum class eShaderType {
MATERIAL = 0,
TEXTURE,
};
static constexpr int shader_type_len = static_cast<int>(eShaderType::TEXTURE) + 1;
static inline eShaderType shader_type_from_v3d_shading(char shading)
{
return shading == V3D_SHADING_TEXTURE_COLOR ? eShaderType::TEXTURE : eShaderType::MATERIAL;
}
static inline const char *get_name(eShaderType type)
{
switch (type) {
case eShaderType::MATERIAL:
return "Material";
case eShaderType::TEXTURE:
return "Texture";
default:
BLI_assert_unreachable();
return "";
}
}
} // namespace blender::workbench

View File

@@ -0,0 +1,95 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "workbench_private.hh"
#include "BLI_hash.h"
/* get_image */
#include "BKE_node.h"
#include "DNA_node_types.h"
#include "ED_uvedit.h"
/* get_image */
namespace blender::workbench {
Material::Material() = default;
Material::Material(float3 color)
{
base_color = color;
packed_data = Material::pack_data(0.0f, 0.4f, 1.0f);
}
Material::Material(::Object &ob, bool random)
{
if (random) {
uint hash = BLI_ghashutil_strhash_p_murmur(ob.id.name);
if (ob.id.lib) {
hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob.id.lib->filepath);
}
float3 hsv = float3(BLI_hash_int_01(hash), 0.5f, 0.8f);
hsv_to_rgb_v(hsv, base_color);
}
else {
base_color = ob.color;
}
packed_data = Material::pack_data(0.0f, 0.4f, ob.color[3]);
}
Material::Material(::Material &mat)
{
base_color = &mat.r;
packed_data = Material::pack_data(mat.metallic, mat.roughness, mat.a);
}
bool Material::is_transparent()
{
uint32_t full_alpha_ref = 0x00ff0000;
return (packed_data & full_alpha_ref) != full_alpha_ref;
}
uint32_t Material::pack_data(float metallic, float roughness, float alpha)
{
/* Remap to Disney roughness. */
roughness = sqrtf(roughness);
uint32_t packed_roughness = unit_float_to_uchar_clamp(roughness);
uint32_t packed_metallic = unit_float_to_uchar_clamp(metallic);
uint32_t packed_alpha = unit_float_to_uchar_clamp(alpha);
return (packed_alpha << 16u) | (packed_roughness << 8u) | packed_metallic;
}
void get_material_image(Object *ob,
int material_index,
::Image *&image,
ImageUser *&iuser,
eGPUSamplerState &sampler_state)
{
const ::bNode *node = nullptr;
ED_object_get_active_image(ob, material_index, &image, &iuser, &node, nullptr);
if (node && image) {
switch (node->type) {
case SH_NODE_TEX_IMAGE: {
const NodeTexImage *storage = static_cast<NodeTexImage *>(node->storage);
const bool use_filter = (storage->interpolation != SHD_INTERP_CLOSEST);
const bool use_mirror = (storage->extension == SHD_IMAGE_EXTENSION_MIRROR);
const bool use_repeat = use_mirror || (storage->extension == SHD_IMAGE_EXTENSION_REPEAT);
const bool use_clip = (storage->extension == SHD_IMAGE_EXTENSION_CLIP);
SET_FLAG_FROM_TEST(sampler_state, use_filter, GPU_SAMPLER_FILTER);
SET_FLAG_FROM_TEST(sampler_state, use_repeat, GPU_SAMPLER_REPEAT);
SET_FLAG_FROM_TEST(sampler_state, use_clip, GPU_SAMPLER_CLAMP_BORDER);
SET_FLAG_FROM_TEST(sampler_state, use_mirror, GPU_SAMPLER_MIRROR_REPEAT);
break;
}
case SH_NODE_TEX_ENVIRONMENT: {
const NodeTexEnvironment *storage = static_cast<NodeTexEnvironment *>(node->storage);
const bool use_filter = (storage->interpolation != SHD_INTERP_CLOSEST);
SET_FLAG_FROM_TEST(sampler_state, use_filter, GPU_SAMPLER_FILTER);
break;
}
default:
BLI_assert_msg(0, "Node type not supported by workbench");
}
}
}
} // namespace blender::workbench

View File

@@ -0,0 +1,405 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "workbench_private.hh"
namespace blender::workbench {
/* -------------------------------------------------------------------- */
/** \name MeshPass
* \{ */
MeshPass::MeshPass(const char *name) : PassMain(name){};
/* Move to draw::Pass */
bool MeshPass::is_empty() const
{
return is_empty_;
}
void MeshPass::init_pass(SceneResources &resources, DRWState state, int clip_planes)
{
is_empty_ = true;
PassMain::init();
state_set(state, clip_planes);
bind_texture(WB_MATCAP_SLOT, resources.matcap_tx);
bind_ssbo(WB_MATERIAL_SLOT, &resources.material_buf);
bind_ubo(WB_WORLD_SLOT, resources.world_buf);
if (clip_planes > 0) {
bind_ubo(DRW_CLIPPING_UBO_SLOT, resources.clip_planes_buf);
}
}
void MeshPass::init_subpasses(ePipelineType pipeline,
eLightingType lighting,
bool clip,
ShaderCache &shaders)
{
texture_subpass_map_.clear();
static std::string pass_names[geometry_type_len][shader_type_len] = {};
for (auto geom : IndexRange(geometry_type_len)) {
for (auto shader : IndexRange(shader_type_len)) {
eGeometryType geom_type = static_cast<eGeometryType>(geom);
eShaderType shader_type = static_cast<eShaderType>(shader);
if (pass_names[geom][shader].empty()) {
pass_names[geom][shader] = std::string(get_name(geom_type)) +
std::string(get_name(shader_type));
}
GPUShader *sh = shaders.prepass_shader_get(pipeline, geom_type, shader_type, lighting, clip);
PassMain::Sub *pass = &sub(pass_names[geom][shader].c_str());
pass->shader_set(sh);
passes_[geom][shader] = pass;
}
}
}
void MeshPass::draw(ObjectRef &ref,
GPUBatch *batch,
ResourceHandle handle,
::Image *image /* = nullptr */,
eGPUSamplerState sampler_state /* = GPU_SAMPLER_DEFAULT */,
ImageUser *iuser /* = nullptr */)
{
is_empty_ = false;
eGeometryType geometry_type = geometry_type_from_object(ref.object);
if (image) {
GPUTexture *texture = nullptr;
GPUTexture *tilemap = nullptr;
if (image->source == IMA_SRC_TILED) {
texture = BKE_image_get_gpu_tiles(image, iuser, nullptr);
tilemap = BKE_image_get_gpu_tilemap(image, iuser, nullptr);
}
else {
texture = BKE_image_get_gpu_texture(image, iuser, nullptr);
}
if (texture) {
auto add_cb = [&] {
PassMain::Sub *sub_pass =
passes_[static_cast<int>(geometry_type)][static_cast<int>(eShaderType::TEXTURE)];
sub_pass = &sub_pass->sub(image->id.name);
if (tilemap) {
sub_pass->bind_texture(WB_TILE_ARRAY_SLOT, texture, sampler_state);
sub_pass->bind_texture(WB_TILE_DATA_SLOT, tilemap);
}
else {
sub_pass->bind_texture(WB_TEXTURE_SLOT, texture, sampler_state);
}
sub_pass->push_constant("isImageTile", tilemap != nullptr);
sub_pass->push_constant("imagePremult", image && image->alpha_mode == IMA_ALPHA_PREMUL);
/* TODO(Miguel Pozo): This setting should be exposed on the user side,
* either as a global parameter (and set it here)
* or by reading the Material Clipping Threshold (and set it per material) */
sub_pass->push_constant("imageTransparencyCutoff", 0.1f);
return sub_pass;
};
texture_subpass_map_.lookup_or_add_cb(TextureSubPassKey(texture, geometry_type), add_cb)
->draw(batch, handle);
}
}
passes_[static_cast<int>(geometry_type)][static_cast<int>(eShaderType::MATERIAL)]->draw(batch,
handle);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name OpaquePass
* \{ */
void OpaquePass::sync(const SceneState &scene_state, SceneResources &resources)
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
scene_state.cull_state;
bool clip = scene_state.clip_planes.size() > 0;
DRWState in_front_state = state | DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
gbuffer_in_front_ps_.init_pass(resources, in_front_state, scene_state.clip_planes.size());
gbuffer_in_front_ps_.state_stencil(0xFF, 0xFF, 0x00);
gbuffer_in_front_ps_.init_subpasses(
ePipelineType::OPAQUE, scene_state.lighting_type, clip, resources.shader_cache);
state |= DRW_STATE_STENCIL_NEQUAL;
gbuffer_ps_.init_pass(resources, state, scene_state.clip_planes.size());
gbuffer_ps_.state_stencil(0x00, 0xFF, 0xFF);
gbuffer_ps_.init_subpasses(
ePipelineType::OPAQUE, scene_state.lighting_type, clip, resources.shader_cache);
deferred_ps_.init();
deferred_ps_.state_set(DRW_STATE_WRITE_COLOR);
deferred_ps_.shader_set(resources.shader_cache.resolve_shader_get(ePipelineType::OPAQUE,
scene_state.lighting_type,
scene_state.draw_cavity,
scene_state.draw_curvature));
deferred_ps_.push_constant("forceShadowing", false);
deferred_ps_.bind_ubo(WB_WORLD_SLOT, resources.world_buf);
deferred_ps_.bind_texture(WB_MATCAP_SLOT, resources.matcap_tx);
deferred_ps_.bind_texture("normal_tx", &gbuffer_normal_tx);
deferred_ps_.bind_texture("material_tx", &gbuffer_material_tx);
deferred_ps_.bind_texture("depth_tx", &resources.depth_tx);
deferred_ps_.bind_texture("stencil_tx", &deferred_ps_stencil_tx);
resources.cavity.setup_resolve_pass(deferred_ps_, resources);
deferred_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
void OpaquePass::draw(Manager &manager,
View &view,
SceneResources &resources,
int2 resolution,
ShadowPass *shadow_pass,
bool accumulation_ps_is_empty)
{
if (is_empty()) {
return;
}
gbuffer_material_tx.acquire(
resolution, GPU_RGBA16F, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT);
gbuffer_normal_tx.acquire(
resolution, GPU_RG16F, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT);
GPUAttachment object_id_attachment = GPU_ATTACHMENT_NONE;
if (resources.object_id_tx.is_valid()) {
object_id_attachment = GPU_ATTACHMENT_TEXTURE(resources.object_id_tx);
}
if (!gbuffer_in_front_ps_.is_empty()) {
opaque_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx),
GPU_ATTACHMENT_TEXTURE(gbuffer_material_tx),
GPU_ATTACHMENT_TEXTURE(gbuffer_normal_tx),
object_id_attachment);
opaque_fb.bind();
manager.submit(gbuffer_in_front_ps_, view);
if (resources.depth_in_front_tx.is_valid()) {
/* Only needed when transparent infront is needed */
GPU_texture_copy(resources.depth_in_front_tx, resources.depth_tx);
}
}
if (!gbuffer_ps_.is_empty()) {
opaque_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx),
GPU_ATTACHMENT_TEXTURE(gbuffer_material_tx),
GPU_ATTACHMENT_TEXTURE(gbuffer_normal_tx),
object_id_attachment);
opaque_fb.bind();
manager.submit(gbuffer_ps_, view);
}
bool needs_stencil_copy = shadow_pass && !gbuffer_in_front_ps_.is_empty() &&
!accumulation_ps_is_empty;
if (needs_stencil_copy) {
shadow_depth_stencil_tx.ensure_2d(GPU_DEPTH24_STENCIL8,
resolution,
GPU_TEXTURE_USAGE_SHADER_READ |
GPU_TEXTURE_USAGE_ATTACHMENT |
GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW);
GPU_texture_copy(shadow_depth_stencil_tx, resources.depth_tx);
deferred_ps_stencil_tx = shadow_depth_stencil_tx.stencil_view();
}
else {
shadow_depth_stencil_tx.free();
deferred_ps_stencil_tx = resources.depth_tx.stencil_view();
}
if (shadow_pass && !gbuffer_in_front_ps_.is_empty()) {
opaque_fb.ensure(GPU_ATTACHMENT_TEXTURE(deferred_ps_stencil_tx));
opaque_fb.bind();
GPU_framebuffer_clear_stencil(opaque_fb, 0);
}
if (shadow_pass) {
shadow_pass->draw(manager,
view,
resources,
resolution,
*deferred_ps_stencil_tx,
!gbuffer_in_front_ps_.is_empty());
}
opaque_fb.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(resources.color_tx));
opaque_fb.bind();
manager.submit(deferred_ps_, view);
if (shadow_pass && !needs_stencil_copy) {
opaque_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx));
opaque_fb.bind();
GPU_framebuffer_clear_stencil(opaque_fb, 0);
}
gbuffer_normal_tx.release();
gbuffer_material_tx.release();
}
bool OpaquePass::is_empty() const
{
return gbuffer_ps_.is_empty() && gbuffer_in_front_ps_.is_empty();
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name TransparentPass
* \{ */
void TransparentPass::sync(const SceneState &scene_state, SceneResources &resources)
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_OIT |
scene_state.cull_state;
bool clip = scene_state.clip_planes.size() > 0;
accumulation_ps_.init_pass(
resources, state | DRW_STATE_STENCIL_NEQUAL, scene_state.clip_planes.size());
accumulation_ps_.state_stencil(0x00, 0xFF, 0xFF);
accumulation_ps_.clear_color(float4(0.0f, 0.0f, 0.0f, 1.0f));
accumulation_ps_.init_subpasses(
ePipelineType::TRANSPARENT, scene_state.lighting_type, clip, resources.shader_cache);
accumulation_in_front_ps_.init_pass(resources, state, scene_state.clip_planes.size());
accumulation_in_front_ps_.clear_color(float4(0.0f, 0.0f, 0.0f, 1.0f));
accumulation_in_front_ps_.init_subpasses(
ePipelineType::TRANSPARENT, scene_state.lighting_type, clip, resources.shader_cache);
if (resolve_sh_ == nullptr) {
resolve_sh_ = GPU_shader_create_from_info_name("workbench_transparent_resolve");
}
resolve_ps_.init();
resolve_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA);
resolve_ps_.shader_set(resolve_sh_);
resolve_ps_.bind_texture("transparentAccum", &accumulation_tx);
resolve_ps_.bind_texture("transparentRevealage", &reveal_tx);
resolve_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
void TransparentPass::draw(Manager &manager,
View &view,
SceneResources &resources,
int2 resolution)
{
if (is_empty()) {
return;
}
accumulation_tx.acquire(
resolution, GPU_RGBA16F, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT);
reveal_tx.acquire(
resolution, GPU_R16F, GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT);
resolve_fb.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(resources.color_tx));
if (!accumulation_ps_.is_empty()) {
transparent_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx),
GPU_ATTACHMENT_TEXTURE(accumulation_tx),
GPU_ATTACHMENT_TEXTURE(reveal_tx));
transparent_fb.bind();
manager.submit(accumulation_ps_, view);
resolve_fb.bind();
manager.submit(resolve_ps_, view);
}
if (!accumulation_in_front_ps_.is_empty()) {
transparent_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_in_front_tx),
GPU_ATTACHMENT_TEXTURE(accumulation_tx),
GPU_ATTACHMENT_TEXTURE(reveal_tx));
transparent_fb.bind();
manager.submit(accumulation_in_front_ps_, view);
resolve_fb.bind();
manager.submit(resolve_ps_, view);
}
accumulation_tx.release();
reveal_tx.release();
}
bool TransparentPass::is_empty() const
{
return accumulation_ps_.is_empty() && accumulation_in_front_ps_.is_empty();
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name TransparentDepthPass
* \{ */
void TransparentDepthPass::sync(const SceneState &scene_state, SceneResources &resources)
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
scene_state.cull_state;
bool clip = scene_state.clip_planes.size() > 0;
DRWState in_front_state = state | DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
in_front_ps_.init_pass(resources, in_front_state, scene_state.clip_planes.size());
in_front_ps_.state_stencil(0xFF, 0xFF, 0x00);
in_front_ps_.init_subpasses(
ePipelineType::OPAQUE, eLightingType::FLAT, clip, resources.shader_cache);
if (merge_sh_ == nullptr) {
merge_sh_ = GPU_shader_create_from_info_name("workbench_next_merge_depth");
}
merge_ps_.init();
merge_ps_.shader_set(merge_sh_);
merge_ps_.state_set(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_WRITE_STENCIL |
DRW_STATE_STENCIL_ALWAYS);
merge_ps_.state_stencil(0xFF, 0xFF, 0x00);
merge_ps_.bind_texture("depth_tx", &resources.depth_in_front_tx);
merge_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
state |= DRW_STATE_STENCIL_NEQUAL;
main_ps_.init_pass(resources, state, scene_state.clip_planes.size());
main_ps_.state_stencil(0x00, 0xFF, 0xFF);
main_ps_.init_subpasses(
ePipelineType::OPAQUE, eLightingType::FLAT, clip, resources.shader_cache);
}
void TransparentDepthPass::draw(Manager &manager,
View &view,
SceneResources &resources,
int2 resolution)
{
if (is_empty()) {
return;
}
GPUAttachment object_id_attachment = GPU_ATTACHMENT_NONE;
if (resources.object_id_tx.is_valid()) {
object_id_attachment = GPU_ATTACHMENT_TEXTURE(resources.object_id_tx);
}
if (!in_front_ps_.is_empty()) {
in_front_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_in_front_tx),
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_NONE,
object_id_attachment);
in_front_fb.bind();
manager.submit(in_front_ps_, view);
merge_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx));
merge_fb.bind();
manager.submit(merge_ps_, view);
}
if (!main_ps_.is_empty()) {
main_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx),
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_NONE,
object_id_attachment);
main_fb.bind();
manager.submit(main_ps_, view);
}
}
bool TransparentDepthPass::is_empty() const
{
return main_ps_.is_empty() && in_front_ps_.is_empty();
}
/** \} */
} // namespace blender::workbench

View File

@@ -200,8 +200,12 @@ typedef struct WORKBENCH_UBO_World {
int matcap_orientation;
int use_specular; /* Bools are 32bit ints in GLSL. */
int _pad1;
float xray_alpha; /* Workbench Next */
int _pad2;
/* Workbench Next data
* (Not used here, but needs to be kept in sync with workbench_shader_shared WorldData) */
float background_color[4];
} WORKBENCH_UBO_World;
BLI_STATIC_ASSERT_ALIGN(WORKBENCH_UBO_World, 16)

View File

@@ -0,0 +1,439 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "DNA_camera_types.h"
#include "DRW_render.h"
#include "draw_manager.hh"
#include "draw_pass.hh"
#include "workbench_defines.hh"
#include "workbench_enums.hh"
#include "workbench_shader_shared.h"
extern "C" DrawEngineType draw_engine_workbench_next;
namespace blender::workbench {
using namespace draw;
class ShaderCache {
public:
~ShaderCache();
GPUShader *prepass_shader_get(ePipelineType pipeline_type,
eGeometryType geometry_type,
eShaderType shader_type,
eLightingType lighting_type,
bool clip);
GPUShader *resolve_shader_get(ePipelineType pipeline_type,
eLightingType lighting_type,
bool cavity = false,
bool curvature = false);
private:
/* TODO(fclem): We might want to change to a Map since most shader will never be compiled. */
GPUShader *prepass_shader_cache_[pipeline_type_len][geometry_type_len][shader_type_len]
[lighting_type_len][2 /*clip*/] = {{{{{nullptr}}}}};
GPUShader *resolve_shader_cache_[pipeline_type_len][lighting_type_len][2 /*cavity*/]
[2 /*curvature*/] = {{{{nullptr}}}};
};
struct Material {
float3 base_color = float3(0);
/* Packed data into a int. Decoded in the shader. */
uint packed_data = 0;
Material();
Material(float3 color);
Material(::Object &ob, bool random = false);
Material(::Material &mat);
static uint32_t pack_data(float metallic, float roughness, float alpha);
bool is_transparent();
};
void get_material_image(Object *ob,
int material_index,
::Image *&image,
ImageUser *&iuser,
eGPUSamplerState &sampler_state);
struct SceneState {
Scene *scene = nullptr;
Object *camera_object = nullptr;
Camera *camera = nullptr;
float4x4 view_projection_matrix = float4x4::identity();
int2 resolution = int2(0);
eContextObjectMode object_mode = CTX_MODE_OBJECT;
View3DShading shading = {};
eLightingType lighting_type = eLightingType::STUDIO;
bool xray_mode = false;
DRWState cull_state = DRW_STATE_NO_DRAW;
Vector<float4> clip_planes = {};
float4 background_color = float4(0);
bool draw_cavity = false;
bool draw_curvature = false;
bool draw_shadows = false;
bool draw_outline = false;
bool draw_dof = false;
bool draw_aa = false;
bool draw_object_id = false;
bool draw_transparent_depth = false;
int sample = 0;
int samples_len = 0;
bool reset_taa_next_sample = false;
bool render_finished = false;
/* Used when material_type == eMaterialType::SINGLE */
Material material_override = Material(float3(1.0f));
/* When r == -1.0 the shader uses the vertex color */
Material material_attribute_color = Material(float3(-1.0f));
void init(Object *camera_ob = nullptr);
};
struct ObjectState {
eV3DShadingColorType color_type = V3D_SHADING_SINGLE_COLOR;
bool sculpt_pbvh = false;
bool texture_paint_mode = false;
::Image *image_paint_override = nullptr;
eGPUSamplerState override_sampler_state = GPU_SAMPLER_DEFAULT;
bool draw_shadow = false;
bool use_per_material_batches = false;
ObjectState(const SceneState &scene_state, Object *ob);
};
class CavityEffect {
private:
/* This value must be kept in sync with the one declared at
* workbench_composite_info.hh (cavity_samples) */
static const int max_samples_ = 512;
UniformArrayBuffer<float4, max_samples_> samples_buf = {};
int sample_ = 0;
int sample_count_ = 0;
bool curvature_enabled_ = false;
bool cavity_enabled_ = false;
public:
void init(const SceneState &scene_state, struct SceneResources &resources);
void setup_resolve_pass(PassSimple &pass, struct SceneResources &resources);
private:
void load_samples_buf(int ssao_samples);
};
struct SceneResources {
static const int jitter_tx_size = 64;
ShaderCache shader_cache = {};
StringRefNull current_matcap = {};
Texture matcap_tx = "matcap_tx";
TextureFromPool color_tx = "wb_color_tx";
TextureFromPool object_id_tx = "wb_object_id_tx";
Texture depth_tx = "wb_depth_tx";
TextureFromPool depth_in_front_tx = "wb_depth_in_front_tx";
StorageVectorBuffer<Material> material_buf = {"material_buf"};
UniformBuffer<WorldData> world_buf = {};
UniformArrayBuffer<float4, 6> clip_planes_buf;
Texture jitter_tx = "wb_jitter_tx";
CavityEffect cavity = {};
void init(const SceneState &scene_state);
void load_jitter_tx(int total_samples);
};
class MeshPass : public PassMain {
private:
using TextureSubPassKey = std::pair<GPUTexture *, eGeometryType>;
Map<TextureSubPassKey, PassMain::Sub *> texture_subpass_map_ = {};
PassMain::Sub *passes_[geometry_type_len][shader_type_len] = {{nullptr}};
bool is_empty_ = false;
public:
MeshPass(const char *name);
/* TODO: Move to draw::Pass */
bool is_empty() const;
void init_pass(SceneResources &resources, DRWState state, int clip_planes);
void init_subpasses(ePipelineType pipeline,
eLightingType lighting,
bool clip,
ShaderCache &shaders);
void draw(ObjectRef &ref,
GPUBatch *batch,
ResourceHandle handle,
::Image *image = nullptr,
eGPUSamplerState sampler_state = eGPUSamplerState::GPU_SAMPLER_DEFAULT,
ImageUser *iuser = nullptr);
};
class OpaquePass {
public:
TextureFromPool gbuffer_normal_tx = {"gbuffer_normal_tx"};
TextureFromPool gbuffer_material_tx = {"gbuffer_material_tx"};
Framebuffer opaque_fb = {};
Texture shadow_depth_stencil_tx = {"shadow_depth_stencil_tx"};
GPUTexture *deferred_ps_stencil_tx = nullptr;
MeshPass gbuffer_ps_ = {"Opaque.Gbuffer"};
MeshPass gbuffer_in_front_ps_ = {"Opaque.GbufferInFront"};
PassSimple deferred_ps_ = {"Opaque.Deferred"};
void sync(const SceneState &scene_state, SceneResources &resources);
void draw(Manager &manager,
View &view,
SceneResources &resources,
int2 resolution,
class ShadowPass *shadow_pass,
bool accumulation_ps_is_empty);
bool is_empty() const;
};
class TransparentPass {
private:
GPUShader *resolve_sh_ = nullptr;
public:
TextureFromPool accumulation_tx = {"accumulation_accumulation_tx"};
TextureFromPool reveal_tx = {"accumulation_reveal_tx"};
Framebuffer transparent_fb = {};
MeshPass accumulation_ps_ = {"Transparent.Accumulation"};
MeshPass accumulation_in_front_ps_ = {"Transparent.AccumulationInFront"};
PassSimple resolve_ps_ = {"Transparent.Resolve"};
Framebuffer resolve_fb = {};
void sync(const SceneState &scene_state, SceneResources &resources);
void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
bool is_empty() const;
};
class TransparentDepthPass {
private:
GPUShader *merge_sh_ = nullptr;
public:
MeshPass main_ps_ = {"TransparentDepth.Main"};
Framebuffer main_fb = {"TransparentDepth.Main"};
MeshPass in_front_ps_ = {"TransparentDepth.InFront"};
Framebuffer in_front_fb = {"TransparentDepth.InFront"};
PassSimple merge_ps_ = {"TransparentDepth.Merge"};
Framebuffer merge_fb = {"TransparentDepth.Merge"};
void sync(const SceneState &scene_state, SceneResources &resources);
void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
bool is_empty() const;
};
class ShadowPass {
private:
enum PassType { PASS = 0, FAIL, FORCED_FAIL, MAX };
class ShadowView : public View {
bool force_fail_method_ = false;
float3 light_direction_ = float3(0);
UniformBuffer<ExtrudedFrustum> extruded_frustum_ = {};
ShadowPass::PassType current_pass_type_ = PASS;
VisibilityBuf pass_visibility_buf_ = {};
VisibilityBuf fail_visibility_buf_ = {};
public:
void setup(View &view, float3 light_direction, bool force_fail_method);
bool debug_object_culling(Object *ob);
void set_mode(PassType type);
ShadowView();
protected:
virtual void compute_visibility(ObjectMatricesBuf &matrices,
ObjectBoundsBuf &bounds,
uint resource_len,
bool debug_freeze);
virtual VisibilityBuf &get_visibility_buffer();
} view_ = {};
bool enabled_;
UniformBuffer<ShadowPassData> pass_data_ = {};
/* Draws are added to both passes and the visibily compute shader selects one of them */
PassMain pass_ps_ = {"Shadow.Pass"};
PassMain fail_ps_ = {"Shadow.Fail"};
/* In some cases, we know beforehand that we need to use the fail technique */
PassMain forced_fail_ps_ = {"Shadow.ForcedFail"};
/* [PassType][Is Manifold][Is Cap] */
PassMain::Sub *passes_[PassType::MAX][2][2] = {{{nullptr}}};
PassMain::Sub *&get_pass_ptr(PassType type, bool manifold, bool cap = false);
/* [Is Pass Technique][Is Manifold][Is Cap] */
GPUShader *shaders_[2][2][2] = {{{nullptr}}};
GPUShader *get_shader(bool depth_pass, bool manifold, bool cap = false);
TextureFromPool depth_tx_ = {};
Framebuffer fb_ = {};
public:
void init(const SceneState &scene_state, SceneResources &resources);
void update();
void sync();
void object_sync(Manager &manager,
SceneState &scene_state,
ObjectRef &ob_ref,
ResourceHandle handle,
const bool has_transp_mat);
void draw(Manager &manager,
View &view,
SceneResources &resources,
int2 resolution,
GPUTexture &depth_stencil_tx,
/* Needed when there are opaque "In Front" objects in the scene */
bool force_fail_method);
};
class OutlinePass {
private:
bool enabled_ = false;
PassSimple ps_ = PassSimple("Workbench.Outline");
GPUShader *sh_ = nullptr;
Framebuffer fb_ = Framebuffer("Workbench.Outline");
public:
void init(const SceneState &scene_state);
void sync(SceneResources &resources);
void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
};
class DofPass {
private:
static const int kernel_radius_ = 3;
static const int samples_len_ = (kernel_radius_ * 2 + 1) * (kernel_radius_ * 2 + 1);
bool enabled_ = false;
float offset_ = 0;
UniformArrayBuffer<float4, samples_len_> samples_buf_ = {};
Texture source_tx_ = {};
Texture coc_halfres_tx_ = {};
TextureFromPool blur_tx_ = {};
Framebuffer downsample_fb_ = {};
Framebuffer blur1_fb_ = {};
Framebuffer blur2_fb_ = {};
Framebuffer resolve_fb_ = {};
GPUShader *prepare_sh_ = nullptr;
GPUShader *downsample_sh_ = nullptr;
GPUShader *blur1_sh_ = nullptr;
GPUShader *blur2_sh_ = nullptr;
GPUShader *resolve_sh_ = nullptr;
PassSimple down_ps_ = {"Workbench.DoF.DownSample"};
PassSimple down2_ps_ = {"Workbench.DoF.DownSample2"};
PassSimple blur_ps_ = {"Workbench.DoF.Blur"};
PassSimple blur2_ps_ = {"Workbench.DoF.Blur2"};
PassSimple resolve_ps_ = {"Workbench.DoF.Resolve"};
float aperture_size_ = 0;
float distance_ = 0;
float invsensor_size_ = 0;
float near_ = 0;
float far_ = 0;
float blades_ = 0;
float rotation_ = 0;
float ratio_ = 0;
public:
void init(const SceneState &scene_state);
void sync(SceneResources &resources);
void draw(Manager &manager, View &view, SceneResources &resources, int2 resolution);
bool is_enabled();
private:
void setup_samples();
};
class AntiAliasingPass {
private:
bool enabled_ = false;
/* Current TAA sample index in [0..samples_len_] range. */
int sample_ = 0;
/* Total number of samples to after which TAA stops accumulating samples. */
int samples_len_ = 0;
/* Weight accumulated. */
float weight_accum_ = 0;
/* Samples weight for this iteration. */
float weights_[9] = {0};
/* Sum of weights. */
float weights_sum_ = 0;
Texture sample0_depth_tx_ = {"sample0_depth_tx"};
Texture taa_accumulation_tx_ = {"taa_accumulation_tx"};
Texture smaa_search_tx_ = {"smaa_search_tx"};
Texture smaa_area_tx_ = {"smaa_area_tx"};
TextureFromPool smaa_edge_tx_ = {"smaa_edge_tx"};
TextureFromPool smaa_weight_tx_ = {"smaa_weight_tx"};
Framebuffer taa_accumulation_fb_ = {"taa_accumulation_fb"};
Framebuffer smaa_edge_fb_ = {"smaa_edge_fb"};
Framebuffer smaa_weight_fb_ = {"smaa_weight_fb"};
Framebuffer smaa_resolve_fb_ = {"smaa_resolve_fb"};
float4 smaa_viewport_metrics_ = float4(0);
float smaa_mix_factor_ = 0;
GPUShader *taa_accumulation_sh_ = nullptr;
GPUShader *smaa_edge_detect_sh_ = nullptr;
GPUShader *smaa_aa_weight_sh_ = nullptr;
GPUShader *smaa_resolve_sh_ = nullptr;
PassSimple taa_accumulation_ps_ = {"TAA.Accumulation"};
PassSimple smaa_edge_detect_ps_ = {"SMAA.EdgeDetect"};
PassSimple smaa_aa_weight_ps_ = {"SMAA.BlendWeights"};
PassSimple smaa_resolve_ps_ = {"SMAA.Resolve"};
public:
AntiAliasingPass();
~AntiAliasingPass();
void init(const SceneState &scene_state);
void sync(SceneResources &resources, int2 resolution);
void setup_view(View &view, int2 resolution);
void draw(Manager &manager,
View &view,
SceneResources &resources,
int2 resolution,
GPUTexture *depth_tx,
GPUTexture *color_tx);
};
} // namespace blender::workbench

View File

@@ -0,0 +1,171 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "../eevee/eevee_lut.h" /* TODO: find somewhere to share blue noise Table. */
#include "BKE_studiolight.h"
#include "IMB_imbuf_types.h"
#include "workbench_private.hh"
namespace blender::workbench {
bool get_matcap_tx(Texture &matcap_tx, const StudioLight &studio_light)
{
ImBuf *matcap_diffuse = studio_light.matcap_diffuse.ibuf;
ImBuf *matcap_specular = studio_light.matcap_specular.ibuf;
if (matcap_diffuse && matcap_diffuse->rect_float) {
int layers = 1;
float *buffer = matcap_diffuse->rect_float;
Vector<float> combined_buffer = {};
if (matcap_specular && matcap_specular->rect_float) {
int size = matcap_diffuse->x * matcap_diffuse->y * 4;
combined_buffer.extend(matcap_diffuse->rect_float, size);
combined_buffer.extend(matcap_specular->rect_float, size);
buffer = combined_buffer.begin();
layers++;
}
matcap_tx = Texture(studio_light.name,
GPU_RGBA16F,
GPU_TEXTURE_USAGE_SHADER_READ,
int2(matcap_diffuse->x, matcap_diffuse->y),
layers,
buffer);
return true;
}
return false;
}
float4x4 get_world_shading_rotation_matrix(float studiolight_rot_z)
{
/* TODO(Miguel Pozo) C++ API ? */
float V[4][4], R[4][4];
DRW_view_viewmat_get(nullptr, V, false);
axis_angle_to_mat4_single(R, 'Z', -studiolight_rot_z);
mul_m4_m4m4(R, V, R);
swap_v3_v3(R[2], R[1]);
negate_v3(R[2]);
return float4x4(R);
}
LightData get_light_data_from_studio_solidlight(const SolidLight *sl,
float4x4 world_shading_rotation)
{
LightData light = {};
if (sl && sl->flag) {
float3 direction = world_shading_rotation.ref_3x3() * float3(sl->vec);
light.direction = float4(direction, 0.0f);
/* We should pre-divide the power by PI but that makes the lights really dim. */
light.specular_color = float4(float3(sl->spec), 0.0f);
light.diffuse_color_wrap = float4(float3(sl->col), sl->smooth);
}
else {
light.direction = float4(1.0f, 0.0f, 0.0f, 0.0f);
light.specular_color = float4(0.0f);
light.diffuse_color_wrap = float4(0.0f);
}
return light;
}
void SceneResources::load_jitter_tx(int total_samples)
{
const int texel_count = jitter_tx_size * jitter_tx_size;
static float4 jitter[texel_count];
const float total_samples_inv = 1.0f / total_samples;
/* Create blue noise jitter texture */
for (int i = 0; i < texel_count; i++) {
float phi = blue_noise[i][0] * 2.0f * M_PI;
/* This rotate the sample per pixels */
jitter[i].x = math::cos(phi);
jitter[i].y = math::sin(phi);
/* This offset the sample along its direction axis (reduce banding) */
float bn = blue_noise[i][1] - 0.5f;
bn = clamp_f(bn, -0.499f, 0.499f); /* fix fireflies */
jitter[i].z = bn * total_samples_inv;
jitter[i].w = blue_noise[i][1];
}
jitter_tx.free();
jitter_tx.ensure_2d(GPU_RGBA16F, int2(jitter_tx_size), GPU_TEXTURE_USAGE_SHADER_READ, jitter[0]);
}
void SceneResources::init(const SceneState &scene_state)
{
const View3DShading &shading = scene_state.shading;
world_buf.viewport_size = DRW_viewport_size_get();
world_buf.viewport_size_inv = DRW_viewport_invert_size_get();
world_buf.xray_alpha = shading.xray_alpha;
world_buf.background_color = scene_state.background_color;
world_buf.object_outline_color = float4(float3(shading.object_outline_color), 1.0f);
world_buf.ui_scale = DRW_state_is_image_render() ? 1.0f : G_draw.block.size_pixel;
world_buf.matcap_orientation = (shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0;
StudioLight *studio_light = nullptr;
if (U.edit_studio_light) {
studio_light = BKE_studiolight_studio_edit_get();
}
else {
if (shading.light == V3D_LIGHTING_MATCAP) {
studio_light = BKE_studiolight_find(shading.matcap, STUDIOLIGHT_TYPE_MATCAP);
if (studio_light && studio_light->name != current_matcap) {
if (get_matcap_tx(matcap_tx, *studio_light)) {
current_matcap = studio_light->name;
}
}
}
/* If matcaps are missing, use this as fallback. */
if (studio_light == nullptr) {
studio_light = BKE_studiolight_find(shading.studio_light, STUDIOLIGHT_TYPE_STUDIO);
}
}
if (!matcap_tx.is_valid()) {
matcap_tx.ensure_2d_array(GPU_RGBA16F, int2(1), 1, GPU_TEXTURE_USAGE_SHADER_READ);
}
float4x4 world_shading_rotation = float4x4::identity();
if (shading.flag & V3D_SHADING_WORLD_ORIENTATION) {
world_shading_rotation = get_world_shading_rotation_matrix(shading.studiolight_rot_z);
}
for (int i = 0; i < 4; i++) {
SolidLight *sl = (studio_light) ? &studio_light->light[i] : nullptr;
world_buf.lights[i] = get_light_data_from_studio_solidlight(sl, world_shading_rotation);
}
if (studio_light != nullptr) {
world_buf.ambient_color = float4(float3(studio_light->light_ambient), 0.0f);
world_buf.use_specular = shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT &&
studio_light->flag & STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS;
}
else {
world_buf.ambient_color = float4(1.0f, 1.0f, 1.0f, 0.0f);
world_buf.use_specular = false;
}
/* TODO(Miguel Pozo) volumes_do */
cavity.init(scene_state, *this);
if (scene_state.draw_dof && !jitter_tx.is_valid()) {
/* We don't care about total_samples in this case */
load_jitter_tx(1);
}
world_buf.push_update();
for (int i : IndexRange(6)) {
if (i < scene_state.clip_planes.size()) {
clip_planes_buf[i] = scene_state.clip_planes[i];
}
else {
clip_planes_buf[i] = float4(0);
}
}
clip_planes_buf.push_update();
}
} // namespace blender::workbench

View File

@@ -0,0 +1,132 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "workbench_private.hh"
namespace blender::workbench {
ShaderCache::~ShaderCache()
{
for (auto i : IndexRange(lighting_type_len)) {
for (auto j : IndexRange(shader_type_len)) {
for (auto k : IndexRange(geometry_type_len)) {
for (auto l : IndexRange(pipeline_type_len)) {
for (auto m : IndexRange(2)) {
DRW_SHADER_FREE_SAFE(prepass_shader_cache_[i][j][k][l][m]);
}
}
}
}
}
for (auto i : IndexRange(lighting_type_len)) {
for (auto j : IndexRange(pipeline_type_len)) {
for (auto k : IndexRange(2)) {
for (auto l : IndexRange(2)) {
DRW_SHADER_FREE_SAFE(resolve_shader_cache_[i][j][k][l]);
}
}
}
}
}
GPUShader *ShaderCache::prepass_shader_get(ePipelineType pipeline_type,
eGeometryType geometry_type,
eShaderType shader_type,
eLightingType lighting_type,
bool clip)
{
GPUShader *&shader_ptr = prepass_shader_cache_[static_cast<int>(pipeline_type)][static_cast<int>(
geometry_type)][static_cast<int>(shader_type)][static_cast<int>(lighting_type)]
[clip ? 1 : 0];
if (shader_ptr != nullptr) {
return shader_ptr;
}
std::string info_name = "workbench_next_prepass_";
switch (geometry_type) {
case eGeometryType::MESH:
info_name += "mesh_";
break;
case eGeometryType::CURVES:
info_name += "curves_";
break;
case eGeometryType::POINTCLOUD:
info_name += "ptcloud_";
break;
}
switch (pipeline_type) {
case ePipelineType::OPAQUE:
info_name += "opaque_";
break;
case ePipelineType::TRANSPARENT:
info_name += "transparent_";
break;
case ePipelineType::SHADOW:
info_name += "shadow_";
break;
}
switch (lighting_type) {
case eLightingType::FLAT:
info_name += "flat_";
break;
case eLightingType::STUDIO:
info_name += "studio_";
break;
case eLightingType::MATCAP:
info_name += "matcap_";
break;
}
switch (shader_type) {
case eShaderType::MATERIAL:
info_name += "material";
break;
case eShaderType::TEXTURE:
info_name += "texture";
break;
}
info_name += clip ? "_clip" : "_no_clip";
shader_ptr = GPU_shader_create_from_info_name(info_name.c_str());
return shader_ptr;
}
GPUShader *ShaderCache::resolve_shader_get(ePipelineType pipeline_type,
eLightingType lighting_type,
bool cavity,
bool curvature)
{
GPUShader *&shader_ptr = resolve_shader_cache_[static_cast<int>(pipeline_type)][static_cast<int>(
lighting_type)][cavity][curvature];
if (shader_ptr != nullptr) {
return shader_ptr;
}
std::string info_name = "workbench_next_resolve_";
switch (pipeline_type) {
case ePipelineType::OPAQUE:
info_name += "opaque_";
break;
case ePipelineType::TRANSPARENT:
info_name += "transparent_";
break;
case ePipelineType::SHADOW:
BLI_assert_unreachable();
break;
}
switch (lighting_type) {
case eLightingType::FLAT:
info_name += "flat";
break;
case eLightingType::STUDIO:
info_name += "studio";
break;
case eLightingType::MATCAP:
info_name += "matcap";
break;
}
info_name += cavity ? "_cavity" : "_no_cavity";
info_name += curvature ? "_curvature" : "_no_curvature";
shader_ptr = GPU_shader_create_from_info_name(info_name.c_str());
return shader_ptr;
}
} // namespace blender::workbench

View File

@@ -13,7 +13,8 @@ struct LightData {
};
struct WorldData {
float4 viewport_size;
float2 viewport_size;
float2 viewport_size_inv;
float4 object_outline_color;
float4 shadow_direction_vs;
float shadow_focus;
@@ -41,8 +42,23 @@ struct WorldData {
int matcap_orientation;
bool use_specular;
float xray_alpha;
int _pad1;
int _pad2;
float4 background_color;
};
#define viewport_size_inv viewport_size.zw
struct ExtrudedFrustum {
/** \note vec3 array padded to vec4. */
float4 corners[16];
float4 planes[12];
int corners_count;
int planes_count;
int _padding[2];
};
struct ShadowPassData {
float4 far_plane;
float3 light_direction_ws;
int _padding;
};

View File

@@ -0,0 +1,465 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup draw_engine
*
* Shadow:
*
* Use stencil shadow buffer to cast a sharp shadow over opaque surfaces.
*
* After the main pre-pass we render shadow volumes using custom depth & stencil states to
* set the stencil of shadowed area to anything but 0.
*
* Then the shading pass will shade the areas with stencil not equal 0 differently.
*/
#include "BKE_object.h"
#include "BLI_math.h"
#include "DRW_render.h"
#include "GPU_compute.h"
#include "workbench_private.hh"
#define DEBUG_SHADOW_VOLUME 0
namespace blender::workbench {
ShadowPass::ShadowView::ShadowView() : View("ShadowPass.View"){};
void ShadowPass::ShadowView::setup(View &view, float3 light_direction, bool force_fail_method)
{
force_fail_method_ = force_fail_method;
light_direction_ = light_direction;
sync(view.viewmat(), view.winmat());
/* Prepare frustum extruded in the negative light direction,
* so we can test regular bounding boxes against it for culling. */
/* Frustum Corners indices
* Z Y
* | /
* |/
* .-----X
* 3----------7
* /| /|
* / | / |
* 0----------4 |
* | | | |
* | 2-------|--6
* | / | /
* |/ |/
* 1----------5
*/
/* Frustum Planes indices */
const int x_neg = 0; /* Left */
const int x_pos = 5; /* Right */
const int y_neg = 1; /* Bottom */
const int y_pos = 3; /* Top */
const int z_pos = 4; /* Near */
const int z_neg = 2; /* Far */
int3 corner_faces[8] = {{x_neg, y_neg, z_pos},
{x_neg, y_neg, z_neg},
{x_neg, y_pos, z_neg},
{x_neg, y_pos, z_pos},
{x_pos, y_neg, z_pos},
{x_pos, y_neg, z_neg},
{x_pos, y_pos, z_neg},
{x_pos, y_pos, z_pos}};
int2 edge_faces[12] = {{x_neg, y_neg},
{x_neg, z_neg},
{x_neg, y_pos},
{x_neg, z_pos},
{y_neg, x_pos},
{z_neg, x_pos},
{y_pos, x_pos},
{z_pos, x_pos},
{y_neg, z_pos},
{z_neg, y_neg},
{y_pos, z_neg},
{z_pos, y_pos}};
int2 edge_corners[12] = {{0, 1},
{1, 2},
{2, 3},
{3, 0},
{4, 5},
{5, 6},
{6, 7},
{7, 4},
{0, 4},
{1, 5},
{2, 6},
{3, 7}};
BoundBox frustum_corners;
DRW_culling_frustum_corners_get(nullptr, &frustum_corners);
float4 frustum_planes[6];
DRW_culling_frustum_planes_get(nullptr, (float(*)[4])frustum_planes);
Vector<float4> faces_result = {};
Vector<float3> corners_result = {};
/* "Unlit" frustum faces are left "as-is" */
bool face_lit[6];
for (int i : IndexRange(6)) {
/* Make the frustum normals face outwards */
frustum_planes[i] *= float4(-1, -1, -1, 1);
face_lit[i] = math::dot(float3(frustum_planes[i]), light_direction_) < 0;
if (!face_lit[i]) {
faces_result.append(frustum_planes[i]);
}
}
/* Edges between lit and unlit faces are extruded "infinitely" towards the light source */
for (int i : IndexRange(12)) {
int2 f = edge_faces[i];
bool a_lit = face_lit[f[0]];
bool b_lit = face_lit[f[1]];
if (a_lit != b_lit) {
/* Extrude Face */
float3 corner_a = frustum_corners.vec[edge_corners[i][0]];
float3 corner_b = frustum_corners.vec[edge_corners[i][1]];
float3 edge_direction = math::normalize(corner_b - corner_a);
float3 normal = math::normalize(math::cross(light_direction_, edge_direction));
float4 extruded_face = float4(UNPACK3(normal), math::dot(normal, corner_a));
/* Ensure the plane faces outwards */
bool flipped = false;
for (float3 corner : frustum_corners.vec) {
if (math::dot(float3(extruded_face), corner) > (extruded_face.w + 0.1)) {
BLI_assert(!flipped);
flipped = true;
extruded_face *= -1;
}
}
faces_result.append(extruded_face);
}
}
for (int i_corner : IndexRange(8)) {
int lit_faces = 0;
for (int i_face : IndexRange(3)) {
lit_faces += face_lit[corner_faces[i_corner][i_face]] ? 1 : 0;
}
if (lit_faces < 3) {
/* Add original corner */
corners_result.append(frustum_corners.vec[i_corner]);
if (lit_faces > 0) {
/* Add extruded corner */
corners_result.append(float3(frustum_corners.vec[i_corner]) - (light_direction_ * 1e4f));
}
}
}
for (int i : corners_result.index_range()) {
extruded_frustum_.corners[i] = float4(corners_result[i], 1);
}
extruded_frustum_.corners_count = corners_result.size();
for (int i : faces_result.index_range()) {
extruded_frustum_.planes[i] = faces_result[i];
}
extruded_frustum_.planes_count = faces_result.size();
extruded_frustum_.push_update();
}
bool ShadowPass::ShadowView::debug_object_culling(Object *ob)
{
printf("Test %s\n", ob->id.name);
const BoundBox *_bbox = BKE_object_boundbox_get(ob);
for (int p : IndexRange(extruded_frustum_.planes_count)) {
float4 plane = extruded_frustum_.planes[p];
bool separating_axis = true;
for (float3 corner : _bbox->vec) {
corner = float4x4(ob->object_to_world) * corner;
float signed_distance = math::dot(corner, float3(plane)) - plane.w;
if (signed_distance <= 0) {
separating_axis = false;
break;
}
}
if (separating_axis) {
printf("Sepatating Axis >>> x: %f, y: %f, z: %f, w: %f \n", UNPACK4(plane));
return true;
}
}
return false;
}
void ShadowPass::ShadowView::set_mode(ShadowPass::PassType type)
{
current_pass_type_ = type;
}
void ShadowPass::ShadowView::compute_visibility(ObjectMatricesBuf &matrices,
ObjectBoundsBuf &bounds,
uint resource_len,
bool debug_freeze)
{
GPU_debug_group_begin("ShadowView.compute_visibility");
uint word_per_draw = this->visibility_word_per_draw();
/* Switch between tightly packed and set of whole word per instance. */
uint words_len = (view_len_ == 1) ? divide_ceil_u(resource_len, 32) :
resource_len * word_per_draw;
words_len = ceil_to_multiple_u(max_ii(1, words_len), 4);
uint32_t data = 0xFFFFFFFFu;
if (current_pass_type_ == ShadowPass::PASS) {
/* TODO(fclem): Resize to nearest pow2 to reduce fragmentation. */
pass_visibility_buf_.resize(words_len);
GPU_storagebuf_clear(pass_visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
fail_visibility_buf_.resize(words_len);
GPU_storagebuf_clear(fail_visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
}
else if (current_pass_type_ == ShadowPass::FAIL) {
/* Already computed in the ShadowPass::PASS */
GPU_debug_group_end();
return;
}
else {
visibility_buf_.resize(words_len);
GPU_storagebuf_clear(visibility_buf_, GPU_R32UI, GPU_DATA_UINT, &data);
}
/* TODO(Miguel Pozo): Disabled in the optimization branch */
do_visibility_ = false;
if (do_visibility_) {
/* TODO(Miguel Pozo): Use regular culling for the caps pass */
static GPUShader *dynamic_pass_type_shader = GPU_shader_create_from_info_name(
"workbench_next_shadow_visibility_compute_dynamic_pass_type");
static GPUShader *static_pass_type_shader = GPU_shader_create_from_info_name(
"workbench_next_shadow_visibility_compute_static_pass_type");
GPUShader *shader = current_pass_type_ == ShadowPass::FORCED_FAIL ? static_pass_type_shader :
dynamic_pass_type_shader;
GPU_shader_bind(shader);
GPU_shader_uniform_1i(shader, "resource_len", resource_len);
GPU_shader_uniform_1i(shader, "view_len", view_len_);
GPU_shader_uniform_1i(shader, "visibility_word_per_draw", word_per_draw);
GPU_shader_uniform_1b(shader, "force_fail_method", force_fail_method_);
GPU_shader_uniform_3fv(shader, "shadow_direction", light_direction_);
GPU_uniformbuf_bind(extruded_frustum_,
GPU_shader_get_uniform_block(shader, "extruded_frustum"));
GPU_storagebuf_bind(matrices, GPU_shader_get_ssbo(shader, "matrix_buf"));
GPU_storagebuf_bind(bounds, GPU_shader_get_ssbo(shader, "bounds_buf"));
if (current_pass_type_ == ShadowPass::FORCED_FAIL) {
GPU_storagebuf_bind(visibility_buf_, GPU_shader_get_ssbo(shader, "visibility_buf"));
}
else {
GPU_storagebuf_bind(pass_visibility_buf_,
GPU_shader_get_ssbo(shader, "pass_visibility_buf"));
GPU_storagebuf_bind(fail_visibility_buf_,
GPU_shader_get_ssbo(shader, "fail_visibility_buf"));
}
GPU_uniformbuf_bind(data_, DRW_VIEW_UBO_SLOT);
GPU_compute_dispatch(shader, divide_ceil_u(resource_len, DRW_VISIBILITY_GROUP_SIZE), 1, 1);
GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
}
GPU_debug_group_end();
}
VisibilityBuf &ShadowPass::ShadowView::get_visibility_buffer()
{
switch (current_pass_type_) {
case ShadowPass::PASS:
return pass_visibility_buf_;
case ShadowPass::FAIL:
return fail_visibility_buf_;
case ShadowPass::FORCED_FAIL:
return visibility_buf_;
default:
BLI_assert_unreachable();
}
return visibility_buf_;
}
PassMain::Sub *&ShadowPass::get_pass_ptr(PassType type, bool manifold, bool cap /*= false*/)
{
return passes_[type][manifold][cap];
}
GPUShader *ShadowPass::get_shader(bool depth_pass, bool manifold, bool cap /*= false*/)
{
GPUShader *&shader = shaders_[depth_pass][manifold][cap];
if (shader == nullptr) {
std::string create_info_name = "workbench_next_shadow";
create_info_name += (depth_pass) ? "_pass" : "_fail";
create_info_name += (manifold) ? "_manifold" : "_no_manifold";
create_info_name += (cap) ? "_caps" : "_no_caps";
#if DEBUG_SHADOW_VOLUME
create_info_name += "_debug";
#endif
shader = GPU_shader_create_from_info_name(create_info_name.c_str());
}
return shader;
}
void ShadowPass::init(const SceneState &scene_state, SceneResources &resources)
{
enabled_ = scene_state.draw_shadows;
if (!enabled_) {
resources.world_buf.shadow_mul = 0.0f;
resources.world_buf.shadow_add = 1.0f;
return;
}
const Scene &scene = *scene_state.scene;
float3 direction_ws = scene.display.light_direction;
/* Turn the light in a way where it's more user friendly to control. */
SWAP(float, direction_ws.y, direction_ws.z);
direction_ws *= float3(-1, 1, -1);
float planes[6][4];
DRW_culling_frustum_planes_get(nullptr, planes);
pass_data_.light_direction_ws = direction_ws;
pass_data_.far_plane = planes[2] * float4(-1, -1, -1, 1);
pass_data_.push_update();
/* Shadow direction. */
float4x4 view_matrix;
DRW_view_viewmat_get(NULL, view_matrix.ptr(), false);
resources.world_buf.shadow_direction_vs = float4(view_matrix.ref_3x3() * direction_ws);
/* Clamp to avoid overshadowing and shading errors. */
float focus = clamp_f(scene.display.shadow_focus, 0.0001f, 0.99999f);
resources.world_buf.shadow_shift = scene.display.shadow_shift;
resources.world_buf.shadow_focus = 1.0f - focus * (1.0f - resources.world_buf.shadow_shift);
resources.world_buf.shadow_mul = scene_state.shading.shadow_intensity;
resources.world_buf.shadow_add = 1.0f - resources.world_buf.shadow_mul;
}
void ShadowPass::sync()
{
if (!enabled_) {
return;
}
#if DEBUG_SHADOW_VOLUME
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL;
DRWState depth_pass_state = state | DRW_STATE_DEPTH_LESS;
DRWState depth_fail_state = state | DRW_STATE_DEPTH_GREATER_EQUAL;
#else
DRWState state = DRW_STATE_DEPTH_LESS | DRW_STATE_STENCIL_ALWAYS;
DRWState depth_pass_state = state | DRW_STATE_WRITE_STENCIL_SHADOW_PASS;
DRWState depth_fail_state = state | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL;
#endif
pass_ps_.init();
pass_ps_.state_set(depth_pass_state);
pass_ps_.state_stencil(0xFF, 0xFF, 0xFF);
fail_ps_.init();
fail_ps_.state_set(depth_fail_state);
fail_ps_.state_stencil(0xFF, 0xFF, 0xFF);
forced_fail_ps_.init();
forced_fail_ps_.state_set(depth_fail_state);
forced_fail_ps_.state_stencil(0xFF, 0xFF, 0xFF);
/* Stencil Shadow passes. */
for (bool manifold : {false, true}) {
PassMain::Sub *&ps = get_pass_ptr(PASS, manifold);
ps = &pass_ps_.sub(manifold ? "manifold" : "non_manifold");
ps->shader_set(get_shader(true, manifold));
ps->bind_ubo("pass_data", pass_data_);
for (PassType fail_type : {FAIL, FORCED_FAIL}) {
PassMain &ps_main = fail_type == FAIL ? fail_ps_ : forced_fail_ps_;
PassMain::Sub *&ps = get_pass_ptr(fail_type, manifold, false);
ps = &ps_main.sub(manifold ? "NoCaps.manifold" : "NoCaps.non_manifold");
ps->shader_set(get_shader(false, manifold, false));
ps->bind_ubo("pass_data", pass_data_);
PassMain::Sub *&caps_ps = get_pass_ptr(fail_type, manifold, true);
caps_ps = &ps_main.sub(manifold ? "Caps.manifold" : "Caps.non_manifold");
caps_ps->shader_set(get_shader(false, manifold, true));
caps_ps->bind_ubo("pass_data", pass_data_);
}
}
}
void ShadowPass::object_sync(Manager &manager,
SceneState &scene_state,
ObjectRef &ob_ref,
ResourceHandle handle,
const bool has_transp_mat)
{
if (!enabled_) {
return;
}
Object *ob = ob_ref.object;
bool is_manifold;
GPUBatch *geom_shadow = DRW_cache_object_edge_detection_get(ob, &is_manifold);
if (geom_shadow == nullptr) {
return;
}
#define DEBUG_CULLING 0
#if DEBUG_CULLING
View view = View("View", DRW_view_default_get());
ShadowView shadow_view = ShadowView("ShadowView", view, pass_data_.light_direction_ws);
printf(
"%s culling : %s\n", ob->id.name, shadow_view.debug_object_culling(ob) ? "true" : "false");
#endif
/* Shadow pass technique needs object to be have all its surface opaque. */
/* We cannot use the PASS technique on non-manifold object (see T76168). */
bool force_fail_pass = has_transp_mat || (!is_manifold && (scene_state.cull_state != 0));
PassType fail_type = force_fail_pass ? FORCED_FAIL : FAIL;
/* Unless we force the FAIL Method we add draw commands to both methods,
* then the visibility compute shader selects the one needed */
if (!force_fail_pass) {
PassMain::Sub &ps = *get_pass_ptr(PASS, is_manifold);
ps.draw(geom_shadow, handle);
}
get_pass_ptr(fail_type, is_manifold, true)->draw(DRW_cache_object_surface_get(ob), handle);
get_pass_ptr(fail_type, is_manifold, false)->draw(geom_shadow, handle);
}
void ShadowPass::draw(Manager &manager,
View &view,
SceneResources &resources,
int2 resolution,
GPUTexture &depth_stencil_tx,
bool force_fail_method)
{
if (!enabled_) {
return;
}
fb_.ensure(GPU_ATTACHMENT_TEXTURE(&depth_stencil_tx),
GPU_ATTACHMENT_TEXTURE(resources.color_tx));
fb_.bind();
view_.setup(view, pass_data_.light_direction_ws, force_fail_method);
view_.set_mode(PASS);
manager.submit(pass_ps_, view_);
view_.set_mode(FAIL);
manager.submit(fail_ps_, view_);
view_.set_mode(FORCED_FAIL);
manager.submit(forced_fail_ps_, view_);
}
} // namespace blender::workbench

View File

@@ -0,0 +1,301 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "workbench_private.hh"
#include "BKE_camera.h"
#include "BKE_editmesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pbvh.h"
#include "DEG_depsgraph_query.h"
#include "DNA_fluid_types.h"
#include "ED_paint.h"
#include "ED_view3d.h"
#include "GPU_capabilities.h"
namespace blender::workbench {
void SceneState::init(Object *camera_ob /*= nullptr*/)
{
bool reset_taa = reset_taa_next_sample;
reset_taa_next_sample = false;
const DRWContextState *context = DRW_context_state_get();
View3D *v3d = context->v3d;
RegionView3D *rv3d = context->rv3d;
scene = DEG_get_evaluated_scene(context->depsgraph);
GPUTexture *viewport_tx = DRW_viewport_texture_list_get()->color;
resolution = int2(GPU_texture_width(viewport_tx), GPU_texture_height(viewport_tx));
camera_object = camera_ob;
if (camera_object == nullptr && v3d && rv3d) {
camera_object = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : nullptr;
}
camera = camera_object && camera_object->type == OB_CAMERA ?
static_cast<Camera *>(camera_object->data) :
nullptr;
object_mode = CTX_data_mode_enum_ex(context->object_edit, context->obact, context->object_mode);
/* TODO(Miguel Pozo):
* Check why Workbench Next exposes OB_MATERIAL, and Workbench exposes OB_RENDER */
bool is_render_mode = !v3d || ELEM(v3d->shading.type, OB_RENDER, OB_MATERIAL);
const View3DShading previous_shading = shading;
shading = is_render_mode ? scene->display.shading : v3d->shading;
cull_state = shading.flag & V3D_SHADING_BACKFACE_CULLING ? DRW_STATE_CULL_BACK :
DRW_STATE_NO_DRAW;
/* FIXME: This reproduce old behavior when workbench was separated in 2 engines.
* But this is a workaround for a missing update tagging. */
DRWState new_clip_state = RV3D_CLIPPING_ENABLED(v3d, rv3d) ? DRW_STATE_CLIP_PLANES :
DRW_STATE_NO_DRAW;
DRWState old_clip_state = clip_planes.size() > 0 ? DRW_STATE_CLIP_PLANES : DRW_STATE_NO_DRAW;
if (new_clip_state != old_clip_state) {
reset_taa = true;
}
clip_planes.clear();
if (new_clip_state & DRW_STATE_CLIP_PLANES) {
int plane_len = (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) ? 4 : 6;
for (auto i : IndexRange(plane_len)) {
clip_planes.append(rv3d->clip[i]);
}
}
if (!is_render_mode) {
if (shading.type < OB_SOLID) {
shading.light = V3D_LIGHTING_FLAT;
shading.color_type = V3D_SHADING_OBJECT_COLOR;
shading.xray_alpha = 0.0f;
}
else if (SHADING_XRAY_ENABLED(shading)) {
shading.xray_alpha = SHADING_XRAY_ALPHA(shading);
}
else {
shading.xray_alpha = 1.0f;
}
}
xray_mode = !is_render_mode && shading.xray_alpha != 1.0f;
if (SHADING_XRAY_FLAG_ENABLED(shading)) {
/* Disable shading options that aren't supported in transparency mode. */
shading.flag &= ~(V3D_SHADING_SHADOW | V3D_SHADING_CAVITY | V3D_SHADING_DEPTH_OF_FIELD);
}
if (SHADING_XRAY_ENABLED(shading) != SHADING_XRAY_ENABLED(previous_shading) ||
shading.flag != previous_shading.flag) {
reset_taa = true;
}
lighting_type = lighting_type_from_v3d_lighting(shading.light);
material_override = Material(shading.single_color);
background_color = float4(0.0f);
if (is_render_mode && scene->r.alphamode != R_ALPHAPREMUL) {
if (World *w = scene->world) {
background_color = float4(w->horr, w->horg, w->horb, 1.0f);
}
}
if (rv3d && rv3d->rflag & RV3D_GPULIGHT_UPDATE) {
reset_taa = true;
/* FIXME: This reproduce old behavior when workbench was separated in 2 engines.
* But this is a workaround for a missing update tagging. */
rv3d->rflag &= ~RV3D_GPULIGHT_UPDATE;
}
float4x4 matrix;
/*TODO(Miguel Pozo): New API ?*/
DRW_view_persmat_get(nullptr, matrix.ptr(), false);
if (matrix != view_projection_matrix) {
view_projection_matrix = matrix;
reset_taa = true;
}
bool is_playback = DRW_state_is_playback();
bool is_navigating = DRW_state_is_navigating();
/* Reset complete drawing when navigating or during viewport playback or when
* leaving one of those states. In case of multires modifier the navigation
* mesh differs from the viewport mesh, so we need to be sure to restart. */
if (is_playback || is_navigating) {
reset_taa = true;
reset_taa_next_sample = true;
}
int _samples_len = U.viewport_aa;
if (v3d && ELEM(v3d->shading.type, OB_RENDER, OB_MATERIAL)) {
_samples_len = scene->display.viewport_aa;
}
else if (DRW_state_is_image_render()) {
_samples_len = scene->display.render_aa;
}
if (is_navigating || is_playback) {
/* Only draw using SMAA or no AA when navigating. */
_samples_len = min_ii(_samples_len, 1);
}
/* 0 samples means no AA */
draw_aa = _samples_len > 0;
_samples_len = max_ii(_samples_len, 1);
/* Reset the TAA when we have already draw a sample, but the sample count differs from previous
* time. This removes render artifacts when the viewport anti-aliasing in the user preferences
* is set to a lower value. */
if (samples_len != _samples_len) {
samples_len = _samples_len;
reset_taa = true;
}
if (reset_taa || samples_len <= 1) {
sample = 0;
}
else {
sample++;
}
render_finished = sample >= samples_len && samples_len > 1;
/* TODO(Miguel Pozo) volumes_do */
draw_cavity = shading.flag & V3D_SHADING_CAVITY &&
ELEM(shading.cavity_type, V3D_SHADING_CAVITY_SSAO, V3D_SHADING_CAVITY_BOTH);
draw_curvature = shading.flag & V3D_SHADING_CAVITY && ELEM(shading.cavity_type,
V3D_SHADING_CAVITY_CURVATURE,
V3D_SHADING_CAVITY_BOTH);
draw_shadows = shading.flag & V3D_SHADING_SHADOW;
draw_outline = shading.flag & V3D_SHADING_OBJECT_OUTLINE;
draw_dof = camera && camera->dof.flag & CAM_DOF_ENABLED &&
shading.flag & V3D_SHADING_DEPTH_OF_FIELD;
draw_transparent_depth = draw_outline || draw_dof;
draw_object_id = draw_outline || draw_curvature;
};
static const CustomData *get_loop_custom_data(const Mesh *mesh)
{
if (mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
BLI_assert(mesh->edit_mesh != nullptr);
BLI_assert(mesh->edit_mesh->bm != nullptr);
return &mesh->edit_mesh->bm->ldata;
}
return &mesh->ldata;
}
static const CustomData *get_vert_custom_data(const Mesh *mesh)
{
if (mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
BLI_assert(mesh->edit_mesh != nullptr);
BLI_assert(mesh->edit_mesh->bm != nullptr);
return &mesh->edit_mesh->bm->vdata;
}
return &mesh->vdata;
}
ObjectState::ObjectState(const SceneState &scene_state, Object *ob)
{
sculpt_pbvh = false;
texture_paint_mode = false;
image_paint_override = nullptr;
override_sampler_state = GPU_SAMPLER_DEFAULT;
draw_shadow = false;
const DRWContextState *draw_ctx = DRW_context_state_get();
const Mesh *me = (ob->type == OB_MESH) ? static_cast<Mesh *>(ob->data) : nullptr;
const bool is_active = (ob == draw_ctx->obact);
/* TODO(Miguel Pozo) Is the double check needed?
* If it is, wouldn't be needed for sculpt_pbvh too?
*/
const bool is_render = DRW_state_is_image_render() && (draw_ctx->v3d == nullptr);
color_type = (eV3DShadingColorType)scene_state.shading.color_type;
if (!(is_active && DRW_object_use_hide_faces(ob))) {
draw_shadow = (ob->dtx & OB_DRAW_NO_SHADOW_CAST) == 0 && scene_state.draw_shadows;
}
if (me == nullptr) {
if (color_type == V3D_SHADING_TEXTURE_COLOR) {
color_type = V3D_SHADING_MATERIAL_COLOR;
}
else if (color_type == V3D_SHADING_VERTEX_COLOR) {
color_type = V3D_SHADING_OBJECT_COLOR;
}
use_per_material_batches = color_type == V3D_SHADING_MATERIAL_COLOR;
/* Early return */
return;
}
sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
!DRW_state_is_image_render();
if (sculpt_pbvh) {
/* Shadows are unsupported in sculpt mode. We could revert to the slow
* method in this case but I'm not sure if it's a good idea given that
* sculpted meshes are heavy to begin with. */
draw_shadow = false;
if (color_type == V3D_SHADING_TEXTURE_COLOR && BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES) {
/* Force use of material color for sculpt. */
color_type = V3D_SHADING_MATERIAL_COLOR;
}
/* Bad call C is required to access the tool system that is context aware. Cast to non-const
* due to current API. */
bContext *C = (bContext *)DRW_context_state_get()->evil_C;
if (C != NULL) {
color_type = ED_paint_shading_color_override(
C, &scene_state.scene->toolsettings->paint_mode, ob, color_type);
}
}
else {
const CustomData *cd_vdata = get_vert_custom_data(me);
const CustomData *cd_ldata = get_loop_custom_data(me);
bool has_color = (CustomData_has_layer(cd_vdata, CD_PROP_COLOR) ||
CustomData_has_layer(cd_vdata, CD_PROP_BYTE_COLOR) ||
CustomData_has_layer(cd_ldata, CD_PROP_COLOR) ||
CustomData_has_layer(cd_ldata, CD_PROP_BYTE_COLOR));
bool has_uv = CustomData_has_layer(cd_ldata, CD_PROP_FLOAT2);
if (color_type == V3D_SHADING_TEXTURE_COLOR) {
if (ob->dt < OB_TEXTURE || !has_uv) {
color_type = V3D_SHADING_MATERIAL_COLOR;
}
}
else if (color_type == V3D_SHADING_VERTEX_COLOR && !has_color) {
color_type = V3D_SHADING_OBJECT_COLOR;
}
if (!is_render) {
/* Force texture or vertex mode if object is in paint mode. */
const bool is_vertpaint_mode = is_active &&
(scene_state.object_mode == CTX_MODE_PAINT_VERTEX);
const bool is_texpaint_mode = is_active &&
(scene_state.object_mode == CTX_MODE_PAINT_TEXTURE);
if (is_vertpaint_mode && has_color) {
color_type = V3D_SHADING_VERTEX_COLOR;
}
else if (is_texpaint_mode && has_uv) {
color_type = V3D_SHADING_TEXTURE_COLOR;
texture_paint_mode = true;
const ImagePaintSettings *imapaint = &scene_state.scene->toolsettings->imapaint;
if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
image_paint_override = imapaint->canvas;
override_sampler_state = GPU_SAMPLER_REPEAT;
SET_FLAG_FROM_TEST(override_sampler_state,
imapaint->interp == IMAGEPAINT_INTERP_LINEAR,
GPU_SAMPLER_FILTER);
}
}
}
}
use_per_material_batches = image_paint_override == nullptr && ELEM(color_type,
V3D_SHADING_TEXTURE_COLOR,
V3D_SHADING_MATERIAL_COLOR);
}
} // namespace blender::workbench

View File

@@ -1052,6 +1052,16 @@ class Framebuffer : NonCopyable {
&fb_, {depth, color1, color2, color3, color4, color5, color6, color7, color8});
}
void bind()
{
GPU_framebuffer_bind(fb_);
}
void clear_depth(float depth)
{
GPU_framebuffer_clear_depth(fb_, depth);
}
Framebuffer &operator=(Framebuffer &&a)
{
if (*this != a) {

View File

@@ -1007,8 +1007,10 @@ void DRW_cache_free_old_batches(Main *bmain)
static void drw_engines_init(void)
{
DRW_stats_group_start("drw_engines.engines_init");
DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) {
PROFILE_START(stime);
DRW_stats_group_start(engine->idname);
const DrawEngineDataSize *data_size = engine->vedata_size;
memset(data->psl->passes, 0, sizeof(*data->psl->passes) * data_size->psl_len);
@@ -1017,15 +1019,19 @@ static void drw_engines_init(void)
engine->engine_init(data);
}
DRW_stats_group_end();
PROFILE_END_UPDATE(data->init_time, stime);
}
DRW_stats_group_end();
}
static void drw_engines_cache_init(void)
{
DRW_stats_group_start("drw_engines.cache_init");
DRW_manager_begin_sync();
DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) {
DRW_stats_group_start(engine->idname);
if (data->text_draw_cache) {
DRW_text_cache_destroy(data->text_draw_cache);
data->text_draw_cache = NULL;
@@ -1037,7 +1043,9 @@ static void drw_engines_cache_init(void)
if (engine->cache_init) {
engine->cache_init(data);
}
DRW_stats_group_end();
}
DRW_stats_group_end();
}
static void drw_engines_world_update(Scene *scene)
@@ -1045,12 +1053,16 @@ static void drw_engines_world_update(Scene *scene)
if (scene->world == NULL) {
return;
}
DRW_stats_group_start("drw_engines.world_update");
DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) {
if (engine->id_update) {
DRW_stats_group_start(engine->idname);
engine->id_update(data, &scene->world->id);
DRW_stats_group_end();
}
}
DRW_stats_group_end();
}
static void drw_engines_cache_populate(Object *ob)
@@ -1091,17 +1103,22 @@ static void drw_engines_cache_populate(Object *ob)
static void drw_engines_cache_finish(void)
{
DRW_stats_group_start("drw_engines.cache_finish");
DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) {
if (engine->cache_finish) {
DRW_stats_group_start(engine->idname);
engine->cache_finish(data);
DRW_stats_group_end();
}
}
DRW_manager_end_sync();
DRW_stats_group_end();
}
static void drw_engines_draw_scene(void)
{
DRW_stats_group_start("drw_engines.draw_scene");
DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) {
PROFILE_START(stime);
if (engine->draw_scene) {
@@ -1117,6 +1134,7 @@ static void drw_engines_draw_scene(void)
}
/* Reset state after drawing */
DRW_state_reset();
DRW_stats_group_end();
}
static void drw_engines_draw_text(void)
@@ -1183,6 +1201,11 @@ static void drw_engines_enable_from_engine(const RenderEngineType *engine_type,
switch (drawtype) {
case OB_WIRE:
case OB_SOLID:
if (U.experimental.enable_workbench_next &&
strcmp(engine_type->idname, "BLENDER_WORKBENCH_NEXT") == 0) {
use_drw_engine(DRW_engine_viewport_workbench_next_type.draw_engine);
break;
}
use_drw_engine(DRW_engine_viewport_workbench_type.draw_engine);
break;
case OB_MATERIAL:
@@ -1669,6 +1692,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
drw_context_state_init();
drw_manager_init(&DST, viewport, NULL);
DRW_viewport_colormanagement_set(viewport);
const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
@@ -1707,6 +1731,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
/* Only iterate over objects for internal engines or when overlays are enabled */
if (do_populate_loop) {
DRW_stats_group_start("drw_render.populate_loop");
DST.dupli_origin = NULL;
DST.dupli_origin_data = NULL;
DEGObjectIterSettings deg_iter_settings = {0};
@@ -1728,6 +1754,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
drw_engines_cache_populate(ob);
}
DEG_OBJECT_ITER_END;
DRW_stats_group_end();
}
drw_duplidata_free();
@@ -2990,6 +3018,9 @@ void DRW_engines_register_experimental(void)
if (U.experimental.enable_eevee_next) {
RE_engines_register(&DRW_engine_viewport_eevee_next_type);
}
if (U.experimental.enable_workbench_next) {
RE_engines_register(&DRW_engine_viewport_workbench_next_type);
}
}
void DRW_engines_register(void)

View File

@@ -166,7 +166,7 @@ void Manager::submit(PassMain &pass, View &view)
bool freeze_culling = (U.experimental.use_viewport_debug && DST.draw_ctx.v3d &&
(DST.draw_ctx.v3d->debug_flag & V3D_DEBUG_FREEZE_CULLING) != 0);
view.compute_visibility(bounds_buf, resource_len_, freeze_culling);
view.compute_visibility(matrix_buf, bounds_buf, resource_len_, freeze_culling);
command::RecordingState state;
state.inverted_view = view.is_inverted();
@@ -174,7 +174,7 @@ void Manager::submit(PassMain &pass, View &view)
pass.draw_commands_buf_.bind(state,
pass.headers_,
pass.commands_,
view.visibility_buf_,
view.get_visibility_buffer(),
view.visibility_word_per_draw(),
view.view_len_);
@@ -217,7 +217,7 @@ Manager::SubmitDebugOutput Manager::submit_debug(PassSimple &pass, View &view)
output.resource_id = {pass.draw_commands_buf_.resource_id_buf_.data(),
pass.draw_commands_buf_.resource_id_count_};
/* There is no visibility data for PassSimple. */
output.visibility = {(uint *)view.visibility_buf_.data(), 0};
output.visibility = {(uint *)view.get_visibility_buffer().data(), 0};
return output;
}
@@ -228,12 +228,13 @@ Manager::SubmitDebugOutput Manager::submit_debug(PassMain &pass, View &view)
GPU_finish();
pass.draw_commands_buf_.resource_id_buf_.read();
view.visibility_buf_.read();
view.get_visibility_buffer().read();
Manager::SubmitDebugOutput output;
output.resource_id = {pass.draw_commands_buf_.resource_id_buf_.data(),
pass.draw_commands_buf_.resource_id_count_};
output.visibility = {(uint *)view.visibility_buf_.data(), divide_ceil_u(resource_len_, 32)};
output.visibility = {(uint *)view.get_visibility_buffer().data(),
divide_ceil_u(resource_len_, 32)};
return output;
}

View File

@@ -16,6 +16,7 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_mesh.h"
#include "BKE_mesh_wrapper.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
@@ -695,7 +696,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob)
drw_call_calc_orco(ob, ob_infos->orcotexfac);
/* Random float value. */
uint random = (DST.dupli_source) ?
DST.dupli_source->random_id :
DST.dupli_source->random_id :
/* TODO(fclem): this is rather costly to do at runtime. Maybe we can
* put it in ob->runtime and make depsgraph ensure it is up to date. */
BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0);
@@ -719,26 +720,41 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob)
static void drw_call_culling_init(DRWCullingState *cull, Object *ob)
{
const BoundBox *bbox;
if (ob != nullptr && (bbox = BKE_object_boundbox_get(ob))) {
float corner[3];
/* Get BoundSphere center and radius from the BoundBox. */
mid_v3_v3v3(cull->bsphere.center, bbox->vec[0], bbox->vec[6]);
mul_v3_m4v3(corner, ob->object_to_world, bbox->vec[0]);
mul_m4_v3(ob->object_to_world, cull->bsphere.center);
cull->bsphere.radius = len_v3v3(cull->bsphere.center, corner);
/* Bypass test */
cull->bsphere.radius = -1.0f;
/* Reset user data */
cull->user_data = nullptr;
if (ob != nullptr) {
if (ob->type == OB_MESH) {
/* Optimization: Retrieve the mesh cached min max directly.
* Avoids allocating a BoundBox on every sample for each DupliObject instance.
* TODO(Miguel Pozo): Remove once T92963 or T96968 are done */
float3 min, max;
INIT_MINMAX(min, max);
BKE_mesh_wrapper_minmax(static_cast<Mesh *>(ob->data), min, max);
/* Get BoundSphere center and radius from min/max. */
float3 min_world = float4x4(ob->object_to_world) * min;
float3 max_world = float4x4(ob->object_to_world) * max;
mid_v3_v3v3(cull->bsphere.center, min_world, max_world);
cull->bsphere.radius = len_v3v3(cull->bsphere.center, max_world);
}
else if (const BoundBox *bbox = BKE_object_boundbox_get(ob)) {
float corner[3];
/* Get BoundSphere center and radius from the BoundBox. */
mid_v3_v3v3(cull->bsphere.center, bbox->vec[0], bbox->vec[6]);
mul_v3_m4v3(corner, ob->object_to_world, bbox->vec[0]);
mul_m4_v3(ob->object_to_world, cull->bsphere.center);
cull->bsphere.radius = len_v3v3(cull->bsphere.center, corner);
}
/* Bypass test for very large objects (see T67319). */
if (UNLIKELY(cull->bsphere.radius > 1e12)) {
cull->bsphere.radius = -1.0f;
}
}
else {
/* Bypass test. */
cull->bsphere.radius = -1.0f;
}
/* Reset user data */
cull->user_data = nullptr;
}
static DRWResourceHandle drw_resource_handle_new(float (*obmat)[4], Object *ob)

View File

@@ -252,6 +252,7 @@ class PassBase {
/**
* Record a compute dispatch call.
*/
void dispatch(int2 group_len);
void dispatch(int3 group_len);
void dispatch(int3 *group_len);
void dispatch(StorageBuffer<DispatchCommand> &indirect_buffer);
@@ -705,6 +706,12 @@ inline void PassBase<T>::draw_procedural_indirect(
/** \name Compute Dispatch Implementation
* \{ */
template<class T> inline void PassBase<T>::dispatch(int2 group_len)
{
BLI_assert(shader_);
create_command(Type::Dispatch).dispatch = {int3(group_len.x, group_len.y, 1)};
}
template<class T> inline void PassBase<T>::dispatch(int3 group_len)
{
BLI_assert(shader_);

View File

@@ -13,6 +13,7 @@
#include "BKE_curve.h"
#include "BKE_duplilist.h"
#include "BKE_mesh.h"
#include "BKE_mesh_wrapper.h"
#include "BKE_object.h"
#include "BKE_volume.h"
#include "BLI_hash.h"
@@ -82,15 +83,6 @@ inline void ObjectInfos::sync(const blender::draw::ObjectRef ref, bool is_active
SET_FLAG_FROM_TEST(
flag, ref.object->transflag & OB_NEG_SCALE, eObjectInfoFlag::OBJECT_NEGATIVE_SCALE);
if (ref.dupli_object == nullptr) {
/* TODO(fclem): this is rather costly to do at draw time. Maybe we can
* put it in ob->runtime and make depsgraph ensure it is up to date. */
random = BLI_hash_int_2d(BLI_hash_string(ref.object->id.name + 2), 0) *
(1.0f / (float)0xFFFFFFFF);
}
else {
random = ref.dupli_object->random_id * (1.0f / (float)0xFFFFFFFF);
}
/* Default values. Set if needed. */
random = 0.0f;
@@ -155,51 +147,54 @@ inline std::ostream &operator<<(std::ostream &stream, const ObjectInfos &infos)
inline void ObjectBounds::sync()
{
bounding_sphere.w = -1.0f; /* Disable test. */
test_enabled = false;
}
inline void ObjectBounds::sync(Object &ob)
{
const BoundBox *bbox = BKE_object_boundbox_get(&ob);
if (bbox == nullptr) {
bounding_sphere.w = -1.0f; /* Disable test. */
return;
float3 min, max;
INIT_MINMAX(min, max);
if (ob.type == OB_MESH) {
/* Optimization: Retrieve the mesh cached min max directly.
* Avoids allocating a BoundBox on every sample for each DupliObject instance.
* TODO(Miguel Pozo): Remove once T92963 or T96968 are done */
BKE_mesh_wrapper_minmax(static_cast<Mesh *>(ob.data), min, max);
}
*reinterpret_cast<float3 *>(&bounding_corners[0]) = bbox->vec[0];
*reinterpret_cast<float3 *>(&bounding_corners[1]) = bbox->vec[4];
*reinterpret_cast<float3 *>(&bounding_corners[2]) = bbox->vec[3];
*reinterpret_cast<float3 *>(&bounding_corners[3]) = bbox->vec[1];
bounding_sphere.w = 0.0f; /* Enable test. */
else {
const BoundBox *bbox = BKE_object_boundbox_get(&ob);
if (bbox == nullptr) {
test_enabled = false;
return;
}
for (const float3 &corner : bbox->vec) {
minmax_v3v3_v3(min, max, corner);
}
}
size = (max - min) / 2.0f;
center = min + size;
test_enabled = true;
}
inline void ObjectBounds::sync(const float3 &center, const float3 &size)
{
*reinterpret_cast<float3 *>(&bounding_corners[0]) = center - size;
*reinterpret_cast<float3 *>(&bounding_corners[1]) = center + float3(+size.x, -size.y, -size.z);
*reinterpret_cast<float3 *>(&bounding_corners[2]) = center + float3(-size.x, +size.y, -size.z);
*reinterpret_cast<float3 *>(&bounding_corners[3]) = center + float3(-size.x, -size.y, +size.z);
bounding_sphere.w = 0.0; /* Enable test. */
this->center = center;
this->size = size;
test_enabled = true;
}
inline std::ostream &operator<<(std::ostream &stream, const ObjectBounds &bounds)
{
stream << "ObjectBounds(";
if (bounds.bounding_sphere.w == -1.0f) {
if (!bounds.test_enabled) {
stream << "skipped)" << std::endl;
return stream;
}
stream << std::endl;
stream << ".bounding_corners[0]"
<< *reinterpret_cast<const float3 *>(&bounds.bounding_corners[0]) << std::endl;
stream << ".bounding_corners[1]"
<< *reinterpret_cast<const float3 *>(&bounds.bounding_corners[1]) << std::endl;
stream << ".bounding_corners[2]"
<< *reinterpret_cast<const float3 *>(&bounds.bounding_corners[2]) << std::endl;
stream << ".bounding_corners[3]"
<< *reinterpret_cast<const float3 *>(&bounds.bounding_corners[3]) << std::endl;
stream << ".sphere=(pos=" << float3(bounds.bounding_sphere)
<< ", rad=" << bounds.bounding_sphere.w << std::endl;
stream << ")" << std::endl;
stream << ".center" << bounds.center << std::endl;
stream << ".size" << bounds.size << std::endl;
return stream;
}

View File

@@ -175,15 +175,11 @@ struct ObjectInfos {
BLI_STATIC_ASSERT_ALIGN(ObjectInfos, 16)
struct ObjectBounds {
/**
* Uploaded as vertex (0, 4, 3, 1) of the bbox in local space, matching XYZ axis order.
* Then processed by GPU and stored as (0, 4-0, 3-0, 1-0) in world space for faster culling.
*/
float4 bounding_corners[4];
/** Bounding sphere derived from the bounding corner. Computed on GPU. */
float4 bounding_sphere;
/** Radius of the inscribed sphere derived from the bounding corner. Computed on GPU. */
#define _inner_sphere_radius bounding_corners[3].w
float3 center;
bool test_enabled;
/* TODO(Miguel Pozo): This is actually half size */
float3 size;
uint _pad;
#if !defined(GPU_SHADER) && defined(__cplusplus)
void sync();

View File

@@ -31,6 +31,14 @@ void View::sync(const float4x4 &view_mat, const float4x4 &win_mat, int view_id)
dirty_ = true;
}
void View::sync(const DRWView *view)
{
float4x4 view_mat, win_mat;
DRW_view_viewmat_get(view, view_mat.ptr(), false);
DRW_view_winmat_get(view, win_mat.ptr(), false);
this->sync(view_mat, win_mat);
}
void View::frustum_boundbox_calc(int view_id)
{
/* Extract the 8 corners from a Projection Matrix. */
@@ -219,7 +227,10 @@ void View::bind()
GPU_uniformbuf_bind(culling_, DRW_VIEW_CULLING_UBO_SLOT);
}
void View::compute_visibility(ObjectBoundsBuf &bounds, uint resource_len, bool debug_freeze)
void View::compute_visibility(ObjectMatricesBuf &matrices,
ObjectBoundsBuf &bounds,
uint resource_len,
bool debug_freeze)
{
if (debug_freeze && frozen_ == false) {
data_freeze_[0] = static_cast<ViewMatrices>(data_[0]);
@@ -256,6 +267,7 @@ void View::compute_visibility(ObjectBoundsBuf &bounds, uint resource_len, bool d
GPU_shader_uniform_1i(shader, "resource_len", resource_len);
GPU_shader_uniform_1i(shader, "view_len", view_len_);
GPU_shader_uniform_1i(shader, "visibility_word_per_draw", word_per_draw);
GPU_storagebuf_bind(matrices, GPU_shader_get_ssbo(shader, "matrix_buf"));
GPU_storagebuf_bind(bounds, GPU_shader_get_ssbo(shader, "bounds_buf"));
GPU_storagebuf_bind(visibility_buf_, GPU_shader_get_ssbo(shader, "visibility_buf"));
GPU_uniformbuf_bind(frozen_ ? data_freeze_ : data_, DRW_VIEW_UBO_SLOT);
@@ -273,4 +285,9 @@ void View::compute_visibility(ObjectBoundsBuf &bounds, uint resource_len, bool d
GPU_debug_group_end();
}
VisibilityBuf &View::get_visibility_buffer()
{
return visibility_buf_;
}
} // namespace blender::draw

View File

@@ -26,13 +26,14 @@ namespace blender::draw {
class Manager;
/* TODO: de-duplicate. */
using ObjectMatricesBuf = StorageArrayBuffer<ObjectMatrices, 128>;
using ObjectBoundsBuf = StorageArrayBuffer<ObjectBounds, 128>;
using VisibilityBuf = StorageArrayBuffer<uint, 4, true>;
class View {
friend Manager;
private:
protected:
/** TODO(fclem): Maybe try to reduce the minimum cost if the number of view is lower. */
UniformArrayBuffer<ViewMatrices, DRW_VIEW_MAX> data_;
@@ -64,14 +65,14 @@ class View {
View(const char *name, const DRWView *view)
: visibility_buf_(name), debug_name_(name), view_len_(1)
{
float4x4 view_mat, win_mat;
DRW_view_viewmat_get(view, view_mat.ptr(), false);
DRW_view_winmat_get(view, win_mat.ptr(), false);
this->sync(view_mat, win_mat);
this->sync(view);
}
void sync(const float4x4 &view_mat, const float4x4 &win_mat, int view_id = 0);
/* For compatibility with old system. Will be removed at some point. */
void sync(const DRWView *view);
bool is_persp(int view_id = 0) const
{
BLI_assert(view_id < view_len_);
@@ -132,10 +133,14 @@ class View {
return (view_len_ == 1) ? 0 : divide_ceil_u(view_len_, 32);
}
private:
protected:
/** Called from draw manager. */
void bind();
void compute_visibility(ObjectBoundsBuf &bounds, uint resource_len, bool debug_freeze);
virtual void compute_visibility(ObjectMatricesBuf &matrices,
ObjectBoundsBuf &bounds,
uint resource_len,
bool debug_freeze);
virtual VisibilityBuf &get_visibility_buffer();
void update_viewport_size();

View File

@@ -123,312 +123,138 @@ IsectFrustum isect_data_setup(Frustum shape)
/** \} */
/* ---------------------------------------------------------------------- */
/** \name View Intersection functions.
* \{ */
bool intersect_view(Pyramid pyramid)
{
bool intersects = true;
/* Do Pyramid vertices vs Frustum planes. */
for (int p = 0; p < 6; ++p) {
bool is_any_vertex_on_positive_side = false;
for (int v = 0; v < 5; ++v) {
float test = dot(drw_view_culling.planes[p], vec4(pyramid.corners[v], 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
}
}
if (!intersects) {
return intersects;
}
/* Now do Frustum vertices vs Pyramid planes. */
IsectPyramid i_pyramid = isect_data_setup(pyramid);
for (int p = 0; p < 5; ++p) {
bool is_any_vertex_on_positive_side = false;
for (int v = 0; v < 8; ++v) {
float test = dot(i_pyramid.planes[p], vec4(drw_view_culling.corners[v].xyz, 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
}
}
return intersects;
}
bool intersect_view(Box box)
{
bool intersects = true;
/* Do Box vertices vs Frustum planes. */
for (int p = 0; p < 6; ++p) {
bool is_any_vertex_on_positive_side = false;
for (int v = 0; v < 8; ++v) {
float test = dot(drw_view_culling.planes[p], vec4(box.corners[v], 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
}
}
if (!intersects) {
return intersects;
}
/* Now do Frustum vertices vs Box planes. */
IsectBox i_box = isect_data_setup(box);
for (int p = 0; p < 6; ++p) {
bool is_any_vertex_on_positive_side = false;
for (int v = 0; v < 8; ++v) {
float test = dot(i_box.planes[p], vec4(drw_view_culling.corners[v].xyz, 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
}
}
return intersects;
}
bool intersect_view(IsectBox i_box)
{
bool intersects = true;
/* Do Box vertices vs Frustum planes. */
for (int p = 0; p < 6; ++p) {
bool is_any_vertex_on_positive_side = false;
for (int v = 0; v < 8; ++v) {
float test = dot(drw_view_culling.planes[p], vec4(i_box.corners[v], 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
}
}
if (!intersects) {
return intersects;
}
for (int p = 0; p < 6; ++p) {
bool is_any_vertex_on_positive_side = false;
for (int v = 0; v < 8; ++v) {
float test = dot(i_box.planes[p], vec4(drw_view_culling.corners[v].xyz, 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
}
}
return intersects;
}
bool intersect_view(Sphere sphere)
{
bool intersects = true;
for (int p = 0; p < 6 && intersects; ++p) {
float dist_to_plane = dot(drw_view_culling.planes[p], vec4(sphere.center, 1.0));
if (dist_to_plane < -sphere.radius) {
intersects = false;
}
}
/* TODO reject false positive. */
return intersects;
}
/** \} */
/* ---------------------------------------------------------------------- */
/** \name Shape vs. Shape Intersection functions.
* \{ */
bool intersect(IsectPyramid i_pyramid, Box box)
bool intersect(IsectPyramid i_pyramid, IsectBox i_box)
{
bool intersects = true;
/* Do Box vertices vs Pyramid planes. */
for (int p = 0; p < 5; ++p) {
bool is_any_vertex_on_positive_side = false;
bool separating_axis = true;
for (int v = 0; v < 8; ++v) {
float test = dot(i_pyramid.planes[p], vec4(box.corners[v], 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
float signed_distance = point_plane_projection_dist(i_box.corners[v], i_pyramid.planes[p]);
if (signed_distance <= 0.0) {
separating_axis = false;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
if (separating_axis) {
return false;
}
}
if (!intersects) {
return intersects;
}
/* Now do Pyramid vertices vs Box planes. */
IsectBox i_box = isect_data_setup(box);
for (int p = 0; p < 6; ++p) {
bool is_any_vertex_on_positive_side = false;
bool separating_axis = true;
for (int v = 0; v < 5; ++v) {
float test = dot(i_box.planes[p], vec4(i_pyramid.corners[v], 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
float signed_distance = point_plane_projection_dist(i_pyramid.corners[v], i_box.planes[p]);
if (signed_distance <= 0.0) {
separating_axis = false;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
if (separating_axis) {
return false;
}
}
return intersects;
return true;
}
bool intersect(IsectPyramid i_pyramid, Box box)
{
return intersect(i_pyramid, isect_data_setup(box));
}
bool intersect(IsectFrustum i_frustum, Pyramid pyramid)
{
bool intersects = true;
/* Do Pyramid vertices vs Frustum planes. */
for (int p = 0; p < 6; ++p) {
bool is_any_vertex_on_positive_side = false;
bool separating_axis = true;
for (int v = 0; v < 5; ++v) {
float test = dot(i_frustum.planes[p], vec4(pyramid.corners[v], 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
float signed_distance = point_plane_projection_dist(pyramid.corners[v], i_frustum.planes[p]);
if (signed_distance <= 0.0) {
separating_axis = false;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
if (separating_axis) {
return false;
}
}
if (!intersects) {
return intersects;
}
/* Now do Frustum vertices vs Pyramid planes. */
IsectPyramid i_pyramid = isect_data_setup(pyramid);
for (int p = 0; p < 5; ++p) {
bool is_any_vertex_on_positive_side = false;
bool separating_axis = true;
for (int v = 0; v < 8; ++v) {
float test = dot(i_pyramid.planes[p], vec4(i_frustum.corners[v].xyz, 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
float signed_distance = point_plane_projection_dist(i_frustum.corners[v].xyz,
i_pyramid.planes[p]);
if (signed_distance <= 0.0) {
separating_axis = false;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
if (separating_axis) {
return false;
}
}
return intersects;
return true;
}
bool intersect(IsectFrustum i_frustum, IsectBox i_box)
{
/* Do Box vertices vs Frustum planes. */
for (int p = 0; p < 6; ++p) {
bool separating_axis = true;
for (int v = 0; v < 8; ++v) {
float signed_distance = point_plane_projection_dist(i_box.corners[v], i_frustum.planes[p]);
if (signed_distance <= 0.0) {
separating_axis = false;
break;
}
}
if (separating_axis) {
return false;
}
}
/* Now do Frustum vertices vs Box planes. */
for (int p = 0; p < 6; ++p) {
bool separating_axis = true;
for (int v = 0; v < 8; ++v) {
float signed_distance = point_plane_projection_dist(i_frustum.corners[v].xyz,
i_box.planes[p]);
if (signed_distance <= 0.0) {
separating_axis = false;
break;
}
}
if (separating_axis) {
return false;
}
}
return true;
}
bool intersect(IsectFrustum i_frustum, Box box)
{
bool intersects = true;
/* Do Box vertices vs Frustum planes. */
for (int p = 0; p < 6; ++p) {
bool is_any_vertex_on_positive_side = false;
for (int v = 0; v < 8; ++v) {
float test = dot(i_frustum.planes[p], vec4(box.corners[v], 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
}
}
if (!intersects) {
return intersects;
}
/* Now do Frustum vertices vs Box planes. */
IsectBox i_box = isect_data_setup(box);
for (int p = 0; p < 6; ++p) {
bool is_any_vertex_on_positive_side = false;
for (int v = 0; v < 8; ++v) {
float test = dot(i_box.planes[p], vec4(i_frustum.corners[v].xyz, 1.0));
if (test > 0.0) {
is_any_vertex_on_positive_side = true;
break;
}
}
bool all_vertex_on_negative_side = !is_any_vertex_on_positive_side;
if (all_vertex_on_negative_side) {
intersects = false;
break;
}
}
return intersects;
return intersect(i_frustum, isect_data_setup(box));
}
bool intersect(IsectFrustum i_frustum, Sphere sphere)
{
bool intersects = true;
for (int p = 0; p < 6; ++p) {
float dist_to_plane = dot(i_frustum.planes[p], vec4(sphere.center, 1.0));
if (dist_to_plane < -sphere.radius) {
intersects = false;
break;
float signed_distance = point_plane_projection_dist(sphere.center, i_frustum.planes[p]);
if (signed_distance > sphere.radius) {
return false;
}
}
return intersects;
return true;
}
bool intersect(Cone cone, Sphere sphere)
@@ -454,7 +280,7 @@ bool intersect(Cone cone, Sphere sphere)
* only in the monotonic region [0 .. M_PI / 2]. This saves costly acos() calls. */
bool intersects = (cone_sphere_center_cos >= cone_sphere_angle_sum_cos);
return intersects;
return true;
}
bool intersect(Circle circle_a, Circle circle_b)
@@ -464,3 +290,41 @@ bool intersect(Circle circle_a, Circle circle_b)
}
/** \} */
/* ---------------------------------------------------------------------- */
/** \name View Intersection functions.
* \{ */
IsectFrustum IsectFrustum_from_view()
{
IsectFrustum result;
for (int i = 0; i < 8; i++) {
result.corners[i] = drw_view_culling.corners[i].xyz;
}
for (int i = 0; i < 6; i++) {
result.planes[i] = drw_view_culling.planes[i];
}
return result;
}
bool intersect_view(Pyramid pyramid)
{
return intersect(IsectFrustum_from_view(), pyramid);
}
bool intersect_view(Box box)
{
return intersect(IsectFrustum_from_view(), box);
}
bool intersect_view(IsectBox i_box)
{
return intersect(IsectFrustum_from_view(), i_box);
}
bool intersect_view(Sphere sphere)
{
return intersect(IsectFrustum_from_view(), sphere);
}
/** \} */

View File

@@ -5,6 +5,9 @@
/** \name Math intersection & projection functions.
* \{ */
/* WARNING: For legacy reasons,
* planes in Blender are represented with the projection component (w) flipped. */
vec4 plane_from_quad(vec3 v0, vec3 v1, vec3 v2, vec3 v3)
{
vec3 nor = normalize(cross(v2 - v1, v0 - v1) + cross(v0 - v3, v2 - v3));
@@ -17,6 +20,11 @@ vec4 plane_from_tri(vec3 v0, vec3 v1, vec3 v2)
return vec4(nor, -dot(nor, v2));
}
float point_plane_projection_dist(vec3 point, vec4 plane)
{
return -dot(vec4(point, 1), plane);
}
float point_plane_projection_dist(vec3 line_origin, vec3 plane_origin, vec3 plane_normal)
{
return dot(plane_normal, plane_origin - line_origin);

View File

@@ -14,6 +14,8 @@ void main()
mat4 model_mat = matrix_buf[resource_id].model;
ObjectInfos infos = infos_buf[resource_id];
#if 0
ObjectBounds bounds = bounds_buf[resource_id];
if (bounds.bounding_sphere.w != -1.0) {
@@ -51,6 +53,7 @@ void main()
bounds_buf[resource_id].bounding_sphere.w = -1.0;
}
}
#endif
vec3 loc = infos.orco_add; /* Box center. */
vec3 size = infos.orco_mul; /* Box half-extent. */

View File

@@ -160,8 +160,9 @@ GPU_SHADER_CREATE_INFO(draw_visibility_compute)
.do_static_compilation(true)
.local_group_size(DRW_VISIBILITY_GROUP_SIZE)
.define("DRW_VIEW_LEN", "64")
.storage_buf(0, Qualifier::READ, "ObjectBounds", "bounds_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, "uint", "visibility_buf[]")
.storage_buf(0, Qualifier::READ, "ObjectMatrices", "matrix_buf[]")
.storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]")
.storage_buf(2, Qualifier::READ_WRITE, "uint", "visibility_buf[]")
.push_constant(Type::INT, "resource_len")
.push_constant(Type::INT, "view_len")
.push_constant(Type::INT, "visibility_word_per_draw")
@@ -202,6 +203,9 @@ GPU_SHADER_CREATE_INFO(draw_resource_id_fallback)
.define("UNIFORM_RESOURCE_ID_NEW")
.vertex_in(15, Type::INT, "drw_ResourceID");
/** TODO mask view id bits. */
GPU_SHADER_CREATE_INFO(draw_resource_handle_new).define("resource_handle", "drw_ResourceID");
/** \} */
/* -------------------------------------------------------------------- */

View File

@@ -26,25 +26,31 @@ void main()
return;
}
mat4 model_mat = matrix_buf[gl_GlobalInvocationID.x].model;
ObjectBounds bounds = bounds_buf[gl_GlobalInvocationID.x];
if (bounds.bounding_sphere.w != -1.0) {
IsectBox box = isect_data_setup(bounds.bounding_corners[0].xyz,
bounds.bounding_corners[1].xyz,
bounds.bounding_corners[2].xyz,
bounds.bounding_corners[3].xyz);
Sphere bounding_sphere = Sphere(bounds.bounding_sphere.xyz, bounds.bounding_sphere.w);
Sphere inscribed_sphere = Sphere(bounds.bounding_sphere.xyz, bounds._inner_sphere_radius);
if (bounds.test_enabled) {
vec3 origin = transform_point(model_mat, bounds.center - bounds.size);
vec3 side_x = transform_point(model_mat, bounds.center + bounds.size * vec3(1, -1, -1)) -
origin;
vec3 side_y = transform_point(model_mat, bounds.center + bounds.size * vec3(-1, 1, -1)) -
origin;
vec3 side_z = transform_point(model_mat, bounds.center + bounds.size * vec3(-1, -1, 1)) -
origin;
vec3 center = origin + ((side_x + side_y + side_z) / 2.0f);
float radius = distance(origin, center);
float inscribed_radius = min(min(bounds.size.x, bounds.size.y), bounds.size.z);
IsectBox box = isect_data_setup(origin, side_x, side_y, side_z);
Sphere bounding_sphere = Sphere(center, radius);
Sphere inscribed_sphere = Sphere(center, inscribed_radius);
for (drw_view_id = 0; drw_view_id < view_len; drw_view_id++) {
if (intersect_view(inscribed_sphere) == true) {
/* Visible. */
if (intersect_view(inscribed_sphere)) {
/* Visible */
}
else if (intersect_view(bounding_sphere) == false) {
/* Not visible. */
mask_visibility_bit(drw_view_id);
}
else if (intersect_view(box) == false) {
else if (intersect_view(bounding_sphere) == false || intersect_view(box) == false) {
/* Not visible. */
mask_visibility_bit(drw_view_id);
}

View File

@@ -7,6 +7,10 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define AREATEX_WIDTH 160
#define AREATEX_HEIGHT 560
#define AREATEX_PITCH (AREATEX_WIDTH * 2)
@@ -28,3 +32,8 @@ extern const unsigned char areaTexBytes[];
* - DX10: DXGI_FORMAT_R8_UNORM
*/
extern const unsigned char searchTexBytes[];
#ifdef __cplusplus
}
#endif

View File

@@ -1296,13 +1296,21 @@ void ED_scene_draw_fps(const struct Scene *scene, int xoffset, int *yoffset);
void ED_view3d_stop_render_preview(struct wmWindowManager *wm, struct ARegion *region);
void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *area);
#define XRAY_ALPHA(v3d) \
(((v3d)->shading.type == OB_WIRE) ? (v3d)->shading.xray_alpha_wire : (v3d)->shading.xray_alpha)
#define XRAY_FLAG(v3d) \
(((v3d)->shading.type == OB_WIRE) ? V3D_SHADING_XRAY_WIREFRAME : V3D_SHADING_XRAY)
#define XRAY_FLAG_ENABLED(v3d) (((v3d)->shading.flag & XRAY_FLAG(v3d)) != 0)
#define XRAY_ENABLED(v3d) (XRAY_FLAG_ENABLED(v3d) && (XRAY_ALPHA(v3d) < 1.0f))
#define XRAY_ACTIVE(v3d) (XRAY_ENABLED(v3d) && ((v3d)->shading.type < OB_MATERIAL))
#define SHADING_XRAY_ALPHA(shading) \
(((shading).type == OB_WIRE) ? (shading).xray_alpha_wire : (shading).xray_alpha)
#define SHADING_XRAY_FLAG(shading) \
(((shading).type == OB_WIRE) ? V3D_SHADING_XRAY_WIREFRAME : V3D_SHADING_XRAY)
#define SHADING_XRAY_FLAG_ENABLED(shading) (((shading).flag & SHADING_XRAY_FLAG(shading)) != 0)
#define SHADING_XRAY_ENABLED(shading) \
(SHADING_XRAY_FLAG_ENABLED(shading) && (SHADING_XRAY_ALPHA(shading) < 1.0f))
#define SHADING_XRAY_ACTIVE(shading) \
(SHADING_XRAY_ENABLED(shading) && ((shading).type < OB_MATERIAL))
#define XRAY_ALPHA(v3d) SHADING_XRAY_ALPHA((v3d)->shading)
#define XRAY_FLAG(v3d) SHADING_XRAY_FLAG((v3d)->shading)
#define XRAY_FLAG_ENABLED(v3d) SHADING_XRAY_FLAG_ENABLED((v3d)->shading)
#define XRAY_ENABLED(v3d) SHADING_XRAY_ENABLED((v3d)->shading)
#define XRAY_ACTIVE(v3d) SHADING_XRAY_ACTIVE((v3d)->shading)
/* view3d_draw_legacy.c */

View File

@@ -29,6 +29,7 @@ set(INC
# For *_info.hh includes.
../compositor/realtime_compositor
../draw/engines/eevee_next
../draw/engines/workbench
../draw/intern
# For node muting stuff.

View File

@@ -41,7 +41,7 @@ typedef enum eGPUTextureType {
GPU_TEXTURE_CUBE_ARRAY = (GPU_TEXTURE_CUBE | GPU_TEXTURE_ARRAY),
} eGPUTextureType;
ENUM_OPERATORS(eGPUTextureType, GPU_TEXTURE_CUBE_ARRAY)
ENUM_OPERATORS(eGPUTextureType, GPU_TEXTURE_BUFFER)
/* Format types for samplers within the shader.
* This covers the sampler format type permutations within GLSL/MSL. */

View File

@@ -141,6 +141,8 @@ void GLContext::activate()
bound_ubo_slots = 0;
immActivate();
process_frame_timings();
}
void GLContext::deactivate()

View File

@@ -95,6 +95,21 @@ class GLContext : public Context {
/** #GLBackend owns this data. */
GLSharedOrphanLists &shared_orphan_list_;
struct TimeQuery {
std::string name;
GLuint handles[2];
int stack_depth;
bool finished;
int64_t cpu_start;
float cpu_time;
};
struct FrameQueries {
Vector<TimeQuery> queries;
};
Vector<FrameQueries> frame_timings;
void process_frame_timings();
public:
GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list);
~GLContext();

View File

@@ -80,7 +80,7 @@ static void APIENTRY debug_callback(GLenum /*source*/,
const bool use_color = CLG_color_support_get(&LOG);
if (ELEM(severity, GL_DEBUG_SEVERITY_LOW, GL_DEBUG_SEVERITY_NOTIFICATION)) {
if ((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level >= CLG_SEVERITY_INFO)) {
if ((LOG.type->flag & CLG_FLAG_USE) && (LOG.type->level <= CLG_SEVERITY_INFO)) {
const char *format = use_color ? "\033[2m%s\033[0m" : "%s";
CLG_logf(LOG.type, CLG_SEVERITY_INFO, "Notification", "", format, message);
}
@@ -131,6 +131,10 @@ static void APIENTRY debug_callback(GLenum /*source*/,
void init_gl_callbacks()
{
if (G.log.level >= CLG_SEVERITY_LEN) {
return;
}
CLOG_ENSURE(&LOG);
char msg[256] = "";
@@ -362,6 +366,9 @@ namespace blender::gpu {
* Useful for debugging through render-doc. This makes all the API calls grouped into "passes".
* \{ */
#define PROFILE_DEBUG_GROUPS 0
#define MAX_DEBUG_GROUPS_STACK_DEPTH 4
void GLContext::debug_group_begin(const char *name, int index)
{
if ((G.debug & G_DEBUG_GPU) &&
@@ -369,6 +376,23 @@ void GLContext::debug_group_begin(const char *name, int index)
/* Add 10 to avoid collision with other indices from other possible callback layers. */
index += 10;
glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, index, -1, name);
#if PROFILE_DEBUG_GROUPS
if (frame_timings.is_empty()) {
frame_timings.append({});
}
TimeQuery query = {};
query.finished = false;
query.name = name;
query.stack_depth = debug_stack.size();
glGetInteger64v(GL_TIMESTAMP, &query.cpu_start);
/* Use GL_TIMESTAMP instead of GL_ELAPSED_TIME to support nested debug groups */
glGenQueries(2, query.handles);
glQueryCounter(query.handles[0], GL_TIMESTAMP);
frame_timings.last().queries.append(query);
#endif
}
}
@@ -377,9 +401,96 @@ void GLContext::debug_group_end()
if ((G.debug & G_DEBUG_GPU) &&
(epoxy_gl_version() >= 43 || epoxy_has_gl_extension("GL_KHR_debug"))) {
glPopDebugGroup();
#if PROFILE_DEBUG_GROUPS
Vector<TimeQuery> &queries = frame_timings.last().queries;
for (int i = queries.size() - 1; i >= 0; i--) {
TimeQuery &query = queries[i];
if (!query.finished) {
glQueryCounter(query.handles[1], GL_TIMESTAMP);
query.finished = true;
int64_t cpu_end;
glGetInteger64v(GL_TIMESTAMP, &cpu_end);
query.cpu_time = (cpu_end - query.cpu_start) / 1000000.0;
break;
}
BLI_assert(i != 0);
}
#endif
}
}
void GLContext::process_frame_timings()
{
#if PROFILE_DEBUG_GROUPS
if (G.debug & G_DEBUG_GPU) {
for (int frame_i = 0; frame_i < frame_timings.size(); frame_i++) {
Vector<TimeQuery> &queries = frame_timings[frame_i].queries;
if (queries.is_empty() || !queries.last().finished /* Group begin/end mismatch */) {
frame_timings.remove(frame_i--);
continue;
}
GLint ready = 0;
glGetQueryObjectiv(queries.last().handles[1], GL_QUERY_RESULT_AVAILABLE, &ready);
if (!ready) {
break;
}
std::stringstream result;
result << "\n";
// clang-format off
result << " Group | GPU | CPU | Latency\n";
result << "--------------------------------|------|------|--------\n";
result << " Total | ";
// clang-format on
GLuint64 begin_timestamp = 0;
GLuint64 end_timestamp = 0;
glGetQueryObjectui64v(queries.first().handles[0], GL_QUERY_RESULT, &begin_timestamp);
glGetQueryObjectui64v(queries.last().handles[1], GL_QUERY_RESULT, &end_timestamp);
float gpu_total_time = (end_timestamp - begin_timestamp) / 1000000.0;
result << std::to_string(gpu_total_time).substr(0, 4) << " | ";
float cpu_total_time = (queries.last().cpu_start - queries.first().cpu_start) / 1000000.0 +
queries.last().cpu_time;
result << std::to_string(cpu_total_time).substr(0, 4) << " | \n";
for (TimeQuery &query : queries) {
if (query.stack_depth >= MAX_DEBUG_GROUPS_STACK_DEPTH) {
glDeleteQueries(2, query.handles);
continue;
}
GLuint64 begin_timestamp = 0;
GLuint64 end_timestamp = 0;
glGetQueryObjectui64v(query.handles[0], GL_QUERY_RESULT, &begin_timestamp);
glGetQueryObjectui64v(query.handles[1], GL_QUERY_RESULT, &end_timestamp);
glDeleteQueries(2, query.handles);
result << std::string(query.stack_depth, '.');
result << " " << query.name
<< std::string(max_ii(0, 30 - query.stack_depth - query.name.length()), ' ')
<< " | ";
float gpu_time = (end_timestamp - begin_timestamp) / 1000000.0;
result << std::to_string(gpu_time).substr(0, 4) << " | ";
result << std::to_string(query.cpu_time).substr(0, 4) << " | ";
result << std::to_string((begin_timestamp - query.cpu_start) / 1000000.0).substr(0, 4)
<< "\n";
}
std::string print = result.str();
printf("%s", print.c_str());
frame_timings.remove(frame_i--);
}
frame_timings.append({});
}
#endif
}
/** \} */
} // namespace blender::gpu

View File

@@ -385,7 +385,9 @@ void GLTexture::clear(eGPUDataFormat data_format, const void *data)
{
BLI_assert(validate_data_format(format_, data_format));
if (GLContext::clear_texture_support) {
/* ClearTexImage can be up to 10 times slower */
const bool USE_CLEAR_TEX_IMAGE = false;
if (USE_CLEAR_TEX_IMAGE && GLContext::clear_texture_support) {
int mip = 0;
GLenum gl_format = to_gl_data_format(format_);
GLenum gl_type = to_gl(data_format);

View File

@@ -652,6 +652,8 @@ typedef struct UserDef_Experimental {
char use_override_templates;
char enable_eevee_next;
char use_sculpt_texture_paint;
char enable_workbench_next;
char _pad[7];
/** `makesdna` does not allow empty structs. */
} UserDef_Experimental;
@@ -955,7 +957,7 @@ extern UserDef U;
/* ***************** USERDEF ****************** */
/* Toggles for unfinished 2.8 UserPref design. */
//#define WITH_USERDEF_WORKSPACES
// #define WITH_USERDEF_WORKSPACES
/** #UserDef_SpaceData.section_active (UI active_section) */
typedef enum eUserPref_Section {

View File

@@ -6426,6 +6426,13 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "enable_eevee_next", 1);
RNA_def_property_ui_text(prop, "EEVEE Next", "Enable the new EEVEE codebase, requires restart");
prop = RNA_def_property(srna, "enable_workbench_next", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "enable_workbench_next", 1);
RNA_def_property_ui_text(prop,
"Workbench Next",
"Enable the new Workbench codebase, requires "
"restart");
prop = RNA_def_property(srna, "use_viewport_debug", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_viewport_debug", 1);
RNA_def_property_ui_text(prop,