Skip to content

Instantly share code, notes, and snippets.

@ScatteredRay
Created November 4, 2024 00:02
Show Gist options
  • Save ScatteredRay/5c189bc8185cd1a006dc70b17c0e8445 to your computer and use it in GitHub Desktop.
Save ScatteredRay/5c189bc8185cd1a006dc70b17c0e8445 to your computer and use it in GitHub Desktop.
TTRender Renderdoc Extract Buffers
import os
import fnmatch
import OpenEXR
import Imath
def WriteEXR(file, header, channels):
f = OpenEXR.OutputFile(file, header)
f.writePixels(channels)
def CombineEXR(outFile, inLayers):
# Just use the first header for now.
header = OpenEXR.InputFile(inLayers[list(inLayers)[0]]).header()
header['channels'] = dict()
channels = dict()
for layer in inLayers:
file = inLayers[layer]
f = OpenEXR.InputFile(file)
inHeader = f.header()
channelList = inHeader['channels'].keys()
newChannelList = [layer + "." + c for c in channelList]
for c, n in zip(channelList, newChannelList):
header['channels'][n] = inHeader['channels'][c]
channels.update(dict(zip(newChannelList, f.channels(channelList))))
WriteEXR(outFile, header, channels)
def ProcessDirectoryForLayers(bufferdir):
bufferFiles = dict()
for file in os.listdir(bufferdir):
if fnmatch.fnmatch(file, '*.exr'):
filename = os.path.join(bufferdir, file)
bufname = os.path.splitext(os.path.basename(file))[0]
bufferFiles[bufname] = filename
return dict(bufferFiles)
def MakeEXRFromLayers(outFile, bufferDir):
layers = ProcessDirectoryForLayers(bufferDir)
CombineEXR(outFile, layers)
MakeEXRFromLayers("~\\RenderData\\shot1\\buffers\\shot1.exr", "~\\RenderData\\shot1\\buffers\\")
import os
import sys
savePath = "~\\RenderData\\shot1\\buffers"
shadowSavePath = savePath + "\\ShadowDepth"
if not os.path.exists(shadowSavePath):
os.makedirs(shadowSavePath)
if 'renderdoc' not in sys.modules:
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "renderdoc\\x64\\Release")))
import renderdoc
rd = renderdoc
ctx = pyrenderdoc
def match(draws, path):
for d in draws:
if d.name == path:
return d
ret = match(d.children, path)
if ret != None:
return ret
return None
def getDrawcallEnd(drawcall):
if len(drawcall.children) == 0:
return drawcall
return getDrawcallEnd(drawcall.children[len(drawcall.children) - 1])
def saveTargetTexture(controller, resourceId, filename):
textureSave = rd.TextureSave()
if(resourceId == rd.ResourceId.Null()):
return
textureSave.resourceId = resourceId
textureSave.mip = 0
textureSave.slice.sliceIndex = 0
textureSave.alpha = rd.AlphaMapping.Preserve
textureSave.destType = rd.FileType.EXR
controller.SaveTexture(textureSave, filename + ".exr")
textureSave.destType = rd.FileType.PNG
controller.SaveTexture(textureSave, filename + ".png")
def savePassTargets(controller, draw):
controller.SetFrameEvent(draw.eventId, True)
for output in draw.outputs:
filename = os.path.join(savePath, ctx.GetResourceName(output))
saveTargetTexture(controller, output, filename)
def savePassDepthTarget(controller, draw):
controller.SetFrameEvent(draw.eventId, True)
output = draw.depthOut
filename = os.path.join(savePath, ctx.GetResourceName(output))
saveTargetTexture(controller, output, filename)
def saveNamedPassTarget(controller, draw, outputName, saveName):
controller.SetFrameEvent(draw.eventId, True)
for output in draw.outputs:
if(ctx.GetResourceName(output) == outputName):
filename = os.path.join(savePath, saveName)
saveTargetTexture(controller, output, filename)
def saveNamedPassInput(controller, draw, inputName, saveName):
controller.SetFrameEvent(draw.eventId, True)
pipelineState = controller.GetPipelineState()
resources = pipelineState.GetReadOnlyResources(rd.ShaderStage.Pixel)
for bra in resources:
for resource in bra.resources:
input = resource.resourceId
if(ctx.GetResourceName(input) == inputName):
filename = os.path.join(savePath, saveName)
saveTargetTexture(controller, input, filename)
def extractDepthBuffer(controller):
draws = controller.GetDrawcalls()
savePassDepthTarget(controller, getDrawcallEnd(match(draws, "ResolveSceneDepthTexture")))
def extractGBuffer(controller):
draws = controller.GetDrawcalls()
basePass = match(draws, "BasePass")
print(basePass.name)
basePassEnd = getDrawcallEnd(basePass)
print(basePassEnd.name)
savePassTargets(controller, basePassEnd)
savePassTargets(controller, getDrawcallEnd(match(draws, "LightCompositionTasks_PreLighting")))
def extractShadowBuffers(controller):
draws = controller.GetDrawcalls()
shadowedLights = match(draws, "ShadowedLights")
for d in shadowedLights.children:
lightName = d.name.split('.')[-1]
print(lightName)
shadowProjection = match(d.children, "ShadowProjectionOnOpaque")
if shadowProjection != None:
shadowDraw = getDrawcallEnd(shadowProjection)
saveNamedPassInput(controller, shadowDraw, "CachedShadowDepthMap", "ShadowDepth\\Lights." + lightName + ".ShadowDepth")
saveNamedPassTarget(controller, shadowDraw, "ScreenShadowMaskTexture", "Lights." + lightName + ".ShadowMask")
def extract(controller):
extractDepthBuffer(controller)
extractGBuffer(controller)
extractShadowBuffers(controller)
if 'pyrenderdoc' in globals():
pyrenderdoc.Replay().BlockInvoke(extract)
else:
rd.InitialiseReplay(rd.GlobalEnvironment(), [])
cap,controller = loadCapture(sys.argv[1])
extract(controller)
controller.Shutdown()
cap.Shutdown()
rd.ShutdownReplay()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment