【问题标题】:How to eliminate texture seams from mipmapping如何从 mipmapping 中消除纹理接缝
【发布时间】:2013-01-23 19:15:45
【问题描述】:

我在地形的片段着色器中使用纹理混合来从一个纹理混合到下一个纹理。就在仅使用我的草纹理和混合泥土/草或雪/草纹理之间的接缝处,mipmap 似乎造成了丑陋的接缝(见下图)。禁用 mipmapping 可以解决问题,但会使我的地形在远处变得非常粗糙/难看。有没有办法在不禁用 mipmapping 的情况下消除这种接缝?


地形-vs.glsl:

precision mediump float;

attribute vec3 Position;
attribute vec2 TextureCoord;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;

varying vec2 texCoord;
varying float y;

void main(void) {
  gl_Position = uPMatrix * uMVMatrix * vec4(Position, 1.0);
  texCoord = TextureCoord;
  y = Position.y;
}

地形-fs.glsl:

precision mediump float;

uniform sampler2D dirt_texture;
uniform sampler2D grass_texture;
uniform sampler2D snow_texture;

varying vec2 texCoord;
varying float y;

void main(void) {
  if (y < -5.0) {
    gl_FragColor = texture2D(dirt_texture, texCoord);
  } else if (y < 0.0) {
    gl_FragColor = mix(
      texture2D(dirt_texture, texCoord),
      texture2D(grass_texture, texCoord),
      (y + 5.0) / 5.0
    );
  } else if (y < 3.0) {
    gl_FragColor = texture2D(grass_texture, texCoord);
  } else if (y < 5.0) {
    gl_FragColor = mix(
      texture2D(grass_texture, texCoord),
      texture2D(snow_texture, texCoord),
      (y - 3.0) / 2.0
    );
  } else {
    gl_FragColor = texture2D(snow_texture, texCoord);
  }
}

TextureManager::初始化

gl.bindTexture(gl.TEXTURE_2D, texture.texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.generateMipmap(gl.TEXTURE_2D);
gl.bindTexture(gl.TEXTURE_2D, null);

配置:

  • Windows 7 专业版 SP1
  • 谷歌浏览器 24.0.1312.57 m
  • NVIDIA GTX 680

普通视图

放大

【问题讨论】:

  • 我不知道究竟是什么导致了这种情况。不确定它如何与 mipmap 相关,因为 mips 本身看起来不错。只是一个随机的想法-您可以尝试在main 的开头对所有纹理进行采样,并在以下if 中使用已经采样的颜色...而且您可能会发现TEXTURE_MIP_FILTER 的一些用途
  • 你也可以发布你的顶点svarer吗?您是否使用 glGenerateMipmap 生成了您的 mipmap?我也觉得很奇怪你使用 CLAMP_TO_EDGE 作为重复纹理......
  • @ArneBergeneFossaa:正如您在我的纹理加载代码中看到的,我使用gl.generateMipmap 来生成我的mipmap。我已经为地形添加了我的顶点着色器。添加/删除 CLAMP_TO_EDGE 似乎没有任何区别,因为我的纹理坐标永远不会高于 1.0 或低于 0.0。

标签: opengl-es webgl textures mipmaps


【解决方案1】:

解释原始片段着色器产生伪影的原因

GPU 需要知道梯度才能对纹理进行采样。您要么显式提供渐变(textureGrad),要么让 GPU 为您计算渐变。使用局部差分计算自动计算的梯度。详见函数 dFdx (http://www.opengl.org/sdk/docs/manglsl/xhtml/dFdx.xml)。

当函数计算一个像素而不是附近像素(非统一控制流)时,计算导数会产生未定义的结果。

答案 1 中的着色器效果很好,因为纹理总是被采样,无论是否使用它们的结果。

更多信息在这里http://www.opengl.org/wiki/Sampler_(GLSL)#Non-uniform_flow_control

【讨论】:

  • 所以它们被采样是因为我将它们全部传递给 texture2D?那么我应该总是这样做吗,或者是否有一段时间我不想对我的所有纹理进行采样?究竟什么是渐变?我会接受你的回答,但如果能得到上述问题的答案,那就太好了!谢谢!
  • 此上下文中的梯度(或派生)表示纹理坐标在一个像素上的变化速度。然后将其用于计算缩放因子和 mipmap 级别。请参阅 OpenGL 规范。 opengl.org/registry/doc/glspec43.core.20130214.pdf 第 8.14.1 章
  • 如果你真的想在非统一控制流中采样纹理,那么在 main() 的顶部计算梯度并将其传递给纹理函数。 vec2 dx = dFdx(texCoord); vec2 dy = dFdy(texCoord); 然后用textureGrad(dirt_texture, texCoord, dx, dy); 代替texture2D(dirt_texture, texCoord);
  • 我已经花了 30 个小时在我的 2D 平铺引擎中寻找伪影……原来是微积分的错?讨厌!不过说真的,这解释了为什么只有我的带有大量空白的纹理会出现故障。 (我认为)
【解决方案2】:

据我所知,以下片段着色器与我上面提供的基本相同,但显然当为a 传入的参数接近 1.0 或 0.0 时,mix 会做一些时髦的事情。不使用混合并手动混合着色器似乎可以解决此问题。


更新片段着色器:

precision mediump float;

uniform sampler2D dirt_texture;
uniform sampler2D grass_texture;
uniform sampler2D snow_texture;

varying vec2 texCoord;
varying float y;
void main(void) {
  vec4 dirt = texture2D(dirt_texture, texCoord);
  vec4 grass = texture2D(grass_texture, texCoord);
  vec4 snow = texture2D(snow_texture, texCoord);
  float dirt_weight = 0.0;
  float grass_weight = 0.0;
  float snow_weight = 0.0;
  if (y < -5.0) {
    dirt_weight = 1.0;
  } else if (y < 0.0) {
    grass_weight = (y + 5.0) / 5.0;
    dirt_weight = 1.0 - grass_weight;
  } else if (y < 3.0) {
    grass_weight = 1.0;
  } else if (y < 5.0) {
    snow_weight = (y - 3.0) / 2.0;
    grass_weight = 1.0 - snow_weight;
  } else {
    snow_weight = 1.0;
  }
  gl_FragColor = dirt * dirt_weight + grass * grass_weight + snow * snow_weight;
}

【讨论】:

    猜你喜欢
    • 2017-08-04
    • 2012-06-25
    • 2014-09-17
    • 1970-01-01
    • 2019-01-29
    • 2023-03-19
    • 1970-01-01
    • 2011-04-22
    • 2018-10-17
    相关资源
    最近更新 更多