SkinLightmapRenderer.py (23617B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\paperDoll\SkinLightmapRenderer.py 2 from __future__ import print_function 3 from __future__ import absolute_import 4 import trinity 5 import blue 6 import telemetry 7 import weakref 8 import itertools 9 import log 10 from . import commonClientFunctions as pdCcf 11 from eve.common.script.paperDoll import paperDollCommonFunctions as pdCf 12 13 def LogError(*args): 14 log.Log(' '.join(map(strx, args)), log.LGERR) 15 16 17 class SkinLightmapRenderer: 18 renderJob = None 19 scene = None 20 instances = set({}) 21 22 @staticmethod 23 def Scene(): 24 if SkinLightmapRenderer.scene is None or SkinLightmapRenderer.scene.object is None: 25 jobs = trinity.renderJobs.recurring 26 for job in jobs: 27 if 'paperdoll' in job.name.lower(): 28 return job.scene.object 29 30 return 31 return SkinLightmapRenderer.scene.object 32 33 LIGHTMAP_RENDERER_EFFECT = 'res:/Graphics/Effect/Managed/Interior/Avatar/SkinnedAvatarBRDFLightmapUnwrap_Single.fx' 34 LIGHTMAP_RENDERER_DOUBLE_EFFECT = 'res:/Graphics/Effect/Managed/Interior/Avatar/SkinnedAvatarBRDFLightmapUnwrap_Double.fx' 35 STRETCHMAP_RENDERER_EFFECT = 'res:/Graphics/Effect/Managed/Interior/Avatar/SkinnedAvatarBRDFStretchmap.fx' 36 LIGHTMAP_SCATTER_EFFECT = 'res:/Graphics/Effect/Managed/Interior/Avatar/LightmapScatter.fx' 37 LIGHTMAP_EXPAND_EFFECT = 'res:/Graphics/Effect/Utility/Compositing/ExpandOpaqueNoMask.fx' 38 BECKMANN_LOOKUP_EFFECT = 'res:/Graphics/Effect/Managed/Interior/Avatar/SkinnedAvatarBRDFBeckmannLookup.fx' 39 LIGHTMAP_APPLICATION_EFFECT = 'res:/Graphics/Effect/Managed/Interior/Avatar/SkinnedAvatarBRDFLightmapApplication_Single.fx' 40 LIGHTMAP_APPLICATION_DOUBLE_EFFECT = 'res:/Graphics/Effect/Managed/Interior/Avatar/SkinnedAvatarBRDFLightmapApplication_Double.fx' 41 42 class Mesh: 43 44 def __init__(self): 45 self.origEffect = {} 46 self.stretchmapRenderEffect = {} 47 self.lightmapRenderEffect = {} 48 self.lightmapApplyEffect = {} 49 self.liveParameters = [] 50 51 def ExtractOrigEffect(self, mesh): 52 for area in itertools.chain(mesh.opaqueAreas, mesh.decalAreas): 53 pdCcf.AddWeakBlue(self, 'origEffect', area, area.effect) 54 55 return len(self.origEffect) > 0 56 57 @staticmethod 58 def CreateRenderTarget(width, height, format, useRT = False): 59 return trinity.TriTextureRes(trinity.Tr2RenderTarget(width, height, 1, format)) 60 61 @telemetry.ZONE_METHOD 62 def CreateRenderTargets(self, lightmapFormat): 63 try: 64 self.lightmap = self.CreateRenderTarget(self.lightmapSize[0], self.lightmapSize[1], lightmapFormat) 65 self.stretchmap = self.CreateRenderTarget(min(1024, self.lightmapSize[0]), min(1024, self.lightmapSize[1]), lightmapFormat) 66 self.scatteredLightmap = self.CreateRenderTarget(self.lightmapSize[0], self.lightmapSize[1], lightmapFormat) 67 self.depth = trinity.Tr2DepthStencil(self.lightmapSize[0], self.lightmapSize[1], trinity.DEPTH_STENCIL_FORMAT.D24S8) 68 except Exception: 69 self.lightmap = None 70 self.stretchmap = None 71 self.scatteredLightmap = None 72 return False 73 74 return True 75 76 @telemetry.ZONE_METHOD 77 def AddTex2D(self, effect, name, resourcePath = None): 78 param = trinity.TriTextureParameter() 79 param.name = name 80 if resourcePath is not None: 81 param.resourcePath = resourcePath 82 effect.resources.append(param) 83 return param 84 85 def Print(self, msg): 86 print('[Skin]', msg) 87 88 def DebugPrint(self, msg): 89 pass 90 91 @telemetry.ZONE_METHOD 92 def __init__(self, highQuality = True, useHDR = True): 93 if True: 94 raytraceWidth = 2048 95 raytraceHeight = 2048 96 else: 97 raytraceWidth = 512 98 raytraceHeight = 512 99 self.raytracing = None 100 self.refreshMeshes = False 101 self.skinMapPath = None 102 self.precomputeBeckmann = False 103 self.useExpandOpaque = False 104 self.lightmapEffectPreload = self.PreloadEffect(self.LIGHTMAP_RENDERER_EFFECT) 105 self.lightmapDoubleEffectPreload = self.PreloadEffect(self.LIGHTMAP_RENDERER_DOUBLE_EFFECT) 106 self.stretchmapEffectPreload = self.PreloadEffect(self.STRETCHMAP_RENDERER_EFFECT) 107 self.lightmapApplicationEffectPreload = self.PreloadEffect(self.LIGHTMAP_APPLICATION_EFFECT) 108 self.lightmapApplicationDoubleEffectPreload = self.PreloadEffect(self.LIGHTMAP_APPLICATION_DOUBLE_EFFECT) 109 self.lightmapScatterEffect = self.PreloadEffect(self.LIGHTMAP_SCATTER_EFFECT) 110 self.lightmapExpandEffect = self.PreloadEffect(self.LIGHTMAP_EXPAND_EFFECT) 111 if self.precomputeBeckmann: 112 self.beckmannLookupEffect = self.PreloadEffect(self.BECKMANN_LOOKUP_EFFECT) 113 self.skinnedObject = None 114 self.paramLightmap = self.AddTex2D(self.lightmapScatterEffect, 'Lightmap') 115 self.paramStretchmap = self.AddTex2D(self.lightmapScatterEffect, 'Stretchmap') 116 self.paramNoisemap = self.AddTex2D(self.lightmapScatterEffect, 'Noisemap', 'res:/Texture/Global/noise.png') 117 self.paramSkinMap = self.AddTex2D(self.lightmapScatterEffect, 'SkinMap') 118 self.paramExpandSource = self.AddTex2D(self.lightmapExpandEffect, 'Texture') 119 self.paramDiffuseScattermap = self.AddTex2D(self.lightmapApplicationEffectPreload, 'DiffuseScatterMap') 120 self.paramDiffusemap = self.AddTex2D(self.lightmapApplicationEffectPreload, 'DiffuseMap') 121 if self.precomputeBeckmann: 122 self.paramBeckmannLookup = self.AddTex2D(self.lightmapApplicationEffectPreload, 'BeckmannLookup') 123 if highQuality: 124 self.lightmapSize = (2048, 2048) 125 else: 126 self.lightmapSize = (512, 512) 127 lightmapFormat = [] 128 if useHDR: 129 lightmapFormat = [trinity.PIXEL_FORMAT.R16G16B16A16_FLOAT] 130 lightmapFormat.append(trinity.PIXEL_FORMAT.B8G8R8X8_UNORM) 131 lightmapFormat.append(trinity.PIXEL_FORMAT.B8G8R8A8_UNORM) 132 lightmapFormat.append(trinity.PIXEL_FORMAT.R8G8B8A8_UNORM) 133 self.lightmapRenderJob = None 134 setupOK = False 135 for format in lightmapFormat: 136 if self.CreateRenderTargets(format): 137 setupOK = True 138 break 139 140 if not setupOK: 141 self.lightmapSize = (self.lightmapSize[0] / 2, self.lightmapSize[1] / 2) 142 for format in lightmapFormat: 143 if self.CreateRenderTargets(format): 144 setupOK = True 145 break 146 147 if setupOK: 148 self.Print('Warning: needed to downsize the lightmap resolution') 149 else: 150 self.Print("Error: couldn't find any lightmap render format that works :(") 151 return 152 if self.precomputeBeckmann: 153 try: 154 self.beckmannLookup = self.CreateRenderTarget(256, 256, trinity.PIXEL_FORMAT.R8_UNORM) 155 self.RenderBeckmannLookup() 156 except Exception: 157 self.Print("[Skin] Error: can't create specular lookup table texture") 158 return 159 160 self.meshes = {} 161 SkinLightmapRenderer.instances.add(weakref.ref(self)) 162 163 @telemetry.ZONE_METHOD 164 def __del__(self): 165 newSet = set({}) 166 for instance in SkinLightmapRenderer.instances: 167 if instance(): 168 newSet.add(instance) 169 170 SkinLightmapRenderer.instances = newSet 171 self.StopRendering() 172 self.RestoreShaders() 173 174 @staticmethod 175 def PreloadEffect(path): 176 effect = trinity.Tr2Effect() 177 effect.effectFilePath = path 178 while not effect.effectResource.isPrepared: 179 pdCf.Yield() 180 181 effect.RebuildCachedData() 182 return effect 183 184 @telemetry.ZONE_METHOD 185 def CreateExtraMaps(self, effect): 186 try: 187 effect.StartUpdate() 188 res = self.FindResource(effect, 'DiffuseScatterMap') 189 if res is None: 190 res = self.AddTex2D(effect, 'DiffuseScatterMap') 191 res.SetResource(self.lightmap if self.useExpandOpaque else self.scatteredLightmap) 192 res = self.FindResource(effect, 'BeckmannLookup') 193 if res is None: 194 if self.precomputeBeckmann: 195 res = self.AddTex2D(effect, 'BeckmannLookup') 196 else: 197 res = self.AddTex2D(effect, 'BeckmannLookup', 'res:/Texture/Global/beckmannSpecular.dds') 198 if self.precomputeBeckmann: 199 res.SetResource(self.beckmannLookup) 200 finally: 201 effect.EndUpdate() 202 203 @staticmethod 204 def FindResource(effect, name): 205 for r in effect.resources: 206 if r.name == name: 207 return r 208 209 @staticmethod 210 def DuplicateResource(targetEffect, sourceEffect, name): 211 p = trinity.TriTextureParameter() 212 p.name = name 213 p.SetResource(SkinLightmapRenderer.FindResource(sourceEffect, name).resource) 214 targetEffect.resources.append(p) 215 216 @staticmethod 217 def DuplicateEffect(fx, newPath, dupResources = True): 218 newEffect = trinity.Tr2Effect() 219 newEffect.effectFilePath = newPath 220 newEffect.parameters.extend(fx.parameters) 221 newEffect.name = fx.name 222 if dupResources: 223 for r in fx.resources: 224 SkinLightmapRenderer.DuplicateResource(newEffect, fx, r.name) 225 226 newEffect.PopulateParameters() 227 newEffect.RebuildCachedData() 228 return newEffect 229 230 @telemetry.ZONE_METHOD 231 def AddMesh(self, mesh): 232 if mesh is None or self.lightmap is None: 233 return 234 235 def SetupSkinMap(): 236 for a in itertools.chain(mesh.opaqueAreas, mesh.decalAreas): 237 if a.effect is not None and a.effect.resources is not None: 238 for e in a.effect.resources: 239 if e.name == 'SkinMap': 240 self.skinMapPath = e.resourcePath 241 self.paramSkinMap.resourcePath = self.skinMapPath 242 return 243 244 if self.skinMapPath is None: 245 SetupSkinMap() 246 m = self.Mesh() 247 if not m.ExtractOrigEffect(mesh): 248 return 249 for areaRef, fx in m.origEffect.iteritems(): 250 if areaRef.object is None: 251 continue 252 if pdCcf.IsBeard(areaRef.object): 253 pdCcf.AddWeakBlue(m, 'lightmapRenderEffect', areaRef.object, None) 254 pdCcf.AddWeakBlue(m, 'lightmapApplyEffect', areaRef.object, fx) 255 pdCcf.AddWeakBlue(m, 'stretchmapRenderEffect', areaRef.object, None) 256 continue 257 wasDouble = 'double' in fx.effectFilePath.lower() 258 singleApply = self.LIGHTMAP_APPLICATION_EFFECT 259 doubleApply = self.LIGHTMAP_APPLICATION_DOUBLE_EFFECT 260 lightmapRenderEffect = SkinLightmapRenderer.DuplicateEffect(fx, self.LIGHTMAP_RENDERER_DOUBLE_EFFECT if wasDouble else self.LIGHTMAP_RENDERER_EFFECT) 261 lightmapApplyEffect = SkinLightmapRenderer.DuplicateEffect(fx, doubleApply if wasDouble else singleApply) 262 pdCcf.AddWeakBlue(m, 'lightmapRenderEffect', areaRef.object, lightmapRenderEffect) 263 pdCcf.AddWeakBlue(m, 'lightmapApplyEffect', areaRef.object, lightmapApplyEffect) 264 stretchmapRenderEffect = trinity.Tr2Effect() 265 stretchmapRenderEffect.effectFilePath = self.STRETCHMAP_RENDERER_EFFECT 266 stretchmapRenderEffect.parameters.extend(fx.parameters) 267 pdCcf.AddWeakBlue(m, 'stretchmapRenderEffect', areaRef.object, stretchmapRenderEffect) 268 m.liveParameters.append(filter(lambda r: r[0].name.startswith('WrinkleNormalStrength') or r[0].name.startswith('spotLight'), zip(fx.parameters, lightmapRenderEffect.parameters, lightmapApplyEffect.parameters))) 269 self.CreateExtraMaps(lightmapApplyEffect) 270 stretchmapRenderEffect.PopulateParameters() 271 stretchmapRenderEffect.RebuildCachedData() 272 lightmapApplyEffect.RebuildCachedData() 273 if False: 274 self.DebugPrint('lightmapRenderEffect resources:') 275 for p in lightmapRenderEffect.resources: 276 self.DebugPrint(p.name) 277 278 self.DebugPrint('lightmapApplyEffect resources:') 279 for p in lightmapApplyEffect.resources: 280 self.DebugPrint(p.name) 281 282 pdCcf.AddWeakBlue(self, 'meshes', mesh, m) 283 284 @staticmethod 285 def DoChangeEffect(attrName, meshes): 286 for meshRef, meshData in meshes.iteritems(): 287 mesh = meshRef.object 288 count = 0 289 dictionary = getattr(meshData, attrName) 290 for areaRef, effect in dictionary.iteritems(): 291 if areaRef.object is not None: 292 areaRef.object.effect = effect 293 294 def ChangeEffect(self, attrName, meshes = None): 295 if meshes is None: 296 meshes = self.meshes 297 SkinLightmapRenderer.DoChangeEffect(attrName, meshes) 298 299 @staticmethod 300 def DoRestoreShaders(meshes): 301 for meshRef, meshData in meshes.iteritems(): 302 mesh = meshRef.object 303 for areaRef, effect in meshData.origEffect.iteritems(): 304 if areaRef.object: 305 areaRef.object.effect = effect 306 307 @telemetry.ZONE_METHOD 308 def RestoreShaders(self, meshes = None): 309 if meshes is None: 310 meshes = self.meshes 311 SkinLightmapRenderer.DoRestoreShaders(meshes) 312 313 @staticmethod 314 def IsScattering(mesh): 315 if mesh.name.startswith('head'): 316 for a in mesh.opaqueAreas: 317 if a.effect is not None: 318 name = a.effect.name.lower() 319 if name.startswith('c_skin') and 'tearduct' not in name: 320 return True 321 322 return False 323 324 @telemetry.ZONE_METHOD 325 def BindLightmapShader(self, mesh): 326 if SkinLightmapRenderer.IsScattering(mesh): 327 self.AddMesh(mesh) 328 return True 329 return False 330 331 @telemetry.ZONE_METHOD 332 def SetSkinnedObject(self, skinnedObject): 333 if self.skinnedObject != skinnedObject or self.refreshMeshes: 334 self.skinnedObject = skinnedObject 335 self.meshes = {} 336 self.refreshMeshes = False 337 if skinnedObject is None or skinnedObject.visualModel is None: 338 return 339 haveNewMeshes = False 340 for mesh in skinnedObject.visualModel.meshes: 341 for meshRef in self.meshes: 342 if meshRef.object == mesh: 343 break 344 else: 345 haveNewMeshes = self.BindLightmapShader(mesh) or haveNewMeshes 346 347 scene = SkinLightmapRenderer.Scene() 348 for each in scene.dynamics: 349 each.display = each == skinnedObject 350 351 if haveNewMeshes: 352 self.RenderStretchmap() 353 354 @telemetry.ZONE_METHOD 355 def Refresh(self, immediateUpdate = False): 356 self.refreshMeshes = True 357 if immediateUpdate: 358 self.SetSkinnedObject(self.skinnedObject) 359 360 @staticmethod 361 def DoCopyMeshesToVisual(skinnedObject, meshList): 362 if skinnedObject is None or skinnedObject.visualModel is None: 363 return 364 skinnedObject.visualModel.meshes.removeAt(-1) 365 for mesh in meshList: 366 skinnedObject.visualModel.meshes.append(mesh) 367 368 @telemetry.ZONE_METHOD 369 def CopyMeshesToVisual(self, meshList): 370 SkinLightmapRenderer.DoCopyMeshesToVisual(self.skinnedObject, meshList) 371 372 @telemetry.ZONE_METHOD 373 def OnBeforeUnwrap(self): 374 self.ChangeEffect('lightmapRenderEffect') 375 scene = SkinLightmapRenderer.Scene() 376 if hasattr(scene, 'updateShadowCubeMap'): 377 scene.updateShadowCubeMap = False 378 if self.skinnedObject is not None and self.skinnedObject.visualModel is not None: 379 self.savedMeshes = self.skinnedObject.visualModel.meshes[:] 380 filteredMeshes = [ ref.object for ref in self.meshes.iterkeys() if ref.object is not None ] 381 self.CopyMeshesToVisual(filteredMeshes) 382 for meshData in self.meshes.itervalues(): 383 for list in meshData.liveParameters: 384 for params in list: 385 params[1].value = params[0].value 386 params[2].value = params[0].value 387 388 trinity.settings.SetValue('apexVisualizeOnly', True) 389 390 @telemetry.ZONE_METHOD 391 def OnAfterUnwrap(self): 392 scene = SkinLightmapRenderer.Scene() 393 if hasattr(scene, 'updateShadowCubeMap'): 394 scene.updateShadowCubeMap = True 395 if hasattr(self, 'savedMeshes'): 396 self.CopyMeshesToVisual(self.savedMeshes) 397 del self.savedMeshes 398 for each in scene.dynamics: 399 each.display = True 400 401 trinity.settings.SetValue('apexVisualizeOnly', False) 402 403 @telemetry.ZONE_METHOD 404 def CreateRJ(self, target, name, depthClear = 0.0, setDepthStencil = True, clearColor = (0.125, 0.125, 0.125, 1.0), isRT = False): 405 rj = trinity.CreateRenderJob(name) 406 rj.PushRenderTarget(target.wrappedRenderTarget).name = name 407 if setDepthStencil: 408 rj.PushDepthStencil(self.depth) 409 rj.Clear(clearColor, depthClear) 410 rj.SetStdRndStates(trinity.RM_FULLSCREEN) 411 vp = trinity.TriViewport() 412 vp.x = 0 413 vp.y = 0 414 if False: 415 rdesc = target.GetDesc() 416 vp.width = rdesc['Width'] 417 vp.height = rdesc['Height'] 418 else: 419 vp.width = target.width 420 vp.height = target.height 421 rj.SetViewport(vp) 422 return rj 423 424 @telemetry.ZONE_METHOD 425 def RenderBeckmannLookup(self): 426 rj = self.CreateRJ(self.beckmannLookup, 'Beckmann precalc') 427 rj.SetDepthStencil(None) 428 rj.RenderEffect(self.beckmannLookupEffect) 429 rj.PopRenderTarget() 430 rj.PopDepthStencil() 431 rj.ScheduleOnce() 432 433 @staticmethod 434 def FuncWrapper(weakSelf, func): 435 if weakSelf(): 436 func(weakSelf()) 437 438 @telemetry.ZONE_METHOD 439 def AddCallback(self, func, name, rj = None): 440 cb = trinity.TriStepPythonCB() 441 weakSelf = weakref.ref(self) 442 cb.SetCallback(lambda : SkinLightmapRenderer.FuncWrapper(weakSelf, func)) 443 cb.name = name 444 rj = rj if rj is not None else self.lightmapRenderJob 445 rj.steps.append(cb) 446 447 @telemetry.ZONE_METHOD 448 def RenderStretchmap(self): 449 if SkinLightmapRenderer.Scene() is None: 450 return 451 rj = self.CreateRJ(self.stretchmap, 'Stretchmap precalc', depthClear=None, setDepthStencil=False) 452 rj.PushDepthStencil(None) 453 self.AddCallback(SkinLightmapRenderer.OnBeforeUnwrap, 'onBeforeUnwrap', rj) 454 self.AddCallback(lambda weakSelf: weakSelf.ChangeEffect('stretchmapRenderEffect'), 'change to stretch effect', rj) 455 rj.Update(SkinLightmapRenderer.Scene()) 456 rj.RenderScene(SkinLightmapRenderer.Scene()) 457 self.AddCallback(SkinLightmapRenderer.OnAfterUnwrap, 'onAfterUnwrap', rj) 458 self.AddCallback(SkinLightmapRenderer.RestoreShaders, 'restoreShaders', rj) 459 rj.PopDepthStencil() 460 rj.PopRenderTarget() 461 rj.ScheduleOnce() 462 463 @telemetry.ZONE_METHOD 464 def OnBeforeBlur(self): 465 rj = self.lightmapRenderJob 466 self.paramLightmap.SetResource(self.lightmap) 467 self.paramStretchmap.SetResource(self.stretchmap) 468 469 @telemetry.ZONE_METHOD 470 def OnBeforeExpand(self): 471 rj = self.lightmapRenderJob 472 self.paramExpandSource.SetResource(self.scatteredLightmap) 473 474 @telemetry.ZONE_METHOD 475 def OnAfterExpand(self): 476 rj = self.lightmapRenderJob 477 self.ChangeEffect('lightmapApplyEffect') 478 479 @telemetry.ZONE_METHOD 480 def SetViewport(self, rj, width, height): 481 vp = trinity.TriViewport() 482 vp.x = 0 483 vp.y = 0 484 vp.width = width 485 vp.height = height 486 rj.SetViewport(vp) 487 488 @telemetry.ZONE_METHOD 489 def RenderLightmap(self): 490 rj = self.CreateRJ(self.lightmap, 'Lightmap rendering', depthClear=None, setDepthStencil=False, clearColor=(0, 0, 0, 0)) 491 self.lightmapRenderJob = rj 492 self.AddCallback(SkinLightmapRenderer.OnBeforeUnwrap, 'onBeforeUnwrap') 493 doHighZOptimization = False 494 if not doHighZOptimization: 495 rj.PushDepthStencil(None).name = 'Depthbuffer = None' 496 rj.RenderScene(SkinLightmapRenderer.Scene()).name = 'Unwrap light pass' 497 self.AddCallback(SkinLightmapRenderer.OnAfterUnwrap, 'onAfterUnwrap') 498 rj.SetRenderTarget(self.scatteredLightmap.wrappedRenderTarget).name = 'Set Scattermap RT' 499 self.AddCallback(SkinLightmapRenderer.OnBeforeBlur, 'onBeforeBlur') 500 rj.SetStdRndStates(trinity.RM_FULLSCREEN) 501 rj.RenderEffect(self.lightmapScatterEffect).name = 'Light blur pass' 502 if self.useExpandOpaque: 503 rj.SetRenderTarget(self.lightmap.wrappedRenderTarget).name = 'Set Lightmap RT for expand' 504 self.AddCallback(SkinLightmapRenderer.OnBeforeExpand, 'onBeforeExpand') 505 rj.RenderEffect(self.lightmapExpandEffect).name = 'Expand lightmap' 506 self.AddCallback(SkinLightmapRenderer.OnAfterExpand, 'onAfterExpand') 507 rj.PopRenderTarget().name = 'PopRT - main scene rendering' 508 if not doHighZOptimization: 509 rj.PopDepthStencil() 510 if SkinLightmapRenderer.renderJob is not None and SkinLightmapRenderer.renderJob.object is not None: 511 step = trinity.TriStepRunJob() 512 step.job = rj 513 SkinLightmapRenderer.renderJob.object.steps.append(step) 514 else: 515 jobs = trinity.renderJobs.recurring 516 for job in jobs: 517 if 'paperdoll' in job.name.lower(): 518 step = trinity.TriStepRunJob(rj) 519 step.name = rj.name 520 job.steps.insert(len(job.steps) - 1, step) 521 break 522 else: 523 rj.ScheduleRecurring() 524 525 @staticmethod 526 def SaveTarget(target, path, isRT = False): 527 if type(target) == trinity.Tr2RenderTarget: 528 trinity.Tr2HostBitmap(target).Save(path) 529 else: 530 target.Save(path) 531 532 def IsRendering(self): 533 return self.lightmapRenderJob is not None 534 535 @telemetry.ZONE_METHOD 536 def StartRendering(self): 537 if self.lightmap is None: 538 return 539 if self.lightmapRenderJob is not None: 540 return 541 self.RenderLightmap() 542 543 @telemetry.ZONE_METHOD 544 def StopRendering(self): 545 if self.lightmapRenderJob is None: 546 return 547 if SkinLightmapRenderer.renderJob is not None and SkinLightmapRenderer.renderJob.object is not None: 548 for step in SkinLightmapRenderer.renderJob.object.steps: 549 if step.job == self.lightmapRenderJob: 550 SkinLightmapRenderer.renderJob.object.steps.remove(step) 551 break 552 553 else: 554 self.lightmapRenderJob.UnscheduleRecurring() 555 self.lightmapRenderJob = None 556 557 def CreateScatterStep(renderJob, scene, append = True): 558 step = trinity.TriStepRunJob() 559 step.name = 'Subsurface scattering' 560 step.job = trinity.CreateRenderJob('Render scattering') 561 if append: 562 renderJob.steps.append(step) 563 SkinLightmapRenderer.renderJob = blue.BluePythonWeakRef(step.job) 564 SkinLightmapRenderer.scene = blue.BluePythonWeakRef(scene) 565 return step