åæã³ã³ã»ãã
ãã€ã€ã«ã®ã¢ã€ãã¢ã¯ããã®äœåã«è§ŠçºãããŸããïŒããŒãã«ã«ããïŒïŒ
ãããªã¯ã¯ãŒã«ã«èŠããäžèŠè€éã«èŠããŸããã ãã ãããããªãšåãã·ãŒã³ãäœæã§ããªãæè¡çãªå¶éãããã€ãèŠã€ãããŸããã äºãã«æ£ããéãªãåãç·ïŒã¯ã€ã€ãã¬ãŒã ïŒããæ°åãäœæããã®ã¯ããã»ã©ç°¡åã§ã¯ãããŸããã èŠããã«ãããã«ã¯å€æ°ã®æç»åŒã³åºããå¿ èŠã«ãªããéåžžã«éãããã¯ããã¯ããŒããŠã§ã¢ã§ã¯éåžžã«å€ãã®æç»åŒã³åºãã«å¯Ÿå¿ã§ããŸããã ããã§ãå¥ã®ã¢ã€ãã¢ã«ç§»ããŸãããå€ãã³ã³ãã¥ãŒã¿ãŒã®ãã¯ã»ã«ãã©ã³ãã®æ°åã«æ·±ã¿ãå ããŸãã
深床ã³ã³ããŒãã³ããªãã®OpenGL ESèšå®
Android Wear APIã®Gles2WatchFaceServiceã¯ã©ã¹ã¯ããã€ã€ã«ã®å®å šãª3次å ã·ãŒã³ãäœæããããã«å¿ èŠãªãã¹ãŠã®æ©èœãžã®ã¢ã¯ã»ã¹ãæäŸããŸããã ããã«çŽé¢ããäž»ãªåé¡ã¯ãå¿ èŠãªOpenGL ESæ§æãéžæã§ããªãããšã§ããã å®éããã®ã¯ã©ã¹ã¯EGLãžã®ã¢ã¯ã»ã¹ããŸã£ããæäŸããŸããã ãµã³ãã«APIãããTiltããã€ã€ã«ãå®è¡ããã ãã§ååã§ãããEGLãæ§æããæè»æ§ã¯ãããŸããã ãã®äŸã«ã¯ãéè€ãããžãªã¡ããªãå«ãŸããŠããªãããã深床ãããã¡ã¯å¿ èŠãããŸããã Gles2WatchFaceService㯠ã EGL_DEPTH_SIZEã䜿çšããã«æ§æãéžæããã ãã§ãAPIã§å€æŽããããšã¯ã§ããŸããã
ãã®ãããªé倧ãªå¶éãçºèŠãããããããœãŒã¹ã³ãŒããéã³ã³ãã€ã«ãããã©ãã¯ãžã£ãã¯ãšæ£ããEGLæ§æã䜿çšããŠGles2WatchFaceServiceã®ç¬èªã®å®è£ ãäœæããããšã決å®ãããŸããã
ãŸããã©ã€ãå£çŽãšãã€ã€ã«ã®éåžžã«æåãªéçºè ã§ããKittehface Softwareã¯ãMoto360ã¯å®å šã«æ£ãã16ãããEGLæ§æã§ã¯åäœããªãããšãããã°ã§å ±åããŸãã ã ãããã£ãŠããã¹ãŠã®ããã€ã¹ã§ãã¢ããªã±ãŒã·ã§ã³ã¯åžžã«32ãããã«ã©ãŒã䜿çšããŸãã ãã®ããšã«ã€ããŠç§ãã¡ãä»ã®éçºè ã«èŠåããŠãããKittehface Softwareã«æè¬ããŸããMoto360ã§ã¯ã©ãã·ã¥ã®åå ãèŠã€ããã«ã¯æ°æ¥ãããå¯èœæ§ãããããã®æç¹ã§ã¯æèšèªäœããããŸããã§ããã
ãã³ã³ãã€ã«ãããã¯ã©ã¹Gles2WatchFaceServiceã®å®å šãªã³ãŒãã¯æäŸããŸãããããã¯ãæ°ããAPIã®ãªãªãŒã¹ã§å€æŽãããããã§ãã 以äžã¯ãéã³ã³ãã€ã«ãããGles2WatchFaceServiceã«å ããå€æŽã§ã ã
1.æ·±ãã³ã³ããŒãã³ãã䜿çšããŠé©åãªæ§æã®æ€çŽ¢ãæŽæ°ããŸãã
private static final int [] EGL_CONFIG_ATTRIB_LIST = new int [] { EGL14.EGL_RENDERABLE_TYPEã4 EGL14.EGL_RED_SIZEã8 EGL14.EGL_GREEN_SIZEã8 EGL14.EGL_BLUE_SIZEã8 EGL14.EGL_ALPHA_SIZEã8 EGL14.EGL_DEPTH_SIZEã16ã//ããã§ã¯ååã§ã¯ãããŸããã§ãã EGL14.EGL_NONE};
2. mInsetBottomããã³mInsetLeftå€æ°ãåã¯ã©ã¹ããå©çšã§ããããã«ããŸãã ãã¥ãŒããŒããæ£ããæŽæ°ããããã«äœ¿çšãããŸãã ããšãã°ãããããä¿è·ããŸãã
protected int mInsetBottom = 0; protected int mInsetLeft = 0;
glViewportïŒïŒ
å ¬åŒããã¥ã¡ã³ãã«ã¯ã onApplyWindowInsetsïŒïŒã¡ãœããã䜿çšããŠç°ãªãç»é¢ãæã€ããã€ã¹ãæäœããæ¹æ³ã«ã€ããŠã®éåžžã«ä¹ããæŒ ç¶ãšãããªãã¡ã¬ã³ã¹ããããŸãã ãã®æ¹æ³ã¯ãäžç«¯ãããªãã³ã°ãããç»é¢ã«é©å¿ããããã«äœ¿çšããå¿ èŠããããšè¿°ã¹ãŠããŸãã ããã¯ãMoto 360ãªã©ã®ããã€ã¹ã®å€èŠ³ã調æŽããããã«å¿ èŠã§ãã
Moto360ãæå ã«ãªãå Žåããã®æ¹æ³ãã©ã®ããã«äœ¿çšããããæ確ã§ã¯ãªãã£ãããããã®æèšã§ã¢ããªã±ãŒã·ã§ã³ãèµ·åããããšããæåã®è©Šã¿ã§ã¯ãç»é¢ã®åãåãããéšåã®ãµã€ãºã ããã¥ãŒãã·ããããŸããã ãã®åé¡ããã£ã«ããã€ã€ã«ã®äŸã«ãªãããšã¯ããªãå¥åŠã§ãã-ããã¯æ£ããäžå€®ã«çœ®ãããŠããŸããã ãããç解ããããã«ã Gles2WatchFaceServiceãµãŒãã¹ã®éã³ã³ãã€ã«ãããã³ãŒããããäžåºŠèŠãå¿ èŠããããŸããã çç±ã¯glViewportïŒïŒã®äœ¿çšã§ããã ãã«ãŒã å¹æãå®è£ ããããã«ããã¯ã¹ãã£ã§ã¬ã³ããªã³ã°ã䜿çšãã glViewportïŒïŒãšåŒã°ããã¬ã³ããªã³ã°ããã¯ã¹ãã£ãŸãã¯ç»é¢ã«åãæ¿ããŸããã ç»åã®ã·ãããé¿ããããã«ã glViewportïŒïŒãæå®ããéã«ãåãåãããç»é¢ã®äžã®ã€ã³ãã³ãã®å€ãèæ ®ããå¿ èŠããããŸãã
éåžžã¢ãŒãããã³åšå²ã¢ãŒãã§ã®éæ床
äžæãªçç±ã«ãããã¹ã¯ãªãŒã³ã»ãŒããŒã¢ãŒãïŒã¢ã³ããšã³ãã¢ãŒãïŒã§äžéæãªéç¥ã«ãŒãïŒããŒã¯ã«ãŒãïŒãæç»ããããšã¯ã§ããŸããã éåžžã¢ãŒãã§ã¯ãã«ãŒãã®ã¿ã€ããæå®ã§ããŸãããä¿åã¢ãŒãã§ã¯ãã«ãŒãã¯åžžã«å®å šã«ééçã§ãã getPeekCardPositionïŒïŒã¡ãœããã䜿çšããŠããã®äžã«ã«ãŒãã衚瀺ãããå Žæã«èªåã§é»ãé·æ¹åœ¢ãæç»ããå¿ èŠããããŸãã ç§ãã¡ã®å Žåãå°ããªãµã€ãºã®ã«ãŒãã䜿çšããã°ååã§ãæ°åãšéãªã£ãŠããŸããããäžè¬çã«ã¯ãã«ãŒãã®ãµã€ãºã«åãããŠæç»é åã®ãµã€ãºãå°ããããããšãæãŸããã§ãããã
ãŠã©ãããã§ã€ã¹ãæŽæ°ããããã®èšå®ãå«ãã¡ãã»ãŒãžãéä¿¡ãã
æèšèª¿æŽã¢ããªã±ãŒã·ã§ã³ã®å®è£ ã§ã¯ã HoloColorPickerã䜿çšããŠæ°åãšèæ¯ã®è²ãéžæããŸãã æèšã®è²ã®å€æŽã¯ããŠãŒã¶ãŒãè²ãå€æŽãããšããã«ãªã¢ã«ã¿ã€ã ã§çºçããŸã ïŒè²éžæã³ã³ãããŒã«ã®ColorPicker.OnColorChangedListenerã€ãã³ãã§ïŒã ãã ããããã«ããããã€ãã®åé¡ãçºçããŸãã ãŠãŒã¶ãŒã¯éåžžã«è¿ éã«è²ãå€æŽã§ããŸãïŒè²éžæãªã³ã°ã«æ²¿ã£ãŠæãåãããšã€ãã³ããçºçããŸãïŒãããã«ãããè²å€æŽã¡ãã»ãŒãžãã¥ãŒããªãŒããŒãããŒããŸãã Wearable Data Layer APIã¯ãããã»ã©éäžçã«ã¡ãã»ãŒãžãéä¿¡ããããã«ã¯èšèšãããŠããŸããã äœãèœã¡ãããšã¯ãããŸããããææ°ã®ã¡ãã»ãŒãžã®äžéšã¯åã«æèšã«å±ããªãå ŽåããããŸãã ãããåé¿ããããã«ãè²ã®æŽæ°ã®éä¿¡ã500ããªç§ã®ééã«å¶éããŸãã ãã®ãããªããããªé 延ã«ãã£ãŠäžéœåãçããããšã¯ãªãããŠã§ã¢ã©ãã«ããŒã¿ã¬ã€ã€ãŒAPIã®æ©èœãéè² è·ã«ããªãããã«ããŸãã
ãã³ãã©ãŒhandlerUpdateColorBackground = new HandlerïŒïŒ; Runnable runnableUpdateColorBackground = new RunnableïŒïŒ{ @Override public void runïŒïŒ{ //è²ãå€æŽãããå Žåã«ã®ã¿æŽæ° ifïŒpickedColorBackgroundïŒ= lastSentColorBackgroundïŒ{ sendConfigUpdateMessageïŒKEY_BACKGROUND_COLORãpickedColorBackgroundïŒ; } handlerUpdateColorBackground.postDelayedïŒthisã500ïŒ; //ãŠã©ããã«éä¿¡ãããæåŸã®è²ãæŽæ°ããŸã lastSentColorBackground = pickedColorBackground; } };
äžè¬çãªAndroid Wearãšã¯ã¹ããªãšã³ã¹
ã»ãšãã©ã®Android Wearæèšã¯Snapdragon 400ãããã«åºã¥ããŠããŸã-ASUSãSonyãSamsungãLGã¯ãã¹ãŠã®æèšã§äœ¿çšããŠããŸãã ãã®ãããã«ã¯ãæ倧1.2 Hzã®åšæ³¢æ°ãæã€å°è±¡çãªã¯ã¢ããã³ã¢ããã»ããµãæèŒãããŠãããæèšãšããŠã¯ååã§ãã 圌ã®ãããªã«ãŒãAdreno 305ã¯äžèŠãå°ãæ代é ãã«èŠãããããããŸããã ãã ãããã®æèšã®è§£å床ã¯320x320ãã¯ã»ã«ãšããå°ãããããéåžžã«è€éãª3Dã·ãŒã³ãæ¯ç§60ãã¬ãŒã ã§ã¬ã³ããªã³ã°ããã«ã¯ååã§ãã å€ãOMAP3630ããããæèŒããMoto 360ã§ããã䜿çšå¯èœãªç»é¢è§£å床ã§ååãªããã©ãŒãã³ã¹ãçºæ®ããããªã匷åãªPowerVR SGX530ã°ã©ãã£ãã¯ã¹ã«ãŒããæèŒããŠããŸãã
ããšãã°ã128x128解å床ã§è¿œå ããã4ãã¹ãã©ãŒã«ãããã«ãŒã å¹æã¯ãããã©ãŒãã³ã¹ã®äœäžãåŒãèµ·ãããŸããã§ãã-Adreno 305ã¯ãã®è¿œå ã¿ã¹ã¯ã«ç°¡åã«å¯ŸåŠããŸããã ãã ããã¯ããã¯ã§ã¯ã2ã€ã®ãã©ãŒãµã€ã¯ã«ã§ãã«ãŒã 64x64ã®äœè§£å床ã䜿çšããã®ã«ååã§ããããšãå€æããŸããã
ãã³ãã«ã©ã³2ãAndroidãŠã©ããã§åäœããGTAãªã©ã®ã²ãŒã ãé 延ãªãåäœãããå€ãã®ãããªããããŸããããã¯ããããã®ããã€ã¹ã§ã®ãããªã«ãŒãã®ããã©ãŒãã³ã¹ãããäžåºŠç€ºããŠããŸãã
ã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšãããã·ã§ãŒããŒ
ã¬ã³ããªã³ã°ã³ãã³ãã®æ°ãšCPUã«ãã£ãŠå®è¡ãããäœæ¥ãæžããããã«ãæ°å€ã®ã¢ãã¡ãŒã·ã§ã³ã¯é ç¹ã·ã§ãŒããŒã§å®è¡ãããŸãã ããã説æããããã«ãæ°åã5ããšã0ãã®éã®é·ç§»ã¢ãã«ã®äŸã次ã«ç€ºããŸãã
ã芧ã®ãšãããã¢ãã«ã®é ç¹ã¯3ã€ã®ã°ã«ãŒãã«åããããŸãã
- ã¢ãã¡ãŒã·ã§ã³åãããŠããªãé»è²ã®éšå-æ°åã5ããšã0ãã®éã§å ±éã®éšåãè¡šããŸãã
- æãç°è²ã®éšåã¯ã¢ãã¡ãŒã·ã§ã³äžã«çç¥ãããŸã-çªå·ã0ãã§ã¯äœ¿çšãããŸããã
- èãç°è²ã®éšåã¯ã¢ãã¡ãŒã·ã§ã³äžã«äžæããŸã;ãããã¯æ°åã0ãã§äœ¿çšãããŸãããã5ãã§ã¯äœ¿çšãããŸããã
ãã®æ å ±ã¯ãã¯ã¹ãã£åº§æšã«å ¥åãããŸããV座æšã¯ãåºå®éšåã®å Žåã¯0ãäžæéšåã®å Žåã¯1ãäžééšåã®å Žåã¯-1ã«èšå®ãããŸãã ããã«å ããŠãU座æšã¯ã¢ãã¡ãŒã·ã§ã³ã®ãã§ãŒãºãèšå®ãããããã·ãªã³ããŒã¯ãã¹ãŠäžç·ã«ç§»åããã®ã§ã¯ãªããäºãã«ããããªé ããæã¡ãŸãã
ãã©ã°ã¡ã³ãã·ã§ãŒããŒã¯éåžžã«åçŽã§ããé ç¹ã®Z座æšãå°ããã»ã©ãæçµãã¯ã»ã«ãããé»ãæç»ãããŸãã ã3ããšã4ãã®éã®é·ç§»ã次ã«ç€ºããŸãïŒã¢ãã«ã¯RenderMonkeyã«ãããã©ãŒãªã³ã°ãããŸãïŒ-ã4ãã®éšåãäžã«ã·ããããã3ãã®éšåãäžã«äžããæ§åã確èªã§ããŸãã
以äžã¯ãã¢ãã«ã®äžéšãé»ãèæ¯ãšçµåãããšãã®æçµçµæã§ãã
é ç¹ã·ã§ãŒããŒã³ãŒã
uAnimã¯[-1..1]ã®ç¯å²ã§èšå®ãããã¢ãã¡ãŒã·ã§ã³ãå¶åŸ¡ããŸã
åäžãªmat4 view_proj_matrix; åäžãããŒãuAnim; åäžãããŒãuHeight; åäžãããŒãuHeightColor; åäžãããŒãuHeightOffset; ããŸããŸãªvec2 Texcoordã å¯å€ãããŒãvColor; void mainïŒãã€ãïŒ { vec2 uv = gl_MultiTexCoord0.xy; vec4 pos = rm_Vertex; pos.z + = uHeight * uv.y * clampïŒuAnim + uv.xã0.0ã1.0ïŒ; gl_Position = view_proj_matrix * pos; Texcoord = uv; vColor =ïŒuHeightColor + pos.z + uHeightOffsetïŒ/ uHeightColor; }
uHeightã¯ã¢ãã¡ãŒã·ã§ã³ã®é«ããèšå®ããŸã-å€ã¯ããã©ã³ããã«äŸåããã¢ãã«ã®åäžåã®é«ããèšå®ããŸã-åçã«è¡šç€ºããããã©ã³ãã®40åäœã«çãããªããŸãã
uHeightColorããã³uHeightOffsetã䜿çšãããšãè²ã®é·ç§»ãé»ã«å€ããããšãã§ããŸãã å€uHeightColor = 40ããã³uHeightOffset = 0ã¯åçã®äŸã«äœ¿çšãããŸãããããã©ã³ãã«ãã£ãŠç°ãªããŸãã
ãã©ã°ã¡ã³ãã·ã§ãŒããŒã³ãŒã
ã芧ã®ãšãããã»ãšãã©ãã¹ãŠã®èšç®ã¯æ¢ã«é ç¹ã·ã§ãŒããŒã§è¡ãããŠããŸãããã©ã°ã¡ã³ã1ã¯è²ãè£éããã ãã§ãã
åäžãªvec4 uColor; åäžãªvec4 uColorBottom; å¯å€ãããŒãvColor; void mainïŒãã€ãïŒ { gl_FragColor = mixïŒuColorBottomãuColorãclampïŒvColorã0.0ã1.0ïŒïŒ; }
RenderMonkeyããã°ã©ã ã®ã·ã§ãŒããŒãå«ãã¢ãŒã«ã€ããžã®ãªã³ã¯ïŒ dl.dropboxusercontent.com/u/20585920/shaders_watchface.rar
転èš
Google Playã§Android Wearã¢ããªãå ¬éãããšãã¯ããAndroid Wearã§ã¢ããªãé åžãããã®æšªã«ãããã§ãã¯ããã¯ã¹ããªã³ã«ããŸã ã ããã«ããã Wear App Qualityã®èŠä»¶ãæºããããã«ã¢ããªãã¢ãã¬ãŒãããããã»ã¹ãéå§ãããŸãã ç§ãã¡ã®å Žåããã®ããã»ã¹ã«ã¯æ°æéããããããŸããã§ããã