Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Разработка игрового движка с нуля
GAMEINATOR forums > Общие разделы > Создание и модификация игр. Геймдев.
Страницы: 1, 2, 3
autistic
Цитата(saas @ 17.12.2017, 23:10) *
В X-Ray 1.8 используют вот такую библиотеку

Ну это что-то MyGui-подобное, оно рисуется непосредственно во вьюпорте движка. А хочется-то для отдельного приложения библиотеку промышленного качества и чтоб без лишнего геморроя smile.gif
autistic
В общем пока обойдусь средствами майи, позже вернусь к этому вопросу если возникнет такая необходимость. Думаю начать делать простую игрушку какую-нибудь, например шашки онлайн или 3Д-головоломку, или что-то в этом духе, как вам идея? Мб у кого-то есть подходящая идейка такой мега-игры, оригинальной, но простой, а главное чтоб приносила многоденег и сделала меня богатеньким буратиной? biggrin.gif

Тем временем котик оброс шерстью.
abramcumner
Цитата(refuse @ 23.12.2017, 16:37) *
шашки онлайн или 3Д-головоломку,

Только Сталкер2Д, ну или 2.5Д.
autistic
Цитата(abramcumner @ 23.12.2017, 18:47) *
Только Сталкер2Д, ну или 2.5Д.

Не, сталкер это слишком сложно, к тому же для 2Д нужно уметь хорошо и много рисовать. Было бы норм запилить какую-нибудь трехмерную игру с ограниченным набором моделек, но зато качественных и чтоб отрисовывались при помощи всяких продвинутых техник, вот я и подумал про головоломку или логическую игру.

+
2,5D я уже делал однажды, как-то не вкатило, душа просит как минимум Сталкер или Фаллаут, на худой конец ГТА5 smile.gif
dPlayer
Цитата(refuse @ 23.12.2017, 18:37) *
шашки онлайн

Шахматы с сталкерскими персонажами.
Diesel
Цитата(refuse @ 23.12.2017, 19:17) *
на худой конец ГТА5 smile.gif


Можно в азоте заморозиться, что бы увидеть результат? biggrin.gif
abramcumner
Цитата(refuse @ 23.12.2017, 17:17) *
Было бы норм запилить какую-нибудь трехмерную игру с ограниченным набором моделек, но зато качественных и чтоб отрисовывались при помощи всяких продвинутых техник, вот я и подумал про головоломку или логическую игру.

Настолка? Очень сталкерская по сути.
В зону, которая меняется после каждого выброса, входит группа сталкеров. Цель - вынести из зоны как можно больше артефактов. Их поджидают смертельные аномали, мутанты и таинственные жители зоны.
Молния в вакууме
Цитата(refuse @ 23.12.2017, 16:37) *
Тем временем котик оброс шерстью.

Хм. А я думал шерсть, которая вырастет на коте, будет шейдерной.
autistic
Цитата(saas @ 23.12.2017, 22:26) *
Хм. А я думал шерсть, которая вырастет на коте, будет шейдерной.

А она и есть шейдерная, только без карты нормалей и освещения, всему свое время. Движок не поддерживает FFP в принципе.

Текст программы
Код
#include <engine/model.h>
#include <engine/platform.h>
#include <engine/renderer.h>
#include <engine/texture.h>

std::string vertexShaderSrc =
"\n\
#version 330\n\
attribute vec4 vertexPosition;\n\
attribute vec4 vertexNormal;\n\
attribute vec4 vertexTangent;\n\
attribute vec4 vertexBinormal;\n\
attribute vec2 vertexTexcoords;\n\
uniform mat4 modelViewProj;\n\
out vec2 UV;\n\
void main()\n\
{\n\
  gl_Position = modelViewProj * vertexPosition;\n\
  UV = vertexTexcoords;\n\
}\n\
\0";

std::string fragmentShaderSrc =
"\n\
#version 330\n\
uniform sampler2D diffuseMap;\n\
in vec2 UV;\n\
out vec4 color;\n\
void main()\n\
{\n\
  color = texture(diffuseMap, UV);\n\
}\n\
\0";

