使用 Visual Studio 在 Opengl 1 中创建纹理动画的最佳方法是什么?

Mar*_*ria 5 c++ opengl animation

我想创建一个简单的动画来显示使用 OpenGL 飞行的蝴蝶/鸟,但我不知道如何解决这个问题。

由于动画很小,因此创建一个具有两个图像的纹理来表示动画会是一个很好的解决方案吗?如果是这样,我应该如何在他们之间交换图片?

Myk*_*ola 5

首先通过调用加载纹理图像,glTexImage2D其他时候使用 加载图像到已经存在的纹理glTexSubImage2D,这比调用要快得多glTexImage2D,非常适合这种类型的动画。

规格信息:

void glTexSubImage2D(
    GLenum target,  
    GLint level,  
    GLint xoffset,  
    GLint yoffset,  
    GLsizei width,  
    GLsizei height,  
    GLenum format,  
    GLenum type,  
    const GLvoid * data
); 
Run Code Online (Sandbox Code Playgroud)

glTexSubImage2D重新定义现有二维纹理图像的连续子区域。数据引用的纹素将现有纹理数组的部分替换为x索引xoffsetxoffset + width - 1 ,包括 和 y 索引yoffsetyoffset + height - 1 ,包括在内。该区域可能不包括最初指定的纹理数组范围之外的任何纹素。

为了获得完整的纹理图像交换,您只需指定xoffsetyoffset等于零。

您可以指定纹理名称数组,例如

char* textureNames[10] = { "...", "...", ..., "..." }; 
Run Code Online (Sandbox Code Playgroud)

然后对于纹理数据

GLbyte* textureData[10]; // 10 texture instances
Run Code Online (Sandbox Code Playgroud)

LoadTGA使用具有自动内存分配功能的 rutine加载纹理数据

for (int i = 0; i < 10; i++) {
    textureData[i] = LoadTGA(
        textureNames[i],
        /*... TEXTURE PARAMS MUST BE THE SAME FOR ALL IMAGES */
    );
}
Run Code Online (Sandbox Code Playgroud)

加载第一张图片

glTexImage2D(
    GL_TEXTURE_2D, GL_RGB, 0, width, height, 0,
    format, GL_UNSIGNED_BYTE, textureData[0]
);
Run Code Online (Sandbox Code Playgroud)

在某些渲染函数中

static int imageIndex = 0;

glTexSubImage2D(
    GL_TEXTURE_2D, 0, 0, 0, width, height,
    format, GL_UNSIGNED_BYTE, textureData[imageIndex]
);

imageIndex++;

if (imageIndex == 10) // max index reached
    imageIndex = 0;
Run Code Online (Sandbox Code Playgroud)

考虑到您使用少量的帧(纹理),我建议您添加一些渲染延迟,因为图片变化非常快。

或者,当您想要实现实时渲染速度时,您可以使用某种异步计时器在纹理索引之间切换。

或者,当您只想在 2 个单独的纹理之间进行更改时,我之前已经回答过如何将纹理随机应用到表面。因此可以通过创建 2 个简单的 2D 纹理来简单地完成。

for (int i = 0; i < 2; i++) {
    g_pnTextures[i] = loadTGA(textureNames[i], g_pnTextures[i]);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
}
Run Code Online (Sandbox Code Playgroud)

g_pnTextures必须是GLuint数组类型。纹理生成调用将类似于glGenTextures(2, g_pnTextures).

然后依次改变其索引。并将它们绑定到某个表面。

glBindTexture(GL_TEXTURE_2D, g_pnTextures[imageIndex++]);
if (imageIndex == 10) // max index reached
    imageIndex = 0;

glBegin(GL_QUADS);
// specify texture coords
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-1.0f, -1.0f);
// specify texture coords
glTexCoord2f(0.0f, 1.0f);
glVertex2f(1.0f, -1.0f);
// specify texture coords
glTexCoord2f(1.0f, 1.0f);
glVertex2f(1.0f, 1.0f);
// specify texture coords
glTexCoord2f(1.0f, 0.0f);
glVertex2f(-1.0f, 1.0f);

glEnd();
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这个 loadTGA 函数返回内存缓冲区而不是 OpenGL 纹理标识符(这会导致值转换问题)。

注意:最后一种技术可以应用于少量纹理。如果你想实现电影效果可视化或者GIF动画,第一种技术是最好的方法。