2

I'm learning WebGL from this tutorial: https://developer.mozilla.org/en-US/docs/WebGL/Animating_textures_in_WebGL and in the last lesson it shows how to use video object as a texture. There's a live example here: https://developer.mozilla.org/samples/webgl/sample8/index.html which works just fine (I'm using Firefox). The problem is when I tried to do that myself I ran into problems. Ever more weird, I have different error messages at my pc (offline) and at my hosting (online). Offline error:

file:///C:/Users/NPS/Desktop/gallery/video.html(351): SecurityError: The operation is insecure.

where line 351 is:

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, videoElement);

Firefox developer toolbar says additionally:

Error: WebGL: It is forbidden to load a WebGL texture from a cross-domain element that has not been validated with CORS. See https://developer.mozilla.org/en/WebGL/Cross-Domain_Textures

I've read about that error and it seems strange that it doesn't work since the html and video files are both in the same place. Also when I open the page the sound from the video file is actually played (but that's about it). On the other hand, the online version's error is different (but I can't place it here because it's in polish and I'm not sure what's the exact english counterpart. But if you have Firefox you can check it here: http://nps.netarteria.pl/gallery/video.html (I'm using firefox developer bar for that). Of course, you can check the page's source code and everything I'm using there too.

Any idea what can I do to make it work? I'd really like to have video textures in my project and right now I'm stuck.

NPS
  • 6,003
  • 11
  • 53
  • 90

2 Answers2

7

The problem with your sample is that your video texture is not a power of 2 and you haven't setup texture filtering to handle that.

Change line 353 from

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);

to

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

and add these 2 lines

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

Also remove the call to gl.generateMipmap(GL_TEXTURE_2D) as you can't generate mips for non-power-of-2 textures.

You can read about the issues with non-power-of-2 textures on the WebGL Wiki

The sample on the MDN site has been broken for a long time and no one has bothered to fix it :-( It used to work because of a bug in Firefox that has long since been fixed.

Note: Chrome 25 (Chrome Canary) will print some messages that make help point this out. When I run your sample on Chrome 25 I get the following messages

WebGL: INVALID_OPERATION: generateMipmap: level 0 not power of 2 or not all the same size video.html:1
WebGL: drawElements: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete' 
gman
  • 100,619
  • 31
  • 269
  • 393
  • Thx a lot, this works! I've got 2 follow-up question though: (1) Why the MDN example works even without your proposed fixes? (2) On my pc I still get the security issue message and testing code by constantly uploading it to a server is tiresome - is there a way to run it on my pc? – NPS Nov 27 '12 at 14:11
  • 2
    It works in FF because of a bug in their video decoder. Play the video directly (https://developer.mozilla.org/samples/webgl/sample8/Firefox.ogv) notice in FF it's just a square (a power-of-2) and is missing the left and right sides of the video. Play it in Chrome and it shows the entire video (which is not a power-of-2). As for running it locally, for video I used node.js. Install node.js (nodejs.org) then install http-server (http://stackoverflow.com/questions/12905426/faster-alternative-to-pythons-simplehttpserver) – gman Nov 28 '12 at 01:15
  • Actually rather than "bug" it should say "difference". That FF decodes only a portion of that video is apparently not a bug. But the WebGL sample is still bad as it only works for power-of-2 videos. I fixed the mdn wiki. Hopefully someone will fix the real sample code. – gman Nov 28 '12 at 01:58
  • There's more NPOT issues with the above example. Change: gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) to: gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) and: gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) to gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) – Cory Jul 15 '13 at 17:01
0

For Chrome you can try shortcut with parameter "chrome.exe --allow-file-access-from-files"

JAre
  • 4,666
  • 3
  • 27
  • 45
  • On Chrome with or without what you suggested I get a scene with almost everything working... except the model (box) is black. But I can hear the sound from the video. – NPS Nov 26 '12 at 21:01
  • @NPS Your video encoding supported by chrome ? Also add this parameter "--disable-web-security" (it will disable same origin policy) just in case :) – JAre Nov 26 '12 at 21:12
  • My chrome says it doesn't even know that parameter. :P Besides, guys, I'm looking for a universal solution (and btw I think my problem isn't browser-connected). – NPS Nov 26 '12 at 21:58