颜色渐变着色器(cg / shaderlab)

时间:2017-10-16 13:08:58

标签: unity3d shader cg shaderlab

我有一个着色器功能,其功能类似于"颜色渐变" Blender3D中的节点。它将一个浮点值设置为零和一,并输出一个颜色,该颜色是指定顺序中任意数量颜色的混合:

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. 在函数中声明了颜色数组,这意味着必须为每个片段创建一个新数组(我认为)。
  4. 我的主要问题是第一个问题:如何在不必编辑硬编码值的情况下更改渐变中的颜色数量?

3 个答案:

答案 0 :(得分:1)

Brice是对的。我可以立即告诉您-从来没有人将这种类型的渐变用于着色器,仅仅是因为与仅使用1x128px的颜色渐变纹理相比,它实际上没有任何优势。使用这样的查找纹理:

fixed4 col = tex2D(_MainTex, i.uv); // Sample the input texture
half lum = dot(col.rgb, fixed3(0.3, 0.59, 0.11)); // Color to luminosity
col = tex2D(_LookUpTex, float2(lum, 0)); // Get value from color ramp

如果要为用户创建方便的检查器,只需从渐变生成查找纹理,然后通过OnValidate()中的脚本将其分配给着色器。仅通过为0和127之间的每个x评估x / 127.0处的梯度来生成一个梯度是很简单的。Unity有一个特殊的Gradient类,当您暴露它时,它会在检查器中为您提供一个梯度编辑器。

答案 1 :(得分:0)

  1. 这是不可能的。 Shader会自动编译。并且编译器不支持循环。你的周期只是语法糖,在编译时它会扩展到确定的迭代次数。
  2. 如果/其他表现并不糟糕。它仅对测试有害,因为它会增加圈复杂度。
  3. 您可以在&#34; Property&#34;中声明数组。块。
  4. 很抱歉,但是你没有在属性块中使用数组。您将在方法之外声明它。

    @RequestMapping(value = {"/api/editPane"}, method = RequestMethod.POST)
    @CrossOrigin(origins = {"*"})
    public ResponseEntity<?> editpane(@RequestBody EditPane editPane) {
      //doSuff();
    }
    

    但是你必须从unity scritpt初始化外部数组。

    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;
    }
    

答案 2 :(得分:0)

简单的答案是:将渐变烘焙成纹理