3D模型顶点颜色转纹理【SIMPLYGON】

在这篇博客中,我们将了解如何将顶点颜色烘焙到纹理中。 其用例是某些照片扫描资产,其中颜色数据保存到顶点颜色中。 我们将了解如何使用 remesher 和聚合器管道来完成此操作。 我们还将介绍如何为顶点颜色材质创建着色网络以及如何从模型后处理中删除顶点颜色。

这个博客或多或少与我们的将纹理烘焙为顶点颜色博客相反,在那篇博客中我们采取了相反的方式; 纹理到顶点颜色。

此示例将使用 Blender 中的 Simplygon 集成,但相同的概念可以应用于 Simplygon API 的所有其他集成。

NSDT在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器

1、需要解决的问题

我们要优化的资源是没有 UV 的照片扫描资源,其中颜色数据保存为顶点颜色。 我们想要的输出是一个模型,其中颜色数据保存在纹理中。 输入资源非常密集,因此我们希望使其更加轻量级。

2、使用remesh解决方案

由于我们的原始模型具有非常密集的几何形状,因此我们可能也希望减少其多边形数量。 我们的remesh管道非常适合这项任务。

2.1 Blender导出

第一步是从 Blender 导出到 Simplygon。 为此,我们将场景导出为 glTF,然后使用场景导入器将其导入 Simplygon。

def export_selection(sg, file_path):"""Export the current selected objects into Simplygon."""bpy.ops.export_scene.gltf(filepath = file_path, use_selection=True)sceneImporter = sg.CreateSceneImporter()sceneImporter.SetImportFilePath(file_path)sceneImporter.Run()scene = sceneImporter.GetScene()return scene

2.2 设置顶点颜色着色网络

如果我们通过 UI 对资源执行颜色投射,我们将不会得到任何颜色输出。 原因是颜色存储在顶点颜色中而不是纹理中。 为了让颜色投射器理解我们想要使用顶点颜色作为输入,我们需要创建一个自定义着色网络。

首先,我们需要为基色添加材质通道。 在 Blender 中,这被称为 Basecolor。 然后我们可以创建一个顶点颜色节点并指定要使用的 VertexColorIndex。 在我们的例子中,我们只有一种顶点颜色,因此索引为 0。然后,我们将顶点颜色节点指定为材质颜色通道的着色网络。

def setup_vertex_color_material(sg, material, channel):"""Set material to use vertex color as color."""material.AddMaterialChannel(channel)shading_node = sg.CreateShadingVertexColorNode()shading_node.SetVertexColorIndex(vertex_color_index)material.SetShadingNetwork(channel, shading_node)

一旦我们有了创建顶点颜色材质的函数,我们就可以迭代场景材质表中的每种材质,并将其设置为使用我们的自定义顶点颜色着色网络。

def setup_vertex_color_materials(sg, scene):"""Set all materials in scene to vertex colored."""material_table = scene.GetMaterialTable()for i in range(0, material_table.GetMaterialsCount()):material = material_table.GetMaterial(i)setup_vertex_color_material(sg, material, color_channel)

2.3 创建remeshing管线

我们的remesh管道做了两件事; 创建一个水密的低多边形网格并将原始资源中的材料烘焙到其中。 这使得它非常适合我们的用例。 我们首先创建一个重新网格化管道,然后根据我们所需的模型输出质量设置 OnScreenSize。 值得一提的是,屏幕尺寸太大会导致缩放效果很差,在这种情况下,请查看我们的博客使用镶嵌属性加速重新网格化,了解如何加快速度。

映射图像负责将表面从原始模型转换为我们重新划分的模型。 我们需要创建一个来传输材质,因此需要将GenerateMappingImage 设置为True。 我们还可以使用TextureHeight和TextureWidth指定大小。

def create_pipline(sg): """Create remesing pipeline and color caster."""pipeline = sg.CreateRemeshingPipeline()settings = pipeline.GetRemeshingSettings()settings.SetOnScreenSize(resolution)mapping_image_settings = pipeline.GetMappingImageSettings()material_output_settings = mapping_image_settings.GetOutputMaterialSettings(0)material_output_settings.SetTextureHeight(texture_size)material_output_settings.SetTextureWidth(texture_size)mapping_image_settings.SetGenerateMappingImage(True)mapping_image_settings.SetTexCoordName("MaterialLOD")

