渲染到纹理 OpenGL ES 2.0

Posted

技术标签:

【中文标题】渲染到纹理 OpenGL ES 2.0【英文标题】:Render to Texture OpenGL ES 2.0 【发布时间】:2011-09-30 21:16:33 【问题描述】:

我正在尝试使用硬件优化的 2D 库来缩放(非插值缩放)图像。我现在是

    加载原始图像 复制原始图像 使用 2D 库“放大”副本 使用 glTexImage2D 从图像中生成纹理 将它们应用于我绘制的矩形

我还不能上传图片,但这里有一个截图链接。 http://img.photobucket.com/albums/v336/prankstar008/zoom.png

我想将右侧的图像每帧放大和缩小一定量,而不是每次都使用 glTexImage2D 来破坏我的性能,我想渲染到纹理。我的问题是

    这是对纹理进行渲染的有效应用吗?为澄清起见,2D 库采用指向填充了原始 RGB(A) 数据的缓冲区的指针,并返回指向应用了 2D 操作的新数据的指针。 我认为我的大部分困惑与纹理与着色器的交互方式有关。有人可以解释在 GLES2 中将纹理应用于表面的最简单方法吗?我显然有一些工作,如有必要,我可以发布代码的 sn-ps。 另外澄清一下,虽然我不确定这是否重要,但这是在 android 上运行的。

谢谢。

【问题讨论】:

为什么要为不同的缩放级别生成新的纹理?不不不!更改您的纹理坐标,甚至只是更改您的投影/视图矩阵。完整图像的一个纹理可以完成工作。 这个应用程序的重点是演示二维库的功能。它本质上是一个黑盒子,其中输入是纹理(指向缓冲区的指针),输出是新纹理(新指针)。我同意有更好的缩放方法,但它们不适用于这个项目。 【参考方案1】:

1) 不,不是。如果您只想放大和缩小图像(不使用缩放库),那么渲染到另一个纹理将是浪费时间。您可以直接放大视图。

2) 着色器是能够计算和转换坐标的程序(通常在顶点着色器中完成)并且能够使用这些坐标从纹理中读取(当时只能在片段着色器中完成) .

我相信你的着色器应该是这样的:

precision mediump float;

uniform matrix4 modelviewProjectionMatrix; // input transformation matrix

attribute vec3 position;
attribute vec2 texcoord; // input coordinates of each vertex

varying vec2 _texcoord; // output coordinate for fragment shader

void main()

    gl_Position = modelviewProjectionMatrix * vec4(position, 1.0); // transform position
    _texcoord = texcoord; // copy texcoord

那是顶点着色器,现在是片段着色器:

precision mediump float;

varying vec2 _texcoord; // input coordinate from vertex shader

uniform sampler2D _sampler; // handle of a texturing unit (e.g. 0 for GL_TEXTURE0)

void main()

    gl_FragColor = glTexture2D(_sampler, _texcoord); // read texture

你可以做的是在顶点着色器中包含一个缩放参数(所谓的统一):

precision mediump float;

uniform float zoom; // zoom
uniform matrix4 modelviewProjectionMatrix; // input transformation matrix

attribute vec3 position;
attribute vec2 texcoord; // input coordinates of each vertex

varying vec2 _texcoord; // output coordinate for fragment shader

void main()

    gl_Position = modelviewProjectionMatrix * vec4(position, 1.0); // transform position
    _texcoord = (texcoord - .5) * zoom + .5; // zoom texcoord

片段着色器没有变化。这只是为它计算不同的坐标,就是这么简单。要设置缩放,您需要:

int zoomLocation = glGetUniformLocation(yourProgram, "zoom");
// this is done in init, where you call glGetUniformLocation(yourProgram, "modelviewProjectionMatrix")
// also, zoomLocation is not local variable, it needs to be stored somewhere to be used later when drawing

glUniform1f(zoomLocation, 1 + .5f * (float)Math.sin(System.nanotime() * 1e-8f));
// this will set zoom that will animatically zoom in and out of the texture (must be called after glUseProgram(yourProgram))

现在这将导致两个纹理都放大和缩小。要解决此问题(我假设您只想缩放正确的纹理),您需要:

// draw the second quad

glUniform1f(zoomLocation, 1);
// this will set no zoom (1:1 scale)

// draw the first quad

我希望这会有所帮助...

【讨论】:

以上是关于渲染到纹理 OpenGL ES 2.0的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL ES 2.0 Framebuffer 渲染到纹理 iOS:没有显示

在 OpenGL ES 2.0 中渲染到纹理时的抗锯齿

Framebuffer FBO渲染到纹理很慢,在Android上使用OpenGL ES 2.0,为啥?

绘制到纹理后的Opengl ES 2.0 glDeleteFramebuffers

哪些 OpenGL ES 2.0 纹理格式可进行颜色、深度或模板渲染?

iPhone OpenGL ES 2.0 奇怪的图案在 COLLADA 文件中的球体上渲染纹理