int main()
{
    Engine::Platform *platform = Engine::GetPlatform();
    if (!platform->CreateMainWindow())
        return -1;

    Engine::Renderer *renderer = Engine::GetRenderer();
    Engine::ModelManager *modelManager = Engine::GetModelManager();
    Engine::ModelPtr teapot = modelManager->GetModel("teapot");
    Engine::HardwareBufferId hardwareBuffer = teapot->GetGraphicsShapes().at(0)->hardwareBufferId;

    Engine::Matrix4 rotation(Engine::Matrix3(M_PI * 0.25f, M_PI * 0.1f, 0));

    Engine::Matrix4 proj, view, model, modelViewProj;
    view.SetIdentity();
    proj.SetPerspective(1.3f, 1.78f, 0.1f, 100000.0f);
    model.SetTranslation(Engine::Vector3(-0.35, -0.3f, -1.5f));
    modelViewProj = rotation * model * proj;

    size_t size = vertexShaderSrc.size();
    const Engine::Byte *pVertShaderData = reinterpret_cast<const Engine::Byte*>(vertexShaderSrc.data());
    Engine::ByteVector vertexSrc(pVertShaderData, pVertShaderData + size);

    size = fragmentShaderSrc.size();
    const Engine::Byte *pFragShaderData = reinterpret_cast<const Engine::Byte*>(fragmentShaderSrc.data());
    Engine::ByteVector fragSrc(pFragShaderData, pFragShaderData + size);

    auto progId = renderer->CreateGpuProgram(Engine::STATIC_VERTEX, vertexSrc, fragSrc);
    renderer->BindGpuProgram(progId);

    renderer->SetGpuProgramConstant(progId, "modelViewProj", modelViewProj);

    Engine::TexturePtr cat = Engine::GetTextureManager()->GetTexture("cat_diff");
    renderer->BindHardwareTexture(cat->GetHardwareTexture(), Engine::DIFFUSE_MAP);

    platform->SetMainWindowSize(1280, 720, false);
    renderer->SetViewport(1280, 720);

    for (;;) {
        if (!platform->UpdateMainWindow()) {
            break;
        }

        renderer->BeginRenderFrame();
        renderer->DrawHardwareBuffer(hardwareBuffer);
        renderer->EndRenderFrame();
    }

    renderer->DestroyGpuProgram(progId);
}



Конвертер моделей
Код
#include <exception>
#include <fstream>
#include <iostream>
#include <set>
#include <vector>

#include <fbxsdk.h>

void ConvertMesh(FbxMesh *fbxMesh, std::vector<short> &indices, std::vector<float> &vertices)
{
    if (!fbxMesh->IsTriangleMesh()) {
        throw std::exception("The mesh should be a triangle mesh");
    }

    const FbxVector4 *controlPoints = fbxMesh->GetControlPoints();

    FbxStringList uvSets;
    fbxMesh->GetUVSetNames(uvSets);

    short k = 0;
    for (int i = 0; i < fbxMesh->GetPolygonCount(); ++i) {
        for (int j = 0; j < 3; ++j) {
            int index = fbxMesh->GetPolygonVertex(i, j);
            indices.push_back(k++);

            const FbxVector4 &controlPoint = controlPoints[index];
            vertices.push_back(controlPoint[0]);
            vertices.push_back(controlPoint[1]);
            vertices.push_back(controlPoint[2]);
            vertices.resize(vertices.size() + 9);

            bool unmapped;
            FbxVector2 textureUV;
            fbxMesh->GetPolygonVertexUV(i, j, uvSets[0], textureUV, unmapped);
            vertices.push_back(textureUV[0]);
            vertices.push_back(1-textureUV[1]);
        }
    }
}

void ConvertMesh(const std::vector<short> &indices, const std::vector<float> &vertices, FbxMesh *mesh)
{
    int count = vertices.size() / 14;
    mesh->InitControlPoints(count);

    const float *verts = vertices.data();
    FbxVector4 *points = mesh->GetControlPoints();

    for (int i = 0; i < count; ++i) {
        float x = *verts++;
        float y = *verts++;
        float z = *verts++;
        verts += 11;
        points[i] = FbxVector4(x, y, z);
    }

    count = indices.size();
    for (int i = 0; i < count; i +=3) {
        mesh->BeginPolygon();
        for (int j = 0; j < 3; ++j) {
            int index = indices[i + j];
            mesh->AddPolygon(index);
        }
        mesh->EndPolygon();
    }
}

