WebGL + SDL + Emscripten

Am Ende habe ich Mika mit SDL 1 und Emscripten auf WebGL portiert.

Als nächstes beschreibe ich, was im Code geändert werden musste, damit der Build in JavaScript erfolgreich abgeschlossen werden konnte.

  1. Verwenden Sie SDL 1 anstelle von SDL 2. Im Moment gibt es einen SDL 2-Port für Emscripten, aber ich fand es angemessener, den in Emscripten integrierten SDL 1 zu verwenden. Der Kontext wird nicht im Fenster initialisiert, sondern mithilfe von SDL_SetVideoMode und dem SDL_OPENGL-Flag. Der Puffer wird mit dem Befehl SDL_GL_SwapBuffers()
  2. gezeichnet

  3. Aufgrund der Art und Weise, wie JavaScript Schleifen durchführt – Das Rendering wird in einer separaten Funktion platziert und der regelmäßige Aufruf erfolgt über die Funktion emscripten_set_main_loop
  4. Die Montage muss ebenfalls mit dem Schlüssel “-s FULL_ES2=1
  5. erfolgen

  6. Ich musste die Assimp-Bibliothek aufgeben, das Modell aus dem Dateisystem laden und die Textur von der Festplatte laden. Alle notwendigen Puffer wurden auf die Desktop-Version geladen und zur Assemblierung mit emscripten.
  7. in die C-Header-Datei eingefügt

Code:
https://github.com/demensdeum/OpenGLES3-Experiments/tree/master/9-sdl-gles-obj-textured-assimp-miku-webgl/mikuWebGL

Artikel:
http://blog.scottlogic.com/2014/03/12/native-code-emscripten-webgl-simmer-gently.html
https://kripken.github.io/emscripten-site/docs/porting/multimedia_and_graphics/OpenGL-support.html

Modell:
https://sketchfab.com/models/7310aaeb8370428e966bdcff414273e7

Es gibt nur Miku

Das Ergebnis der Arbeit an der FSGL-Bibliothek mit OpenGL ES und Code:

Als nächstes werde ich beschreiben, wie alles programmiert wurde und verschiedene interessante Probleme gelöst wurden.

Zuerst initialisieren wir den OpenGL ES-Kontext, wie ich im vorherigen Beitrag geschrieben habe. Im Folgenden betrachten wir nur das Rendern und eine kurze Beschreibung des Codes.

Die Matrix beobachtet dich

Diese Figur von Miku im Video besteht aus Dreiecken. Um in OpenGL ein Dreieck zu zeichnen, müssen Sie drei Punkte mit den Koordinaten x, y, z angeben. in 2D-Koordinaten des OpenGL-Kontexts.
Da wir eine Figur zeichnen müssen, die 3D-Koordinaten enthält, müssen wir eine Projektionsmatrix verwenden. Wir müssen das Modell auch drehen, vergrößern oder was auch immer wir tun möchten – Hierzu wird die Modellmatrix verwendet. In OpenGL gibt es kein Konzept einer Kamera; tatsächlich drehen sich Objekte um eine statische Kamera. Hierzu wird eine Ansichtsmatrix verwendet.

Um die Implementierung von OpenGL ES zu vereinfachen – es enthält keine Matrixdaten. Sie können Bibliotheken verwenden, die fehlende Funktionalität hinzufügen, zum Beispiel GLM.

Shader

Um es dem Entwickler zu ermöglichen, alles und in irgendeiner Weise zu zeichnen, muss OpenGL ES Vertex- und Fragment-Shader implementieren. Der Vertex-Shader muss Rendering-Koordinaten als Eingabe erhalten, Transformationen mithilfe von Matrizen durchführen und die Koordinaten an gl_Position übergeben. Fragment- oder Pixel-Shader – Zeichnet bereits Farbe/Textur, wendet Überlagerung an usw.

Ich habe Shader in GLSL geschrieben. In meiner aktuellen Implementierung sind Shader als C-Strings

direkt in den Hauptanwendungscode integriert

Puffer

