修改底层渲染为OpenGL

This commit is contained in:
2025-10-23 15:21:12 +08:00
parent 1fe898e09c
commit f9a2300b5a
37 changed files with 2782 additions and 3761 deletions

View File

@@ -1,91 +1,204 @@
#include "EngineFrame/Render/Texture.h"
#include "Texture.h"
#include "Asset/Asset_ImagePack.h"
#include "EngineCore/Game.h"
#include "Texture.h"
Texture::Texture()
{
}
Texture::Texture(std::string PngPath)
Texture::~Texture()
{
glDeleteTextures(1, &m_TextureID);
}
bool Texture::Init(std::string PngPath)
{
SDL_Surface *surface = IMG_Load(PngPath.c_str());
if (!surface)
{
SDL_Log("无法加载图片: %s", SDL_GetError());
return;
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Couldn't load image %s: %s", PngPath.c_str(), IMG_GetError());
return false;
}
m_texture = SDL_CreateTextureFromSurface(Game::GetInstance().GetRenderer(), surface);
if (!m_texture)
{
SDL_Log("无法创建纹理: %s", SDL_GetError());
SDL_FreeSurface(surface); // 记得释放surface
return;
}
this->TextureSize.width = surface->w;
this->TextureSize.height = surface->h;
this->TextureFramepos.width = surface->w;
this->TextureFramepos.height = surface->h;
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;
}
Texture::Texture(std::string imgPath, int Index)
bool Texture::Init(std::string ImgPath, int Index)
{
this->ImgPath = imgPath;
this->Index = Index;
Asset_ImagePack::IMG *Info = Asset_ImagePack::GetInstance().GetIMG(imgPath);
m_Path = ImgPath;
m_TextureIndex = Index;
Asset_ImagePack::IMG *Info = Asset_ImagePack::GetInstance().GetIMG(ImgPath);
if (Info->lpImgName == "sprite/interface/base.img")
return;
return false;
Asset_ImagePack::ImgInfo &Buf = Info->lp_lplist[Index];
m_texture = SDL_CreateTexture(
Game::GetInstance().GetRenderer(),
SDL_PIXELFORMAT_ARGB8888, // 匹配RGBA数据格式
SDL_TEXTUREACCESS_STREAMING,
Buf.Width, Buf.Height);
if (!m_texture)
// 检查像素数据是否有效
if (!Buf.PNGdata || Buf.Width <= 0 || Buf.Height <= 0)
{
SDL_Log("纹理创建失败: %s", SDL_GetError());
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "无效的图像数据: %s (index: %d)", ImgPath.c_str(), Index);
return false;
}
int pitch = Buf.Width * 4;
SDL_UpdateTexture(m_texture, NULL, Buf.PNGdata, pitch);
SDL_SetTextureBlendMode(m_texture, SDL_BLENDMODE_BLEND);
SDL_SetTextureScaleMode(m_texture, SDL_ScaleModeNearest);
this->TexturePos.x = Buf.Xpos;
this->TexturePos.y = Buf.Ypos;
this->TextureSize.width = Buf.Width;
this->TextureSize.height = Buf.Height;
this->TextureFramepos.width = Buf.FrameXpos;
this->TextureFramepos.height = Buf.FrameYpos;
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;
}
Texture::~Texture()
bool Texture::Init(SDL_Surface *rgbaSurface)
{
SDL_DestroyTexture(m_texture);
// 生成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;
}
SDL_Texture *Texture::GetTexture()
bool Texture::Init(VecSize size)
{
return m_texture;
}
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 // 初始数据(为空,后续绘制填充)
);
RefPtr<Texture> Texture::GetTextureCopy()
{
RefPtr<Texture> nt = new Texture(this->ImgPath, this->Index);
return nt;
}
// 记录纹理信息
m_TextureSize = size;
m_FrameSize = size;
void Texture::SetBlendMode(SDL_BlendMode blendMode)
{
SDL_SetTextureBlendMode(m_texture, blendMode);
}
// 环绕方式
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_BlendMode Texture::GetBlendMode()
{
SDL_BlendMode blendMode;
SDL_GetTextureBlendMode(m_texture, &blendMode);
return blendMode;
}
glBindTexture(GL_TEXTURE_2D, 0); // 解绑
return true;
}