1

I' experimenting in draw to texture with opengl.

I've found this simple and clear c code that do that (see in the end). It draws a cube on a texture, and then a cube on the screen using the previous texture. The generated image is a cube with, in the textures, a lot of cube inside a cube inside a cube etc..: it seems a recursion loop.

But why? I was expecting only 2 cubes. And It seems an infinite recursion loop.. where is the actual recursion? and when does it stops?

enter image description here

 /* ============================================================================
**
** Demonstration of rendering to texture
** Copyright (C) 2005  Julien Guertault
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
**
** ========================================================================= */

#include <stdio.h>

#include <stdlib.h>
#include <GL/glut.h>
#include <math.h>

#define     SIZE    256

static unsigned char texture[3 * SIZE * SIZE];
static unsigned int texture_id;
static int window_width = 500;
static int window_height = 500;


/*
** Just a textured cube
*/
void        Cube(void)
{
  glBegin(GL_QUADS);

  glTexCoord2i(0, 0); glVertex3f(-1, -1, -1);
  glTexCoord2i(0, 1); glVertex3f(-1, -1,  1);
  glTexCoord2i(1, 1); glVertex3f(-1,  1,  1);
  glTexCoord2i(1, 0); glVertex3f(-1,  1, -1);

  glTexCoord2i(0, 0); glVertex3f( 1, -1, -1);
  glTexCoord2i(0, 1); glVertex3f( 1, -1,  1);
  glTexCoord2i(1, 1); glVertex3f( 1,  1,  1);
  glTexCoord2i(1, 0); glVertex3f( 1,  1, -1);

  glTexCoord2i(0, 0); glVertex3f(-1, -1, -1);
  glTexCoord2i(0, 1); glVertex3f(-1, -1,  1);
  glTexCoord2i(1, 1); glVertex3f( 1, -1,  1);
  glTexCoord2i(1, 0); glVertex3f( 1, -1, -1);

  glTexCoord2i(0, 0); glVertex3f(-1,  1, -1);
  glTexCoord2i(0, 1); glVertex3f(-1,  1,  1);
  glTexCoord2i(1, 1); glVertex3f( 1,  1,  1);
  glTexCoord2i(1, 0); glVertex3f( 1,  1, -1);

  glTexCoord2i(0, 0); glVertex3f(-1, -1, -1);
  glTexCoord2i(0, 1); glVertex3f(-1,  1, -1);
  glTexCoord2i(1, 1); glVertex3f( 1,  1, -1);
  glTexCoord2i(1, 0); glVertex3f( 1, -1, -1);

  glTexCoord2i(0, 0); glVertex3f(-1, -1,  1);
  glTexCoord2i(0, 1); glVertex3f(-1,  1,  1);
  glTexCoord2i(1, 1); glVertex3f( 1,  1,  1);
  glTexCoord2i(1, 0); glVertex3f( 1, -1,  1);

  glEnd();
}

/*
** Function called to update rendering
*/
void        DisplayFunc(void)
{
  static float alpha = 20;

  glLoadIdentity();
  glTranslatef(0, 0, -10);
  glRotatef(alpha, 1, 0, 0);
  glRotatef(20   , 0, 1, 0);

  /* Define a view-port adapted to the texture */
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(20, 1, 5, 15);
  glViewport(0, 0, SIZE, SIZE);
  glMatrixMode(GL_MODELVIEW);

  /* Render to buffer */
  glClearColor(1, 1, 1, 0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  Cube();
  glFlush();

  /* Copy buffer to texture */
  glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 5, 5, 0, 0, SIZE - 10, SIZE - 10);

  /* Render to screen */
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(20, window_width / (float) window_height, 5, 15);
  glViewport(0, 0, window_width, window_height);
  glMatrixMode(GL_MODELVIEW);
  glClearColor(0, 0, 0, 0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  Cube();

  /* End */
  glFlush();
  glutSwapBuffers();

  /* Update again and again */
  alpha = alpha + 0.1;
  glutPostRedisplay();
}

/*
** Function called when the window is created or resized
*/
void        ReshapeFunc(int width, int height)
{
  window_width = width;
  window_height = height;
  glutPostRedisplay();
}

/*
** Function called when a key is hit
*/
void        KeyboardFunc(unsigned char key, int x, int y)
{
  int foo;

  foo = x + y; /* Has no effect: just to avoid a warning */
  printf("%d",foo);
  if ('q' == key || 'Q' == key || 27 == key)
      exit(0);
}


int     main(int argc, char **argv)
{
  /* Creation of the window */
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  glutInitWindowSize(500, 500);
  glutCreateWindow("Render to texture");

  /* OpenGL settings */
  glEnable(GL_DEPTH_TEST);

  /* Texture setting */
  glEnable(GL_TEXTURE_2D);
  glGenTextures(1, &texture_id);
  glBindTexture(GL_TEXTURE_2D, texture_id);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SIZE, SIZE, 0, GL_RGB,
           GL_UNSIGNED_BYTE, texture);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

  /* Declaration of the callbacks */
  glutDisplayFunc(&DisplayFunc);
  glutReshapeFunc(&ReshapeFunc);
  glutKeyboardFunc(&KeyboardFunc);

  /* Loop */
  glutMainLoop();

  /* Never reached */
  return 0;
}

/* ========================================================================= */
4

1 回答 1

0

但为什么?我期待只有 2 个立方体。而且它似乎是一个无限递归循环..实际递归在哪里?什么时候停止?

这是一个反馈循环。给你的小实验:拿一个网络摄像头把它连接到你的电脑上,让它显示网络摄像头的实时图片。现在将网络摄像头指向屏幕,以便它查看生成的图像。

这就是这里发生的事情:绘制了一个带有纹理的立方体。该图片现在被复制到纹理中。然后再次绘制立方体,但这次纹理已经包含该立方体,所以它是一个上面有立方体的立方体。此外,为了您的乐趣,相同的立方体被绘制到屏幕上,但这并没有反馈。

如果你想有一个嵌套深度,你必须在绘制复制到纹理的立方体时禁用纹理。

更新不递归的代码修改

void        DisplayFunc(void)
{

第一次渲染没有纹理,所以我们不反馈。同时将绘图颜色设为黑色,这样会在黑色背景上生成一个纯黑色立方体。

  /* Render to buffer */
  glClearColor(1, 1, 1, 0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glDisable(GL_TEXTURE_2D); /* <<<<<< */
  glColor3f(0,0,0);         /* <<<<<< */
  Cube();

附带说明:为此,确实应该使用帧缓冲区对象,而不是依赖后台缓冲区不被破坏(重叠的窗口可能使其无法通过像素所有权测试)。

  /* Copy buffer to texture */
  glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 5, 5, 0, 0, SIZE-10, SIZE-10);

  /* Render to screen */
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(20, window_width / (float) window_height, 5, 15);
  glViewport(0, 0, window_width, window_height);
  glMatrixMode(GL_MODELVIEW);
  glClearColor(0, 0, 0, 0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

重新启用纹理并将颜色切换为白色,以便我们可以看到纹理(或使用 GL_REPLACE 纹理模式)。

  glEnable(GL_TEXTURE_2D);
  glColor3f(1,1,1);
  Cube();

  /* End */
  glFlush();
  glutSwapBuffers();

  /* Update again and again */
  alpha = alpha + 0.1;
  glutPostRedisplay();
}
于 2013-06-26T13:36:58.033 回答