graphics - 绘制像素化的纹理

标签 graphics webgl

我有一个位图,我想放大并在像素之间绘制直的、定义的边缘。

我尝试将 MAG 过滤器设置为 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

但是,当我绘制它时,像素会一起流血:

enter image description here

这是 webGL,所以我有着色器。我的着色器代码非常简单:

顶点着色器:
...
attribute vec2 texCoord;
varying vec2 texel;
void main() {
    texel = texCoord;
    ...

和片段着色器:
...
varying vec2 texel;
uniform sampler2D texture;
void main() {
    vec4 fragColour = texture2D(texture,texel);
    ...

这是相关代码的较大片段:
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;
}

最佳答案

[已解决] 问题是我为纹理启用了各向异性。似乎各向异性胜过 gl_NEAREST。如果您想在纹理上使用 gl_NEAREST,重要的是不要设置各向异性。

关于graphics - 绘制像素化的纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15428153/

相关文章:

android - 如何判断闭合路径是否包含给定点?

android - 创建透视(android)应用程序图标

c++ - 朗伯阴影和阴影(光线追踪)的问题

javascript - 如何将多个参数发送到 WebGL 上的顶点着色器?

graphics - 英国广播公司基本 : Cannot plot rectangle on screen

algorithm - 在不计算凸包本身的情况下查找点是否在一组点的凸包内

javascript - 使用 Javascript、WebGL 和 HTML 绘制正方形

glsl - WebGL 逆 FFT 实现

javascript - WebGL矩阵(mat4)符号是否对应于数学矩阵符号

javascript - 球体对象的 three.js 外发光?