Render scene at lower resolution (three.js) - javascript

How can i decrease my rendered canvas resolution(just like i can do on blender camera resolution)? I've seen another question saying that i need to use
renderer.setDevicePixelRatio(window.devicePixelRatio)
The problem is that the object either gets black or nothing shows on canvas, so i don't really know if this is it solves my problem.
I also tried to use
renderer.setSize()
and
renderer.setViewport()
together and separately, but it only changed the canvas size to a very small one(i need a high size preview of the canvas), and even though the viewport got on the size i wanted, it seems that the objects are rendered only on the smaller size, so i can't see all of it, so it doesn't do the trick.
Also, if possible, is there a way to do that by manually changing the image buffer to a lower resolution one, and displaying it?

The thing i needed was the setPixelRatio function on therenderer. no setDevicePixelRatio.

Related

(Three.js) Bloom effect performance

It has 50-60fps, if there is no bloom effect.
renderer.render( scene, camera );
Then, just have 10fps after added bloom effect.
camera.layers.set( BLOOM_SCENE );
bloomComposer.render();
camera.layers.set( ENTIRE_SCENE );
finalComposer.render();
How can i fix it? demo link is here
https://codepen.io/anson-chan/pen/QXeKqm?editors=1010
There are a few different problems here.
You have a LARGE number of cubes in your scene. Each cube is a unique material and drawCall. To keep a scene fast, you want to keep the number of drawcalls around 500 or so, and the number of polygons at or below around 1.5 million.
This is called being "draw call bound".
There are some strategies for dealing with this... such as using hardware instancing and/or a library like THREE.BAS to do instancing of your cubes. These techniques can render LARGE numbers of objects with a single draw call, and may help you.
(https://github.com/zadvorsky/three.bas)
(http://three-bas-examples.surge.sh/examples/instanced_prefabs/)
Next up:
your resize handler is always resizing to the bounds of the window.. not the size of the actual canvas. You are also NOT resizing the actual renderPasses in your code. Each pass that has a width/height parameter also needs to be resized, along with the effectsComposer itself, and presently always resizing to the size of the window.. not the size of the actual canvas area your are rendering.
Instead, try something like renderer.resize(renderer.domElement.width,renderer.domElement.height,false) Then control the canvas resizing via css rules, and then make sure your blurPass size is set, and the effectsComposer size is also set. The 'false' parameter on the resize method prevents THREE from setting the width/height of the canvas style, and allows you to control it explicitly. Otherwise, you can have problems of your size changing triggering additional resizes when THREE tries to change the CSS of the canvas to the new width/height you're passing.
This problem is causing you to render a full window sized canvas and effects pass no matter what the display size it.
The next issue is that blur/bloom is an inherently costly operation.. since it requires scaling down the entire framebuffer a few times to generate the blurred/bloomed version of the effect. This is compounded by the sizing problem mentioned above ^
Next up... I don't know what hardware you are running on, but if it's a retina display.. your devicePixelRatio will be greater than 1, in which case it further compounds the display sizing problems, since on a retina display, a devicePixelRatio of 2 will cause the renderer to render 4x as much as a devicePixelRatio of 1. You may want to consider using 1 instead of whatever you get from window.devicePixelRatio.
All of these issues compound each other. GPU's can only do so much, so you have to be clever how you manage them and what kind of loads you place on them.
Hope this helps.

What are maximum dimensions of Three.js render canvas?

When I set render canvas size to ~4000x4000px it's ok, however starting from around 4000 (tested 5k, 6k, 8k) it seems that scene is "cut off" in some way. See image below:
So up to ~4k content is properly rendered in the center of canvas and for higher canvas sizes it cuts the content.
Is it a Three.js/WebGL limitation?
If yes then what are actual maximum canvas dimensions that don't cause any "deformations"?
Is there anything I can do about it? I need to get canvas snapshot in high resolution (8k).
Is there anything I can do about it? I need to get canvas snapshot in high resolution (8k).
You can render portions of the scene using Camera.setViewOffset and then assemble the parts into a large image. You can look at this sample where it renders the image in 4 separate parts. In that example it makes 4 renderers but for your case you'd only need one and just render->capture canvas->render->capture canvas-> repeat until you get all parts. Then you need a way to stitch those parts together. You could use gIMP or Photoshop for example.
Here's library that does this
https://greggman.github.io/dekapng/
I know there is an answer here I wrote that shows how to do this in three.js since I wrote that library because of my answer. Unfortunately 10 minutes of searching didn't bring up >:(
This is not a limitation of three.js but a limitation of the maximum size of the drawing buffer. It's defined by the browser vendor and can't be exceeded by an application. More information in this github issue:
https://github.com/mrdoob/three.js/issues/5194

Change DPI of canvas element in HTML5

I'm looking to create a chrome application that allows the user to design a few different things using the canvas element. After they're done, I'd like to use a mask to crop out everything outside a specified area and then send the image to a printer. However, I need to be able to control the printed size precisely.
When I was making a similar app in python, it was a simple matter of setting the DPI to a ratio of the resolution to the dimensions I needed. I'm trying to find if there's a solution as simple as this one for HTML5.
I've found a couple posts asking for similar things, but they're unanswered and don't have a lot of activity.
Any help would be appreciated!
Canvas is a bitmap (raster) format. You can not just increase the DPI without some horrible artifacts appearing.
You can however record all the drawing, strokes/fills etc, and then at print time create a larger canvas for print and scale up all the drawing commands to fit the higher resolution canvas. As long as you don't use bitmapped images or direct pixel manipulation the results will be good. Though large canvas formats can be problematic on some devices and browsers. A better way is to convert it all to a vector format like SVG and print that. Or skip the canvas altogether and draw to SVG.

canvas tile grid with hover effects, tilesheet, etc

I've been working on building a tile-based display grid for canvas. This is what I have so far: http://jsfiddle.net/dDmTf/7/
Some problems I'm having, and can't quite grasp are:
The initial load time is ridiculous... I don't understand what I'm doing wrong - fixed, found out I was rendering ^32 more than I was supposed to
The hover effect, which "should" just highlight the border of the tile, erases it, and I have no way of recovering the previous tile without re-rendering the entire canvas.
How do I use tilesheets, providing me a single image instead of a bunch of small ones
Resizing the window (which resizes the canvas) also erases the canvas. Do I need to re-render? Or can I maintain state of various things when width/height is changed - added an onresize callback, which re-renders the map. Might not be the best way though?
Multiple layers? How would I go about allowing transparency .png files overlaying each-other
Those are the main problems I'm stuck on right now, and any guidance would be majorly appreciated.
Also, if you have any pointers for my javascript, feel free! I'm learning it more as I go, and I'm sure I'm doing a lot of things wrong.
Edit
As an FYI, I just copy-pasted the sprite map currently being shown on the jsfiddle. It's not the one I'm planning to use, but it was easier than uploading one. I plan to maintain a 32x32 grid instead of (what appears to be) a 16x16 grid from that tilesheet
Edit
I've got the a 32x32 tilesheet displaying on there now, but the hover effect is still breaking it, and I'm not sure how to "know" what the old value was.
The problem is that you are not redrawing your tiles after 'mouseout'.
You either need to redraw the single tile after you move out of it, but this can get tricky as things get more complicated or better yet on mouse move do the following.
Clear the canvas
draw the grid
draw your tiles
then do the highlighting/clearing that cell.
If you end up having any sort of animation this is the process that will be used anyhow otherwise as something moves from one tile to another it will leave ghost images behind.

Dynamically pixelate an html image element

I'm to take an image on a webpage, and then use javascript (or whatever would be best suited) to dynamically 'pixelate' it (e.g. into 20px squares). Then, as the user scrolls down the page, I need the image to gradually increase in resolution, till it is no longer pixelated.
Any ideas how I could go about doing this? I realise I could use php to resize an image and several times and just switch out the image, but that would require loading several extra images. Also, I know I could probably do the effect with flash & pixelbender, but I want to achieve it within the limitations of HTML5, CSS & Javascript if possible.
Appreciate any thoughts!
Update: Something like this, but with Javascript instead of Flash? http://www.reflektions.com/miniml/template_permalink.asp?id=390
You could render the picture in a hidden <canvas> element. Then use a derivation of the technique described here http://dev.opera.com/articles/view/html-5-canvas-the-basics/#pixelbasedmanipulation . To create a pixelated version of the image in a second <canvas> element using ever decreasing fillRect's. This way you even buffer the orginal image data.
edit: I would use 2 <canvas> elements so that you only have to fetch and draw the original image once. Perhaps you could buffer/cache this image in the same <canvas> element but by drawing it outside of the view port i am not sure if this is possible though.
I would use a calculation where you get the width in pixels divided by the square width and then the height divided by the square height. This would give you the lower resolution your looking for.
Then you can find a way to change the resolution to the result or grab the color of every pixel at position (height and width)/2 of the square your looking for. Then generate them into div tags or table with the appropriate color and size eventually resulting in the image its self.
I have a probably faster idea where you can have multiple versions of the image and change their z-index or their visibility as you scroll. Basically each image would have the different resolutions. If you have to do that to many images then this solution wont be as efficient as there would be lots of image editing but you can always do a batch edit.
Let me see If I can think of more ideas then I will edit.
Have a look at http://close-pixelate.desandro.com/
Explanation here: https://stackoverflow.com/a/8372981/22470
Not in a portable way.
That might be doable in Flash. Firefox JS extensions allow it to read images as JS arrays, Base64 strings etc. You might experiment with "1 DIV=1 pixel" hack, but it's hard to get any reasonable size of the image at any reasonable speed. If you feel really hyper, you could try creating base64-encoded images on the fly using the data: URI... many ways but none good...

Categories