void ExportMesh(const char *source, const char *target)
{
    std::vector<short> indices;
    std::vector<float> vertices;

    FbxManager *sdkManager = FbxManager::Create();
    FbxIOSettings *ios = FbxIOSettings::Create(sdkManager, IOSROOT);
    sdkManager->SetIOSettings(ios);

    FbxImporter* importer = FbxImporter::Create(sdkManager, "");
    if (!importer->Initialize(source, -1, sdkManager->GetIOSettings()))
        throw std::exception("Call to FbxImporter::Initialize() failed.");

    FbxScene* scene = FbxScene::Create(sdkManager, "ImportedScene");
    importer->Import(scene);
    importer->Destroy();

    std::ofstream file;
    file.open(target, std::ios::out | std::ios::binary);
    file.write("mdl\0", 4);

    short minor = 1, major = 0;
    file.write((char*)&major, 2);
    file.write((char*)&minor, 2);

    FbxNode *root = scene->GetRootNode();
    for (int i = 0; i < root->GetChildCount(); ++i) {
        std::vector<short> indices;
        std::vector<float> vertices;
        FbxNode *child = root->GetChild(i);
        ConvertMesh(child->GetMesh(), indices, vertices);

        int chunkId = 1, size = indices.size() * 2, fmt = 31;
        file.write((char*)&chunkId, 4);
        file.write((char*)&size, 4);
        file.write((const char*)indices.data(), indices.size() * 2);

        size = vertices.size() * 4;
        file.write((char*)&fmt, 4);
        file.write((char*)&size, 4);
        file.write((const char*)vertices.data(), vertices.size() * 4);
    }

    file.close();
}

void ImportMesh(const char *source, const char *target)
{
    std::vector<short> indices;
    std::vector<float> vertices;

    std::ifstream file;
    file.open(source, std::ios::in | std::ios::binary);
    if (!file)
        throw std::exception("Can't open source file");

    int size;
    file.seekg(12, SEEK_CUR);
    file.read((char*)&size, 4);

    indices.resize(size);
    file.read((char*)&indices[0], size);

    file.seekg(4, SEEK_CUR);
    file.read((char*)&size, 4);
    vertices.resize(size);
    file.read((char*)&vertices[0], size);

    FbxManager *sdkManager = FbxManager::Create();
    FbxIOSettings *ios = FbxIOSettings::Create(sdkManager, IOSROOT);
    sdkManager->SetIOSettings(ios);

    FbxExporter* exporter = FbxExporter::Create(sdkManager, "");
    if (!exporter->Initialize(source, -1, sdkManager->GetIOSettings()))
        throw std::exception("Call to FbxImporter::Initialize() failed.");

    FbxScene *scene = FbxScene::Create(sdkManager, "ExportedScene");
    FbxNode *root = scene->GetRootNode();

    FbxNode *child = FbxNode::Create(sdkManager, "teapot");
    FbxMesh *mesh = FbxMesh::Create(scene, "teapot");

    ConvertMesh(indices, vertices, mesh);

    child->SetNodeAttribute(mesh);
    root->AddChild(child);

    exporter->Export(scene);
    exporter->Destroy();
}

int main(int argc, char *argv[])
{
    try {
        if (argc != 3) {
            throw std::exception("Invalid parameters passed.");
        }

#if 0
        ExportMesh(argv[1], argv[2]);
#elif 0
        ImportMesh(argv[2], argv[1]);
#else
        ExportMesh(argv[1], argv[2]);
        ImportMesh(argv[2], argv[1]);
#endif
    }
    catch (const std::exception &error) {
        std::clog << error.what() << std::endl;
    }
}


Конвертер текстур в формат PVR можно скачать с оф. сайта PowerVR
Молния в вакууме
refuse, я про такую:
autistic
saas, ну она будет примерно такой шороховатой после применения bump mapping'а, нормал мапа в комплекте с котиком имеется, осталось шейдер допилить немного.
autistic
Ревьюшка: https://bitbucket.org/mkbkompas/engine/pull...-to-master/diff
Молния в вакууме
Зачем в texture.cpp #pragma once? smile.gif
autistic
saas, комментарии можно оставлять прямо на битбакете, для этого нужно залогиниться/зарегистрироваться под своим аккаунтом, открыть ревью и кликнуть мышкой на нужной строчке smile.gif
Молния в вакууме
refuse, ну ладно, написал ещё и на битбакете.
autistic
saas, спасибо, исправил. Там есть кнопочка approve, если замечаний нет больше нажми ее пожалуйста.
Молния в вакууме
refuse, у меня нет, но я не сильно в C++11 разбираюсь.
autistic
Цитата(saas @ 24.12.2017, 02:54) *
у меня нет

