Saturday, November 17th, 2007

3D Canvas in Opera

Category: Canvas, Opera

Tim Johansson is talking about Opera’s support for a 3d Canvas which differs from Mozilla’s in that it doesn’t map directly to OpenGL, which they did because:

  • It makes it easier to implement on non-OpenGL platforms (such as D3D)
  • We wanted to have some form of collision detection available

What can you do? Here is the interface that you get to work with:


  1. interface CanvasRenderingContextOpera3D {
  3.   // state
  4.   void save(); // push state on state stack
  5.   void restore(); // pop state stack and restore state
  7.   // scene/frame
  8.   void beginScene(); // start rendering a new frame
  9.   void endScene(); // finish rendering of the scene and present the result
  11.   // transformations
  12.   void translate(in float x, in float y, in float z);
  13.   void scale(in float x, in float y, in float z);
  14.   void rotateX(in float rotation);
  15.   void rotateY(in float rotation);
  16.   void rotateZ(in float rotation);
  18.   // rendering operation
  19.   void drawTriangle(in float x1, in float y1, in float z1, in float tex_s1, in float tex_t1,
  20.       in float x2, in float y2, in float z2, in float tex_s2, in float tex_t2,
  21.       in float x3, in float y3, in float z3, in float tex_s3, in float tex_t3);
  22.   void draw3DModel(in Canvas3DModel model);
  24.   // create objects
  25.   CanvasTexture createTexture(in Image img);
  26.   Canvas3DModel create3DModel();
  28.   // collision detection
  29.   string checkIntersection(in float x, in float y, in float z, in float radius, in Canvas3DModel model);
  31.   // rendering state
  32.   attribute CanvasTexture texture; // current texture or null for no texture, default is null
  33.   attribute string color; // current color, default is transparent black
  34.   attribute float fov; // field of view of the scene in degrees, default is 45
  35.   attribute float nearPlane; // distance to the near clipping plane, default is 0.1
  36.   attribute float farPlane; // distance to the far clipping plane, default is 100
  37.   attribute string ztest; // "none", "less", "lessequal", "greater", "greaterequal", "equal", "notequal". Default is "lessequal"
  38.   attribute string blend; // "replace", "add", "srcalpha", "multiply". Default is "replace"
  39. };
  41. interface Canvas3DModel {
  42.   void addVertex(in float x, in float y, in float z, in float s, in float t);
  43.   void addTriangle(in integer vertex1, in integer vertex2, in integer vertex3);
  44. };
  46. interface CanvasTexture{
  47. };

And, here is an example of a rotating cube (which you can see if you are using a new Opera build).

  1. <canvas id="canvas" width="200" height="200">
  2.   Canvas not supported!
  3. </canvas>
  5. <script>
  6.   var canvas;
  7.   var context3d;
  8.   var rotation;
  9.   var texture;
  10.   var cube;
  11.   function render(){
  12.     context3d.beginScene();
  13.     context3d.translate(0,0,-5);
  14.     context3d.rotateY(rotation);
  15.     context3d.rotateX(rotation);
  16.     rotation += 2;
  17.     context3d.color = "white";
  18.     context3d.draw3DModel(cube);
  19.     context3d.endScene();
  20.   }
  21.   function onTick(){
  22.     render();
  23.   }
  24.   function onload(){
  25.     canvas = document.getElementById("canvas");
  26.     context3d = canvas.getContext("opera-3d");
  27.     if (!context3d)
  28.     {
  29.       alert("3d canvas not supported");
  30.       return;
  31.     }
  32.     logo = new Image();
  33.     logo.src = "operalogo.png";
  34.     texture = context3d.createTexture(logo);
  35.     context3d.texture = texture;
  37.     cube = context3d.create3DModel();
  38.     cube.addVertex(-1, 1, 1, 0, 0);
  39.     cube.addVertex(1, 1, 1, 1, 0);
  40.     cube.addVertex(-1, -1, 1, 0, 1);
  41.     cube.addVertex(1, -1, 1, 1, 1);
  42.     cube.addVertex(-1, 1, -1, 1, 1);
  43.     cube.addVertex(1, 1, -1, 0, 1);
  44.     cube.addVertex(-1, -1, -1, 1, 0);
  45.     cube.addVertex(1, -1, -1, 0, 0);
  47.     cube.addTriangle(0,1,2);
  48.     cube.addTriangle(2,1,3);
  49.     cube.addTriangle(4,5,6);
  50.     cube.addTriangle(6,5,7);
  51.     cube.addTriangle(0,4,2);
  52.     cube.addTriangle(2,4,6);
  53.     cube.addTriangle(1,5,3);
  54.     cube.addTriangle(3,5,7);
  55.     cube.addTriangle(0,4,1);
  56.     cube.addTriangle(1,4,5);
  57.     cube.addTriangle(2,6,3);
  58.     cube.addTriangle(3,6,7);
  60.     setInterval(onTick, 10);
  61.   }
  62.   document.onload = onload();
  63. </script>

