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

от автора

Привет Хабр!

Тема создания 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, поэтому батарейка будет поедаться достаточно быстро. Экспериментируйте!

ссылка на оригинал статьи http://habrahabr.ru/post/161775/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *