找回密码
 立即注册
查看: 481|回复: 0

Unreal中针对Instance物体获取位置

[复制链接]
发表于 2020-12-23 09:28 | 显示全部楼层 |阅读模式
最近帮忙解决了一个很奇怪的问题:在材质球里如何获得Instance模型(譬如Foliage)的坐标,其实也就是Foliage instance position in Material editor。TA需要的是模型原点的世界坐标。
解决方法非常简单粗暴:
Try passing object position through custom UVs
我是用VertexInterpolator来实现(其实意思一样),这样能得到正确结果的原因是:对于Instance物体 在VS里计算世界坐标是对的,而PS里是错的。


下面来看下具体的原因:对于非Instance的物体,两者除了经过一次v2f插值之外没什么区别;但是对于Instance的物体,那么PS里计算的时候数据是不够的(没有InstanceLocalToWorld)。当PS里世界空间坐标是错误的情况下,肯定就不能指望了。
ps. 仔细观察可以发现UE4内置的不少节点其实都是实现了两个版本(Vertex/Pixel),区分的地方其实就是第一个参数是FMaterialVertexParameters还是FMaterialPixelParameters。

  1. /** Transforms a vector from local space to world space (VS version) */
  2. MaterialFloat3 TransformLocalVectorToWorld(FMaterialVertexParameters Parameters,MaterialFloat3 InLocalVector)
  3. {
  4.     #if USE_INSTANCING || IS_MESHPARTICLE_FACTORY
  5.         return mul(InLocalVector, (MaterialFloat3x3)Parameters.InstanceLocalToWorld);
  6.     #else
  7.         return mul(InLocalVector, GetLocalToWorld3x3());
  8.     #endif
  9. }
  10. /** Transforms a vector from local space to world space (PS version) */
  11. MaterialFloat3 TransformLocalVectorToWorld(FMaterialPixelParameters Parameters,MaterialFloat3 InLocalVector)
  12. {
  13.     return mul(InLocalVector, GetLocalToWorld3x3());
  14. }
复制代码
顺便提一句常见的几个位置区别Coordinates Expressions:
    ActorPositionWS: Actor位置(逻辑概念)ObjectPositionWS: 包围盒中心(和网格有关)TransformPosition(float4(0,0,0,0))是获取的模型坐标系零点对应的世界坐标
如果一定要获取准确Instance物体的LocalPosition,可以参考TransformLocalVectorToWorld来个CustomExpression自定义一发

这里我自定义扩展了一个材质节点,把Pixel和Vertex分开输入(防止编译错误)。最后生成的代码就是
  1. MaterialFloat3 CustomExpression0(FMaterialPixelParameters Parameters)
  2. {
  3.     return mul(float4(GetWorldPosition(Parameters), 1), Primitive.WorldToLocal).xyz;;
  4. }
  5. MaterialFloat3 CustomExpression1(FMaterialVertexParameters Parameters)
  6. {
  7. #if USE_INSTANCING
  8.     return Parameters.InstanceLocalPosition;
  9. #else
  10.     return mul(float4(GetWorldPosition(Parameters), 1), Primitive.WorldToLocal).xyz;
  11. #endif
  12. }
复制代码
ps. UE4里扩展材质球节点比我想象中简单很多,直接在插件里实现一个UMaterialExpression的子类,核心代码是virtual int32 Compile(class FMaterialCompiler* Compiler, int32 OutputIndex)函数生成最后的HLSL。具体生成逻辑参考HLSLMaterialTranslator.h里的FHLSLMaterialTranslator实现即可

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-26 10:06 , Processed in 0.121165 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表