I'm playing around with WebGL, and I can successfully render a video element to a WebGL context with texImage2D. However, I'm now trying to crop this video element before rendering it. For example, I want to take the top half of the video element and draw it in the left half of my GL context; and the bottom half in the right half.
What is the best practice for this "crop action" in WebGL 1?
I have figured out that I can adjust the viewport to render something in the left/right half, but I can't seem to find how to crop.
It would be nice if texImage2D supported offset and dimension parameters for video elements, but that's not the case.
Maybe I can adjust this in the texture parameters or something?
In WebGL1 there is no easy way to crop at the texImage2D level. I suggest you just put the entire video frame into 1 texture and then use texture coordinates when rendering to select the part of the texture you want to display in each area
Related
I was working on a real time whiteboard.
I want to create an Infinite canvas, which can be zoomed using the mouse wheel and panned using drag, using javascript.During the zoom and pan the items drawn on the canvas must also be affected. Is there a was to achieve this without using any external library?
Yes, but it'll take a bit of work. The general idea of what you'll do is the following:
You will need to keep track of the position of the "camera", as well as how close it is to the content - a zoom factor
You will need to attach event listeners to different mouse actions to cause the camera's state to change
When you drag or zoom, you will need to redraw your canvas with the new positions and sizes of all the content. Some math will have to be done to know what the new canvas content is.
There may or may not be certain performance issues you have to address if there's a lot of content on the canvas.
An alternative, possibly quicker approach, but maybe less powerful, would be to not use canvas, and use some CSS magic instead with plain HTML. The basic concept here is that you'll have a 0x0 div as your plane. That div will contain your content, which may include content such as custom SVGs. Each of its children will break out of the div, and will be positioned relative to it. When you drag, you just move the div (through transform: translate()). When you zoom, you just scale the div (through transform: scale()).
Some useful references if taking the second approach:
CSS transform - to move and scale the whiteboard
CSS position - to position content on the whiteboard, and for the general layout
CSS overflow - to crop the whiteboard
The canvas element itself won't be infinite, I guess that's clear enough. What will change when you drag and zoom is the mapping of the real coordinates of your whiteboard elements to the drawing coordinates on the canvas. There's some work to do with detecting the mouse events and doing the calculations for updating the mapping, so there are too many specifics to really put in an answer. But yes of course this is possible without an external library.
Basically canvas could not be set to infinite sized. All you can do is to draw the portion that should be visible in the canvas.
first of all you should store all the points you have drawn to an array.
whenever you pan your canvas , track the offset that you have panned. this offset values can be used to reposition your stored points in your canvas.
eg. suppose you have drawn a line from (50 , 50) to (100 , 100).
let the offsets be {x:0 , y:0}
x , y offsets shows how much x and y distances you have panned in total
then update the points by adding the offsets and redraw
https://github.com/TomHumphries/InfiniteCanvasWhiteboard
here is a simple html5 whiteboard created by Tom Humphries which has infinite zoom and pan.
Usually when an image is being resized in javascript or css3(using background-size), it will stretch an image from the center point. I need an image to be stretched and distorted from a single point that could be anywhere. It's going to be dynamic so I don't want to resort to using separate images.
Here's a pic that illustrates what I mean:
Hopefully there's an answer out there!
You have a few options to achieve this effect.
The "correct" way would be to use canvas to draw the image: Skewing images individually using canvas
Another way would be to fake the effect using the CSS transform skew.
http://developerdrive.com/demo/skewing_elements/skewing_elements.html
You would do this inside an element with "overflow: hidden" to make it look like a background image.
It's not even clear to me what you want from the image you're linking too. Do you want it distorted or not? And is the distortion uniform?
I'm going to guess whatever you're doing can be approximated by drawing an ever decreasing set of (or maybe rectangles) clipped from the center of a some image and drawing them onto a "canvas" (think generic term not html5 term) given new coordinates for the center of each clipping. There may be a faster way to draw this than redrawing parts of the image multiple times, it's just how I visualize it possibly working.. at least maybe in some mathematical sense.
What I am trying to make is some kind of scrollable viewport in which a really large image is loaded (as in 10.000 x 10.000 pixels or more) and I should be able to draw some lines / shapes on this image.
There are two methods I can think of to draw the image / allowing the shapes to be drawn:
Using an tag to draw the image and draw a canvas the size of the image above it.
Using the drawImage() method to draw the image and just use a canvas.
I have tried both cases but when I load an image (in the img tag or using the javascript Image() object) it consumes about 500MB of memory.
I am wondering if there is a more efficient way to accomplish this.
Never ever make a user download an image that size unless you absolutely have to.
Make 100 smaller tiles (or thereabouts) of the image and draw the tiles to the Canvas, only drawing the tiles that can be seen at the current time (like google maps, etc do).
I have 2 canvas in a div. I tried to translate one of the canvas, but it didn't work.
http://jsfiddle.net/VkbV5/ shows the case where i commented off the translation line:
this.innerElement2Ctx.translate(100,100);
But when I include the line, the small square disappeared. Why? If you run this page in browser and inspect the innerElement2, you will see that it didn't move at all, but the small square disappeared.
For your information, I need 2 canvas, because I am planning to attach mouse event to innerElement2.
Translating a context adjusts where the 0,0 point is for future drawing commands; scaling a context adjusts how large items draw on the canvas; rotating a context adjusts the direction that items are drawn. None of these context transformations adjust the size or position of the canvas box itself.
Here's an example I made of adjusting canvas transformation so that drawing the same commands allows the user to zoom and pan around a canvas drawing:
http://phrogz.net/tmp/canvas_zoom_to_cursor.html
If you want to move the placement of a canvas within your HTML page, use simple CSS placement as you would with any other element, e.g. a <div>.
If you want complex 2D or 3D transformations you can use cutting edge features of CSS for this (as supported by modern browsers). For example, see:
https://developer.mozilla.org/en/CSS/transform#CSS_transform_functions
I'm making a canvas-based game engine and am wondering if anyone has any good info on how to achieve an overhead view perspective. What I'm looking for is somewhere halfway between the traditional birds eye view and the old SNES mode7 view. Just a slight angle to give the illusion of 3D.
I'm trying to figure out what is going to be the best way to deal with the perspective skewing. I'm not doing rotations so 3D matrix stuff would be going overboard, but I need to be able to deal with rendering the map layers at a consistent angle and it'd be nice if the angle was adjustable. I also need to deal with the depth warp. Basically, the bottom row of pixels should be 1:1 pixel width and height, then for each row it'd get, for example, 5% smaller or something like that. What I'd like is to be able to supply a large canvas as a texture and then supply a camera angle between 0 and 90 where 0 is perfectly horizontal and 90 is birds eye view.
Anyone have any related tutorials or sample code? I've searched online a bit, but everything I've found seems to either be unsuitable for use in this particular application or overly complex, doing all sorts of crazy 3D skewing and rotation stuff. All I want is to take the normal tiled grid and lean it back a bit, no rotations or complicated stuff like that.
Here's an example of what I want;
Here's an example. http://img801.imageshack.us/img801/2176/perspectivesample.jpg
The bottom pixel row is 1:1 pixel ratio, and each row above that progressively gets shorter horizontally and vertically. The source texture of the top center region is normally about half the height of the bottom center region, but it has been shrunk vertically and horizontally to fit the perspective.
What I'm thinking might work best is to render the current viewport state to another canvas in flat, birds eye view, with approximately 50% extra space on the top and sides, then slice an upside triangular region from that and draw that to the actual visible canvas.
Only problem is, I suck at math when it comes to calculating angles and such.
if i understand you right, you just want a simple trapeze transformation. if so, maybe this or this link helps you out. for images that aren't centered it would just be an additional rhomboid tranformation, wich is easily possible with canvas, as far as i know.
What you're talking about is something that can be done simply with any 3D api. However since you've decided to try to stick to 2D canvas, you have to do everything in the 2D world which means working with rectangles, rotation, scaling, skewing, etc. Also know as affine transformations as mentioned the other answer.
What you want to do is possible, but since you want to use 2D you have to think in terms of 2D functions.
Generate your initial image.
Add a slice from the bottom of the original image to the bottom of the canvas, very slightly positioned to the left so the center of the image matches up with the center of the current canvas.
Very slightly increase the scale of the entire image
Repeat until you get to the top of the image.
The Pseudo code would look like this...
imgA = document.getElementById('source');
// grab image slices from bottom to top of image
for (var ix=height-slice_height;ix>=0;ix-=slice_height)
{
// move a section of the source image to the target canvas
ctx.drawImage(imgA, 0,ix,width,slice_height,
0-half_slice_width_increase,width,slice_height);
// stretch the whole canvas
ctx.scale(scale_ratio, 1);
}
This will take lots of tweaking, but that is the general solution.
scale_ratio will be a number slightly larger, but very close to 1.
ctx is the standard canvas 2D context
half_slice_width_increase is the 1/2 the amount the canvas will grow when scaled by the scale ratio. This keeps the scaled image centered.
To look correct you would want to transform the background tiles first before you add the icon overlays.