How much data does texImage2D in WebGL need? - javascript

I created a DataTexture in ThreeJS, which in turn will call texImage2D.
var twidth = 50;
var theight = 50;
var tsize = twidth * theight;
var tileData = new Uint8Array( tsize * 3);
//fill it with some data
tileDataTexture = new THREE.DataTexture(this.tileData, twidth, theight, THREE.RGBFormat);
As you can see, I used a size of 50x50 Texels and three 8Bit channels (THREE.RGB in threejs). When I used a UInt8Array of size 7500 (50*50*3), Firefox tells me, that it needs more data:
Error: WebGL: texImage2D: not enough data for operation (need 7598, have 7500)
I would like to know: where do this extra 98 bytes come from? I would guess alignment, but 7598 is not even divisible by 4 while 7500 is. (Now that I think of it, it is not divisible by 3, my number of channels, either)
7600 would make sense, since that would mean 2 Bytes of padding per row, is the last row not padded?
(I get that one should use only multiples of four for the dimensions, still I would like to know the answer)

The row lengths are aligned to multiples of 4, except for the last row. In your case this means each row needs 2 bytes of padding, for a total of 152 bytes (3 * 50 + 2) per row.
152 * (50 - 1) + 3 * 50 = 7598
For reference, see the source code of Gecko.

As user1421750 pointed out the rows are padded
But, you can set how much padding per row by setting texture.unpackAlignment. it defaults to 4 but you can set it to 8, 4, 2 or 1.
Personally I would have made the default 1 because I think you'd be less likely to be surprised like you were

Related

What is the indexing logic in the ImageData array?

This question is for a deeper understanding of my previous question about large size Canvas animation. The question is here: Repeat HTML canvas element (box) to fill whole viewport
I am trying to understand the logic behind the TypedArray - Uint8ClampedArray. I will first start with my research and get to the question itself later.
So, ImageData represents the pixel data of the HTML5 Canvas. It allows for much faster performance and is good for heavy animations. After we have our ImageData object, we create a buffer space for it. Because we can not read & write directly from / to buffer, we pass this buffer to a TypedArray. In this case Uint8ClampedArray which is like a normal array and allows to access data inside it.
Each pixel on our canvas is represented by 4 integer values that stand for red, green, blue, alfa - as in RGBA - ranging from 0 to 255. Each of these value is assigned to an Uint8ClampedArray index starting from 0 and the array is divided into chunks of 4. So first 4 values are very first pixel, second 4 values are 2nd pixel and so on. The Cavnas pixels are being read from left to right, row by row.
So if for example we want to get array index of red value of the pixel at xCoord = 3; yCoord = 1; canvasWidth = 10;. The formula from MDN: Pixel manipulation with canvas suggests that we do the following math:
var red = y * (width * 4) + x * 4; = 1 * 10 * 4 + 3 * 4 = 52;
But if we try to do the same manually, and just calculate ourselves pixel by pixel, we don't get the same value. It's always a little off. How would we calculate manually? In this picture we start from 0 X 0 to 0 X 9 and to 1 X 3. Because we start from top left and move toward right, it's inverted and Y is our first coordinate and X is our second coordinate. From 0 X 0 to 0 X 9 we record 40 values in total (4 values on each pixel, 10 pixels in total width); From 1 X 0 to 1 X 3 we record 16 values in total. We get 56th index at the end, instead of 52 as we had calculated using the formula.
So, please help me understand the whole logic in Uint8ClampedArray and how it's calcualted.
From 1 X 0 to 1 X 3 we record 16 values in total
The last 4 bytes of these 16 do represent the pixel at (3, 1). The red channel is the first of these, preceded by 12 bytes for the pixels to the left and 40 bytes for the pixels in the first row. It is sitting at index 52 in the overall array.
Remember that arrays are indexed as
0 1 2
+---+---+--
| | |
+---+---+--
not as
+---+---+--
| 0 | 1 | 2
+---+---+--

Javascript D3 Histogram: thresholds producing wrong number of bins

