在webgl中获取投影曲面的法线
我使用DrawArray(gl.三角形,…)在画布上绘制了一些曲面的顶点。我需要为特定的摄影机视点绘制这些曲面,因此所有3d点都投影到2d中,我使用toDataUrl下载最终图像。以下是下载的图像: 后来我使用gl.readPixels检索everypixel的数据 对于所有边顶点,我有法线的信息。就像我得到2d图像中每个像素的颜色一样,我想得到2d图像中每个像素的法线。因为我只在边顶点上有法线,所以我决定以与渲染上述图像相同的方式渲染法线,并决定使用gl.readpixels。这是行不通的。以下是相关代码: 这是调用drawOverlayTriangeNormals的函数。DrawOverlyTriangles函数(在本文中不可见)用于生成上面所示的图像在webgl中获取投影曲面的法线,webgl,projection,Webgl,Projection,我使用DrawArray(gl.三角形,…)在画布上绘制了一些曲面的顶点。我需要为特定的摄影机视点绘制这些曲面,因此所有3d点都投影到2d中,我使用toDataUrl下载最终图像。以下是下载的图像: 后来我使用gl.readPixels检索everypixel的数据 对于所有边顶点,我有法线的信息。就像我得到2d图像中每个像素的颜色一样,我想得到2d图像中每个像素的法线。因为我只在边顶点上有法线,所以我决定以与渲染上述图像相同的方式渲染法线,并决定使用gl.readpixels。这是行不通的。
//Saving BIM
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.vertexAttrib1f(shaderProgram.aIsDepth, 0.0);
drawOverlayTriangles();
saveBlob('element');
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.vertexAttrib1f(shaderProgram.aIsDepth, 0.0);
drawOverlayTrianglesNormals();
saveBlob('element');
var pixels = new Uint8Array(glCanvas.width*glCanvas.height*4);
gl.readPixels(0, 0, glCanvas.width, glCanvas.height, gl.RGBA, gl.UNSIGNED_BYTE,pixels);
pixels = new Float32Array(pixels.buffer);
}
这是DrawOverlayTriangelSnormals函数:
function drawOverlayTrianglesNormals()
{
if (overlay.numElements <= 0)
return;
//Creating the matrix for normal transform
var normal_matrix = mat4.create();
var u_Normal_Matrix = mat4.create();
mat4.invert(normal_matrix,pMVMatrix);
mat4.transpose(u_Normal_Matrix,normal_matrix);
gl.enable(gl.DEPTH_TEST);
gl.enableVertexAttribArray(shaderProgram.aVertexPosition);
gl.enableVertexAttribArray(shaderProgram.aVertexColor);
gl.enableVertexAttribArray(shaderProgram.aNormal);
gl.vertexAttrib1f(shaderProgram.aIsNormal, 1.0);
//Matrix upload
gl.uniformMatrix4fv(shaderProgram.uMVMatrix, false, pMVMatrix);
gl.uniformMatrix4fv(shaderProgram.uPMatrix, false, perspM);
gl.uniformMatrix4fv(shaderProgram.uNMatrix, false, u_Normal_Matrix);
//Create normals buffer
normals_buffer = gl.createBuffer();
for (var i = 0; i < overlay.numElements; i++) {
// Upload overlay vertices
gl.bindBuffer(gl.ARRAY_BUFFER, overlayVertices[i]);
gl.vertexAttribPointer(shaderProgram.aVertexPosition, 3, gl.FLOAT, false, 0, 0);
// Upload overlay colors
gl.bindBuffer(gl.ARRAY_BUFFER, overlayTriangleColors[i]);
gl.vertexAttribPointer(shaderProgram.aVertexColor, 4, gl.FLOAT, false, 0, 0);
var normal_vertex = [];
//Upload Normals
var normals_element = overlay.elementNormals[i];
for( var j=0; j< overlay.elementNumVertices[i]; j++)
{
var x = normals_element[3*j+0];
var y = normals_element[3*j+1];
var z = normals_element[3*j+2];
var length = Math.sqrt(x*x + y*y + z*z);
normal_vertex[3*j+0] = x/length;
normal_vertex[3*j+1] = y/length;
normal_vertex[3*j+2] = z/length;
}
gl.bindBuffer(gl.ARRAY_BUFFER, normals_buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normal_vertex),gl.STATIC_DRAW);
gl.vertexAttribPointer(shaderProgram.aNormal, 3, gl.FLOAT, false, 0, 0);
// Draw overlay
gl.drawArrays(gl.TRIANGLES, 0, overlay.elementNumVertices[i]);
}
gl.disableVertexAttribArray(shaderProgram.aVertexPosition);
gl.disableVertexAttribArray(shaderProgram.aVertexColor);
gl.vertexAttrib1f(shaderProgram.aisdepth, 0.0);
}
片段着色器:
if (vIsNormal > 0.5)
{
gl_FragColor = vec4(normals.xyz*0.5+0.5,1);
}
}
现在我的输出是相同的灰度图像。我不确定出了什么问题。我觉得这个方法很有道理,但似乎有点迂回。我不完全确定我是否理解您的意图,但似乎您只是希望能够访问法线以计算照明效果,所以让我尝试回答这个问题 不要使用gl.readPixels()!这主要用于点击交互和填充,或者修改少量像素。使用这种方法肯定是非常低效的,因为您必须绘制像素,然后读取它们,然后在计算适当的照明后重新绘制它们。WebGL的奇妙之处在于,它允许您从一开始就执行所有这些操作:片段着色器将插入它提供的信息,以便在两个相邻顶点之间平滑绘制效果 大多数照明都依赖于将曲面法线与灯光方向进行比较(正如您所理解的,从您的一条评论判断)。看 现在,您提到需要所有渲染点的法线,而不仅仅是顶点。但是顶点的法线将与曲面上每个点的法线相同,因此您甚至不需要比顶点法线更多的东西。这是因为WebGL知道如何绘制三角形(我相信),三角形是平面或平面曲面。因为平面上的每个点都有和其他点相同的法线,所以你只需要一条法线就可以知道所有的法线 由于您试图绘制的似乎都是圆柱体和矩形棱柱体,因此指定您创建的对象的法线应该很简单。矩形棱柱体的法线很小,但圆柱体的法线也很小:法线平行于从圆柱体轴到曲面的直线
由于WebGL的片段着色器会插值在相邻顶点之间传递的任何
变化的变量,您可以告诉它在顶点之间平滑插值这些法线,以实现Phong shadin页面中看到的平滑照明!:D我不确定你想做什么,但是如果你想在片段着色器中有一个像素的法线,你可以通过你的顶点着色器用一个variable
变量“赋予”它。我也不太明白。您可以调用“canvas.toDataURL”或gl.readPixels
从画布中获取数据。至于渲染法线,是的,只需将它们从顶点着色器传递到片段着色器,然后使用它们进行渲染,如gl_FragCoord=vec4(法线*0.5+0.5,1)代码>我只需要所有渲染点的法线,而不仅仅是顶点。现在,颜色是通过检查法线并在gl_FragColor中使用它来手动完成的。如果我想要每个像素的法线,我应该渲染一个单独的图像,只使用法线值并使用readPixels吗?我在尝试了上面评论中提到的内容后编辑了我的帖子。我还包括了一些相关的代码
if (vIsNormal > 0.5)
{
gl_FragColor = vec4(normals.xyz*0.5+0.5,1);
}
}