Posted by Dion Almaer at 5:51 am

4.4 rating from 25 votes


Comments feed TrackBack URI

Here we go again. Everyone is implementing the 3d Canvas in his own way. :s

Comment by Westworld — November 17, 2007

i tried to view this in a virtualbox machine. i only get the “3d canvas not supported”, of course using opera last build presented on that post.
i wonder why


Comment by dan tamas — November 17, 2007

This is great news :)
I find it really interesting that people tries to implement HTML(ish) ways of creating more RIA capabilities, not only that but with the current state of FireFox, Safari and Opera I think Opera is the only real contestant left for Safari in the long run… :(
Safari virtually only needs the plugin architecture from FireFox and the fox is dead… :(
So it’s great to see Opera becoming better…!
(Not only that but it’s also great seeing other great companies here in cold little Norway doing great besides us)

Comment by Thomas Hansen — November 17, 2007

@Dan Tamas: you need this build

Comment by ws79 — November 17, 2007

yes, this one is what i used
i even uninstalled opera 9.24 and put that one…

Comment by dan tamas — November 17, 2007

It drives me nuts when browser vendors can’t come to some sort of agreement on standards.

Currently to set the context for a 2d canvas you write:
var myCanvas = $(‘canvas’).getContext(‘2d’);

So Opera wasn’t arrogant enough to set there version with:
var myCanvas = $(‘canvas’).getContext(‘3d’);

But rather:
var myCanvas = $(‘canvas’).getContext(‘opera-3d’);

So it seems to me they are still keeping their options open. If pressured enough Opera may end up rendering .getContent(‘3d’) as Firefox does or vice versa.

Also, I imagine the 3d canvas syntax is going to remain the same regardless of the context, so even if two different browsers use a different rendering engine you may still end up with the same or very similar result.

Will see …

Comment by Greg Houston — November 17, 2007

*sighs* in dispair.

Not only is it yet another API, no they also went and implemented it against a library (Direct3d) which is only available on one platform alone (Windows). Wasn’t opera intended to be cross platform?

Also the thing about collision detection is pure and utter rubbish, there’s plenty of excelent collision detection engines out there, both commercial and open source. You don’t _have_ to use Direct3d in order to get collision detection.

Maybe it helps to drop another hint…

Ever seen a productivity application (like 3dstudio max, you know, which people keep open all day to work, much like a browser) that uses Direct3d?
I tell you why, because Direct3d makes bloddy unstable applications. Whoever goes for any sort of “real” 3d programming scoffs at the notion of using Direct3d for anything then short lived games.

Comment by florian — November 17, 2007

Yeah, I want to see Opera reimplement Direct3D in Linux. O, wait, they can use Wine for this, just like Borland did the Kylix UI back then… Huge success, never quite understood why they dropped the project.

Comment by Bundyo — November 17, 2007

“makes it easier to implement on non-OpenGL platforms” is a bogus reason, as there is only one platform that Direct3D supports, Windows, _and_ Windows supports OpenGL. This is a super-lame move by Opera. At least say you only had Windows programmers working on it and be honest.

Comment by Andy — November 17, 2007

I don’t know why everyone’s up in arms about an experimental implementation of something that’s far from standardization. In fact, none of the 3d contexts will be useful on the Real Web until they’re somewhat emulated in IE (excanvas). Would a Direct3D-like API make that easier? I don’t know anything about 3D APIs.

Comment by Steve Clay — November 17, 2007

Opera will once again be ignored by developers for this retarded move

Comment by Viktor Kojouharov — November 19, 2007

Why’re we up in arms?

Coding on the web means: Dealing with various subtly or wildly different or simply missing APIs/implementations of basic things like DOM, CSS, XHR, javascript, svg, canvas, events, etc.

This has spawned an entire ecosystem of libraries/frameworks that wrap a unified API/hacks/fixes/reimplementations in javascript over basic browser infrastructure just so we can code applications that run more or less everywhere.

We usually put up with it because we don’t have a chance to change it, and when we complain loudly enough at the right places we get told it’s historical and we just have to live with it. OK

Now here we have something brand-new like 3d canvas. And instead of fixing the old mistakes of bloddy once going after one single API/functionality right from the start they go and implement it with widly different features and a wildly different API…

great, what’re we supposed to do? Roll over and get ready for yet another round of 3d javascript frameworks just so we can code against one API?

Comment by florian — November 19, 2007

Leave a comment

You must be logged in to post a comment.