1

我正在开发一款使用像素艺术的游戏和一个与像素艺术大小不一一匹配的相机。为了让像素看起来像像素,我想以更高的分辨率渲染整个游戏,然后将其下采样到实际的窗口分辨率(类似于黑暗之魂 2 中的 GeDoSaTo 模组所做的),并在游戏中简单地使用最近的过滤纹理作为 mag 过滤器。如何在代码中进行这种下采样?

4

1 回答 1

4

我为您编写了一些伪代码,展示了如何设置具有尺寸的 FBO:

  scale* ( res_xx res_y)。

        scale2x 超级采样将使用2.0

我做了一些额外的工作来为您的颜色缓冲区获取纹理图像附件,以便您可以使用带纹理的四边形(更好的性能)而不是 blitting 来绘制它。但是,由于这样做需要编写一个(简单的)着色器,glBlitFramebuffer (...)因此是最快的解决方案。

初始化 FBO 的代码:

GLuint supersample_fbo,
       supersample_tex,
       supersample_rbo_depth;

glGenTextures (1, &supersample_tex);
glBindTexture (GL_TEXTURE_2D, supersample_tex);

glGenRenderbuffers (1, &supersample_rbo_depth);
glBindRenderbuffer (GL_RENDERBUFFER, supersample_rbo_depth);

// Allocate storage for your texture (scale X <res_x,res_y>)
glTexImage2D  (GL_TEXTURE_2D, 0, GL_RGBA8, res_x * scale, res_y * scale, 0, GL_RGBA, GL_FLOAT, NULL);

// Allocate storage for your depth buffer
glRenderBufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, res_x * scale, res_y * scale);

glGenFramebuffers (1, &supersample_fbo);
glBindFramebuffer (GL_FRAMEBUFFER, supersample_fbo);

// Attach your texture to the FBO: Color Attachment 0.
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, supersample_tex, 0);

// Attach the depth buffer to the FBO.
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, supersample_rbo_depth);

绘制到您的 FBO 的代码:

glBindFramebuffer (GL_FRAMEBUFFER, supersample_fbo);

// You need to modify the viewport mapping to reflect the difference in size.
// Your projection matrix can stay the same since everything is uniformly scaled.
//
glViewport        (0, 0, res_x * scale, res_y * scale);

  // DRAW

将 FBO Blit 到默认帧缓冲区的代码:

glBindFramebuffer (GL_READ_FRAMEBUFFER, supersample_fbo); // READ:  Supersampled
glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0);               // WRITE: Default

// Downsample the supersampled FBO using LINEAR interpolation
glBlitFramebuffer (0,0,res_x * scale, res_y * scale,
                   0,0,res_x,         res_y,
                   GL_COLOR_BUFFER_BIT,
                   GL_LINEAR);

恢复绘图到默认帧缓冲区的代码:

// You probably want all subsequent drawing to go into the default framebuffer...
glBindFramebuffer (GL_FRAMEBUFFER, 0);
glViewport        (0,0,res_x,res_y);

这段代码中有很多缺失的错误检查,而且 FBO容易出错,但它应该能让你找到正确的方向。

于 2014-05-07T20:21:55.543 回答