如何使用 ShaderModifier 更改 SCNGeometry 中特定三角形的颜色

2024-01-06

首先,在继续之前,我已经阅读了:SceneKit 使用纹理坐标在纹理上绘制 https://stackoverflow.com/questions/26129111/ios8-scenekit-painting-on-texture-with-texture-coordinates这似乎表明我走在正确的轨道上。

我有一个复杂的 SCNGeometry 代表一个六球体。它的渲染效果非常好,在我的所有测试设备上都达到了 60 fps。

目前,所有六边形都使用单一材质渲染,因为据我了解,我添加到几何体中的每个 SCNMaterial 都会添加另一个绘制调用,这是我无法承受的。

最终,我希望能够为近 10,000 个六边形中的每一个单独着色,因此为每个六边形添加另一种材质是行不通的。

我一直计划将颜色范围限制为(比如说)100 种颜色,然后在不同的几何图形之间移动六边形,每个几何图形都有自己的颜色材质,但这行不通,因为 SCNGeometry 说它适用于一组不可变的顶点。

因此,我当前的想法/计划是使用 @rickster 在上述问题中建议的着色器修改器来以某种方式修改单个六边形(或 4 个三角形的集合)的颜色。

问题是,我有点理解所提到的Apple doco,但我不明白如何向着色器提供我认为本质上必须是颜色信息数组的内容,以某种方式进行索引,以便着色器知道哪些三角形要给出什么颜色。

我现在创建几何图形的代码如下:

NSData *indiceData = [NSData dataWithBytes:oneMeshIndices length:sizeof(UInt32) * indiceIndex];
SCNGeometryElement *oneMeshElement =
    [SCNGeometryElement geometryElementWithData:indiceData
                                  primitiveType:SCNGeometryPrimitiveTypeTriangles
                                 primitiveCount:indiceIndex / 3
                                  bytesPerIndex:sizeof(UInt32)];
[oneMeshElements addObject:oneMeshElement];

SCNGeometrySource *oneMeshNormalSource =
    [SCNGeometrySource geometrySourceWithNormals:oneMeshNormals count:normalIndex];

SCNGeometrySource *oneMeshVerticeSource =
    [SCNGeometrySource geometrySourceWithVertices:oneMeshVertices count:vertexIndex];

SCNGeometry *oneMeshGeom =
    [SCNGeometry geometryWithSources:[NSArray arrayWithObjects:oneMeshVerticeSource, oneMeshNormalSource, nil]
                            elements:oneMeshElements];

SCNMaterial *mat1 = [SCNMaterial material];
mat1.diffuse.contents = [UIColor greenColor];
oneMeshGeom.materials = @[mat1];
SCNNode *node = [SCNNode nodeWithGeometry:oneMeshGeom];

如果有人可以阐明如何为着色器提供一种方法来为 indiceData 中的索引索引的每个三角形着色,那就太棒了。

EDIT

我尝试过为着色器提供纹理作为颜色信息的容器,该颜色信息将由 VertexID 索引,但似乎 SceneKit 并未使 VertexID 可用。我的想法是通过 SCNMaterialProperty 类提供此纹理(实际上只是一个字节数组,六球体上的每个六边形 1 个),然后在着色器中根据顶点编号提取适当的字节。该字节将用于索引固定颜色数组,然后每个顶点的最终颜色将给出所需的结果。

如果没有 VertexID,这个想法就行不通,除非有其他一些类似有用的数据......

EDIT 2

也许我很固执。我一直在努力让它发挥作用,作为一个实验,我创建了一个基本上是条纹彩虹的图像,并编写了以下着色器,认为它基本上可以用彩虹为我的球体着色。

这不起作用。整个球体是使用图像左上角的颜色绘制的。

我的shaderModifer代码是:

#pragma arguments
sampler2D colorMap;
uniform sampler2D colorMap;
#pragma body
vec4 color = texture2D(colorMap, _surface.diffuseTexcoord);
_surface.diffuse.rgba = color;

我使用以下代码应用它:

SCNMaterial *mat1 = [SCNMaterial material];
mat1.locksAmbientWithDiffuse = YES;
mat1.doubleSided = YES;

mat1.shaderModifiers = @{SCNShaderModifierEntryPointSurface :
                             @"#pragma arguments\nsampler2D colorMap;\nuniform sampler2D colorMap;\n#pragma body\nvec4 color = texture2D(colorMap, _surface.diffuseTexcoord);\n_surface.diffuse.rgba = color;"};

colorMap = [SCNMaterialProperty materialPropertyWithContents:[UIImage imageNamed:@"rainbow.png"]];

[mat1 setValue:colorMap forKeyPath:@"colorMap"];

