我试图将一个顶点数组存储在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中的纹理大小仅限于两个数字的幂。顶点的数量也应该是可变的,因为我计划在场景中渲染多个模型。
对于正确使用ArrayBuffer
,Float32Array
和texImage2D()
命令来解决我将顶点发送到WebGL中的片段着色器的问题,我将不胜感激。
答案 0 :(得分:1)
我想我找到了解决问题的方法:
首先我们需要计算拟合纹理宽度
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);
生成的纹理现在包含我的顶点数组,看起来像这样
我愿意接受对此解决方案的评论或评论,随时可以通过代码简化或其他方法做出贡献。
答案 1 :(得分:-2)
如果你不喜欢缓冲,那么你应该从Learning WebGL开始(其他人都在这里)。
纹理是存储顶点数据的一个坏主意,因为每个颜色值只存储一个字节,你肯定希望顶点至少有一些float32。无论如何,你的尝试都是针对着色器属性和点绘图的。