Погоди-ка, а кто тогда аппрув поставил? Я похоже в ревьюверы еще кого-то добавил с таким же ником как у тебя laugh.gif

Заехал пул реквест в мастер, спасибо всем smile.gif
Молния в вакууме
Цитата(refuse @ 24.12.2017, 01:02) *
Цитата(saas @ 24.12.2017, 02:54) *
у меня нет

Погоди-ка, а кто тогда аппрув поставил? Я похоже в ревьюверы еще кого-то добавил с таким же ником как у тебя laugh.gif

Заехал пул реквест в мастер, спасибо всем smile.gif

Замечаний нет. Кнопочку я нажал.
autistic
Нашел математику от товарищей из гугла, выглядит вроде неплохо, SIMD оптимизация под различные платформы, включая мобильные http://google.github.io/mathfu/
autistic
В общем посмотрел на эту библиотеку, и на некоторые другие, и решил что в проэкт из нескольких классов не стоит затаскивать зависимость с несколькими сабмодулями и кучей разных систем сборки. Пусть пока останется наивная реализация, ибо как сказал один известный человек: "Premature optimization is the root of all evil".

Сейчас обдумываю чем бы заняться дальше, пока на примете такие варианты:
1. Прикрутить логирование и обработку ошибок.
2. Сделать редактор материалов и углубиться в реализацию эффектов и свойств материала.
3. ...
Молния в вакууме
Всё, я его собрал biggrin.gif Первая неважная попытка освещения кота:


refuse, а у тебя какая версия винды? У меня и на Win7 и на XP была ошибка из за ReadFile.
https://msdn.microsoft.com/en-us/library/wi...v=vs.85%29.aspx
Цитата
lpNumberOfBytesRead [out, optional]

A pointer to the variable that receives the number of bytes read when using a synchronous hFile parameter. ReadFile sets this value to zero before doing any work or error checking. Use NULL for this parameter if this is an asynchronous operation to avoid potentially erroneous results.

This parameter can be NULL only when the lpOverlapped parameter is not NULL.


Алсо компилятор GCC ругается на векторы в анонимных союзах(в классах матриц).
autistic
Цитата(saas @ 24.12.2017, 19:56) *
refuse, а у тебя какая версия винды? У меня и на Win7 и на XP была ошибка из за ReadFile.

У меня win 10, ошибки не было, однако в документации по этому кейсу действительно все однозначно определено. Можешь пул реквест с исправлением создать в ветку develop?

Цитата(saas @ 24.12.2017, 19:56) *
компилятор GCC ругается на векторы в анонимных союзах

А вот тут надо уточнять что в стандарте С++11 по поводу анонимных структур говорится, у тебя какая версия GCC ?
Молния в вакууме
Цитата(refuse @ 24.12.2017, 18:22) *
У меня win 10, ошибки не было, однако в документации по этому кейсу действительно все однозначно определено. Можешь пул реквест с исправлением создать в ветку develop?

А что делать если количество считанных байт != size? Возвращать false?

Цитата(refuse @ 24.12.2017, 18:22) *
А вот тут надо уточнять что в стандарте С++11 по поводу анонимных структур говорится, у тебя какая версия GCC ?

Последняя из Mingw-w64, 7.2.0.
autistic
Цитата(saas @ 24.12.2017, 20:28) *
А что делать если количество считанных байт != size? Возвращать false?

По идее если функция вернула код успешного завершения операции, то все ок, так что если нам вернули буфер меньшего размера чем мы попросили я бы просто ворнинг в лог писал, а там пускай оно в другом месте валится с другой ошибкой. Но ты на свое усмотрение делай, ревью еще abramcumner будет смотреть.

Цитата(saas @ 24.12.2017, 20:28) *
Последний из Mingw-w64, 7.2.0.

Ok. Поправь пожалуйста и это тоже.
autistic
Цитата(saas @ 24.12.2017, 19:56) *
Первая неважная попытка освещения кота:

