I'm looking to capture a 360 degree - spherical panorama - photo of my scene. How can I do this best? If I have it right, I can't do this the ordinary way of setting the perspective to 360.
If I would need a vertex shader, is there one available?
This is actually a nontrivial thing to do.
In a naive approach a vertex shader that transforms the vertex positions not by matrix multiplication, but by feeding them through trigonometric functions may seem to do the trick. The problem is, that this will not make straight lines "curvy". You could use a tesselation shader to add sufficient geometry to compensate for this.
The most straightforward approach is two-fold. First you render your scene into a cubemap, i.e. render with a 90°×90° FOV into the 6 directions making up a cube. This allows you to use regular affine projections rendering the scene.
In a second step you use the generated cubemap to texture a screen filling grid, where the texture coordinates of each vertex are azimuth and elevation.
Another approach is to use tiled rendering with very small FOV and rotating the "camera", kind of like doing a panoramic picture without using a wide angle lens. As a matter of fact the cubemap based approach is tiled rendering, but its easier to get right than trying to do this directly with changed camera direction and viewport placement.
Related
This question already has answers here:
OpenGL ES 2.0 - Fisheye shader displays a grey image
(1 answer)
Shader - Anti fisheye by "pulling" pixels
(2 answers)
Closed 1 year ago.
I am trying to create lomo fisheye effect on an image using openGL.
Should I use cube mapping and fisheye projection? Is there any open source that I can refer to?
You can draw a single quad with the image textured onto it, and use a fragment shader to warp the texture coordinate per-pixel as you desire. You'll have to do all the math yourself, but it looks like the previous post here might be a good starting point.
Taking the question title beyond effect on an image to producing "true" fisheye views, ie. usable field of view 180+ degrees...
There are two slightly different methods to adapt existing pipelines to fisheye view (with "simple" OpenGL). Both require scene rendering for up to 6 times - for each side of the "box" that will be projected to a flat screen. Each side / surface must be square - or should be, depends on the method - and likely smaller than the original full viewport.
The number of sides required depends on how wide the fisheye field of view is requested. In a typical FPS, for a FOV of 130 - three sides is enough. For a FOV up to 220 - five sides.
Method 1 - cubemap texture (GL_ARB_texture_cube_map)
init once, for a specific FOV, pre-calculate a translation table of 2d on-screen coordinates to cubemap texture 3d coordinates, 16x16 grid for the whole screen should be enough
setup the viewport and position camera accordingly to render box sides, do the usual rendering
bind sides to the GL_TEXTURE_CUBE_MAP_ARB texture
iterate over screen emitting (rectangular) GL_QUAD_STRIP-s using the translation table and the cubemap.
Method 2 - 2d or rectangular textures (GL_NV_texture_rectangle)
init once, for a specific FOV, pre-calculate a "ray" table of texture + 2d texture coordinates to 2d screen coordinates
as in Method 1, setup the viewport and position camera accordingly to render box sides, do the usual rendering
bind sides to the GL_TEXTURE_RECTANGLE_NV or GL_TEXTURE_2D textures
iterate over textures emitting (trapezoid) GL_QUAD_STRIP-s on the screen using the "ray" table.
The Method 1 is simpler and delivers better results.
Gotchas:
set cubemap texture wrapping to GL_CLAMP_TO_EDGE
in a typical FPS, player view is not only pitch and yaw, but also roll - calculate camera orientation for each side via proper rotation
if the render loop is combined with progress / physics / ai, this repeated scene re-rendering may confuse existing internals.
This is all of course depends on the specifics of a particular engine. I'm not sure how well this applies to OpenGL 3.3+ core profile yet the idea should be the same.
It is possible to draw the world to fisheye in one pass by doing fisheye transformaion in vertex shader. But! it requires original geometry sufficiently (pre-)tessellated. Or, it could be possible to employ Geometry Shader and/or Tessellation Shaders to organize tessellation / transform feedback on the GPU. The later should be built into the rendered from the ground up, perhaps.
For a well-isolated example using Quake 1 engine see Fisheye and Panorama OpenGL FPS and this diff specifically. Unfortunatelly, the vertex shader example is lost.
I have a 3D scene I'm drawing and I want to draw a rectangle for a dialogue text that will be stretched for all the screen's width, what's the best way to achieve this, having performance in mind?
I found about glOrtho() that I can use for exact pixel placing, but since it's a matrix multiplication task, won't my app feel much heavier during scenes with dialogues?
If yes, should I try to find a math solution to find the X position of my left window corner according to some Z distance and draw a QUAD from there? (Is this even possible?)
glOrtho() is the way to go.
In the course of OpenGL's rendering Pipeline, during the Primitive Assembly stage, every vertex will be transformed (projected) from eye coordinates to clip coordinates. Whether your projection matrix is used for 3D perspective or 2D orthogonalization, it's still one matrix multiplication per vertex before Rasterization starts.
glOrtho() will change your projection matrix to an orthographic one but the matrix only needs to be generated once per frame and the equations required to do so are very simple:
(image credit: MSDN)
Once you have a projection matrix, don't let the thought of matrix multiplication scare you. It's exactly what video cards are designed to do and it's hardly a frightening task for any processor or GPU these days.
I have a struct QUAD that stores 4 pointers to 4 VECTOR3D (which contains 3 floats) so that I can draw the quad mesh.
From what I understand is whenever I draw a mesh, I need normal as well to properly light/shade a mesh and it's relatively easy when it's a mesh laying on a plain, using normal per face.
When I have 2 by 2 quad meshes laying on XZ coordinate and tried to raise it's centre (0,0,0) by a certain point, say (0, 4, 0) it would start to form real 3D shapes, then I need to calculate normals again. I'm having hard time understanding how and what is to be to calculated normals. As expected, the 3D shape shades like it's still a flat mesh, so it does not represent real shape. One of the explanation says I need to calculate normals per vertex instead of per face.
Does it mean I need to calculate normals for all corners of mesh? once i have normals what would i do? I was still using old glBegin glEnd methods but now I feel like i need to use DrawArray method. I'm deeply confused and I'm pretty sure I don't make much sound but i'd much appreciate your help.
If you need flat looking surface then your normals will be normals to the quad plane. If you need "soft looking" surface you need to blend(read this and watch this cool simple video) normals - that will add sort of gradient.
I am trying to write an optimized code that renders a 3D scene using OpenGL onto a sphere and then displays the unwrapped sphere on the screen ie producing a planar map of a purely reflective sphere. In math terms, I would like to produce a projection map where the x axis is the polar angle and y axis is the azimuth.
I am trying to do this by placing the camera at the center of the sphere probe and taking planar shots around so as to approximate spherical quads with planar tiles of the frustum. Then I can use this as texture to apply to a distorted planar patch.
Seems to me this is pretty tedious approach. I wonder if there is way to take this on using shaders or some GPU-smart method.
Thank you
S.
I can give you two solutions.
The first is to make a standard render-to-texture, but with a cubemap attached as the destination buffer. If your hardware is recent enough, it can be done in a single pass. This will deal with all the needed math in HW for you, but data repartition of cubemaps aren't ideal (quite a lot of distortion if the corners). In most cases, it should be enough though.
After this, you render a quad to the screen, and in a shader you map your UV coordinates to xyz vectors using staightforwad spherical mapping. The HW will compute for you which side of the cubemap to take, at which UV.
The second is more or less the same, but with a custom deformation and less HW support : dual paraboloids. Two paraboloids may not be enough, but you are free to slightly modify the equations and make 6 passes. The rendering pass is the same, but this time you're all by yourself to choose the right texture and compute the UVs.
By the time you've bothered to build the model, take the planar shots, apply non-affine transformations and stitch the whole thing together, you've probably gained no performance and considerable complexity. Just project the planar image mathematically and be done with it.
You seem to be asking for OpenGL's sphere mapping. NeHe has a tutorial on sphere mapping that might be useful.
This question already has answers here:
OpenGL ES 2.0 - Fisheye shader displays a grey image
(1 answer)
Shader - Anti fisheye by "pulling" pixels
(2 answers)
Closed 1 year ago.
I am trying to create lomo fisheye effect on an image using openGL.
Should I use cube mapping and fisheye projection? Is there any open source that I can refer to?
You can draw a single quad with the image textured onto it, and use a fragment shader to warp the texture coordinate per-pixel as you desire. You'll have to do all the math yourself, but it looks like the previous post here might be a good starting point.
Taking the question title beyond effect on an image to producing "true" fisheye views, ie. usable field of view 180+ degrees...
There are two slightly different methods to adapt existing pipelines to fisheye view (with "simple" OpenGL). Both require scene rendering for up to 6 times - for each side of the "box" that will be projected to a flat screen. Each side / surface must be square - or should be, depends on the method - and likely smaller than the original full viewport.
The number of sides required depends on how wide the fisheye field of view is requested. In a typical FPS, for a FOV of 130 - three sides is enough. For a FOV up to 220 - five sides.
Method 1 - cubemap texture (GL_ARB_texture_cube_map)
init once, for a specific FOV, pre-calculate a translation table of 2d on-screen coordinates to cubemap texture 3d coordinates, 16x16 grid for the whole screen should be enough
setup the viewport and position camera accordingly to render box sides, do the usual rendering
bind sides to the GL_TEXTURE_CUBE_MAP_ARB texture
iterate over screen emitting (rectangular) GL_QUAD_STRIP-s using the translation table and the cubemap.
Method 2 - 2d or rectangular textures (GL_NV_texture_rectangle)
init once, for a specific FOV, pre-calculate a "ray" table of texture + 2d texture coordinates to 2d screen coordinates
as in Method 1, setup the viewport and position camera accordingly to render box sides, do the usual rendering
bind sides to the GL_TEXTURE_RECTANGLE_NV or GL_TEXTURE_2D textures
iterate over textures emitting (trapezoid) GL_QUAD_STRIP-s on the screen using the "ray" table.
The Method 1 is simpler and delivers better results.
Gotchas:
set cubemap texture wrapping to GL_CLAMP_TO_EDGE
in a typical FPS, player view is not only pitch and yaw, but also roll - calculate camera orientation for each side via proper rotation
if the render loop is combined with progress / physics / ai, this repeated scene re-rendering may confuse existing internals.
This is all of course depends on the specifics of a particular engine. I'm not sure how well this applies to OpenGL 3.3+ core profile yet the idea should be the same.
It is possible to draw the world to fisheye in one pass by doing fisheye transformaion in vertex shader. But! it requires original geometry sufficiently (pre-)tessellated. Or, it could be possible to employ Geometry Shader and/or Tessellation Shaders to organize tessellation / transform feedback on the GPU. The later should be built into the rendered from the ground up, perhaps.
For a well-isolated example using Quake 1 engine see Fisheye and Panorama OpenGL FPS and this diff specifically. Unfortunatelly, the vertex shader example is lost.