I'm in the process of creating a histogram JS script using D3, and it all seems to be working correctly... except for the number of bins.
Following is the relevant part of my code:
//Define the scales for the x and y attributes
var x = d3.scaleBand()
.range([0, width])
.padding(configProperties.barPadding);
var y = d3.scaleLinear()
.range([height,0]);
//Create the bins
var bins = d3.histogram()
.domain(d3.extent(data))
.thresholds(configProperties.binsCount)
(data);
console.log("number of bins: " + bins.length); //9
console.log("intended number of bins: " + configProperties.binsCount); //10
If I set configProperties.binsCount to 9, bins.length is still 9.
If I set configProperties.binsCount to 14, bins.length is still 9.
If I set binsCount to 15 or higher, however... bins.length outputs 23.
My understanding of how histogram.thresholds works based on the documentation is that if I give it a value, it will divide the data into that many + 1 equal segments (i.e. that many bins). However, it doesn't seem to be doing that at all. All of the example code that I could find seemed to indicate that I am using it correctly, but I can't get the number of bins that I need.
I've also tried using d3.ticks as a thresholds argument, but I encounter the same issue.
Is there something I'm missing? Does it have to do with my domain? Thanks in advance.
You are passing a count (that is, a simple number) to the thresholds function, not an array.
What you're seeing is the expected behaviour when you pass a number. According to the same docs:
If a count is specified instead of an array of thresholds, then the domain will be uniformly divided into approximately count bins;
Let's see it in this demo:
var data = d3.range(100);
const histogram = d3.histogram()
.value(d => d)
.thresholds(5);
var bins = histogram(data);
console.log("The number of bins is " + bins.length)
<script src="https://d3js.org/d3.v4.js"></script>
As you can see, count is 5 and the number of bins is also 5.
If you pass an array, however, the behaviour is what you expect: the number of bins will be array.length + 1:
Thresholds are defined as an array of values [x0, x1, …]. Any value less than x0 will be placed in the first bin; any value greater than or equal to x0 but less than x1 will be placed in the second bin; and so on. Thus, the generated histogram will have thresholds.length + 1 bins.
Here is the demo:
var data = d3.range(100);
const histogram = d3.histogram()
.value(d => d)
.thresholds([10, 30, 50, 70, 90]);
var bins = histogram(data);
console.log("The number of bins is " + bins.length)
<script src="https://d3js.org/d3.v4.js"></script>
As you can see, the array has 5 values and the number of bins is 6.
Finally, have in mind that the actual number of bins depends on the data you pass to the histogram generator. That explains the other results you're describing in your question.
I realize this is a little old, and that Gerardo explained how to do what you were asking, but he didn't actually answer the why of the question. So here's that, in case anyone else comes across this question and is curious. If you pass a number to the thresholds function, D3 finds a number of bins that is near to that number, such that the thresholds are 'nice' numbers. And it's the choosing of those 'nice' numbers that results in the number of bins being different than what you specify.
So if your data goes from 0 to 24.37, and you request 8 bins, the thresholds will not be multiples of 3.481428571428... ( = 24.37 / (8-1)). Instead D3 will pick a 'nice' maximum of 25, and the threshold will be multiples of 2.5 (to make 10 bins) or multiples of 5 (to make 5 bins). These numbers are much nicer to display on a graph, and are what a human would probably choose if they were making the histogram by hand.

Javascript divide buffer into golden rectangles

Im using JS in max/Msp and want to slice the buffer into sections using the golden ratio. I know that this will be a recursive function using the formula a+b/a = a/b but im not sure how to express this in javascript and how to then divide the remaining sections into golden rectangles recursively.
The golden ratio of 1.6xx talks about spiraling out, expanding.
If you start with a buffer and want to mark inwards, you can expand it by the reciprocal to shrink.
golden_ratio = ( 1 / 1.61803398875 ) // 0.6180339887498547 of 1.00
//where 1.00 is the 'whole' of your buffer
//the following values are percentage points the slices are at in the buffer
slice_1 = 1.00 * golden_ratio // .618
slice_2 = slice_1 * golden_ratio // .618^2
slice_3 = slice_2 * golden ratio // .618^3
You could calculate a given-depth slice of from an arbitrary buffer in one explicit call:
slicepoint = Math.pow(golden_ratio, slice_depth) * buffer_size
Otherwise manually performing that recursively could be from providing the initial condition (buffer size) and multiplying the last slice you just calculated by the golden ratio again. Our "last slice" would be the first condition provided, whatever buffer you've got.
some pseudocode:
A[0] = buffer_size
while n++
A[n] = A[n-1] * golden_ratio
for actual javascript code:
Slicing 1sec. of audio into 10 buffers (9 slices needed for 10 buffers)
arbitrary_buffer = 44100 //buffer length 1 sec # 44.1kHz
slices = 10; //slice count
// get the reciprocal of golden ratio
// we can just shrink the whole and mark those points as slices
golden_ratio = ( 1 / 1.61803398875 )
// creepily enough
// the reciprocal of the golden ratio is
// its same value without the integer in front of it: .6180339887498547
// so its a 61.80339887498547% of the original size per-iteration
// This is a list of our slice point locations
slice_points = new Array();
// add an initial condition (arbitrary_buffer) for the recursion
// like knowing the end of a loaf of bread before cutting
slice_points[0] = arbitrary_buffer;
// the following recursion is in the [i-1] back-tracking
// that's why this for-loop condition has i at 1 instead of 0 per usual
// we provided the initial 44100 and start with index 1 instead
// slice_point[1] should be about 27255.29890386859
for(i=1;i<slices;i++)
slice_point[i] = slice_points[i-1] * golden_ratio;
The array is populated in descending order starting at its end: 44100
You can switch those values to forward-facing if you just take
arbitrary_buffer - slice_point[i];
or, outside of the js object and back in max use [- ] and subtract the js output value from the buffer ms length from bufferinfo~'s right-most outlet, converted to samples.
You might also try using this as a velocity-map for loudness