Der Vertex-Puffer enthält die Koordinaten der Scheitelpunkte (Vertices); dieser Puffer enthält auch Koordinaten für die Texturierung und andere für Shader notwendige Daten. Nachdem Sie den Vertex-Puffer generiert haben, müssen Sie den Zeiger an die Daten für den Vertex-Shader binden. Dies erfolgt mit dem Befehl glVertexAttribPointer, bei dem Sie die Anzahl der Elemente, einen Zeiger auf den Anfang der Daten und die Schrittgröße angeben müssen, die zum Durchlaufen des Puffers verwendet wird. In meiner Implementierung erfolgt die Bindung von Scheitelpunktkoordinaten und Texturkoordinaten für den Pixel-Shader. Es ist jedoch anzumerken, dass die Übertragung der Daten (Texturkoordinaten) an den Fragment-Shader über den Vertex-Shader erfolgt. Um dies zu erreichen, werden die Koordinaten mit Varying angegeben.

Damit OpenGL weiß, in welcher Reihenfolge Punkte für Dreiecke gezeichnet werden müssen – Sie benötigen einen Indexpuffer (Index). Der Indexpuffer enthält die Scheitelpunktnummer im Array. Unter Verwendung dreier solcher Indizes wird ein Dreieck erhalten.

Texturen

Zuerst müssen Sie eine Textur für OpenGL laden/generieren. Hierzu habe ich SDL_LoadBMP verwendet, die Textur wird aus einer BMP-Datei geladen. Es ist jedoch zu beachten, dass nur 24-Bit-BMPs geeignet sind und die Farben darin nicht in der üblichen RGB-Reihenfolge, sondern in BGR gespeichert werden. Das heißt, nach dem Laden müssen Sie den roten Kanal durch einen blauen ersetzen.
Texturkoordinaten werden im Format angegeben UV< /a>, das heißt, Sie müssen nur zwei Koordinaten übertragen. Die Texturausgabe erfolgt im Fragment-Shader. Dazu müssen Sie die Textur in einen Fragment-Shader binden.

Nichts Besonderes

Da OpenGL gemäß unseren Anweisungen 3D bis 2D zeichnet – dann um die Tiefe zu implementieren und unsichtbare Dreiecke auszuwählen – Sie müssen Culling und einen Tiefenpuffer (Z-Puffer) verwenden. In meiner Implementierung ist es mir gelungen, die manuelle Generierung des Tiefenpuffers mithilfe von zwei Befehlen zu vermeiden: glEnable(GL_DEPTH_TEST); und Auswahlen glEnable(GL_CULL_FACE);
Stellen Sie außerdem sicher, dass die Nahebene für die Projektionsmatrix größer als Null ist, denn Die Überprüfung der Tiefe mit einer Null-Nahebene funktioniert nicht.

Rendering

Um den Vertex-Puffer und den Index-Puffer mit etwas Bewusstem zu füllen, zum Beispiel dem Miku-Modell, müssen Sie dieses Modell laden. Hierfür habe ich die Bibliothek assimp verwendet. Miku wurde in eine Wavefront-OBJ-Formatdatei eingefügt, mit assimp geladen und die Datenkonvertierung von assimp in Vertex- und Indexpuffer wurde implementiert.

Das Rendern erfolgt in mehreren Schritten:

  1. Rotieren Sie Miku mithilfe der Modellmatrixrotation
  2. Bildschirm und Tiefenpuffer löschen
  3. Zeichnen von Dreiecken mit dem glDrawElements-Befehl.

Nächste Stufe – Implementierung des Renderings in WebGL mit Emscripten.

Quellcode:
https://github.com/demensdeum/OpenGLES3-Experiments/tree/master/8-sdl-gles-obj-textured-assimp-miku
Modell:
https://sketchfab.com/models/7310aaeb8370428e966bdcff414273e7

 

Projizieren Sie es

Nachdem ich eine rote Teekanne in 3D gezeichnet habe, betrachte ich es als meine Pflicht, kurz zu beschreiben, wie es gemacht wird.

Modernes OpenGL zeichnet nicht 3D, sondern nur Dreiecke, Punkte usw. in 2D-Bildschirmkoordinaten.
Um zumindest etwas mit OpenGL auszugeben, müssen Sie einen Vertex-Puffer bereitstellen, einen Vertex-Shader schreiben, alle erforderlichen Matrizen (Projektion, Modell, Ansicht) zum Vertex-Shader hinzufügen und alle Eingabedaten damit verknüpfen Rufen Sie für den Shader die Methode Rendering in OpenGL auf. Sieht es einfach aus?


Ok, was ist ein Vertex-Puffer? Liste der zu zeichnenden Koordinaten (x, y, z)
Der Vertex-Shader teilt der GPU mit, welche Koordinaten gezeichnet werden sollen.
Der Pixel-Shader sagt, was gezeichnet werden soll (Farbe, Textur, Mischung usw.)
Die Matrizen übersetzen 3D-Koordinaten in 2D-OpenGL-Koordinaten, die gerendert werden können

