WebGL + SDL + Emscript

Acabei migrando Mika para WebGL usando SDL 1 e Emscripten.

A seguir descreverei o que precisou ser alterado no código para que a compilação em JavaScript fosse concluída com sucesso.

  1. Use SDL 1 em vez de SDL 2. No momento existe uma porta SDL 2 para emscripten, mas achei mais apropriado usar o SDL 1 embutido no emscripten. O contexto não é inicializado na janela, mas usando SDL_SetVideoMode e o sinalizador SDL_OPENGL. O buffer é desenhado usando o comando SDL_GL_SwapBuffers()
  2. Devido à forma como o JavaScript faz loops – a renderização é colocada em uma função separada e sua chamada periódica é feita usando a função emscripten_set_main_loop
  3. A montagem também deve ser realizada com a chave “-s FULL_ES2=1
  4. Tive que abandonar a biblioteca assimp, carregando o modelo do sistema de arquivos e carregando a textura do disco. Todos os buffers necessários foram carregados na versão desktop e inseridos no arquivo c-header para montagem usando emscripten.

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

Artigos:
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

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

Só existe Miku

O resultado de trabalhar na biblioteca FSGL com OpenGL ES e código:

A seguir descreverei como tudo foi programado, vários problemas interessantes foram resolvidos.

Primeiro, inicializaremos o contexto OpenGL ES, conforme escrevi no post anterior. Além disso, consideraremos apenas a renderização e uma breve descrição do código.

A Matrix está observando você

Esta figura de Miku no vídeo consiste em triângulos. Para desenhar um triângulo no OpenGL, você precisa especificar três pontos com coordenadas x, y, z. em coordenadas 2D do contexto OpenGL.
Como precisamos desenhar uma figura contendo coordenadas 3D, precisamos usar uma matriz de projeção. Também precisamos girar, ampliar ou o que quisermos fazer com o modelo. Para tanto, é utilizada a matriz modelo. Não existe o conceito de câmera no OpenGL; na verdade, os objetos giram em torno de uma câmera estática; Para isso, é utilizada uma matriz de visualização.

Para simplificar a implementação do OpenGL ES – não contém dados de matriz. Você pode usar bibliotecas que adicionam funcionalidades ausentes, por exemplo, GLM.

Sombreadores

Para permitir que o desenvolvedor desenhe qualquer coisa, e de qualquer forma, o OpenGL ES deve implementar shaders de vértices e fragmentos. O vertex shader deve receber coordenadas de renderização como entrada, realizar transformações usando matrizes e passar as coordenadas para gl_Position. Fragmento ou pixel shader – já desenha cor/textura, aplica sobreposição, etc.

Eu escrevi shaders em GLSL. Na minha implementação atual, os shaders são integrados diretamente no código principal do aplicativo como strings C.

Buffers

O buffer de vértices contém as coordenadas dos vértices (vértices); este buffer também contém coordenadas para texturização e outros dados necessários para shaders. Depois de gerar o buffer de vértice, você precisa vincular o ponteiro aos dados do sombreador de vértice. Isso é feito com o comando glVertexAttribPointer, onde você precisa especificar o número de elementos, um ponteiro para o início dos dados e o tamanho do passo que será usado para percorrer o buffer. Na minha implementação, é feita a ligação de coordenadas de vértice e coordenadas de textura para o pixel shader. Porém, vale ressaltar que a transferência dos dados (coordenadas de textura) para o fragment shader é realizada através do vertex shader. Para conseguir isso, as coordenadas são declaradas usando variando.

Para que o OpenGL saiba em que ordem desenhar pontos para triângulos – você precisará de um buffer de índice (índice). O buffer de índice contém o número do vértice na matriz. Usando três desses índices, um triângulo é obtido.

Texturas

Primeiro você precisa carregar/gerar uma textura para OpenGL. Para isso utilizei SDL_LoadBMP, a textura é carregada a partir de um arquivo bmp. No entanto, é importante notar que apenas BMPs de 24 bits são adequados e as cores neles são armazenadas não na ordem RGB usual, mas em BGR. Ou seja, após o carregamento, é necessário substituir o canal vermelho por um azul.
As coordenadas de textura são especificadas no formato UV< /a>, ou seja, você só precisa transferir duas coordenadas. A saída da textura é feita no fragment shader. Para fazer isso, você precisa vincular a textura em um fragment shader.

Nada extra

Como, de acordo com nossas instruções, o OpenGL desenha de 3D a 2D – em seguida, implemente a profundidade e selecione triângulos invisíveis – você precisa usar seleção e um buffer de profundidade (Z-Buffer). Na minha implementação, consegui evitar a geração manual do buffer de profundidade usando dois comandos: glEnable(GL_DEPTH_TEST); e seleções glEnable(GL_CULL_FACE);
Certifique-se também de verificar se o plano próximo da matriz de projeção é maior que zero, porque verificar a profundidade com um plano próximo nulo não funcionará.

