enable webGL automatically? - javascript

I am using glfx.js jquery plugin for adjusting image's hue/saturation but most of the browser not supporting WebGL
is there a way to automatically enable webgl in browser if website uses it?
I know that you need to enable it manually in Safari, and there is a plugin for IE.
Or Is there any way so we can know at the time of page load that WebGl is disabled ?

There isn't a way to automatically enable WebGL in a browser. It's in the hands of the browser vendor to enable it by default - Safari and IE are the two latecomers in that area. WebGL is coming in IE11 (source), and I would imagine the next release of Safari will have it on by default (it's been over a year since the last release).
You can however detect if WebGL is enabled.
As you're probably aware, glfx.js spits out an error message if WebGL isn't enabled. It sounds like you're trying to take some other action if that's the case (no WebGL support).
Looking at the glfx.js documentation, they provide this example:
window.onload = function() {
// try to create a WebGL canvas (will fail if WebGL isn't supported)
try {
var canvas = fx.canvas();
} catch (e) {
alert(e);
// Here is where you want to take some other action
// For example, redirecting to another page with window.location.href = ...
return;
}
}
For those reading this not using glfx.js, theeasiest check is to use !!window.WebGLRenderingContext, but that doesn't always work (some browsers throw back false positives). Your best be is to create a canvas element and check for the WebGL context:
function webGLSupport()
{
var canvas = document.createElement( 'canvas' );
var webgl = false;
try
{
webgl = !!( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) );
}
catch(e) {};
return webgl;
}

Related

The blur filter doesn't work on discord.js [duplicate]

It seems like ctx.filter = "blur(amount)" doesn't work. Here's my code:
const {
body
} = await request.get(
url
);
const data = await Canvas.loadImage(body);
ctx.filter = "blur(50px)"
ctx.drawImage(data, 0, 0, canvas.width, canvas.heigth)
const final = new Discord.MessageAttachment(
canvas.toBuffer(),
"blurred.png"
);
Yeah it's for Discord.
Indeed they still don't support this feature.
Here is the issue tracking the feature request.
Apparently, these filters are not built-in Cairo, the rendering engine used by node-canvas, however Skia, an other rendering engine that node-canvas could switch to in the near future apparently does. So there is hope it comes one day, but for the time being, we have to implement it ourselves.
For gaussian blur, you can look at the StackBlur.js project, which was the de-facto blur filter library before browsers implement it natively. Here is a glitch project as an example.

Blurring image with canvas nodeJS

It seems like ctx.filter = "blur(amount)" doesn't work. Here's my code:
const {
body
} = await request.get(
url
);
const data = await Canvas.loadImage(body);
ctx.filter = "blur(50px)"
ctx.drawImage(data, 0, 0, canvas.width, canvas.heigth)
const final = new Discord.MessageAttachment(
canvas.toBuffer(),
"blurred.png"
);
Yeah it's for Discord.
Indeed they still don't support this feature.
Here is the issue tracking the feature request.
Apparently, these filters are not built-in Cairo, the rendering engine used by node-canvas, however Skia, an other rendering engine that node-canvas could switch to in the near future apparently does. So there is hope it comes one day, but for the time being, we have to implement it ourselves.
For gaussian blur, you can look at the StackBlur.js project, which was the de-facto blur filter library before browsers implement it natively. Here is a glitch project as an example.

Webgl context is null if 2d context is called on canvas

