So I'm gonna just delete most of this stuff, delete the settings so that we just have dimensions. And then delete the render stuff inside the render function just so we have a blank slate to work with, and then I save, we should have an empty canvas. Cuz right now if we save our image, we're gonna end up with a transparent PNG. So the first thing we have to do is set a fillStyle to white. And we fill a white rectangle the full size of the screen, so top left corner all the way to bottom right.
So outside of our render function, remember this our render function, we can actually before our render function, before we return it we can create some local state here. So I'm gonna create a function called create grid, and this function is gonna return basically the points on a grid.
So this is the grid size. So how many across by how many down? And if we look at, I'll just switch this for one second, I'll switch back. We can change that later, just for now. And then we're gonna have a nested four loop, so we're gonna create a four loop across and a four loop down.
These are the two axes, the two sort of coordinates that we're working with in two dimensions. And you basically say, x starts at zero, x continues to count, then we do the same thing for the y dimension. But right now we're just creating a two-dimensional grid.
WebGL - Modes of Drawing
And here is where we want to, we wanna have the point at each grid point. So we wanna basically figure out what's the pixel coordinate for each of those grid points. And this is an idea where you work in numbers between zero and one rather than working in your final pixel coordinates. And I like to work in UV space between zero and one just because then you can start to manipulate the numbers in different ways, and we'll start to see why it's useful. And so to get that we have to actually divide the x by the count, and that's gonna give us roughly a value between zero and one.
Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information.
I'd like to have a triangle that has thin, 1px lines every 10 units, and a thicker 2px line every units the units here being arbitrary but consistent with world-space, not screen-space. Here's what I have so far, without the secondary thicker lines like in the video note that this is literally a copy from my open buffer, and obviously isn't right :. It produces approximately the right image at a certain distance but notice the banding effect where there's 2px lines instead of 1px :. Grid with banding Zoomed in grid with unwanted thicker lines.
So, how can I get a consistent grid, with 1px thick lines at every distance, all inside of a WebGL fragment shader? Learn more. Asked 6 years, 2 months ago. Active 6 years, 2 months ago. Viewed 7k times. Why wouldn't you use texture for this kind of problem? They are much easier to use than writing fragment shader. Active Oldest Votes.
I believe I've found an acceptable solution. Using the following vertices drawn in a triangle strip : [ 1. It's fun to test this kind of stuff here.
The number in the top left sets the resolution. Sign up or log in Sign up using Google. Sign up using Facebook. Sign up using Email and Password. Post as a guest Name. Email Required, but never shown. The Overflow Blog.
Podcast Ben answers his first question on Stack Overflow. The Overflow Bugs vs.Creative Bloq is supported by its audience. When you purchase through links on our site, we may earn an affiliate commission.
Learn more. The first encounter with WebGL can be intimidating. The API has nothing of the friendly object-oriented libraries you might have used. It features a long list of functions used to set different states and pass data to the GPU. All of this is described in the official specification. This document is not intended for beginners, thought it will be very useful once you start to find your way around the API.
While WebGL has in fact a lot of features that will help you develop 3D applications, in itself it is not 3D.shader tutorial series - episode 023 - morph grid
Let's start adding some code inside this function. You can name it anything you want, but "gl" seems like a good convention. Note that the 3D context is called "experimental-webgl". This is a temporary solution until the browser manufacturers decide that it's stable. By then the name will change to just "webgl". Once we have the context, it's time to define the viewport and set some default colour to it.
The viewport defines the area you want to draw the WebGL content on: in our case it will be the whole canvas. Next we define a default colour for the viewport and call the clear function to set the viewport to this colour. Continue by adding the following lines:. Notice that colours in WebGL are not defined using hex notation but usually as four numbers, each in range  that define values for the Red, Green, Blue and Alpha channels separately. If you open the file in the browser you should see the canvas area painted in dark green.
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It only takes a minute to sign up.
I have created canvas x - and filled it with a grid. It works but the rendering of the grid lines takes around 3 seconds, which seems excessively long. Am I doing something wrong?
Quill already did a good job speeding up your code, so I'll focus on the code you have right now. Your drawGrid function takes the id of a DOM element that the function is expected to find on its own. However, this is not good practice. Instead, you should pass the DOM element itself. This could also speed up your code by a lot if used correctly. For more on why it's bad practice, think about it this way: if you need to do some specific checking on an element after you've found it before you are ready to give it to the function, how are you supposed to pass that prepared element to the function?
This is created every time your function is called. Assuming more drawing will take place in this code, why not put both the canvas and the context in a global scope? There is no point in finding the context, putting it in a variable, and then destroying it at the end of the function every time it is called. This makes absolutely zero sense.
First, you use the canvas to get the ctx. Then, you use the ctx to get the canvas again by accessing its properties. Why not just use the canvas that you literally just defined? Yes, the way you are currently forming the grid is very slow. As Quill has already shown, there are other options:. I did not test these out, so I don't know how much of a speed boost they provide if any. However, feel free to try some of them. URL window.
Of course, you'll need to play around with the sizes of the grid to match what you want.D3FC is a library which extends the D3 library, providing commonly used components to make it easier to build interactive charts.
We created a series of squares in the vertex shader before discarding any unneeded pixels in the fragment shader. The shapes had similar heights and widths, so this worked well - the fragment shader needed to discard relatively few pixels.
This blog explores a different approach to rendering in WebGL, looking at how to render lines with minimal data transferred across buffers and making best use of the shaders. Everything in WebGL is built using triangles. We can place two triangles next to each other to create a rectangle. Our first idea might be to connect each point to the next by drawing a rectangle between them. When we try this, however, we see that there is a problem with this technique. The two rectangles leave a dip at the top.
Instead of rectangles, we could draw trapeziums. These would allow us to fit two together without any overlap or gaps. This type of joint is called a miter. A triangle strip is a series of triangles which share vertices. We only have to define each vertex once, and WebGL will connect the triangles into a strip. B is the current point being considered by the vertex shader, A is the previous point, and C is the next point.
We can pass in these values through the buffers. To correctly translate the points to the vertices of the triangles, we need to know two things: how far to move them and in which direction.
To help us calculate the direction of the miter, we can use the miter tool which was developed by Tom McLaughlan. As you can see, the miter line is the normal vector to the tangent of the lines AB and BC. So if we find the tangent, we can use that to calculate the direction. We can calculate the tangent by adding the normalized vectors AB and BC.
However, the canvas we are drawing to is more likely to be a rectangle. One side effect of this mapping, though, is that the angles of the vectors in clip space are not the same as they will be on our canvas. We want whatever value we calculate for the vector to have a distance of 1 so that we can multiply it by the distance to get the correct value at the end.
To get around this, we can move the previous or next point in the opposite direction to the next or previous point, so that the three points are in a straight line.
Drawing the Grid
Well, it gives us one of them. We do this by loading in another array into the buffers: aCorner. We calculate normalA in the same way that we calculated the miter direction from the tangent. The width or thickness of the line can be passed in through the buffers and loaded as a uniformuWidth. Notice that we are also dividing by uScreen. As the angle between the two lines decreases, the miter length increases at an increasing rate.
Once we hit a pre-defined limit, we should cut off the point, so the corner of the line is flat. To do this, we need to increase the vertices per point to four.
This will allow us to calculate two vertices for the outer joint if the miter length is too large, as shown in the image above. We need to determine two things in our vertex shader: if the miterLength is above a certain threshold in this case, 10 and if the vertex we are processing is intended for the outer joint. The sign of the dot product of two vectors tells you whether the angle is acute or obtuse i.
Because aCorner.D3 is often used for rendering chart visualisations, and our d3fc library extends D3 with some commonly used components such as series. It offers SVG implementations, which are a bit more flexible and easier to interact with, and Canvas implementations, which offer better performance for large data sets. Eventually though, given enough data, even the Canvas renderers slow down. Are there other use-cases? I wanted to learn WebGL anyway, so as part of that learning I decided to find out.
These mirror the corresponding d3fc series components. This post is not going to be a tutorial for WebGL, since there are many excellent resources for that already. It seems like a strange thing to want to do. Why render a 2D scene in 3D space, only to project it back onto a 2D screen again? WebGL transforms each vertex in 3D space by simply multiplying it by a projection matrix, making it a point in 2D screen space.
It then just has to work out what colour each pixel should be, based on three vertices making up a triangle. Our projection is about as simple as they get. The attribute aVertexPosition is the incoming vertex, and is different each time the shader is run. The two uniform matrices are the same each time, and project the vertex into 2D screen space.
What about drawing lines? The line is then a series of boxes, where each one is a pair of triangles. That allows you to input one set of vertices, and output a different set of vertices for passing to the vertex shader. In our case, we could input the raw data points and use a geometry shader to calculate the set of triangles needed to render each point as a circle.
I wanted my WebGL series components to match the Canvas counterparts as much as possible. We also need to be able to customise things like the line and fill colours, and line thickness. You can read more about the decorate pattern here: d3fc decorate pattern.
I decided to mirror that pattern too, then read back those colours and the line thickness to use them when rendering the WebGL shapes. Like the points, it performs better if we use individual triangles rather than triangle strips. A point rendered as a circle requires many triangles. The bigger it is, the more triangles we need to make it look smooth. I mentioned above that it performs better using individual triangles rather than a triangle fan for each point.
What if we need to draw an outline around each point? Drawing a line around each circle has a dramatic impact on performance. Instead of that, can we do something sneaky with the shader programs? Earlier I described how WebGL interpolates variables that are passed into the fragment shader.Now it's time to run the file.
Find your personalised file on the desktop, and double-click on it to make it run. Then find the AutoHotKey icon on your toolbar, right-click it, and press 'Reload this script'.
Drawing 2D charts with WebGL
You can now use the shortcuts. Once the file's up and running, it can be edited at any time. Just find it on your desktop and right-click on it to edit the script. After it's saved, right-click on the AutoHotKey tool bar icon and select 'Reload this script'. This will make the changes. For a more advanced guide, use AutoHotKey's tutorials.
Often competition board threads involve opening lots of links to different contests. Google Chrome users can open several threads at once with the free LinkClump add-on. For email entries, draft and save a template email with your name, email, address and telephone number, so you can fire it off quickly. Remember to leave a space for the answer. Got a top tip we haven't listed. Sounds too good to be true, but it's legit. Several forumites have got lucky:On my sixth check I won.
And it was a rollover. Wonderfully timed as I recently lost my job. The MSE Deals team are all big fans (they even have a winner in their midst. For a full guide, read their Free Postcode Lottery guide. Never pay for postcards. Cinemas and library tills always have plenty of freebies. Buy sticky labels and print them out with your details to speed up entries.
With stamps, the only difference between first-class and second-class is that with first, Royal Mail aims to deliver your letter or packet the next working day. It aims to deliver second-class by the third working day. So unless the closing date's near, don't buy first.
Social media is a godsend for compers. Contests abound on Facebook and Twitter, so it may be worth signing up if you haven't already. To enter contests, you usually need to 'retweet' a firm's tweet (ie, repost it on your feed). Always do this directly from the promoter's Twitter page to be in with a chance.
Facebook comps usually involve 'liking' a company's page, so this is for those who don't mind their mates seeing what they're up to. The temptation's to set up two Facebook accounts, yet it's against Facebook's rules to have two, and a few MoneySavers have been banned for this.
It's hard to search for competitions on Facebook, so try searching for 'Facebook' on our Competitions board.