Renderização

Para preencher o buffer de vértice, buffer de índice com algo consciente, por exemplo o modelo Miku, você precisa carregar este modelo. Para isso usei a biblioteca assimp. Miku foi colocado em um arquivo no formato Wavefront OBJ, carregado usando assimp, e a conversão de dados de assimp para vértice e buffers de índice foi implementada.

A renderização ocorre em vários estágios:

  1. Gire Miku usando a rotação da matriz do modelo
  2. Limpando a tela e o buffer de profundidade
  3. Desenhar triângulos usando o comando glDrawElements.

Próxima etapa – Implementação de renderização em WebGL usando Emscripten.

Código fonte:
https://github.com/demensdeum/OpenGLES3-Experiments/tree/master/8-sdl-gles-obj-textured-assimp-miku
Modelo:
https://sketchfab.com/models/7310aaeb8370428e966bdcff414273e7

 

Projete

Tendo desenhado um bule vermelho em 3D, considero meu dever descrever brevemente como isso é feito.

O OpenGL moderno não desenha em 3D, apenas desenha triângulos, pontos, etc. em coordenadas de tela 2D.
Para produzir pelo menos algo usando OpenGL, você precisa fornecer um buffer de vértice, escrever um sombreador de vértice, adicionar todas as matrizes necessárias (projeção, modelo, visualização) ao sombreador de vértice,associar todos os dados de entrada com o shader, chame o método renderização em OpenGL. Parece simples?


Ok, o que é um buffer de vértice? Lista de coordenadas a serem desenhadas (x, y, z)
O vertex shader informa à GPU quais coordenadas desenhar.
O pixel shader informa o que desenhar (cor, textura, mesclagem, etc.)
As matrizes traduzem coordenadas 3D em coordenadas OpenGL 2D que podem ser renderizadas

Nos artigos a seguir fornecerei exemplos de código e resultados.

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: Criando um jogo no Android. Nós torcemos a terra. Rajawali

No princípio Deus criou o céu e a terra.

Este é o segundo vídeo em que estamos fazendo um jogo para Android. Vamos mover a terra!
Entre em contato comigo se tiver alguma dúvida ou se quiser acrescentar algo a este curso.
Vídeo baseado no artigo Configuração básica e configuração básica do Rajawali. Esfera (Maven):
http://www.clintonmedbery.com/basic-rajawali3d-tutorial-for-android/

Mecanismo Rajawali: https://github.com/Rajawali/Rajawali

Plano, comandos, links:
1. Instale VirtualBox Adiçõespara convidados

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

2. Adicionar biblioteca Rajawali ao projeto
Arquivobuild.gradle (Projeto: Caverna do Demônio)
Adicione mavenCentral() < /span>para a seção buildscript/repositories
Adicione
maven { url< /span> “https://oss.sonatype.org/content/repositories/snapshots/” } para a seção todos os projetos/repositórios

Arquivo build.gradle (Módulo: app)
Adicionar compilar ‘org.rajawali3d:rajawali:1.0.306-SNAPSHOT@aar& #8217; para a seção dependências

3. Crie uma classe Renderer, inicialize a cena, adicione uma esfera e gire!
Código fonte da classe Renderer.java:
https://github.com/clintonmedbery/RajawaliBasicProject/blob/master/app/src/main/java/com/clintonmedbery/rajawalibasicproject/Renderer.java

4. Adicione a classe Renderer a MainActivity
Código fonte MainActivity.java:
https://github.com/clintonmedbery/RajawaliBasicProject/blob/master/app/src/main/java/com/clintonmedbery/rajawalibasicproject/MainActivity.java

Textura do solo:
http://www.clintonmedbery.com/wp-content/uploads/2015/04/earthtruecolor_nasa_big.jpg

Tutorial: Criando um jogo no Android

‘Aprender é luz, e ignorância é escuridão

Demon’s Cave chegará ao Android em breve.
Comecei a gravar um curso sobre como portar um jogo para Android porque tem muita gente realmente interessada no processo de desenvolvimento.
Entre em contato comigo se tiver alguma dúvida ou se quiser acrescentar algo a este curso.
Você também pode adicionar legendas para outros idiomas: http://www.youtube.com/ timedtext_video?ref=share&v=rx7NYkAJB2I

Plano, comandos, links:
1. Instalando o VirtualBox https://www.virtualbox.org/wiki/Downloads
2. Instalando o Xubuntu http://xubuntu.org/getxubuntu/
3. Instalando o Oracle Java 7

sudo add-apt-repository ppa:webupd8team/javasudo apt-get atualizaçãosudo apt-get install oracle-java7-installer

4. Instalando bibliotecas de 32 bits

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

5. Instalando o Chromium

sudo apt-get install chromium-browser

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