I wrote the following JS code:
var main=function() {
var CANVAS=document.getElementById("your_canvas");
CANVAS.width=window.innerWidth;
CANVAS.height=window.innerHeight;
//ctx=CANVAS.getContext("2d");
//ctx.fillText("Hello World",10,50);
/*========================= GET WEBGL CONTEXT ========================= */
var GL;
try {
GL = CANVAS.getContext("experimental-webgl", {antialias: true});
} catch (e) {
alert("You are not webgl compatible :(") ;
return false;
}
var CUBE_VERTEX= GL.createBuffer ();
};
If I uncomment the two commented lines, then the webgl context is NULL. Is this expected ? It's not possible to use 2D context and webgl context on the same canvas ?
This is expected, as webgl basically is a wrapper around opengl, primarily used for accelerated 3D rendering. getContext("experimental-webgl") is essentially telling the browser, that the defined canvas is to be used exclusively by OpenGL/WebGL. (It is possible to use OpenGL/WebGL for 2D, but unless you know what you are doing, you're giving yourself a hard time in doing so.)
If you are trying to render text on top of a 3D view, you will have to overlay two different DOM-elements (or render the text with the correct projection in 3D, again hard time-territory).

Canvas toDataURL() returns blank image

I'm using glfx.js to edit my image but when I'm trying to get that image's data using the toDataURL() function I get a blank image (width the same size as the original image).
The strange thing is that in Chrome the script works perfect.
What I want to mention is that the image is loaded in canvas using the onload event:
img.onload = function(){
try {
canvas = fx.canvas();
} catch (e) {
alert(e);
return;
}
// convert the image to a texture
texture = canvas.texture(img);
// draw and update canvas
canvas.draw(texture).update();
// replace the image with the canvas
img.parentNode.insertBefore(canvas, img);
img.parentNode.removeChild(img);
}
Also my image's path is on the same domain;
The problem (in Firefox) is when i hit the save button. Chrome returns the expected result but Firefox return this:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA7YAAAIWCAYAAABjkRHCAAAHxklEQVR4nO3BMQEAAADCoPVPbQZ/oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
... [ lots of A s ] ...
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAzwD6aAABkwvPRgAAAABJRU5ErkJggg==
What could cause this result and how can I fix it?
Most likely there's some async event between the time you draw to the canvas and the time you call toDataURL. By default the canvas is cleared after every composite. Either prevent the canvas from being cleared by creating the WebGL context with preserveDrawingBuffer: true as in
var gl = canvas.getContext("webgl", {preserveDrawingBuffer: true});
or make sure toDataURL is called before exiting whatever event you're using to render. For example if you do this
function render() {
drawScene();
requestAnimationFrame(render);
}
render();
And somewhere else do this
someElement.addEventListener('click', function() {
var data = someCanvas.toDataURL();
}, false);
Those 2 events, the animation frame, and the click are not in sync and the canvas may be cleared between calling them. Note: The canvas won't appear cleared as it's double buffered but the buffer toDataURL and other commands that effect that buffer are looking at is cleared.
The solution is either use preserveDrawingBuffer or make your call to toDataURL inside the same event as rendering. For example
var captureFrame = false;
function render() {
drawScene();
if (captureFrame) {
captureFrame = false;
var data = someCanvas.toDataURL();
...
}
requestAnimationFrame(render);
}
render();
someElement.addEventListener('click', function() {
captureFrame = true;
}, false);
What's the point of preserveDrawingBuffer: false which is the default? It can be significantly faster, especially on mobile to not have to preserve the drawing buffer. Another way to look at it is the browser needs 2 copies of your canvas. The one you're drawing to and the one it's displaying. It has 2 ways to deal with these 2 buffers. (A) double buffer. Let you draw to one, display the other, swap the buffers when you're done rendering which is inferred from exiting any event that issued draw commands (B) Copy the contents of the buffer you're drawing to do the buffer that's being displayed. Swapping is much faster than copying. So, swapping is the default. It's up to the browser what actually happens. The only requirement is that if preserveDrawingBuffer is false that the drawing buffer get cleared after a composite (which is yet another async event and therefore unpredictable) if preserveDrawingBuffer is true then it must copy so that the drawingbuffer's contents is preserved.
Note that once a canvas has a context it will always have the same context. So in other words let's say you change the code that initializes the WebGL context but you still want to set preserveDrawingBuffer: true
There are at least 2 ways.
find the canvas first, get a context on it
since the code later will end up with the same context.
<script>
document.querySelector('#somecanvasid').getContext(
'webgl', {preserveDrawingBuffer: true});
</script>
<script src="script/that/will/use/somecanvasid.js"></script>
Because you've already created a context for that canvas whatever script comes after will get the same context.
augment getContext
<script>
HTMLCanvasElement.prototype.getContext = function(origFn) {
return function(type, attributes) {
if (type === 'webgl') {
attributes = Object.assign({}, attributes, {
preserveDrawingBuffer: true,
});
}
return origFn.call(this, type, attributes);
};
}(HTMLCanvasElement.prototype.getContext);
</script>
<script src="script/that/will/use/webgl.js"></script>
In this case any webgl context created after augmenting the getContext will have preserveDrawingBuffer set to true.

Three.js detect webgl support and fallback to regular canvas

Can anyone who has used three.js tell me if its possible to detect webgl support, and, if not present, fallback to a standard Canvas render?
Yes, it's possible. You can use CanvasRenderer instead of WebGLRenderer.
About WebGL detection:
1) Read this WebGL wiki article: http://www.khronos.org/webgl/wiki/FAQ
if (!window.WebGLRenderingContext) {
// the browser doesn't even know what WebGL is
window.location = "http://get.webgl.org";
} else {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("webgl");
if (!context) {
// browser supports WebGL but initialization failed.
window.location = "http://get.webgl.org/troubleshooting";
}
}
2) Three.js already has a WebGL detector:
https://github.com/mrdoob/three.js/blob/master/examples/js/Detector.js
renderer = Detector.webgl? new THREE.WebGLRenderer(): new THREE.CanvasRenderer();
3) Check also the Modernizr detector:
https://github.com/Modernizr/Modernizr/blob/master/feature-detects/webgl.js
Juan Mellado's pointer to the Three.js detector was super useful, but I prefer not to bring the whole file into my project. So here is the extracted Detector.webgl() function.
function webglAvailable() {
try {
var canvas = document.createElement("canvas");
return !!
window.WebGLRenderingContext &&
(canvas.getContext("webgl") ||
canvas.getContext("experimental-webgl"));
} catch(e) {
return false;
}
}
And it is used similar to his example:
renderer = webglAvailable() ? new THREE.WebGLRenderer() : new THREE.CanvasRenderer();
Unfortunatelly, just detecting WebGL support does not automatically mean it will be any good. WebGL can be backed by software renderer like "google swiftshader" or partial emulation like "mesa 3D". Especially with a good 2D renderer like Mesa 2D it makes sense to manually choose canvas even when WebGL seems available.

Categories