205 lines
6.9 KiB
C++
205 lines
6.9 KiB
C++
#include "Texture.h"
|
||
#include "Asset/Asset_ImagePack.h"
|
||
#include "EngineCore/Game.h"
|
||
|
||
Texture::Texture()
|
||
{
|
||
}
|
||
|
||
Texture::~Texture()
|
||
{
|
||
glDeleteTextures(1, &m_TextureID);
|
||
}
|
||
|
||
bool Texture::Init(std::string PngPath)
|
||
{
|
||
SDL_Surface *surface = IMG_Load(PngPath.c_str());
|
||
if (!surface)
|
||
{
|
||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Couldn't load image %s: %s", PngPath.c_str(), IMG_GetError());
|
||
return false;
|
||
}
|
||
SDL_Surface *rgbaSurface = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
|
||
SDL_FreeSurface(surface);
|
||
if (!rgbaSurface)
|
||
{
|
||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to convert surface: %s\n", SDL_GetError());
|
||
return false;
|
||
}
|
||
|
||
// 生成OpenGL纹理
|
||
glGenTextures(1, &m_TextureID);
|
||
glBindTexture(GL_TEXTURE_2D, m_TextureID);
|
||
|
||
// 环绕方式
|
||
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_MIN_FILTER, GL_NEAREST);
|
||
// 放大过滤:使用最近邻采样
|
||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||
|
||
// 处理像素对齐(确保SDL的像素行对齐与OpenGL兼容)
|
||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||
|
||
// 记录纹理信息
|
||
m_TextureSize.width = rgbaSurface->w;
|
||
m_TextureSize.height = rgbaSurface->h;
|
||
m_FrameSize.width = rgbaSurface->w;
|
||
m_FrameSize.height = rgbaSurface->h;
|
||
m_Path = PngPath;
|
||
|
||
// 将像素数据上传到GPU
|
||
glTexImage2D(
|
||
GL_TEXTURE_2D,
|
||
0, // 纹理级别(基础级)
|
||
GL_RGBA8, // 内部存储格式(8位RGBA)
|
||
m_TextureSize.width,
|
||
m_TextureSize.height,
|
||
0, // 边框(必须为0)
|
||
GL_RGBA, // 源数据格式(与SDL转换后的格式一致)
|
||
GL_UNSIGNED_BYTE, // 源数据类型(无符号字节)
|
||
rgbaSurface->pixels);
|
||
|
||
// 释放转换后的表面(数据已上传到GPU)
|
||
SDL_FreeSurface(rgbaSurface);
|
||
return true;
|
||
}
|
||
|
||
bool Texture::Init(std::string ImgPath, int Index)
|
||
{
|
||
m_Path = ImgPath;
|
||
m_TextureIndex = Index;
|
||
Asset_ImagePack::IMG *Info = Asset_ImagePack::GetInstance().GetIMG(ImgPath);
|
||
if (Info->lpImgName == "sprite/interface/base.img")
|
||
return false;
|
||
Asset_ImagePack::ImgInfo &Buf = Info->lp_lplist[Index];
|
||
|
||
// 检查像素数据是否有效
|
||
if (!Buf.PNGdata || Buf.Width <= 0 || Buf.Height <= 0)
|
||
{
|
||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "无效的图像数据: %s (index: %d)", ImgPath.c_str(), Index);
|
||
return false;
|
||
}
|
||
|
||
int pixelCount = Buf.Width * Buf.Height;
|
||
uint32_t *srcPixels = reinterpret_cast<uint32_t *>(Buf.PNGdata);
|
||
uint32_t *dstPixels = new uint32_t[pixelCount];
|
||
for (int i = 0; i < pixelCount; ++i)
|
||
{
|
||
uint8_t b = (srcPixels[i] >> 0) & 0xFF; // 蓝
|
||
uint8_t g = (srcPixels[i] >> 8) & 0xFF; // 绿
|
||
uint8_t r = (srcPixels[i] >> 16) & 0xFF; // 红
|
||
uint8_t a = (srcPixels[i] >> 24) & 0xFF; // 透明
|
||
dstPixels[i] = (a << 24) | (b << 16) | (g << 8) | r; // 重组为 RGBA
|
||
}
|
||
|
||
// 生成OpenGL纹理
|
||
glGenTextures(1, &m_TextureID);
|
||
glBindTexture(GL_TEXTURE_2D, m_TextureID);
|
||
|
||
// 设置纹理参数(保持与原有SDL纹理相同的采样模式)
|
||
// 环绕方式:重复
|
||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||
// 过滤方式:最近邻(与SDL_ScaleModeNearest对应)
|
||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||
|
||
// 处理像素对齐(SDL表面可能有不同的行对齐方式)
|
||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||
|
||
// 记录纹理信息
|
||
m_TextureSize.width = Buf.Width;
|
||
m_TextureSize.height = Buf.Height;
|
||
m_FrameSize.width = Buf.FrameXpos;
|
||
m_FrameSize.height = Buf.FrameYpos;
|
||
m_TexturePos.x = Buf.Xpos;
|
||
m_TexturePos.y = Buf.Ypos;
|
||
|
||
// 上传纹理数据到GPU
|
||
glTexImage2D(
|
||
GL_TEXTURE_2D,
|
||
0, // 基础纹理级别
|
||
GL_RGBA8, // 内部存储格式(8位RGBA)
|
||
m_TextureSize.width,
|
||
m_TextureSize.height,
|
||
0, // 无边框
|
||
GL_RGBA, // 源数据格式(根据实际数据格式调整)
|
||
GL_UNSIGNED_BYTE, // 源数据类型
|
||
dstPixels);
|
||
|
||
return true;
|
||
}
|
||
|
||
bool Texture::Init(SDL_Surface *rgbaSurface)
|
||
{
|
||
// 生成OpenGL纹理
|
||
glGenTextures(1, &m_TextureID);
|
||
glBindTexture(GL_TEXTURE_2D, m_TextureID);
|
||
|
||
// 环绕方式
|
||
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_MIN_FILTER, GL_LINEAR);
|
||
// 放大过滤:使用最近邻采样
|
||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||
|
||
// 处理像素对齐(确保SDL的像素行对齐与OpenGL兼容)
|
||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||
|
||
// 记录纹理信息
|
||
m_TextureSize.width = rgbaSurface->w;
|
||
m_TextureSize.height = rgbaSurface->h;
|
||
m_FrameSize.width = rgbaSurface->w;
|
||
m_FrameSize.height = rgbaSurface->h;
|
||
|
||
// 将像素数据上传到GPU
|
||
glTexImage2D(
|
||
GL_TEXTURE_2D,
|
||
0, // 纹理级别(基础级)
|
||
GL_RGBA8, // 内部存储格式(8位RGBA)
|
||
m_TextureSize.width,
|
||
m_TextureSize.height,
|
||
0, // 边框(必须为0)
|
||
GL_RGBA, // 源数据格式(与SDL转换后的格式一致)
|
||
GL_UNSIGNED_BYTE, // 源数据类型(无符号字节)
|
||
rgbaSurface->pixels);
|
||
|
||
return true;
|
||
}
|
||
|
||
bool Texture::Init(VecSize size)
|
||
{
|
||
glGenTextures(1, &m_TextureID);
|
||
glBindTexture(GL_TEXTURE_2D, m_TextureID);
|
||
// 设置纹理参数(根据需求调整尺寸、格式)
|
||
glTexImage2D(
|
||
GL_TEXTURE_2D,
|
||
0, // 多级渐远纹理级别
|
||
GL_RGBA, // 内部格式(存储格式)
|
||
size.width, // 纹理宽度
|
||
size.height, // 纹理高度
|
||
0, // 边框(必须为0)
|
||
GL_RGBA, // 源数据格式
|
||
GL_UNSIGNED_BYTE, // 源数据类型
|
||
nullptr // 初始数据(为空,后续绘制填充)
|
||
);
|
||
|
||
// 记录纹理信息
|
||
m_TextureSize = size;
|
||
m_FrameSize = size;
|
||
|
||
// 环绕方式
|
||
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_MIN_FILTER, GL_LINEAR);
|
||
// 放大过滤:使用最近邻采样
|
||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||
|
||
glBindTexture(GL_TEXTURE_2D, 0); // 解绑
|
||
return true;
|
||
}
|