如何在OpenGL中绘制曲面法线?

时间:2017-01-10 08:20:43

标签: opengl graphics

我有一个顶点格式,它们都是浮点数,看起来像这样:

POSITION  POSITION  POSITION  NORMAL  NORMAL  NORMAL  TEXCOORD TEXCOORD

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

我知道每次绘制调用我只能绘制一行,并且只是循环,但这是多次绘制调用?对于像调试这样的东西,通常的法线是如何绘制的?

我也想过索引,但索引只能帮助选择特定的顶点,在这种情况下我想在我的普通顶点布局的两个属性之间绘制。

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

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

由于您将进行调试,因此无需过多担心性能,只需坚持使用更快的方法来获取屏幕上的内容

我亲自做的方式取决于网格是否具有顶点或面法线,我们可以为网格中的每个顶点填充一个缓冲区,其中与顶点的偏移代表您需要的法线使用以下伪代码调试

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);

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