在GLSL中混合多个纹理

6

这是一个长篇但有趣的内容。:)

我正在尝试使用jMonkeyEngine来模拟另一个应用程序的纹理外观。我有一组顶点和面(三角形),构成了一个“景观网格”,应该用大约7-15种不同的纹理(取决于“景观”的地形)进行纹理贴图。每个三角形都有一个与之关联的纹理代码,表示该特定三角形应主要由哪个纹理组成。当然,纹理之间应该平滑混合。

因此,我正在尝试开发一种策略,允许这样做(不使用预先制作的alpha map png文件,纹理alphas需要在运行时完成)。现在,我认为如果我在每个顶点处计算每个纹理的“强度”(在顶点着色器中)-通过考虑所有相邻面的地形类型(尚不确定如何实现此目标)-我应该能够根据像素距离顶点的远近设置alpha值。生成的'alpha map'将由frag shader用于每个像素的纹理混合。

这种方法可行吗?还是我应该寻找完全不同的策略?我有要模仿的应用程序的着色器代码(但它们是HLSL,而我正在使用GLSL),但似乎它们在其他地方执行这个混合步骤:

    sampler MeshTextureSampler = sampler_state { Texture = diffuse_texture; AddressU = WRAP; AddressV = WRAP; MinFilter = LINEAR; MagFilter = LINEAR; }; 

我不确定什么是HLSL的"MeshTextureSampler",但是这个应用似乎预先混合了所有所需的纹理,并根据面/地形代码数据为整个网格创建了一个单一的纹理。在像素/片段着色器中,他们真正做的只是这样:

float4 tex_col = tex2D(MeshTextureSampler, In.Tex0);

之后只是阴影、灯光等方面,没有任何纹理混合的痕迹,据我所知,这种纹理混合工作可能在CPU上提前完成。欢迎任何建议。

1个回答

3
如果我理解你的问题正确,我的第一步解决方案如下:
您的问题或多或少是如何将每个面的值分配到顶点上。这实际上类似于网格上的法线生成:首先为每个三角形生成一个法线,然后按顶点计算它们。搜索“法线生成”即可找到相关信息,但以下是要点:对于每个相邻的三角形,找到一个加权因子(通常是使用该顶点的角度或三角形的表面积,或两者的组合),然后将加权因子乘以值(无论是法线还是您的“强度”),并累加到总结果中。标准化即可完成。
然后您就有了纹理“强度”,可以将其发送到顶点着色器。现代解决方案是使用chars并在像素着色器中采样纹理数组,在您微调混合值以获得更好传输之后。
所以,如果我正确理解您的问题:
预处理:
forearch vertex in mesh
  vertexvalue = 0
  normalization = 0
  foreach adjacent triangle of vertex
      angle = calculateAngleBetween3Vertices(vertex,triangle.someothervertex,triangle.theotherothervertex)
      vertexvalue += triangle.value * angle
      normalization += angle
  vertexvalue/=normalization

渲染时间:

将每个顶点的值传递到片元着色器中,并在片元着色器中执行此操作:

basecolour = 0;
foreach value    
   basecolour = mix(basecolour, texture2D(textureSamplerForThisValue,uv), value)
   //this is simple, but we could do better once we have this working

或者,您可以仔细检查几何图形。如果您有大三角形和小三角形的组合,则数据分布不均匀,由于数据是每个顶点的,因此在这里有更多几何图形的地方会有更多的细节。在这种情况下,您可能希望像其他人一样通过使用混合贴图来将纹理与几何图形解耦。这些可以是低分辨率的,并且不应该增加太多内存消耗或着色器执行时间。


我卡住的地方通常是“对于每个相邻的三角形,找到一个权重因子...”——我应该在哪里做这个,如何从着色器内部访问它?仍然很难想象。 - Manius
你不需要这样做。这只是预处理阶段(您的值在渲染时是静态的,对吧?)。每个三角形的权重因子应为1,这是一种质量要求。否则,您可以将其视为触摸顶点的三角形角的角度。然后,在顶点处的值变为FOREACHN值+ = angle_of_triangle*value_at_triange. - El Marcel
我刚想到了一个可能的解决方案,但再次阅读后,我认为这基本上与你建议的相同(真是个巧合)。我考虑尝试传递每个顶点的“加权” alpha 值(每个纹理),并在 frag shader 中将其用作纹理 alpha。(这就是你所说的吗?)我一直很难确定如何在 jMonkeyEngine 中实现这一点,但我希望可以将此数据作为“texCoordX”顶点缓冲区类型的顶点属性传递。(这里有一些 jME 特定的东西。)如果这样可以工作,那么使用面积/角度来计算权重就可能会奏效... - Manius
竞争非常激烈,但你是赢家,我的朋友...这个策略确实有效,但我仍然需要看看是否可以对其进行微调以获得所需的外观,但这个概念是有效的。 - Manius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接