在 ThreeJS DataTexture 中寻址 Texel

Addressing Texel in ThreeJS DataTexture

我正在为 Javascript 中的 THREE.DataTexture 计算纹素引用,以便在片段着色器中使用。我已经成功地计算了点的屏幕 space 坐标,并将它们传递给 x 和 y 值的统一浮点数组中的着色器,然后在我的着色器中通过索引引用这些点。我现在想渲染太多点以在统一浮点数组中传递坐标,所以我想使用 DataTexture 并将坐标写入 RGBA 纹素的 RG 值中。

我正在使用以下方法:

var tDataWidth = points.length;
var tData = new Uint8Array( Math.pow(tDataWidth, 2) );

var texelSize = 1.0 / tDataWidth;
var texelOffset = new THREE.Vector2(0.5 * texelSize, 0.5 * texelSize);

for(var i = 0; i < points.length; i++){

    //convert data to 0-1, then to 0-255
    //inverse is to divide by 255 then multiply by width, height respectively

    tData[i * 4] = Math.round(255 * (points[i].x / window.innerWidth));
    tData[i * 4 + 1] = Math.round(255 * ((window.innerHeight - points[i].y) / window.innerHeight));
    tData[i * 4 + 2] = 0;
    tData[i * 4 + 3] = 0;

    //calculate UV texel coordinates here
    //Correct after edit
    var u = ((i % tDataWidth) / tDataWidth) + texelOffset;
    var v = (Math.floor(i / tDataWidth) + texelOffset);
    var vUV = new THREE.Vector2(u, v);
    //this function inserts the reference to the texel at the index into the shader
    //referenced in the frag shader:
    //cvec = texture2D(tData, index);
    shaderInsert += ShaderInsert(vUV, screenPos.x, window.innerHeight - screenPos.y);

}
var dTexture = new THREE.DataTexture( sdfUItData, tDataWidth, tDataWidth, THREE.RGBAFormat, THREE.UnsignedByteType );
//I think this is necessary
dTexture.magFilter = THREE.NearestFilter;
dTexture.needsUpdate = true;

//update uniforms of shader to get this DataTexture
renderer.getUniforms("circles")["tData"].value = dTexture;

//return string insert of circle
//I'm editing the shader through javascript then recompiling it
//There's more to it in the calling function, but this is the relevant part I think

    ...

ShaderInsert(index){
     var circle = "\n\tvIndex = vec2(" + String(index.x) + ", " + String(index.y) + ");\n";
     circle += "\tcvec = texture2D(tData, vIndex);\n";
     circle += "\tcpos = vec2( (cvec.r / 255.0) * resolution.x, (cvec.y / 255.0) * resolution.y);\n";
     circle += "\tc = circleDist(translate(p, cpos), 7.0);\n";
     circle += "\tm = merge(m, c);";
     return(circle);    
}

对我出错的地方有帮助吗?现在输出都在左下角,所以 (0, window.innerHeight) 据我所知。谢谢!

所以答案其实很简单。在片段着色器中,rgba 值是 0.0 - 1.0,所以不需要像我在片段着色器中那样除以 255。

我还想说我发现了 Spector.js Chrome 扩展,它允许查看所有 webgl 调用和缓冲区。很酷!

如果有人想了解有关片段着色器中绘图函数如何工作的更多信息,都在我没有写的这个很棒的着色器中:

https://www.shadertoy.com/view/4dfXDn

<3