How to make low precision texture? - three.js

Does anyone know how to make a WebGL texture which is of lower precision? I want to push quite a lot of values onto the GPU (its tiled 3D data for ray tracing). The volume rendering is animated, so the data is updated each frame. This is currently a bottleneck in the performance.
I'd like to reduce the precision of each of the texel values as much as possible, as I don't think it will affect the visualisation too much. What is the default precision of a texel a value? How can I specify it to be lower? I'd be happy with 4 bit precision if it helped with performance.
When I google I seem to find lots of stuff about setting the precision of variables once they are on the shader, but I want to do it to the texture before it gets sent to the GPU.
Thanks everyone. Code is here if you want a look - or if you need to know something specific about the code then let me know
Thanks

Related

Dividing a sphere into multiple texture

I have a sphere with texture of earth that I generate on the fly with the canvas element from an SVG file and manipulate it.
The texture size is 16384x8192 , and less than this - it's look blurry on close zoom.
But this is a huge texture size and causing memory problems... (But it's look very good when it is working)
I think a better approach would be to split the sphere into 32 separated textures, each in size of 2048x2048
A few questions:
How can I split the sphere and assign the right textures?
Is this approach better in terms of memory and performance from a single huge texture?
Is there a better solution?
Thanks
You could subdivide a cube, and cubemap this.
Instead of having one texture per face, you would have NxN textures. 32 doesn't sound like a good number, but 24 for example does, (6x2x2).
You will still use the same amount of memory. If the shape actually needs to be spherical you can further subdivide the segments and normalize the entire shape (spherify it).
You probably cant even use such a big texture anyway.
notice the top sphere (cubemap, ignore isocube):
Typically, that's not something you'd do programmatically, but in a 3D program like Blender or 3D max. It involves some trivial mesh separation, UV mapping and material assignment. One other approach that's worth experimenting with would be to have multiple materials but only one mesh - you'd still get (somewhat) progressive loading. BUT
Are you sure you'd be better off with "chunks" loading sequentially rather than one big texture taking a huge amount of time? Sure, it'll improve a bit in terms of timeouts and caching, but the tradeoff is having big chunks of your mesh be textureless, which is noticeable and unasthetic.
There are a few approaches that would mitigate your problem. First, it's important to understand that texture loading optimization techniques - while common in game engines - aren't really part of threejs or what it's built for. You'll never get the near-seamless LODs or GPU optimization techniques that you'll get with UE4 or Unity. Furthermore webGL - while having made many strides over the past decade - is not ideal for handling vast texture sizes, not at the GPU level (since it's based on OpenGL ES, suited primarily for mobile devices) and certainly not at the caching level - we're still dealing with broswers here. You won't find a lot of webGL work done with vast textures of the dimensions you refer to.
Having said that,
A. A loader will let you do other things while your textures are loading so your user isn't staring at an 'unfinished mesh'. It lets you be pretty clever with dynamic loading times and UX design. Additionally, take a look at this gist to give you an idea for what a progressive texture loader could look like. A much more involved technique, that's JPEG specific, can be found here but I wouldn't approach it unless you're comfortable with low-level graphics programming.
B. Threejs does have a basic implementation of LOD although I haven't tinkered with it myself and am not sure it's useful for textures; that said, the basic premise to inquire into is whether you can load progressively higher-resolution files on a per-need basis, just like Google Earth does it for example.
C. This is out of the scope of your question - but I'd look into what happens under the hood in Unity's webgl export (which is based on threejs), and what kind of clever tricks are being employed there for similar purposes.
Finally, does your project have to be in webgl? For something ambitious and demanding, sometimes "proper" openGL / DX makes much more sense.

Is it possible to implement a filter to make dark images appear illuminated?

I am working on an image processing project. Faster I process the images, the better. However as I increase the fps of my camera, everything begin to appear darker, since the camera do not have enough time to receive light. I was wondering if I could find a way around of this issue, since I know what is causing it.
I am thinking of writing a code that will increase all pixel values proportionally with what camera returns. Since only difference is the time duration, I think there should be a linear proportion between pixel values and the time duration camera had while taking that picture.
Before trying this, I have searched if there is anything available online but failed to find any. It feels like this is a basic concept so I would be surprised if no one had done such a thing before, so I might be using wrong keywords.
So my question is, is there a filter or an algorithm that increases the "illumination" of a dark image (since shot at high fps). If not, does what I intend to do make sense?
I think you should use Histogram Equalization here, rather than increasing all the pixels by some constant factor. Histogram Equalization makes the the probability of all possible pixel intensity equal thus enhancing the image.
Read about it using the following links
http://www.math.uci.edu/icamp/courses/math77c/demos/hist_eq.pdf
https://en.wikipedia.org/wiki/Histogram_equalization
Read this article on how to do it in opencv,
http://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/histogram_equalization/histogram_equalization.html
If your image is too dark use more light. That would be the proper way.
Of course you can increase brightness values but the image by simply multiplying them with a factor or adding an offset. Or spreading the histogram.
Instead of a bad dark image you'll end up with a bad bright image.
Low contrast, low dynamic range, low signal to noise ratio, all of that won't change.

Issue with NPOT Atlas (C++/iOS) using glTexCoordPointer

