My computer is a Mac pro with a 13 inch retina screen. The screen resolution is 1280*800 (default).
Using the following code:
gWindow = glfwCreateWindow(800, 600, "OpenGL Tutorial", NULL, NULL);
//case 1
glViewport(0,0,1600,1200);
//case 2
glViewport(0,0,800,600);
Case 1 results in a triangle that fits the window.
Case 2 results in a triangle that is 1/4th the size of the window.
Half of viewport:
The GLFW documentation indicates the following (from here):
While the size of a window is measured in screen coordinates, OpenGL
works with pixels. The size you pass into glViewport, for example,
should be in pixels. On some machines screen coordinates and pixels
are the same, but on others they will not be. There is a second set of
functions to retrieve the size, in pixels, of the framebuffer of a
window.
Why my retina screen coordinate value is twice the value of pixel value?
As Sabuncu said is hard to know what result should be correct without knowing how you draw the triangle.
But I guess your problems is related to the fact that with retina screen, when you use the 2.0 scale factor you need to render twice the pixels as you would with a regular screen - see here
The method you're after is shown just a few lines below your GLFL link
There is also glfwGetFramebufferSize for directly retrieving the current size of the framebuffer of a window.
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
The size of a framebuffer may change independently of the size of a window, for example if the window is dragged between a regular monitor and a high-DPI one.
In your case I'm betting the framebuffer size you'll get will be twice the window size, and your gl viewport needs to match it.
The frame-buffer size never needs to be equal to the size of the window, as of that you need to use glfwGetFramebufferSize:
This function retrieves the size, in pixels, of the framebuffer of the specified window. If you wish to retrieve the size of the window in screen coordinates, see glfwGetWindowSize.
Whenever you resize your window you need to retrieve the size of its frambuffer and update the Viewport according to it:
glfwGetFramebufferSize(gWindow, &framebufferWidth, &framebufferHeight);
glViewport(0, 0, framebufferWidth, framebufferHeight);
With retina display, the default framebuffer (the one that rendered onto the canvas) is twice the resolution of the display. Thus, if the display is 800x600, the internal canvas is 1600x1200, and therefore your viewpoert should be 1600x1200 since this is the "window" into the framebuffer.
Related
I want this pixelated look in sdl2 for all the object in my screen
To do this, the nearest scaling must be set (default in SDL2), which does not use antialiasing. If so, you can use SDL_SetHint by setting hint SDL_HINT_RENDER_SCALE_QUALITY to nearest (or 0). If you now render a small texture in a large enough area (much larger than the texture size), you will see large pixels in the window.
If, on the other hand, you have large textures (just like in the linked thread), or you just want to render the entire frame pixelated, you can do this by rendering the contents of the frame on a low-resolution auxiliary texture (serving as the back buffer), and after rendering the entire frame, rendering the back buffer in the window. The buffer texture will be stretched across the entire window and the pixelation will then be visible.
I used this method for the Fairtris game which renders the image in NES-like resolution. Internal back buffer texture has resolution of 256×240 pixels and is rendered in a window of any size, maintaining the required proportions (4:3, so slightly stretched horizontally). However, in this game I used linear scaling to make the image smoother.
To do this you need to:
remember that the nearest scaling must be set,
create a renderer with the SDL_RENDERER_TARGETTEXTURE flag,
create back buffer texture with low resolution (e.g. 256×240) and with SDL_TEXTUREACCESS_TARGET flag.
When rendering a frame, you need to:
set the renderer target to the backbuffer texture with SDL_SetRenderTarget,
render everything the frame should contain using the renderer and back buffer size (e.g. 256×240),
bring the renderer target back to the window using SDL_SetRenderTarget again.
You can resize the back buffer texture at any time if you want a smaller area (zoom in effect, so larger pixels on the screen) or a larger area (zoom out effect, so smaller pixels on the screen) in the frame. To do this, you will most likely have to destroy and recreate the backbuffer texture with a different size. Or you can create a big backbuffer texture with an extra margin and when rendering, use a smaller or bigger area of it — this will avoid redundant memory operations.
At this point, you have the entire frame in an auxiliary texture that you can render in the window. To render it in a window, use the SDL_RenderCopy function, specifying the renderer handle and back buffer texture handle (rects should not be given so that the texture will be rendered completely over the entire window area), and finally SDL_RenderPresent.
If you need to render in window the frame respecting the aspect ratio, get the current window size with SDL_GetWindowSize and calculate the target area taking into account the aspect ratio of the back buffer texture and the window proportions (portrait and landscape). However, before rendering the back buffer texture in the window, first clean the window with SDL_RenderClear so that the remaining areas of the window (black bars) are filled with black.
My computer is a Mac pro with a 13 inch retina screen. The screen resolution is 1280*800 (default).
Using the following code:
gWindow = glfwCreateWindow(800, 600, "OpenGL Tutorial", NULL, NULL);
//case 1
glViewport(0,0,1600,1200);
//case 2
glViewport(0,0,800,600);
Case 1 results in a triangle that fits the window.
Case 2 results in a triangle that is 1/4th the size of the window.
Half of viewport:
The GLFW documentation indicates the following (from here):
While the size of a window is measured in screen coordinates, OpenGL
works with pixels. The size you pass into glViewport, for example,
should be in pixels. On some machines screen coordinates and pixels
are the same, but on others they will not be. There is a second set of
functions to retrieve the size, in pixels, of the framebuffer of a
window.
Why my retina screen coordinate value is twice the value of pixel value?
As Sabuncu said is hard to know what result should be correct without knowing how you draw the triangle.
But I guess your problems is related to the fact that with retina screen, when you use the 2.0 scale factor you need to render twice the pixels as you would with a regular screen - see here
The method you're after is shown just a few lines below your GLFL link
There is also glfwGetFramebufferSize for directly retrieving the current size of the framebuffer of a window.
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
The size of a framebuffer may change independently of the size of a window, for example if the window is dragged between a regular monitor and a high-DPI one.
In your case I'm betting the framebuffer size you'll get will be twice the window size, and your gl viewport needs to match it.
The frame-buffer size never needs to be equal to the size of the window, as of that you need to use glfwGetFramebufferSize:
This function retrieves the size, in pixels, of the framebuffer of the specified window. If you wish to retrieve the size of the window in screen coordinates, see glfwGetWindowSize.
Whenever you resize your window you need to retrieve the size of its frambuffer and update the Viewport according to it:
glfwGetFramebufferSize(gWindow, &framebufferWidth, &framebufferHeight);
glViewport(0, 0, framebufferWidth, framebufferHeight);
With retina display, the default framebuffer (the one that rendered onto the canvas) is twice the resolution of the display. Thus, if the display is 800x600, the internal canvas is 1600x1200, and therefore your viewpoert should be 1600x1200 since this is the "window" into the framebuffer.
I'm trying to render a 2D image so that it will cover the entire window exactly.
For my test, I setup a window so that the client area is exactly 320x240 and the texture is also this size.
I setup my orthographic projection for a 1x1x1 cube centered at the origin, and set my viewport to 0,0,320,240
The texture is mapped to a quad of size 1x1 centered in the origin.
The shader is a trivial shader doing the ProjModelViewPos
I created a test texture that will allow me to verify the rendering, and I see a consistent discrepancy I can't shake.
The results of the rendering always some stretching that puts some of the pixels up and to the right of the window, and seem to be always by the same amount, regardless of the window size (same amount of pixels, if I replace 320x240 by another value)
I think it has to do with window decoration widths, but I'm not sure how to fix it so that the solution is not platform / machine specific.
EDITS:
The code is straight C++ using freeglut and glew
Verified that this doesn't happen if I call glutFullScreen, so it's definitely windowed mode related.
Note: this was answered before the language tag was added
Not sure what module you are using for this.
If you are using Pyglet the easiest way is achieve this is:
import pyglet
width = 320
height = 240
window = pyglet.window.Window(width, height)
image = pyglet.resource.image('image.png')
#window.event
def on_draw():
window.clear()
image.blit(0, 0, 0, width, height)
pyglet.app.run()
You can find more information about this here:
http://www.pyglet.org/doc/programming_guide/size_and_position.html
http://www.pyglet.org/doc/programming_guide/displaying_images.html
I am doing a game in OpenGL and using SDL for managing the window, setting the icons, and all that stuff.
Now that I have set rendering the scene to a framebuffer, I wondered if I could resize the SDL window while keeping my starting GL settings (I am trying to emulate a exact resolution so window resizing is a rescale of the framebuffer to the window size)
I tried giving the SDL window double the resolution of the resolution I pass to glortho, but it gives unexpected results©. Is this possible at all, or do I need to adapt my working resolution to the screen resolution all the time?
I use this code to initialize video
SDL_SetVideoMode(XRES, YRES, bpp, SDL_OPENGL | SDL_HWPALETTE);
gl_init(XRES,YRES);
And into gl_init I set glortho to glOrtho(0, width, 0, height, -1, 1), and then the framebuffer "blank" texture to width and height in size, as well.
When the function is called as above, all is well. But if I try something like
SDL_SetVideoMode(XRES*2, YRES*2, bpp, SDL_OPENGL | SDL_HWPALETTE);
gl_init(XRES,YRES);
Instead of getting my expected results (scaled output) I find out that the output is somewhere at the far left on X axis and somewhere in the middle of the Y axis, like if GL size was even bigger than the screen and the rest was cropped out. Is there anything I am missing?
Try to simply set the FBO texture size to 1/4 of the window size (1/2 of its edge lengths), then render the FBO's color buffer texture to the entire SDL window.
I know this is an old question, but it is a top result on Google and does not have an answer.
You'll need to call glViewport(). Suppose you want your internal resolution as 1024x768, and your window resolution is windowWidth and windowHeight. Before you write to your FBO, call glViewport(0, 0, 1024, 768). Then, before writing your FBO to the window, call glViewport(0, 0, windowWidth, windowHeight).
You use this code in your game loop
int w, h;
SDL_GetWindowSize(Window, &w, &h);
glViewport(0, 0, w, h);
Is there a standard way, using only OpenGL functions, to obtain the size of the backbuffer, in pixels? The closest I've found is querying the size of the viewport, but I doubt it always matches the backbuffer size. I'm looking for the maximum width and height values I can supply to glReadPixels, for example.
The backbuffer is part of the window framebuffer planes set (front color, back color, depth, stencil, etc. depending on what's been configured). Since they all belong together they all have the same dimensions. Since the standard framebuffer is tied to the visible window the accessible part is determined by the window dimensions.
However there's one important thing to be aware of: A window's framebuffer is (or used to be) just a slice of the screen framebuffer. If the window is moved or resized only the offset and the stride of the slice in the screen framebuffer changes. It also means that if the window is (partially) obstructed by another window, the occluded parts of the window don't contribute to the framebuffer. Reading from a framebuffer partially covered by other windows you may end up with either undefined contents there, or the contents of the occluding window.
On modern operating systems windows are rendered into off screen areas which can not be occluded, to support compositing window management.