我正在尝试为FBO启用mutlisampling和alpha-to-coverage.使用默认的帧缓冲区,我所要做的就是调用glEnable(GL_MULTISAMPLE)和glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE).但是,我无法使用自己的FBO达到同样的效果.
我的目标:将场景绘制到FBO,就像使用上述属性绘制到默认帧缓冲区一样.从那里我希望能够将图像用作未来通过着色器的纹理.
这适用:制作没有多重采样/ alpha到覆盖的FBO的代码,1种颜色附件,1种深度附件:
// Generate the color attachment
glGenTextures(1,&defaultColorAttachment0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,defaultColorAttachment0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,screenWidth,screenHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
// Bind the texture to the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, defaultColorAttachment0,0);
// Generate the depth attachment
glGenRenderbuffers(1,&defaultDepthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, defaultDepthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, screenWidth, screenHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, defaultDepthBuffer);
Run Code Online (Sandbox Code Playgroud)
这不起作用.试图制作多重采样FBO的代码:
// Generate the color attachment
glGenTextures(1,&defaultColorAttachment0);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, defaultColorAttachment0);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA, screenWidth, screenHeight, GL_FALSE);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, defaultColorAttachment0,0);
// Generate the depth attachment
glGenRenderbuffers(1,&defaultDepthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, defaultDepthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, …Run Code Online (Sandbox Code Playgroud) 设置此变量有什么作用?例如,如果我将其设置为4,那意味着什么?
我在"Framebuffer相关提示"部分下阅读了glfw.org上的描述(参见这里:GLFW窗口指南).手册中说"GLFW_SAMPLES指定了用于多重采样的所需样本数.Zero禁用多重采样.GLFW_DONT_CARE表示应用程序没有首选项."
我还阅读了一般的多重采样说明(参见此处: Shawn Hargreaves的多重采样).
我大致了解多重采样的含义:在调整图像大小和重新绘制图像时,用于重绘图像的点数应该足够接近,以便我们看到的是图像的精确表示.数字示波器也会出现同样的想法 - 比如你正在采样正弦信号.如果采样速率恰好恰好等于波的频率(f),则示波器显示恒定电压,这与您希望看到的输入信号非常不同.为了避免这种情况,奈奎斯特定理告诉我们,我们应该以至少2f的速率进行采样.所以我看到计算机图形学中会出现问题,但我不知道究竟是什么功能
glfwWindowHint(GLFW_SAMPLES, 4); 确实.
我对了解多重采样的工作原理非常感兴趣.我已经找到了关于如何启用或使用它的大量文献,但是关于它为了实现抗锯齿渲染它真正做了什么的信息非常少.在许多地方,我发现的是相互矛盾的信息,这些信息只会让我更加困惑.
请注意,我知道如何启用和使用多重采样(我实际上已经在使用它),我不知道的是多重采样渲染缓冲区/纹理中真正涉及的是什么类型的数据,以及如何在渲染管道中使用这些数据.
我可以很好地理解超级采样是如何工作的,但是多重采样仍然有一些我想要理解的模糊区域.
这是规格说的:(OpenGL 4.2)
像素样本值(包括颜色,深度和模板值)存储在此缓冲区(多重采样缓冲区)中.样本包含每种片段颜色的单独颜色值.
...
在多重采样渲染期间,像素片段的内容以两种方式改变.首先,每个片段包括具有SAMPLES位的覆盖值.
...
其次,每个片段包括SAMPLES深度值和关联数据集,而不是单样本渲染模式中维护的单个深度值和关联数据集.
因此,每个样本都包含不同的颜色,覆盖位和深度.与普通超级采样有什么区别?看起来像是对我的"加权"超级采样,其中每个最终像素值由其样本的覆盖值而不是简单平均值确定,但我对此非常不确定.那么样本级别的纹理坐标呢?
如果我在RGBF多重采样纹理中存储法线,我会在多边形的边缘上将它们"反锯齿"(即接近0)读回来吗?
每个片段调用一次片段着色器,除非它使用gl_SampleID,glSampleIn或具有"样本"存储限定符.如何为每个片段调用一次片段着色器并获得抗锯齿渲染?
我有一个带有颜色和深度附件的FBO对象,我将其呈现,然后从使用中读取glReadPixels(),我正在尝试添加多重采样支持.
而不是glRenderbufferStorage()我要求glRenderbufferStorageMultisampleEXT()颜色附件和深度附件.帧缓冲区对象似乎已成功创建并报告为完成.
渲染后我试图用它读取glReadPixels().当样本数为0时,即多重采样禁用,它完美地工作,我得到我想要的图像.当我将样本数量设置为其他东西时,比如4,帧缓冲区仍然构造正常但是glReadPixels()失败了INVALID_OPERATION
任何人都知道这里有什么问题吗?
编辑:glReadPixels的代码:
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
Run Code Online (Sandbox Code Playgroud)
其中ptr指向一个宽度为*height uints的数组.
虽然我不鼓励我阅读OpenGL红皮书,但我仍然这样做,因为它是为初学者设计的唯一一本书,教程和/或文档虽然非常重要但并不能完全替代一本书.为了证明自己的合理性:)
现在,有一个使用多重采样的抗锯齿的例子,其中涉及到
glEnable(GL_MULTISAMPLE);
我使用Qt,我得到一个编译错误,因为GL_MULTISAMPLE是一个未声明的标识符.我目前看到以下原因:
<QGLWidget>Qt中未包含或未附带的其他标题中上述原因之一是否正确?如果没有,这就是我没有它的原因,我怎样才能获得?提前致谢
在创建窗口时如何启用多重采样?我应该如何初始化OpenGL以匹配?
我正在尝试使用MTKView. 我有MTKView一个代表。我将视图的sampleCount属性设置为 4。我创建了一个rasterSampleCount设置为 4的管道状态描述符,并使用它来创建渲染时使用的渲染管道状态。
在代理的draw(in:)方法,我通过获取该视图的当前渲染通道描述符和设置创建渲染过程描述storeAction到multisampleResolve。我也设置了尝试storeAndMultisampleResolve无济于事。
我为渲染通道描述符创建了一个解析纹理,它与视图具有相同的宽度和高度以及相同的像素格式。
鉴于上述情况,我在渲染过程中得到了一个完整的红框。我已经使用金属调试器来查看纹理,并且视图的纹理和解析纹理都有正确的渲染。我在 AMD 机器上,全红色纹理通常表示未初始化的纹理。
我需要做些什么才能让渲染进入屏幕?
下面是我设置视图、管道状态和解析纹理的方法:
metalView = newMetalView
metalView.sampleCount = 4
metalView.clearColor = MTLClearColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0)
device = newMetalView.device!
let metalLibrary = device.makeDefaultLibrary()!
let vertexFunction = metalLibrary.makeFunction(name: "vertexShader")
let fragmentFunction = metalLibrary.makeFunction(name: "fragmentShader")
let pipelineStateDescriptor = MTLRenderPipelineDescriptor.init()
pipelineStateDescriptor.label = "Particle Renderer"
pipelineStateDescriptor.vertexFunction = vertexFunction
pipelineStateDescriptor.fragmentFunction = fragmentFunction
pipelineStateDescriptor.colorAttachments [ 0 ].pixelFormat = metalView.colorPixelFormat …Run Code Online (Sandbox Code Playgroud) 我正在尝试将多重采样的场景渲染为纹理,这是我正在使用的代码.我有黑屏.我在init结束时检查fbo完整性,并且他们报告两个fbo都已完成.
void init_rendered_FBO() {
glGenFramebuffers(1,&fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1,&fbo_tex);
glBindTexture(GL_TEXTURE_2D, fbo_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width_screen, height_screen, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width_screen, height_screen);
glBindTexture (GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_tex, 0);
int objectType;
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,&objectType);
ASSERT(objectType == GL_TEXTURE);
int objectName;
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,&objectName);
ASSERT(glIsTexture(objectName) == GL_TRUE);
int wid, hei, fmt;
glBindTexture(GL_TEXTURE_2D, objectName);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &wid);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &hei);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT,
&fmt);
glBindTexture(GL_TEXTURE_2D, …Run Code Online (Sandbox Code Playgroud) 我知道 webgl 可以抗锯齿或多采样你渲染到屏幕上的东西以避免硬边,但是当我使用帧缓冲区时它不再这样做了,并且屏幕上有一堆锯齿状边缘。
如何让帧缓冲区使用多重采样?
尝试在延迟着色之上实现抗锯齿,我尝试使用多重采样渲染缓冲区,然后使用缓冲区位块传输传递解析样本。
按照延迟着色的传统做法,我使用发出 3 个颜色输出的专用着色器来渲染场景:
然后将它们用于照明计算通道,从而产生最终的场景纹理
使用简单的着色器将场景纹理渲染到全屏四边形的屏幕上
正如您可能猜到的,渲染到屏幕时,屏幕上的 MSAA 不会应用于场景纹理的内容:为了实现抗锯齿,我因此选择在步骤 1) 中使用多重采样渲染缓冲区,并引入了额外的步骤1.1) 分辨率。当然,多重采样仅对彩色图是必要的/有用的,对其他两张图来说不是必需的/有用的。
我的问题是,显然,具有多个渲染缓冲区/颜色附件的帧缓冲区只能为相同类型的附件定义;这意味着如果一个附件经过多次采样,那么所有其他附件也必须经过多次采样。
这成为分辨率期间位置和法线缓冲区的一个问题,因为几何体和照明会因抗锯齿而受到影响。
// Create the frame buffer for deferred shading: 3 color attachments and a depth buffer
glGenFramebuffers(1, &gBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
{
// - Position color buffer
glGenRenderbuffers(1, &gPosition);
glBindRenderbuffer(GL_RENDERBUFFER, gPosition);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_RGBA16F, w, h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, gPosition);
// - Normal color buffer
glGenRenderbuffers(1, &gNormal);
glBindRenderbuffer(GL_RENDERBUFFER, gNormal);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_RGBA16F, w, h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, gNormal);
// …Run Code Online (Sandbox Code Playgroud) opengl multisampling framebuffer deferred-rendering deferred-shading
multisampling ×10
opengl ×8
fbo ×3
c++ ×2
graphics ×2
framebuffer ×1
glfw ×1
javascript ×1
metal ×1
metalkit ×1
qt ×1
qt5 ×1
swift ×1
webgl ×1