最近在用UE4的Instancing, 发现限制很多。

Unity有instancing的attribute array (uniform/constant buffer),通过InstanceID来访问每个instance的数据,实现每个实例的不同的参数(通常的一种做法)。

然而Unreal没有这样的功能,只有一些instancing的vertex buffer。

shader:

 #if USE_INSTANCING && !USE_INSTANCING_EMULATED
float4 InstanceOrigin : ATTRIBUTE8; // per-instance random in w
half4 InstanceTransform1 : ATTRIBUTE9; // hitproxy.r + 256 * selected in .w
half4 InstanceTransform2 : ATTRIBUTE10; // hitproxy.g in .w
half4 InstanceTransform3 : ATTRIBUTE11; // hitproxy.b in .w
#endif // USE_INSTANCING && !USE_INSTANCING_EMULATED

C++:

 template <class FloatType>
struct FInstanceStream
{
FVector4 InstanceOrigin; // per-instance random in w
FloatType InstanceTransform1[]; // hitproxy.r + 256 * selected in .w
FloatType InstanceTransform2[]; // hitproxy.g in .w
FloatType InstanceTransform3[]; // hitproxy.b in .w
int16 InstanceLightmapAndShadowMapUVBias[];
...
};

在不改动引擎代码的前提下(不熟悉,风险大), 总结了以下workaround:

其中第一种是简单的颜色映射。

后面的几种是为了解决多个参数的方式,因为只有一个随机值,导致随机化不理想。比如一个实例有两个随机颜色,用PerInstanceRandom去查两个颜色表【蓝,黄,绿】和【黑,白,灰】那么第一个颜色是蓝色的时候,第二个颜色一定是黑色,而实际需求的很可能是两个颜色也要随机搭配。

解决方法是把一个随机值映射为多个。前两种比较类似,一个用随机函数,一个用纹理采样。最后一种是hack, 取每一位的数字就不一样。虽然hack,有很多限制,但是目前用起来还算可以。
事实上,后面两种都是第一种的特化,第二种Fn=TextureSample(Texn, x), 第三种Fn=frac(x*10^n),虽然我一开始想到的就是第三种最简单的hack。

  1. Simple senario

    • map to color

      • create an color LUT table (i.e. using photoshop, filter mode need to set as point/nearest if interpolation is not expected)
      • make float2: use PerInstanceRandom as x
      • link to TextureSample node's uv pin
    • map to value
      • PerInstanceRandom * (max-min) + min
    • could be done in blueprint
  2. Multiple variation attributes:(i.e. speed/color/move range/angular speed/etc.)
    • Simply map PerInstanceRandom to multiple attributes works but may not have expected results
    • i.e. instances with 2 different color, using PerInstanceRandom to access 2 color tables, lets say [Blue, Yellow, Cyan] and [Black, White, Grey]
      because using the same PerInstanceRandom as UV, when the first color is "Blue", the second "random" color will always be "Black".
      while the expected result may need be any combinations of the color in the 2 tables, not fixed combinations.
    • Solution: remap PerInstanceRandom to multiple random data
      • 1.multiple custom random function

        • random0 = F0(PerInstanceRandom)
        • random1 = F1(PerInstanceRandom);
        • ...
        • randomn = Fn(PerInstanceRandom);
        • get color using random0;
        • get speed/color2 using random1;
        • ...
        • pros: can map PerInstanceRandom to any count of random numbers
        • cons: custom math/random function need to be written for each attribute variation
      • 2.using random noise texture: similiar as above while using texture sampling
        • random0 = sample(RandomNoiseTexture0, float2( PerInstanceRandom, 0));
        • random1 = sample(RandomNoiseTexture1, float2(PerInstancerandom, 0));
        • ...
        • pros: easy & simple; blueprint friendly; can map PerInstanceRandom to any count of random number
        • cons: one additional random noise texture for each attribute - extra workflow & runtime cost (texture uniform may exceed?)
          - this could be avoid by using a single random texture with multiple rows: randomn = sample(Texture, float2(PerInstanceRandom, (0.5+n)/N));
      • 3.simple hack: most significant digit shift
        • random0 = PerInstanceRandom;
        • random1 = frac(random0*10);
        • random2 = rac(random1*10);
        • ...
        • pros: simple & easy; blueprint friendly
        • cons: precision lost on each iteration; max attribute variations limited to 5-6, due to floating point precision issue. last random number( i.e. random5 ) have lowest resolution: approximately 10 (probably 0.0~0.9 or even less), but still good to be used as index/uv to sampling color table if color count is small.
        • if variation count is small, this method is personally recommended.

note: the last 2 methods can be consider as an speicialization of the first one: 2. Fn=TextureSample(x),  3.Fn=frac(x*10^n)

note2: instance's AbsoluteWorldPosition could be used to generate attribute variations.

