Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/235.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android OpenGL ES 2.0:如何以较低的分辨率渲染到帧缓冲区以进行环境映射?_Android_Opengl Es_Opengl Es 2.0 - Fatal编程技术网

Android OpenGL ES 2.0:如何以较低的分辨率渲染到帧缓冲区以进行环境映射?

Android OpenGL ES 2.0:如何以较低的分辨率渲染到帧缓冲区以进行环境映射?,android,opengl-es,opengl-es-2.0,Android,Opengl Es,Opengl Es 2.0,我正在尝试使用OpenGLES2.0在Android上实现动态环境反射 为此,我将相机设置在反射对象的位置,并在6个不同方向(每个轴两个)上渲染为屏幕外渲染缓冲,以构建立方体贴图,但这非常缓慢,因此我的想法是使立方体贴图具有较低的分辨率,以加快速度。我认为这应该很简单,但我不理解我的观察结果 我想查看这6个渲染的结果,以检查结果是否符合预期,因此在渲染下一个渲染之前,我将它们作为png文件导出到磁盘。我用1024x1024帧缓冲区渲染了一次,用256x256渲染了一次。但是,当我查看导出的文件时

我正在尝试使用OpenGLES2.0在Android上实现动态环境反射

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

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

我有静态常量REFLECTION_TEX_WIDTH和REFLECTION_TEX_HEIGHT来设置创建的纹理和渲染缓冲层的宽度和高度,我使用这些常量进行创建和导出。但是导出的文件从来没有像我期望的那样覆盖那么多的区域。当我将这些尺寸设置得非常大时,例如每个尺寸为2000,渲染区域似乎覆盖了大约1080x1550像素,文件的其余部分保持黑色。有人能告诉我这是怎么回事吗

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

我希望渲染相同的区域/视野,但分辨率较低。这要求太高了吗

一些代码。 初始化:

// 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");
要将结果导出为文件,我需要执行以下操作:

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;
}
public void savePNG(final int x,final int y,final int w,final int h,final String name)
{
最终位图bmp=保存像素(x、y、w、h);
尝试
{
最终文件=新文件(Environment.getExternalStoragePublicDirectory(
环境。目录(图片),名称);
final File parent=File.getParentFile();
//如有必要,创建父目录
if(null!=parent&&!parent.isDirectory())
parent.mkdirs();
//删除现有文件以避免新旧数据混合
if(file.exists())
delete();
final FileOutputStream fos=新FileOutputStream(文件);
压缩(CompressFormat.PNG,100,fos);
fos.flush();
fos.close();
sendBroadcast(新的Intent(Intent.ACTION\u MEDIA\u SCANNER\u SCAN\u文件,Uri.fromFile(文件));
}
捕获(最终文件NotFounde异常)
{
//TODO自动生成的捕捉块
日志错误(“问题”+e);
}
捕获(最终IOE例外)
{
//TODO自动生成的捕捉块
日志错误(“问题”+e);
}
}
//TODO:神奇的导入代码
公共位图保存像素(最终整数x、最终整数y、最终整数w、最终整数h)
{
最终整数b[]=新整数[w*(y+h)];
最终整数bt[]=新整数[w*h];
最终IntBuffer ib=IntBuffer.wrap(b);
ib.位置(0);
GLES20.glReadPixels(x,0,w,y+h,GL10.GL_RGBA,GL10.GL_无符号字节,ib);
for(inti=0,k=0;i>16)和0xff;

final int pr=(pix在渲染到FBO之前,似乎缺少设置视口的功能。在FBO渲染设置过程中,添加以下调用:

glViewport(0, 0, REFLECTION_TEX_WIDTH, REFLECTION_TEX_HEIGHT);
您可以将其放置在具有
glClear()
的位置。在完成FBO渲染后,在渲染到默认帧缓冲区之前,不要忘记将其设置回默认帧缓冲区的大小


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

想想看,观察到的尺寸可能等于我手机的屏幕大小。起初我没有意识到这一点,因为di不同的比例,但高度通常会通过操作栏等方式降低,宽度似乎与我的Nexus 5的1920x1080屏幕相匹配。
glViewport(0, 0, REFLECTION_TEX_WIDTH, REFLECTION_TEX_HEIGHT);