RenderScript este o limbă de scripting pe Android, care vă permite să scrieți redarea grafică de înaltă performanță și codul de calcul brut. Aflați mai multe despre RenderScript și scrieți prima aplicație grafică care utilizează RenderScript în acest tutorial.
API-urile RenderScript au fost introduse oficial în Android SDK în API Level 11 (aka Android 3.0, Honeycomb). RenderScript oferă un mijloc de scriere a codului critic de performanță pe care sistemul mai târziu îl compilează la codul nativ pentru procesorul pe care poate funcționa. Acesta ar putea fi CPU-ul dispozitivului, un procesor multi-core sau chiar GPU-ul. Ceea ce rulează în cele din urmă depinde de mulți factori care nu sunt ușor disponibili dezvoltatorului, dar depinde și de ce arhitectură suportă compilatorul platformei interne.
Acest tutorial vă va face să începeți cu un script simplu de redare pe care îl numim "Falling Snow". Este un sistem de particule în care fiecare fulg de zăpadă este reprezentat de un punct care cade, accelerând pe ecran. Vânturile și alte aleatoare produc un efect turbionar ușor.
RenderScript se bazează pe limbajul de programare C. Dacă nu sunteți familiarizat cu C, vă recomandăm să vă familiarizați mai întâi cu acesta înainte de a încerca să utilizați RenderScript. Deși RenderScript nu este OpenGL și nici nu este necesar să îl utilizați pentru redarea grafică, conceptele pentru utilizarea acestuia sunt similare conceptelor OpenGL. Prin urmare, familiarizarea cu terminologia grafice OpenGL și 3D vă va ajuta.
Codul open source pentru acest tutorial este disponibil pentru descărcare. Vă recomandăm să o utilizați pentru a vă urma. Codurile din acest tutorial nu includ întregul conținut al fiecărui fișier.
Să începem cu pasul cel mai detaliat și să lucrăm la utilizarea scriptului dintr-o activitate tipică Android.
Creați un nou fișier de proiect numit snow.rs în arborele dvs. src, sub pachetul în care veți lucra. În partea de sus, definiți versiunea RenderScript cu care lucrați:
versiunea #pragma (1)
Apoi, setați pachetul Java căruia îi aparține acest script, de exemplu:
#pragma rs java_package_name (com.mamlambo.fallingsnow)
Vom utiliza câteva funcții din API-ul grafice RenderScript, astfel încât să includeți acel antet:
#include "rs_graphics.rsh"
Acum, definiți două funcții, root () și init ():
int rădăcină () // TBD void init () // TBD
Funcția root () va fi punctul de intrare al acestui script. Valoarea returnată definește dacă scriptul rulează o dată (return 0) sau la intervale de N-milisecunde (return N). Dacă hardware-ul nu poate ține pasul cu frecvența solicitată, atunci root () rulează cât mai des posibil.
Funcția init () se numește o dată când scriptul se încarcă și este un loc bun pentru a inițializa variabilele și alți parametri de stare.
Creați o variabilă de ochiuri care va fi inițializată pe partea Android și creați un simplu struct pentru a ține informații despre fiecare fulg de zăpadă. În timp ce sunteți la el, creați câteva variabile pentru a menține valorile vântului și gravitației.
rs_mesh snowMesh; typedef struct __attribute __ ((împachetat, aliniat (4))) Snow float2 velocity; poziția float2; culoarea uchar4; Snow_t; Snow_t * zăpadă; float2 vânt; float2 grav;
Inițializați vântul și gravitatea în funcția init ():
grav.x = 0; grav.y = 18; wind.x = rsRand (50) +20; wind.y = rsRand (4) - 2;
Inițializați zăpada în propria sa funcție:
void initSnow () const float w = rsgGetWidth (); const float h = rsgGetHeight (); int snowCount = rsAllocationGetDimX (rsGetAlocație (zăpadă)); Snow_t * pSnow = zăpadă; pentru (int i = 0; i < snowCount; i++) pSnow->loc.x = rsRand (w); pSnow-> position.y = rsRand (h); pSnow-> viteza.y = rsRand (60); pSnow-> viteza.x = rsRand (100); pSnow-> viteza.x - = 50; uchar4 c = rsPackColorTo8888 (255, 255, 255); pSnow-> culoare = c; pSnow ++;
Înainte de a merge mai departe, hai să vorbim despre funcția initSnow (). Pentru a începe, lățimea și înălțimea zonei de desen sunt recuperate. Apoi scriptul trebuie să știe câte structuri de fulgi de zăpadă vom crea. Aceasta face acest lucru prin obținerea dimensiunilor alocării, care este indicată de indicatorul de zăpadă. Dar unde este indicatorul inițializat și care este alocarea? Indicatorul este inițializat din codul Android. O alocare este unul dintre mijloacele prin care memoria este gestionată de codul Android, dar este utilizată de script. Detaliile interne nu sunt importante în acest moment. Pentru scopurile noastre, putem să ne gândim la aceasta ca la o serie de obiecte de structură Snow_t.
Bucla iterează peste fiecare structură și stabilește câteva valori aleatorii, astfel încât scena de pornire pare naturală.
Acum, să implementăm o funcție rădăcină simplă () care atrage scena fără animație. Vom folosi acest lucru pentru a obține restul sistemului în loc:
int rădăcină () rsgClearColor (0.0f, 0.0f, 0.0f, 0.0f); rsgDrawMesh (snowMesh); retur 0;
Când salvați fișierul de proiect script în Eclipse, constructorii vor crea automat un fișier numit snow.bc în directorul / res / raw. Acest fișier generat automat nu trebuie să fie verificat în controlul sursă și nici să fie modificat. În plus, unele fișiere Java sunt create în directorul / gen. Acestea sunt fișierele de interfață utilizate pentru apelarea scriptului de pe Android.
Acum, că script-ul este creat, trebuie să îl inițializăm pentru a fi utilizat din clasele Android. Pentru a face acest lucru, am creat o clasă Java de ajutor, numită SnowRS. În acesta, alocăm memoria pentru fulgii de zăpadă, inițializăm scenariul și le alocăm alocarea ochiului și a fulgii de zăpadă. Această clasă utilizează, de asemenea, un obiect RenderScriptGL. Acest obiect este creat în următorul pas ca parte a clasei de vizualizare pe care o vom face.
clasa publică SnowRS public static final int SNOW_FLAKES = 4000; privat ScriptC_snow mScript; protejate int mwidth; protejate int mHeight; mPreview boolean protejat; resurse protejate mResurse; RenderScriptGL mRS protejat; publicul SnowRS (lățime int, int înălțime) mWidth = width; mHeight = înălțime; void stop public () mRS.bindRootScript (null); void public public () mRS.bindRootScript (mScript); public void init (RenderScriptGL rs, resurse res, boolean isPreview) mRS = rs; mResources = res; mPreview = isPreview; mScript = (ScriptC_snow) createScript (); public RenderScriptGL getRS () retur mRS; resurse publice getResources () return mResources; public ScriptC createScript () ScriptField_Snow snow = nou ScriptField_Snow (mRS, SNOW_FLAKES); Mesh.AllocationBuilder smb = Mesh.AllocationBuilder nou (mRS); smb.addVertexAllocation (snow.getAllocation ()); smb.addIndexSetType (Mesh.Primitive.POINT); Mesaj sm = smb.create (); Script ScriptC_snow; script = nou ScriptC_snow (mRS, getResources (), R.raw.snow); script.set_snowMesh (sm); script.bind_snow (zăpadă); script.invoke_initSnow (); scriptul de returnare;
În special, să examinăm metoda createScript (). Prima secțiune creează matricea de structuri cu 4.000 de intrări (SNOW_FLAKES = 4000). Se folosește apoi pentru a crea un obiect din rețea, utilizat pentru redare. Construcția de redare este setată la POINT, astfel încât fiecare fulg de zăpadă va apărea ca un pixel pe ecran.
Apoi, inițializăm scriptul însuși, folosind intrarea de resurse prime creată de constructorul Eclipse. Apoi atribuim plasa și alocarea matricei în scenariu prin apelurile set_snowMesh () și respectiv bind_snow (). În final, inițializăm zăpada cu un apel la funcția initSnow () pe care am creat-o mai devreme, sunând la invoke_initSnow ().
Scriptul nu începe să ruleze în acest moment, dar a fost apelată funcția init (). Pentru a lansa scriptul, apelați bindRootScript () pe obiectul script, așa cum se vede în metoda start ().
SDK-ul Android oferă doar obiectul de care avem nevoie pentru ieșirea din clasa RenderScript: RSSurfaceView. Implementați o clasă numită FallingSnowView care extinde această clasă, după cum urmează:
clasa publică FallingSnowView extinde RSSurfaceView private RenderScriptGL mRSGL; private SnowRS mRender; public FallingSnowView (Context context) super (context); @Overide public void surfaceChanged (SuprafațăHolder titular, int format, int w, int h) super.surfaceChanged (titular, format, w, h); dacă (mRSGL == null) RenderScriptGL.SurfaceConfig sc = noua RenderScriptGL.SurfaceConfig (); mRSGL = createRenderScriptGL (sc); mRSGL.setSurface (suport, w, h); mRender = SnowRS noi (w, h); mRender.init (mRSGL, getResources (), false); mRender.start (); @Override protejat void onDetachedFromWindow () if (mRSGL! = Null) mRSGL = null; destroyRenderScriptGL ();
Metoda surfaceChanged () creează un obiect RenderScriptGL din SurfaceHolder trecut, după cum este necesar. Apoi, obiectul SnowRS este creat și începe redarea.
Totul este în vigoare pentru a utiliza clasa FallingSnowView în cadrul unei clase de activitate. Metoda onCreate () a clasei dvs. de activitate ar putea fi la fel de simplă:
public void onCreate (bundle savedInstanceState) super.onCreate (savedInstanceState); snowView = nou FallingSnowView (aceasta); setContentView (snowView);
Dar asteapta! Aceasta este doar o imagine statică. Nu prea interesant, nu-i așa? Să revenim la fișierul snow.rs și să editați funcția root (). Pentru o simulare simplă în stil pseudo-fizică, veți dori să repetați fiecare fulg de zăpadă și să aplicați viteza actuală și vântul în poziția sa. Apoi reglați viteza bazată pe accelerația gravitațională. În cele din urmă, verificați dacă vreun zăpadă a căzut de pe fundul ecranului. Nivelul de complexitate și eficiența codării aici vor avea un impact asupra tipului de rată de cadre pe care o veți obține în cele din urmă. Am încercat să o păstrăm pur și simplu pentru acest tutorial.
Iată ce am făcut:
int root () // Clear pentru culoarea de fundal rsgClearColor (0.0f, 0.0f, 0.0f, 0.0f); // timpul de la ultima actualizare float dt = min (rsGetDt (), 0.1f); // dimensiunea floatului w = rsgGetWidth (); flotați h = rsgGetHeight (); int snowCount = rsAllocationGetDimX (rsGetAlocație (zăpadă)); Snow_t * pSnow = zăpadă; pentru (int i = 0; i < snowCount; i++) pSnow->poziția.x + = ((pSnow-> viteza.x + wind.x) * dt); pSnow-> position.y + = ((pSnow-> viteza.y + wind.y) * dt); dacă (pSnow-> position.y> h) pSnow-> position.y = 0; pSnow-> position.x = rsRand (w); pSnow-> viteza.y = rsRand (60); pSnow-> viteza.x + = (grav.x) * dt; pSnow-> viteza.y + = (grav.y) * dt; pSnow ++; rsgDrawMesh (snowMesh); dacă (rsRand (32) == 1) wind.x = 0-wind.x; retur 30;
Și aici este în mișcare:
Acest tutorial tocmai a zgâriat suprafața a ceea ce poate face RenderScript (Haha, obțineți-o? Suprafață?). Puteți utiliza un script de calcul RenderScript pentru a aplica efecte grafice bitmapurilor. Aveți posibilitatea să adăugați shadere pentru a pârghia hardware-ul grafic al dispozitivului pentru a desena scena în mod diferit. Puteți configura transformări pentru a desena un spațiu 3D. Puteți configura texturile pentru a desena. Mai puteți face multe lucruri cu RenderScript.
În timp ce RenderScript este mai limitator decât utilizarea OpenGL ES în zona de redare 3D, adăugarea unui RenderScript numai pentru calcul adaugă câteva funcții de întâmpinare. Desenarea unei scene 3D rapide folosind RenderScript poate fi mai eficientă, cu codificare decât utilizarea OpenGL. Folosirea RenderScript pentru calculul greu sau manipularea imaginilor poate fi mai rapidă pentru a se dezvolta și a funcționa mai bine decât soluțiile NDK similare (datorită distribuției automate între nucleele hardware). Spre deosebire de dezvoltarea cu Android NDK, nu trebuie să vă faceți griji cu privire la arhitectura hardware de bază.
Dezavantajul principal al RenderScript este lipsa portabilității codului existent. Dacă aveți deja cod OpenGL sau funcții de calcul în C pe care doriți să le folosiți în aplicațiile Android, este posibil să doriți doar să vă lipiți de aplicația Android NDK.
Acest tutorial vă oferă un gust de utilizare a RenderScript cu aplicațiile Android. Ați învățat elementele de bază ale scrierii și inițializării unui script și redarea pe ecran. Toate acestea s-au făcut în contextul unui sistem simplu de particule care simulează fulgi de zăpadă de dimensiuni reduse.
Spuneți-ne ce aplicații RenderScript se dezvoltă în comentariile dvs.!
Dezvoltatorii mobili Lauren Darcey și Shane Conder au coautorizat mai multe cărți despre dezvoltarea Android: o carte de programare în profunzime intitulată Dezvoltarea aplicațiilor fără fir Android și Sams Învățați-vă dezvoltarea de aplicații Android în 24 de ore. Când nu scriu, își petrec timpul dezvoltând software-ul mobil la compania lor și oferind servicii de consultanță. Acestea pot fi obținute prin e-mail la androidwirelessdev@[email protected], prin intermediul blogului lor la androidbook.blogspot.com, și pe Twitter @ androidwireless.