5

我在地形的片段着色器中使用纹理混合来从一个纹理混合到下一个纹理。就在仅使用我的草纹理和混合泥土/草或雪/草纹理之间的接缝处,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);
  }
}

纹理管理器::初始化

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

配置:

  • 视窗 7 专业版 SP1
  • 谷歌浏览器 24.0.1312.57 m
  • 英伟达 GTX 680

正常视图 正常视图

放大 放大

4

2 回答 2

8

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

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

于 2013-02-17T17:25:21.753 回答
0

据我所知,下面的片段着色器与我上面提供的基本相同,但是当传入的参数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;
}
于 2013-02-16T21:49:53.093 回答