I drew some quad like this with OpenGL:
_______ _______
| || |
| || |
| || |
|_______||_______|
currently I draw second quad using firstQuad.pos.x + width which is calculated manually.but when I want to scale them in at center point, I was wondering is it the right way to use calculated value, or use glTranslatef one by one, then glTranslatef to center of them, then use glScalef to scale them in? or how to do it right?
Unless you are updating quad's position firstQuad according to your transformations, yes, you will have to use the GL matrix manipulation functions as you described. I'm assuming you are using legacy GL here (2.1 and older), modern releases no longer provide matrix manipulation functions.
What you must understand is that a GL transformation must be seen as a transformation on the base and origin that will be used for further draw calls, until reset to a previous state with glPopMatrix().
Related
I'm in a situation where I have a (n+1)x(n+1) texture attached to a framebuffer.
My idea is to update this texture in 2 passes.
Draw a full screen quad and use the scissor test to mask out the outermost 1 pixels, so I write to the n x n 'inner' of the texture.
Second pass where I draw line primitives to write to the outermost pixels, and update the same texture, using the result of pass 1 as input. The computation on this step depend on the state of the inner (n x n) grid which was computed in the first pass.
In the second pass I would bind the result of the first pass for both reading and writing. I know that according to OpenGL this would yield undefined behaviour, but since I am never reading and writing simultaneously from the same texels, I think it could work.
Is it a good idea to do it like this, or is it perhaps better to draw a full screen quad, and in my glsl shader do a check like:
if (gl_FragCoord.x == 0.5 || gl_FragCoord.x == n + 0.5){
...
}
As you say, OpenGL says it's undefined behaviour, so it won't work. Your best bet for things like this is to ping-pong between two render targets.
Since I am never reading and writing simultaneously from the same
texels, I think it could work.
Unfortunately this doesn't help. Actually, there are extensions common on mobile (particularly Mali and PowerVR GPUs) that allow you to read and write simultaneously, but only if it's the same texels. Google 'Pixel Local Storage' for details.
I am looking for Javascript libraries that can help me do the following:
1.Given an image. Crop it using 4 coordinates points. (this may result in a non regular quadrilateral)
2.Transform the new image into a regular rectangle.
There is an example here.
I've looking at libraries like JCrop (and many others), but as far as I can see it only crops using regular rectangles.
The libraries could either be for client or node.js.
Bonus points for a computer vision library that can do corner detection.
Many thanks,
As far as i can see the "transformation" just crops the image anyway.
So just first transform the 4 coordinates to a regular rectangle and then use a library like JCrop.
Example: (each coordinate is x,y)
[left-up] | [right-up]
[left-down] | [right-down]
4 coords:
22,11 | 45,13
25,56 | 47,62
Rectangle:
25,13 | 45,13
25,56 | 45,56
I'd like to draw semi-transparent primitives with GLKit. I already disabled depth testing via glDisable(GL_DEPTH_TEST) and enabled blending via
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Now for large alpha values (e.g. 0.9), I need to draw the farthest triangles first so they don't appear above nearer triangles. This is also stated in the documentation for glBlendFunc:
Transparency is best implemented using blend function (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) with primitives sorted from farthest to nearest. Note that this transparency calculation does not require the presence of alpha bitplanes in the frame buffer
And in the OpenGL transparency FAQ:
When using depth buffering in an application, you need to be careful about the order in which you render primitives. Fully opaque primitives need to be rendered first, followed by partially opaque primitives in back-to-front order. If you don't render primitives in this order, the primitives, which would otherwise be visible through a partially opaque primitive, might lose the depth test entirely.
But as the viewing angle can change (when I change the render effect's modelViewMatrix), the farthest-to-nearest order depends on the current viewing angle.
Is there a way to have OpenGL automatically render my primitives in the right order, and if not, what would be the best way to proceed? I think that calculating the z-position of (depending on the current viewing angle) and ordering a few thousand triangles for each frame (or, more precisely, each time the viewing angle changes, which can be each frame) would be too cost intensive, especially as I'd need to push this order to the GPU for each frame.
Note that I'm not concerned with using textures (just colored vertices).
There's no automatic solution because there's no robust real-time solution due to the problem of mutual overlap. If you'll forgive the ASCII art, consider four quads arranged as:
+--+ +--+
| | | |
+---------------------| |------+
| | | |
+---------------------| |------+
| | | |
| | | |
| | | |
+----| |-----------------------+
| | | |
+----| |-----------------------+
| | | |
+--+ +--+
There is no correct ordering. You'd need to split at least one of the quads into two — which is what an ahead-of-time scheme like building a BSP tree would do. That's why depth buffering exists; to solve this problem per-pixel on the basis that most geometry is opaque.
So the best ways to proceed are:
build a BSP tree for your transparent geometry (for complete accuracy);
build a per-object BSP tree for transparent geometry, sort objects back to front (for pretty good accuracy);
require that objects have only more-or-less convex transparent segments, so that you'd end up with a BSP tree with a single leaf were you to build one, sort back to front (for reasonable accuracy, depending on your art);
use additive blending and draw in any order with depth writes off, after having drawn all opaque geometry (for a different look but no ordering concerns).
First of all, no, there is no way to have OpenGL do this for you. You'll have to manually sort your transparent geometry, based on the current camera and model position (i.e. the modelview matrix).
To implement this, in real-time implementations you don't usually sort individual triangles, but logical subsets thereof (meshes, submeshes). Problem cases then become:
Non-convex geometry in a single rendered element. Usually solved by
splitting the geometry up manually beforehand, or ignoring the artifacts.
Intersecting geometry of different elements. Usually not solved.
Performance-wise it is important that, while constructing your scene, you split up your elements in (partially) transparent v.s. non-transparent. This way you avoid large sort operations, as you only need to sort the transparent geometry.
Advanced techniques
For a completely different approach, look up depth peeling and similar techniques. When done right, those techniques have a lot to offer. However, I don't know of any OpenGL ES titles actually implementing them. That doesn't mean it's not an option though.
However...
If you are not very familiar with 3D programming in general yet, I'd strongly advise to stick with the manual sort and try to reduce the artifacts to a minimum. This way you can make an informed decision whether such an implementation is sufficient or not for your particular case.
If nothing else, implementing this stuff will automatically grant you the superhuman ability to immediately spot (and be hugely distracted by) transparency-related rendering issues in every videogame you´ll ever play from now on. A marvelous skill to have.
I'm looking for deep understanding of how WebGL works. I'm wanting to gain knowledge at a level that most people care less about, because the knowledge isn't necessary useful to the average WebGL programmer. For instance, what role does each part(browser, graphics driver, etc..) of the total rendering system play in getting an image on the screen?
Does each browser have to create a javascript/html engine/environment in order to run WebGL in browser? Why is chrome a head of everyone else in terms of being WebGL compatible?
So, what's some good resources to get started? The kronos specification is kind of lacking( from what I saw browsing it for a few minutes ) for what I'm wanting. I'm wanting mostly how is this accomplished/implemented in browsers and what else needs to change on your system to make it possible.
Hopefully this little write-up is helpful to you. It overviews a big chunk of what I've learned about WebGL and 3D in general. BTW, if I've gotten anything wrong, somebody please correct me -- because I'm still learning, too!
Architecture
The browser is just that, a Web browser. All it does is expose the WebGL API (via JavaScript), which the programmer does everything else with.
As near as I can tell, the WebGL API is essentially just a set of (browser-supplied) JavaScript functions which wrap around the OpenGL ES specification. So if you know OpenGL ES, you can adopt WebGL pretty quickly. Don't confuse this with pure OpenGL, though. The "ES" is important.
The WebGL spec was intentionally left very low-level, leaving a lot to
be re-implemented from one application to the next. It is up to the
community to write frameworks for automation, and up to the developer
to choose which framework to use (if any). It's not entirely difficult
to roll your own, but it does mean a lot of overhead spent on
reinventing the wheel. (FWIW, I've been working on my own WebGL
framework called Jax for a while
now.)
The graphics driver supplies the implementation of OpenGL ES that actually runs your code. At this point, it's running on the machine hardware, below even the C code. While this is what makes WebGL possible in the first place, it's also a double edged sword because bugs in the OpenGL ES driver (which I've noted quite a number of already) will show up in your Web application, and you won't necessarily know it unless you can count on your user base to file coherent bug reports including OS, video hardware and driver versions. Here's what the debug process for such issues ends up looking like.
On Windows, there's an extra layer which exists between the WebGL API and the hardware: ANGLE, or "Almost Native Graphics Layer Engine". Because the OpenGL ES drivers on Windows generally suck, ANGLE receives those calls and translates them into DirectX 9 calls instead.
Drawing in 3D
Now that you know how the pieces come together, let's look at a lower level explanation of how everything comes together to produce a 3D image.
JavaScript
First, the JavaScript code gets a 3D context from an HTML5 canvas element. Then it registers a set of shaders, which are written in GLSL ([Open] GL Shading Language) and essentially resemble C code.
The rest of the process is very modular. You need to get vertex data and any other information you intend to use (such as vertex colors, texture coordinates, and so forth) down to the graphics pipeline using uniforms and attributes which are defined in the shader, but the exact layout and naming of this information is very much up to the developer.
JavaScript sets up the initial data structures and sends them to the WebGL API, which sends them to either ANGLE or OpenGL ES, which ultimately sends it off to the graphics hardware.
Vertex Shaders
Once the information is available to the shader, the shader must transform the information in 2 phases to produce 3D objects. The first phase is the vertex shader, which sets up the mesh coordinates. (This stage runs entirely on the video card, below all of the APIs discussed above.) Most usually, the process performed on the vertex shader looks something like this:
gl_Position = PROJECTION_MATRIX * VIEW_MATRIX * MODEL_MATRIX * VERTEX_POSITION
where VERTEX_POSITION is a 4D vector (x, y, z, and w which is usually set to 1); VIEW_MATRIX is a 4x4 matrix representing the camera's view into the world; MODEL_MATRIX is a 4x4 matrix which transforms object-space coordinates (that is, coords local to the object before rotation or translation have been applied) into world-space coordinates; and PROJECTION_MATRIX which represents the camera's lens.
Most often, the VIEW_MATRIX and MODEL_MATRIX are precomputed and
called MODELVIEW_MATRIX. Occasionally, all 3 are precomputed into
MODELVIEW_PROJECTION_MATRIX or just MVP. These are generally meant
as optimizations, though I'd like find time to do some benchmarks. It's
possible that precomputing is actually slower in JavaScript if it's
done every frame, because JavaScript itself isn't all that fast. In
this case, the hardware acceleration afforded by doing the math on the
GPU might well be faster than doing it on the CPU in JavaScript. We can
of course hope that future JS implementations will resolve this potential
gotcha by simply being faster.
Clip Coordinates
When all of these have been applied, the gl_Position variable will have a set of XYZ coordinates ranging within [-1, 1], and a W component. These are called clip coordinates.
It's worth noting that clip coordinates is the only thing the vertex shader really
needs to produce. You can completely skip the matrix transformations
performed above, as long as you produce a clip coordinate result. (I have even
experimented with swapping out matrices for quaternions; it worked
just fine but I scrapped the project because I didn't get the
performance improvements I'd hoped for.)
After you supply clip coordinates to gl_Position WebGL divides the result by gl_Position.w producing what's called normalized device coordinates.
From there, projecting a pixel onto the screen is a simple matter of multiplying by 1/2 the screen dimensions and then adding 1/2 the screen dimensions.[1] Here are some examples of clip coordinates translated into 2D coordinates on an 800x600 display:
clip = [0, 0]
x = (0 * 800/2) + 800/2 = 400
y = (0 * 600/2) + 600/2 = 300
clip = [0.5, 0.5]
x = (0.5 * 800/2) + 800/2 = 200 + 400 = 600
y = (0.5 * 600/2) + 600/2 = 150 + 300 = 450
clip = [-0.5, -0.25]
x = (-0.5 * 800/2) + 800/2 = -200 + 400 = 200
y = (-0.25 * 600/2) + 600/2 = -150 + 300 = 150
Pixel Shaders
Once it's been determined where a pixel should be drawn, the pixel is handed off to the pixel shader, which chooses the actual color the pixel will be. This can be done in a myriad of ways, ranging from simply hard-coding a specific color to texture lookups to more advanced normal and parallax mapping (which are essentially ways of "cheating" texture lookups to produce different effects).
Depth and the Depth Buffer
Now, so far we've ignored the Z component of the clip coordinates. Here's how that works out. When we multiplied by the projection matrix, the third clip component resulted in some number. If that number is greater than 1.0 or less than -1.0, then the number is beyond the view range of the projection matrix, corresponding to the matrix zFar and zNear values, respectively.
So if it's not in the range [-1, 1] then it's clipped entirely. If it is in that range, then the Z value is scaled to 0 to 1[2] and is compared to the depth buffer[3]. The depth buffer is equal to the screen dimensions, so that if a projection of 800x600 is used, the depth buffer is 800 pixels wide and 600 pixels high. We already have the pixel's X and Y coordinates, so they are plugged into the depth buffer to get the currently stored Z value. If the Z value is greater than the new Z value, then the new Z value is closer than whatever was previously drawn, and replaces it[4]. At this point it's safe to light up the pixel in question (or in the case of WebGL, draw the pixel to the canvas), and store the Z value as the new depth value.
If the Z value is greater than the stored depth value, then it is deemed to be "behind" whatever has already been drawn, and the pixel is discarded.
[1]The actual conversion uses the gl.viewport settings to convert from normalized device coordinates to pixels.
[2]It's actually scaled to the gl.depthRange settings. They default 0 to 1.
[3]Assuming you have a depth buffer and you've turned on depth testing with gl.enable(gl.DEPTH_TEST).
[4]You can set how Z values are compared with gl.depthFunc
I would read these articles
http://webglfundamentals.org/webgl/lessons/webgl-how-it-works.html
Assuming those articles are helpful, the rest of the picture is that WebGL runs in a browser. It renderers to a canvas tag. You can think of a canvas tag like an img tag except you use the WebGL API to generate an image instead of download one.
Like other HTML5 tags the canvas tag can be styled with CSS, be under or over other parts of the page. Is composited (blended) with other parts of the page. Be transformed, rotated, scaled by CSS along with other parts of the page. That's a big difference from OpenGL or OpenGL ES.
or even better, is there software available which can do it?
--new detail
to people that is saying that it's impossible, I remember that at college, staring into the projector, the analogic focus could be changed so I could se a clear image without the glasses.
Sadly, no. The problem with myopia is that the light coming into the eye is not focused correctly upon the retina. No matter what you do to an image, that image will come in unfocused. Unfocusing the image in any way will just mean that the viewer will have a blurrier image of a blurry object.
The crazy part of this answer: this could be possible if you had a monitor that, for each pixel, could potentially shine at different intensities/colors at different emission angles. If you had that setup, and had an image that supported it, and you knew the exact amount to adjust by, and could get the person to sit in exactly the right spot, you could potentially adjust it to be focused. However, this is more of a conceptual pipe dream than feasible reality.
EDIT: Tom asked me to respond to this:
I remember that at college, stirring in the projector, the analogic focus could be changed so I could se a clear image without the glasses.
I'll assume that you had either an overhead/film/lcd projector or something similar...I'm guessing it doesn't make a difference. They have manual focus features that can be used to bring the image in or out of focus...this is used to allow the image to focus correctly at different wall/screen distances. I'm not sure exactly what you mean by "stirring in the projector"...but I'm going to assume you mean "staring into the projector".
I haven't tried this (and since I don't need glasses, I can't), but I suspect that this would work. But what you're doing is essentially the same thing as wearing glasses...you're looking at an image, and adjusting the focus to compensate for your myopia. The lens is inside the machine rather than in a pair of frames on your face, but the concept is otherwise very similar.
However, it doesn't mean that you can take an image on a screen and blur it and have it render correctly.
Without a diagram, it's difficult to explain why, but a simplified explanation about why they're not identical cases could be made like this...in the case of the projector/glasses, you're starting with a perfect image that isn't being focused correctly by a set of lenses, and then adjusting the lenses (adding glasses or changing focus on the projector) to correctly bring it into focus...and this is the critical part: you are not degrading the image in any way. You're just using refraction to change the angles at which the light is traveling.
On the other hand, if you have an image on a monitor, and you blur it in some way, you are changing and degrading the image itself. No matter how good the receptor viewing it is, the best it can do is the blurred image that is being displayed.
Okay, that's not satisfying probably, so I'm going to try to make a few pictures:
P will be our source point. It emits photons from it in every direction. Some of these photons go into our eye. If our eye is perfect, the lens focuses all of those rays onto a single point on the retina.
source point P
/|\
/ | \
/ | \
eye lens (ideal) ---------
\ | /
\ | /
\|/
retina ----p----
For simplicity, I've drawn only three photons being emitted from the source point, but in reality there would be a large number of them, at many different angles. The point is that all of them should be focused by the lens onto a single spot on the retina.
But in a myopic eye, the focal point is before the retina, and so the rays cross over and do not hit at the same point on the retina.
source point P
/|\
/ | \
/ | \
eye lens (myopic) ---------
\ | /
\|/
X
/ \
retina --p---p--
This is what causes blurring by myopia...each source point is seen a tiny bit in a few spots, rather than exactly one.
This also shows how glasses and staring into a projector can help...we're adding a second lens into the mix to compensate slightly for the not-perfect one. (Image slightly expanded)
source point P
/|\
/ | \
/ | \
glasses ---------------
/ | \
eye lens (myopic) ---------------
\ | /
\ | /
\ | /
\ | /
\ | /
\|/
retina -------P-------
Notice the path of the light bends outwards slightly by the glasses...this is how they compensate for the lens in your eye.
Now is there anything can can be done by blurring the original image to compensate for this? Unfortunately, no. If we try to do this, we end up with something like this, with the source point now blurred into two locations that we'll call Q and R. If things work perfectly the blurred P (now Q and R) should reconstitute themselves correctly back into P:
(I'm expanding the picture a bit for clarity...though it's still not great.)
First, we'll look at an ideal eye:
source point, blurred R Q
|\ /|
| \ / |
| \ / |
| \ / |
| \ / |
eye lens (ideal) --------------------
\ \ / /
\ \ / /
\ X /
\/ \/
/ X \
// \\
retina (and focus point) ------q-------r-----
We get exactly what we expect from the ideal eye...a perfect replica of the original (blurred) image. (It's reversed, but that's okay; the focusing of the eye always does that...the brain flips it around so it looks correct.)
So what happens when we try the blurred image with the myopic eye?
source point, blurred R Q
|\ /|
| \ / |
| \ / |
| \ / |
| \ / |
eye lens (myopic) --------------------
\ \ / /
\ \ / /
\ X /
focus point X X
/ / \ \
/ / \ \
retina --q-- q-------r---r--
As you can see, our image has just gotten worse. Instead of recombining Q and R back into P, it's blurred them even more. We've taken a blurry image, and just made it more blurry.
I know the pictures aren't great, but I hope this makes things a bit clearer (no pun intended.)
Another Edit:
Just as an aside, because I'm sure this will be brought up...the majority of the focusing power of the eye is not actually done by the "lens" of the eye, but rather by the cornea...or more specifically, light passing through the aqueous humor contained by the cornea. This is why laser surgery that reshapes the cornea can be used to correct eye focus problems. However, since "lens" is more familiar and makes semantic sense here, I'm sticking with that.
You would need a display which not only emits light, but emits that light into very specific directions such that it emulates the radiation falling into a mypic person's eyes when wearing glasses.
That would involve some kind of holographic display which I am not aware of existing at all.
In any case, this is a hardware (and wetware) problem, not a software one.
Update
For your case of directly staring into a projector (make sure you significantly dim the light beforehand to avoid completely ruining your eyes): You can focus the projector and put your eye into the proper position such that the radiation falling into the eye mimicks the radiation going through your glasses. You must not move your eye's position much, though.
I wouldn't say it's possible. I'm badly nearsighted and all I see without my glasses is a blur. As far as I know, it's not possible to create an image that looks sharp after getting blurred by the viewer's eyes.
If there is software that would do it, I suspect an optometrist would know about it because the obvious application is to have a patient correct an image until a prescription can be derived.
I don't know near enough about the eye or optics to know if this is possible but I suspect if you could model how prescription lenses alter the light going into the eye (and such a function is invertible), you could alter the image so the pixels get sent to the right part of the eye.
Given all that, I'm sure there's some science that makes this really hard, if not impossible.
Sure you can, its totally possible to distort displayed patterns to compensate for focus problem. By essentially de-focusing, or really producing an opposite focus you can effectively change the wave convergence on your retina. Now the down side is that the distortion would depend heavily on how far you are from the screen, and angle relative to the screen. So for example you would need to tune your TV every time you sat in a different place in your living room. In addition it would be a problem if there is more then one person watching. That's why tablets, laptops, and phones are probably a better option...assuming your willing to tune your screen to look at it (although technically with the proper camera detecting your pupillary distance, position, and facial recognition to load the right prescription profile it could be calculated dynamically within the device).
http://www.forbes.com/sites/jaymcgregor/2014/07/31/microsoft-and-mit-make-glasses-obsolete-with-new-display-technology/
http://televisions.reviewed.com/news/futuristic-displays-correct-your-vision-glasses-free
I add these two links, that somewhat answer the question. I don't think it's yes or no. There are pros and cons.
Virtual Glasses: The Myopic Revenge
Tailored Displays to Compensate for Visual Aberrations
I also update Brito's broken link of the "Apr 4 '10 at 23:22" comment:
Optics model for a Near-Sighted eye (with corrective lenses)
By the way, Brito, what are the characteristics of your eye condition (i.e., the parameters of your lens)?