为了能够烘焙颜色,我们在remesh管道中添加了一个调色器。 当我们运行管道时它会自动被转换。 我们需要指定的是要烘焙的 MaterialChannel,这应该与我们的顶点颜色材质输出 - 基色相同。

    caster = sg.CreateColorCaster()caster_settings = caster.GetColorCasterSettings()caster_settings.SetMaterialChannel( color_channel )pipeline.AddMaterialCaster( caster, 0 )return pipeline

2.4 导入Blender

为了将结果返回到 Blender,我们将使用场景导出器将优化后的场景导出为 gltf 文件。 然后我们可以导入到 Blender 中。

def import_results(sg, scene, file_path):"""Import the Simplygon scene into Blender."""scene_exporter = sg.CreateSceneExporter()scene_exporter.SetExportFilePath(file_path)scene_exporter.SetScene(scene)scene_exporter.Run()bpy.ops.import_scene.gltf(filepath=file_path)

2.5 整合在一起

一旦创建了所有辅助函数,我们就可以将它们放在一起。 首先,我们将从 Blender 中导出选定的网格,然后设置我们的自定义顶点颜色材质。 之后,我们创建一个remesh管道并运行它。 最后我们将结果导入到 Blender 中。

def process_selection(sg):"""Process selected mesh in Blender"""# Export scene from Blender and import it file_path = temp_path + filescene = export_selection(sg, file_path)# Setup vertex color shadersetup_vertex_color_materials(sg, scene)# Process scenepipeline = create_pipline(sg)pipeline.RunScene(scene, Simplygon.EPipelineRunMode_RunInThisProcess)# Import result into Blenderimport_results(sg, scene, file_path)

2.6 remesh结果

最终结果是一个低多边形模型,其中顶点颜色被烘焙到纹理中。 非常适合用于运行时可视化。

资产三角形
原始资产673152
优化资产988

所有顶点颜色现在都被烘焙到纹理中:

进一步改善我们的结果的一件事是添加一个法线脚轮,它可以将任何微小的几何细节转移到法线贴图中。

3、聚合解决方案

如果我们想保持几何体完整但只是烘焙 UV 贴图,我们可以使用聚合管道而不是重新划分网格。 代码的许多部分是相同的,因此我们将只讨论新的部分。

3.1 删除顶点颜色

由于我们的颜色数据现在驻留在纹理中,我们可以从场景中删除顶点颜色字段。 为此,我们首先通过创建包含所有 SceneMesh 节点的选择集来查找场景中的所有网格。 之后我们一一迭代它们。

def remove_vertex_weights(sg, scene, vertex_color_index):"""Remove all vertex colors of index from scene."""scene_meshes_selection_set_id = scene.SelectNodes("SceneMesh")scene_meshes_selection_set = scene.GetSelectionSetTable().GetSelectionSet(scene_meshes_selection_set_id)# Loop through all meshes in the scenefor node_id in range(scene_meshes_selection_set.GetItemCount()):

将节点安全投射到 SceneMesh 后,我们可以从中获取几何数据。 在这里我们可以操纵它,在我们的例子中,我们将通过调用RemoveColors来删除顶点颜色字段。 在我们的 Blender 资源中,这是顶点颜色索引 0。

        scene_mesh = Simplygon.spSceneMesh.SafeCast(scene.GetNodeByGUID( scene_meshes_selection_set.GetItem(node_id)))# Get geometry for meshgeometry = scene_mesh.GetGeometry()if not geometry: continuegeometry.RemoveColors(vertex_color_index)

如果你的顶点颜色仅用于指导 Simplygon 使用顶点权重,则上述函数对于清理优化后的资源非常有用。 优化后可以调用该函数。

3.2 创建聚合管道

