我的OpenGL学习进阶之旅C++如何加载TGA文件?
Posted 字节卷动
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我的OpenGL学习进阶之旅C++如何加载TGA文件?相关的知识,希望对你有一定的参考价值。
一、TGA文件相关介绍
通过前面的博客
- 【我的OpenGL学习进阶之旅】什么是TGA文件以及如何打开TGA文件?
地址:https://ouyangpeng.blog.csdn.net/article/details/121408436 - 【我的C语言学习进阶之旅】关于C/C++内存对齐读取文件产生的问题以及解决方法
地址:https://ouyangpeng.blog.csdn.net/article/details/121539330
我们了解了什么是TGA文件,现在我们来正式介绍一下C++中如何加载TGA文件?
二、如何加载TGA文件?
2.1 定义一个结构体TGA_HEADER
定义这个结构体的时候,得注意内存对齐方式,否则读取出来的TGA文件是有错误的。
具体的坑参考下面的博客:
- 【我的C语言学习进阶之旅】关于C/C++内存对齐读取文件产生的问题以及解决方法
地址: https://ouyangpeng.blog.csdn.net/article/details/121539330
// 注意点:保证内存是连续的,不然读取错误 使用 #pragma pack(1) 或者 __attribute__ ( ( packed ) ) 都可以
// C/C++内存对齐详解 https://zhuanlan.zhihu.com/p/30007037
// #pragma的常用方法讲解 https://blog.csdn.net/weixin_39640298/article/details/84503428
//#pragma pack(push,x1) // Byte alignment (8-bit)
//#pragma pack(1) // 如果前面加上#pragma pack(1),那么此时有效对齐值为1字节
typedef struct
// C语言__attribute__的使用 https://blog.csdn.net/qlexcel/article/details/92656797
// 使用该属性对struct 或者union 类型进行定义,设定其类型的每一个变量的内存约束。
// 就是告诉编译器取消结构在编译过程中的优化对齐(使用1字节对齐),按照实际占用字节数进行对齐,是GCC特有的语法。
// 这个功能是跟操作系统没关系,跟编译器有关,gcc编译器不是紧凑模式的
__attribute__ ( ( packed ) )
unsigned char IdSize,
MapType,
ImageType;
unsigned short PaletteStart,
PaletteSize;
unsigned char PaletteEntryDepth;
unsigned short X,
Y,
Width,
Height;
unsigned char ColorDepth,
Descriptor;
TGA_HEADER;
//#pragma pack(pop,x1)
2.2 加载Assets目录下的TGA文件
一般我们的TGA文件放在assets目录下,如下所示:
可以参考下面的博客,加载assets目录下的文件:
- 【我的OpenGL学习进阶之旅】如何抽取着色器代码到assets目录下的GLSL文件,以及如何通过Java或者C++代码来加载着GLSL文件?
地址:https://ouyangpeng.blog.csdn.net/article/details/121851163
下面的代码是:从assets目录下下载了指定的assets目录下的相对文件路径的TGA文件。 如何转换成Texture纹理。
-
GLUtils::loadTgaTexture
方法
GLUtils::loadTgaTexture
方法 用来加载 TGA图片并转换为纹理
-
GLUtils::loadTgaTexture
方法 调用了GLUtils::lesLoadTGA
方法
GLUtils::lesLoadTGA
方法用来读取TGA文件并转换成char *
-
GLUtils::lesLoadTGA
方法 调用了GLUtils::esFileOpen
方法和GLUtils::esFileClose
方法
GLUtils::esFileOpen
方法和GLUtils::esFileClose
方法 分别是打开和关闭assets目录下的指定文件
其中esFile
是AAsset
-
完整代码如下
#include <android/asset_manager_jni.h>
typedef AAsset esFile;
//
// File open
//
static esFile *esFileOpen ( const char *fileName )
AAssetManager* nativeManager = AAssetManager_fromJava(sEnv, sAssetManager);
if (nativeManager == nullptr)
return nullptr;
return AAssetManager_open(nativeManager, fileName, AASSET_MODE_BUFFER);
//
// File close
//
static void esFileClose ( esFile *pFile )
if ( pFile != nullptr )
AAsset_close ( pFile );
//
// File read
//
static int esFileRead ( esFile *pFile, int bytesToRead, void *buffer )
int bytesRead = 0;
if ( pFile == nullptr )
return bytesRead;
bytesRead = AAsset_read ( pFile, buffer, bytesToRead );
return bytesRead;
//
// esLoadTGA()
//
// Loads a 8-bit, 24-bit or 32-bit TGA image from a file
//
char * esLoadTGA (const char *fileName, int *width, int *height )
char *buffer;
esFile *fp;
TGA_HEADER Header;
int bytesRead;
// Open the file for reading
fp = esFileOpen (fileName );
if ( fp == nullptr )
// Log error as 'error in opening the input file from apk'
LOGE ( "esLoadTGA FAILED to load : %s \\n", fileName )
return nullptr;
LOGD ( "sizeof ( TGA_HEADER ) : %d \\n", sizeof ( TGA_HEADER ) )
bytesRead = esFileRead ( fp, sizeof ( TGA_HEADER ), &Header );
*width = Header.Width;
*height = Header.Height;
if ( Header.ColorDepth == 8 ||
Header.ColorDepth == 24 || Header.ColorDepth == 32 )
int bytesToRead = sizeof ( char ) * ( *width ) * ( *height ) * Header.ColorDepth / 8;
// Allocate the image data buffer
buffer = ( char * ) malloc ( bytesToRead );
if ( buffer )
bytesRead = esFileRead ( fp, bytesToRead, buffer );
esFileClose ( fp );
return ( buffer );
return ( nullptr );
//
// Load texture from disk
//
GLuint GLUtils::loadTgaTexture (const char *fileName )
int width, height;
char *buffer = esLoadTGA (fileName, &width, &height );
GLuint texId;
if ( buffer == nullptr )
LOGI ( "Error loading (%s) image.\\n", fileName )
return 0;
glGenTextures ( 1, &texId );
glBindTexture ( GL_TEXTURE_2D, texId );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer );
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_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
free ( buffer );
return texId;
2.3 使用它
使用方式很简单,之间调用下面的方法,参数传文件相对路径即可
textureId = GLUtils::loadTgaTexture("texture/heightmap.tga");
最终我们加载并显示出来的效果如下:
具体效果实现参考GitHub:https://github.com/ouyangpeng/OpenGLESDemo.git
找到代码: src/main/cpp/sample/texture/TerrainRender.cpp 查看效果实现
以上是关于我的OpenGL学习进阶之旅C++如何加载TGA文件?的主要内容,如果未能解决你的问题,请参考以下文章
我的OpenGL学习进阶之旅什么是TGA文件以及如何打开TGA文件?
我的OpenGL学习进阶之旅什么是TGA文件以及如何打开TGA文件?
我的C语言学习进阶之旅关于C/C++内存对齐读取文件产生的问题以及解决方法
我的OpenGL学习进阶之旅如何抽取着色器代码到assets目录下的GLSL文件,以及如何通过Java或者C++代码来加载着GLSL文件?
我的OpenGL学习进阶之旅如何抽取着色器代码到assets目录下的GLSL文件,以及如何通过Java或者C++代码来加载着GLSL文件?