In den folgenden Artikeln werde ich Codebeispiele und Ergebnisse bereitstellen.

SDL2 – OpenGL ES

I love Panda3D game engine. But right now this engine is very hard to compile and debug on Microsoft Windows operation system. So as I said some time ago, I begin to develop my own graphics library. Right now it’s based on OpenGL ES and SDL2.
In this article I am going to tell how to initialize OpenGL ES context and how SDL2 helps in this task. We are going to show nothing.

King Nothing

First of all you need to install OpenGL ES3 – GLES 3 libraries. This operation is platform dependant, for Ubuntu Linux you can just type sudo apt-get install libgles2-mesa-dev. To work with OpenGL you need to initialize OpenGL context. There is many ways to do that, by using one of libraries – SDL2, GLFW, GLFM etc. Actually there is no one right way to initialize OpenGL context, but I chose SDL2 because it’s cross-platform solution, code will look same for Windows/*nix/HTML5/iOS/Android/etc.

To install sdl2 on Ubuntu use this command sudo apt-get install libsdl2-dev

So here is OpenGL context initialization code with SDL2:

    SDL_Window *window = SDL_CreateWindow(
            "SDL2 - OGLES",
            SDL_WINDOWPOS_UNDEFINED,
            SDL_WINDOWPOS_UNDEFINED,
            640,
            480,
            SDL_WINDOW_OPENGL
            );
	    

    SDL_GLContext glContext = SDL_GL_CreateContext(window);

After that, you can use any OpenGL calls in that context.

Here is example code for this article:
https://github.com/demensdeum/OpenGLES3-Experiments/tree/master/3sdl-gles
https://github.com/demensdeum/OpenGLES3-Experiments/blob/master/3sdl-gles/sdlgles.cpp

You can build and test it with command cmake . && make && ./SDLGles

Russian Quantum Hack and Number Generator

[Translation may be, some day]

Эта заметка увеличит длину вашего резюме на 5 см!

Без лишних слов о крутости квантовых компьютеров и всего такого, сегодня я покажу как сделать генератор чисел на реальном квантовом процессоре IBM.
Для этого мы будем использовать всего один кубит, фреймворк для разработки квантового ПО для python – ProjectQ, и 16 кубитовый процессор от IBM, онлайн доступ к которому открыт любому желающему по программе IBM Quantum Experience.

Установка ProjectQ

Для начала у вас должен быть Linux, Python и pip. Какие либо инструкции по установке этих базовых вещей приводить бесполезно, т.к. в любом случае инструкции устареют через неделю, поэтому просто найдите гайд по установке на официальном сайте. Далее устанавливаем ProjectQ, гайд по установке приведен в документации. На данный момент все свелось к установке пакета ProjectQ через pip, одной командой: python -m pip install –user projectq

Ставим кубит в суперпозицию

Создаем файл quantumNumberGenerator.py и берем пример генератора бинарного числа из документации ProjectQ, просто добавляем в него цикл на 32 шага, собираем бинарную строку и переводим в 32-битное число:

import projectq.setups.ibm
from projectq.ops import H, Measure
from projectq import MainEngine
from projectq.backends import IBMBackend

binaryString = ""

eng = MainEngine()

for i in range(1, 33):

 qubit = eng.allocate_qubit()

 H | qubit

 Measure | qubit

 eng.flush()

 binaryString = binaryString + str(int(qubit))

 print("Step " + str(i))

number = int(binaryString, 2)

print("\n--- Quantum 32-Bit Number Generator by demensdeum@gmail.com (2017) ---\n")
print("Binary: " + binaryString)
print("Number: " + str(number))
print("\n---")

Запускаем и получаем число из квантового симулятора с помощью команды python quantumNumberGenerator.py

Незнаю как вы, но я получил вывод и число 3974719468:

--- Quantum 32-Bit Number Generator by demensdeum@gmail.com (2017) ---

Binary: 11101100111010010110011111101100
Number: 3974719468

---

Хорошо, теперь мы запустим наш генератор на реальном квантовом процессоре IBM.

Хакаем IBM

Проходим регистрацию на сайте IBM Quantum Experience, подтверждаем email, в итоге должен остаться email и пароль для доступа.
Далее включаем айбиэмовский движок, меняем строку eng = MainEngine() -> eng = MainEngine(IBMBackend())
В теории после этого вы запускаете код снова и теперь он работает на реальном квантовом процессоре, используя один кубит. Однако после запуска вам придется 32 раза набрать свой email и пароль при каждой аллокации реального кубита. Обойти это можно прописав свой email и пароль прямо в библиотеки ProjectQ.

Заходим в папку где лежит фреймворк ProjectQ, ищем файл с помощью grep по строке IBM QE user (e-mail).
В итоге я исправил строки в файле projectq/backends/_ibm/_ibm_http_client.py:

email = input_fun('IBM QE user (e-mail) > ') -> email = "quantumPsycho@aport.ru"

password = getpass.getpass(prompt='IBM QE password > ') -> password = "ilovequbitsandicannotlie"

Напишите свой email и password со-но.

После этого IBM будет отправлять результаты работы с кубитом онлайн прямо в ваш скрипт, процесс генерации занимает около 20 секунд.

Возможно в дальнейшем я доберусь до работы квантового регистра, и возможно будет туториал, но это не обязательно.
Да прибудет с вами запутанность.

Статья на похожую тему:
Introducing the world’s first game for a quantum computer

Porting SDL C++ Game to HTML5 (Emscripten)

[Translation may be some day]

За последний год я написал простейший движок Flame Steel Engine и набор классов для игровой разработки Flame Steel Engine Game Toolkit. В данной статье я опишу как производил портирование движка и SDL игры Bad Robots на HTML 5, с использованием компилятора Emscripten.

Установка Hello World – Emscripten

Для начала нужно установить Emscripten. Простейшим вариантом оказалось использование скрипта emsdk для Linux. На официальном сайте данный тип установки называется как “Portable Emscripten SDK for Linux and OS X“. Внутри архива есть инструкция по установке с использованием скрипта. Я производил установку в директорию ~/emsdk/emsdk_portable.

После установки emscripten нужно проверить корректность работы компилятора, для этого создаем простейший hello_world.cpp и собираем его в hello_world.html с помощью команд:

source ~/emsdk/emsdk_portable/emsdk_env.sh
emcc hello_world.cpp -o hello_world.html

После компиляции в папке появится hello_world.html и вспомогательные файлы, откройте его в лучшем браузере Firefox, проверьте что все работает корректно.

Портирование кода игры

В javascript нежелательно вызывать бесконечный цикл – это приводит к зависанию браузера. На данный момент корректная стратегия – запрашивать один шаг цикла у браузера с помощью вызова window.requestAnimationFrame(callback)

В Emscripten данное обстоятельство решено с помощью вызова:

emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop);

Таким образом, нужно изменить код игры для корректного вызова метода emscripten. Для этого я сделал глобальный метод GLOBAL_fsegt_emscripten_gameLoop, в котором вызываю шаг цикла игрового контроллера. Главный игровой контроллер также вынесен в глобальную видимость:

#ifdef __EMSCRIPTEN__

void GLOBAL_fsegt_emscripten_gameLoop() {

GLOBAL_fsegt_emscripten_gameController->gameLoop();

}
#endif

Также для обработки специфических для Emscripten моментов, нужно использовать макрос __EMSCRIPTEN__.

Ресурсы и оптимизация

Emscripten поддерживает ресурсы и сборку с оптимизацией.

Для добавления изображений, музыки и прочего, положите все файлы в одну папку, например data. Далее в скрипт сборки добавьте:

emcc <файлы для сборки> –use-preload-plugins –preload-file data

Флаг –use-preload-plugins включает красивый прелоадер в углу экрана, –preload-file добавляет указанный ресурс в файл <имя проекта>.data
Код постоянно останавливался с ошибками доступа к ресурсам, пока я не включил оба этих флага. Также стоит заметить что для корректного доступа к ресурсам, желательно запускать игру на https (возможно и http) сервере, или отключить защиту локального доступа к файлам в вашем браузере.

Для включения оптимизации добавьте флаги:

-s TOTAL_MEMORY=67108864 -O3 -ffast-math

TOTAL_MEMORY – оперативная память в байтах(?) необходимая для корректной работы игры. Вы можете использовать флаг для динамического выделения памяти, но тогда часть оптимизаций работать не будет.

Производительность

Код javascript из C++ работает гораздо медленнее, даже со включенными оптимизациями. Поэтому если ваша цель это разработка для HTML5, то приготовьтесь к ручной оптимизации алгоритмов игры, паралелльному тестированию, также к написанию javascript кода вручную в особо узких местах. Для написания javascript кода используется макрос EM_ASM. Во время реализации рейкастера на emscripten, мне удалось добиться повышения fps с 2-4 до 30 с помощью прямого использования методов canvas.drawImage, в обход обертки SDL->Canvas, что почти приравнялось к написанию всего на javascript.

Поддержка SDL

На данный момент почти не работает SDL_TTF, поэтому отрисовка шрифта для Game Score в BadRobots очень проста. SDL_Image, SDL_Mixer работают корректно, в mixer я проверил только проигрывание музыки.

Исходный код Flame Steel Engine, Flame Steel Engine Game Toolkit, игры Bad Robots:

https://github.com/demensdeum/BadRobots
https://github.com/demensdeum/FlameSteelEngine
https://github.com/demensdeum/FlameSteelEngineGameToolkit

Статья на эту тему:

https://hacks.mozilla.org/2012/04/porting-me-my-shadow-to-the-web-c-to-javascriptcanvas-via-emscripten/

Tutorial: Ein Spiel auf Android erstellen. Wir verdrehen die Erde. Rajawali

Am Anfang schuf Gott Himmel und Erde.

Dies ist das zweite Video, in dem wir ein Spiel für Android entwickeln. Lasst uns die Erde bewegen!
Kontaktieren Sie mich, wenn Sie Fragen haben oder diesem Kurs etwas hinzufügen möchten.
Video basierend auf dem Artikel Rajawali Basic Setup & Kugel (Maven):
http://www.clintonmedbery.com/basic-rajawali3d-tutorial-for-android/

Rajawali-Engine: https://github.com/Rajawali/Rajawali

Plan, Befehle, Links:
1. Installieren Sie VirtualBox Guest Additions

sudo apt-get install dkmssudo apt-get install linux-headers-$(uname -r)

2. Rajawali-Bibliothek zum Projekt hinzufügen
Dateibuild.gradle (Projekt: Demon’s Cave)
Fügen Sie mavenCentral() < hinzu /span>zum Abschnitt buildscript/repositories
Fügen Sie
maven { url< hinzu /span> “https://oss.sonatype.org/content/repositories/snapshots/” } zum Abschnitt allprojects/repositories

Datei build.gradle (Modul: app)
Fügen Sie compile ‘org.rajawali3d:rajawali:1.0.306-SNAPSHOT@aar& hinzu #8217; zum Abschnitt Abhängigkeiten

3. Erstellen Sie eine Renderer-Klasse, initialisieren Sie die Szene, fügen Sie eine Kugel hinzu und drehen Sie!
Quellcode für die Renderer.java-Klasse:
https://github.com/clintonmedbery/RajawaliBasicProject/blob/master/app/src/main/java/com/clintonmedbery/rajawalibasicproject/Renderer.java

4. Fügen Sie die Klasse Renderer zu MainActivity
hinzuQuellcode MainActivity.java:
https://github.com/clintonmedbery/RajawaliBasicProject/blob/master/app/src/main/java/com/clintonmedbery/rajawalibasicproject/MainActivity.java

Bodentextur:
http://www.clintonmedbery.com/wp-content/uploads/2015/04/earthtruecolor_nasa_big.jpg

Tutorial: Ein Spiel auf Android erstellen

‘Lernen ist Licht, und Unwissenheit ist Dunkelheit

Demon’s Cave erscheint bald für Android.
Ich habe mit der Aufzeichnung eines Kurses über die Portierung eines Spiels auf Android begonnen, weil es viele Leute gibt, die sich wirklich für den Entwicklungsprozess interessieren.
Kontaktieren Sie mich, wenn Sie Fragen haben oder diesem Kurs etwas hinzufügen möchten.
Sie können auch Untertitel für andere Sprachen hinzufügen: http://www.youtube.com/ timedtext_video?ref=share&v=rx7NYkAJB2I

Plan, Befehle, Links:
1. VirtualBox installieren https://www.virtualbox.org/wiki/Downloads
2. Xubuntu installieren http://xubuntu.org/getxubuntu/
3. Installieren von Oracle Java 7

sudo add-apt-repository ppa:webupd8team/javaSudo apt-get updatesudo apt-get install oracle-java7-installer

4. 32-Bit-Bibliotheken installieren

sudo apt-get install lib32ncurses5 lib32stdc++6 zlib1g:i386

5. Chromium installieren

sudo apt-get install chromium-browser

6. Installieren von Android Studio http://developer.android.com/sdk/index.html< /p>