由于我们希望保持网格完整,因此我们使用聚合管道来处理网格。 如上所述,我们需要创建一个映射图像,用于从顶点颜色传输到纹理。 将 TexCoordGeneratorType 设置为 ETexcoordGeneratorType_Parameterizer 后,我们使用 Simplygon 中的参数化器为我们的资源创建新的 UV 贴图。

def create_aggregaton_pipline(sg): """Create aggregation pipeline with color material caster"""aggregation_pipeline = sg.CreateAggregationPipeline()aggregator_settings = aggregation_pipeline.GetAggregationSettings()mapping_image_settings = aggregation_pipeline.GetMappingImageSettings()mapping_image_settings.SetGenerateMappingImage(True)material_settings = mapping_image_settings.GetOutputMaterialSettings(0)material_settings.SetTextureWidth(texture_size)material_settings.SetTextureHeight(texture_size)mapping_image_settings.SetTexCoordGeneratorType( Simplygon.ETexcoordGeneratorType_Parameterizer )

然后,我们以与重新网格化管道完全相同的方式添加色彩投射器。

    caster = sg.CreateColorCaster()caster_settings = caster.GetColorCasterSettings()caster_settings.SetMaterialChannel( color_channel )aggregation_pipeline.AddMaterialCaster( caster, 0 )return aggregation_pipeline

3.3 整合在一起

与remesh解决方案的唯一区别是我们在运行管道后调用 remove_vertex_weights

def process_selection(sg):"""Remove and bake decals on selected meshes."""# Export scene from Blender and import it file_path = temp_path + filescene = export_selection(sg, file_path)# Setup vertex color shadersetup_vertex_color_materials(sg, scene)# Aggregate optimized scenepipeline = create_aggregaton_pipline(sg)pipeline.RunScene(scene, Simplygon.EPipelineRunMode_RunInThisProcess)# Clean up vertex colorsremove_vertex_weights(sg, scene, vertex_color_index)# Import result into Blenderimport_results(sg, scene, file_path)

3.4 聚合结果

运行聚合脚本后的结果是网格保持完整的模型。

我们已经从中删除了顶点颜色字段,并将颜色保存在纹理中,并使用新烘焙的 UV 贴图来访问它。 图像的黑色部分是非常密集的 UV 图。

其用例可能相当狭窄,但我们希望将其包括在内,因为它还介绍了如何从网格优化后删除顶点颜色,这是一个可能有用的代码片段。

4、完整的代码

remesh方案:

# Copyright (c) Microsoft Corporation. 
# Licensed under the MIT license. import os
import bpy
import gcfrom simplygon10 import simplygon_loader
from simplygon10 import Simplygonfile = "scene.glb"
temp_path = "c:/tmp/"# Change parameters for quality
texture_size = 4096
resolution = 300# Blender specific settings
color_channel = "Basecolor"
vertex_color_index = 0def export_selection(sg, file_path):"""Export the current selected objects into Simplygon."""bpy.ops.export_scene.gltf(filepath = file_path, use_selection=True)sceneImporter = sg.CreateSceneImporter()sceneImporter.SetImportFilePath(file_path)sceneImporter.Run()scene = sceneImporter.GetScene()return scenedef import_results(sg, scene, file_path):"""Import the Simplygon scene into Blender."""scene_exporter = sg.CreateSceneExporter()scene_exporter.SetExportFilePath(file_path)scene_exporter.SetScene(scene)scene_exporter.Run()bpy.ops.import_scene.gltf(filepath=file_path)def create_pipline(sg): """Create remesing pipeline and color caster."""pipeline = sg.CreateRemeshingPipeline()settings = pipeline.GetRemeshingSettings()settings.SetOnScreenSize(resolution)mapping_image_settings = pipeline.GetMappingImageSettings()material_output_settings = mapping_image_settings.GetOutputMaterialSettings(0)material_output_settings.SetTextureHeight(texture_size)material_output_settings.SetTextureWidth(texture_size)mapping_image_settings.SetGenerateMappingImage(True)mapping_image_settings.SetTexCoordName("MaterialLOD")caster = sg.CreateColorCaster()caster_settings = caster.GetColorCasterSettings()caster_settings.SetMaterialChannel( color_channel )pipeline.AddMaterialCaster( caster, 0 )return pipelinedef setup_vertex_color_materials(sg, scene):"""Set all materials in scene to vertex colored."""material_table = scene.GetMaterialTable()for i in range(0, material_table.GetMaterialsCount()):material = material_table.GetMaterial(i)setup_vertex_color_material(sg, material, color_channel)def setup_vertex_color_material(sg, material, channel):"""Set material to use vertex color as color."""material.AddMaterialChannel(channel)shading_node = sg.CreateShadingVertexColorNode()shading_node.SetVertexColorIndex(vertex_color_index)material.SetShadingNetwork(channel, shading_node)def process_selection(sg):"""Process selected mesh in Blender"""# Export scene from Blender and import it file_path = temp_path + filescene = export_selection(sg, file_path)# Setup vertex color shadersetup_vertex_color_materials(sg, scene)# Process scenepipeline = create_pipline(sg)pipeline.RunScene(scene, Simplygon.EPipelineRunMode_RunInThisProcess)# Import result into Blenderimport_results(sg, scene, file_path)def main():sg = simplygon_loader.init_simplygon()process_selection(sg)sg = Nonegc.collect()if __name__== "__main__":main()