Calculating percentage with min-max in Gamemaker

I have a healthbar that i want to use a min/max and actual number.
6 is min
8 is max
the actual number will float between them with 7 as the beginning number.
tried ((max_n + min_n) / act_n)*100, but of course that doesn't work.
i think i was sick that day when they went over that in school (eyeroll)
If you have a floating point value that is (6, 8) and you want the distance between the value and minimum expressed as a different between the maximum -
var min = 6,
max = 8,
current = 7,
difference = max - min,
percent = (current - min) / difference; // <-- is the value you're after
// it is 50% between (6,8)
I'm not sure I understand what you're doing, but I believe you're calculating the average the wrong way.
Shouldn't you have the actual value be divided by the total possible?
Currently, your logic looks like this:
(8 + 6 (14) / Actual (7) )*100, which would be 14/7 = 2 * 100 = 200.
I think you need to reverse these two arguments, the min+max and the actual value.
If it were me, instead of doing it that way, I would actually subtract the minimum amount from both, and then divide it by the difference between the two.
If the 6 and 8 are dynamic, this may look like:
( (act_n - min_n) / (max_n - min_n) )*100
Or, with values, that would be:
( (7.2 - 6) / (8 - 6)*100
(1.2 / 2)*100 = 60, so your percentage would be 60%
I don't use Javascript, so please ignore any spacing errors I made. I don't know how strict the language is.

Text Grouping Algorithm

Given an arbitrary string of text, the task is to group the text into separate sections of a template. Each section has different min length and max length parameters. A solution can be considered optimal for a section as long as it falls within those bounds. A greedy solution might result in some sections not meeting their minimums, which means the solution as a whole is not acceptable.
I'm having trouble efficiently constructing an algorithm to do this. It seems that a dynamic programming approach might help, but thus far, I haven't been able to couch it in dynamic programming terms. Does anyone have any leads on solving this problem?
function groupText(str, template)
Inputs:
str: a string of text
template: array of JavaScript objects.
One object per section that describes the min/max amount of text allowed
Output:
array: each element corresponds to one section.
The value of the element is the text that is in the section.
As an example, let's define a string str that is equal to "This is a test." We also have a template t. t consists of several sections. Each section s has a minimum and maximum amount of characters allowed. Let's say for this example there are only two sections: s1 and s2. s1 has a minimum of 1 character and a maximum of 100. s2 has a minimum of 10 characters and a maximum of 15. We pass our string str and our template t to a function groupText. groupText must return an array, with each element i corresponding to a section. For example, element 0 will correspond to s1. The value of the element will be the text that has been assigned to the section.
In this example, a solution might be.
s1text = "This "
s2text = "is a test."
If I understood the problem correctly there's no need of any search... just subtract from the total length the sum of the minimum lengths and what remains is the amount to be distributed. Then distribute this amount to each element up to its maximum until nothing is left... in code
var minsum = 0;
for (vsr i=0; i < sections.length; i++)
minsum += sections[i].min_size;
var extra = text.length - minsum;
if (extra < 0) return null; // no solution
var solution = [];
for (var i=0; i < sections.length; i++)
{
var x = sections[i].min_size + extra;
if (x > sections[i].max_size)
x = sections[i].max_size;
solution.push(x);
extra -= x - sections[i].min_size;
}
if (extra > 0) return null; // no solution
return solution;
OK, so here's an ad-hoc, untested algorithm. If it's no good, perhaps it's good enough to goad someone else into a better answer;
Let's have some trial data. Suppose your template comprises 6 sections, which have min,max limits as:
1 - 12
13 - 25
5 - 7
6 - 7
5 - 5
10 - 25
which means that you're going to need a string of at least 40 and at most 81 characters to satisfy your constraints. And therein lies the solution. First, compute a table like this:
40 - 81
39 - 69
26 - 34
21 - 37
15 - 30
10 - 25
in which each row gives the total length of string that can still be partitioned across the 'slots' in your template. Into slot 1 you put text so that you still have between 39 and 69 characters left for the rest of the slots. Into slot 2 you put text so that you still have between 26 and 34 characters. And so on.

Categories

Resources