Adapting for web

This commit is contained in:
Vladislav Khorev committed 2026-02-08 22:38:24 +03:00
1 parent cf1ec1e76f
commit a59bcc0c4b
42 files changed
+843 -294

No files matched your search

+136 -88
View File
@@ -1,4 +1,4 @@
#include "render/TextRenderer.h"
#include "render/TextRenderer.h"
#include <ft2build.h>
#include FT_FREETYPE_H
@@ -11,53 +11,87 @@ namespace ZL {
TextRenderer::~TextRenderer()
{
for (auto& kv : glyphs) {
/*for (auto& kv : glyphs) {
if (kv.second.texID) glDeleteTextures(1, &kv.second.texID);
}
}*/
glyphs.clear();
textMesh.positionVBO.reset();
/*
if (vbo) glDeleteBuffers(1, &vbo);
// if (vao) glDeleteVertexArrays(1, &vao);
vao = 0;
vbo = 0;
vbo = 0;*/
}
bool TextRenderer::init(Renderer& renderer, const std::string& ttfPath, int pixelSize)
bool TextRenderer::init(Renderer& renderer, const std::string& ttfPath, int pixelSize, const std::string& zipfilename)
{
r = &renderer;
#ifdef EMSCRIPTEN
r->shaderManager.AddShaderFromFiles(shaderName,
"resources/shaders/text2d.vertex",
"resources/shaders/text2d.fragment",
"" // ZIP пустой
"resources/shaders/text2d_web.fragment",
zipfilename
);
#else
r->shaderManager.AddShaderFromFiles(shaderName,
"resources/shaders/text2d.vertex",
"resources/shaders/text2d_desktop.fragment",
zipfilename
);
#endif
ZL::CheckGlError();
if (!loadGlyphs(ttfPath, pixelSize, zipfilename)) return false;
ZL::CheckGlError();
if (!loadGlyphs(ttfPath, pixelSize)) return false;
textMesh.data.PositionData.resize(6, Eigen::Vector3f(0, 0, 0));
textMesh.RefreshVBO();
// VAO/VBO для 6 вершин (2 треугольника) * (pos.xy + uv.xy) = 4 float
// glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
/* glGenBuffers(1, &vbo);
//glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, nullptr, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
*/
ZL::CheckGlError();
return true;
}
bool TextRenderer::loadGlyphs(const std::string& ttfPath, int pixelSize)
bool TextRenderer::loadGlyphs(const std::string& ttfPath, int pixelSize, const std::string& zipfilename)
{
// 1. Загружаем сырые данные из ZIP
std::vector<char> fontData;
try {
fontData = !zipfilename.empty()
? readFileFromZIP(ttfPath, zipfilename)
: readFile(ttfPath); // Предполагаем наличие функции readFile
}
catch (const std::exception& e) {
std::cerr << "TextRenderer: failed to read font data: " << e.what() << "\n";
return false;
}
if (fontData.empty()) return false;
FT_Library ft;
if (FT_Init_FreeType(&ft)) {
std::cerr << "FreeType: FT_Init_FreeType failed\n";
return false;
}
// 2. Инициализируем Face из памяти
FT_Face face;
if (FT_New_Face(ft, ttfPath.c_str(), 0, &face)) {
std::cerr << "FreeType: failed to load font: " << ttfPath << "\n";
// Важно: передаем указатель на буфер и его размер
if (FT_New_Memory_Face(ft,
reinterpret_cast<const FT_Byte*>(fontData.data()),
static_cast<FT_Long>(fontData.size()),
0,
&face))
{
std::cerr << "FreeType: failed to load font from memory: " << ttfPath << "\n";
FT_Done_FreeType(ft);
return false;
}
@@ -67,52 +101,50 @@ bool TextRenderer::loadGlyphs(const std::string& ttfPath, int pixelSize)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glyphs.clear();
// Проходим по стандартным ASCII символам
for (unsigned char c = 32; c < 128; ++c) {
if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
continue;
}
FT_Load_Char(face, c, FT_LOAD_RENDER);
unsigned int tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RED,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_RED,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer
);
TextureDataStruct glyphData;
glyphData.width = face->glyph->bitmap.width;
glyphData.height = face->glyph->bitmap.rows;
glyphData.format = TextureDataStruct::R8;
glyphData.mipmap = TextureDataStruct::NONE;
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);
// Копируем буфер FreeType в вектор данных
size_t dataSize = glyphData.width * glyphData.height;
glyphData.data.assign(face->glyph->bitmap.buffer, face->glyph->bitmap.buffer + dataSize);
GlyphInfo g;
g.texID = tex;
// Теперь создание текстуры — это одна строка!
auto tex = std::make_shared<Texture>(glyphData);
GlyphInfo g;
g.texture = tex;
g.size = Eigen::Vector2f((float)face->glyph->bitmap.width, (float)face->glyph->bitmap.rows);
g.bearing = Eigen::Vector2f((float)face->glyph->bitmap_left, (float)face->glyph->bitmap_top);
// Advance во FreeType измеряется в 1/64 пикселя
g.advance = (unsigned int)face->glyph->advance.x;
glyphs.emplace((char)c, g);
}
// Очистка
FT_Done_Face(face);
FT_Done_FreeType(ft);
// После FT_Done_Face данные из fontData больше не нужны,
// вектор сам очистится при выходе из функции.
glBindTexture(GL_TEXTURE_2D, 0);
return true;
}
void TextRenderer::drawText(const std::string& text, float x, float y, float scale, bool centered, std::array<float, 4> color)
{
if (!r) return;
if (!r || text.empty()) return;
// Считаем ширину строки для центрирования
// 1. Считаем ширину для центрирования
float totalW = 0.0f;
if (centered) {
for (char ch : text) {
@@ -123,35 +155,8 @@ void TextRenderer::drawText(const std::string& text, float x, float y, float sca
x -= totalW * 0.5f;
}
r->shaderManager.PushShader(shaderName);
// Орто-проекция в пикселях: (0..W, 0..H)
float W = (float)Environment::width;
float H = (float)Environment::height;
Eigen::Matrix4f proj = Eigen::Matrix4f::Identity();
proj(0,0) = 2.0f / W;
proj(1,1) = 2.0f / H;
proj(0,3) = -1.0f;
proj(1,3) = -1.0f;
// uProjection
r->RenderUniformMatrix4fv("uProjection", false, proj.data());
r->RenderUniform1i("uText", 0);
r->RenderUniform4fv("uColor", color.data());
glActiveTexture(GL_TEXTURE0);
// glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
r->EnableVertexAttribArray("vPosition");
r->EnableVertexAttribArray("vTexCoord");
r->VertexAttribPointer2fv("vPosition", 4 * sizeof(float), (const char*)0);
r->VertexAttribPointer2fv("vTexCoord", 4 * sizeof(float), (const char*)(2 * sizeof(float)));
// 2. Подготовка данных (аналог CreateRect2D, но для всей строки)
VertexDataStruct textData;
float penX = x;
float penY = y;
@@ -163,36 +168,79 @@ void TextRenderer::drawText(const std::string& text, float x, float y, float sca
float xpos = penX + g.bearing.x() * scale;
float ypos = penY - (g.size.y() - g.bearing.y()) * scale;
float w = g.size.x() * scale;
float h = g.size.y() * scale;
// 2 треугольника
float verts[6][4] = {
{ xpos, ypos + h, 0.0f, 0.0f },
{ xpos, ypos, 0.0f, 1.0f },
{ xpos + w, ypos, 1.0f, 1.0f },
// Добавляем 2 треугольника (6 вершин) для текущего символа
// Координаты Z ставим 0.0f, так как это 2D
textData.PositionData.push_back({ xpos, ypos + h, 0.0f });
textData.PositionData.push_back({ xpos, ypos, 0.0f });
textData.PositionData.push_back({ xpos + w, ypos, 0.0f });
textData.PositionData.push_back({ xpos, ypos + h, 0.0f });
textData.PositionData.push_back({ xpos + w, ypos, 0.0f });
textData.PositionData.push_back({ xpos + w, ypos + h, 0.0f });
{ xpos, ypos + h, 0.0f, 0.0f },
{ xpos + w, ypos, 1.0f, 1.0f },
{ xpos + w, ypos + h, 1.0f, 0.0f }
};
glBindTexture(GL_TEXTURE_2D, g.texID);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts);
glDrawArrays(GL_TRIANGLES, 0, 6);
// UV-координаты (здесь есть нюанс с атласом, ниже поясню)
textData.TexCoordData.push_back({ 0.0f, 0.0f });
textData.TexCoordData.push_back({ 0.0f, 1.0f });
textData.TexCoordData.push_back({ 1.0f, 1.0f });
textData.TexCoordData.push_back({ 0.0f, 0.0f });
textData.TexCoordData.push_back({ 1.0f, 1.0f });
textData.TexCoordData.push_back({ 1.0f, 0.0f });
penX += (g.advance >> 6) * scale;
}
// cleanup
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 3. Обновляем VBO через наш стандартный механизм
// Примечание: для текста лучше использовать GL_DYNAMIC_DRAW,
// но RefreshVBO сейчас жестко зашит на GL_STATIC_DRAW.
// Для UI это обычно не критично, если строк не тысячи.
textMesh.AssignFrom(textData);
// 4. Рендеринг
r->shaderManager.PushShader(shaderName);
// Матрица проекции (экрана)
float W = (float)Environment::width;
float H = (float)Environment::height;
Eigen::Matrix4f proj = Eigen::Matrix4f::Identity();
proj(0, 0) = 2.0f / W;
proj(1, 1) = 2.0f / H;
proj(0, 3) = -1.0f;
proj(1, 3) = -1.0f;
r->RenderUniformMatrix4fv("uProjection", false, proj.data());
r->RenderUniform1i("uText", 0);
r->RenderUniform4fv("uColor", color.data());
glActiveTexture(GL_TEXTURE0);
// ВНИМАНИЕ: Так как у тебя каждый символ — это отдельная текстура,
// нам всё равно придется делать glDrawArrays в цикле, ЛИБО использовать атлас.
// Если оставляем текущую систему с разными текстурами:
r->EnableVertexAttribArray("vPosition");
r->EnableVertexAttribArray("vTexCoord");
for (size_t i = 0; i < text.length(); ++i) {
auto it = glyphs.find(text[i]);
if (it == glyphs.end()) continue;
glBindTexture(GL_TEXTURE_2D, it->second.texture->getTexID());
// Отрисовываем по 6 вершин за раз
// Нам нужно вручную биндить VBO, так как DrawVertexRenderStruct рисует всё сразу
glBindBuffer(GL_ARRAY_BUFFER, textMesh.positionVBO->getBuffer());
r->VertexAttribPointer3fv("vPosition", 0, (const char*)(i * 6 * sizeof(Vector3f)));
glBindBuffer(GL_ARRAY_BUFFER, textMesh.texCoordVBO->getBuffer());
r->VertexAttribPointer2fv("vTexCoord", 0, (const char*)(i * 6 * sizeof(Vector2f)));
glDrawArrays(GL_TRIANGLES, 0, 6);
}
r->DisableVertexAttribArray("vPosition");
r->DisableVertexAttribArray("vTexCoord");
r->shaderManager.PopShader();
}
} // namespace ZL
+9 -6
View File
@@ -1,17 +1,18 @@
#pragma once
#pragma once
#include <string>
#include <memory>
#include <vector>
#include <unordered_map>
#include <Eigen/Dense>
#include "render/Renderer.h"
#include "render/TextureManager.h"
#include <array>
namespace ZL {
struct GlyphInfo {
unsigned int texID = 0; // GL texture for glyph
std::shared_ptr<Texture> texture; // Texture for glyph
Eigen::Vector2f size; // glyph size in pixels
Eigen::Vector2f bearing; // offset from baseline
unsigned int advance = 0; // advance.x in 1/64 pixels
@@ -22,19 +23,21 @@ public:
TextRenderer() = default;
~TextRenderer();
bool init(Renderer& renderer, const std::string& ttfPath, int pixelSize);
bool init(Renderer& renderer, const std::string& ttfPath, int pixelSize, const std::string& zipfilename);
void drawText(const std::string& text, float x, float y, float scale, bool centered, std::array<float, 4> color = { 1.f,1.f,1.f,1.f });
private:
bool loadGlyphs(const std::string& ttfPath, int pixelSize);
bool loadGlyphs(const std::string& ttfPath, int pixelSize, const std::string& zipfilename);
Renderer* r = nullptr;
std::unordered_map<char, GlyphInfo> glyphs;
// OpenGL objects for a dynamic quad
unsigned int vao = 0;
unsigned int vbo = 0;
//unsigned int vao = 0;
//unsigned int vbo = 0;
VertexRenderStruct textMesh;
std::string shaderName = "text2d";
};
+67 -82
View File
@@ -1,4 +1,4 @@
#include "render/TextureManager.h"
#include "render/TextureManager.h"
#include "render/OpenGlExtensions.h"
#ifdef PNG_ENABLED
#include "png.h"
@@ -11,48 +11,68 @@ namespace ZL
Texture::Texture(const TextureDataStruct& texData) {
width = texData.width;
height = texData.height;
glGenTextures(1, &texID);
if (texID == 0) {
throw std::runtime_error("glGenTextures did not work");
glBindTexture(GL_TEXTURE_2D, texID);
GLint internalFormat;
GLenum externalFormat;
switch (texData.format) {
case TextureDataStruct::R8:
// Для WebGL 1.0 лучше использовать GL_LUMINANCE вместо GL_RED
// Если используешь WebGL 2.0, можно оставить GL_RED
#if defined(EMSCRIPTEN) || defined(__ANDROID__)
internalFormat = GL_LUMINANCE;
externalFormat = GL_LUMINANCE;
#else
internalFormat = GL_RED;
externalFormat = GL_RED;
#endif
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Исправлено: используем GL_TEXTURE_2D
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
break;
case TextureDataStruct::RGB:
internalFormat = GL_RGB;
externalFormat = GL_RGB;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // RGB может быть не выровнен по 4 байта
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
break;
default: // RGBA
internalFormat = GL_RGBA;
externalFormat = GL_RGBA;
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
break;
}
glBindTexture(GL_TEXTURE_2D, texID);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat,
static_cast<GLsizei>(width), static_cast<GLsizei>(height),
0, externalFormat, GL_UNSIGNED_BYTE, texData.data.data());
CheckGlError();
// ��������� ���������� � ����������� �� ���������� ����
if (texData.mipmap == TextureDataStruct::GENERATE) {
// ���������� ����������� ���������� ��� ���������� ��������
// 3. Фильтрация и Мип-мапы
// ВНИМАНИЕ: Для шрифтов (NPOT) в WebGL glGenerateMipmap работать НЕ будет!
if (texData.mipmap == TextureDataStruct::GENERATE && texData.format != TextureDataStruct::R8) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
// ������� �������� ���������� (����� ������� �� ��������)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
CheckGlError();
// �������� ������ �������� ������ (Level 0)
GLint format = (texData.bitSize == TextureDataStruct::BS_24BIT) ? GL_RGB : GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, format,
static_cast<GLsizei>(width),
static_cast<GLsizei>(height),
0, format, GL_UNSIGNED_BYTE, texData.data.data());
CheckGlError();
// ��������� ���-�����, ���� ��� ����������
if (texData.mipmap == TextureDataStruct::GENERATE) {
glGenerateMipmap(GL_TEXTURE_2D);
CheckGlError();
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
}
Texture::Texture(const std::array<TextureDataStruct, 6>& texDataArray)
{
// ��������, ��� ��� ����� ����� ���������� �������
width = texDataArray[0].width;
height = texDataArray[0].height;
@@ -73,36 +93,28 @@ namespace ZL
CheckGlError();
// ��������� ���������� ��� Cubemap
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// ���������� GL_LINEAR ��� MIN_FILTER, ��� ��� ������� ����� �� ������������
// ���� �� �������������� ������� (e.g., GL_LINEAR_MIPMAP_LINEAR), ����� ���� �� ������� glGenerateMipmap.
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// ������������ ��������� ������� ��� Cubemap
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// GL_TEXTURE_WRAP_R �� �������������� � WebGL 1.0/OpenGL ES 2.0 � �������� ������.
// ������������ ��� ����� ������ ��� ���������� ��������.
#ifndef EMSCRIPTEN
#ifndef __ANDROID__
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
#endif
#endif
CheckGlError(); // �������� ����� ��������� ����������
// �������� ������ ��� ������ �� 6 ������
// GL_TEXTURE_CUBE_MAP_POSITIVE_X + i ���� �����: +X (0), -X (1), +Y (2), -Y (3), +Z (4), -Z (5)
CheckGlError();
for (int i = 0; i < 6; ++i)
{
GLint internalFormat;
GLenum format;
// � WebGL 1.0/OpenGL ES 2.0 ���������� ������ (internalFormat)
// ������ ������ ��������������� ������� ������ (format).
if (texDataArray[i].bitSize == TextureDataStruct::BS_24BIT)
if (texDataArray[i].format == TextureDataStruct::RGB)
{
internalFormat = GL_RGB; // internalFormat
format = GL_RGB; // format
@@ -114,20 +126,19 @@ namespace ZL
}
glTexImage2D(
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, // ������� �����
0, // ������� MIP-��������
internalFormat, // ���������� ������ (������ ��������� � ��������)
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
0,
internalFormat,
static_cast<GLsizei>(width),
static_cast<GLsizei>(height),
0, // ������� (������ 0)
format, // ������ �������� ������
GL_UNSIGNED_BYTE, // ��� ������
texDataArray[i].data.data() // ��������� �� ������
0,
format,
GL_UNSIGNED_BYTE,
texDataArray[i].data.data()
);
CheckGlError();
}
// ������� �������� ��� �������
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
@@ -173,7 +184,7 @@ namespace ZL
texData.width = *reinterpret_cast<uint32_t*>(&fileArr[18]);
texData.height = *reinterpret_cast<uint32_t*>(&fileArr[22]);
texData.bitSize = TextureDataStruct::BS_24BIT;
texData.format = TextureDataStruct::RGB;
size_t dataSize = texData.width * texData.height * 3;
@@ -222,7 +233,7 @@ namespace ZL
texData.width = *reinterpret_cast<uint32_t*>(&fileArr[18]);
texData.height = *reinterpret_cast<uint32_t*>(&fileArr[22]);
texData.bitSize = TextureDataStruct::BS_32BIT;
texData.format = TextureDataStruct::RGBA;
size_t dataSize = texData.width * texData.height * 4;
@@ -255,48 +266,33 @@ namespace ZL
#ifdef PNG_ENABLED
// ��������� ��� �������� ������ � �����/������� � ������� ������� ������
struct png_data_t {
const char* data;
size_t size;
size_t offset;
};
// ���������������� ������� ������ ��� libpng
// 'png_ptr' - ��������� �� ��������� png
// 'out_ptr' - ���� ���������� ����������� ������
// 'bytes_to_read' - ������� ���� ����� ���������
void user_read_data(png_structp png_ptr, png_bytep out_ptr, png_size_t bytes_to_read) {
// �������� ��������� �� ���� ��������� png_data_t, ������� �� ���������� � ������� png_set_read_fn
png_data_t* data = (png_data_t*)png_get_io_ptr(png_ptr);
if (data->offset + bytes_to_read > data->size) {
// ������� ��������� ������, ��� ���� � �������.
// ������ ������ ����������� ������, �� ����� ������ ��������� ������� ��� ������� ������.
// � ���� ������ �� ������� ������ libpng.
png_error(png_ptr, "PNG Read Error: Attempted to read past end of data buffer.");
bytes_to_read = data->size - data->offset; // �������������, ����� ��������� ����������
bytes_to_read = data->size - data->offset;
}
// �������� ������ �� ������ ������� � ����� libpng
std::memcpy(out_ptr, data->data + data->offset, bytes_to_read);
// ��������� ��������
data->offset += bytes_to_read;
}
// ���������������� ������� �������������� (�� �������, ����� ������������ nullptr)
void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) {
// ����� ����� ����������� ����������� ��������������
//throw std::runtime_error();
std::cout << "PNG Warning: " << warning_msg << std::endl;
}
// ���������������� ������� ������ (����������� ��� setjmp)
void user_error_fn(png_structp png_ptr, png_const_charp error_msg) {
// ����� ����� ����������� ����������� ������
std::cout << "PNG Error: " << error_msg << std::endl;
// ����������� �������� longjmp ��� ������ �� �������� ������/������ PNG
longjmp(png_jmpbuf(png_ptr), 1);
}
@@ -304,7 +300,6 @@ namespace ZL
{
TextureDataStruct texData;
// ��������� ��� ���������� ������� �� �������
png_data_t png_data = { fileArr.data(), fileArr.size(), 0 };
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
@@ -318,21 +313,15 @@ namespace ZL
throw std::runtime_error("Could not create PNG info structure");
}
// === ��������� ���������������� ������� ������ � ��������� ������ ===
// 1. ��������� ����������� ������ � longjmp
if (setjmp(png_jmpbuf(png))) {
png_destroy_read_struct(&png, &info, nullptr);
throw std::runtime_error("Error during PNG read (longjmp was executed)");
}
// 2. ��������� ���������������� ������� ��� ��������� ������ � ��������������
// ������ nullptr � error_ptr � warning_ptr ����� �������� ��������� �� ���� ��������� ������, ���� ����������
png_set_error_fn(png, nullptr, user_error_fn, user_warning_fn);
// 3. ��������� ���������������� ������� ������ � �������� �� ����� ��������� png_data
png_set_read_fn(png, &png_data, user_read_data);
// ===================================================================
png_read_info(png, info);
texData.width = png_get_image_width(png, info);
@@ -340,7 +329,6 @@ namespace ZL
png_byte color_type = png_get_color_type(png, info);
png_byte bit_depth = png_get_bit_depth(png, info);
// === ���� �������������� (�������� ��� ���������) ===
if (bit_depth == 16)
png_set_strip_16(png);
@@ -363,9 +351,7 @@ namespace ZL
png_set_gray_to_rgb(png);
png_read_update_info(png, info);
// ====================================================
// === ������ �������� (�������� ��� ���������) ===
png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * texData.height);
for (int y = 0; y < texData.height; y++) {
row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png, info));
@@ -379,11 +365,11 @@ namespace ZL
if (has_alpha)
{
texData.bitSize = TextureDataStruct::BS_32BIT;
texData.format = TextureDataStruct::RGBA;
}
else
{
texData.bitSize = TextureDataStruct::BS_24BIT;
texData.format = TextureDataStruct::RGB;
}
int channels = has_alpha ? 4 : 3;
@@ -424,7 +410,6 @@ namespace ZL
throw std::runtime_error("Could not read file data into memory");
}
// �������� ����� �������, ������� �������� � �������� ����
return CreateTextureDataFromPng(fileArr);
}
+10 -13
View File
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "render/OpenGlExtensions.h"
#include "utils/Utils.h"
@@ -15,23 +15,20 @@ namespace ZL
size_t height;
std::vector<char> data;
enum BitSize {
BS_24BIT,
BS_32BIT
enum Format {
R8, // Для шрифтов (GL_RED)
RGB, // BS_24BIT
RGBA // BS_32BIT
};
// ����� ������������ ��� ���������� ���-���������
enum MipmapType {
NONE, // ��� ���-����� (GL_LINEAR)
GENERATE // �������������� ��������� (GL_LINEAR_MIPMAP_LINEAR)
NONE,
GENERATE
};
BitSize bitSize;
/*#ifdef SIMPLIFIED
MipmapType mipmap = NONE; // �� ��������� ��������
#else*/
MipmapType mipmap = GENERATE; // �� ��������� ��������
//#endif
Format format = RGBA;
MipmapType mipmap = GENERATE;
};
class Texture
{