My app uses an atlas and reaches parts of it to display items using glTexCoordPointer.
It works well with power-of-two textures, but I wanted to use NPOT to reduce the amount of memory used.
Actually, the picture itself is well loaded with the linear filter and clamp-to-edge wrapping (the content displayed comes from the pic, even with alpha), but the display is deformed.
The coordinates are not the correct ones, and the "shape" is more a trapezoid than a rectangle.
I guessed I had to play with glEnable(), passing GL_TEXTURE_2D in the case of a POT texture, and GL_APPLE_texture_2D_limited_npot in the other case, but I cannot find a way to do so.
Also, I do not have the GL_TEXTURE_RECTANGLE_ARB, I don't know if it is an issue...
Anyone had the same kind of problem ?
Since OpenGL-2 (i.e. for about 10 years) there are no longer constraints on the size of a regular texture. You can use whatever image size you want, it will just work.

How should I sort object? By shaders or by meshes?

To minimize count of state changes, I should sort drawing order of meshes. Anyway If I have multiple meshes using multiple shaders, I need to choose sorting by one of vertex attribute bindings or shader uniform parameters.
What should I choose? I think I have to choose minimizing vertex attribute change because of GPU cache hit rate, but I have no idea about shader changing cost. What's the generic concern when deciding drawing order? Can I get some basis to choose this?
PS. I'm targeting iOS/PowerVR SGX chips.
Edit
I decided to go sort-by-material because many meshes will use just a few materials, but there're bunch of meshes to draw. This means I will have more opportunity to share materials than share meshes. So it will have more chance to decrease state change count. Anyway I'm not sure, so if you have better opinion, please let me know.
You don't need to depth sort opaque objects on the PowerVR SGX since uses order-independent, pixel perfect hidden surface removal.
Depth sort only to achieve proper transparency/translucency rendering.
The best practice on SGX is to sort by state, in the following order:
Viewport
Framebuffer
Shader
Textures
Clipping, Blending etc.
Texture state change can be significantly reduced by using texture atlases.
The amount of draw calls can be reduced by batching.
Thats just the golden rules, remember that you should profile first and then optimize :)
See:
http://www.imgtec.com/powervr/insider/docs/PowerVR.Performance%20Recommendations.1.0.28.External.pdf
Use something like this http://realtimecollisiondetection.net/blog/?p=86 and then you can change which parts are sorted first in your code at run time to achieve the best speeds per device

graphics: best performance with floating point accumulation images

I need to speed up some particle system eye candy I'm working on. The eye candy involves additive blending, accumulation, and trails and glow on the particles. At the moment I'm rendering by hand into a floating point image buffer, converting to unsigned chars at the last minute then uploading to an OpenGL texture. To simulate glow I'm rendering the same texture multiple times at different resolutions and different offsets. This is proving to be too slow, so I'm looking at changing something. The problem is, my dev hardware is an Intel GMA950, but the target machine has an Nvidia GeForce 8800, so it is difficult to profile OpenGL stuff at this stage.
I did some very unscientific profiling and found that most of the slow down is coming from dealing with the float image: scaling all the pixels by a constant to fade them out, and converting the float image to unsigned chars and uploading to the graphics hardware. So, I'm looking at the following options for optimization:
Replace floats with uint32's in a fixed point 16.16 configuration
Optimize float operations using SSE2 assembly (image buffer is a 1024*768*3 array of floats)
Use OpenGL Accumulation Buffer instead of float array
Use OpenGL floating-point FBO's instead of float array
Use OpenGL pixel/vertex shaders
Have you any experience with any of these possibilities? Any thoughts, advice? Something else I haven't thought of?
The problem is simply the sheer amount of data you have to process.
Your float buffer is 9 megabytes in size, and you touch the data more than once. Most likely your rendering loop looks somewhat like this:
Clear the buffer
Render something on it (uses reads and writes)
Convert to unsigned bytes
Upload to OpenGL
That's a lot of data that you move around, and the cache can't help you much because the image is much larger than your cache. Let's assume you touch every pixel five times. If so you move 45mb of data in and out of the slow main memory. 45mb does not sound like much data, but consider that almost each memory access will be a cache miss. The CPU will spend most of the time waiting for the data to arrive.
If you want to stay on the CPU to do the rendering there's not much you can do. Some ideas:
Using SSE for non temporary loads and stores may help, but they will complicate your task quite a bit (you have to align your reads and writes).
Try break up your rendering into tiles. E.g. do everything on smaller rectangles (256*256 or so). The idea behind this is, that you actually get a benefit from the cache. After you've cleared your rectangle for example the entire bitmap will be in the cache. Rendering and converting to bytes will be a lot faster now because there is no need to get the data from the relative slow main memory anymore.
Last resort: Reduce the resolution of your particle effect. This will give you a good bang for the buck at the cost of visual quality.
The best solution is to move the rendering onto the graphic card. Render to texture functionality is standard these days. It's a bit tricky to get it working with OpenGL because you have to decide which extension to use, but once you have it working the performance is not an issue anymore.
Btw - do you really need floating point render-targets? If you get away with 3 bytes per pixel you will see a nice performance improvement.
It's best to move the rendering calculation for massive particle systems like this over to the GPU, which has hardware optimized to do exactly this job as fast as possible.
Aaron is right: represent each individual particle with a sprite. You can calculate the movement of the sprites in space (eg, accumulate their position per frame) on the CPU using SSE2, but do all the additive blending and accumulation on the GPU via OpenGL. (Drawing sprites additively is easy enough.) You can handle your trails and blur either by doing it in shaders (the "pro" way), rendering to an accumulation buffer and back, or simply generate a bunch of additional sprites on the CPU representing the trail and throw them at the rasterizer.
Try to replace the manual code with sprites: An OpenGL texture with an alpha of, say, 10%. Then draw lots of them on the screen (ten of them in the same place to get the full glow).
If you by "manual" mean that you are using the CPU to poke pixels, I think pretty much anything you can do where you draw textured polygons using OpenGL instead will represent a huge speedup.

Resources