# Stage 1.7
- Added File to Memory and FastHashMomory - Add Protection that only one app can exist - Add a Trace exist Variable as GetTraceRef automatically creates a trace - Outsource the LI::Rect to its own header - Add a CurrentScreen func - Use Rect for uv (to manually set all corners) - Rect still supports to use vec4 for uv - Add tex3ds Spritesheet support - Add T3X Loader to Texture (if single tex) - Integrate an autounload into Texture as in case of spritesheet the Tex needs to be unloaded manually - Safe some performance in texture loading by combining the Loops (best thing ive ever found) - Use the Momory Hash to only render one error icon into the TTF Texture - Also Try loading the whole 16-Bit range - Use GPU_A8 format for TTF rendering to save 24Bits per pixel and use the same Rendermode as System Font - Simplify Quad Command by using modern vec api - Integrate Text aligning - Fix FPS displayed twice in Performance overlay - UI7 DrawList now has its own AST system - TODO: do the same layering for the objects as Text uses - Map Drawcommands with a bool that declares either bottom or top screen was active - Add first basic Manu functions - Fix Typos in Theme - Add a basic UI7 Context Handler ## Extra - Added JetBrainsMono font in Test app ## Bugs: - Performance Overlay Freezes 3ds hardware and crashes Citra with Vulkan when System Font is used - UI7 Menu scrolling is as scruffed as back in RenderD7 0.9.5
This commit is contained in:
@ -23,6 +23,7 @@ SOFTWARE.
|
||||
|
||||
#include <pd/external/stb_truetype.h>
|
||||
|
||||
#include <pd/common/io.hpp>
|
||||
#include <pd/common/strings.hpp>
|
||||
#include <pd/common/sys.hpp>
|
||||
#include <pd/graphics/li7_shader.hpp>
|
||||
@ -45,31 +46,44 @@ void Font::LoadTTF(const std::string& path, int height) {
|
||||
loader.read(reinterpret_cast<char*>(buffer), len);
|
||||
loader.close();
|
||||
stbtt_InitFont(&inf, buffer, 0);
|
||||
std::vector<unsigned char> font_tex(quad * quad * 4);
|
||||
std::vector<unsigned char> font_tex(quad * quad);
|
||||
float scale = stbtt_ScaleForPixelHeight(&inf, pixel_height);
|
||||
|
||||
int ascent, descent, lineGap;
|
||||
stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap);
|
||||
int baseline = static_cast<int>(ascent * scale);
|
||||
|
||||
std::map<u32, int> buf_cache;
|
||||
|
||||
auto tex = Texture::New();
|
||||
vec2 off;
|
||||
for (int i = 0; i < 255; i++) {
|
||||
Codepoint c;
|
||||
for (u32 ii = 0x0000; ii < 0xFFFF; ii++) {
|
||||
int i = stbtt_FindGlyphIndex(&inf, ii);
|
||||
if (i == 0) {
|
||||
continue;
|
||||
}
|
||||
if (stbtt_IsGlyphEmpty(&inf, i)) {
|
||||
c.cp(i);
|
||||
c.tex(tex);
|
||||
c.invalid(true);
|
||||
cpmap[i] = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
Codepoint c;
|
||||
int w = 0, h = 0, xo = 0, yo = 0;
|
||||
unsigned char* bitmap =
|
||||
stbtt_GetCodepointBitmap(&inf, scale, scale, i, &w, &h, &xo, &yo);
|
||||
int x0, y0, x1, y1;
|
||||
stbtt_GetCodepointBitmapBox(&inf, i, scale, scale, &x0, &y0, &x1, &y1);
|
||||
|
||||
u32 hashed_map = IO::HashMemory(std::vector<u8>(bitmap, bitmap + (w * h)));
|
||||
if (buf_cache.find(hashed_map) != buf_cache.end()) {
|
||||
c = GetCodepoint(buf_cache[hashed_map]);
|
||||
c.cp(i);
|
||||
cpmap[i] = c;
|
||||
free(bitmap);
|
||||
continue;
|
||||
} else {
|
||||
buf_cache[hashed_map] = i;
|
||||
}
|
||||
|
||||
if (off[0] + w > quad) {
|
||||
off[1] += pixel_height;
|
||||
off[0] = 0;
|
||||
@ -88,24 +102,25 @@ void Font::LoadTTF(const std::string& path, int height) {
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
int map_pos = ((off[1] + y) * quad + (off[0] + x)) * 4;
|
||||
|
||||
font_tex[map_pos + 0] = 255;
|
||||
font_tex[map_pos + 1] = 255;
|
||||
font_tex[map_pos + 2] = 255;
|
||||
font_tex[map_pos + 3] = bitmap[x + y * w];
|
||||
int map_pos = ((off[1] + y) * quad + (off[0] + x));
|
||||
font_tex[map_pos] = bitmap[x + y * w];
|
||||
}
|
||||
}
|
||||
|
||||
free(bitmap);
|
||||
cpmap[i] = c;
|
||||
|
||||
// Small Patch to avoid some possible artifacts
|
||||
off[0] += w + 1;
|
||||
if (off[0] + w > quad) {
|
||||
off[1] += pixel_height;
|
||||
if (off[1] + pixel_height > quad) {
|
||||
break;
|
||||
}
|
||||
off[0] = 0;
|
||||
}
|
||||
free(bitmap);
|
||||
cpmap[i] = c;
|
||||
}
|
||||
tex->LoadPixels(font_tex, quad, quad, Texture::RGBA32, Texture::LINEAR);
|
||||
tex->LoadPixels(font_tex, quad, quad, Texture::A8, Texture::LINEAR);
|
||||
textures.push_back(tex);
|
||||
}
|
||||
|
||||
@ -143,6 +158,7 @@ void Font::LoadSystemFont() {
|
||||
tx->border = 0xffffffff;
|
||||
tx->lodParam = 0;
|
||||
stex->LoadExternal(tx, vec2(tx->width, tx->height), vec4(0, 1, 1, 0));
|
||||
stex->AutoUnLoad(false);
|
||||
textures[i] = stex;
|
||||
}
|
||||
std::vector<unsigned int> charSet;
|
||||
@ -192,8 +208,10 @@ void Font::LoadSystemFont() {
|
||||
codepoint.uv(vec4(dat.texcoord.left, dat.texcoord.top, dat.texcoord.right,
|
||||
dat.texcoord.bottom));
|
||||
|
||||
if (textures.at(dat.sheetIndex) != nullptr) {
|
||||
if (dat.sheetIndex < (int)textures.size()) {
|
||||
codepoint.tex(textures[dat.sheetIndex]);
|
||||
} else {
|
||||
codepoint.invalid(true);
|
||||
}
|
||||
codepoint.size(vec2(dat.vtxcoord.right, dat.vtxcoord.bottom));
|
||||
codepoint.off(0);
|
||||
@ -250,7 +268,9 @@ void Renderer::StaticText::Setup(Renderer* ren, const vec2& pos, u32 clr,
|
||||
this->pos = pos;
|
||||
this->ren = ren;
|
||||
this->text = StaticObject::New();
|
||||
ren->TextCommand(this->text->List(), pos, clr, text, flags, box);
|
||||
/// Ensure that it also renders Out of Screen i guess
|
||||
ren->TextCommand(this->text->List(), pos, clr, text,
|
||||
flags | LITextFlags_RenderOOS, box);
|
||||
OptiCommandList(this->text->List());
|
||||
}
|
||||
|
||||
@ -267,6 +287,8 @@ void Renderer::StaticText::SetPos(const vec2& pos) {
|
||||
text->MoveIt(pos - this->pos);
|
||||
}
|
||||
|
||||
void Renderer::StaticText::SetLayer(int layer) { text->ReLayer(layer); }
|
||||
|
||||
bool Renderer::InBox(const vec2& pos, const vec2& szs, const vec4& rect) {
|
||||
return (pos[0] < rect[2] || pos[1] < rect[3] || pos[0] + szs[0] > rect[0] ||
|
||||
pos[1] + szs[1] > rect[1]);
|
||||
@ -341,18 +363,14 @@ void Renderer::SetupCommand(Command::Ref cmd) {
|
||||
cmd->Index(cmd_idx++).Layer(current_layer).Tex(current_tex);
|
||||
}
|
||||
|
||||
void Renderer::QuadCommand(Command::Ref cmd, const Rect& quad, const vec4& uv,
|
||||
void Renderer::QuadCommand(Command::Ref cmd, const Rect& quad, const Rect& uv,
|
||||
u32 col) {
|
||||
cmd->PushIndex(0).PushIndex(1).PushIndex(2);
|
||||
cmd->PushIndex(0).PushIndex(2).PushIndex(3);
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Bot().z(), quad.Bot().w()), vec2(uv.z(), uv.w()), col));
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Top().z(), quad.Top().w()), vec2(uv.z(), uv.y()), col));
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Top().x(), quad.Top().y()), vec2(uv.x(), uv.y()), col));
|
||||
cmd->PushVertex(
|
||||
Vertex(vec2(quad.Bot().x(), quad.Bot().y()), vec2(uv.x(), uv.w()), col));
|
||||
cmd->PushVertex(Vertex(quad.BotRight(), uv.BotRight(), col));
|
||||
cmd->PushVertex(Vertex(quad.TopRight(), uv.TopRight(), col));
|
||||
cmd->PushVertex(Vertex(quad.TopLeft(), uv.TopLeft(), col));
|
||||
cmd->PushVertex(Vertex(quad.BotLeft(), uv.BotLeft(), col));
|
||||
}
|
||||
|
||||
void Renderer::TriangleCommand(Command::Ref cmd, const vec2& a, const vec2& b,
|
||||
@ -364,7 +382,6 @@ void Renderer::TriangleCommand(Command::Ref cmd, const vec2& a, const vec2& b,
|
||||
cmd->PushVertex(Vertex(c, vec2(1.f, 0.f), col));
|
||||
}
|
||||
|
||||
/// TO BE REWRITTEN
|
||||
void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
u32 color, const std::string& text,
|
||||
LITextFlags flags, const vec2& box) {
|
||||
@ -375,6 +392,23 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
float cfs = (default_font_h * text_size) / (float)font->PixelHeight();
|
||||
float lh = (float)font->PixelHeight() * cfs;
|
||||
vec2 td;
|
||||
vec2 rpos = pos;
|
||||
vec2 rbox = box;
|
||||
if (flags & (LITextFlags_AlignMid | LITextFlags_AlignRight)) {
|
||||
td = GetTextDimensions(text);
|
||||
if (rbox[0] == 0.f) {
|
||||
rbox[0] = area_size.x();
|
||||
}
|
||||
if (rbox[1] == 0.f) {
|
||||
rbox[1] = area_size.y();
|
||||
}
|
||||
}
|
||||
if (flags & LITextFlags_AlignMid) {
|
||||
rpos = rbox * 0.5 - td * 0.5 + pos;
|
||||
}
|
||||
if (flags & LITextFlags_AlignRight) {
|
||||
rpos[0] = rbox[0] - td[0];
|
||||
}
|
||||
|
||||
std::vector<std::string> lines;
|
||||
std::istringstream iss(text);
|
||||
@ -384,10 +418,10 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
}
|
||||
|
||||
for (auto& it : lines) {
|
||||
if (pos[1] + off[1] + lh < 0) {
|
||||
if (rpos[1] + off[1] + lh < 0) {
|
||||
off[1] += lh;
|
||||
continue;
|
||||
} else if (pos[1] + off[1] > GetViewport().w() &&
|
||||
} else if (rpos[1] + off[1] > GetViewport().w() &&
|
||||
!(flags & LITextFlags_RenderOOS)) {
|
||||
// Break cause next lines would be out of screen
|
||||
break;
|
||||
@ -396,9 +430,7 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
auto cmd = Command::New();
|
||||
current_tex = font->GetCodepoint(wline[0]).tex();
|
||||
SetupCommand(cmd);
|
||||
if (font->SystemFont()) {
|
||||
cmd->Rendermode(RenderMode_SysFont);
|
||||
}
|
||||
cmd->Rendermode(RenderMode_Font);
|
||||
for (auto& jt : wline) {
|
||||
auto cp = font->GetCodepoint(jt);
|
||||
if (cp.invalid() && jt != '\n' && jt != '\t') {
|
||||
@ -409,9 +441,7 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
cmd = Command::New();
|
||||
current_tex = cp.tex();
|
||||
SetupCommand(cmd);
|
||||
if (font->SystemFont()) {
|
||||
cmd->Rendermode(RenderMode_SysFont);
|
||||
}
|
||||
cmd->Rendermode(RenderMode_Font);
|
||||
}
|
||||
if (jt == '\t') {
|
||||
off[0] += 16 * cfs;
|
||||
@ -421,13 +451,13 @@ void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
if (flags & LITextFlags_Shaddow) {
|
||||
// Draw
|
||||
Rect rec = CreateRect(
|
||||
pos + vec2(off[0] + 1, off[1] + (cp.off() * cfs)) + 1,
|
||||
rpos + vec2(off[0] + 1, off[1] + (cp.off() * cfs)) + 1,
|
||||
cp.size() * cfs, 0.f);
|
||||
QuadCommand(cmd, rec, cp.uv(), 0xff111111);
|
||||
current_layer++;
|
||||
}
|
||||
// Draw
|
||||
Rect rec = CreateRect(pos + off + vec2(0, (cp.off() * cfs)),
|
||||
Rect rec = CreateRect(rpos + off + vec2(0, (cp.off() * cfs)),
|
||||
cp.size() * cfs, 0.f);
|
||||
QuadCommand(cmd, rec, cp.uv(), color);
|
||||
current_layer = lr;
|
||||
@ -450,7 +480,6 @@ vec4 Renderer::GetViewport() {
|
||||
return vec4(0, 0, screen[0], screen[1]);
|
||||
}
|
||||
|
||||
/// TO BE REWRITTEN
|
||||
vec2 Renderer::GetTextDimensions(const std::string& text) {
|
||||
if (!font) {
|
||||
// No font no size (oder so)
|
||||
@ -516,7 +545,8 @@ vec2 Renderer::GetTextDimensions(const std::string& text) {
|
||||
void Renderer::UpdateRenderMode(const RenderMode& mode) {
|
||||
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||
switch (mode) {
|
||||
case RenderMode_SysFont:
|
||||
case RenderMode_Font:
|
||||
/// Sets Only Alpha Using the Color and Replase RGB with vertex color
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_RGB, GPU_PRIMARY_COLOR);
|
||||
C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE);
|
||||
@ -526,6 +556,7 @@ void Renderer::UpdateRenderMode(const RenderMode& mode) {
|
||||
// Fall trough instead of defining twice
|
||||
case RenderMode_RGBA:
|
||||
default:
|
||||
/// Use Texture for RGBA and vertexcolor for visibility
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0);
|
||||
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
|
||||
@ -536,23 +567,17 @@ void Renderer::UpdateRenderMode(const RenderMode& mode) {
|
||||
void Renderer::RenderOn(bool bot) {
|
||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection,
|
||||
(bot ? &bot_proj : &top_proj));
|
||||
|
||||
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL);
|
||||
|
||||
UpdateRenderMode(RenderMode_RGBA);
|
||||
|
||||
int total_vertices = 0;
|
||||
int total_indices = 0;
|
||||
drawcalls = 0;
|
||||
auto& cmds = draw_list[bot];
|
||||
|
||||
commands = cmds.size();
|
||||
size_t index = 0;
|
||||
|
||||
if (flags & RenderFlags_LRS) {
|
||||
OptiCommandList(cmds);
|
||||
}
|
||||
|
||||
while (index < cmds.size()) {
|
||||
C3D_Tex* tex = cmds[index]->Tex()->GetTex();
|
||||
auto mode = cmds[index]->Rendermode();
|
||||
@ -572,6 +597,7 @@ void Renderer::RenderOn(bool bot) {
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
C3D_TexBind(0, tex);
|
||||
|
||||
auto bufInfo = C3D_GetBufInfo();
|
||||
@ -580,6 +606,7 @@ void Renderer::RenderOn(bool bot) {
|
||||
|
||||
C3D_DrawElements(GPU_TRIANGLES, index_idx - start_idx, C3D_UNSIGNED_SHORT,
|
||||
index_buf.data() + start_idx);
|
||||
|
||||
drawcalls++;
|
||||
total_vertices += vertex_idx - start_vtx;
|
||||
total_indices += index_idx - start_idx;
|
||||
@ -629,6 +656,8 @@ void Renderer::Render() {
|
||||
if (Sys::GetTime() - it.second.TimeCreated() > 5) rem.push_back(it.first);
|
||||
}
|
||||
for (auto it : rem) tms.erase(it);
|
||||
} else {
|
||||
tms.clear();
|
||||
}
|
||||
if (flags & RenderFlags_AST) {
|
||||
std::vector<u32> rem;
|
||||
@ -641,11 +670,13 @@ void Renderer::Render() {
|
||||
for (auto& it : rem) {
|
||||
ast.erase(it);
|
||||
}
|
||||
} else {
|
||||
ast.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::DrawRect(const vec2& pos, const vec2& size, u32 color,
|
||||
const vec4& uv) {
|
||||
const Rect& uv) {
|
||||
if (!InBox(pos, size, GetViewport())) {
|
||||
// Instand abort as it is out of screen
|
||||
return;
|
||||
@ -659,7 +690,7 @@ void Renderer::DrawRect(const vec2& pos, const vec2& size, u32 color,
|
||||
|
||||
void Renderer::DrawRectSolid(const vec2& pos, const vec2& size, u32 color) {
|
||||
UseTex();
|
||||
DrawRect(pos, size, color);
|
||||
DrawRect(pos, size, color, vec4(0.f, 1.f, 1.f, 0.f));
|
||||
}
|
||||
|
||||
void Renderer::DrawTriangle(const vec2& a, const vec2& b, const vec2& c,
|
||||
|
44
source/graphics/spritesheet.cpp
Normal file
44
source/graphics/spritesheet.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include <pd/common/io.hpp>
|
||||
#include <pd/graphics/spritesheet.hpp>
|
||||
|
||||
namespace PD {
|
||||
SpriteSheet::~SpriteSheet() { textures.clear(); }
|
||||
|
||||
void SpriteSheet::LoadFile(const std::string& path) {
|
||||
auto file = IO::LoadFile2Mem(path);
|
||||
if (file.size() == 0) {
|
||||
Error("Unable to load file:\n" + path);
|
||||
}
|
||||
C3D_Tex* tex = new C3D_Tex;
|
||||
auto t3x =
|
||||
Tex3DS_TextureImport(file.data(), file.size(), tex, nullptr, false);
|
||||
if (!t3x) {
|
||||
Error("Unable to import:\n" + path);
|
||||
}
|
||||
tex->border = 0;
|
||||
C3D_TexSetWrap(tex, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER);
|
||||
C3D_TexSetFilter(tex, GPU_LINEAR, GPU_NEAREST);
|
||||
textures.reserve(Tex3DS_GetNumSubTextures(t3x) + 1);
|
||||
for (int i = 0; i < (int)Tex3DS_GetNumSubTextures(t3x); i++) {
|
||||
auto t = Texture::New();
|
||||
auto st = Tex3DS_GetSubTexture(t3x, i);
|
||||
LI::Rect uv(vec2(st->left, st->top), vec2(st->right, st->top),
|
||||
vec2(st->left, st->bottom), vec2(st->right, st->bottom));
|
||||
if (st->top < st->bottom) {
|
||||
uv.SwapVec2XY();
|
||||
}
|
||||
t->LoadExternal(tex, vec2(st->width, st->height), uv);
|
||||
textures.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
Texture::Ref SpriteSheet::Get(int idx) {
|
||||
if (idx >= (int)textures.size()) {
|
||||
Error("Trying to Access Texture " + std::to_string(idx + 1) + " of " +
|
||||
std::to_string(NumTextures()));
|
||||
}
|
||||
return textures[idx];
|
||||
}
|
||||
|
||||
int SpriteSheet::NumTextures() const { return textures.size(); }
|
||||
} // namespace PD
|
@ -24,12 +24,14 @@ SOFTWARE.
|
||||
|
||||
#include <3ds.h>
|
||||
#include <pd/external/stb_image.h>
|
||||
#include <tex3ds.h>
|
||||
|
||||
#include <pd/common/error.hpp>
|
||||
#include <pd/common/io.hpp>
|
||||
#include <pd/common/timetrace.hpp>
|
||||
#include <pd/graphics/texture.hpp>
|
||||
#include <pd/maths/bit_util.hpp>
|
||||
#include <pd/maths/img_convert.hpp>
|
||||
#include <pd/common/error.hpp>
|
||||
|
||||
namespace PD {
|
||||
GPU_TEXCOLOR GetTexFmt(Texture::Type type) {
|
||||
@ -54,36 +56,6 @@ void Texture::MakeTex(std::vector<u8>& buf, int w, int h, Texture::Type type,
|
||||
Filter filter) {
|
||||
// Don't check here as check done before
|
||||
int bpp = GetBPP(type);
|
||||
if (bpp == 4) {
|
||||
// RGBA -> Abgr
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int pos = (x + y * w) * bpp;
|
||||
auto r = buf[pos + 0];
|
||||
auto g = buf[pos + 1];
|
||||
auto b = buf[pos + 2];
|
||||
auto a = buf[pos + 3];
|
||||
buf[pos + 0] = a;
|
||||
buf[pos + 1] = b;
|
||||
buf[pos + 2] = g;
|
||||
buf[pos + 3] = r;
|
||||
}
|
||||
}
|
||||
} else if (bpp == 3) {
|
||||
// RGBA -> Abgr
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int pos = (x + y * w) * bpp;
|
||||
auto r = buf[pos + 0];
|
||||
auto g = buf[pos + 1];
|
||||
auto b = buf[pos + 2];
|
||||
buf[pos + 0] = b;
|
||||
buf[pos + 1] = g;
|
||||
buf[pos + 2] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vec2 tex_size(w, h);
|
||||
// Pow2
|
||||
if (!PD::BitUtil::IsSingleBit(w)) {
|
||||
@ -95,10 +67,8 @@ void Texture::MakeTex(std::vector<u8>& buf, int w, int h, Texture::Type type,
|
||||
|
||||
this->size.x() = (u16)w;
|
||||
this->size.y() = (u16)h;
|
||||
this->uv.x() = 0.0f;
|
||||
this->uv.y() = 1.0f;
|
||||
this->uv.z() = ((float)w / (float)tex_size.x());
|
||||
this->uv.w() = 1.0 - ((float)h / (float)tex_size.y());
|
||||
this->uv = vec4(0.f, 1.f, ((float)w / (float)tex_size.x()),
|
||||
1.0 - ((float)h / (float)tex_size.y()));
|
||||
|
||||
// Texture Setup
|
||||
auto fltr = (filter == NEAREST ? GPU_NEAREST : GPU_LINEAR);
|
||||
@ -109,7 +79,9 @@ void Texture::MakeTex(std::vector<u8>& buf, int w, int h, Texture::Type type,
|
||||
|
||||
memset(tex->data, 0, tex->size);
|
||||
|
||||
if (bpp == 3 || bpp == 4) {
|
||||
/// Probably Remove this if statement in future
|
||||
/// This are the things confirmed as working
|
||||
if (bpp == 3 || bpp == 4 || bpp == 1) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int dst_pos = ((((y >> 3) * ((int)tex_size.x() >> 3) + (x >> 3)) << 6) +
|
||||
@ -117,13 +89,13 @@ void Texture::MakeTex(std::vector<u8>& buf, int w, int h, Texture::Type type,
|
||||
((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3))) *
|
||||
bpp;
|
||||
int src_pos = (y * w + x) * bpp;
|
||||
|
||||
memcpy(&((u8*)tex->data)[dst_pos], &buf[src_pos], bpp);
|
||||
/// Best idea i had
|
||||
for (int i = 0; i < bpp; i++) {
|
||||
((u8*)tex->data)[dst_pos + bpp - 1 - i] = buf[src_pos + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
C3D_TexFlush(tex);
|
||||
} else if (bpp == 1) {
|
||||
C3D_TexLoadImage(tex, buf.data(), GPU_TEXFACE_2D, 0);
|
||||
}
|
||||
|
||||
tex->border = 0x00000000;
|
||||
@ -200,4 +172,23 @@ void Texture::LoadPixels(const std::vector<u8>& pixels, int w, int h, Type type,
|
||||
std::vector<u8> cpy(pixels);
|
||||
MakeTex(cpy, w, h, type, filter);
|
||||
}
|
||||
|
||||
void Texture::LoadT3X(const std::string& path) {
|
||||
this->Delete();
|
||||
auto file = IO::LoadFile2Mem(path);
|
||||
if (file.size() == 0) {
|
||||
Error("Unable to load file:\n" + path);
|
||||
}
|
||||
this->tex = new C3D_Tex;
|
||||
auto t3x =
|
||||
Tex3DS_TextureImport(file.data(), file.size(), this->tex, nullptr, false);
|
||||
if (!t3x) {
|
||||
Error("Unable to import:\n" + path);
|
||||
}
|
||||
auto st = Tex3DS_GetSubTexture(t3x, 0);
|
||||
this->uv = vec4(st->left, st->top, st->right, st->bottom);
|
||||
this->size[0] = st->width;
|
||||
this->size[1] = st->height;
|
||||
Tex3DS_TextureFree(t3x);
|
||||
}
|
||||
} // namespace PD
|
Reference in New Issue
Block a user