I recently started working on a configurator tool, and I need a reflective surface on the ground to reflect the object we want to showcase and create a studio-like appearance.
The problem is that Three.js has a version of reflector, but its a 1:1 reflection and it looks weird since its too reflective. The question is if anyone knows how I can make that reflected image slightly more blurry. I'm not that well versed in shaders...
Alternatively, if there are better ways I am open to changing my approach. I am looking for the most performant way of getting a similar result to a car showcase. Image for reference
https://comps.canstockphoto.com/3d-red-hot-rod-drawing_csp0608954.jpg
Link to the file I am using.
https://github.com/mrdoob/three.js/blob/master/examples/jsm/objects/Reflector.js
and the code I use to place it in the scene:
var mirrorGeometry = new THREE.CircleGeometry(200, 200);
var groundMirror = new Reflector(mirrorGeometry, {
clipBias: 0.05,
textureWidth: window.innerWidth * window.devicePixelRatio,
textureHeight: window.innerHeight * window.devicePixelRatio,
color: 0x777777,
recursion: 1
});
scene.add(groundMirror);
tl;dr: Object is placed on a mirror, causing an identical reflection. Which looks weird for a showcase model. I am asking for information on how to blur it, but a different approach would also work for me.
Edit: Apparently the Reflector object can also not receive shadows (though I need to look into this first. This is also a factor in the final render)
Related
Im somewhat new to Babylon JS but I created a scene and filled it with some cubes, added a light and a shadow map using:
new BABYLON.ShadowGenerator(4096, light);
Im getting really aliased shadow edges. I would like to know how I can get the aliasing to be smaller without bumping up the shadow map size.
Its already at 4096 which is already fairly large. Am I missing something? Thanks!
you can try using one of the soft shadows flag, while reducing the shadow map size, because as you say - 4096 is way too large.
You can read more about it here, and try the following
shadowGenerator.useExponentialShadowMap = true;
// or!
shadowGenerator.usePoissonSampling = true;
It turns out that how spread out shadow casting objects are makes a difference in the shadow quality. For example, go here and change the "distance_range" var to 10:
https://playground.babylonjs.com/#ZSB485#3
I ended up just using shadowGenerator.useBlurExponentialShadowMap = true and that seemed to be good enough for me.
I need to create text with inset shadow on my object in three.js, which looks like this:
Something like ring with engraved text.
I think the easier way to do that would be to use a normal-map for the engraving, at least if the text doesn't have to be dynamic (here's how you can export a normal-map from blender). And even if it needs to be dynamic it might be easier to create a normal-map dynamically in a canvas than to actually create a geometry for the engraving.
Another option would be to actually create a geometry that contains the engraving. For that you might want to look at the ThreeCSG-library, that let's you use boolean operators on geometries: You create the 3D-text mesh, warp and align it to the curvature of the ring and finally subtract it from the ring-mesh. This should give you the ring with the engraving spared out.
In fact, I was curious how this would actually work out and implemented something very similar here: https://usefulthink.github.io/three-text-warp-csg/ (source here).
In essence, This is using ThreeCSG to subtract a text-geometry from a cylinder-geometry like so:
const textBSP = new ThreeBSP(textGeometry);
const cylinderBSP = new ThreeBSP(cylinderGeometry);
const resultGeometry = cylinderBSP.subtract(textBSP).toGeometry();
scene.add(new THREE.Mesh(resultGeometry, new THREE.MeshStandardMaterial());
Turns out that the tessellation created by threeCSG really slow (I had to move it into a worker so the page doesn't freeze for almost 10 seconds). It doesn't look too good right now, as there is still a problem with the computed normals that i haven't figured out yet.
The third option would be to use a combination of displacement and normal-maps.
This would be a lot easier and faster in processing, but you would need to add a whole lot of vertices in order to have vertices available where you want an displacement to happen. Here is a small piece of code by mrdoob that can help you with creating the normal-map based on the displacement: http://mrdoob.com/lab/javascript/height2normal/
I found a bunnymark for Javascript canvas here.
Now of course, I understand their default renderer is using webGL but I am only interested in the native 2D context performance for now. I disabled webGL on firefox and after spawning 16500 bunnies, the counter showed a FPS of 25. I decided to wrote my own little very simple rendering loop to see how much overhead Pixi added. To my surprise, I only got a FPS of 20.
My roughly equivalent JSFiddle.
So I decided to take a look into their source here and it doesn't appear to be that the magic is in their rendering code:
do
{
transform = displayObject.worldTransform;
...
if(displayObject instanceof PIXI.Sprite)
{
var frame = displayObject.texture.frame;
if(frame)
{
context.globalAlpha = displayObject.worldAlpha;
context.setTransform(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]);
context.drawImage(displayObject.texture.baseTexture.source,
frame.x,
frame.y,
frame.width,
frame.height,
(displayObject.anchor.x) * -frame.width,
(displayObject.anchor.y) * -frame.height,
frame.width,
frame.height);
}
}
Curiously, it seems they are using a linked list for their rendering loop and a profile on both app shows that while my version allocates the same amount of cpu time per frame, their implementation shows cpu usage in spikes.
My knowledge ends here unfortunately and I am curious if anyone can shed some light on whats going on.
I think, in my opinion, that it boils down to how "compilable" (cache-able) the code is. Chrome and Firefox uses two different JavaScript "compilers"/engines as we know which optimizes and caching code differently.
Canvas operations
Using transform versus direct coordinates should not have an impact as setting a transform merely updates the matrix which is in any case is used with what-ever is in it.
The type of position values can affect performance though, float versus integer values, but as both your fiddle and PIXI seem to use floats only this is not the key here.
So here I don't think canvas is the cause of the difference.
Variable and property caching
(I got unintentionally too focused on the prototypal aspect in the first version of this answer. The essence I was trying to get at was mainly object traversing, so here the following text is re-worded a bit -)
PIXI uses object properties as the fiddle but these custom objects in PIXI are smaller in size so the traversing of the object tree takes less time compared to what it takes to traverse a larger object such as canvas or image (a property such as width would also be at the end of this object).
It's a well known classic optimization trick to cache variables due to this very reason (traverse time). The effect is less today as the engines has become smarter, especially V8 in Chrome which seem to be able to predict/cache this better internally, while in Firefox it seem to still have a some impact not to cache these variables in code.
Does it matter performance-wise? For short operations very little, but drawing 16,500 bunnies onto canvas is demanding and do gain a benefit from doing this (in FF) so any micro-optimization do actually count in situations such as this.
Demos
I prototyped the "renderer" to get even closer to PIXI as well as caching the object properties. This gave a performance burst in Firefox:
http://jsfiddle.net/AbdiasSoftware/2Dbys/8/
I used a slow computer (to scale the impact) which ran your fiddle at about 5 FPS. After caching the values it ran at 6-7 fps which is more than 20% increase on this computer showing it do have an effect. On a computer with a larger CPU instruction cache and so forth the effect may be less, but it's there as this is related to the FF engine itself (disclaimer: I am not claiming this to be a scientific test however, only a pointer :-) ).
/// cache object properties
var lastTime = 0,
w = canvas.width,
h = canvas.height,
iw = image.width,
ih = image.height;
This next version caches these variables as properties on an object (itself) to show that also this improves performance compared to using large global objects directly - result about the same as above:
http://jsfiddle.net/AbdiasSoftware/2Dbys/9/
var RENDER = function () {
this.width = canvas.width;
this.height = canvas.height;
this.imageWidth = image.width;
this.imageHeight = image.height;
}
In conclusion
I am certain based on the results and previous experience that PIXI can run the code faster due to using custom small-sized objects rather than getting the properties directly from large objects (elements) such as canvas and image.
The FF engine seem not yet to be as "smart" as the V8 engine in regard to object traversing of tree and branches so caching variables do have an impact in FF which comes to display when the demand is high (such as when drawing 16,500 bunnies per "frame").
One difference I noticed between your version and Pixi's is this:
You render image at certain coordinates by passing x/y straight to drawImage function:
drawImage(img, x, y, ...);
..whereas Pixi translates entire canvas context, and then draws image at 0/0 (of already shifted context):
setTransform(1, 0, 0, 1, x, y);
drawImage(img, 0, 0, ...);
They also pass more arguments to drawImage; arguments that control "destination rectangle" — dx, dy, dw, dh.
I suspected this is where speed difference hides. However, changing your test to use same "technique" doesn't really make things better.
But there's something else...
I clocked bunnies to 5000, disabled WebGL, and Pixi actually performs worse than the custom fiddle version.
I get ~27 FPS on Pixi:
and ~32-35 FPS on Fiddle:
This is all on Chrome 33.0.1712.4 dev, Mac OS X.
I'd suspect that this is some canvas compositing issue. Canvas is transparent by default, so the page background needs to be combined with the canvas contents...
I found this in their source...
// update the background color
if (this.view.style.backgroundColor != stage.backgroundColorString &&
!this.transparent) {
this.view.style.backgroundColor = stage.backgroundColorString;
}
Maybe they set the canvas to be opaque for this demo (the fiddle doesn't really work for me, seems like most of the bunnys jump out with an extremely large dt most of the time)?
I don't think it's an object property access timing / compilability thing: The point is valid, but I don't think it can explain that much of a difference.
I am trying to adapt the gamefromscratch page showing how to Handling sprite based shooting. But I'm trying to replace the sprite with a bitmap that's in a container. The point where I'm stumbling is the end of the onTick(delta) where there is a graphics object created , I don't know the syntax to replace
var g = new createjs.Graphics();
g.setStrokeStyle(5);
g.beginStroke(createjs.Graphics.getRGB(255,0,0));
g.drawCircle(this.x,this.y,10);
this.bulletGraphic = new createjs.Shape(g);
stage.addChild(this.bulletGraphic);
}
bullets.push(bullet);
with code that would work for a Bitmap In a container.
Thanks for looking .
I believe you are looking for g.beginBitmapStroke() to replace the g.drawCircle()
You can find the EaselJS Documentation here:
http://www.createjs.com/Docs/EaselJS/classes/Graphics.html#yui_3_8_0pr2_2_1363403850534_598
For just using a Bitmap instead of a Shape you could use:
this.bulletGraphic = new createjs.Bitmap('urlOrImage');
stage.addChild(this.bulletGraphic);
}
bullets.push(bullet);
if you want the bullet-Bitmap additionally to be in a container (for whatever reason):
this.bulletGraphic = new createjs.Container();
this.bulletBitmap = new createjs.Bitmap('urlOrImage');
this.bulletGraphic.addChild(this.bulletBitmap);
stage.addChild(this.bulletGraphic);
}
bullets.push(bullet);
A little sidenote from me (note related to your question, but in case you care):
The code-example given on that page explains the Math behind the topic pretty good, but code-wise I would not take this as a good example. For a bullet you would usually create a new class, inheriting from Shape or Bitmap, the author of this example uses a plain object and just references the graphical-asset (this.bulletGraphic) through it. So if you're just using this to learn the Math, this is good, if you want to take this to create a real game out of it, I'd suggest you to restructure the code quite a bit, because this will get messy very soon.
I'm trying to make a little scene for viewing 3D models.
I modified the GLGE Collada example to add a .dae model from code.
http://goleztrol.nl/SO/GLGE/01/
What I've got
So far it works. The camera is rotated using an animation.
Using the buttons 'Add' and 'Remove' the model is added and removed from the scene, using the following code (Don't mind 'duck'. It was a duck in the original example.)
var duck = null;
function addDuck()
{
if (duck) return;
duck = new GLGE.Collada();
doc.getElement("mainscene").addCollada(duck);
duck.setId("duck");
duck.setDocument("amyrose.dae");
duck.setLocY(-15);
duck.setRotX(1);
duck.setScale(2);
}
function removeDuck()
{
if (!duck) return;
doc.getElement("mainscene").removeChild(duck);
duck = null;
}
Problem
Now the model is lying down, while it should stand up. The various methods of the element seem to work. The location is set, and the scale is set, but the call to setRotX seems to be ignored. I tried various others methods from the api, but setRotY, setRot, setQuatX and setDRotX all seem to fail. I don't get any errors (well not about this method). I tried values of 1.57 (which should be about 90 degrees), but other values as well, ranging from 1 to 180.
I can't find out what I'm doing wrong. Of course I could rotate the model itself in Blender, but I'd like to do it using the GLGE API.
Update
When I load the demo-model, seymourplane_triangulate.dae, the rotation works. Apparently my model differs in that it cannot be rotated. I just don't understand why. I figured it may be because the model is built of various separate meshes, but I don't understand why scaling and moving does work.
Does anyone know what's wrong with this model, and what I could do to fix it (maybe using Blender)?
Setting an initial rotation in the XML file that contains the scene does work. Setting rotation on another element (like the whole scene) works as well.
You need to rotate it after it has been loaded.
You can do this in the callback to setDocument
duck.setDocument("amyrose.dae", null, function() {
duck.setLocY(-15);
duck.setScale(2);
duck.setRotX(0);
duck.setRotY(0);
duck.setRotZ(3);
});