I have a terrain mesh stored in a VBO. The mesh is a grid composed of right triangles. In other words, it looks like a rectilinear grid with diagonals. The width and height of the mesh are known, so it's easy to calculate the vertex indices for a given XY or vice-versa.
The terrain mesh will be editable. My question concerns rebuffering the vertex data when the terrain is edited. I will be able to determine the rectangular region of vertices that are dirtied by any edit operation, so obviously I'd prefer to rebuffer only those and leave the rest alone.
The first thing that comes to mind is glBufferSubData. But I can't come up with a way to lay out my VBO such that glBufferSubData would only affect the dirty vertices. For example, suppose my mesh is 5 x 5 vertices. (It would actually be much larger; this is just an example.) Like this:
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
(Each number in the diagram above represents the vertex's offset from the start of the VBO.)
Suppose the 3 x 3 region in the center needs to be rebuffered. That means I want to hit vertices 6, 7, 8, 11, 12, 13, 16, 17, and 18. So I could call glBufferSubData starting at index 6 and ending at 18:
0 1 2 3 4
5 *6 *7 *8 *9
*10 *11 *12 *13 *14
*15 *16 *17 *18 19
20 21 22 23 24
(In the diagram above, the vertices marked with * are rebuffered.)
Notice that vertices 10, 14, and 15 are not dirty, and yet they get rebuffered, because they're in the range given to glBufferSubData. This strikes me as inefficient. For a large mesh, I'd be rebuffering way more data than I need to in most cases.
Is there a well-known solution to this problem? Should I call glBufferSubData once per row (which would solve the present problem, but would come with its own overhead)? Or is it standard just to buffer the full range and eat the cost of the unnecessary writing?
Also, terrain editing happens sometimes but not often. When it does, it will be animated, so the dirty vertices will have to be updated repeatedly while the animation is occurring. I'm thinking GL_DYNAMIC_DRAW would be good. Does this sound right?
You shall use buffer object mapping. You can access to buffer object as a memory array, indeed accessing sparse vertices. The driver (hopefully) will optimize it for you.
The use of GL_DYNAMIC_DRAW is correct.
Related
I have 2 layers of land use (2006 and 2018) of the Multipolygon type, and a grid of polygons of 100 * 100m of the Polygon type.
These 2 layers are cut on a circle of 10,000 m², are on the Lambert 93, and have a spatial index.
https://zupimages.net/viewer.php?id=20/49/dlkk.png
The 2006 land use layer contains 14,320 entries, the 2018 land cover approximately 13,000, and the grid 31,000.
In each cell of my grid (and in its strict hold), I want to cut out the land use elements, separately for the 2 different dates (to start). For this, I headed to st_intersection :
/* 1 */
select
grille.id as id_carr,
2006 as annee,
code,
st_intersection(occ_2006_test.geom, grille.geom) as geom
from grille, occ_2006_test
where st_intersects(occ_2006_test.geom, grille.geom);
/* 2 */
select
grille.id as id_carr,
2018 as annee,
code,
st_intersection(occ_2018_test.geom, grille.geom) as geom
from grille, occ_2018_test
where st_intersects(occ_2018_test.geom, grille.geom);
The first query, the one on the 2006 layer, lasts 12 seconds and returns 110,000 rows. The second, for some reason, still turns after 10 minutes ....
How to explain this difference in performance? (the link to access my diapers, if ever ... https://drive.google.com/file/d/1RC76v0Dm-iufw_mmA8EGaarO0ZaC4MJw/view?usp=sharing)
Thank you.
So I remember there was an opengl function that you could call to set an index value you could have in your element buffer that would cause opengl to skip over the triangle.
Like if your skip value was -1 you could have 3 triangle, but have one be removed.
Element Buffer Object: 1 2 3 -1 -1 -1 3 2 4
I hope I'm getting my point across. I am having trouble finding the function online.
You cannot merely skip a vertex in the index list. There is primitive restart functionality, which allows a specific index to mean "start a new primitive". But that's different from skipping a vertex.
If you're drawing a GL_TRIANGLES primitive, and you want to change the index list such that certain triangles don't appear, simply repeat the same index 3 times. That will generate a triangle with no area, and since you used the same index, the VS will only need to be invoked once. If you used the same index as the last index of the previous triangle, the VS would not need to be invoked at all for any of the missing triangle's vertices:
1 2 3 3 3 3 3 2 4
Primitive restart is pointless for triangle lists; its main use is to create multiple fans/strips without having to introduce degenerate triangles or new rendering commands.
In 2-d array, there are pixels of bmp files. and its size is width(3*65536) * height(3*65536) of which I scaled.
It's like this.
1 2 3 4
5 6 7 8
9 10 11 12
Between 1 and 2, There are 2 holes as I enlarged the original 2-d array. ( multiply 3 )
I use 1-d array-like access method like this.
array[y* width + x]
index
0 1 2 3 4 5 6 7 8 9...
1 2 3 4 5 6 7 8 9 10 11 12
(this array is actually 2-d array and is scaled by multiplying 3)
now I can patch the hole like this solution.
In double for loop, in the condition (j%3==1)
Image[i*width+j] = Image[i*width+(j-1)]*(1-1/3) + Image[i*width+(j+2)]*(1-2/3)
In another condition ( j%3==2 )
Image[i*width+j] = Image[i*width+(j-2)]*(1-2/3) + Image[i*width+(j+1)]*(1-1/3)
This is the way I know I could patch the holes which is so called "Bilinear Interpolation".
I want to be sure about what I know before implementing this logic into my code. Thanks for reading.
Bi linear interpolation requires either 2 linear interpolation passes (horizontal and vertical) per interpolated pixel (well, some of them only require 1), or requires up to 4 source pixels per interpolated pixel.
Between 1 and 2 there are two holes. Between 1 and 5 there are 2 holes. Between 1 and 6 there are 4 holes. Your code, as written, could only patch holes between 1 and 2, not the other holes correctly.
In addition your division is integer division, and does not do what you want.
Generally you are far better off writing a r=interpolate_between(a,b,x,y) function, that interpolates between a and b at step x out of y. Then test and fix. Now scale your image horizontally using it, and check visually you got it right (especially the edges!)
Now try using it to scale vertically only.
Now do both horizontal, then vertical.
Next, write the bilinear version, which you can test again using the linear version three times (will be within rounding error). Then try to bilinear scale the image, checking visually.
Compare with the two-linear scale. It should differ only by rounding error.
At each of these stages you'll have a single "new" operation that can go wrong, with the previous code already validated.
Writing everything at once will lead to complex bug-ridden code.
I was trying to create an OBJ parser which will read OBJ files and render it using GL_TRIANGLE_STRIP. I know OBJ files behaves as TRIANGLES that's why as I read the faces, I rearrange them into STRIPS.
Example I have faces like this
f 5 1 4
f 5 4 8
f 3 7 8
it will be in this order after I rearrange them minus 1 because OBJ files are 1 based indexes.
f 4 0 3
f 3 0 4
f 0 4 3
f 3 4 7
f 4 7 2
f 2 7 6
f 7 6 7
I send this indices to OpenGL and draw them using glDrawElements but the output I get is wrong. Take a look here for the image.
I based the arrangement on the OpenGL documentation on using GL_TRIANGLE_STRIP and I'm stuck on this step as using GL_TRIANGLES works for me. What would cause the incorrect output?
The .obj file contains indexes suitable for rendering in GL_TRIANGLES mode. You render them in GL_TRIANGLES_STRIP mode. You are completely wrong here. Render them in GL_TRIANGLES mode and be happy.
Rendering the same index data in other mode is almost always incorrect. GL_TRIANGLES mode uses three indices per triangle, while GL_TRIANGLE_STRIP uses one index per triangle on average (it is compressed format). So unless you have compressed your index data in approximately three times, you cannot use your indices to draw as GL_TRIANGLE_STRIP.
See wikipedia article for details. Below you can see result of rendering indices {0, 1, 2, 3, 4, 5, 6} in GL_TRIANGLE_STRIP. Obviously, if you render them in GL_TRIANGLES mode, you'll see only 2 triangles instead of 5.
I'm somewhat new to OpenGL though I'm fairly sure my problem lies in the pixel format being used, or how my texture is being generated...
I'm drawing a texture onto a flat 2D quad using a 16bit RGB5_A1 pixel format, though I don't make use of any alpha at this stage. The problem I'm having is that each pair of horizontal pixel values have been swapped.
That is... if the pixels positions should be in this order (assume 8x2 image)
0 1 2 3
4 5 6 7
they are instead drawn as
1 0 3 2
5 4 7 6
Or, more clearly from this image (below).
Left is what I get... Right is what I should get.
.
The question is... How have I ended up with this? Is there something wrong with the pixel format? Unlikely since the colours all appear correct, and I would expect all kinds of nasty if it were down to endian-ness. Suggestions greatly appreciated.
Update: Turns out the problem was in my source renderer. Interestingly, I've avoided the problem entirely by using 32-bit textures (haven't tried 24-bit at this point).
This may be unrelated, and you have found a workaround, but it could be related to OpenGL unpack alignment. Have you tried with the following call ? To instruct the alignment of every image row to 1 byte (default is 4).
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);