Files
DNF_DEV/source/EngineFrame/Render/Texture.cpp

209 lines
7.2 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
// 环绕方式
// 对2D纹理设置环绕模式S=X轴T=Y轴
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 缩小过滤:使用最近邻采样
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;
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纹理相同的采样模式
// 环绕方式:重复
// 对2D纹理设置环绕模式S=X轴T=Y轴
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 过滤方式最近邻与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);
// 环绕方式
// 对2D纹理设置环绕模式S=X轴T=Y轴
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 缩小过滤:使用最近邻采样
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;
// 环绕方式
// 对2D纹理设置环绕模式S=X轴T=Y轴
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// 缩小过滤:使用最近邻采样
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;
}