OpenGL ES 2.0:如何以较低的分辨率渲染到frameBuffer以进行环境映射?

小便

我正在尝试使用OpenGL ES 2.0在Android上实现动态环境反射。

为此,我将相机放置在反射对象的位置,并沿6个不同方向(每个轴两个)渲染到屏幕外的渲染缓冲区,以构建立方体贴图,但这非常慢,所以我的想法是制作立方体贴图具有较低的分辨率以加快处理速度。我认为这应该很简单,但是我不理解我的观察。

我想查看这6个渲染器的结果,以检查结果是否符合预期,因此在渲染下一个渲染器之前,我将它们作为png文件导出到磁盘。我使用1024x1024的帧缓冲区渲染一次,并使用256x256渲染一次。但是,当我查看导出的文件时,可以看到256.png仅包含较大文件的一小部分。我希望它们具有相同的内容(如果您愿意,可以看到视场),但分辨率不同(“更大的像素”),但是事实并非如此。

我有静态常量REFLECTION_TEX_WIDTH和REFLECTION_TEX_HEIGHT来设置创建的纹理和渲染缓冲区的宽度和高度,并且我将这些常量用于创建和导出。但是,导出的文件永远不会覆盖我所期望的区域。当我将这些尺寸设置为非常大时(例如每个设置为2000),渲染区域似乎覆盖约1080x1550像素,文件的其余部分保持黑色。有人可以告诉我这是怎么回事吗?

我不确定问题出在我对帧缓冲区工作原理的理解还是渲染是否正确,但是问题是在文件导出中引入的...那些文件导出方法是从互联网复制的,我不是真的了解他们。

我想渲染相同的区域/ FOV,但分辨率更高。那是过分的要求?

然后一些代码。初始化:

// create 6 textures for the dynamic environment reflection
final int skyboxFaces=6;
final int[] textureId=new int[1];
GLES20.glGenTextures(1, textureId, 0);
skyboxTexture=textureId[0];
ShaderFactory.checkGLError("initRendering::createSkyboxTextures");

GLES20.glBindTexture(GLES20.GL_TEXTURE_CUBE_MAP, skyboxTexture);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_CUBE_MAP, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
for(int i=0; i < skyboxFaces; i++)
{
  GLES20.glTexImage2D(GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GLES20.GL_RGBA,
    REFLECTION_TEX_WIDTH, REFLECTION_TEX_HEIGHT, 0, GLES20.GL_RGBA,
    GLES20.GL_UNSIGNED_BYTE, null);
  ShaderFactory.checkGLError("initRendering::setSkyboxTexture(" + i + ")");
}
// create renderbuffer and bind 16-bit depth buffer
renderBuffers=new int[1];
GLES20.glGenRenderbuffers(1, renderBuffers, 0);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, renderBuffers[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16,
  REFLECTION_TEX_WIDTH, REFLECTION_TEX_HEIGHT);
ShaderFactory.checkGLError("initRendering::createRenderbuffer");

frameBuffers=new int[1];
GLES20.glGenFramebuffers(1, frameBuffers, 0);
// GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
// GLES20.GL_RENDERBUFFER, frameBuffers[0]);
ShaderFactory.checkGLError("initRendering::createFrameBuffer");

然后在renderloop中,执行以下操作:

GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBuffers[0]);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, renderBuffers[0]);
// assign the cubemap texture to the framebuffer
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
  GLES20.GL_TEXTURE_CUBE_MAP_POSITIVE_X + bufferId, skyboxTexture, 0);
// assign the depth renderbuffer to the framebuffer
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT,
  GLES20.GL_RENDERBUFFER, frameBuffers[0]);
// clear the current framebuffer (color and depth)
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

并将结果导出为文件,我这样做:

public void savePNG(final int x, final int y, final int w, final int h, final String name)
{
  final Bitmap bmp=savePixels(x, y, w, h);
  try
  {
    final File file=new File(Environment.getExternalStoragePublicDirectory(
      Environment.DIRECTORY_PICTURES), name);
    final File parent=file.getParentFile();
    // create parent directories if necessary
    if(null != parent && !parent.isDirectory())
      parent.mkdirs();
    // delete existing file to avoid mixing old data with new
    if(file.exists())
      file.delete();

    final FileOutputStream fos=new FileOutputStream(file);
    bmp.compress(CompressFormat.PNG, 100, fos);
    fos.flush();
    fos.close();
    context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
  }
  catch(final FileNotFoundException e)
  {
    // TODO Auto-generated catch block
    LOG.error("problem " + e);
  }
  catch(final IOException e)
  {
    // TODO Auto-generated catch block
    LOG.error("problem " + e);
  }
}

