gromiczek gromiczek - 15 days ago 7
Javascript Question

How to dynamically and efficiently generate texture sizes and dimensions

I've fleshed out a loop to dynamically generates texture sizes for each different view I have in a browser-based visualization using shaders. I know the minimum number of pixels I need to pass my values to the shaders; however I need to scale them up to a power of 2 size, and then make sure their x and y dimensions are also powers of two with a 1:1, 2:1, or 1:2 ratio. Right now my loop is infinite, and I suppose I will need to continue to increase the overall pixel count until I reach a size that satisfies my ratio.

My question is: Is there a more efficient or direct way to achieve what I'm trying to do here?

var motifMinBufferSize = 80000;
var bufferSize; // the total number of texels that will be in the computation buffers (must be a power of two)
var dimensions;

function initValues() {

bufferSize = setBufferSize();
dimensions = setPositionsTextureSize();
}

function setBufferSize() {

var buffer = motifMinBufferSize;

// fill out the buffers to a power of two - necessary for the computation textures in the shaders
var powCount = 1;
var powOf2 = 2;
while ( buffer > powOf2 ) {
powOf2 *= 2;
powCount++;
}

while ( buffer < powOf2 ) {
buffer += 1;
}
}

function setPositionsTextureSize() {

var dimensions = {
texWidth : null,
texHeight : null
};
var foundDimensions = false;
var powOf2 = 2;

while (foundDimensions === false) {
var candidateWidth = bufferSize/powOf2;
if ( candidateWidth === powOf2 || candidateWidth/2 === powOf2 || candidateWidth*2 === powOf2 ) {
dimensions.texWidth = candidateWidth;
dimensions.textHeight = powOf2;
foundDimensions = true;
} else {
powOf2 *= 2;
}
}
return dimensions;

}

Answer

Your buffer must contain 2^n elements since both the width and height of the buffer are powers of two. The smallest n that satisfies the requirement of holding at least motifMinBufferSize elements is calculated using logarithms: n = Math.ceil(Math.log2(motifMinBufferSize)).

Let's say height of the buffer is 2^h and the width of the buffer is 2^w. We know that w and h can differ by at most one (due to the restrictions on the ratio of the buffer dimensions). We also know that 2^n = 2^w * 2^h which means n = w + h. Since w and h differ by at most 1, they are both basically half of n. Therefore we can get:

function getBufferDimensions(minBufferSize) {
  var n = Math.ceil(Math.log2(minBufferSize));
  var w = Math.ceil(n / 2);
  var h = n - w;

  return {
    width: Math.pow(2, w),
    height: Math.pow(2, h),
  };
}