我正在开发一个 Android 项目,我想使用
WallpaperService
将 GLSL 着色器设置为壁纸。目标是显示一个简单的灰色着色器,但我遇到了壁纸仅显示黑屏的问题。
注意。
我知道着色器编辑器的存在,但我有一些新的想法,可以使创建和自定义着色器的过程变得非常容易。
您可以查看this以获取突出显示问题的最基本的精简版本。 设置如下:
GLSL代码:
void main() {// basic code for testing purpose
if(gl_FragCoord.y > 250.0){
gl_FragColor = vec4(0.25);
}
else{
gl_FragColor = vec4(0.75);
}
}
壁纸服务实现:
import android.service.wallpaper.WallpaperService
import android.view.SurfaceHolder
import com.dhruv.hellohome.glsl.MyGLSurfaceView
class GLSLWallpaperService : WallpaperService() {
private var engine: GLWallpaperEngine? = null
fun isRunning(): Boolean {
return engine != null
}
override fun onCreateEngine(): Engine {
return GLWallpaperEngine()
}
inner class GLWallpaperEngine : Engine() {
private var glSurfaceView: MyGLSurfaceView? = null
override fun onCreate(surfaceHolder: SurfaceHolder) {
super.onCreate(surfaceHolder)
glSurfaceView = MyGLSurfaceView(this@GLSLWallpaperService)
}
override fun onSurfaceCreated(holder: SurfaceHolder) {
super.onSurfaceCreated(holder)
glSurfaceView?.surfaceCreated(holder)
}
override fun onVisibilityChanged(visible: Boolean) {
super.onVisibilityChanged(visible)
if (visible) {
glSurfaceView?.onResume()
} else {
glSurfaceView?.onPause()
}
}
override fun onDestroy() {
super.onDestroy()
glSurfaceView?.let {
it.onPause()
it.onDetachedFromWindow()
}
}
override fun onSurfaceDestroyed(holder: SurfaceHolder) {
super.onSurfaceDestroyed(holder)
glSurfaceView?.surfaceDestroyed(holder)
}
}
}
GLSurfaceView 实现:
import android.content.Context
import android.opengl.GLSurfaceView
import android.util.Log
import android.view.SurfaceHolder
class MyGLSurfaceView(context: Context) : GLSurfaceView(context) {
private val renderer: MyGLRenderer
init {
setEGLContextClientVersion(2)
renderer = MyGLRenderer(ShaderData())
setRenderer(renderer)
renderMode = RENDERMODE_CONTINUOUSLY
}
override fun surfaceCreated(holder: SurfaceHolder) {
super.surfaceCreated(holder)
Log.d("MyGLSurfaceView", "Surface created")
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
super.surfaceDestroyed(holder)
Log.d("MyGLSurfaceView", "Surface destroyed")
}
public override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
}
}
在这种情况下,MyGLRenderer 是 GLSurfaceView.Renderer 的实现,可以正常工作。 迷你节是:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto">
<supports-screens
android:largeScreens="true"
android:xlargeScreens="true"/>
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="19"/>
<!-- Required below API < 28 for exporting shaders -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"/>
<uses-feature android:glEsVersion="0x00020000"/>
<uses-feature android:name="android.hardware.camera.any"
android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus"
android:required="false"/>
<uses-feature android:name="android.software.live_wallpaper"/>
<queries>
<intent>
<action android:name="android.intent.action.VIEW"/>
<data android:scheme="https"/>
</intent>
</queries>
<application
tools:ignore="UnusedAttribute"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.HelloHome">
<service
android:name=".services.GLSLWallpaperService"
android:exported="true"
android:description="@string/wallpaper_description"
android:label="@string/app_name"
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>
<activity android:name="com.example.openglwallpaper.SettingsActivity" />
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.HelloHome">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".PreviewActivity" />
</application>
</manifest>
最后是 GLSLWallpaperService 实现:
import android.service.wallpaper.WallpaperService
import android.view.SurfaceHolder
import com.dhruv.hellohome.glsl.MyGLSurfaceView
class GLSLWallpaperService : WallpaperService() {
private var engine: GLWallpaperEngine? = null
fun isRunning(): Boolean {
return engine != null
}
override fun onCreateEngine(): Engine {
return GLWallpaperEngine()
}
override fun onDestroy() {
super.onDestroy()
}
inner class GLWallpaperEngine : Engine() {
private var glSurfaceView: MyGLSurfaceView? = null
override fun onCreate(surfaceHolder: SurfaceHolder) {
super.onCreate(surfaceHolder)
glSurfaceView = MyGLSurfaceView(this@GLSLWallpaperService)
}
override fun onSurfaceCreated(holder: SurfaceHolder) {
super.onSurfaceCreated(holder)
glSurfaceView?.surfaceCreated(holder)
}
override fun onVisibilityChanged(visible: Boolean) {
super.onVisibilityChanged(visible)
if (visible) {
glSurfaceView?.onResume()
} else {
glSurfaceView?.onPause()
}
}
override fun onDestroy() {
super.onDestroy()
glSurfaceView?.let {
it.onPause()
it.onDetachedFromWindow()
}
}
override fun onSurfaceDestroyed(holder: SurfaceHolder) {
super.onSurfaceDestroyed(holder)
glSurfaceView?.surfaceDestroyed(holder)
}
}
}
我已经被困了大约两周,似乎不明白出了什么问题。 如果有人可以帮助我,那将是一个巨大的帮助。
好吧,问题出在 GLSLWallpaperService 如何处理 engien。
这是固定代码
class GLSLWallpaperService : WallpaperService() {
private var engine: GLWallpaperEngine? = null
fun isRunning(): Boolean {
return engine != null
}
override fun onCreateEngine(): Engine {
engine = GLWallpaperEngine()
return engine!!
}
override fun onDestroy() {
super.onDestroy()
engine = null
}
inner class GLWallpaperEngine : Engine() {
private var glSurfaceView: MyGLSurfaceView? = null
override fun onCreate(surfaceHolder: SurfaceHolder) {
super.onCreate(surfaceHolder)
glSurfaceView = GLWallpaperSurfaceView()
}
override fun onSurfaceCreated(holder: SurfaceHolder) {
super.onSurfaceCreated(holder)
glSurfaceView?.surfaceCreated(holder)
}
override fun onVisibilityChanged(visible: Boolean) {
super.onVisibilityChanged(visible)
if (visible) {
glSurfaceView?.onResume()
} else {
glSurfaceView?.onPause()
}
}
override fun onDestroy() {
super.onDestroy()
glSurfaceView?.let {
it.onPause()
it.onDetachedFromWindow()
}
}
override fun onSurfaceDestroyed(holder: SurfaceHolder) {
super.onSurfaceDestroyed(holder)
glSurfaceView?.surfaceDestroyed(holder)
}
inner class GLWallpaperSurfaceView : MyGLSurfaceView(this@GLSLWallpaperService) {
override fun getHolder(): SurfaceHolder {
return getSurfaceHolder()
}
}
}
}
这是一个愚蠢的问题,但我希望如果其他人被困在这个问题上,那么这可能会对你有所帮助。