Выглядит так, словно bump mapping работает, однако из диффузной карты цвет не применился smile.gif
Молния в вакууме
refuse, диффузная карта на скриншоте не используется. Почему-то после BindHardwareTexture карта нормалей оказывалась в обоих семплерах.
autistic
saas, Прокомментировал. Добавь пожалуйста abramcumner'а в ревьюверы, пусть тоже посмотрит.
Цитата
To add a reviewer to an already existing pull request. Go to the pull request and press the Edit button at the top of the page. You can add reviewers and then press Update pull request to leave edit mode.

Молния в вакууме
refuse, добавил, на комментарий ответил.
autistic
saas, заапрувил, подождем abramcumner'a и можно мержить.
autistic
Есть апрув, можно мержить (кнопка Merge в правом верхрем углу)
Молния в вакууме
Так, подожди, здесь нужно reinterpret_cast вместо static_cast:
Код
const float *GetData() const { return static_cast<const float*>(&mat[0]); }
autistic
saas, поэтому лучше пул реквест сначала создавать в девелоп, чтоб в течение недели можно было подобные ошибки обнаружить, а в конце недели уже подмерживать в мастер wink.gif
Молния в вакууме
refuse, в следующий раз так и сделаю.

А где кнопка то?
autistic
Добавил прав, должна появиться кнопка
Молния в вакууме
refuse, появилась, замержил.
autistic
Цитата(saas @ 24.12.2017, 21:36) *
Почему-то после BindHardwareTexture карта нормалей оказывалась в обоих семплерах.

Это нормально. При создании текстуры она всегда привязывается к первому текстурному юниту и если ее потом привязать ко второму или третьему она останется привязанной и к первому, пока к нему явно не привяжут какую-нибудь другую текстуру. Так сделано в целях экономии ресурсов.

Код
Engine::TexturePtr diffuse = Engine::GetTextureManager()->GetTexture("diffuse");
Engine::TexturePtr normal = Engine::GetTextureManager()->GetTexture("normal");
renderer->BindHardwareTexture(diffuse->GetHardwareTexture(), Engine::DIFFUSE_MAP);
renderer->BindHardwareTexture(normal->GetHardwareTexture(), Engine::NORMAL_MAP);
// теперь к разным текстурным юнитам привязаны разные текстуры

ForserX
Миленько. Почему не гитхаб?
jamakasi
Цитата(refuse @ 23.12.2017, 16:37) *
например шашки онлайн или 3Д-головоломку, или что-то в этом духе, как вам идея?

Когда то давно году эдак в 2003 я долго залипал в одни шахматы. Были сделаны в 3д, фигуры анимированные модели, каждый ход проанимирован, ъзаются спецэффекты и анимации ударов, смерти и т.д. Были разные поля сражений и на каждом свои уникальные фигурки.
Что то типа такого только намного древнее и графоном уровня первой кваки:
Молния в вакууме
Цитата(refuse @ 25.12.2017, 07:14) *
Это нормально. При создании текстуры она всегда привязывается к первому текстурному юниту и если ее потом привязать ко второму или третьему она останется привязанной и к первому, пока к нему явно не привяжут какую-нибудь другую текстуру. Так сделано в целях экономии ресурсов.

Хм, действительно. Кот с бампом:
autistic
Цитата(ForserX @ 25.12.2017, 12:40) *
Почему не гитхаб?

К битбакету привык, изначально на гитхабе было больше ограничений для владельцев бесплатных аккаунтов.
ForserX
refuse, я ушел от бакета в сторону хаба. Пока ни разу не пожалел.
1001v
У них за приватный репозиторий надо платить по 7 долларов в месяц, это жирновато
ForserX
RedPxthon, зато кол-во юзеров в открытом больше.
Trollz0r
Цитата(ForserX @ 25.12.2017, 22:25) *
зато кол-во юзеров в открытом больше.
Да ты гонишь. На ведре нет ограничения на кол-во юзеров для НЕприватных репо.