我原以为 _surface.diffuseTexcoord 是合适的,但我开始认为我需要通过了解图像的尺寸并以某种方式进行插值,以某种方式将其映射到图像中的坐标。

但如果是这种情况,_surface.diffuseTexcoord 的单位是什么?我如何知道它的最小/最大范围,以便我可以将其映射到图像?

再次,我希望如果这些尝试是错误的,有人可以引导我走向正确的方向。

EDIT 3

好的,所以我知道我现在走在正确的轨道上。我已经意识到,通过使用 _surface.normal 而不是 _surface.diffuseTexcoord,我可以将其用作球体上的纬度/经度来映射到图像中的 x,y,现在我看到六边形根据中的颜色进行着色colorMap 但是我做什么并不重要(到目前为止);法线角度似乎相对于相机位置是固定的,因此当我移动相机以查看球体的不同点时,颜色贴图不会随之旋转。

这是最新的着色器代码:

 #pragma arguments
 sampler2D colorMap;
 uniform sampler2D colorMap;
 #pragma body
 float x = ((_surface.normal.x * 57.29577951) + 180.0) / 360.0;
 float y = 1.0 - ((_surface.normal.y * 57.29577951) + 90.0) / 180.0;
 vec4 color = texture2D(colorMap, vec2(x, y));
 _output.color.rgba = color;

ANSWER

所以我解决了这个问题。事实证明,不需要着色器就可以达到我想要的结果。

答案是使用mappingChannel http://developer.apple.com/reference/scenekit/scnmaterialproperty/1395405-mappingchannel为几何体的每个顶点提供一组纹理坐标。这些纹理坐标用于从适当的纹理中提取颜色数据(这完全取决于您如何设置材质)。

因此,虽然我确实设法让着色器正常工作,但旧设备上存在性能问题,而使用映射通道要好得多,现在在所有设备上都以 60fps 的速度工作。

我确实发现,尽管文档说映射通道是一系列 CGPoint 对象,但这在 64 位设备上不起作用,因为 CGPoint 似乎使用双精度而不是浮点数。

我需要定义我自己的结构:

typedef struct {
  float x;
  float y;
} MyPoint;

MyPoint oneMeshTextureCoordinates[vertexCount];

然后建立了一个数组,每个顶点一个,然后我创建了appingChannel源,如下所示:

SCNGeometrySource *textureMappingSource =
  [SCNGeometrySource geometrySourceWithData:
    [NSData dataWithBytes:oneMeshTextureCoordinates
                   length:sizeof(MyPoint) * vertexCount]
                                   semantic:SCNGeometrySourceSemanticTexcoord
                                vertexCount
                            floatComponents:YES
                        componentsPerVector:2
                          bytesPerComponent:sizeof(float)
                                 dataOffset:0
                                 dataStride:sizeof(MyPoint)];

