将顶点数据打包到 WebGL 纹理中

5
我希望能够将顶点数组存储在WebGL纹理中,但实际上我并不确定正确的做法。 这样做的目的是将顶点传递给我的片元着色器,并对它们进行光线跟踪处理。
当前,我的JavaScript代码如下:
var a = new ArrayBuffer();
// Model.VerticeMap is an array holding all vertices [x1, y1, z1, x2, y2, z2, ...]
a = Model.VerticeMap;  // array length: 36864
var dataArray = new Float32Array(a);
var vMapTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, vMapTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 2, 2, 0, gl.RGB, gl.FLOAT, dataArray);

当纹理的宽度和高度为2时,我没有任何错误。如果取值更高,将会出现错误“ArrayBufferView not big enough for request”。

我还使用扩展功能 OES_texture_float 来处理纹理中的浮点数。

我必须承认,我不太确定自己在做什么。这多少是一个反复试验的过程,当我用这段代码没有出现任何错误时,我有点高兴了。我的主要想法是将每个顶点的 x、y、z 值作为每个像素的 r、g、b 值存储到纹理中。因此,纹理大小必须等于或大于我的 3D 模型三角形数量。不幸的是,在 WebGL 中,纹理大小被限制为 2 的幂次方。由于我计划在场景中渲染多个模型,因此顶点数也应该是可变的。

对于正确使用 ArrayBufferFloat32ArraytexImage2D() 命令来解决在 WebGL 中将顶点发送到片段着色器的问题,我将感激您提供帮助。

2个回答

2

我想我找到了解决问题的方法:

首先,我们需要计算适合的纹理宽度。

var vMapTexture = gl.createTexture();
var vertexTextureWidth = Math.ceil(Math.sqrt(verticeCount/3));

使用verticeCount表示顶点数组的长度,我们将其除以3以适应像素的RGB组件,取其平方根并向上取整,以确保所有顶点都适合于纹理。纹理的宽度也等于其高度。

接下来,我们创建一个Float32Array数组。

var a = new Float32Array(vertexTextureWidth * vertexTextureWidth * 3);

我将从顶点数组中获取值并填充它。
for(var i = 0; i < (verticeCount); i++){
a[i] = Model.VerticeMap[i];
}

现在将您的纹理设置为活动状态并绑定它:
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, vMapTexture);
gl.uniform1i(gl.getUniformLocation(this.program, "uVertexTexture"), 1);

为了将数据打包到纹理中,我使用以下代码行。
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, vertexTextureWidth, vertexTextureWidth, 0, gl.RGB, gl.FLOAT, a);

我使用RGB格式和FLOAT类型。为了做到这一点,您必须启用OES_texture_float扩展。

最后,添加以下纹理参数:

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

现在生成的纹理包含我的顶点数组,并且看起来像这样:

RGB Vertex Texture

对于这个解决方案,我很乐意听取评论或建议,欢迎用代码简化或其他方法做出贡献。


-3

如果你不喜欢缓冲区,那么你应该从学习WebGL开始(这也是其他人的做法)。

纹理不适合存储顶点数据,因为每个颜色值只能存储一个字节,而你肯定希望至少有一些float32用于你的顶点。而且你的尝试无论如何都会涉及到着色器属性和点绘制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接