I have a bitmap that I want to draw zoomed in and with straight, defined edges between pixels.
I have tried setting the MAG filter to NEAREST:
gl.bindTexture(gl.TEXTURE_2D,this.tex);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST);
...
gl.drawArrays(gl.TRIANGLES,0,6); // draw the texture
However, when I draw it the pixels bleed together:
This is webGL so I have shaders. My shader code is super-simple:
Vertex shader:
...
attribute vec2 texCoord;
varying vec2 texel;
void main() {
texel = texCoord;
...
And fragment shader:
...
varying vec2 texel;
uniform sampler2D texture;
void main() {
vec4 fragColour = texture2D(texture,texel);
...
Here's a larger snippet of the relative code:
map = {
vbo: gl.createBuffer(),
tex: gl.createTexture(),
program: createProgram(
"precision mediump float;\n"+
"uniform mat4 mvMatrix, pMatrix;\n"+
"attribute vec3 vertex;\n"+
"attribute vec2 texCoord;\n"+
"varying vec2 texel;\n"+
"void main() {\n"+
" texel = texCoord;\n"+
" gl_Position = pMatrix * mvMatrix * vec4(vertex,1.0);\n"+
"}\n",
"precision mediump float;\n"+
"uniform vec4 colour;\n"+
"uniform float fogDensity;\n"+
"uniform vec4 fogColour;\n"+
"varying vec2 texel;\n"+
"uniform sampler2D texture;\n"+
"const float LOG2 = 1.442695;\n"+
"void main() {\n"+
" float z = gl_FragCoord.z / gl_FragCoord.w;\n"+
" float fogFactor = exp2(-fogDensity*fogDensity*z*z*LOG2);\n"+
" fogFactor = clamp(fogFactor,0.0,1.0);\n"+
" vec4 fragColour = texture2D(texture,texel) * colour;\n"+
" gl_FragColor = mix(fogColour,fragColour,fogFactor);\n"+
"}\n",
["mvMatrix","pMatrix","colour","fogDensity","fogColour","texture"],
["vertex","texCoord"]),
plane: [[0,0,0],[0,1,0]],
init: function(w,h) {
this.w = w;
this.h = h;
var vertices = [
w,0,0, 1,0,
0,0,0, 0,0,
w,0,h, 1,1,
w,0,h, 1,1,
0,0,0, 0,0,
0,0,h, 0,1,
];
gl.bindBuffer(gl.ARRAY_BUFFER,this.vbo);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(vertices),gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER,null);
this._mapArrayBuffer = new ArrayBuffer(w*h*4);
this._mapByteBuffer = new Uint8Array(this._mapArrayBuffer);
this.map = new Uint32Array(this._mapArrayBuffer);
for(var i=0; i<w*h; i++) // test data: red and green pixels
this.map[i] = Math.random()>0.5? 0xff000080: 0xff008000;
createTexture(this.tex,w,h,this._mapByteBuffer,true);
},
draw: function() {
var program = this.program;
gl.useProgram(program);
gl.uniformMatrix4fv(program.pMatrix,false,camera.pMatrix);
gl.uniformMatrix4fv(program.mvMatrix,false,camera.mvMatrix);
gl.uniform4f(program.colour,1,1,1,1);
gl.uniform4f(program.fogColour,1,1,1,1);
gl.uniform1f(program.fogDensity,0.03);
gl.bindTexture(gl.TEXTURE_2D,this.tex);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST);
gl.bindBuffer(gl.ARRAY_BUFFER,this.vbo);
gl.enableVertexAttribArray(program.vertex);
gl.vertexAttribPointer(program.vertex,3,gl.FLOAT,false,5*4,0);
gl.enableVertexAttribArray(program.texCoord);
gl.vertexAttribPointer(program.texCoord,2,gl.FLOAT,false,5*4,3*4);
gl.drawArrays(gl.TRIANGLES,0,6);
gl.disableVertexAttribArray(program.texCoord);
gl.disableVertexAttribArray(program.vertex);
gl.bindBuffer(gl.ARRAY_BUFFER,null);
gl.bindTexture(gl.TEXTURE_2D,null);
gl.useProgram(null);
},
};
function createTexture(tex,width,height,data,noMipMap) {
tex = tex || gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D,tex);
tex.width = width || data.width;
tex.height = height || data.height;
if(width != null)
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,width,height,0,gl.RGBA,gl.UNSIGNED_BYTE,data || null);
else
gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,data);
if(anisotropy)
gl.texParameterf(gl.TEXTURE_2D,anisotropic.TEXTURE_MAX_ANISOTROPY_EXT,anisotropy);
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.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR);
if(!noMipMap && !(tex.width&(tex.width-1)) && !(tex.height&(tex.height-1))) { //pow2
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR_MIPMAP_LINEAR);
gl.generateMipmap(gl.TEXTURE_2D);
} else
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR);
gl.bindTexture(gl.TEXTURE_2D,null);
_textures.push(tex);
return tex;
}
[SOLVED] The problem was that I was enabling anisotropy for the texture. Anisotropy trumps gl_NEAREST, it seems. If you want to use gl_NEAREST on a texture, its important to not also have anisotropy set.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With