编辑: 为了响应请求,这里有一个项目演示了我如何使用它。https://github.com/pkclsoft/HexasphereDemo https://github.com/pkclsoft/HexasphereDemo


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 ShaderModifier 更改 SCNGeometry 中特定三角形的颜色 的相关文章

  • 关于在 Objective-C 中迭代 2 个数组的简单问题

    我正在 Objective c 中迭代 NSArray for id object in array1 我现在有另一个 array2 我需要使用当前 array1 的相同索引进行访问 我应该使用另一个 for 语句吗 thanks 您有多种
  • 如何呈现半屏模态视图?

    我有一个 UIViewController 当按下按钮时 我想要一个半屏视图向上滑动 其中有一个 UIPicker 我在 IB 中使用 UIPicker 和带有 完成 取消 按钮的 UIToolBar 制作了一个 UIView 我怎样才能做
  • _ 和 self 之间的区别。在 Objective-C 中

    使用下划线和使用selfObjective C 中调用时的关键字 property 财产申报 property weak nonatomic NSString myString Calling synthesize关于物业 synthesi
  • 如何去除 UIImageView 遮罩后的透明区域?

    在我的一个 iOS 应用程序中 我尝试使用以下命令剪切图像的一部分CGImageMask 我已成功使用以下代码屏蔽图像 UIImage maskImage UIImage referenceImage withMask UIImage ma
  • 图像高斯模糊 - iOS 8

    我有一个移动的背景图像 我想模糊它的底部 我would只用 Photoshop 就能做到 但由于图像会移动 效果不太好 这就是我的意思 看图片底部 基本上就像底座对 iPhone 的影响一样 我使用的是 iOS 8 但不是 Swift 我根
  • &(与符号)和 && 或 | 之间的区别(管道)和||在 Objective-C 中?

    我想知道Objective C是否关心我是写 还是 我相信一个与号 会或应该导致如果左侧已经为假 则右侧将不会被评估 这适用于 Objective C 吗 Yes 这些运算符在 C 和 Objective C 中的功能相同 就像在 C 中一
  • 方向改变时重新定位控件

    我知道自动布局可用于在方向改变时使尺寸和位置保持一致 当方向改变时 是否可以完全改变布局 例如 请查看下面的纵向模式下简单登录屏幕的线框 现在 如果我旋转设备 我想完全重新定位控件 这种事情可以用自动布局来完成吗 如果没有 我该怎么办 谢谢
  • UILocalNotification 在后台 10 分钟后不提示

    In didFinishLaunchingWithOptions调用函数的定时器循环httpRequest每 1 分钟间隔一次 BOOL application UIApplication application didFinishLaun
  • 为什么performSegueWithIdentifier在viewDidLoad中不起作用?

    我试图在视图控制器上调用 viewDidLoad 后立即触发故事板转场 Segue 附加了一个标识符 当从链接到按钮或其他控件的方法内部调用时 它可以正常工作 但它在 viewDidLoad 内部不起作用 它只是默默地失败了 viewDid
  • 如何在iOS中处理1到3个手指的滑动手势

    我使用以下代码来处理代码中的 1 根手指滑动 UISwipeGestureRecognizer swipe UISwipeGestureRecognizer alloc initWithTarget self action selector
  • locationOfTouch 和 numberOfTouches

    你好 我有这个识别器 设置为 2 次触摸 但它只返回一个 而不是两个 CGPoint void gestureLoad UIGestureRecognizer recognizer recognizer UITapGestureRecogn
  • NSUInteger 的奇怪行为 - 无法正确转换为浮动

    这是我的情况 这让我发疯 我有一个计数值为 517 的 NSMutableArray 我有一个双精度值 它是我的乘数 double multiplier 0 1223 double result myArray count multipli
  • Cocoa 应用程序菜单栏不可点击

    我正在我的可可应用程序中构建一个菜单栏 其中包含以下代码 implementation我的自定义应用程序CustomApplication void setUpMenuBar CustomApplication sharedApplicat
  • 调整 UIImage 的大小而不将其完全加载到内存中?

    我正在开发一个应用程序 用户可以在其中尝试加载非常非常大的图像 这些图像首先在表格视图中显示为缩略图 我的原始代码会在大图像上崩溃 因此我重写它以首先将图像直接下载到磁盘 是否有一种已知的方法可以调整磁盘上图像的大小 而无需通过以下方式将其
  • iPhone:UIApplication WillResignActiveNotification 从未被调用

    我正在视图控制器中播放视频 当用户按下硬件主页按钮并且当前正在播放视频时 应用程序崩溃并显示EXC BAD ACCESS在模拟器中 我读到我应该使用applicationWillResignActive停止视频播放的消息应该可以解决崩溃问题
  • 如果我使用自定义 UITableViewCell,是否需要设置 heightForRowAtIndexPath?

    如果我使用自定义 UITableViewCell 是否需要设置 heightForRowAtIndexPath 在我的 NIB 中 我已经设置了单元高度 当我覆盖 heightForRowAtIndexPath 时 单元格的内容不会出现 即
  • 叠加 SKScene 未显示

    我正在尝试将 SKScene 覆盖在 SCNScene 上 当我在模拟器和 iPhone6 上运行我的应用程序时 overlayScene SKScene 按预期显示 但是当我尝试在 iPhone5 上运行它 尝试了 2 个不同的设备 时
  • 如何在 UICollectionView 中将行居中?

    我有一个UICollectionView与随机细胞 有什么方法可以让我将行居中吗 默认情况下它是这样的 x x x x x x x x x x x x x x 这是所需的布局 x x x x x x x x x x x x 我必须做这样的事
  • 为什么 Objective-C 允许在方法定义末尾使用分号? [复制]

    这个问题在这里已经有答案了 可能的重复 Objective C 实现文件中方法名后面的分号 https stackoverflow com questions 5678360 semicolon after the method name
  • 如何为 UIImageView 随机化器实现滑动手势

    我一直在浏览大量的教程和问题 但似乎找不到我要找的东西 我有一种感觉 我只是错过了一个简单的步骤 我仍在学习诀窍 所以请承受和我一起做这个 我正在 xcode 4 3 3 上制作图像随机化器 并且我已经能够使用按钮来随机化图像 但我希望它能