// TODO: magic imported code
public Bitmap savePixels(final int x, final int y, final int w, final int h)
{
  final int b[]=new int[w * (y + h)];
  final int bt[]=new int[w * h];
  final IntBuffer ib=IntBuffer.wrap(b);
  ib.position(0);
  GLES20.glReadPixels(x, 0, w, y + h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, ib);

  for(int i=0, k=0; i < h; i++, k++)
  {
    // OpenGL bitmap is incompatible with Android bitmap and needs some correction.
    for(int j=0; j < w; j++)
    {
      final int pix=b[i * w + j];
      final int pb=(pix >> 16) & 0xff;
      final int pr=(pix << 16) & 0x00ff0000;
      final int pix1=(pix & 0xff00ff00) | pr | pb;
      bt[(h - k - 1) * w + j]=pix1;
    }
  }

  final Bitmap sb=Bitmap.createBitmap(bt, w, h, Bitmap.Config.ARGB_8888);
  return sb;
}
雷托·科拉迪(Reto Koradi)

看起来好像缺少在渲染到FBO之前设置视口的功能。在设置FBO渲染期间,添加此调用:

glViewport(0, 0, REFLECTION_TEX_WIDTH, REFLECTION_TEX_HEIGHT);

您可以将其放置在您拥有的地方glClear()在完成FBO渲染之后,以及渲染为默认帧缓冲区之前,请不要忘记将其设置回默认帧缓冲区的大小。

视口大小是全局状态,默认为默认帧缓冲区的初始大小。因此,无论何时使用大小与默认绘制曲面不同的FBO,都需要相应地设置视口。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

将OpenGL ES Framebuffer移植到OpenGL

来自分类Dev

Android OpenGL ES2。0VBO无法渲染

来自分类Dev

关于OpenGL ES 2的问题

来自分类Dev

多个OpenGL ES 2 Android渲染器

来自分类Dev

如何在OpenGL ES 2中正确缩放

来自分类Dev

Android上的OpenGL ES 2:如何使用VBO

来自分类Dev

在opengl es 2中如何释放纹理(ios硬崩溃)

来自分类Dev

如何在OpenGL ES 2中处理多个对象

来自分类Dev

Android上的OpenGL ES 2:如何使用VBO

来自分类Dev

Android OpenGL ES 2:如何在主活动中将OpenGL活动用作片段

来自分类Dev

Android OpenGL ES 2:如何在主活动中将OpenGL活动用作片段

来自分类Dev

将OpenGL glBegin()移植到OpenGL ES

来自分类Dev

Android OpenGL以原始(小)分辨率渲染到frameBuffer,然后将其缩放(viewPort)到屏幕大小

来自分类Dev

OpenGL ES 2D矩阵设置

来自分类Dev

Android NDK SDL2 OpenGL ES 2阴影映射(定向)-可能吗?

来自分类Dev

使用OpenGL ES 2进行Box2D调试绘图

来自分类Dev

OpenGL ES无法渲染到纹理

来自分类Dev

在OpenGL-ES 2.0中渲染多个2D图像

来自分类Dev

在OpenGL ES 2.x场景中渲染一些字符

来自分类Dev

错误的转换在OpenGL ES 2(iOS)上渲染一个简单的正方形

来自分类Dev

金字塔在android opengl ES2下渲染期间变形

来自分类Dev

将OpenGL ES帧缓冲移植到OpenGL

来自分类Dev

如何使SDL2在Raspberry Pi上使用OpenGL-ES?

来自分类Dev

如何在opengl es 2.0中的2D游戏中设置深度范围?

来自分类Dev

如何在openGL ES 2.0中执行2次传递以获得模糊效果

来自分类Dev

如何在OpenGL ES 2中使用顶点数组对象

来自分类Dev

Android OpenGL ES 2.0根据屏幕分辨率计算距离

来自分类Dev

OpenGL ES(WebGL)渲染许多小对象

来自分类Dev

OpenGL ES 2.0渲染透明背景纹理

Related 相关文章

热门标签

归档