Sampling equirectangular textures

Suppose you want to do 360 panorama demo using equirectangular texture. Easy way would be to use sphere mesh, with enough triangles distortions are invisible, and the client is happy. The few of us, who are dealing with “make me another matterport” bullshit, are not so lucky – we have to project images onto complex meshes and, therefore, write the shaders. Continue reading ‘Sampling equirectangular textures’

What are UV coordinates?

Isn’t it amazing how many people in the field do not understand UV coordinates? I thought so too, so back in 2011 I took two images from Senocular article and made this animated GIF:


Well, I am just reposting it here now in case Alternativa3D wiki currently hosting it will go down, like their forum did.

Your stats are booming!

Apparently that is wordpress way to say

👍 your blog is dead, and we’re surprised someone has actually visited it!

Yay. I don’t write here very often, but when I do – nothing happens. People search for something in their favorite search engine, and sometimes my blog pops up. So they click, and sometimes they find my post helpful. Some other times they find it confusing, and most of the times it is simply not what they were looking for. But in all these cases they just close the tab afterwards. They do not comment. They do not discuss.

Where is everybody?

It could be just that my posts are bad. Or it could be that blogs are no longer relevant. People are not interested in blogs. People are not even interested in discussing their interest in blogs. Either way, I think I will find better ways to spend my time in coming year.

How to set object.matrix in three.js?

While all the top google hits for this problem revolve around messing with matrixAutoUpdate property, I thought I’d share this simple trick:

object.matrix.copy (...); // or fromArray (...), etc
object.matrix.decompose (

This only really works with the matrices that can be represented with three.js’ position/quaternion/scale model, but in practice this is vast majority of the cases. You’re welcome.

Using VideoTexture with Camera in AIR

These days I am trying to write simple iOS app that takes live camera stream and applies custom shader to it, as my pet project. And – surprise – I am doing this with AIR. That’s right, after I have finally come to terms with the fact that flash is dead and, considering how much GLSL is superior to AGAL as a shader language, I am still using AIR to build this app. Why? Because it works :) Unlike HTML5 aka flash killer. WebRTC is still not supported on iOS, and community polyfills simply are not enough to plug the gap. So, the only other option would be to use ObjC or Swift, but I know neither yet, while with flash I am at home (and, potentially, can easily port the app to Android later).

VideoTexture ?

Ok, so we have simple access to live camera feed, but how to bring it to Stage3D (flash version of WebGL) to apply the shader? Traditionally, we had to draw the display list video object into bitmap and re-upload it to GPU every frame, which was costly. But quite recently Adobe gave us more straightforward option – VideoTexture. Whole new runtime feature with amusing history, however, flash is still dead, so its documentation is crap. Just following NetStream-based snippets and changing attachNetStream to attachCamera like this

var videoTexture:VideoTexture = stage3D.context3D.createVideoTexture ();
videoTexture.attachCamera (camera);
videoTexture.addEventListener (Event.TEXTURE_READY, renderFrame);

did not work.

The missing piece ?

There is RENDER_STATE event that can tell you if video decoding is GPU accelerated (in the case of live camera stream it is not, btw). Turns out, you have to subscribe to this event even if you don’t care, or else the magic does not happen – camera stream data will never reach the texture and, correspondingly, TEXTURE_READY events will never fire. You’d think this is stupid and can’t possibly be true, but then adding event listeners is exactly how you get webcam activityLevel property to work, for example, so I am not surprised. With this, the final code to make it work is

var videoTexture:VideoTexture = stage3D.context3D.createVideoTexture ();
videoTexture.attachCamera (camera);
videoTexture.addEventListener (VideoTextureEvent.RENDER_STATE, function (e:*):void {
	// yes, we want TEXTURE_READY events
videoTexture.addEventListener (Event.TEXTURE_READY, renderFrame);

Old stuff

March 2023

Oh, btw…