Opengl es 如何从mipmap中消除纹理接缝

Opengl es 如何从mipmap中消除纹理接缝,opengl-es,webgl,textures,mipmaps,Opengl Es,Webgl,Textures,Mipmaps,我在地形的片段着色器中使用纹理混合,从一个纹理混合到下一个纹理。就在仅使用“我的草”纹理和混合土/草或雪/草纹理之间的接缝处,mipmap似乎造成了难看的接缝(见下图)。禁用mipmapping可以解决问题,但会使我的地形在远处变得非常粗糙/丑陋。有没有办法在不禁用mipmapping的情况下消除此接缝 地形与glsl: precision mediump float; attribute vec3 Position; attribute vec2 TextureCoord; unifor

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


地形与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);
  }
}

配置:

  • Windows 7 Pro SP1
  • 谷歌浏览器24.0.1312.57米
  • 英伟达GTX 680

正常视图

放大

据我所知,下面的片段着色器基本上与我上面提供的相同,但是当为
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;
}
precision mediump float;
均匀的纹理;
纹理均匀;
均匀的二维雪景纹理;
可变矢量2 texCoord;
可变浮动y;
真空总管(真空){
vec4污垢=纹理2D(污垢纹理,texCoord);
vec4草地=纹理2D(草地纹理,texCoord);
vec4雪=纹理2D(雪纹理,texCoord);
浮子重量=0.0;
浮草重量=0.0;
浮雪重量=0.0;
如果(y<-5.0){
污垢重量=1.0;
}否则如果(y<0.0){
草重=(y+5.0)/5.0;
污垢重量=1.0-草重量;
}否则,如果(y<3.0){
草重=1.0;
}否则,如果(y<5.0){
雪重=(y-3.0)/2.0;
草重=1.0-雪重;
}否则{
雪重=1.0;
}
gl_FragColor=泥土*泥土重量+草*草重量+雪*雪重量;
}
解释原始片段着色器产生瑕疵的原因 GPU需要知道渐变以对纹理进行采样。您可以显式地提供渐变(textureGrad),也可以让GPU为您计算渐变。使用局部差分计算自动计算的梯度。有关详细信息,请参见函数dFdx()

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

答案1中的着色器工作良好,因为无论是否使用纹理的结果,纹理都始终进行采样


更多信息在这里

我不知道到底是什么导致了这一现象。不知道它与mipmapping有什么关系,因为mips本身看起来不错。只是一个随机的想法-您是否可以尝试在
main
的开头对所有纹理进行采样,并在以下
中使用已采样的颜色(如果
)。。。此外,你可能会发现一些使用
纹理\u MIP\u过滤器的方法
你也可以发布你的顶点svarer吗?您是否已使用glGenerateMipmap生成mipmap?我也觉得奇怪的是,你在重复纹理中使用钳制到边缘…@ArneBergeneFossaa:正如你在我的纹理加载代码中看到的,我正在使用
gl.generateMipmap
生成我的mipmap。我已经为地形添加了顶点着色器。添加/删除夹具到边缘似乎没有任何区别,因为我的纹理坐标从未超过1.0或低于0.0。所以它们正在采样,因为我将它们全部传递到纹理2D?我应该一直这样做,还是有一段时间我不想对所有的纹理进行采样?梯度到底是什么?我会接受你的回答,但如果能得到以上问题的答案那就太好了!非常感谢。此上下文中的渐变(或派生)表示纹理坐标在一个像素上的变化速度。然后使用该值计算缩放因子和mipmap级别。请参阅OpenGL规范第8.14.1章,如果您确实希望在非均匀控制流中对纹理进行采样,请计算main()顶部的梯度并将其传递给纹理函数<代码>vec2 dx=dFdx(texCoord);vec2dy=dFdy(texCoord)然后使用
textureGrad(污垢纹理、texCoord、dx、dy)而不是
纹理2d(污垢纹理,texCoord)我花了30个小时在我的2D平铺引擎中搜寻工件。。。原来是微积分的错?该死!说真的,这解释了为什么只有我的纹理有大量的空白。(我想)
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;
}