聚合方案:

# Copyright (c) Microsoft Corporation. 
# Licensed under the MIT license. import os
import bpy
import gcfrom simplygon10 import simplygon_loader
from simplygon10 import Simplygonfile = "scene.glb"
temp_path = "c:/tmp/"# Change parameters for quality
texture_size = 4096# Blender specific settings
color_channel = "Basecolor"
vertex_color_index = 0def export_selection(sg, file_path):"""Export the current selected objects into Simplygon."""bpy.ops.export_scene.gltf(filepath = file_path, use_selection=True)sceneImporter = sg.CreateSceneImporter()sceneImporter.SetImportFilePath(file_path)sceneImporter.Run()scene = sceneImporter.GetScene()return scenedef import_results(sg, scene, file_path):"""Import the Simplygon scene into Blender."""scene_exporter = sg.CreateSceneExporter()scene_exporter.SetExportFilePath(file_path)scene_exporter.SetScene(scene)scene_exporter.Run()bpy.ops.import_scene.gltf(filepath=file_path)def create_aggregaton_pipline(sg): """Create aggregation pipeline with color material caster"""aggregation_pipeline = sg.CreateAggregationPipeline()aggregator_settings = aggregation_pipeline.GetAggregationSettings()mapping_image_settings = aggregation_pipeline.GetMappingImageSettings()mapping_image_settings.SetGenerateMappingImage(True)material_settings = mapping_image_settings.GetOutputMaterialSettings(0)material_settings.SetTextureWidth(texture_size)material_settings.SetTextureHeight(texture_size)mapping_image_settings.SetTexCoordGeneratorType( Simplygon.ETexcoordGeneratorType_Parameterizer )caster = sg.CreateColorCaster()caster_settings = caster.GetColorCasterSettings()caster_settings.SetMaterialChannel( color_channel )aggregation_pipeline.AddMaterialCaster( caster, 0 )return aggregation_pipelinedef setup_vertex_color_materials(sg, scene):"""Set all materials in scene to vertex colored."""material_table = scene.GetMaterialTable()for i in range(0, material_table.GetMaterialsCount()):material = material_table.GetMaterial(i)setup_vertex_color_material(sg, material, color_channel)def setup_vertex_color_material(sg, material, channel):"""Set material to use vertex color as color."""material.AddMaterialChannel(channel)shading_node = sg.CreateShadingVertexColorNode()shading_node.SetVertexColorIndex(vertex_color_index)material.SetShadingNetwork(channel, shading_node)def remove_vertex_weights(sg, scene, vertex_color_index):"""Remove all vertex colors of index from scene."""scene_meshes_selection_set_id = scene.SelectNodes("SceneMesh")scene_meshes_selection_set = scene.GetSelectionSetTable().GetSelectionSet(scene_meshes_selection_set_id)# Loop through all meshes in the scenefor node_id in range(scene_meshes_selection_set.GetItemCount()):scene_mesh = Simplygon.spSceneMesh.SafeCast(scene.GetNodeByGUID( scene_meshes_selection_set.GetItem(node_id)))# Get geometry for meshgeometry = scene_mesh.GetGeometry()if not geometry: continuegeometry.RemoveColors(vertex_color_index)def process_selection(sg):"""Remove and bake decals on selected meshes."""# Export scene from Blender and import it file_path = temp_path + filescene = export_selection(sg, file_path)# Setup vertex color shadersetup_vertex_color_materials(sg, scene)# Aggregate optimized scenepipeline = create_aggregaton_pipline(sg)pipeline.RunScene(scene, Simplygon.EPipelineRunMode_RunInThisProcess)# Clean up vertex colorsremove_vertex_weights(sg, scene, vertex_color_index)# Import result into Blenderimport_results(sg, scene, file_path)def main():sg = simplygon_loader.init_simplygon()process_selection(sg)sg = Nonegc.collect()if __name__== "__main__":main()

