11from __future__ import annotations
2+
3+ bl_info = {
4+ "name" : "Fast PBR Viewport Render" ,
5+ "blender" : (3 , 00 , 0 ),
6+ "category" : "Object" ,
7+ }
8+ __name__ # This is the name of the folder that the __init__.py is in. I think
9+ addonName : str = bl_info ["name" ]
10+ addonNameShort : str = "Fast PBR"
11+
212from typing import Any , Mapping , ValuesView
313from typing import TYPE_CHECKING
414
5- from PIL import ImageChops
615
716import bpy
817
918import bpy
1019import subprocess
1120import sys
12-
21+ import ctypes
1322from bpy .types import MaterialSlot , PropertyGroup
23+ # print("LOOK HERE ", sys.executable)
24+ import os
25+ import importlib
26+ def putTextInBox (text ):
27+ lines = text .splitlines ()
28+ width = max (len (s ) for s in lines )
29+ res = ['┌' + '─' * width + '┐' ]
30+ for s in lines :
31+ res .append ('│' + (s + ' ' * width )[:width ] + '│' )
32+ res .append ('└' + '─' * width + '┘' )
33+ return '\n ' .join (res )
34+ import pip
35+ def installPackage (package ):
36+ if hasattr (pip , 'main' ):
37+ pip .main (['install' , package ])
38+ else :
39+ pip ._internal .main (['install' , package ])
40+
41+ # def installPackage(package: str):
42+ # # subprocess.check_call(['"' + sys.executable + '"', "-m", "pip", "install", package])
43+ # # os.system(f'"{sys.executable}" -m pip install {package}')
44+ # ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, f"""-c import pdb; pdb.set_trace()\nimport os\nos.system('"{sys.executable}" -m pip install {package}')\ninput()""", None, 1)
45+
46+ # Running installPackage is a slow operation, therefore we want to make sure that we only run it when necessary, hence this function to speed up registration/activation time of the addon SIGNIFICANTLY (like by 5-10 seconds).
47+ def attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist (packageName , moduleName ):
48+ print ("Attempting" )
49+ try :
50+ importlib .import_module (moduleName )
51+ # from PIL import Image
52+ except Exception as error :
53+ print (putTextInBox (f"{ addonName } Error: ---\n { error } \n ---\n when attempting to import { moduleName } , we're assuming that you dont have { packageName } installed and will try to install it for you!" ))
54+ installPackage (packageName )
55+ importlib .import_module (moduleName ) # Doesnt actually work?
56+ ListOfModulesToAttemptToImportAndInstallItIfItIfTheCorespondingPackageDoesntExist = [['PILLOW' , 'PIL' ], ['numpy' ]]
57+ attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist ('PILLOW' , 'PIL' )
58+ import PIL
59+ attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist ('numpy' , 'numpy' )
60+ import numpy
61+
62+
63+ from PIL import ImageChops
64+
1465
15- bl_info = {
16- "name" : "Fast PBR Viewport Render" ,
17- "blender" : (3 , 00 , 0 ),
18- "category" : "Object" ,
19- }
2066
2167def copyModifiers (copyAllModifiersAndThereSettingsFromObject : bpy .types .Object , copyTargetObjects : list (bpy .types .Object )):
2268 # copyAllModifiersAndThereSettingsFromObject = bpy.context.object
@@ -54,37 +100,9 @@ def copyModifiers(copyAllModifiersAndThereSettingsFromObject: bpy.types.Object,
54100
55101# installPackage('PILLOW')
56102# installPackage('numpy')
57- __name__ # This is the name of the folder that the __init__.py is in. I think
58- addonName : str = bl_info ["name" ]
59- addonNameShort : str = "Fast PBR"
60103
61- import importlib
62- def putTextInBox (text ):
63- lines = text .splitlines ()
64- width = max (len (s ) for s in lines )
65- res = ['┌' + '─' * width + '┐' ]
66- for s in lines :
67- res .append ('│' + (s + ' ' * width )[:width ] + '│' )
68- res .append ('└' + '─' * width + '┘' )
69- return '\n ' .join (res )
70- def installPackage (package : str ):
71- subprocess .check_call ([sys .executable , "-m" , "pip" , "install" , package ])
72104
73- # Running installPackage is a slow operation, therefore we want to make sure that we only run it when necessary, hence this function to speed up registration/activation time of the addon SIGNIFICANTLY (like by 5-10 seconds).
74- def attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist (packageName , moduleName ):
75- print ("Attempting" )
76- try :
77- importlib .import_module (moduleName )
78- # from PIL import Image
79- except Exception as error :
80- print (putTextInBox (f"{ addonName } Error: ---\n { error } \n ---\n when attempting to import { moduleName } , we're assuming that you dont have { packageName } installed and will try to install it for you!" ))
81- installPackage (packageName )
82- importlib .import_module (moduleName ) # Doesnt actually work?
83- ListOfModulesToAttemptToImportAndInstallItIfItIfTheCorespondingPackageDoesntExist = [['PILLOW' , 'PIL' ], ['numpy' ]]
84- attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist ('PILLOW' , 'PIL' )
85- import PIL
86- attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist ('numpy' , 'numpy' )
87- import numpy
105+
88106# import pi
89107# attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist('PILLOW', 'PIL')
90108# attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist('numpy', 'numpy')
@@ -1223,7 +1241,8 @@ def restoreSettings(self):
12231241# subtype="FILE_PATH")
12241242
12251243class RenderPass (FastPanelBaseClass , bpy .types .Panel ):
1226- bl_options = {'DRAW_BOX' , 'DEFAULT_CLOSED' }
1244+ bl_options = {'DEFAULT_CLOSED' }
1245+ # bl_options = {'DRAW_BOX', 'DEFAULT_CLOSED'}
12271246 # @registerOperatorsDecorator
12281247
12291248 class settings (bpy .types .PropertyGroup ): # CANNOT BE RENAMED
@@ -1336,7 +1355,7 @@ def save_to_disk(self):
13361355 # bpy.ops.image.
13371356
13381357 @classmethod
1339- def perform_post_process (self ):
1358+ def perform_post_process (self = None ):
13401359 """Runs after save_to_disk"""
13411360 pass
13421361
@@ -1405,7 +1424,7 @@ def prepare_to_render(self):
14051424 # raise ValueError('A very specific bad thing happened.')
14061425
14071426 @classmethod
1408- def perform_post_process (self ):
1427+ def perform_post_process (self = None ):
14091428 pathToStoreImageInIncludingFileNameAndFileExtension = pathToStoreImagesIn
14101429 fileToPerformPostProcessOn = pathToStoreImageInIncludingFileNameAndFileExtension + self .passName + ".png"
14111430
@@ -1497,11 +1516,18 @@ def prepare_to_render(self):
14971516 bpy .context .scene .view_settings .gamma = 1
14981517 bpy .context .scene .sequencer_colorspace_settings .name = 'Raw'
14991518
1519+ # Render properties > Sampling
1520+ bpy .context .scene .eevee .taa_samples = 1
1521+ bpy .context .scene .eevee .taa_render_samples = 1
1522+
1523+
15001524 @classmethod
15011525 def perform_post_process (cls ):
15021526 # return
15031527 # Now we will invert the pixels where the normal map has rendered a face that is facing away from the camera.
15041528
1529+
1530+
15051531 # This will let users simply not care about correcting there face normals before rendering, so even if it may
15061532 # add 3-4 seconds worth of render time - its probably gonna save the user more time than if he had to ensure
15071533 # his normals are correct.
@@ -1592,9 +1618,7 @@ def perform_post_process(cls):
15921618 # image_with_inverted_green = Image.merge('RGB', (invert(red), invert(green), blue))
15931619 # image_with_inverted_green.save('test_inverted_green.tif')
15941620
1595- # os.remove(normalWithBackfaceCulling)
1596-
1597-
1621+ os .remove (normalWithBackfaceCulling )
15981622 bpy .context .scene .display .shading .show_backface_culling = False
15991623
16001624
@@ -1646,8 +1670,15 @@ def prepare_to_render(self):
16461670class RenderMatIDPassWithWorkbenchViewportDisplayCol (RenderPass ):
16471671 passName = "MatID"
16481672
1673+
1674+ display_device = ''
1675+ view_transform = ''
1676+ sequencer_colorspace_settings_name = ''
1677+
1678+
16491679 @classmethod
16501680 def prepare_to_render (self ):
1681+ self : RenderMatIDPassWithWorkbenchViewportDisplayCol
16511682
16521683 # # 3D Viewport > Viewport shading (top right) > Render Pass
16531684 # bpy.context.space_data.shading.render_pass = 'DIFFUSE_COLOR'
@@ -1664,11 +1695,29 @@ def prepare_to_render(self):
16641695 # Render properties > Options
16651696 bpy .context .scene .display .shading .show_cavity = False
16661697
1698+
1699+ # Render Properties > Color Management
1700+ self .display_device = bpy .context .scene .display_settings .display_device
1701+ bpy .context .scene .display_settings .display_device = 'sRGB'
1702+
1703+ self .view_transform = bpy .context .scene .view_settings .view_transform
1704+ bpy .context .scene .view_settings .view_transform = 'Filmic'
1705+
1706+ self .sequencer_colorspace_settings_name = bpy .context .scene .sequencer_colorspace_settings .name
1707+ bpy .context .scene .sequencer_colorspace_settings .name = 'Filmic Log'
1708+
1709+
16671710 # for material in bpy.data.materials:
16681711 # material: bpy.types.Material
16691712 # material.diffuse_color = material.node_tree.nodes
16701713 # bpy.data.materials["Material"].node_tree.nodes["Principled BSDF"].inputs[0].default_value = (0.8, 0.272124, 0.414903, 1)
16711714
1715+ @classmethod
1716+ def perform_post_process (self ):
1717+ bpy .context .scene .display_settings .display_device = self .display_device
1718+ bpy .context .scene .view_settings .view_transform = self .view_transform
1719+ bpy .context .scene .sequencer_colorspace_settings .name = self .sequencer_colorspace_settings_name
1720+
16721721
16731722# @bookmark AO pass
16741723@renderPassDecorator
@@ -1735,6 +1784,7 @@ class RenderTransparencyPassWithEeveeEnvironmentPass(RenderPass):
17351784 # settings["High quality transparency"] = False
17361785
17371786 restoreDisplayDevice = ''
1787+ restoreViewtransform = ''
17381788 restoreSequencer = ''
17391789
17401790
@@ -1753,16 +1803,28 @@ def prepare_to_render(self):
17531803 # Render properties > Color
17541804 bpy .context .scene .display .shading .single_color = (999 , 999 , 999 )
17551805
1806+ # World properties > Surface > color
1807+ bpy .context .scene .world .color = (9999 , 9999 , 9999 )
1808+
1809+
17561810 self .restoreDisplayDevice = bpy .context .scene .display_settings .display_device
17571811 bpy .context .scene .display_settings .display_device = 'None'
17581812
1813+ # self.restoreViewtransform = bpy.context.scene.view_settings.view_transform
1814+ # bpy.context.scene.view_settings.view_transform = 'Raw'
1815+
1816+
17591817 self .restoreSequencer = bpy .context .scene .sequencer_colorspace_settings .name
17601818 bpy .context .scene .sequencer_colorspace_settings .name = 'Raw'
17611819
1820+
1821+
17621822
1823+ @classmethod
17631824 def perform_post_process (self ):
17641825 # Inverts the alpha pass so that white means visible and black means invisible.
17651826 bpy .context .scene .display_settings .display_device = self .restoreDisplayDevice
1827+ # bpy.context.scene.view_settings.view_transform = self.restoreViewtransform
17661828 bpy .context .scene .sequencer_colorspace_settings .name = self .restoreSequencer
17671829
17681830 pathToStoreImageInIncludingFileNameAndFileExtension = pathToStoreImagesIn
0 commit comments