Matthias Bohlen
Matthias Bohlen

Reputation: 668

Water with reflections in ThreeJS

The "ocean" example in ThreeJS is really nice because the sun is reflected on the water and it looks realistic. I am trying to replicate this but there is a part of the code that I still need to understand.

The ocean example constructs a Water object and a Sky object. Then, it constructs a CubeCamera and uses this camera's render target as the background of the scene. So far, so clear. The code looks like this, with lots of detail suppressed (by me):

scene = new Scene();
water = new Water();
sky = new Sky();
scene.add( water );

cubeCamera = new CubeCamera();
scene.background = cubeCamera.renderTarget;

cubeCamera.update( renderer, sky );

I can understand everything except the last line: cubeCamera.update( renderer, sky );

In the ThreeJS docs, it says that the last parameter of CubeCamera.update() must be a Scene, not a Sky. I cannot understand why this sample works at all because a Sky has different methods than a Scene.

However, the line of code seems to be really important because when I delete it, there is no sun at all any more.

Can somebody enlighten me and tell me why it works, please?

Upvotes: 3

Views: 1784

Answers (2)

ScieCode
ScieCode

Reputation: 1735

In Three.js, a Scene is simply an extension of an Object3D. It only differs in that it can accept a .background and a .fog parameter and deal with that accordingly.

A Skybox object is not implemented in Three.js core. It is an example specific implementation that can be used as reference by the users. If you take a look at the implementation, it's nothing more than a Mesh with a BoxGeometry and a custom shader material. Which, in turn, is also an Object3D.

Despite what the documentation states, you don't need to render a scene on your cubeCamera, just as you don't need a scene on any three.js project. Everything can be replaced with an Object3D. (you might run into a few troubles, but this holds true most of the time)

In the end, it all depends on the purpose you are trying to achieve. In this example, the cubeCamera is used to simulate a skybox, which is independent from what's in the scene.

A more common use, is to create an environment map for the objects in the scene. In that scenario, it makes sense to use the actual scene to create the map. Check the reflective sphere in the back of this example.

Upvotes: 3

user128511
user128511

Reputation:

First off JavaScript is extremely dynamic. In many cases any object that has the correct properties and methods can be passed to a function that expects an object with those functions and methods.

Digging into the code you can see Sky is based on Mesh and Mesh is based on Object3D. Further Scene is based on Object3D

So if you dig through the code you'll find you can pass Object3D to CubeCamera.update which just calls renderer.renderer(scene, camera) and happens to not depend on any of the Scene specific things of Scene but only really needs the Object3D parts of Scene

Upvotes: 0

Related Questions