IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【我的OpenGL学习进阶之旅】C++如何加载TGA文件? -> 正文阅读

[C++知识库]【我的OpenGL学习进阶之旅】C++如何加载TGA文件?

一、TGA文件相关介绍

通过前面的博客

我们了解了什么是TGA文件,现在我们来正式介绍一下C++中如何加载TGA文件?

二、如何加载TGA文件?

2.1 定义一个结构体TGA_HEADER

定义这个结构体的时候,得注意内存对齐方式,否则读取出来的TGA文件是有错误的。
具体的坑参考下面的博客:

在这里插入图片描述

// 注意点:保证内存是连续的,不然读取错误  使用  #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目录下的文件:

下面的代码是:从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目录下的指定文件
    在这里插入图片描述
    其中esFileAAsset
    在这里插入图片描述

  • 完整代码如下

#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 查看效果实现

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:32:36  更:2021-12-11 15:34:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:59:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码