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