2017-10-16 141 views
1

我有一个着色器函数,其功能类似于Blender3D中的“色彩渐变”节点。它输入零和一之间的浮动,并输出颜色,是按照指定的顺序任意数量的颜色的共混物:色彩渐变着色器(cg/shaderlab)

blender3D色带
blender3D color ramp

这是我的代码:

fixed4 ColorRamp(float factor){ 
      float positions[5] = {_Pos0, _Pos1, _Pos2, _Pos3, _Pos4}; 
      fixed4 colors[5] = {_Color0, _Color1, _Color2, _Color3, _Color4}; 

      fixed4 outColor = _Color0; 

      for(int i = 0; i <4; i++){ 

       if(factor >= positions[i] && factor <positions[i+1]){ 
        fixed localFactor = (factor - positions[i])/(positions[i+1] - positions[i]); 
        outColor = lerp(colors[i], colors[i+1], localFactor); 
       }else if (factor > positions [_NumColors-1]){ 
        outColor = colors[_NumColors -1]; 
       } 
      } 
      return outColor; 
     } 

它的工作原理。但它很糟糕,原因如下:

  1. 斜坡中的颜色数是硬编码的。在Unity编辑器中添加它们的列表会更好。
  2. if/else语句。我知道这些表现很糟糕,应该避免。
  3. 颜色数组在函数中声明,这意味着必须为每个片段创建一个新数组(我认为)。

我的主要问题是第一个问题:如何在不需要编辑硬编码值的情况下更改斜坡中的颜色数量?

回答

0
  1. 这是不可能的。着色器会自动编译。并且编译器不支持循环。你的循环只是语法糖,编译时它会扩展到确定的迭代次数。
  2. If/else对于表现并不可怕。这只是为了测试,因为它会增加圈复杂度。
  3. 您可以在“属性”块中声明数组。

对不起,但你不能在属性块中使用数组。你会在方法之外声明它。

float positions[5]; 
fixed4 colors[5]; 

fixed4 ColorRamp(float factor){ 
    positions[0] = _Pos0; 
    positions[0] = _Pos2; 
    positions[0] = _Pos3; 
    positions[0] = _Pos4; 
    positions[0] = _Pos5; 

    colors[0] = _Color0; 
    colors[1] = _Color1; 
    colors[2] = _Color2; 
    colors[3] = _Color3; 
    colors[4] = _Color4; 

    fixed4 outColor = _Color0; 

    for(int i = 0; i <4; i++) 
    { 
     if(factor >= positions[i] && factor <positions[i+1]) 
     { 
      fixed localFactor = (factor - positions[i])/(positions[i+1] - positions[i]); 
      outColor = lerp(colors[i], colors[i+1], localFactor); 
     } 
     else if (factor > positions [_NumColors-1]) 
     { 
      outColor = colors[_NumColors -1]; 
     } 
    } 
    return outColor; 
} 

但是你必须初始化统一scritpt的外部数组。

float[] array = new float[] {1, 2, 3, 4, 5} 
material.SetFloatArray("positions", array); 
Vector4[] colors = new Vector4[] { new Vector4(), new Vector4(), new Vector4(), new Vector4(), new Vector4() }; 
material.SetVectorArray("colors", colors); 
+0

谢谢!你能否提供一个在属性块中声明数组的例子?我遇到了麻烦,无论是从Unity编辑器传递数组还是从可以从Unity编辑器传递的属性创建数组。 – dixiepig

0

最简单的答案是:烤你渐变成纹理