OpenGL Vertex着色器有多强大?可以绘制多少个四边形?

问题描述 投票:1回答:1

我编写了一个演示应用程序来测试顶点着色器的功能,因为据说它可以处理每秒数百万个四边形,但在我的情况下它会在一定限度内失败。

我写了一个演示here,它有一个只接受数字的输入框,它会根据输入的数字动态渲染方块。我可以很容易地看到它在行动中没有任何延迟,直到大约25平方四边形,然后它减慢,在某些时候甚至GPU崩溃,这是更糟糕的。

我们可以优化我编写的代码,还是GPU和OpenGL-ES的限制?

代码:

`

    <script type="vertexShader" id="vertexShader">
    #version 300 es
    in vec3 position;
    in vec4 color;
    out vec4 fcolor;
    void main () {
        gl_Position = vec4(position, 1.0);
        fcolor = color;
    }
</script>

<script type="fragmentShader" id="fragmentShader">
    #version 300 es
    precision mediump float;
    in vec4 fcolor;
    out vec4 finalColor;
    void main () {
        finalColor = vec4(fcolor);
    }
</script>
    var gl, canvas;
    gl = initWebGLCanvas('canvas');
    var program = getProgram('vertexShader', 'fragmentShader', true);
    document.getElementById('numOfGrids').oninput = function () {
        clearCanvas(gl);
        this.value = this.value || 1;
        this.value = this.value >= 0 ? this.value : 0;
        var gridVertices = createGridVerticesBuffer(this.value || 1);
        enableVerticesToPickBinaryDataWithinGPU(program, 'position', 'color');
        fetchDataFromGPUAndRenderToCanvas({
            positionIndex : gl.positionIndex,
            vertices : gridVertices,
            positionSize : 3,
            stride : 7,
            colorIndex : gl.colorIndex,
            colorSize : 4,
            positionoffset : 0,
            colorOffset : 3,
            startIndexToDraw : 0,
            numOfComponents : 6
        }, gl);
    };

        var r = [1.0, 0.0, 0.0, 1.0];
var g = [0.0, 1.0, 0.0, 1.0];
var b = [0.0, 0.0, 1.0, 1.0];
var z = 0.0;

var createGridVerticesBuffer = (gridsRequested) => {
    var vertices = [
        1.0, -1.0, z, r[0], r[1], r[2], r[3],
    -1.0, 1.0, z, g[0], g[1], g[2], g[3],
    -1.0, -1.0, z, b[0], b[1], b[2], b[3],

    1.0, -1.0, z, r[0], r[1], r[2], r[3],
    -1.0, 1.0, z, g[0], g[1], g[2], g[3],
    1.0, 1.0, z, b[0], b[1], b[2], b[3]];

    var vertexArray = [];
    var factor = 2.0/gridsRequested;
    var areaRequired = -1.0 + factor;
    vertices[21] = vertices[0] = areaRequired;
    vertices[15] = vertices[1] = -areaRequired;

    vertices[22] = -areaRequired;
    vertices[35] = areaRequired;
    vertices[36] = vertices[8];
    vertexArray.push(vertices);
    var lastVertices = vertices.slice();
    var processX = true;
    for (var i = 1; i <= gridsRequested * gridsRequested - 1; i++) {
        var arr = lastVertices.slice();
        if (processX) {
            arr[21] = arr[0] = lastVertices[0] + factor;
            arr[28] = arr[7] = lastVertices[35];
            arr[8] = lastVertices[36];
            arr[14] = lastVertices[0];
            arr[15] = lastVertices[1];
            arr[35] = lastVertices[35] + factor;
        } else {
            arr[22] = arr[1] = lastVertices[1] - factor;
            arr[29] = arr[8] = lastVertices[8] - factor;
            arr[15] = lastVertices[15] - factor;
            arr[36] = lastVertices[36] - factor;
        }
        vertexArray.push(arr);
        if ((i + 1) % gridsRequested === 0) {
            lastVertices = vertexArray[i + 1 - gridsRequested];
            processX = false;
        } else {
            processX = true;
            lastVertices = arr;
        }
    }
    return createBuffers(gl, vertexArray, true);

};

`

webgl vertex-shader webgl2
1个回答
0
投票

你问了一个无法回答的问题

可以绘制多少个四边形?

我们在谈论哪种设备?覆盆子PI? iPhone 2?带有NVidia 2080 RTX的Windows PC?什么尺寸四边形?你的片段着色器在做什么?

在任何情况下,您遇到的问题不是顶点着色器问题,它是一个fragement着色器问题。绘制像素需要时间。绘图称1024x1024四边形正在绘制100万像素。绘制一百个1024x1024四边形正在绘制1亿像素。试图每秒做60次就要求绘制60亿像素。

将所有四边形更改为1x1像素,它将运行得很好,因为那时你只要求它每秒绘制6000像素。

这通常被称为填充限制。你只是无法绘制那么多像素。在你的情况下,它也被称为过度透支。通过绘制重叠的四边形,你做的浪费工作比一个像素更多地绘制相同的像素。如果可能,您应该尝试仅绘制一次每个像素。

我猜一般的经验法则是,大多数GPU只能以每秒60帧的速度绘制2到12个全屏四边形。我只是把这个数字从没有位置拉出来,但是例如原始的android GPU只能以60fps的速度绘制1.5个全屏四边形。我认为Raspberry PI可能不到4个。我知道2015年英特尔图形(不确定哪个型号)可以在1280x720处做到7。我的2019 Macbook Air可以做到3(它的分辨率是2560x1600,与1280x720的12个屏幕大致相同)。

至于崩溃,GPU没有崩溃,而是浏览器或操作系统重置GPU,因为它花了太长时间。大多数GPU(截至2019年)不像CPU那样是多任务处理。可以中断CPU并将其切换为执行其他操作。这就是您的PC能够同时运行大量应用程序和服务的方式。大多数GPU都无法做到这一点。他们一次只能做一件事。因此,如果你在一次平局调用中给他们30秒的工作时间,他们将完成30秒的工作而不会中断。这对操作系统没有好处,因为它需要GPU来更新窗口并运行其他应用程序。因此,操作系统(以及一些浏览器)会在每次绘制调用时计时。如果一次绘制调用花费的时间超过一定时间,则会重置GPU并经常杀死要求GPU执行花费太长时间的程序或页面。

至于如何知道什么是太多的工作,你不应该尝试做尽可能多的工作,而应该尽可能少地尝试。您的应用无缘无故地绘制重叠的四边形。

如果你确实需要绘制重叠四边形或进行一些需要很长时间的计算,那么你可能需要找到一种方法将它分解为每次绘制调用的较小操作。每次绘制调用处理5个四元组并使用5个绘制调用而不是25个调用。处理更小的四边形而不是更少的大四边形等...

© www.soinside.com 2019 - 2024. All rights reserved.