Делаем OpenGL ES LiveWallpaper на Linderdaum Engine под Android

  • Tutorial
Привет Хабр!

Тема создания LiveWallpaper под Android уже хорошо обкатана: есть туториалы на чистой Java, есть туториалы на Java с OpenGL ES 1.0/2.0, есть… да чего только нет!

Сегодня мы посмотрим, как быстро сделать LiveWallpaper под Android на С++ используя Linderdaum Engine и GLSL.



Прежде всего нам понадобится настроенный Linderdaum Engine. Про то, как его настроить, был пост на Хабре: http://habrahabr.ru/post/121062/

В качестве источника вдохновения воспользуемся сайтом: http://www.chromeexperiments.com/webgl Там есть наборы image-space эффектов на WebGL, которые можно взять за отправную точку (шейдеры WebGL и OpenGL ES 2 совместимы).

Начнём вот с такого кода на С++, который и будет представлять всё наше приложение:

#include "Linderdaum.h"

sEnvironment* Env = NULL;

clPtr<clRenderState> Background = NULL;

void DrawOverlay(LEvent Event, const LEventArgs& Args)
{
	Env->Renderer->GetCanvas()->FullscreenRect( Background );
}

APPLICATION_ENTRY_POINT
{
	Env = new sEnvironment();
	Env->DeployDefaultEnvironment( NULL, "..\\..\\CommonMedia" );
	Env->Connect( L_EVENT_DRAWOVERLAY, Utils::Bind( &DrawOverlay ) );
	Background = Env->Resources->LoadShader( "Background.shader" );
	Env->RunApplication( DEFAULT_CONSOLE_AUTOEXEC );
	APPLICATION_EXIT_POINT( Env );
}

APPLICATION_SHUTDOWN
{
	Background = NULL;
}


Совсем не много, правда? Положем его в Test_LiveWallpaper.cpp и с С++ на этом действительно всё закончено.

Приступаем к шейдерам. Сначала напишем Background.shader:

Object("clRenderState")
{
   ShaderProgram "Plane.sp"
}


и Plane.sp:

/*VERTEX_PROGRAM*/
#include Layout.sp
in vec4 in_Vertex;
in vec4 in_TexCoord;
out vec2 Coord;
void main()
{
   gl_Position = in_ModelViewProjectionMatrix * in_Vertex;
   Coord = in_TexCoord.xy;
}

/*FRAGMENT_PROGRAM*/
in vec2 Coord;
uniform float ENGINE_TIME;
out vec4 out_FragColor;
// Plane deformations by Anton Platonov <platosha@gmail.com> twitter.com/platosha
const float TAU = 5.2832;
void main( void ) 
{
	vec2 position = Coord;
	vec2 p = -1.0 + 2.0 * position;
	float alpha = -ENGINE_TIME * 0.13;
	float sinA = sin(alpha), cosA = cos(alpha);
	p = vec2(cosA*p.x+sinA*p.y, -sinA*p.x+cosA*p.y);
	vec2 q = p;
	float zr = 1.0/length(q);
	float zp = 1.0/abs(q.y);
	float mc = sin(ENGINE_TIME*0.16)*.5 + .5;
	float z = mix(zr, zp, mc);
	float ur = 5.0*atan(q.x*sign(q.y), abs(q.y))/TAU + cos(0.2*z*TAU+ENGINE_TIME*1.37) * 1.2 * sin( ENGINE_TIME * 0.21 );
	float up = q.x*z;
	float u = mix(ur, up, mc);
	vec2 uv = vec2(u, (1.0+mc*2.0)*z);
	float mv = sin(ENGINE_TIME * 0.55);
	uv = mix(uv, q, 0.0);
	float color = 0.0;
	color = cos(uv.x*TAU) * cos(uv.y*TAU + ENGINE_TIME*7.7);
	color = pow(abs(cos(color*TAU)), 3.0);
	float color2 = 0.0;
	color2 = cos(uv.x*TAU*2.0);
	color2 -= 0.25;
	float shadow = 1.0/(z*z);
	vec3 rc = vec3(0.9, 1.0, 0.8)*color + vec3(0.3, 0.7, 0.6)*color2;
	rc *= shadow;
	out_FragColor = vec4( rc, 1.0 );
}


На этом этапе уже можно потестировать приложение под виндой. Просто добавив в проект и запустив. На экране будет вот такая картинка:

image

Для того, чтобы всё заработало на Android, придётся ещё немного поработать. Правда на Java придётся написать и того меньше. Test_LiveWallpaperService.java:

package com.linderdaum.engine.Test_LiveWallpaper;

import com.linderdaum.engine.LinderdaumEngineService;

public class Test_LiveWallpaperService extends LinderdaumEngineService
{
	@Override
	public LinderdaumEngineService.GLEngine onCreateEngine()
	{
		return new LinderdaumEngineService.GLEngine();
	}
}


Ещё понадобится манифест AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.linderdaum.engine.Test_LiveWallpaper"
      android:versionCode="1"
      android:versionName="1.0.0">
	<supports-screens
        android:smallScreens="false"
        android:normalScreens="true"
        android:largeScreens="true"
        android:anyDensity="true" />
    <uses-sdk android:minSdkVersion="7" />
    <uses-feature android:glEsVersion="0x00020000"/>
    <uses-feature android:name="android.software.live_wallpaper"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <application android:label="Test_LiveWallpaper"
                 android:icon="@drawable/icon"
                 android:installLocation="preferExternal"
                 android:debuggable="false">
		  <service android:name="com.linderdaum.engine.Test_LiveWallpaper.Test_LiveWallpaperService"
                 android:label="Test_LiveWallpaper"
                 android:permission="android.permission.BIND_WALLPAPER">
            <intent-filter>
                <action android:name="android.service.wallpaper.WallpaperService" />
            </intent-filter>
            <meta-data android:name="android.service.wallpaper" android:resource="@xml/wallpaper" />
        </service>

    </application>
</manifest> 


Всё! Остальные файлы есть в обычном проекте Linderdaum для Android. Запускаем ndk-build и ant copy-common-media debug. Можно устанавливать Test_LiveWallpaper-debug.apk на девайс — новые живые обои появятся в списке.

P.S. Такой шейдер весьма тяжёлый для мобильного GPU, поэтому батарейка будет поедаться достаточно быстро. Экспериментируйте!
Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 2

    0
    Конкуренты. :) Надо бы и мне выложить статью про 3D Wallpaper для Android.
      0
      Выкладывайте, конечно! Места всем хватит! Да и тема слишком обширная, чтобы вот так просто лоб в лоб столкнуться.

    Only users with full accounts can post comments. Log in, please.