Opengl画到纹理..递归?

时间:2013-06-26 13:23:45

标签: opengl recursion textures

我正在尝试用opengl绘制纹理。

我发现这个简单明了的c代码可以做到这一点(见最后)。 它在纹理上绘制一个立方体,然后使用前一个纹理在屏幕上绘制一个立方体。生成的图像是一个立方体,在纹理中,立方体内的立方体内有很多立方体等。:它似乎是一个递归循环。

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

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;
}

/* ========================================================================= */

1 个答案:

答案 0 :(得分: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();
}