原文链接:顶点颜色转纹理 - BimAnt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/175218.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

6.Spring源码解析-loadBeanDefinitions(String location)

这里resourceLoader其实就是ClassPathXmlApplicationContext 1.ClassPathXmlApplicationContext 在上文中图例就能看出来 获取资源组可能存在多个bean.xml 循环单独加载资源组 创建一个编码资源并解析 获取当前正在加载的资源发现是空 创建了一个字节输入流&#xff0c…

pytorch分布式训练

1 基本概念 rank:进程号,在多进程上下文中,我们通常假定rank 0是第一个进程或者主进程,其它进程分别具有1,2,3不同rank号,这样总共具有4个进程 node:物理节点,可以是一个…

Find My键盘|苹果Find My技术与键盘结合,智能防丢,全球定位

键盘是最常用也是最主要的输入设备,通过键盘可以将英文字母、汉字、数字、标点符号等输入到计算机中,从而向计算机发出命令、输入数据等。还有一些带有各种快捷键的键盘。随着时间的推移,渐渐的市场上也出现独立的具有各种快捷功能的产品单独…

自己动手实现一个深度学习算法——八、深度学习

深度学习是加深了层的深度神经网络。 1.加深网络 1)向更深的网络出发 创建一个如下图所示的网络结构的CNN 这个网络的层比之前实现的网络都更深。这里使用的卷积层全都是33 的小型滤波器,特点是随着层的加深,通道数变大(卷积…

FLASK博客系列7——我要插入数据库

我们来继续上次的内容,实现将数据插入数据库。 我们先更改下models.py,由于上次笔误,把外键关联写错了。在这里给大家说声抱歉。不过竟然没有小伙伴发现。 models.py from app import dbclass User(db.Model): # 表名将会是 user&#xff0…

针对无法创建JDK8版本的SpringBoot项目

自从昨日起,JDK突然改版了,不能在使用JDK8来进行创建Spring Boot项目了,导致目前小编的JDK无从下手~~ 因此,在仔细琢磨了一晚之后,想起来了以下几个方法,与大家共勉。希望能够得到大家的认可! …

生命科学领域 - 新药从研发到上市全流程

新药是指新研制的、临床尚未应用的药物,其化学本质应为新的化合物或称新化学实体、 新 分子实体、新活性实体。新药研发的根本目的是治疗疑难危重疾病,研制出来的药物即使是全新的化学结构,但是疗效或安全性却不及现有的药物便失去新药价值&a…

Redis面试题:哨兵模式相关问题,以及脑裂问题

目录 面试官:怎么保证Redis的高并发高可用 面试官:你们使用redis是单点还是集群,哪种集群 面试官:redis集群脑裂,该怎么解决呢? 面试官:怎么保证Redis的高并发高可用 候选人:首先…

人工智能-优化算法之凸集

凸性 凸性(convexity)在优化算法的设计中起到至关重要的作用, 这主要是由于在这种情况下对算法进行分析和测试要容易。 换言之,如果算法在凸性条件设定下的效果很差, 那通常我们很难在其他条件下看到好的结果。 此外&…

统信UOS安装Virtualbox虚拟机和Windows10系统

在UOS统信系统中部署Windows环境我可以通过安装虚拟机来实现,这也可以解决软件不适配带来的一些问题,当然对硬件配置也有一定的要求,不建议性能过低的设备使用。 接下来请按照以下步骤进行安装Virtualbox及Win10虚拟系统的设置。 1、安装Vi…

ETL+BI结合的数据集成工具

在当今信息化时代,企业积累了大量的数据资产,如何高效地提取、转换和加载(ETL)这些数据,并将其转化为有用的洞察力成为了企业取得竞争优势的关键。同时,商业智能(BI)作为一种数据驱动…

微软重磅更新:Bing Chat全线改名Copilot,用户可免费使用GPT4!(文末附Copilot使用教程)

原创 | 文 BFT机器人 微软在2023年的Ignite大会上宣布了许多新产品和功能。其中最引人注目的是Bing Chat更名为Copilot,Copilot基于最新的OpenAI模型,包括GPT-4和DALL・E 3,为用户提供文本和图像生成功能。也就是说,只要你拥有微…

Flutter 桌面应用开发之读写Windows注册表

文章目录 需求来源Windows查询Windows版本号方法1. 如何查看Windows版本号2. Windows开发如何通过代码查询Windows版本号(1) 使用C#代码:(2) 使用VB.NET代码 3.通过注册表查看Windows版本信息 Flutter查询Windows版本号方法依赖库支持平台实现步骤1. 在pubspec.yaml…

opencv-医学图像预处理

医学图像预处理通常需要针对特定任务和数据集的特点进行定制。以下是一些常见的医学图像预处理步骤,可以使用OpenCV以及其他相关库来实现: 导入相关的库 import cv2 import matplotlib.pyplot as plt1. 读取图像 image cv2.imread(r"C:\Users\m…

【图像分类】基于深度学习的中草药分类系统的设计与实现(ResNet网络,附代码和数据集)

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。(专栏订阅用户订阅专栏后免费提供数据集和源码一份,超级VIP用户不在服务范围之内,不想订阅专栏的兄弟们可以私信…

从0开始学习JavaScript--JavaScript对象继承深度解析

JavaScript中的对象继承是构建灵活、可维护代码的关键部分。本文将深入讨论JavaScript中不同的继承方式,包括原型链继承、构造函数继承、组合继承等,并通过丰富的示例代码展示它们的应用和差异。通过详细解释,大家可以更全面地了解如何在Java…

nodejs+vue+elementui+express青少年编程课程在线考试系统

针对传统线下考试存在的老师阅卷工作量较大,统计成绩数据时间长等问题,实现一套高效、灵活、功能强大的管理系统是非常必要的。该系统可以迅速完成随机组卷,及时阅卷、统计考试成绩排名的效果。该考试系统要求:该系统将采用B/S结构…

【JMeter】使用BeanShell写入内容到文件

一、前言 在我们日常工作中,可能会遇到需要将请求返回的数据写入到文件中。在我们使用JMeter进行性能测试时,就经常能够遇到这种情况。要想达到这种目的,我们一般采取BeanShell后置处理器来将内容写入到文件。 二、提取 在目前大多数的性能…

11.22数电第四次报告

《数字逻辑》实验报告 姓名 贾轲 年级 22 学号 20220669 专业、班级 计算机科学与技术计卓01 实验名称 实验十五 摩尔状态机序列检测器&实验十六 米利状态机序列检测器 实验时间 2023.11.23 实验地点 DS1410 实验成绩 实验性质 □验证性 □设计性 □…

SIFT尺度不变特征变换

SIFT(Scale-Invariant Feature Transform)是一种用于图像处理和计算机视觉中的特征提取和匹配的算法。它的主要优点是对图像的尺度、旋转和亮度变化具有较强的鲁棒性。 基本原理: Scale-space peak selection: Potential location for finding features.Keypoint Localizat…