I'm looking to compute texel references for a THREE.DataTexture in Javascript for use in a fragment shader. I've succeeded in computing screen space coordinates of points and passing them to a shader in a uniform float array of x and y values, and then referencing those points by indices in my shader. I now want to render too many points to pass the coordinates in a uniform float array so I'd like to use a DataTexture and write the coordinates in the RG values of RGBA texels.
Referencing this question I am using the following method:
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);
}
Any help on where I'm going wrong? Right now output is all in the lower left corner, so (0, window.innerHeight) as far as I can tell. Thanks!
So the answer is actually straightforward. In the fragment shader rgba values are 0.0 - 1.0, so there's no need to divide by 255 as I was doing in the fragment shader.
I'd also like to say that I discovered the Spector.js Chrome extension which allows one to view all webgl calls and buffers. Pretty cool!
If anyone wants to learn more about how the drawing functions work in the fragment shader, it's all in this awesome shader which I did not write:
https://www.shadertoy.com/view/4dfXDn
<3