我爱霍启刚掖 发表于 2020-12-23 09:28

Unreal中针对Instance物体获取位置

最近帮忙解决了一个很奇怪的问题:在材质球里如何获得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。


/** Transforms a vector from local space to world space (VS version) */
MaterialFloat3 TransformLocalVectorToWorld(FMaterialVertexParameters Parameters,MaterialFloat3 InLocalVector)
{
    #if USE_INSTANCING || IS_MESHPARTICLE_FACTORY
      return mul(InLocalVector, (MaterialFloat3x3)Parameters.InstanceLocalToWorld);
    #else
      return mul(InLocalVector, GetLocalToWorld3x3());
    #endif
}

/** Transforms a vector from local space to world space (PS version) */
MaterialFloat3 TransformLocalVectorToWorld(FMaterialPixelParameters Parameters,MaterialFloat3 InLocalVector)
{
    return mul(InLocalVector, GetLocalToWorld3x3());
}顺便提一句常见的几个位置区别Coordinates Expressions:
ActorPositionWS: Actor位置(逻辑概念)ObjectPositionWS: 包围盒中心(和网格有关)TransformPosition(float4(0,0,0,0))是获取的模型坐标系零点对应的世界坐标
如果一定要获取准确Instance物体的LocalPosition,可以参考TransformLocalVectorToWorld来个CustomExpression自定义一发

这里我自定义扩展了一个材质节点,把Pixel和Vertex分开输入(防止编译错误)。最后生成的代码就是
MaterialFloat3 CustomExpression0(FMaterialPixelParameters Parameters)
{
    return mul(float4(GetWorldPosition(Parameters), 1), Primitive.WorldToLocal).xyz;;
}

MaterialFloat3 CustomExpression1(FMaterialVertexParameters Parameters)
{
#if USE_INSTANCING
    return Parameters.InstanceLocalPosition;
#else
    return mul(float4(GetWorldPosition(Parameters), 1), Primitive.WorldToLocal).xyz;
#endif
}ps. UE4里扩展材质球节点比我想象中简单很多,直接在插件里实现一个UMaterialExpression的子类,核心代码是virtual int32 Compile(class FMaterialCompiler* Compiler, int32 OutputIndex)函数生成最后的HLSL。具体生成逻辑参考HLSLMaterialTranslator.h里的FHLSLMaterialTranslator实现即可
页: [1]
查看完整版本: Unreal中针对Instance物体获取位置