当前位置: 首页 > 知识库问答 >
问题:

统一-如何重新着色单个面的纹理网格?

李良策
2023-03-14

我有一个纹理网格,它有一个特定的三角形列表,这些三角形对应于网格上的面,在运行时使用如下代码重新着色:

        _mesh = GetComponent<MeshFilter>().mesh;
        ...
        var colors = _mesh.colors;
        foreach (int n in trianglesIndexList)
        {
            colors[n] = Color.blue;
        }
        _mesh.colors = colors;

它的工作很好,但我原本打算这些脸是一个明亮的蓝色。不幸的是,着色似乎与我在Unity中分配给网格的材质纹理混合在一起。在这里你可以看到纹理上的绿草和看起来相当绿的“蓝”混在一起:

我试过玩灯光,但这似乎不是问题。我得到的网格着色需要使用特定的着色器,所以我为网格分配了particle/Standard surface着色器。

有没有办法在运行时对纹理的子部分重新着色,并使这些面看起来亮蓝色?

共有1个答案

楚昀
2023-03-14

好的,没关系,我找到了自己的解决方案,在大约3个小时内学习着色器代码是如何工作的,并编写了一个自定义着色器。简单地使用Unity的默认标准着色器作为起点,添加worldNormal和worldPos输入,如下所示:

struct Input
{
   float2 uv_MainTex;
   float3 worldNormal;
   float3 worldPos;
};

然后,在冲浪函数中,您可以过滤到只是朝上的法线(这是我在本例中想要的),并通过世界空间坐标再次过滤这些网格坐标。

void surf(Input IN, inout SurfaceOutputStandard o)
                {
                float2 UV;
                fixed4 c;

                if (abs(IN.worldNormal.x) > 0.5)
                {
                    // normals facing the left and right side
                    UV = IN.worldPos.yz; 
                    c = tex2D(_MainTex, IN.uv_MainTex);
                }
                else if (abs(IN.worldNormal.z) > 0.5)
                {
                    // normals facing forward and backward
                    UV = IN.worldPos.xy; 
                    c = tex2D(_MainTex, IN.uv_MainTex);
                }
                else
                {
                    // normals facing up and down
                    if (abs(IN.worldPos.x) > 0.5)
                    {
                        UV = IN.worldPos.xz;
                        // COLOR IT BLUE
                        c = tex2D(_MainTex, IN.uv_MainTex) + (_Color * _SinTime.y);
                    }
                    else
                    {
                        UV = IN.worldPos.xz;
                        c = tex2D(_MainTex, IN.uv_MainTex);
                    }
                }

显然可以简化这一点,但这是我想知道的全部怎么做。我甚至想出了如何使用内置的SinTime变量随时间重新着色。超级容易。

 类似资料:
  • 他们没有提到的是如何首先将两个纹理传递给着色器。 以前我 所以现在我 如何将大小不同的纹理数组传递给GLSL? 将多个纹理从OpenGL传递到GLSL着色器 GLSL中的多个纹理-只有一个有效 (这是家庭作业,所以请用最少的代码片段回答(如果有的话)。谢谢!) 如果做不到这一点,有人有茶具吗?

  • 如何在平面上滚动纹理?所以我有一个平面有一个纹理,我可以使用一个着色器滚动左从右(无限)的纹理上?

  • 标准着色器 Unity 标准着色器是一个内置着色器,具有非常全面的功能。它可以用于渲染『真实世界』的对象,例如,石头、木材、玻璃、塑料和金属,并支持各种各样的着色器类型和组合。通过使用或不使用材质编辑器中的各种纹理插槽和参数,可以很容易地启动或禁用其功能。 标准着色器还包括一个称为 物理着色器(Physically Based Shading,PBS) 的高级光照模型。物理着色器以模拟真实世界的方

  • 我试图在OpenGL中制作一个场景,从太空模拟地球。我现在有两个球体,一个用于地球,另一个稍大一些用于云层。地球和云球体对象都有自己的着色器程序来保持简单。地球着色器程序采用4种纹理(白天、夜晚、specmap和normalmap),而云着色器程序采用2种纹理(cloudmap和normalmap)。我有一个对象类,它有一个渲染函数,在该函数中我使用以下逻辑: 它从第0个纹理单元开始,从GL_TE

  • 我正在学习opengl,我认为我非常了解片段着色器。我的直觉是片段着色器应用于每个像素一次,但最近在处理纹理时,我对它们的确切工作方式感到困惑。 首先,片段着色器通常会获取一系列纹理坐标,因此如果我有一个四边形,片段着色器将获取四边形的4个角的纹理坐标。现在我不明白的是采样过程,即获取纹理坐标并在该纹理坐标处获得适当颜色值的过程。具体来说,由于我只提供4个纹理坐标,opengl如何知道为颜色值采样

  • 我需要处理许多只共享少数纹理的对象。手动定义和加载纹理一个接一个(如SO上的另一篇文章中所述)感觉不太对劲...尤其是因为WebGL中没有语句。 因此,我想将用于顶点的纹理作为顶点属性传递,并将该数字用作fragement着色器中某些“纹理数组”的索引。但是采样器上的OpenGL wiki(不是WebGL的完美参考,但我找到的那个)说: 取样器的变量只能用两种方式之一来定义。它可以定义为函数参数或