I am building a scify scene where I am using RectAreaLights to simulate strip lights. The problem is whenever I use these type of lights I get low fps (not more than 20, 30). Switching to other types of lights like PointLight or SpotLight solves the performance issue, showing a steady 60 fps.
Is there anything I can do to improve performance using RectAreaLight?
RectAreaLights are just expensive. Especially if you are using a lot of them...
Perhaps you can get away with using one or two, but break them up by covering them with geometry? If you really need lots of little glowy bits.. consider adding the UnrealBlur post processing effect via EffectComposer.. that can be a good way to get lots of glowy things, at the expense of some realism, and careful attention to contrast to get the glow to pop.
Related
My issue is uncommon and, I think, requires some background in order to adequately phrase the question, so here goes...
I have a 3d world engine similar to Kieth Clarks', only without all the cool lighting effects. Instead I have some other immersive 3d perks that are also expensive, and chose to fake the lighting for now in order to be able to have the most complexity possible on mobile without dropping many frames noticeably.
I have an approximate visual/spacial scale ratio (not talking transform scales) of css pixels to object size. For instance, 50px is about 5 feet. Note, I am not trying to model exact dimensions in the real world, just close enough to be fairly convincing. Anyway, this means large objects are generally built from tile elements 100px^2. So a really simple 1-car garage, small hut etc. is easily modeled as a 100px cube made of divs or whatever you want. Usually I put the walls and top divs inside the bottom div, positioned so it acts as a base, eliminating the need for an extra containing element.
Now, tiles can be any 2d px ratio, but I'm using 100px^2 for big tile css classes, 66px, 50px, 20px, 10px etc. for smaller tile classes to make the markup simpler and easier to change px "scales" in "the world" through the css sheet, or later during runtime style alterations.
It takes a lot of tiles to model complex objects. Obvi, the potential drain on framerate stacks up exponentially as you add in objects, animations, especially large ones or complex shapes like cylinders or spheres (ouch) and have a populated simulation environment, especially outside or anywhere you can see a lot of things at one time.
I have completely re-written this thing three times to accommodate some major changes, using different "physical scale" ratios. Once enough complexity was achieved, it became apparent there is a huge difference in rendering efficiency when using a different ratio of pixels to feet (or meters, 3 feet being close enough). Basically it works out pixels/foot but it's important to note the basic tile size is just a little bigger than a 1-car garage door.
This difference is not as obvious as it would seem, such as more pixels more gpu. Some experiments proved to be more efficient with 100px : 10ft (what I'm using now) as opposed to 50px : 10ft, which is what I used on the first version.
The second version of the engine is a lot more efficient than the first and third, and not just for this reason. There are different effects involved, and special features that are now central to the purpose of this thing, so it is really time-consuming to play with how many pixels everything is made of.
For the engine to work properly I have to heavily account for various aspects such as css perspective, perspective-origin, altitude and distance of the carousel, and a lot of physical perspective cues that don't have directly-correlating css or DOM attributes, and don't easily translate into numbers I can just swap out using an equation. Also, changing one of these can wreak havok on proper rendering if you're not careful, of course like flashing, visual super-position, apparent z-order (not real z-order) incorrect etc., or just making the visual perspective look "wierd", even if it's more efficient then and not dropping frames, so making this kind of change is a real hassle and takes a lot of time and page reloads to get it right.
Now my question is this:
What is the ideal size ratio of pixels to feet for performance? I've even tried really small, like 1px is the size of a car and different transform scales for the stage to make it look right. I can glean a little more efficiency that way, but it throws my numbers for the physics way out of whack, even when I adjust them I'm not quite happy with how things move. Almost like if you miniaturized yourself to the size of a spider, you and things your relative size would behave a lot differently than they do now.
Should I go small and zoom in? Should I use larger image tiles and transform:scale3d the whole stage down? Or should I just use small images and tile elements? Should I use div's for the tiles, or is one of the newer semantic tags more efficient at rendering in css 3d space?
A combination of the above seems to be more efficient, but it's not a straight line. Almost like harmonics. Theres a periodicity to it. On the small to large pixels/foot ratio continuum, some smaller sizes seem to be less efficient than some larger ones.
There's a demo that tests how many cubes your browser can render efficiently, but I wonder if anyone's published results that describe different tile or cube pixel sizes with masses of cubes, or if anyone here has tried something like this.
Addendum: This is primarily geared for Chrome Android as an instant app or embedded in a webview, though hopefully Firefox catches up soon as it can't handle as many cubes. I will love that.
Couple screenshots of a test space... Note the sky is round. This is the anaglyph view, which takes the most processing. The SBS views are a lot more efficient as they use half or less of the viewport, and thereby have less to render since the view for each eye is half the width of anaglyph.
Also the overhead from mixing the anaglyph views.
I am developing a room in threejs and there are lot of models like sofa, walls, floor, curtain, rug, table, wall-panel, etc. (all are 3ds max models). So my problem is the controls are not smooth, I have tried orbital as well firstPersonControls but all are getting janked while operating. Please help?
You should try to reduce the models details of the mesh in favor of providing details in the texture map images (bump map etc.).
Basically you can load initially low quality models and if the frame rate is still good (maybe 20 fps and up) start adding in the more detailed versions.
If it's really bad, notify them they should try it on a faster device or desktop.
If this is on your fast machine/device, then try one model at a time to isolate when or where there's something else going on that's wrong.
Otherwise I'm sure there's a handful of features to disable from double-sided to aliasing etc. Same with lights and shadows etc. Isolate the problem or reduce the models and features. Again you can do this optimization and problem analysis on lights and shadows too.
Context :
I'm working on a pretty simple THREE.JS project, and it is, I believe, optimized in a pretty good way.
I'm using a WebGLRenderer to display lot's of Bode plot extracted from an audio signal every 50ms. This is pretty cool, but obviously, the more Bode I display, the more laggy it is. In addition, Bodes are moving at constant speed, letting new ones some space to be displayed.
I'm now at a point where I implemented every "basic" optimization I found on Internet, and I managed to get a 30 fps constantly at about 10.000.000 lines displayed, with such a bad computer (nVidia GT 210 and Core i3 2100...).
Note also i'm not using any lights,reflections... Only basic lines =)
As it is a working project, i'm not allowed to show some screenshots/code, sorry ...
Current implementation :
I'm using an array to store all my Bodes, which are each displayed via a THREE.Line.
FYI, actually 2000 THREE.Line are used.
When a Bode has been displayed and moved for 40s, it is then deleted and the THREE.Line is re-used with another one. Note that to move these, I'm modifying THREE.Line.position property.
Note also that I already disabled my scene and object matrix autoUpdate, as I'm doing it manually. (Thx for pointing that Volune).
My Question :
Do the THREE.Line.position modification induces some heavy
calculations the renderer has already done ? Or is three.js aware that my object did not change and
avoid these ?
In other words, I'd like to know if rendering/updating the same object which was just translated is heavier in the rendering process than just leaving it alone, without updating his matrix etc...
Is there any sort of low-level optimization, either in ThreeJS about rendering the same objects many times ? Is this optimization cancelled when I move my object ?
If so, I've in mind an other way to do this : using only two big Mesh, which are folowing each other, but this induces merging/deleting parts of their geometries each frames... Might it be better ?
Thanks in advance.
I found in the sources (here and here) that the meshes matrices are updated each frame no matter the position changed or not.
This means that the position modification does not induce heavy calculation itself. This also means that a lot of matrices are updated and a lot of uniforms are sent to the GC each frame.
I would suggest trying your idea with one or two big meshes. This should reduce javascript computations internal to THREE.js, and the only big communications with the GC will be relative to the big buffers.
Also note that there exists a WebGL function bufferSubData (MSDN documentation) to update parts of a buffer, but it seems not yet usable in THREE.js
I'm new to HTML5/Canvas/Game programming, but have been tinkering around with it after reading a couple of books. I THINK I have a fairly good idea of how things work out. This question asks several smaller questions, but in general is basically a "structural approach" question. I'm not expecting verbose responses, but hopefully small pointers here and there :) Here is a link to a non-scrolling, and currently rather boring Super Mario World.
Super Mario World Test
NOTE: Controls are Left/Right and Spacebar to jump. This is only setup for Firefox right now as I'm just learning.
Did I Do Something Wrong at This Point?
Currently I've just focused on how Mario runs and jumps, and think that I've gotten it down fairly okay. The coin box doesn't do anything and the background is just an image loaded in for looks. Here's my approach, please let me know if there is anything entirely wrong with this:
Allows Mario to jump by enacting on 2 Y velocities (Gravity and Jump variables)
Allows Mario to run by enacting on 1 velocity (Left or Right "Friction" + Acceleration)
Sprites are used and positioned according to keypress/keydown
I'm not sure if this is right, but I'm using a constructor function to build an object, then inside the main animation loop I'm calling the prototype.draw function for that object to update all variables and redraw the object.
I'm clearing the entire canvas each Frame
Should I be splitting this into more than just a draw function, like Mario.move()?
I've setup a GroundLevel and a JumpLevel variable to create 2 planes of gameplay. The JumpLevel is setup to allow for controlling how high Mario can jump on the fly. The 2 places would allow for the ground to rise like a hill - keeping the point at which Gravity overrules Mario's jumping force at the same distance from the ground.
For clarity sake, everything is separated into different JS files, but would obviously consolidate.
Moving Forward:
Now that I've finished setting up how Mario moves around (I think there are a couple other minor things I might do like mushroom up/down and shooting fireballs). I think I can figure that out, but I'm really lost when it comes to visualizing the following and how HTML5/Canvas can handle this easily:
Scrolling background (I've tried setting up Ground Tiles and using Screen Wrapping, but that seems to cause a lot of uneven issues since I was moving the tiles in the opposite direction. Unfortunately, since I'm trying to account for acceleration, this threw off the count and was causing gaps in the ground. I ditched this idea. Would a DIV beneath the canvas with a large background image be the best solution?
Enemies: Would I create enemies the same way and run a loop for collision detection on every enemy during each frame?
Background Boxes: I'm trying to allow Mario to stand on the boxes in the background, but am unsure how to approach this. I currently have boundaries setup for Mario to stay on the canvas, do I continue to expand these conditions to setup different boundaries based on the boxes? I can see that having several boxes on the screen and doing it this way would get kind of crazy, especially if I would be doing the same hit testing for enemies? I know I'm missing something here....
Level Movement: This is somewhat related. When the Right key is pressed, basically everything in the level needs to move to the left. Would I need to track out all positions of everything that could touch Mario (boxes for him to stand on and enemies for him to collide with) during every animation frame? This seems like it would get kind of inefficient?
Thanks to all! I'll keep this updated with results/solutions :)
Wow, okay. I really like your question because you've obviously done a lot of thinking on this, but partially because of that it's incredibly broad and conversational. You'd do better to find a forum to ask this question.
...That being said, I'm gonna answer the handful of points I'm qualified to, in no particular order. :)
Level Movement: That's a weird (read: inefficient) way to do it. I wouldn't do any calculations based on onscreen positions: track a canonical, camera-agnostic set of coordinates for everything in your level and update the visuals to match. This will stop you from running into weird niggling problems where framerate impacts what you can and can't walk through, or causing slower computers to let Mario run through enemies without being damaged sometimes. Tracking positions this way will incidentally fix a lot of your other problems.
You should absolutely be splitting this into multiple functions. Having movement code and rendering code in the same place is going to screw you, particularly by interacting malignantly with your update/refresh rate. It's going to essentially mean that every time the player does a tricky jump the game does more updates than usual which will make animation/hit detection/etc much less likely to be even.
Enemies: I'd suggest rolling this in with everything else. Do one hit-detection pass against everything, and if you hit something check to see what it was. You could try to optimize this by only checking any given entity against objects within 100 pixels of itself, but if you do it this way you'll need to run separate collision detection events for every enemy. Letting the enemies clip through each other would be computationally cheaper.
Edit: I'd like to clarify about my first point on 'level movement.' Essentially, what you don't want to do is move every entity onscreen every time the camera does, or to store all entity locations as offsets from the camera location (in which case you're still effectively having to move everything, every time the camera moves.)
Your ideal approach is to store your enemy, block, terrain locations with X/Y coordinates that are offset from the absolute top-left of the level (at the very beginning.) In order to render a frame, you'd do essentially this: (pseudocode because we're talking about a hypothetical level format!)
function GetVisible(x,width,level_entities_array) {
for (i = 0; i < count(level_array); i++){
if (level_entities_array[i][x] > x && level_entities_array[i][x] < x+width) {
visible_elements[] = level_entities_array[i][x];
}
}
return visible_elements;
}
Boom, you've got everything that should be inside the window. Now you subtract the camera's x offset from the entity's x location and ZAP, you've got its position on the canvas. Pose as a team, 'cause things just got real.
You'll note that I'm not bothering to cull on the Y axis. This can be rectified by extrapolation, which I'm guessing you can handle because you've made it this far. This will be necessary if you want to do any Mario-style vertical exploration.
Yes, I know my pseudocode looks like C# and JavaScript's unholy lovechild. I'm sorry, that's just how I roll at 11:30 at night. ;)
I'm trying to create moving lights with trails for an HTML5 website/app targeted at iPad 2.
I wonder what the best way to do this is and whether using HTML5 is viable at all. I chose HTML5 because it's easier and cheaper to develop and deploy than native iOS apps with Objective C. Of course if it turns out that HTML5 simply doesn't offer enough performance I might have to swallow the bitter pill.
Anyway to give you an impression what I'm talking about, this is what I got so far:
screenshot http://devdali.no-ip.org/mathias/test-lights/screenshots/1.jpg
Or you can see it in action here (only works in webkit based browsers).
At first I tried using HTML5 canvas and drawing radial gradients as particles in similar manner you see above. It worked but the framerate was horrible even on my desktop computer!
So after a bit of reading I found out that CSS3 transforms may be hardware accelerated, so I build the version you see above. Every "particle" is a 64x64 png image. For each light there is the "head" light (one img) followed by a trail consisting of 115 img elements. Each img element is transformed using "translate3d" (as well as scale and rotation). Also the opacity of each element is adjusted dynamically.
Doing it this way provided much better framerates on my computer, but I doubt the iPad 2 will handle it.
I'd be grateful if anyone could give me some hints on how to improve the performance of this in general and considering the target platform.
Thanks for any help in advance!
If you accept small changes to the effect, some other procedure may work fast:
Instead of drawing the light's trails by the means of many particles, just draw the lights in their current positions in a Canvas element.
You can then darken the whole image at the beginning of a frame by filling a black rectangle with a very low opacity on top. This way the trails fade into dark, but would not alter their color like they do now.
The amount of drawing operations however will reduce vastly. The most costly operation would be filling the fading rectangle for every frame.
This should be built in the canvas. Check out EaselJS and this demo.
http://easeljs.com/
http://easeljs.com/demos/MusicVisualizer/index.html
You could optimize performances a LOT by using WebGL(, which is supported on the iPad2.)... which is not supported for basic html pages on ios safari as stated Nison Maƫl...
For the time being you only have canvas as a solution. Which will still give you better performances...
(You can check this blog for more info:
http://learningwebgl.com/blog/
With a little faith and time you'll be amazed!)