glebedev's picture

WebGL through Silverlight/Monolight

Hi all.

There is new big feature arriving for web developers - WebGL. Basicly it is OpenGL ES 2.0 available from javascript.

Since OpenTK is .NET library, it should be possible to create new platform - Silverlight/Monolight with WebGL binding. My idea is to create invisible silverlight object which can create and control HTML canvas. It is 100% possible. I just don't know where to start :)

Please, help me to find how to create new platform in OpenTK.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

I've been keeping an eye out for WebGL but there's not much information available at this point.

As far as I know, Silverlight/Moonlight don't allow p/invoking native libraries (please correct me if I am wrong). With this limitation in place, it is simply not possible to use OpenTK on Silverlight (OpenTK relies on unmanaged APIs heavily).

It might be possible to add a modified version of the OpenGL|ES bindings into Moonlight itself but this won't work on Silverlight for obvious reasons.

Until we find a workaround for the p/invoke limitation, there is little point in trying to add a Silverlight platform to OpenTK.

glebedev's picture

pinvoke is not the only way...

 
			HtmlDocument doc = HtmlPage.Document;
			canvas = doc.GetElementById("webglcanvas");
 
			ScriptObject gl = null;
			try
			{
				if (gl == null)
					gl = canvas.Invoke("getContext", new object[] { "moz-webgl" }) as ScriptObject;
			}
			catch(Exception ex)
			{
				Debug.WriteLine(ex.ToString());
			}
			try
			{
				if (gl == null)
					gl = canvas.Invoke("getContext", new object[] { "webkit-3d" }) as ScriptObject;
			}
			catch (Exception ex)
			{
				Debug.WriteLine(ex.ToString());
			}
			if (gl != null)
			{
				arrayBuffer = gl.Invoke("createBuffer");
			}
the Fiddler's picture

I am not familiar with Silverlight. In the example above, how are you going to access WebGL functions from C#?

glebedev's picture

>I am not familiar with Silverlight. In the example above, how are you going to access WebGL functions from C#?

this is an example of WebGL method invokation:

gl.Invoke("createBuffer");

Step by step:

1. I take an element by id from HTML page. It should be < canvas >.
canvas = doc.GetElementById("webglcanvas");

Actualy we can create an element by ourself.

2. Here I take WebGL context object:
gl = canvas.Invoke("getContext", new object[] { "moz-webgl" }) as ScriptObject;

3. Now I can invoke any WebGL method:
gl.Invoke("createBuffer");

the Fiddler's picture

Ah, I see. Thanks for the explanation!

In this case, it should be possible to write a Silverlight/Moonlight driver for OpenTK. I will upload documentation for the internals of OpenTK to the hacking OpenTK section of the documentation, but until then a quick overview. A Silverlight port would consist of three parts:

  1. An implementation of OpenTK.Platform.IPlatformFactory using Silverlight APIs.
  2. The addition of the new Silverlight platform to OpenTK.Platform.Factory.
  3. The "rerouting" of OpenGL|ES function calls to WebGL.

For #1, you'd need to implement the interfaces used in the IPlatformFactory (for example, IGraphicsContext, INativeWindow) using Silverlight. The OpenTK.Platform namespace provides a few abstract base classes which will make this process easier.

I don't know the exact capabilities of Silverlight but you'd probably stub many of these interfaces without providing a complete implementation. For example, judging from the above code snippet, you don't have any control over the WebGL graphics mode - in that case, you can stub IGraphicsMode without implementing it.

We don't need to worry about #2 just yet: just hardcode the Silverlight platform into the OpenTK.Platform.Factory constructor. The long-term solution is to add a form of "plugin" interface to OpenTK, where the user can provide IPlatformFactory implementations at runtime.

For #3, the ideal solution is to add an exact WebGL binding to OpenGL. Since the exact WebGL specs are not released yet, we can fake this by using the OpenGL|ES bindings. This requires a small (but not exactly terrible) hack: in the Silverlight IGraphicsContextInternal.LoadAll() implementation we can use reflection to reroute the OpenGL|ES delegates to call (for example) gl.Invoke("createBuffer") instead of using the "createBuffer" p/invoke.

I guess an experienced Silverlight hacker could piece together an alpha implementation without too much trouble (it's certainly easier than dealing with the madness of X11 or win32!) As I said before, I am not familiar with Silverlight but I can certainly help with any issues that arise on the OpenTK part.