WebGL:尽管使用相同的代码,但一切都很模糊

Posted

技术标签:

【中文标题】WebGL:尽管使用相同的代码,但一切都很模糊【英文标题】:WebGL: Everything is blurry despite using same code 【发布时间】:2012-11-06 16:03:27 【问题描述】:

刚开始使用 WebGL,尝试绘制一些基本的线条,甚至不是多边形。我找到了一些示例,将它们复制粘贴到本地并从 Firefox 中运行,它们看起来不错:锐利、清晰的边缘。然后,我创建了自己的项目,重构(糟糕!)示例代码,使用 RequireJS 加载等,示例仍然有效,但现在我的边缘/点/线都是模糊的。就像一些糟糕的抗锯齿设置搞砸了一切。我尝试了所有方法,起初我的代码看起来有些不同(尽管功能相同,恕我直言),然后我进行了更多重构,使其看起来与示例几乎相同,但我仍然看到模糊的线条。

我做错了什么?

示例代码:http://jsfiddle.net/6QCNR/ 示例代码的实时工作版本: http://dl.dropbox.com/u/17612367/OpenGL%20to%20WebGL/figure%202.16%20-%20dot%20plot/index.html

我的版本: http://bernardofanti.azurewebsites.net/

我的重构代码:

main.js(通过 index.html 中的 data-main 属性加载):

define(
[
    "libs/domReady",
    "webglengine",
    "libs/text!../shaders/fragmentShader.glsl",
    "libs/text!../shaders/vertexShader.glsl"
],
function(domReady, GLEngine, fragmentShaderCode, vertexShaderCode)

    domReady(function()
    
        GLEngine.init("graphCanvas");
        GLEngine.initShaders(fragmentShaderCode, vertexShaderCode);

        var geometry = (function()
        
            var res = [];
            var a = document.getElementById("graphCanvas").width / 4.0;
            var b = document.getElementById("graphCanvas").height / 2.0;

            for (var x = 0; x < 4.0; x += 0.005)
            
                var y = Math.exp(-x) * Math.cos(2 * Math.PI * x);
                res.push(x * a, (y + 1) * b, 0);
            

            return res;
        )();

        GLEngine.createBuffers(geometry);
        GLEngine.render();
    );
);

WebGlEngine.js:

define(
[
],
function()

    "use strict";

    // Singleton Pattern through RequireJS
    var gl = null;
    var shaderProgram = null;

    var pMatrix = mat4.create();

    var initGl = function(canvasId)
    
        try 
        
            var canvas = document.getElementById(canvasId);
            //gl = canvas.getContext("experimental-webgl",  antialias: true );
            gl = (function()
            
                var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
                var context = null;
                for (var ii = 0; ii < names.length; ++ii)
                
                    try
                    
                        context = canvas.getContext(names[ii]);
                    
                    catch (e)  
                    if (context)
                    
                        break;
                    
                
                return context;
            )();

            gl.clearColor(0.0, 0.0, 0.0, 1.0);

            gl.viewportWidth = canvas.width;
            gl.viewportHeight = canvas.height;

            mat4.ortho(0, gl.viewportWidth, 0, gl.viewportHeight, -1, 1, pMatrix);
        
        catch (e)
        
        
        if (!gl)
        
            throw("Could not initialise WebGL");
        
    

    var createShader = function(shaderCode, shaderType)
    
        if(shaderType !== "FRAGMENT_SHADER" && shaderType !== "VERTEX_SHADER")
            throw("Invalid shader type");

        var shader = gl.createShader(gl[shaderType]);
        gl.shaderSource(shader, shaderCode);
        gl.compileShader(shader);

        if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
            throw("Bad shader: " + gl.getShaderInfoLog(shader));

        return shader;
    ;

    var initShaders = function(fragmentShaderCode, vertexShaderCode)
    
        shaderProgram = gl.createProgram();

        var fragmentShader = createShader(fragmentShaderCode, "FRAGMENT_SHADER");
        var vertexShader = createShader(vertexShaderCode, "VERTEX_SHADER");

        gl.attachShader(shaderProgram, vertexShader);
        gl.attachShader(shaderProgram, fragmentShader);
        gl.linkProgram(shaderProgram);

        if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
            throw("Could not initialise shaders");

        gl.useProgram(shaderProgram);
        shaderProgram.vertexPositionLoc = gl.getAttribLocation(shaderProgram, "aVertexPosition");
        gl.enableVertexAttribArray(shaderProgram.vertexPositionLoc);
        shaderProgram.pMatrixLoc = gl.getUniformLocation(shaderProgram, "uPMatrix");
    ;

    var geometry = [];
    var vertexBuffer = null;

    var createBuffers = function(vertices)
    
        geometry = vertices;
        vertexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(geometry), gl.STATIC_DRAW);
    ;

    var render = function()
    
        gl.clear(gl.COLOR_BUFFER_BIT);

        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        gl.vertexAttribPointer(shaderProgram.vertexPositionLoc, 3, gl.FLOAT, false, 0, 0);
        gl.uniformMatrix4fv(shaderProgram.pMatrixLoc, 0, pMatrix);

        gl.drawArrays(gl.POINTS, 0, geometry.length / 3);
    ;

    return 
        init: initGl,
        initShaders: initShaders,
        createBuffers: createBuffers,
        render: render,
        GL: function()
        
            return gl;
        
    ;
);

【问题讨论】:

【参考方案1】:

问题是不是与您发布的 Javascript 代码有关,而是与Canvas 元素有关。

与通常的html 元素相反,Canvas 元素需要widthheight 属性并将其用作逻辑大小。

您设置的CSS 宽度和高度只会拉伸结果,这就是您看到模糊的原因。

关于这个问题可以找到更详细的解释:Canvas width and height in HTML5

【讨论】:

哇。那让我发疯了-感谢您的解决方案!我猜应该阅读画布规范。 精彩的评论,这个问题快把我逼疯了。

以上是关于WebGL:尽管使用相同的代码,但一切都很模糊的主要内容,如果未能解决你的问题,请参考以下文章

尽管一切都是高分辨率和未压缩的,但 Unity 纹理仍然模糊

为啥它一直向我返回“IndentationError:意外缩进”,当我在终端中输入相同的代码时一切都很好?

webgl智慧楼宇发光效果算法系列之高斯模糊

尽管在 Java 代码中使用了 lock(),但两个线程使用相同的方法?

尽管代码相同,但切换菜单按钮在索引页面上有效,但在其他页面上无效 - 为啥?

调试执行冒险