北京网站建设设计,wordpress 禁止,韶关网站建设墨子,简单的企业网页模板故事背景#xff1a;美术那里有需求#xff0c;需要别人游戏的模型#xff0c;来借鉴一下#xff0c;问我是否有工具可以一键导出模型。我就搜索了一下RenderDoc批量导出图片#xff0c;结果搜到了用C改RenderDoc源码的文章。让RenderDoc批量导出纹理_专栏-CSDN博客blog…故事背景美术那里有需求需要别人游戏的模型来借鉴一下问我是否有工具可以一键导出模型。我就搜索了一下RenderDoc批量导出图片结果搜到了用C改RenderDoc源码的文章。让RenderDoc批量导出纹理_专栏-CSDN博客blog.csdn.net然后看了一下官网看到了可以用python写工具的(因为不会C而且好像很麻烦的样子),我就试着用python来写RenderDoc的工具(其实我也不会python只是这种语言应该好学)。使用步骤1.在RenderDoc里面截一张图。2.运行RenderDoc的python shell。3.导出图片与csv(因为只能导出csv导不出模型我会在unity里把他转为模型)至于RenderDoc如何写python只要看下官网就可以了这里贴出地址。Python API - RenderDoc documentationrenderdoc.org原理分析主要还是python部分的原理怎么调用RenderDoc接口官网虽然有解析和例子但是并不完全导出图片的那个例子居然是导出output的图片。就是fragment Shader return出去的那个完全没找到input的图片我都是自己试出来的。其实导出顶点CSV跟导出图片都用到个这个函数controller.GetPipelineState()从这个pipeline的state里面获取就是对应RenderDoc里面的这个面板然后用这个函数state.GetReadOnlyResources(renderdoc.ShaderStage.Fragment)这个里面就有所有的图片的resourceId,可以写个循环保存所有的图片。texsave rd.TextureSave()texsave.resourceId resourceIdif texsave.resourceId rd.ResourceId.Null():return Falsefilename str(int(texsave.resourceId))texsave.mip 0texsave.slice.sliceIndex 0texsave.alpha rd.AlphaMapping.Preservetexsave.destType rd.FileType.PNGif not os.path.exists({0}/{1}.format(folderName,eventId)):os.makedirs({0}/{1}.format(folderName,eventId))outTexPath {0}/{1}/{2}.png.format(folderName,eventId,filename)controller.SaveTexture(texsave, outTexPath)同样的vertex也是这么获取获取vertex index的resourceId,跟vertex自身的resourceId。ib.state.GetIBuffer()vbs.state.GetVBuffers()....something...meshInput.indexResourceId ib.resourceId # vertex index的resourceIdmeshInput.vertexResourceId vbs[attr.vertexBuffer].resourceId # vertex自身的resourceId然后根据resourceId去BufferData里面去得到vertexcontroller.GetBufferData(meshInput.indexResourceId, meshInput.indexByteOffset, 0)源码只给出python源码C#源码可以参考这里RenderDocMeshParserForUnitygithub.comimport sysimport csvfolderName C:/Users/Administrator/Desktop/capMesh1startIndex 475endIndex 759isPrint False# Import renderdoc if not already imported (e.g. in the UI)if renderdoc not in sys.modules and _renderdoc not in sys.modules:import renderdoc# Alias renderdoc for legibilityrd renderdoc# Well need the struct data to read out of bytes objectsimport structimport os# We base our data on a MeshFormat, but we add some propertiesclass MeshData(rd.MeshFormat):indexOffset 0name def pySaveTexture(resourceId,eventId,controller):texsave rd.TextureSave()texsave.resourceId resourceIdif texsave.resourceId rd.ResourceId.Null():return Falsefilename str(int(texsave.resourceId))# texsave.alpha rd.AlphaMapping.BlendToCheckerboard# Most formats can only display a single image per file, so we select the# first mip and first slicetexsave.mip 0texsave.slice.sliceIndex 0texsave.alpha rd.AlphaMapping.Preservetexsave.destType rd.FileType.PNGif not os.path.exists({0}/{1}.format(folderName,eventId)):os.makedirs({0}/{1}.format(folderName,eventId))outTexPath {0}/{1}/{2}.png.format(folderName,eventId,filename)controller.SaveTexture(texsave, outTexPath)print(保存图片{0}.format(outTexPath))return Truedef findIndexDrawLoop(d,index):ret Noneif d.eventId index:return dfor c in d.children:ret findIndexDrawLoop(c,index)if ret:return retreturn ret# Recursively search for the drawcall with the most verticesdef findIndexDraw(index,controller):ret Nonefor d in controller.GetDrawcalls():if d.eventId index:ret dreturn retfor c in d.children:ret findIndexDrawLoop(c,index)if ret:return retreturn ret# Unpack a tuple of the given format, from the datadef unpackData(fmt, data):if isPrint:print(888)# We dont handle special formats - typically bit-packed such as 10:10:10:2# raise RuntimeError(Packed formats are not supported!)formatChars {}# 012345678formatChars[rd.CompType.UInt] xBHxIxxxLformatChars[rd.CompType.SInt] xbhxixxxlformatChars[rd.CompType.Float] xxexfxxxd # only 2, 4 and 8 are valid# These types have identical decodes, but we might post-process themformatChars[rd.CompType.UNorm] formatChars[rd.CompType.UInt]formatChars[rd.CompType.UScaled] formatChars[rd.CompType.UInt]formatChars[rd.CompType.SNorm] formatChars[rd.CompType.SInt]formatChars[rd.CompType.SScaled] formatChars[rd.CompType.SInt]# We need to fetch compCount componentsvertexFormat str(fmt.compCount) formatChars[fmt.compType][fmt.compByteWidth]# Unpack the datavalue struct.unpack_from(vertexFormat, data, 0)# If the format needs post-processing such as normalisation, do that nowif fmt.compType rd.CompType.UNorm:divisor float((2 ** (fmt.compByteWidth * 8)) - 1)value tuple(float(i) / divisor for i in value)elif fmt.compType rd.CompType.SNorm:maxNeg -float(2 ** (fmt.compByteWidth * 8)) / 2divisor float(-(maxNeg-1))value tuple((float(i) if (i maxNeg) else (float(i) / divisor)) for i in value)# If the format is BGRA, swap the two componentsif fmt.BGRAOrder():value tuple(value[i] for i in [2, 1, 0, 3])return value# Get a list of MeshData objects describing the vertex inputs at this drawdef getMeshInputs(controller, draw):state controller.GetPipelineState()# Get the index vertex buffers, and fixed vertex inputsib state.GetIBuffer()vbs state.GetVBuffers()attrs state.GetVertexInputs()sampleList state.GetReadOnlyResources(renderdoc.ShaderStage.Fragment)for sample in sampleList:for res in sample.resources:print(res.resourceId)if not pySaveTexture(res.resourceId,draw.eventId,controller):breakmeshInputs []# for i in ib:# if isPri:nt# print(i)# for v in vbs:# print(v)#for attr in attrs:# print(attr.name)for attr in attrs:# We dont handle instance attributesif attr.perInstance:raise RuntimeError(Instanced properties are not supported!)meshInput MeshData()meshInput.indexResourceId ib.resourceId # 2646meshInput.indexByteOffset ib.byteOffset # 0meshInput.indexByteStride draw.indexByteWidth # 0meshInput.baseVertex draw.baseVertex # 0meshInput.indexOffset draw.indexOffset # 0meshInput.numIndices draw.numIndices #顶点总数 18# If the draw doesnt use an index buffer, dont use it even if boundif not (draw.flags rd.DrawFlags.Indexed):meshInput.indexResourceId rd.ResourceId.Null()# The total offset is the attribute offset from the base of the vertexmeshInput.vertexByteOffset attr.byteOffset vbs[attr.vertexBuffer].byteOffset draw.vertexOffset * vbs[attr.vertexBuffer].byteStride # 0meshInput.format attr.formatmeshInput.vertexResourceId vbs[attr.vertexBuffer].resourceId # 2645meshInput.vertexByteStride vbs[attr.vertexBuffer].byteStride # 56meshInput.name attr.namemeshInputs.append(meshInput)return meshInputsdef getIndices(controller, mesh):# Get the character for the width of indexindexFormat Bif mesh.indexByteStride 2:indexFormat Helif mesh.indexByteStride 4:indexFormat I# Duplicate the format by the number of indicesindexFormat str(mesh.numIndices) indexFormat# If we have an index bufferif mesh.indexResourceId ! rd.ResourceId.Null():# Fetch the dataibdata controller.GetBufferData(mesh.indexResourceId, mesh.indexByteOffset, 0)# Unpack all the indices, starting from the first index to fetchoffset mesh.indexOffset * mesh.indexByteStrideindices struct.unpack_from(indexFormat, ibdata, offset)# Apply the baseVertex offsetreturn [i mesh.baseVertex for i in indices]else:# With no index buffer, just generate a rangereturn tuple(range(mesh.numIndices))def printMeshData(controller, meshData,draw):if isPrint:print(4444)indices getIndices(controller, meshData[0])csvArray []fileheader []formatxyzw [.x,.y,.z,.w]if isPrint:print(Mesh configuration:)fileheader.append(VTX)fileheader.append(IDX)for attr in meshData:if not attr.format.Special():if isPrint:print(\t%s: % attr.name)if isPrint:print(\t\t- vertex: %s / %d stride % (attr.vertexResourceId, attr.vertexByteStride))if isPrint:print(\t\t- format: %s x %s %d % (attr.format.compType, attr.format.compCount, attr.vertexByteOffset))headFormat {0}{1}for i in range(0,attr.format.compCount):newStr headFormat.format(attr.name,formatxyzw[i])fileheader.append(newStr)# Well decode the first three indices making up a trianglecsvArray.append(fileheader)# 写入CSVif not os.path.exists({0}/{1}.format(folderName,draw.eventId)):os.makedirs({0}/{1}.format(folderName,draw.eventId))outPath {0}/{1}/model.csv.format(folderName,draw.eventId)csvFile open(outPath, w,newline)writer csv.writer(csvFile)# ##########################保存图片#############################################for inputIter in draw.outputs:if not pySaveTexture(inputIter,draw.eventId,controller):break# ##########################保存图片#############################################i 0for idx in indices:# for i in range(0, 3):# idx indices[i]# 每个顶点的信息indiceArray []if isPrint:print(Vertex %d is index %d: % (i, idx))indiceArray.append(i)indiceArray.append(idx)for attr in meshData:if not attr.format.Special():# This is the data were reading from. This would be good to cache instead of# re-fetching for every attribute for every indexoffset attr.vertexByteOffset attr.vertexByteStride * idxdata controller.GetBufferData(attr.vertexResourceId, offset, 0)# Get the value from the datavalue unpackData(attr.format, data)for j in range(0,attr.format.compCount):indiceArray.append(value[j])# if isPri:ntWe dont go into the details of semantic matching here, just# print bothif isPrint:print(\tAttribute %s: %s % (attr.name, value))csvArray.append(indiceArray)i i 1writer.writerows(csvArray)csvFile.close()print(写入{0}成功.format(outPath))def sampleCodePreDraw(controller,draw):if draw.eventId startIndex and draw.eventId endIndex:# Move to that drawcontroller.SetFrameEvent(draw.eventId, True)if isPrint:print(Decoding mesh inputs at %d: %s\n\n % (draw.eventId, draw.name))# # Calculate the mesh input configurationmeshInputs getMeshInputs(controller, draw)# if isPri:nt# Fetch and# print the data from the mesh inputsprintMeshData(controller, meshInputs,draw)def sampleCodeRecursion(controller,draw):sampleCodePreDraw(controller,draw)for d in draw.children:sampleCodeRecursion(controller,d)def sampleCode(controller):for draw in controller.GetDrawcalls():sampleCodeRecursion(controller,draw)def loadCapture(filename):if isPrint:print(222)# Open a capture file handlecap rd.OpenCaptureFile()# Open a particular file - see also OpenBuffer to load from memorystatus cap.OpenFile(filename, , None)# Make sure the file opened successfullyif status ! rd.ReplayStatus.Succeeded:raise RuntimeError(Couldnt open file: str(status))# Make sure we can replayif not cap.LocalReplaySupport():raise RuntimeError(Capture cannot be replayed)# Initialise the replaystatus,controller cap.OpenCapture(rd.ReplayOptions(), None)if status ! rd.ReplayStatus.Succeeded:raise RuntimeError(Couldnt initialise replay: str(status))return (cap, controller)if pyrenderdoc in globals():if isPrint:print(111)pyrenderdoc.Replay().BlockInvoke(sampleCode)else:if isPrint:print(aaaa)rd.InitialiseReplay(rd.GlobalEnvironment(), [])if len(sys.argv) 1:if isPrint:print(Usage: python3 {} filename.rdc.format(sys.argv[0]))sys.exit(0)cap,controller loadCapture(sys.argv[1])sampleCode(controller)controller.Shutdown()cap.Shutdown()rd.ShutdownReplay()print(导出完毕)优化其实还可以做优化这样导csv文件实在太慢了我想到两个方法优化。1.用C直接导出csv这样是最快的。2.可以只顺序的导出vertex因为现在是导了很多重复的vertex就是把index跟vertex分开导在c#部分把他转成三角形可以使得程序更快大概能快两到三倍的样子。