Added android version too

This commit is contained in:
Vladislav Khorev committed 2026-01-11 12:08:48 +03:00
1 parent 8089bcc0f3
commit a08ee412a6
54 files changed
+7146 -488

No files matched your search

+4 -4
View File
@@ -1,5 +1,5 @@
#pragma once
#include "OpenGlExtensions.h"
#include "render/OpenGlExtensions.h"
#include <memory>
namespace ZL {
@@ -9,10 +9,10 @@ namespace ZL {
GLuint fbo = 0;
GLuint textureID = 0;
int width, height;
bool useMipmaps; // Ôëàã èñïîëüçîâàíèÿ ìèï-ìàïîâ
bool useMipmaps; // ���� ������������� ���-�����
public:
// Äîáàâëÿåì ïàðàìåòð â êîíñòðóêòîð ïî óìîë÷àíèþ false
// ��������� �������� � ����������� �� ��������� false
FrameBuffer(int w, int h, bool useMipmaps = false);
~FrameBuffer();
@@ -22,7 +22,7 @@ namespace ZL {
void Bind();
void Unbind();
// Ìåòîä äëÿ ïðèíóäèòåëüíîé ãåíåðàöèè ìèï-ìàïîâ ïîñëå ðåíäåðà
// ����� ��� �������������� ��������� ���-����� ����� �������
void GenerateMipmaps();
GLuint getTextureID() const { return textureID; }
+9 -5
View File
@@ -10,13 +10,17 @@
#include "emscripten.h"
#endif
#ifdef __linux__
#include <GL/gl.h>
#include <GL/glu.h>
#include <GLES3/gl3.h>
#ifdef __ANDROID__
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#else
#ifdef __linux__
#include <GL/gl.h>
#include <GL/glu.h>
#include <GLES3/gl3.h>
#endif
#endif
#include <exception>
#include <stdexcept>
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+11 -4
View File
@@ -50,17 +50,17 @@ namespace ZL {
Matrix4f r;
// Ìàñøòàáèðîâàíèå
// ���������������
r.data()[0] = 2.f / width;
r.data()[5] = 2.f / height;
r.data()[10] = -1.f / depthRange;
// Îáíóëåíèå íåèñïîëüçóåìûõ êîìïîíåíòîâ
// ��������� �������������� �����������
r.data()[1] = r.data()[2] = r.data()[3] = 0;
r.data()[4] = r.data()[6] = r.data()[7] = 0;
r.data()[8] = r.data()[9] = r.data()[11] = 0;
// Òðàíñëÿöèÿ (ñìåùåíèå)
// ���������� (��������)
r.data()[12] = -(xmax + xmin) / width;
r.data()[13] = -(ymax + ymin) / height;
r.data()[14] = zNear / depthRange;
@@ -120,20 +120,23 @@ namespace ZL {
VAOHolder::VAOHolder()
{
#ifndef EMSCRIPTEN
#ifndef ANDROID
glGenVertexArrays(1, &vao);
#endif
#endif
}
VAOHolder::~VAOHolder()
{
#ifndef EMSCRIPTEN
#ifndef ANDROID
#ifdef __linux__
glDeleteVertexArrays(1, &vao);
#else
//Windows
glDeleteVertexArray(1, &vao);
#endif
#endif
#endif
}
@@ -365,12 +368,14 @@ namespace ZL {
//Check if main thread, check if data is not empty...
#ifndef EMSCRIPTEN
#ifndef __ANDROID__
if (!vao)
{
vao = std::make_shared<VAOHolder>();
}
glBindVertexArray(vao->getBuffer());
#endif
#endif
if (!positionVBO)
{
@@ -509,7 +514,9 @@ namespace ZL {
glActiveTexture(GL_TEXTURE0);
#ifndef EMSCRIPTEN
#ifndef __ANDROID__
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
#endif
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_LEQUAL);
+2 -1
View File
@@ -1,6 +1,7 @@
#pragma once
#include "OpenGlExtensions.h"
#include "render/OpenGlExtensions.h"
#include <exception>
#include <stdexcept>
#include "ShaderManager.h"
+182 -187
View File
@@ -1,227 +1,222 @@
#include "ShaderManager.h"
#include <iostream>
#include <SDL.h>
#ifdef __ANDROID__
#include <android/log.h>
#endif
namespace ZL {
ShaderResource::ShaderResource(const std::string& vertexCode, const std::string& fragmentCode)
{
ShaderResource::ShaderResource(const std::string &vertexCode, const std::string &fragmentCode) {
const int CONST_INFOLOG_LENGTH = 256;
const int CONST_INFOLOG_LENGTH = 256;
char infoLog[CONST_INFOLOG_LENGTH];
int infoLogLength;
char infoLog2[CONST_INFOLOG_LENGTH];
int infoLogLength2;
char infoLog[CONST_INFOLOG_LENGTH];
int infoLogLength;
int vertexShaderCompiled;
int fragmentShaderCompiled;
int programLinked;
int vertexShaderCompiled;
int fragmentShaderCompiled;
int programLinked;
GLuint vertexShader;
GLuint fragmentShader;
GLuint vertexShader;
GLuint fragmentShader;
int vertexCodeLength = static_cast<int>(strlen(vertexCode.c_str()));
int fragmentCodeLength = static_cast<int>(strlen(fragmentCode.c_str()));
int vertexCodeLength = static_cast<int>(strlen(vertexCode.c_str()));
int fragmentCodeLength = static_cast<int>(strlen(fragmentCode.c_str()));
const char* vc = &vertexCode[0];
const char* fc = &fragmentCode[0];
const char *vc = &vertexCode[0];
const char *fc = &fragmentCode[0];
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &(vc), &vertexCodeLength);
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &(vc), &vertexCodeLength);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &(fc), &fragmentCodeLength);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &(fc), &fragmentCodeLength);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexShaderCompiled);
glGetShaderInfoLog(vertexShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexShaderCompiled);
glGetShaderInfoLog(vertexShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentShaderCompiled);
glGetShaderInfoLog(fragmentShader, CONST_INFOLOG_LENGTH, &infoLogLength2, infoLog2);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentShaderCompiled);
glGetShaderInfoLog(fragmentShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
if (!vertexShaderCompiled)
{
#ifdef EMSCRIPTEN
std::cout << "Failed to compile vertex shader code!" << std::endl;
std::cout << infoLog << std::endl;
if (!vertexShaderCompiled) {
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_ERROR, "ShaderManager",
"Failed to compile vertex shader: %s", infoLog);
#endif
throw std::runtime_error("Failed to compile vertex shader code!");
}
if (!fragmentShaderCompiled)
{
#ifdef EMSCRIPTEN
std::cout << "Failed to compile fragment shader code!" << std::endl;
std::cout << infoLog2 << std::endl;
throw std::runtime_error("Failed to compile vertex shader code!");
}
if (!fragmentShaderCompiled) {
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_ERROR, "ShaderManager",
"Failed to compile fragment shader: %s", infoLog);
#endif
throw std::runtime_error("Failed to compile fragment shader code!");
}
throw std::runtime_error("Failed to compile fragment shader code!");
}
shaderProgram = glCreateProgram();
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &programLinked);
glGetProgramInfoLog(shaderProgram, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
if (!programLinked)
{
#ifdef EMSCRIPTEN
std::cout << "Failed to link shader program!" << std::endl;
std::cout << infoLog << std::endl;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &programLinked);
glGetProgramInfoLog(shaderProgram, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog);
if (!programLinked) {
shaderProgram = 0;
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_ERROR, "ShaderManager",
"Failed to link shader program: %s", infoLog);
#endif
shaderProgram = 0;
throw std::runtime_error("Failed to link shader program!");
}
throw std::runtime_error("Failed to link shader program!");
}
//================= Parsing all uniforms ================
int dummySize; //Dummy
int dummyLen; //Dummy
GLenum dummyEnum;
int activeUniforms;
const int CONST_UNIFORM_NAME_LENGTH = 256;
char uniformName[CONST_UNIFORM_NAME_LENGTH];
glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &activeUniforms);
for (int i = 0; i < activeUniforms; i++) {
glGetActiveUniform(shaderProgram, i, CONST_UNIFORM_NAME_LENGTH, &dummyLen, &dummySize,
&dummyEnum, uniformName);
uniformList[uniformName] = glGetUniformLocation(shaderProgram, uniformName);
}
//================= Parsing all attributes ================
int activeAttribs;
const int CONST_ATTRIB_NAME_LENGTH = 256;
char attribName[CONST_ATTRIB_NAME_LENGTH];
glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs);
for (int i = 0; i < activeAttribs; i++) {
glGetActiveAttrib(shaderProgram, i, CONST_ATTRIB_NAME_LENGTH, &dummyLen, &dummySize,
&dummyEnum, attribName);
attribList[attribName] = glGetAttribLocation(shaderProgram, attribName);
}
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
"Shader created successfully, program ID: %u", shaderProgram);
#endif
}
ShaderResource::~ShaderResource() {
if (shaderProgram != 0) {
glDeleteProgram(shaderProgram);
shaderProgram = 0;
}
}
GLuint ShaderResource::getShaderProgram() {
return shaderProgram;
}
int dummySize; //Dummy
int dummyLen; //Dummy
GLenum dummyEnum;
void ShaderManager::AddShaderFromFiles(const std::string &shaderName,
const std::string &vertexShaderFileName,
const std::string &fragmentShaderFileName,
const std::string &ZIPFileName) {
#ifdef __ANDROID__
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
"Loading shader: %s", shaderName.c_str());
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
"Vertex shader: %s", vertexShaderFileName.c_str());
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
"Fragment shader: %s", fragmentShaderFileName.c_str());
#endif
std::string vertexShader;
std::string fragmentShader;
if (!ZIPFileName.empty()) {
std::vector<char> vertexShaderData;
std::vector<char> fragmentShaderData;
vertexShaderData = readFileFromZIP(vertexShaderFileName, ZIPFileName);
fragmentShaderData = readFileFromZIP(fragmentShaderFileName, ZIPFileName);
vertexShader = std::string(vertexShaderData.begin(), vertexShaderData.end());
fragmentShader = std::string(fragmentShaderData.begin(), fragmentShaderData.end());
} else {
vertexShader = readTextFile(vertexShaderFileName);
fragmentShader = readTextFile(fragmentShaderFileName);
}
///std::cout << "Shader: "<< vertexShader << std::endl;
shaderResourceMap[shaderName] = std::make_shared<ShaderResource>(vertexShader,
fragmentShader);
}
void ShaderManager::PushShader(const std::string &shaderName) {
if (shaderStack.size() >= CONST_MAX_SHADER_STACK_SIZE) {
throw std::runtime_error("Shader stack overflow!");
}
if (shaderResourceMap.find(shaderName) == shaderResourceMap.end()) {
throw std::runtime_error("Shader does not exist!");
}
shaderStack.push(shaderName);
glUseProgram(shaderResourceMap[shaderName]->getShaderProgram());
}
//================= Parsing all uniforms ================
void ShaderManager::PopShader() {
if (shaderStack.size() == 0) {
throw std::runtime_error("Shader stack underflow!");
}
int activeUniforms;
shaderStack.pop();
const int CONST_UNIFORM_NAME_LENGTH = 256;
char uniformName[CONST_UNIFORM_NAME_LENGTH];
if (shaderStack.size() == 0) {
glUseProgram(0);
} else {
glUseProgram(shaderResourceMap[shaderStack.top()]->getShaderProgram());
}
}
glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &activeUniforms);
for (int i = 0; i < activeUniforms; i++)
{
glGetActiveUniform(shaderProgram, i, CONST_UNIFORM_NAME_LENGTH, &dummyLen, &dummySize, &dummyEnum, uniformName);
uniformList[uniformName] = glGetUniformLocation(shaderProgram, uniformName);
}
//================= Parsing all attributes ================
int activeAttribs;
const int CONST_ATTRIB_NAME_LENGTH = 256;
char attribName[CONST_ATTRIB_NAME_LENGTH];
glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs);
for (int i = 0; i < activeAttribs; i++)
{
glGetActiveAttrib(shaderProgram, i, CONST_ATTRIB_NAME_LENGTH, &dummyLen, &dummySize, &dummyEnum, attribName);
attribList[attribName] = glGetAttribLocation(shaderProgram, attribName);
}
}
ShaderResource::~ShaderResource()
{
if (shaderProgram != 0)
{
glDeleteProgram(shaderProgram);
shaderProgram = 0;
}
}
GLuint ShaderResource::getShaderProgram()
{
return shaderProgram;
}
std::shared_ptr <ShaderResource> ShaderManager::GetCurrentShader() {
if (shaderStack.size() == 0) {
throw std::runtime_error("Shader stack underflow!");
}
void ShaderManager::AddShaderFromFiles(const std::string& shaderName, const std::string& vertexShaderFileName, const std::string& fragmentShaderFileName, const std::string& ZIPFileName)
{
return shaderResourceMap[shaderStack.top()];
std::string vertexShader;
std::string fragmentShader;
if (!ZIPFileName.empty()){
std::vector<char> vertexShaderData;
std::vector<char> fragmentShaderData;
vertexShaderData = readFileFromZIP(vertexShaderFileName, ZIPFileName);
fragmentShaderData = readFileFromZIP(fragmentShaderFileName, ZIPFileName);
vertexShader = std::string(vertexShaderData.begin(), vertexShaderData.end());
fragmentShader = std::string(fragmentShaderData.begin(), fragmentShaderData.end());
}else{
vertexShader = readTextFile(vertexShaderFileName);
fragmentShader = readTextFile(fragmentShaderFileName);
}
///std::cout << "Shader: "<< vertexShader << std::endl;
shaderResourceMap[shaderName] = std::make_shared<ShaderResource>(vertexShader, fragmentShader);
}
void ShaderManager::PushShader(const std::string& shaderName)
{
if (shaderStack.size() >= CONST_MAX_SHADER_STACK_SIZE)
{
throw std::runtime_error("Shader stack overflow!");
}
if (shaderResourceMap.find(shaderName) == shaderResourceMap.end())
{
throw std::runtime_error("Shader does not exist!");
}
shaderStack.push(shaderName);
glUseProgram(shaderResourceMap[shaderName]->getShaderProgram());
}
}
void ShaderManager::PopShader()
{
if (shaderStack.size() == 0)
{
throw std::runtime_error("Shader stack underflow!");
}
ShaderSetter::ShaderSetter(ShaderManager &inShaderManager, const std::string &shaderName)
: shaderManager(inShaderManager) {
shaderManager.PushShader(shaderName);
}
shaderStack.pop();
if (shaderStack.size() == 0)
{
glUseProgram(0);
}
else
{
glUseProgram(shaderResourceMap[shaderStack.top()]->getShaderProgram());
}
}
std::shared_ptr<ShaderResource> ShaderManager::GetCurrentShader()
{
if (shaderStack.size() == 0)
{
throw std::runtime_error("Shader stack underflow!");
}
return shaderResourceMap[shaderStack.top()];
}
ShaderSetter::ShaderSetter(ShaderManager& inShaderManager, const std::string& shaderName)
: shaderManager(inShaderManager)
{
shaderManager.PushShader(shaderName);
}
ShaderSetter::~ShaderSetter()
{
shaderManager.PopShader();
}
ShaderSetter::~ShaderSetter() {
shaderManager.PopShader();
}
}
+2 -1
View File
@@ -1,5 +1,6 @@
#pragma once
#include "OpenGlExtensions.h"
#include "render/OpenGlExtensions.h"
#include "utils/Utils.h"
namespace ZL {
+53 -51
View File
@@ -20,20 +20,20 @@ namespace ZL
glBindTexture(GL_TEXTURE_2D, texID);
CheckGlError();
// Настройка фильтрации в зависимости от выбранного типа
// ��������� ���������� � ����������� �� ���������� ����
if (texData.mipmap == TextureDataStruct::GENERATE) {
// Используем трилинейную фильтрацию для устранения мерцания
// ���������� ����������� ���������� ��� ���������� ��������
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
else {
// Обычная линейная фильтрация (будет мерцать на удалении)
// ������� �������� ���������� (����� ������� �� ��������)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
CheckGlError();
// Загрузка данных базового уровня (Level 0)
// �������� ������ �������� ������ (Level 0)
GLint format = (texData.bitSize == TextureDataStruct::BS_24BIT) ? GL_RGB : GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, format,
@@ -43,7 +43,7 @@ namespace ZL
CheckGlError();
// Генерация мип-мапов, если это необходимо
// ��������� ���-�����, ���� ��� ����������
if (texData.mipmap == TextureDataStruct::GENERATE) {
glGenerateMipmap(GL_TEXTURE_2D);
CheckGlError();
@@ -52,7 +52,7 @@ namespace ZL
Texture::Texture(const std::array<TextureDataStruct, 6>& texDataArray)
{
// Проверка, что все грани имеют одинаковые размеры
// ��������, ��� ��� ����� ����� ���������� �������
width = texDataArray[0].width;
height = texDataArray[0].height;
@@ -73,33 +73,35 @@ namespace ZL
CheckGlError();
// Настройка параметров для Cubemap
// ��������� ���������� ��� Cubemap
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Используем GL_LINEAR для MIN_FILTER, так как мипмапы здесь не генерируются
// Если бы использовались мипмапы (e.g., GL_LINEAR_MIPMAP_LINEAR), нужно было бы вызвать glGenerateMipmap.
// ���������� GL_LINEAR ��� MIN_FILTER, ��� ��� ������� ����� �� ������������
// ���� �� �������������� ������� (e.g., GL_LINEAR_MIPMAP_LINEAR), ����� ���� �� ������� glGenerateMipmap.
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Обязательные параметры обертки для Cubemap
// ������������ ��������� ������� ��� 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 и вызывает ошибку.
// Ограничиваем его вызов только для настольных платформ.
// 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(); // Проверка после установки параметров
CheckGlError(); // �������� ����� ��������� ����������
// Загрузка данных для каждой из 6 граней
// GL_TEXTURE_CUBE_MAP_POSITIVE_X + i дает грани: +X (0), -X (1), +Y (2), -Y (3), +Z (4), -Z (5)
// �������� ������ ��� ������ �� 6 ������
// GL_TEXTURE_CUBE_MAP_POSITIVE_X + i ���� �����: +X (0), -X (1), +Y (2), -Y (3), +Z (4), -Z (5)
for (int i = 0; i < 6; ++i)
{
GLint internalFormat;
GLenum format;
// В WebGL 1.0/OpenGL ES 2.0 внутренний формат (internalFormat)
// должен строго соответствовать формату данных (format).
// � WebGL 1.0/OpenGL ES 2.0 ���������� ������ (internalFormat)
// ������ ������ ��������������� ������� ������ (format).
if (texDataArray[i].bitSize == TextureDataStruct::BS_24BIT)
{
internalFormat = GL_RGB; // internalFormat
@@ -112,20 +114,20 @@ namespace ZL
}
glTexImage2D(
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, // Целевая грань
0, // Уровень MIP-текстуры
internalFormat, // Внутренний формат (должен совпадать с форматом)
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, // ������� �����
0, // ������� MIP-��������
internalFormat, // ���������� ������ (������ ��������� � ��������)
static_cast<GLsizei>(width),
static_cast<GLsizei>(height),
0, // Граница (всегда 0)
format, // Формат исходных данных
GL_UNSIGNED_BYTE, // Тип данных
texDataArray[i].data.data() // Указатель на данные
0, // ������� (������ 0)
format, // ������ �������� ������
GL_UNSIGNED_BYTE, // ��� ������
texDataArray[i].data.data() // ��������� �� ������
);
CheckGlError();
}
// Снимаем привязку для чистоты
// ������� �������� ��� �������
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
@@ -253,48 +255,48 @@ 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' - сколько байт нужно прочитать
// ���������������� ������� ������ ��� 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, ������� �� ���������� � ������� 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.
// ������� ��������� ������, ��� ���� � �������.
// ������ ������ ����������� ������, �� ����� ������ ��������� ������� ��� ������� ������.
// � ���� ������ �� ������� ������ 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
// �������� ������ �� ������ ������� � ����� libpng
std::memcpy(out_ptr, data->data + data->offset, bytes_to_read);
// Обновляем смещение
// ��������� ��������
data->offset += bytes_to_read;
}
// Пользовательская функция предупреждений (по желанию, можно использовать nullptr)
// ���������������� ������� �������������� (�� �������, ����� ������������ 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)
// ���������������� ������� ������ (����������� ��� 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
longjmp(png_jmpbuf(png_ptr), 1);
}
@@ -302,7 +304,7 @@ 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);
@@ -316,18 +318,18 @@ namespace ZL
throw std::runtime_error("Could not create PNG info structure");
}
// === Установка пользовательских функций чтения и обработки ошибок ===
// 1. Установка обработчика ошибок и longjmp
// === ��������� ���������������� ������� ������ � ��������� ������ ===
// 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 можно передать указатель на свою структуру данных, если необходимо
// 2. ��������� ���������������� ������� ��� ��������� ������ � ��������������
// ������ nullptr � error_ptr � warning_ptr ����� �������� ��������� �� ���� ��������� ������, ���� ����������
png_set_error_fn(png, nullptr, user_error_fn, user_warning_fn);
// 3. Установка пользовательской функции чтения и передача ей нашей структуры png_data
// 3. ��������� ���������������� ������� ������ � �������� �� ����� ��������� png_data
png_set_read_fn(png, &png_data, user_read_data);
// ===================================================================
@@ -338,7 +340,7 @@ 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,7 +365,7 @@ namespace ZL
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));
@@ -422,7 +424,7 @@ namespace ZL
throw std::runtime_error("Could not read file data into memory");
}
// Вызываем новую функцию, которая работает с массивом байт
// �������� ����� �������, ������� �������� � �������� ����
return CreateTextureDataFromPng(fileArr);
}
+7 -7
View File
@@ -1,9 +1,9 @@
#pragma once
#include "OpenGlExtensions.h"
#include "render/OpenGlExtensions.h"
#include "utils/Utils.h"
#ifdef EMSCRIPTEN
#if defined EMSCRIPTEN || defined __ANDROID__
#define PNG_ENABLED
#endif
@@ -20,17 +20,17 @@ namespace ZL
BS_32BIT
};
// Íîâîå ïåðå÷èñëåíèå äëÿ óïðàâëåíèÿ ìèï-ìàïïèíãîì
// ����� ������������ ��� ���������� ���-���������
enum MipmapType {
NONE, // Áåç ìèï-ìàïîâ (GL_LINEAR)
GENERATE // Àâòîìàòè÷åñêàÿ ãåíåðàöèÿ (GL_LINEAR_MIPMAP_LINEAR)
NONE, // ��� ���-����� (GL_LINEAR)
GENERATE // �������������� ��������� (GL_LINEAR_MIPMAP_LINEAR)
};
BitSize bitSize;
/*#ifdef SIMPLIFIED
MipmapType mipmap = NONE; // Ïî óìîë÷àíèþ âêëþ÷åíî
MipmapType mipmap = NONE; // �� ��������� ��������
#else*/
MipmapType mipmap = GENERATE; // Ïî óìîë÷àíèþ âêëþ÷åíî
MipmapType mipmap = GENERATE; // �� ��������� ��������
//#endif
};
class Texture