opengl窗口超过分辨率

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opengl窗口超过分辨率相关的知识,希望对你有一定的参考价值。

我有一个基于 OpenGL 的 gui。我使用超分辨率能够处理各种比例。不是放大图像,而是缩小图像(除非碰巧有人以 4000x4000+ 分辨率运行)。
问题是,OpenGL 似乎并不能顺利缩减。我有工件,好像缩放是最近的邻居。 (例如,文本边缘是块状的,即使它们不在原始文件中)
这些是我使用的设置:
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
这是一个工件样本,我相信比例是 2:1。由于窗口边缘等原因,可能并不准确。
您可以看到左边缘看起来很完美(虽然不是这样),但右边缘有奇怪的中断。原始图形完全对称,没有伪影。
我试过 GL_NEAREST、GL_LINEAR。没有 mipmapping 所以...
OpenGL 在缩放方面肯定不是那么差吗?我想要双三次缩放之类的东西或能产生良好结果的东西。
我使用的是 OpenGL 1.1。我可能会预先缩放图像,但每次窗口大小发生变化时我都必须这样做,并且 cpu 可能会很慢。首先,您必须了解信号理论,即Nyquist Theorem(该***页面在谈论“时间”域中的信号时过于具体;该原理对于所有类型的离散采样信号(包括图像)都是通用的)。在进行下采样时,您始终必须应用lowpass anti aliasing filter,它会切断采样频率一半以上的所有频率分量,以避免产生混叠伪影。如果没有过滤,即使是线性积分下采样器也会产生伪影。实现纹理低通滤波器的实时图形方式是mipmaps。每个 mipmap 级别的截止频率恰好是下一个更高级别的频率的一半。
你现在有两个选择:
实现 mipmapping
实现下采样片段着色器
当然,明智的做法是首先不要以过高的分辨率进行渲染,而是以完全目标分辨率来渲染你的 GUI。
【讨论】:
【解决方案2】:
根据你提供的代码,我会猜测可能是什么问题。
尝试加载您的图像或至少分配内存在您使用glParameteri 设置这些纹理参数之前。另外,将GL_TEXTURE_MIN_FILTER 设置各向异性过滤可以应用于不同的级别,此代码将应用到最大级别,如果您愿意,可以使用小于aniso 的数字我用OpenGL渲染出三维场景,然后通过glReadPixels()将三维场景保存为BMP格式的图片,发现保存图片的分辨率就是渲染窗口的分辨率,请问通过什么方法可以实现将渲染的场景保存为超过窗口分辨率的图片?例如:我的图形显示窗口为300*300,我想保存为1000*1000分辨率的图片如何实现,请大家给点思路,要是有相关的链接或代码也可以我可能问题描述的不清楚,我并不是想渲染得到纹理,只是想将渲染窗口的图像保存为BMP图片,遇到的问题是保存的图片只能和窗口大小一样,有没有办法得到保存图片的场景内容与窗口中的一样,只是得到的图片大小几倍于窗口么?例如:我渲染的窗口比较小,直观看的话图像并不清晰,保存为图片后由于图片较大就比较清晰了是在显卡存储空间中开辟出的一块内存缓存区,用于存储顶点的各类属性信息,如顶点坐标,顶点法线,顶点颜色数据等。
顶点着色器渲染时,可直接从VBO中取出顶点的各类属性数据,由于VBO在显存而不是在内存中,不需要从CPU传输数据,处理效率更高。所以可以理解为VBO就是显存中的一个存储区域,可以保持大量的顶点属性信息。并且可以开辟很多个VBO,每个VBO在OpenGL中有它的唯一标识ID,这个ID对应着具体的VBO的显存地址,通过这个ID可以对特定的VBO内的数据进行存取操作。
顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER,允许同时绑定多个缓冲,只要它们是不同的缓冲类型
可使用glBindBuffer函数把新创建的缓冲绑定到GL_ARRAY_BUFFER目标上。
使用VBO画图
在这里插入图片描述

顶点数组对象 (Vertex Array Object,VAO)

是一个保存了所有顶点数据属性的状态结合,它存储了顶点数据的格式以及顶点数据所需的VBO对象的引用。
VAO本身并没有存储顶点的相关属性数据,这些信息是存储在VBO中的,VAO相当于是对很多个VBO的引用,把一些VBO组合在一起作为一个对象统一管理。一个着色器程序对象(shader program object) 就是多个着色器结合链接到一起的最终版本。激活的着色器程序对象将在调用渲染操作时使用它会使用比正常分辨率更高的分辨率(即超采样)来渲染场景,当图像输出在帧缓冲中更新时,分辨率会被下采样(Downsample)至正常的分辨率。栅器会将一个图元的所有顶点作为输入,并将它转换为一系列的片段。顶点坐标理论上可以取任意值,但片段不行,因为它们受限于你窗口的分辨率。顶点坐标与片段之间几乎永远也不会有一对一的映射,所以光栅器必须以某种方式来决定每个顶点最终所在的片段/屏幕坐标由于屏幕像素总量的限制,有些边缘的像素能够被渲染出来,而有些则不会。结果就是我们使用了不光滑的边缘来渲染图元,导致之前讨论到的锯齿边缘。多重采样所做的正是将单一的采样点变为多个采样点(这也是它名称的由来)。我们不再使用像素中心的单一采样点,取而代之的是以特定图案排列的4个子采样点(Subsample)。我们将用这些子采样点来决定像素的遮盖度。当然,这也意味着颜色缓冲的大小会随着子采样点的增加而增加。在这里插入图片描述这里,每个像素包含4个子采样点(不相关的采样点都没有标注),蓝色的采样点被三角形所遮盖,而灰色的则没有。对于三角形的内部的像素,片段着色器只会运行一次,颜色输出会被存储到全部的4个子样本中。而在三角形的边缘,并不是所有的子采样点都被遮盖,所以片段着色器的结果将只会储存到部分的子样本中。根据被遮盖的子样本的数量,最终的像素颜色将由三角形的颜色与其它子样本中所储存的颜色来决定。
参考技术A 如果您创建的窗口大于桌面,那些不在视图中的像素不会通过像素所有权测试。因此这些像素的内容是undefined,对于任何不可见的像素,无论窗口刚刚离开桌面还是被其他窗口覆盖,都是如此。无论如何,你不应该创建一个窗口大小的桌面。您应该创建一个普通窗口,并制作一个包含大颜色和深度,将所有渲染操作都放到这些离屏缓冲区中。那么你将不必担心窗口的大小限制,以非常大的图像分辨率捕捉OpenGL窗口的快照,我希望我可以使用Qt为这个快照抓取程序,但我只限于过剩,因为我的项目团队伙伴正在研究同一个程序的另一个模块,对于我来说,是否有创建一个不受桌面大小限制并且可以像4000乘2000一样大的过量窗口, 参考技术B OpenGL应用程序可以超出分辨率的大小,并且应用程序可以按照需要缩放显示在屏幕上。如果您想了解更多相关信息,可以查看OpenGL官方文档。

以上是关于opengl窗口超过分辨率的主要内容,如果未能解决你的问题,请参考以下文章

更改分辨率时如何保留其他应用程序窗口的大小和位置? (例如,以非桌面分辨率来回全屏游戏)

使用openGL的视频显示

OpenGL 超分辨率问题

openGL分辨率设置,屏幕行为无法解释

Opengl 纹理映射和图像分辨率

CSS:如果大于窗口,则缩小背景图像,否则保持 100%