随机推荐

  • 访问Python列表中的元素

    我的答案列表如下 answers defaultdict
  • 在 R 中使用 tryCatch() 在循环中分配错误值

    我正在努力了解 R 中 tryCatch 的说明 我正在尝试捕获股票的收盘价 案例 2 好案例 TickersJuly2 独特的价格与股票代码关系 情况 1 坏情况 TickersJuly1 FABU 收盘价是 CETX 的重复 对于 FA
  • 以编程方式估计 Android 手机电池耗尽的时间

    因此有一些方法可以通过监听器获取当前的电池电量 但是 这些可以为您提供手机当前电池状态的值 但无法指示电池耗尽的速度有多快 慢 有什么方法可以估计电池耗尽之前的剩余时间 你能做任何知道电压是多少的事情吗 或者也许可以监控一段时间内电池消耗的
  • android recyclerview加载更多按钮[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有教程 示例包含带有 recyclerview 的加载更多按钮 我需要在 recyclerview
  • 控制鼠标键盘Golang?

    如何在操作系统 X11 级别上控制检索 设置鼠标位置并触发键盘事件 这与中的功能类似Java 中的机器人类 http docs oracle com javase 7 docs api java awt Robot html 我知道很可能不
  • 如何在AppBundle中添加视图?

    我正在尝试在 symfony3 中进行实验 我试图在谷歌上搜索它 但我没有找到他们明确的答案 这是 symfony 中的默认控制器 class DefaultController extends Controller Route name
  • Anaconda navigator 和 activate.bat 在 Windows 中出现空格问题

    最近 我突然开始遇到 Anaconda 提示符和使用 VS Code 启动 jupyter 实例的问题 存在 访问被拒绝 错误 但即使作为管理员 我也收到一个错误 该错误提示我路径中存在空格问题 我从来没有遇到过这个问题 并且 anacon
  • discord.py 中的 Cog 和 Extension 有什么区别?

    在discord py文档中 有 扩展 https discordpy readthedocs io en stable ext commands extensions html https discordpy readthedocs io
  • 获取 Puppeteer 中 XPath 的所有链接(暂停或不起作用)?

    我需要使用 XPath 选择页面上的所有链接 然后我的 Puppeteer 应用程序才能单击并执行一些操作 我发现该方法 下面的代码 有时会卡住 我的爬虫会暂停 是否有更好 不同的方式从 XPath 获取所有链接 或者我的代码中是否存在不正
  • Firefox 中可点击的电话协议标签

    我有一个非常标准的电话号码标签 它适用于一切except火狐 我认为电话协议是标准的 有我不知道的解决方法吗 a class tel href 800 123 4567 a 火狐浏览器错误信息 地址不明白 Firefox 不知道如何打开此地
  • java 中最好的 XML 解析库是哪个 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Rails 范围查找当前用户

    我使用 Rails 3 和 Devise 进行用户身份验证 假设我有一个启用了 Devise 的用户模型和一个产品模型 并且用户有很多产品 在我的产品控制器中 我希望我的 find 方法的范围由 current user 确定 即 prod
  • 为什么 Heroku 会给出权限被拒绝的错误?

    When git clone v email protected cdn cgi l email protection testabcde git Cloning into testabcde Heroku 回归 Permission de
  • 角度 2 不透明令牌

    需要一些有关提供 OpaqueToken 的帮助 使用 Angular 2 beta 12 如果提供程序密钥是字符串 则它可以正常工作 但在使用 OpaqueToken 时则不起作用 在 Child 类中 SF 未定义 家长班级 expor
  • 如何计算时间加权平均值并创建滞后

    我搜索了论坛 但没有找到任何可以回答或提供如何在论坛上做我想做的事情的提示 我有每年的暴露数据测量 我希望根据每个人参与研究的情况来计算个人水平的年平均值 对于每一行 一年暴露分配应包括从加入研究前最后一个月开始的前 12 个月的数据 例如
  • 从内存中扩充 XML 文件

    我复制了一个 XML 文件 assets到我的应用程序数据文件夹 data data package name files 我这样做是因为用户将能够修改大量数据 并且我想将该数据保存到内部存储器中 然后在重新启动应用程序时再次加载 这一切都
  • 如何为 Chrome 设置可调试标志?

    官方教程里有https github com phonegap phonegap wiki Debugging in PhoneGap https github com phonegap phonegap wiki Debugging in
  • 如何将完整的 PartCover 结果纳入 TeamCity 5?

    我正在尝试在 TeamCity 5 0 中正确生成 PartCover 报告 当我单击构建详细信息中的 代码覆盖率 选项卡时 报告为空 我正在使用 sln2008 构建代理 我的 PartCoverage 设置如下 包括模式 报告 XSLT
  • Mat::checkVector 在 OpenCV 中做什么?

    我尝试在 OpenCV C 中使用以下函数 calcOpticalFlowPyrLK prev frame gray frame gray points 0 points 1 status err winSize 3 termcrit 0
  • 如何使用 ShaderModifier 更改 SCNGeometry 中特定三角形的颜色

    首先 在继续之前 我已经阅读了 SceneKit 使用纹理坐标在纹理上绘制 https stackoverflow com questions 26129111 ios8 scenekit painting on texture with