【问题标题】:How can I draw surface normals in OpenGL?如何在 OpenGL 中绘制表面法线?
【发布时间】:2017-01-10 08:20:43
【问题描述】:

我有一个全是浮点数的顶点格式,看起来像这样:

POSITION  POSITION  POSITION  NORMAL  NORMAL  NORMAL  TEXCOORD TEXCOORD

我在想我需要从前三个浮点数画线到接下来的三个浮点数,然后我需要跳过接下来的两个浮点数并继续。有没有办法在不为每个布局正确的对象创建另一个缓冲区的情况下做到这一点?

我知道我每次绘制调用只能绘制一条线,然后循环,但那是很多绘制调用?为调试之类的东西绘制法线的一般方式是什么?

我也考虑过索引,但索引只有助于选择特定的顶点,在这种情况下,我想在我的正常顶点布局的两个属性之间进行绘制。

【问题讨论】:

    标签: opengl graphics


    【解决方案1】:

    这不能仅通过设置适当的glVertexAttribPointer 来完成,因为您必须跳过 texcoords。此外,您不想画一条从positionnormal 的线,而是从positionposition + normal,因为法线只描述一个方向,而不是空间中的一个点。

    您可以做的是使用几何着色器。基本上,您设置了两个属性,一个用于位置,一个用于正常(就像渲染模型一样)并发出带有GL_POINTS 原始类型的绘制命令。然后在几何着色器中生成一条从positionposition + normal 的线。

    【讨论】:

    • 是的,我意识到了正常+位置的问题。好的,我以前从未做过几何着色器,我会研究一下。谢谢。编辑:我刚刚意识到,您的方法是否在每次正常绘制时都会发出绘制调用?
    【解决方案2】:

    通常要绘制表面法线,您需要设置一个单独的缓冲区或几何着色器来完成这项工作。为网格设置单独的缓冲区以仅绘制法线是微不足道的,并且不需要为每个法线调用绘制调用,所有表面法线都将在单个绘制调用中绘制

    由于您将这样做是为了调试,因此无需过多担心性能,只需坚持使用更快的方法即可将内容显示在屏幕上

    我个人的做法取决于网格是否具有顶点法线或面法线,例如,我们可以为网格中的每个顶点填充一条线,其与顶点本身的偏移量代表您需要的法线使用以下伪代码进行调试

    var normal_buffer = [];
    
    //tweak to your liking
    var normal_length = 10.0; 
    
    //this assumes your mesh has 2 arrays of the same length
    //containing structs of vertices and normals
    for(var i = 0; i < mesh.vertices.length; i++)  {
        //retrieving the normal associated with this vertex
        var nx = mesh.normals[i].x;
        var ny = mesh.normals[i].y;
        var nz = mesh.normals[i].z;
    
        //retrieving the vertex itself, it'll be the first point of our line
        var v1x = mesh.vertices[i].x;
        var v1y = mesh.vertices[i].y;
        var v1z = mesh.vertices[i].z;
    
        //second point of our line representing the normal direction
        var v2x = v1x + nx * normal_length;
        var v2y = v1y + ny * normal_length;
        var v2z = v1z + nz * normal_length;
    
        buffer.push(v1x, v1y, v1z, v2x, v2y, v2z);
    }
    

    您可以稍后照常进行并将缓冲区附加到顶点缓冲区对象并使用您喜欢的任何程序发出一个绘制调用来绘制所有网格法线

    vertbuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertbuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(buffer), gl.STATIC_DRAW);
    
    /* later on in your program */
    
    gl.drawArrays(gl.LINES, 0, buffer.length / 3);
    

    法线调试的一个很酷的功能是您可以在片段着色器中使用法线本身作为输出颜色来快速检查它是否指向预期的方向

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-30
      • 2014-04-07
      • 2012-06-11
      • 2021-11-01
      相关资源
      最近更新 更多