[工作积累] Tricks with UE4 PerInstanceRandom的更多相关文章

  1. [工作积累] D3D10+ 中 Pixel Shader 的input semantic和参数顺序

    由于semantic的使用,我们有理由相信 vertex shader的output 和 pixel shader的input是按照semantic来匹配的,而跟传入顺序无关.印象dx9时代是这样. ...

  2. [工作积累] UE4 并行渲染的同步 - Sync between FParallelCommandListSet & FRHICommandListImmediate calls

    UE4 的渲染分为两个模式1.编辑器是同步绘制的 2.游戏里是FParallelCommandListSet并行派发的. mesh渲染也分两类,static mesh 使用TStaticMeshDra ...

  3. [工作积累] UE4 TAA ReProjection的精度处理

    先贴一个UE4 TAA的slidehttps://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf ...

  4. [工作积累] Google/Amazon平台的各种坑

    所谓坑, 就是文档中没有标明的特别需要处理的细节, 工作中会被无故的卡住各种令人恼火的问题. 包括系统级的bug和没有文档化的限制. 继Android的各种坑后, 现在做Amazon平台, 遇到的坑很 ...

  5. [工作积累] 32bit to 64bit: array index underflow

    先贴一段C++标准(ISO/IEC 14882:2003): 5.2.1 Subscripting: 1 A postfix expression followed by an expression ...

  6. [工作积累] bitfield

    ISO/IEC 14882:2003: 9.6 Bit-fields [class.bit] A member-declarator of the form identifieropt : const ...

  7. [工作积累] GCC 4.6 new[] operator内存对齐的BUG

    对于用户没有定义dctor(包括其所有成员)的类来说, new CLASS[n] 可能会直接请求sizeof(CLASS)*n的空间. 而带有dctor的 类, 因为delete[]的时候要逐个调用析 ...

  8. [工作积累] TAA Ghosting 的相关问题

    因为TAA要使用上一帧的历史结果,那么在相机移动的时候,颜色就会有残留,出现ghosting(残影). 由于上一帧历史是累积的,是由上一帧的直接渲染结果和上上帧的结果做了合并,所以ghosting并不 ...

  9. [工作积累] shadow map问题汇总

    1.基本问题和相关 Common Techniques to Improve Shadow Depth Maps: https://msdn.microsoft.com/en-us/library/w ...

随机推荐

  1. 实时输出topk最频繁变动的股价

    网上看到了一道关于bloomburg的面试题,follow 评论的思路 自己试着写了一个HashHeap的实现. 基本思路是维护一个大小为K的最小堆,里面是topK股价变动的公司ID(假设ID是Int ...

  2. [转载]关于laravel中表关系的一对一、一对多、多对一、多对多实践

    这是转载的文章 出处:https://blog.csdn.net/weixin_38112233/article/details/79220535 作者:重新遇到 一.建表和插入测试数据 1.用户表建 ...

  3. android LogConfigurator

    android LogConfigurator  此为第三方的 Log日志

  4. 获取百度地图POI数据三(模拟关键词搜索)

    上一篇博文中讲到如何获取用于搜索的关键词,并且已经准备好了一百五十万的关键词   这其中有门牌号码,餐馆酒店名称,公司名称,道路名称等.有了这些数据,我们就可以通过代码,模拟我们在百度地图的搜索框中搜 ...

  5. Problem A: STL——灵活的线性表

    Description 数组和链表是我们熟知的两种线性结构,但是它们不够灵活(不能同时实现直接插入.删除和访问操作),给你若干种操作,你能通过一种灵活的容器,实现它们的功能吗? 操作1:Build a ...

  6. C# FTP操作报550错误

    最近在做FTP创建文件夹和上传文件的功能,测试之后一直提示“远程服务器返回错误: (550) 文件不可用(例如,未找到文件,无法访问文件)”,我在网上找了很久的解决方案也没有解决掉这个问题,网上找到的 ...

  7. Spring源码学习(5)—— bean的加载 part 2

    之前归纳了从spring容器的缓存中直接获取bean的情况,接下来就需要从头开始bean的加载过程了.这里着重看单例的bean的加载 if(ex1.isSingleton()) { sharedIns ...

  8. No mapping found for HTTP request with URI [/crmcrmcrm/css/bootstrap.min.css] in DispatcherServlet with name 'springMvc'

    先把错误贴上来 No mapping found for HTTP request with URI [/crmcrmcrm/css/sb-admin-2.css] in DispatcherServ ...

  9. python并发_协程

    在操作系统中进程是资源分配的最小单位, 线程是CPU调度的最小单位. 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明:协程是一种用户态的轻量级线程,即协程是由用户程序自 ...

  10. 使用Bash Bunny从被锁定的系统抓取登陆凭据

    在今年早些时候,FB就对Bash Bunny做了相关的报导.这款号称“世界上最先进的USB攻击工具”的Bash Bunny,是否真的像其所说的一样是款渗透神器呢?下面,我将通过实例演示如何利用Bash ...