Цитата(refuse @ 17.12.2017, 11:41) *
Народ! Тут возникла мысль, что экспортировать модельки из майи скриптом на С++ не очень удобно, а точнее совсем неудобно, и рано или поздно встанет вопрос о том, что неплохо бы иметь удобный инструмент который сможет не только импорт отекстуренных мешей делать, а позволит настраивать положение, материалы, анимации, физическую модель и т.д.
В общем задумался я тут какую технологию использовать для этого дела. Пока не сильно задумался, просто несколько очевидных решений которые первыми пришли в голову в порядке убывания приоритета:
1. Использовать C# в связке с С++. Для связывания использовать какой-нибудь сторонний биндинг, основанный на C++/CLI.
2. Использовать C# в связке с С++. Для связывания написать скрипт, скажем на питоне, который из интерфейсов С++ классов будет генерировать код для оболочки на C++/CLI.
3. Использовать С++ в связке с библиотекой Qt.
Хз что там с вашими сисярпами, но, по моим наблюдениям, очень многие используют кьюте (и колхозники, и автостоловцы). Редисты кладут рядом со своими бинарниками, и всё работает из коробки. Кстати, в Qt не идёт библа для работы с SVG?

Была ещё некая хрень под названием Tk, со своей киллинг фичей — отрывающимися окошками, как в майе (это адски удобно); уж не знаю, будет ли она применима в твоих целях. Ну да недолго проверить: http://cpptk.sourceforge.net/

Цитата(saas @ 23.12.2017, 19:01) *
refuse, я про такую:

Это же другая технология? у нас в майе такая шерсть генерируется по текстуре, но сама она — не текстура.
abramcumner
Цитата(STALKER2011y @ 26.12.2017, 15:49) *
Кстати, в Qt не идёт библа для работы с SVG?

http://doc.qt.io/qt-5/qtsvg-index.html

Кстати может действительно на основе Qt 3D делать? Чего в миллионный раз писать работу с файлами и велосипедить вектора с матрицами.
В 5.10 вон тоже небось можно кошку забацать. Они как раз прикрутили скелетную анимацию прикрутили smile.gif
Trollz0r
Ну вот, значит, и нормальное масштабирование иконок будет. (если их кто-то нарисует, и вообще они будут нужны)
Молния в вакууме
Цитата(STALKER2011y @ 26.12.2017, 15:49) *
Цитата(saas @ 23.12.2017, 19:01) *
refuse, я про такую:

Это же другая технология? у нас в майе такая шерсть генерируется по текстуре, но сама она — не текстура.

Не знаю, как работает шерсть в майе. Шерсть на картинке получается многократным рендерингом модели с текстурой с точками-волосами, постепенным увеличением модели и увеличением требуемой альфы для альфа теста. Проще говоря, модель становится больше, точка становится меньше, картинка накладывается на предыдущую, так много раз, в данном случае вроде 60, и получается то что получается.

Шейдеры для её создания не обязательны, кстати, можно и без них обойтись.
autistic
Цитата(STALKER2011y @ 26.12.2017, 17:49) *
Хз что там с вашими сисярпами, но, по моим наблюдениям, очень многие используют кьюте (и колхозники, и автостоловцы). Редисты кладут рядом со своими бинарниками, и всё работает из коробки.

Я в итоге тоже пришел к тому что это наименее затратно будет, opengl есть из коробки + сборка тем же cmake'ом. На самом деле я уже даже небольшой скелетик набросал, но пока не покажу.

Цитата(abramcumner @ 26.12.2017, 18:00) *
Кстати может действительно на основе Qt 3D делать? Чего в миллионный раз писать работу с файлами и велосипедить вектора с матрицами.

Сейчас уже не припомню где, то ли на гд.ру, то ли на почившем в бозе огре3д.ру, поднимали эту тему несколько лет. Был большооой холивар, но в итоге все сошлись на том, что эта библиотека изначально была спроектирована для разработки оконных приложений и в качестве движка не годится. Кстати шахматы на Qt 3D неплохо бы зашли.

Цитата(abramcumner @ 26.12.2017, 18:00) *
Они как раз прикрутили скелетную анимацию

Меня больше система материалов беспокоит, непонятно пока как ее организовать.
autistic
В общем по поводу материалов такая мысль имеется: разработать json-подобный скрипт (или прям в чистом виде json использовать) которым описывать используемые константы, а в шейдере дефайнами определять в компайл тайме какие константы будут использованы.
Что-то вроде такого:
Код
{
    Stage {
        DiffuseMap cat_diff.pvr
        NormalMap cat_norm.pvr
        ...
    }

    Stage {
        ...
    }

     ...
}


Такая система на первых порах позволит вообще без редактора обойтись, а в последствии поверх нее гуй легко можно будет прикрутить.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.