コード例 #1
0
ファイル: TextureTools.cpp プロジェクト: dgadens/ActionEngine
UCHAR* TextureTools::LoadDDS(CHAR* file, ImageInfoDDS &info)
{
	const INT ddsHeightOffset = 12;
	const INT ddsWidthOffset = 16;
	const INT ddsLinearSizeOffset = 20;
	const INT ddsMipMapNumOffset = 28;
	const INT ddsFourCCOffset = 84;
	const INT ddsImageDataOffset = 128;
	EndianType e = GetEndian();
	BOOL byteSwap = FALSE;

	if (e == ENDIAN_Big)
		byteSwap = TRUE;

	FILE *fp = fopen(file, "rb");

	if (fp == nullptr)
		return nullptr;

	CHAR imageID[4];
	fread(imageID, 1, 4, fp);
	if(strncmp(imageID, "DDS ", 4) != 0)
	{
		fclose(fp);

		return FALSE;
	}

	UINT dwHeight = 0, dwWidth = 0,
	dwLinearSize, dwMipMaps = 0,
	dwFourCC = 0;
	fseek(fp, ddsHeightOffset, SEEK_SET);
	fread(&dwHeight, sizeof(UINT), 1, fp);

	if(byteSwap == TRUE)
		SwapBytes((CHAR*)&dwHeight, sizeof(UINT));
	fseek(fp, ddsWidthOffset, SEEK_SET);
	fread(&dwWidth, sizeof(UINT), 1, fp);

	if(byteSwap == TRUE)
		SwapBytes((CHAR*)&dwWidth, sizeof(UINT));
	fseek(fp, ddsLinearSizeOffset, SEEK_SET);
	fread(&dwLinearSize, sizeof(UINT), 1, fp);

	if(byteSwap == TRUE)
		SwapBytes((CHAR*)&dwLinearSize, sizeof(UINT));
	fseek(fp, ddsMipMapNumOffset, SEEK_SET);
	fread(&dwMipMaps, sizeof(UINT), 1, fp);

	if(byteSwap == TRUE)
		SwapBytes((CHAR*)&dwMipMaps, sizeof(UINT));
	fseek(fp, ddsFourCCOffset, SEEK_SET);
	fread(&dwFourCC, sizeof(UINT), 1, fp);

	if(byteSwap == TRUE)
		SwapBytes((CHAR*)&dwFourCC, sizeof(UINT));
	if(dwLinearSize == 0)
		dwLinearSize = dwHeight * dwWidth;

	if(dwLinearSize <= 0)
	{
		fclose(fp);

		return nullptr;
	}

	info.m_numMipMaps = dwMipMaps;
	info.m_width = dwWidth;
	info.m_height = dwHeight;

	INT mipFactor = 0;
	switch(dwFourCC)
	{
		case DS_FOURCC_DXT1:
			mipFactor = 2;
			info.m_components = 3;
			info.m_type = DDS_DXT1;
		break;
		case DS_FOURCC_DXT3:
			mipFactor = 4;
			info.m_components = 4;
			info.m_type = DDS_DXT3;
		break;
		case DS_FOURCC_DXT5:
			mipFactor = 4;
			info.m_components = 4;
			info.m_type = DDS_DXT5;
		break;
		default:
			fclose(fp);
			return nullptr;
		break;
	}

	INT totalSize = 0;
	// Take into account multiple mipmaps.
	if(dwMipMaps > 1)
		totalSize = dwLinearSize * mipFactor;
	else
		totalSize = dwLinearSize;

	UCHAR* image = nullptr;
	image = new UCHAR[totalSize * sizeof(UCHAR)];
	if(image != nullptr)
	{
		fseek(fp, ddsImageDataOffset, SEEK_SET);
		fread(image, 1, totalSize, fp);
	}
	fclose(fp);

	return image;
};
コード例 #2
0
ファイル: texture.cpp プロジェクト: evehj/NDKOpenGLES2App
	/** KTXファイルを読み込む.
	*/
	TexturePtr LoadKTX(const char* filename, GLint minFilter, GLint magFilter) {
		auto file = Mai::FileSystem::Open(filename);
		if (!file) {
			LOGW("cannot open:'%s'", filename);
			return nullptr;
		}

		const size_t size = file->Size();
		if (size <= sizeof(KTXHeader)) {
			LOGW("illegal size:'%s'", filename);
			return nullptr;
		}
		KTXHeader header;
		int result = file->Read(&header, sizeof(KTXHeader));
		if (result < 0 || !IsKTXHeader(header)) {
			LOGW("illegal header:'%s'", filename);
			return nullptr;
		}
		TexturePtr p = std::make_shared<Texture>();
		Texture& tex = static_cast<Texture&>(*p);
		const Endian endianness = GetEndian(header);
		const GLenum type = GetValue(&header.glType, endianness);
		const GLenum format = GetValue(type ? &header.glFormat : &header.glBaseInternalFormat, endianness);
		const int faceCount = GetValue(&header.numberOfFaces, endianness);
		const int mipCount = GetValue(&header.numberOfMipmapLevels, endianness);
		tex.internalFormat = GetValue(type ? &header.glBaseInternalFormat : &header.glInternalFormat, endianness);
		tex.width = GetValue(&header.pixelWidth, endianness);
		tex.height = GetValue(&header.pixelHeight, endianness);
		tex.target = faceCount == 6 ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;

		const uint32_t off = GetValue(&header.bytesOfKeyValueData, endianness);
		file->Seek(file->Position() + off);

		glGenTextures(1, &tex.texId);
		glBindTexture(tex.Target(), tex.texId);
		std::vector<uint8_t> data;
		GLsizei curWidth = tex.Width();
		GLsizei curHeight = tex.Height();
		for (int mipLevel = 0; mipLevel < (mipCount ? mipCount : 1); ++mipLevel) {
			uint32_t imageSize;
			result = file->Read(&imageSize, 4);
			if (result < 0) {
				LOGW("can't read(miplevel=%d):'%s'", mipLevel, filename);
				return nullptr;
			}
			imageSize = GetValue(&imageSize, endianness);
			const uint32_t imageSizeWithPadding = (imageSize + 3) & ~3;
			data.resize(imageSizeWithPadding * faceCount);
			result = file->Read(&data[0], data.size());
			if (result < 0) {
				LOGW("can't read(miplevel=%d):'%s'", mipLevel, filename);
				return nullptr;
			}
			const uint8_t* pImage = reinterpret_cast<const uint8_t*>(&data[0]);
			const GLenum target = tex.Target() == GL_TEXTURE_CUBE_MAP ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : GL_TEXTURE_2D;
			for (int faceIndex = 0; faceIndex < faceCount; ++faceIndex) {
				if (type == 0) {
					glCompressedTexImage2D(target + faceIndex, mipLevel, tex.InternalFormat(), curWidth, curHeight, 0, imageSize, pImage);
				} else {
					glTexImage2D(target + faceIndex, mipLevel, tex.InternalFormat(), curWidth, curHeight, 0, format, type, pImage);
				}
				const GLenum result = glGetError();
				switch(result) {
				case GL_NO_ERROR:
				  break;
				case GL_INVALID_OPERATION:
				  LOGW("glCompressed/TexImage2D return GL_INVALID_OPERATION");
				  break;
				default:
				  LOGW("glCompressed/TexImage2D return error code 0x%04x", result);
				  break;
				}
				pImage += imageSizeWithPadding;
			}
			curWidth = std::max(1, curWidth / 2);
			curHeight = std::max(1, curHeight / 2);
		}
		glTexParameteri(tex.Target(), GL_TEXTURE_MIN_FILTER, CorrectFilter(mipCount, minFilter));
		glTexParameteri(tex.Target(), GL_TEXTURE_MAG_FILTER, CorrectFilter(mipCount, magFilter));
		glTexParameteri(tex.Target(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(tex.Target(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glBindTexture(tex.Target(), 0);
		LOGI("Load %s(ID:%x).", filename, tex.texId);
		return p;
	}