├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── client_token └── com │ └── banuba │ └── sdk │ └── example │ └── common │ └── BanubaClientToken.kt ├── effect_player_realtime_preview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── banuba │ │ └── sdk │ │ └── example │ │ └── effect_player_realtime_preview │ │ ├── AllActivitiesTest.kt │ │ ├── ExampleInstrumentedTest.kt │ │ ├── VideoMaskTest.kt │ │ └── screenshot │ │ ├── EspressoScreenshot.kt │ │ └── ScreenshotTestRule.kt │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── bnb-resources │ │ │ └── effects │ │ │ │ ├── DebugWireframe │ │ │ │ ├── config.json │ │ │ │ ├── preview.png │ │ │ │ ├── wireframe.frag │ │ │ │ └── wireframe.vert │ │ │ │ ├── PineappleGlasses │ │ │ │ ├── audios │ │ │ │ │ └── music.ogg │ │ │ │ ├── config.js │ │ │ │ ├── config.json │ │ │ │ ├── images │ │ │ │ │ ├── 50s_256x512.png │ │ │ │ │ ├── EYES_high.png │ │ │ │ │ ├── FLARE_37_768.png │ │ │ │ │ ├── LUT_sunny.png │ │ │ │ │ ├── PineappleGlasses_Base_Color.ktx │ │ │ │ │ ├── PineappleGlasses_MRAO.ktx │ │ │ │ │ ├── PineappleGlasses_Normal.ktx │ │ │ │ │ ├── REDMASK_v3_256.png │ │ │ │ │ ├── TEETH_high.png │ │ │ │ │ ├── brdf.ktx │ │ │ │ │ ├── ibl_diff.ktx │ │ │ │ │ ├── ibl_spec.ktx │ │ │ │ │ ├── null_image.png │ │ │ │ │ ├── null_lut.png │ │ │ │ │ ├── preview.png │ │ │ │ │ └── soft_dark_eyes_256.png │ │ │ │ ├── meshes │ │ │ │ │ ├── PineappleGlasses.bsm2 │ │ │ │ │ └── morth.bsm2 │ │ │ │ ├── preview.png │ │ │ │ ├── shaders │ │ │ │ │ ├── PineappleGlasses.frag │ │ │ │ │ ├── PineappleGlasses.vert │ │ │ │ │ ├── backgroundSeparation.frag │ │ │ │ │ ├── backgroundSeparation.vert │ │ │ │ │ ├── finalColorFilter.fsh.frag │ │ │ │ │ ├── finalColorFilter.fsh.vert │ │ │ │ │ ├── glass.frag │ │ │ │ │ ├── glass.vert │ │ │ │ │ ├── retouch.frag │ │ │ │ │ └── retouch.vert │ │ │ │ └── videos │ │ │ │ │ └── Back_F.mp4 │ │ │ │ ├── TrollGrandma │ │ │ │ ├── config.js │ │ │ │ ├── config.json │ │ │ │ ├── images │ │ │ │ │ ├── EYES_medium.png │ │ │ │ │ ├── FLARE_39_512.png │ │ │ │ │ ├── LUT_bubblegum_bright.png │ │ │ │ │ ├── REDMASK_v3_256.png │ │ │ │ │ ├── TEETH_medium.png │ │ │ │ │ ├── brdf.ktx │ │ │ │ │ ├── facemat_Base_Color.ktx │ │ │ │ │ ├── ibl_diff.ktx │ │ │ │ │ ├── ibl_spec.ktx │ │ │ │ │ ├── null_image.png │ │ │ │ │ ├── null_lut.png │ │ │ │ │ ├── preview.png │ │ │ │ │ ├── soft_trollma.png │ │ │ │ │ ├── trollma_Base_Color.ktx │ │ │ │ │ ├── trollma_MRAO.ktx │ │ │ │ │ └── trollma_Normal.ktx │ │ │ │ ├── meshes │ │ │ │ │ ├── TrollGrandma.bsm2 │ │ │ │ │ └── Trollma_morphing.bsm2 │ │ │ │ ├── preview.png │ │ │ │ └── shaders │ │ │ │ │ ├── facemat.frag │ │ │ │ │ ├── facemat.vert │ │ │ │ │ ├── finalColorFilter.fsh.frag │ │ │ │ │ ├── finalColorFilter.fsh.vert │ │ │ │ │ ├── glasses.frag │ │ │ │ │ ├── glasses.vert │ │ │ │ │ ├── hair_alpha.frag │ │ │ │ │ ├── hair_alpha.vert │ │ │ │ │ ├── hair_base.frag │ │ │ │ │ ├── hair_base.vert │ │ │ │ │ ├── retouch.frag │ │ │ │ │ └── retouch.vert │ │ │ │ └── watermark.png │ │ ├── face_video_1080p.mp4 │ │ ├── face_video_1080p_r180.mp4 │ │ ├── face_video_1080p_r270.mp4 │ │ ├── face_video_1080p_r90.mp4 │ │ └── face_video_720p.mp4 │ ├── java │ │ └── com │ │ │ └── banuba │ │ │ └── sdk │ │ │ └── example │ │ │ └── effect_player_realtime_preview │ │ │ ├── Application.kt │ │ │ ├── CameraPreviewActivity.kt │ │ │ ├── MainActivity.kt │ │ │ ├── MaskActivity.kt │ │ │ ├── VideoMaskActivity.kt │ │ │ └── VideoRecordingActivity.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_apply_mask.xml │ │ ├── activity_camera_preview.xml │ │ ├── activity_main.xml │ │ ├── activity_mask_video.xml │ │ └── activity_video_recording.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── provider_paths.xml │ └── test │ └── java │ └── com │ └── banuba │ └── sdk │ └── example │ └── effect_player_realtime_preview │ └── ExampleUnitTest.kt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitattributes: -------------------------------------------------------------------------------- 1 | *.vert linguist-detectable=false 2 | *.frag linguist-detectable=false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/* 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Banuba Limited 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository is considered as outdated, prefer [this repo](https://github.com/Banuba/banuba-sdk-android-samples) as a basement for new projects. 2 | 3 | [![](https://www.banuba.com/hubfs/Banuba_November2018/Images/Banuba%20SDK.png)](https://docs.banuba.com/face-ar-sdk-v1/android/android_overview) 4 | 5 | ## Quick start examples for [Banuba SDK on Android](https://docs.banuba.com/face-ar-sdk-v1/android/android_overview) 6 | 7 | ## [Requirements](https://docs.banuba.com/face-ar-sdk-v1/overview/system_requirements) 8 | 9 | ## Usage 10 | ### Token 11 | Before you commit to a license, you are free to test all the features of the SDK for free. To start it, [send us a message](https://www.banuba.com/facear-sdk/face-filters#form). 12 | We will get back to you with the trial token. 13 | You can store the token within the app. 14 | 15 | Feel free to [contact us](https://docs.banuba.com/face-ar-sdk-v1/support) if you have any questions. 16 | 17 | ### Getting Started 18 | 19 | 1. Clone the repository 20 | 2. Copy and Paste your client token into appropriate section of 21 | [`client_token/com/banuba/sdk/example/common/BanubaClientToken.kt`](client_token/com/banuba/sdk/example/common/BanubaClientToken.kt) 22 | 3. Open the project in Android Studio and run the necessary target using the usual steps. 23 | 24 | ### Docs 25 | You can find more info [here](https://docs.banuba.com/face-ar-sdk-v1/android/android_overview). 26 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | mavenCentral() 7 | } 8 | 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:7.4.1' 11 | classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21' 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | mavenCentral() 21 | 22 | maven { 23 | name "GitHubPackages" 24 | url "https://maven.pkg.github.com/sdk-banuba/banuba-sdk-android" 25 | credentials { 26 | username = "sdk-banuba" 27 | password = "\u0067\u0068\u0070\u005f\u0033\u0057\u006a\u0059\u004a\u0067\u0071\u0054\u0058\u0058\u0068\u0074\u0051\u0033\u0075\u0038\u0051\u0046\u0036\u005a\u0067\u004f\u0041\u0053\u0064\u0046\u0032\u0045\u0046\u006a\u0030\u0036\u006d\u006e\u004a\u004a" 28 | } 29 | } 30 | } 31 | } 32 | 33 | task clean(type: Delete) { 34 | delete rootProject.buildDir 35 | } 36 | -------------------------------------------------------------------------------- /client_token/com/banuba/sdk/example/common/BanubaClientToken.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.common 2 | 3 | /** 4 | * Client token for Banuba SDK. Consider obfuscation in release app. 5 | */ 6 | 7 | internal const val BANUBA_CLIENT_TOKEN: String = 8 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 31 7 | 8 | defaultConfig { 9 | applicationId "com.banuba.sdk.example.effect_player_realtime_preview" 10 | minSdkVersion 23 11 | targetSdkVersion 31 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | 25 | kotlinOptions { 26 | jvmTarget = '1.8' 27 | } 28 | 29 | // NOTE! Add if your project uses Kotlin as main language 30 | compileOptions { 31 | coreLibraryDesugaringEnabled true 32 | 33 | sourceCompatibility JavaVersion.VERSION_1_8 34 | targetCompatibility JavaVersion.VERSION_1_8 35 | } 36 | 37 | // Add client_token sources shared across example projects. 38 | // You may just move the BanubaClientToken.kt in your app, if such sharing is not neccessary. 39 | sourceSets { 40 | main { 41 | java { 42 | srcDir '../client_token' 43 | } 44 | } 45 | } 46 | } 47 | 48 | dependencies { 49 | coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.9' 50 | 51 | 52 | implementation 'androidx.appcompat:appcompat:1.4.1' 53 | implementation 'androidx.constraintlayout:constraintlayout:2.1.3' 54 | 55 | testImplementation 'junit:junit:4.13.2' 56 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 57 | 58 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 59 | androidTestImplementation 'androidx.test:runner:1.4.0' 60 | androidTestImplementation 'androidx.test:rules:1.4.0' 61 | 62 | // Banuba SDK dependencies 63 | implementation "com.banuba.sdk:banuba_sdk:1+" 64 | } 65 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/androidTest/java/com/banuba/sdk/example/effect_player_realtime_preview/AllActivitiesTest.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.effect_player_realtime_preview 2 | 3 | import androidx.test.espresso.Espresso.onView 4 | import androidx.test.espresso.Espresso.pressBack 5 | import androidx.test.espresso.action.ViewActions.click 6 | import androidx.test.espresso.assertion.ViewAssertions.matches 7 | import androidx.test.espresso.matcher.ViewMatchers.* 8 | import androidx.test.filters.LargeTest 9 | import androidx.test.rule.ActivityTestRule 10 | import androidx.test.rule.GrantPermissionRule 11 | import androidx.test.runner.AndroidJUnit4 12 | import com.banuba.sdk.example.effect_player_realtime_preview.screenshot.EspressoScreenshot 13 | import com.banuba.sdk.example.effect_player_realtime_preview.screenshot.ScreenshotTestRule 14 | import org.junit.Rule 15 | import org.junit.Test 16 | import org.junit.rules.TestName 17 | import org.junit.runner.RunWith 18 | 19 | 20 | @RunWith(AndroidJUnit4::class) 21 | @LargeTest 22 | class AllActivitiesTest { 23 | @Rule 24 | @JvmField 25 | val testName = TestName() 26 | 27 | @Rule 28 | @JvmField 29 | val screenshotTestRule = ScreenshotTestRule() 30 | 31 | @Rule 32 | @JvmField 33 | var mActivityTestRule = ActivityTestRule(MainActivity::class.java) 34 | 35 | @Rule 36 | @JvmField 37 | var mGrantPermissionRule = 38 | GrantPermissionRule.grant( 39 | "android.permission.CAMERA", 40 | "android.permission.RECORD_AUDIO", 41 | "android.permission.WRITE_EXTERNAL_STORAGE", 42 | "android.permission.READ_EXTERNAL_STORAGE" 43 | ) 44 | 45 | @Test 46 | fun cameraPreviewTest() { 47 | onView(withId(R.id.openCameraButton)).perform(click()) 48 | Thread.sleep(2000) 49 | 50 | // Negative case to make test fail 51 | // onView(withId(R.id.openCameraButton)).check(matches(withText("Hello!"))) 52 | pressBack() 53 | } 54 | 55 | @Test 56 | fun applyMaskTest() { 57 | onView(withId(R.id.applyMaskButton)).perform(click()) 58 | onView(withId(R.id.showMaskButton)).check(matches(isDisplayed())).perform(click()) 59 | // Wait until effect appeared to make a screenshot 60 | Thread.sleep(2000) 61 | EspressoScreenshot.takeScreenshot(testName.methodName) 62 | 63 | // Enable all 3 effects by tapping on the screen 64 | 65 | onView(withId(R.id.surfaceView)).perform(click()) 66 | Thread.sleep(2000) 67 | EspressoScreenshot.takeScreenshot(testName.methodName) 68 | 69 | onView(withId(R.id.surfaceView)).perform(click()) 70 | Thread.sleep(2000) 71 | EspressoScreenshot.takeScreenshot(testName.methodName) 72 | 73 | onView(withId(R.id.surfaceView)).perform(click()) 74 | Thread.sleep(2000) 75 | EspressoScreenshot.takeScreenshot(testName.methodName) 76 | 77 | onView(withId(R.id.showMaskButton)).perform(click()) 78 | 79 | pressBack() 80 | } 81 | 82 | @Test 83 | fun RecordVideoTest() { 84 | onView(withId(R.id.recordVideoButton)).perform(click()) 85 | onView(withId(R.id.recordAudioSwitch)).check(matches(isDisplayed())).perform(click()) 86 | 87 | Thread.sleep(500) 88 | onView(withId(R.id.recordActionButton)).perform(click()) 89 | Thread.sleep(2000) 90 | onView(withId(R.id.recordActionButton)).perform(click()) 91 | 92 | pressBack() 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/androidTest/java/com/banuba/sdk/example/effect_player_realtime_preview/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.effect_player_realtime_preview 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals( 23 | "com.banuba.sdk.example.effect_player_realtime_preview", 24 | appContext.packageName 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/androidTest/java/com/banuba/sdk/example/effect_player_realtime_preview/VideoMaskTest.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.effect_player_realtime_preview 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import com.banuba.sdk.example.effect_player_realtime_preview.media.MaskProcessor 5 | import org.junit.Test 6 | import java.io.File 7 | 8 | class VideoMaskTest { 9 | 10 | @Test 11 | @Throws(Exception::class) 12 | fun test720p() { 13 | makeMaskOnVideo("face_video_720p.mp4") 14 | } 15 | 16 | @Test 17 | @Throws(Exception::class) 18 | fun test1080p() { 19 | makeMaskOnVideo("face_video_1080p.mp4") 20 | } 21 | 22 | @Test 23 | @Throws(Exception::class) 24 | fun test1080p_r90() { 25 | makeMaskOnVideo("face_video_1080p_r90.mp4") 26 | } 27 | 28 | @Test 29 | @Throws(Exception::class) 30 | fun test1080p_r180() { 31 | makeMaskOnVideo("face_video_1080p_r180.mp4") 32 | } 33 | 34 | @Test 35 | @Throws(Exception::class) 36 | fun test1080p_r270() { 37 | makeMaskOnVideo("face_video_1080p_r270.mp4") 38 | } 39 | 40 | 41 | private fun makeMaskOnVideo(input: String) { 42 | val context = InstrumentationRegistry.getInstrumentation().targetContext 43 | val inputFile = FileUtils.copyFromAssetsToFile(context, input) 44 | val outputFile = File(context.getExternalFilesDir(null), "$input.mask.mp4") 45 | MaskProcessor(context, inputFile, outputFile, "UnluckyWitch").process() 46 | } 47 | 48 | 49 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/androidTest/java/com/banuba/sdk/example/effect_player_realtime_preview/screenshot/EspressoScreenshot.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.effect_player_realtime_preview.screenshot 2 | 3 | /* 4 | * Copyright (C) 2017 - present Instructure, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.util.Log 20 | import androidx.test.runner.screenshot.Screenshot 21 | import org.junit.runner.Description 22 | import java.io.BufferedOutputStream 23 | import java.io.File 24 | import java.io.FileOutputStream 25 | import java.io.IOException 26 | import java.util.concurrent.atomic.AtomicInteger 27 | 28 | /** 29 | * Used to automatically capture screenshots of failed tests. 30 | */ 31 | object EspressoScreenshot { 32 | private val imageCounter = AtomicInteger(0) 33 | private val dotPNG = ".png" 34 | private val underscore = "_" 35 | // Firebase Test Lab requires screenshots to be saved to /sdcard/screenshots 36 | // https://github.com/firebase/firebase-testlab-instr-lib/blob/f0a21a526499f051ac5074dc382cf79e237d2f4e/firebase-testlab-instr-lib/testlab-instr-lib/src/main/java/com/google/firebase/testlab/screenshot/FirebaseScreenCaptureProcessor.java#L36 37 | private val screenshotFolder = File("/sdcard/screenshots") 38 | private val TAG = EspressoScreenshot::class.java.simpleName 39 | 40 | private fun getScreenshotName(description: String): String { 41 | // val className = description.className 42 | // val methodName = description.methodName 43 | val className = description 44 | 45 | val imageNumberInt = imageCounter.incrementAndGet() 46 | var number = imageNumberInt.toString() 47 | if (imageNumberInt < 10) number = "0$number" 48 | 49 | // val components = arrayOf(className, underscore, methodName, underscore, number, dotPNG) 50 | val components = arrayOf(className, underscore, number, dotPNG) 51 | 52 | var length = 0 53 | 54 | for (component in components) { 55 | length += component.length 56 | } 57 | 58 | val result = StringBuilder(length) 59 | 60 | for (component in components) { 61 | result.append(component) 62 | } 63 | 64 | return result.toString() 65 | } 66 | 67 | private fun prepareScreenshotPath() { 68 | try { 69 | screenshotFolder.mkdirs() 70 | } catch (ignored: Exception) { 71 | Log.e(TAG, "Failed to make screenshot folder $screenshotFolder") 72 | } 73 | 74 | } 75 | 76 | fun takeScreenshot(description: String) { 77 | prepareScreenshotPath() 78 | 79 | val screenshotName = getScreenshotName(description) 80 | val capture = Screenshot.capture() // default format is PNG 81 | 82 | // based on BasicScreenCaptureProcessor#process 83 | val imageFile = File(screenshotFolder, screenshotName) 84 | var out: BufferedOutputStream? = null 85 | try { 86 | Log.i(TAG, "Saving screenshot to " + imageFile.absolutePath) 87 | out = BufferedOutputStream(FileOutputStream(imageFile)) 88 | capture.bitmap.compress(capture.format, 100, out) 89 | out.flush() 90 | Log.i(TAG, "Screenshot exists? " + imageFile.exists()) 91 | } catch (ignored: Exception) { 92 | Log.e(TAG, ignored.toString()) 93 | ignored.printStackTrace() 94 | } finally { 95 | try { 96 | out?.close() 97 | } catch (ignored: IOException) { 98 | Log.e(TAG, ignored.toString()) 99 | ignored.printStackTrace() 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/androidTest/java/com/banuba/sdk/example/effect_player_realtime_preview/screenshot/ScreenshotTestRule.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.effect_player_realtime_preview.screenshot 2 | 3 | /* 4 | * Copyright (C) 2017 - present Instructure, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import androidx.test.espresso.Espresso 20 | import androidx.test.espresso.base.DefaultFailureHandler 21 | import androidx.test.platform.app.InstrumentationRegistry 22 | import org.junit.rules.TestRule 23 | import org.junit.runner.Description 24 | import org.junit.runners.model.Statement 25 | import java.util.concurrent.atomic.AtomicBoolean 26 | 27 | class ScreenshotTestRule : TestRule { 28 | // Note: Data seeding must happen before we run a test. As a result, retrying failed tests 29 | // at the JUnit level doesn"t make sense because we can"t run data seeeding. 30 | // 31 | // Run all test methods tryCount times. Take screenshots on failure. 32 | // A method rule would allow targeting specific (method.getAnnotation(Retry.class)) 33 | private val tryCount = 1 34 | 35 | override fun apply(base: Statement, description: Description): Statement { 36 | return object : Statement() { 37 | @Throws(Throwable::class) 38 | override fun evaluate() { 39 | var error: Throwable? = null 40 | 41 | val errorHandled = AtomicBoolean(false) 42 | 43 | // Espresso failure handler will capture accurate UI screenshots. 44 | // if we wait for `try { base.evaluate() } catch ()` then the UI will be in a different state 45 | // 46 | // Only espresso failures trigger the espresso failure handlers. For JUnit assert errors, 47 | // those must be captured in `try { base.evaluate() } catch ()` 48 | Espresso.setFailureHandler { throwable, matcher -> 49 | EspressoScreenshot.takeScreenshot("failure_${description}") 50 | errorHandled.set(true) 51 | val targetContext = InstrumentationRegistry.getInstrumentation().targetContext 52 | DefaultFailureHandler(targetContext).handle(throwable, matcher) 53 | } 54 | 55 | for (i in 0 until tryCount) { 56 | errorHandled.set(false) 57 | try { 58 | base.evaluate() 59 | return 60 | } catch (t: Throwable) { 61 | if (!errorHandled.get()) { 62 | EspressoScreenshot.takeScreenshot("failure_${description}") 63 | } 64 | error = t 65 | } 66 | 67 | } 68 | 69 | if (error != null) throw error 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 32 | 33 | 37 | 38 | 42 | 43 | 47 | 48 | 53 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/DebugWireframe/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets": { 3 | "attachments": { 4 | "effect_color": { 5 | "type": "color" 6 | }, 7 | "effect_depth": { 8 | "clear": [ 9 | 1.0 10 | ], 11 | "type": "depth" 12 | } 13 | }, 14 | "images": { 15 | "camera: tex_y": { 16 | "type" : "camera", 17 | "format": "y" 18 | }, 19 | "camera: tex_uv": { 20 | "type" : "camera", 21 | "format": "uv" 22 | }, 23 | "camera: tex_rgb": { 24 | "type" : "camera", 25 | "format": "rgba" 26 | } 27 | }, 28 | "materials": { 29 | "$builtin$materials/camera": { 30 | "samplers": [ 31 | { 32 | "name": "tex_y", 33 | "image": "camera: tex_y" 34 | }, 35 | { 36 | "name": "tex_uv", 37 | "image": "camera: tex_uv" 38 | }, 39 | { 40 | "name": "tex_rgb", 41 | "image": "camera: tex_rgb" 42 | } 43 | ], 44 | "state": { 45 | "backfaces": true, 46 | "blend": "off", 47 | "colorwrite": true, 48 | "ztest": false, 49 | "zwrite": false 50 | }, 51 | "parameters": { 52 | "bnb_camera_orientation": { 53 | "type": "vec4", 54 | "value": [1, 0, 0, 1] 55 | }, 56 | 57 | "bnb_camera_scale": { 58 | "type": "vec4", 59 | "value": [1, 0, 0, 1] 60 | }, 61 | 62 | "bnb_view_width_fraction": { 63 | "type": "vec4", 64 | "value": [1, 0, 0, 0] 65 | } 66 | } 67 | }, 68 | "wireframe": { 69 | "samplers": [ 70 | ], 71 | "state": { 72 | "backfaces": false, 73 | "blend": "off", 74 | "colorwrite": true, 75 | "ztest": false, 76 | "zwrite": false 77 | }, 78 | "geometry_topology": "lines_list", 79 | "parameters": {} 80 | } 81 | }, 82 | "meshes": { 83 | "!bnb_FACE": "$builtin$meshes/wireframe.stream:0", 84 | "camera_surface": "$builtin$meshes/fs_tri" 85 | }, 86 | "faces": { 87 | "face0": { 88 | "index": 0, 89 | "mesh": "!bnb_FACE" 90 | } 91 | } 92 | }, 93 | "components": { 94 | "camera_tri": { 95 | "materials": ["$builtin$materials/camera"], 96 | "mesh": "camera_surface", 97 | "type": "mesh_instance" 98 | }, 99 | "face:0": { 100 | "materials": ["wireframe"], 101 | "mesh": "!bnb_FACE", 102 | "type": "mesh_instance" 103 | }, 104 | "face_tracker:0": { 105 | "face": "face0", 106 | "type": "face_tracker" 107 | } 108 | }, 109 | "entities": { 110 | "camera": { 111 | "components": [ 112 | "camera_tri" 113 | ], 114 | "layer": "composer_pre" 115 | }, 116 | "face0": { 117 | "components": [ 118 | "face:0" 119 | ], 120 | "layer": "retouch" 121 | }, 122 | "face_tracker0": { 123 | "components": [ 124 | "face_tracker:0" 125 | ] 126 | } 127 | }, 128 | "hierarchy": { 129 | "face_tracker0": [ 130 | "face0" 131 | ], 132 | "root": [ 133 | "camera", 134 | "face_tracker0" 135 | ] 136 | }, 137 | "layers": { 138 | "composer_pre": {}, 139 | "camera_copy": {}, 140 | "retouch": {}, 141 | "morph": {} 142 | }, 143 | "render_list": { 144 | "default": [ 145 | { 146 | "layer": "composer_pre", 147 | "render_target": "EffectRT" 148 | }, 149 | { 150 | "layer": "retouch", 151 | "render_target": "EffectRT" 152 | } 153 | ] 154 | }, 155 | "render_targets": { 156 | "EffectRT": [ 157 | "effect_color", 158 | "effect_depth" 159 | ] 160 | }, 161 | 162 | 163 | "scene": "face_tracker" 164 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/DebugWireframe/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/DebugWireframe/preview.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/DebugWireframe/wireframe.frag: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void main() 4 | { 5 | bnb_FragColor = vec4(0., 1., 0., 1.); 6 | } 7 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/DebugWireframe/wireframe.vert: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | BNB_LAYOUT_LOCATION(0) BNB_IN vec3 attrib_pos; 4 | BNB_LAYOUT_LOCATION(1) BNB_IN vec3 attrib_pos_static; 5 | BNB_LAYOUT_LOCATION(2) BNB_IN vec2 attrib_uv; 6 | BNB_LAYOUT_LOCATION(3) BNB_IN vec4 attrib_red_mask; 7 | 8 | void main() 9 | { 10 | gl_Position = bnb_MVP * vec4( attrib_pos, 1. ); 11 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/audios/music.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/audios/music.ogg -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/config.js: -------------------------------------------------------------------------------- 1 | function Effect() 2 | { 3 | var self = this; 4 | 5 | this.meshes = [ 6 | {file: "morth.bsm2", anims: [ 7 | {a: "static", t: 0}, 8 | ]}, 9 | {file: "PineappleGlasses.bsm2", anims: [ 10 | {a: "static", t: 0}, 11 | ]}, 12 | ]; 13 | 14 | this.play = function() { 15 | var now = (new Date()).getTime(); 16 | for (var i = 0; i < self.meshes.length; i++) { 17 | if (now > self.meshes[i].endTime) { 18 | self.meshes[i].animIdx = (self.meshes[i].animIdx + 1) % self.meshes[i].anims.length; 19 | Api.meshfxMsg("animOnce", i, 0, self.meshes[i].anims[self.meshes[i].animIdx].a); 20 | self.meshes[i].endTime = now + self.meshes[i].anims[self.meshes[i].animIdx].t; 21 | } 22 | } 23 | 24 | // if(Api.isMouthOpen()) { 25 | // Api.hideHint(); 26 | // } 27 | }; 28 | 29 | this.init = function() { 30 | Api.meshfxMsg("spawn", 2, 0, "!glfx_FACE"); 31 | 32 | Api.meshfxMsg("spawn", 0, 0, "morth.bsm2"); 33 | // Api.meshfxMsg("animOnce", 0, 0, "static"); 34 | 35 | Api.meshfxMsg("spawn", 1, 0, "PineappleGlasses.bsm2"); 36 | // Api.meshfxMsg("animOnce", 1, 0, "static"); 37 | 38 | for (var i = 0; i < self.meshes.length; i++) { 39 | self.meshes[i].animIdx = -1; 40 | self.meshes[i].endTime = 0; 41 | } 42 | 43 | self.faceActions = [self.play]; 44 | // Api.showHint("Open mouth"); 45 | // Api.playVideo("frx",true,1); 46 | Api.playVideo("backgroundSeparation", true, 1); 47 | Api.playSound("music.ogg", true, 1); 48 | Api.showRecordButton(); 49 | }; 50 | 51 | this.restart = function() { 52 | Api.meshfxReset(); 53 | // Api.stopVideo("frx"); 54 | Api.stopSound("music.ogg"); 55 | self.init(); 56 | }; 57 | 58 | this.faceActions = []; 59 | this.noFaceActions = []; 60 | 61 | this.videoRecordStartActions = []; 62 | this.videoRecordFinishActions = []; 63 | this.videoRecordDiscardActions = [this.restart]; 64 | } 65 | 66 | configure(new Effect()); -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/50s_256x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/50s_256x512.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/EYES_high.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/EYES_high.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/FLARE_37_768.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/FLARE_37_768.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/LUT_sunny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/LUT_sunny.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/PineappleGlasses_Base_Color.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/PineappleGlasses_Base_Color.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/PineappleGlasses_MRAO.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/PineappleGlasses_MRAO.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/PineappleGlasses_Normal.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/PineappleGlasses_Normal.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/REDMASK_v3_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/REDMASK_v3_256.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/TEETH_high.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/TEETH_high.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/brdf.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/brdf.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/ibl_diff.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/ibl_diff.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/ibl_spec.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/ibl_spec.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/null_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/null_image.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/null_lut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/null_lut.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/preview.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/soft_dark_eyes_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/images/soft_dark_eyes_256.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/meshes/PineappleGlasses.bsm2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/meshes/PineappleGlasses.bsm2 -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/meshes/morth.bsm2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/meshes/morth.bsm2 -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/preview.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/shaders/PineappleGlasses.frag: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #define GLFX_IBL 5 | #define GLFX_TBN 6 | #define GLFX_TEX_MRAO 7 | #define GLFX_LIGHTING 8 | 9 | BNB_IN(0) vec2 var_uv; 10 | #ifdef GLFX_TBN 11 | BNB_IN(1) vec3 var_t; 12 | BNB_IN(2) vec3 var_b; 13 | #endif 14 | BNB_IN(3) vec3 var_n; 15 | BNB_IN(4) vec3 var_v; 16 | 17 | 18 | 19 | BNB_DECLARE_SAMPLER_2D(0, 1, tex_diffuse); 20 | #ifdef GLFX_TBN 21 | 22 | BNB_DECLARE_SAMPLER_2D(2, 3, tex_normal); 23 | #endif 24 | #ifdef GLFX_TEX_MRAO 25 | 26 | BNB_DECLARE_SAMPLER_2D(10, 11, tex_mrao); 27 | #else 28 | #ifdef GLFX_AO 29 | #endif 30 | #endif 31 | #ifdef GLFX_TEX_EMI 32 | #endif 33 | 34 | #ifdef BNB_USE_SHADOW 35 | 36 | BNB_IN(5) vec3 var_shadow_coord; 37 | float glfx_shadow_factor() 38 | { 39 | 40 | vec2 offsets[4]; 41 | offsets[0] = vec2( -0.94201624, -0.39906216 ); 42 | offsets[1] = vec2( 0.94558609, -0.76890725 ); 43 | offsets[2] = vec2( -0.094184101, -0.92938870 ); 44 | offsets[3] = vec2( 0.34495938, 0.29387760 ); 45 | float s = 0.; 46 | for( int i = 0; i != 4 /*assume that offsets.length() was called.*/; ++i ) 47 | s += texture( glfx_SHADOW, var_shadow_coord + vec3(offsets[i]/110.,0.1) ); 48 | s *= 0.125; 49 | return s; 50 | } 51 | #endif 52 | 53 | // gamma to linear 54 | vec3 g2l( vec3 g ) 55 | { 56 | return g*(g*(g*0.305306011+0.682171111)+0.012522878); 57 | } 58 | 59 | // combined hdr to ldr and linear to gamma 60 | vec3 l2g( vec3 l ) 61 | { 62 | return sqrt(1.33*(1.-exp(-l)))-0.03; 63 | } 64 | 65 | vec3 fresnel_schlick( float prod, vec3 F0 ) 66 | { 67 | return F0 + ( 1. - F0 )*pow( 1. - prod, 5. ); 68 | } 69 | 70 | vec3 fresnel_schlick_roughness( float prod, vec3 F0, float roughness ) 71 | { 72 | return F0 + ( max( F0, 1. - roughness ) - F0 )*pow( 1. - prod, 5. ); 73 | } 74 | 75 | float distribution_GGX( float cN_H, float roughness ) 76 | { 77 | float a = roughness*roughness; 78 | float a2 = a*a; 79 | float d = cN_H*cN_H*( a2 - 1. ) + 1.; 80 | return a2/(3.14159265*d*d); 81 | } 82 | 83 | float geometry_schlick_GGX( float NV, float roughness ) 84 | { 85 | float r = roughness + 1.; 86 | float k = r*r/8.; 87 | return NV/( NV*( 1. - k ) + k ); 88 | } 89 | 90 | float geometry_smith( float cN_L, float ggx2, float roughness ) 91 | { 92 | return geometry_schlick_GGX( cN_L, roughness )*ggx2; 93 | } 94 | 95 | float diffuse_factor( float n_l, float w ) 96 | { 97 | float w1 = 1. + w; 98 | return pow( max( 0., n_l + w )/w1, w1 ); 99 | } 100 | 101 | #ifdef GLFX_IBL 102 | 103 | BNB_DECLARE_SAMPLER_2D(4, 5, tex_brdf); 104 | 105 | BNB_DECLARE_SAMPLER_CUBE(6, 7, tex_ibl_diff); 106 | 107 | BNB_DECLARE_SAMPLER_CUBE(8, 9, tex_ibl_spec); 108 | #endif 109 | 110 | #ifdef GLFX_LIGHTS 111 | // direction in xyz, lwrap in w 112 | #endif 113 | 114 | void main() 115 | { 116 | #ifdef GLFX_LIGHTS 117 | vec3 radiance[2]; 118 | radiance[1] = vec3(1.,1.,1.)*0.9*2.; 119 | radiance[0] = vec3(1.,1.,1.)*2.; 120 | #endif 121 | #ifdef GLFX_LIGHTS 122 | vec4 lights[2]; 123 | lights[1] = vec4(normalize(vec3(97.6166,-48.185,183.151)),1.); 124 | lights[0] = vec4(0.,0.6,0.8,1.); 125 | #endif 126 | vec4 base_opacity = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_diffuse),var_uv); 127 | 128 | //if( base_opacity.w < 0.5 ) discard; 129 | 130 | vec3 base = g2l(base_opacity.xyz); 131 | float opacity = base_opacity.w; 132 | #ifdef GLFX_TEX_MRAO 133 | vec3 mrao = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_mrao),var_uv).xyz; 134 | #ifdef GLFX_DIELECTRIC 135 | float metallic = 0.; 136 | #else 137 | float metallic = mrao.x; 138 | #endif 139 | float roughness = mrao.y; 140 | #else 141 | #ifdef GLFX_DIELECTRIC 142 | float metallic = 0.; 143 | #else 144 | float metallic = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_metallic),var_uv).x; 145 | #endif 146 | float roughness = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_roughness),var_uv).x; 147 | #endif 148 | 149 | #ifdef GLFX_TBN 150 | #ifdef GLFX_NORMAL_DIRECTX 151 | vec3 N = normalize( mat3(var_t,var_b,var_n)*(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normal),var_uv).xyz*vec3(2.,-2.,2.)-vec3(1.,-1.,1.)) ); 152 | #else 153 | vec3 N = normalize( mat3(var_t,var_b,var_n)*(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normal),var_uv).xyz*2.-1.) ); 154 | #endif 155 | #else 156 | vec3 N = normalize( var_n ); 157 | #endif 158 | 159 | #ifdef GLFX_2SIDED 160 | N *= gl_FrontFacing ? 1. : -1.; 161 | #endif 162 | 163 | vec3 V = normalize( -var_v ); 164 | float cN_V = max( 0., dot( N, V ) ); 165 | vec3 R = reflect( -V, N ); 166 | 167 | vec3 F0 = mix( vec3(0.04), base, metallic ); 168 | 169 | #ifdef GLFX_IBL 170 | vec3 F = fresnel_schlick_roughness( cN_V, F0, roughness ); 171 | vec3 kD = ( 1. - F )*( 1. - metallic ); 172 | 173 | vec3 diffuse = BNB_TEXTURE_CUBE(BNB_SAMPLER_CUBE(tex_ibl_diff), N ).xyz * base; 174 | 175 | const float MAX_REFLECTION_LOD = 7.; // number of mip levels in tex_ibl_spec 176 | vec3 prefilteredColor = BNB_TEXTURE_CUBE_LOD(BNB_SAMPLER_CUBE(tex_ibl_spec), R, roughness*MAX_REFLECTION_LOD ).xyz; 177 | vec2 brdf = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_brdf), vec2( cN_V, roughness ) ).yx; 178 | vec3 specular = prefilteredColor * (F * brdf.x + brdf.y); 179 | 180 | vec3 color = (kD*diffuse + specular); 181 | #else 182 | vec3 color = 0.03*base; // ambient 183 | #endif 184 | 185 | #ifdef GLFX_LIGHTS 186 | float ggx2 = geometry_schlick_GGX( cN_V, roughness ); 187 | for( int i = 0; i != 2 /*assume that lights.length() was called.*/; ++i ) 188 | { 189 | vec3 L = lights[i].xyz; 190 | float lwrap = lights[i].w; 191 | vec3 H = normalize( V + L ); 192 | float N_L = dot( N, L ); 193 | float cN_L = max( 0., N_L ); 194 | float cN_H = max( 0., dot( N, H ) ); 195 | float cH_V = max( 0., dot( H, V ) ); 196 | 197 | float NDF = distribution_GGX( cN_H, roughness ); 198 | float G = geometry_smith( cN_L, ggx2, roughness ); 199 | vec3 F_light = fresnel_schlick( cH_V, F0 ); 200 | 201 | vec3 specular = NDF*G*F_light/( 4.*cN_V*cN_L + 0.001 ); 202 | 203 | vec3 kD_light = ( 1. - F_light )*( 1. - metallic ); 204 | 205 | color += ( kD_light*base/3.14159265 + specular )*radiance[i]*diffuse_factor( N_L, lwrap )/*cN_L*/; 206 | } 207 | #endif 208 | 209 | #ifdef GLFX_AO 210 | #ifdef GLFX_TEX_MRAO 211 | color *= mrao.z; 212 | #else 213 | color *= BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_ao),var_uv).x; 214 | #endif 215 | #endif 216 | 217 | #ifdef GLFX_TEX_EMI 218 | color += g2l(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_emi),var_uv).xyz); 219 | #endif 220 | 221 | #ifdef BNB_USE_SHADOW 222 | 223 | color = mix( color, vec3(0.), glfx_shadow_factor() ); 224 | #endif 225 | 226 | bnb_FragColor = vec4(l2g(color),opacity); 227 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/shaders/PineappleGlasses.vert: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define bnb_IDX_OFFSET 0 5 | #ifdef BNB_VK_1 6 | #ifdef gl_VertexID 7 | #undef gl_VertexID 8 | #endif 9 | #ifdef gl_InstanceID 10 | #undef gl_InstanceID 11 | #endif 12 | #define gl_VertexID gl_VertexIndex 13 | #define gl_InstanceID gl_InstanceIndex 14 | #endif 15 | 16 | 17 | #define GLFX_IBL 18 | #define GLFX_TBN 19 | #define GLFX_TEX_MRAO 20 | #define GLFX_LIGHTING 21 | 22 | BNB_LAYOUT_LOCATION(0) BNB_IN vec3 attrib_pos; 23 | #ifdef GLFX_LIGHTING 24 | #ifdef BNB_VK_1 25 | BNB_LAYOUT_LOCATION(1) BNB_IN uint attrib_n; 26 | #else 27 | BNB_LAYOUT_LOCATION(1) BNB_IN vec4 attrib_n; 28 | #endif 29 | #ifdef GLFX_TBN 30 | #ifdef BNB_VK_1 31 | BNB_LAYOUT_LOCATION(2) BNB_IN uint attrib_t; 32 | #else 33 | BNB_LAYOUT_LOCATION(2) BNB_IN vec4 attrib_t; 34 | #endif 35 | #endif 36 | #endif 37 | BNB_LAYOUT_LOCATION(3) BNB_IN vec2 attrib_uv; 38 | #ifndef BNB_GL_ES_1 39 | BNB_LAYOUT_LOCATION(4) BNB_IN uvec4 attrib_bones; 40 | #else 41 | BNB_LAYOUT_LOCATION(4) BNB_IN vec4 attrib_bones; 42 | #endif 43 | #ifndef BNB_1_BONE 44 | BNB_LAYOUT_LOCATION(5) BNB_IN vec4 attrib_weights; 45 | #endif 46 | 47 | 48 | 49 | BNB_DECLARE_SAMPLER_2D(12, 13, bnb_BONES); 50 | 51 | #ifdef BNB_USE_UVMORPH 52 | 53 | BNB_DECLARE_SAMPLER_2D(14, 15, bnb_UVMORPH); 54 | #ifdef GLFX_USE_BG 55 | 56 | BNB_DECLARE_SAMPLER_2D(16, 17, bnb_STATICPOS); 57 | #endif 58 | #endif 59 | 60 | #ifdef GLFX_USE_BG 61 | BNB_OUT(6) vec2 var_bg_uv; 62 | #endif 63 | 64 | #ifdef BNB_USE_AUTOMORPH 65 | 66 | BNB_DECLARE_SAMPLER_2D(18, 19, bnb_MORPH); 67 | #ifndef BNB_AUTOMORPH_BONE 68 | #else 69 | #endif 70 | #endif 71 | 72 | BNB_OUT(0) vec2 var_uv; 73 | #ifdef GLFX_LIGHTING 74 | #ifdef GLFX_TBN 75 | BNB_OUT(1) vec3 var_t; 76 | BNB_OUT(2) vec3 var_b; 77 | #endif 78 | BNB_OUT(3) vec3 var_n; 79 | BNB_OUT(4) vec3 var_v; 80 | #endif 81 | 82 | #ifdef BNB_USE_SHADOW 83 | 84 | BNB_OUT(5) vec3 var_shadow_coord; 85 | vec3 spherical_proj( vec2 fovM, vec2 fovP, float zn, float zf, vec3 v ) 86 | { 87 | vec2 xy = (atan( v.xy, v.zz )-(fovP+fovM)*0.5)/((fovP-fovM)*0.5); 88 | float z = (length(v)-(zn+zf)*0.5)/((zf-zn)*0.5); 89 | return vec3( xy, z ); 90 | } 91 | #endif 92 | 93 | 94 | #include 95 | #include 96 | void main() 97 | { 98 | mat4 m = bnb_get_bone( 99 | #ifdef BNB_GL_ES_1 100 | (float(attrib_bones[0]) * 3. + 0.5) * (1. / (bnb_ANIM.z * 3.)), 1. / (bnb_ANIM.z * 3.), bnb_ANIMKEY 101 | #else 102 | attrib_bones[0], int(bnb_ANIMKEY) 103 | #endif 104 | ); 105 | #ifndef BNB_1_BONE 106 | if( attrib_weights[1] > 0. ) 107 | { 108 | m = m*attrib_weights[0] + bnb_get_bone( 109 | #ifdef BNB_GL_ES_1 110 | (float(attrib_bones[1]) * 3. + 0.5) * (1. / (bnb_ANIM.z * 3.)), 1. / (bnb_ANIM.z * 3.), bnb_ANIMKEY 111 | #else 112 | attrib_bones[1], int(bnb_ANIMKEY) 113 | #endif 114 | )*attrib_weights[1]; 115 | if( attrib_weights[2] > 0. ) 116 | { 117 | m += bnb_get_bone( 118 | #ifdef BNB_GL_ES_1 119 | (float(attrib_bones[2]) * 3. + 0.5) * (1. / (bnb_ANIM.z * 3.)), 1. / (bnb_ANIM.z * 3.), bnb_ANIMKEY 120 | #else 121 | attrib_bones[2], int(bnb_ANIMKEY) 122 | #endif 123 | )*attrib_weights[2]; 124 | if( attrib_weights[3] > 0. ) 125 | m += bnb_get_bone( 126 | #ifdef BNB_GL_ES_1 127 | (float(attrib_bones[3]) * 3. + 0.5) * (1. / (bnb_ANIM.z * 3.)), 1. / (bnb_ANIM.z * 3.), bnb_ANIMKEY 128 | #else 129 | attrib_bones[3], int(bnb_ANIMKEY) 130 | #endif 131 | )*attrib_weights[3]; 132 | } 133 | } 134 | #endif 135 | 136 | vec3 vpos = attrib_pos; 137 | 138 | #ifdef BNB_USE_UVMORPH 139 | #ifndef BNB_VK_1 140 | vec2 flip_uv = vec2( attrib_uv.x, 1. - attrib_uv.y ); 141 | #else 142 | vec2 flip_uv = vec2( attrib_uv.xy ); 143 | #endif 144 | 145 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_UVMORPH),flip_uv).xyz; 146 | #ifdef GLFX_UVMORPH_Z_UP 147 | vpos += vec3(translation.x,-translation.z,translation.y); 148 | #else 149 | vpos += translation; 150 | #endif 151 | #endif 152 | 153 | vpos = vec3(vec4(vpos,1.)*m); 154 | 155 | #ifdef BNB_USE_AUTOMORPH 156 | #ifndef BNB_AUTOMORPH_BONE 157 | vpos = bnb_auto_morph( vpos ); 158 | #else 159 | vpos = bnb_auto_morph( vpos, m ); 160 | #endif 161 | #endif 162 | 163 | gl_Position = bnb_MVP * vec4(vpos,1.); 164 | 165 | #ifdef GLFX_USE_BG 166 | #ifdef BNB_USE_UVMORPH 167 | vec4 uvmorphed_view = bnb_MVP * vec4( BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_STATICPOS),flip_uv).xyz + translation, 1. ); 168 | #ifndef BNB_VK_1 169 | var_bg_uv = (uvmorphed_view.xy/uvmorphed_view.w)*0.5 + 0.5; 170 | #else 171 | var_bg_uv = (uvmorphed_view.xy/uvmorphed_view.w)*0.5 + 0.5; 172 | var_bg_uv.y = 1. - var_bg_uv.y; 173 | #endif 174 | 175 | #else 176 | var_bg_uv = (gl_Position.xy/gl_Position.w)*0.5 + 0.5; 177 | #endif 178 | #endif 179 | 180 | var_uv = attrib_uv; 181 | 182 | #ifdef GLFX_LIGHTING 183 | var_n = mat3(bnb_MV)*(bnb_decode_int1010102(attrib_n).xyz*mat3(m)); 184 | #ifdef GLFX_TBN 185 | var_t = mat3(bnb_MV)*(bnb_decode_int1010102(attrib_t).xyz*mat3(m)); 186 | var_b = bnb_decode_int1010102(attrib_t).w*cross( var_n, var_t ); 187 | #endif 188 | var_v = (bnb_MV*vec4(vpos,1.)).xyz; 189 | #endif 190 | 191 | #ifdef BNB_USE_SHADOW 192 | 193 | var_shadow_coord = spherical_proj( 194 | vec2(-radians(60.),-radians(20.)),vec2(radians(60.),radians(100.)), 195 | 400.,70., 196 | vpos+vec3(0.,100.,50.))*0.5+0.5; 197 | #endif 198 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/shaders/backgroundSeparation.frag: -------------------------------------------------------------------------------- 1 | #include 2 | #define USE_BG_NN 3 | BNB_IN(0) vec2 var_uv; 4 | 5 | #ifdef USE_BG_NN 6 | BNB_IN(1) vec2 var_bg_mask_uv; 7 | BNB_DECLARE_SAMPLER_2D(2, 3, s_segmentation_mask); 8 | BNB_DECLARE_SAMPLER_2D(4, 5, s_bg_texture); 9 | #endif 10 | 11 | BNB_DECLARE_SAMPLER_VIDEO(0, 1, tex_src); 12 | 13 | #ifdef USE_BG_NN 14 | vec4 cubic(float v) 15 | { 16 | vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v; 17 | vec4 s = n * n * n; 18 | float x = s.x; 19 | float y = s.y - 4.0 * s.x; 20 | float z = s.z - 4.0 * s.y + 6.0 * s.x; 21 | float w = 6.0 - x - y - z; 22 | return vec4(x, y, z, w) * (1.0/6.0); 23 | } 24 | 25 | vec2 rgb_hs( vec3 rgb ) 26 | { 27 | float cmax = max(rgb.r, max(rgb.g, rgb.b)); 28 | float cmin = min(rgb.r, min(rgb.g, rgb.b)); 29 | float delta = cmax - cmin; 30 | vec2 hs = vec2(0.); 31 | if( cmax > cmin ) 32 | { 33 | hs.y = delta/cmax; 34 | if( rgb.r == cmax ) 35 | hs.x = (rgb.g-rgb.b)/delta; 36 | else 37 | { 38 | if( rgb.g == cmax ) 39 | hs.x = 2.+(rgb.b-rgb.r)/delta; 40 | else 41 | hs.x = 4.+(rgb.r-rgb.g)/delta; 42 | } 43 | hs.x = fract(hs.x/6.); 44 | } 45 | return hs; 46 | } 47 | 48 | float rgb_v( vec3 rgb ) 49 | { 50 | return max(rgb.r, max(rgb.g, rgb.b)); 51 | } 52 | 53 | vec3 hsv_rgb( float h, float s, float v ) 54 | { 55 | return v*mix(vec3(1.),clamp(abs(fract(vec3(1.,2./3.,1./3.)+h)*6.-3.)-1.,0.,1.),s); 56 | } 57 | 58 | vec3 blendColor(vec3 base, vec3 blend) 59 | { 60 | float v = rgb_v( base ); 61 | vec2 hs = rgb_hs( blend ); 62 | return hsv_rgb( hs.x, hs.y, v ); 63 | } 64 | 65 | vec3 blendColor(vec3 base, vec3 blend, float opacity) 66 | { 67 | return (blendColor(base, blend) * opacity + base * (1.0 - opacity)); 68 | } 69 | #endif 70 | void main() 71 | { 72 | vec2 uv = var_uv; 73 | uv.x *= 0.5; 74 | vec3 rgb = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_src), uv).rgb; 75 | uv.x += 0.5; 76 | float a = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_src), uv).r; 77 | rgb *= a; 78 | #ifdef USE_BG_NN 79 | const float threshold = 0.2; 80 | 81 | vec2 texSize = background_nn_meta.xy; 82 | vec2 invTexSize = 1.0 / texSize; 83 | 84 | vec2 texCoords = var_bg_mask_uv * texSize - 0.5; 85 | 86 | vec2 fxy = fract(texCoords); 87 | texCoords -= fxy; 88 | 89 | vec4 xcubic = cubic(fxy.x); 90 | vec4 ycubic = cubic(fxy.y); 91 | 92 | vec4 c = texCoords.xxyy + vec2(-0.5, +1.5).xyxy; 93 | 94 | vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw); 95 | vec4 offset = c + vec4(xcubic.yw, ycubic.yw) / s; 96 | 97 | offset *= invTexSize.xxyy; 98 | 99 | vec4 sample0 = BNB_TEXTURE_2D(BNB_SAMPLER_2D(s_segmentation_mask), offset.xz); 100 | vec4 sample1 = BNB_TEXTURE_2D(BNB_SAMPLER_2D(s_segmentation_mask), offset.yz); 101 | vec4 sample2 = BNB_TEXTURE_2D(BNB_SAMPLER_2D(s_segmentation_mask), offset.xw); 102 | vec4 sample3 = BNB_TEXTURE_2D(BNB_SAMPLER_2D(s_segmentation_mask), offset.yw); 103 | 104 | float sx = s.x / (s.x + s.y); 105 | float sy = s.z / (s.z + s.w); 106 | 107 | vec4 filtered_mask = mix(mix(sample3, sample2, sx), mix(sample1, sample0, sx), sy); 108 | rgb = mix(BNB_TEXTURE_2D(BNB_SAMPLER_2D(s_bg_texture), var_uv).rgb, rgb, filtered_mask.r); 109 | #endif 110 | rgb *= filtered_mask.r; 111 | bnb_FragColor = vec4(rgb, 1.0); 112 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/shaders/backgroundSeparation.vert: -------------------------------------------------------------------------------- 1 | #include 2 | #define USE_BG_NN 3 | BNB_LAYOUT_LOCATION(0) BNB_IN vec2 attrib_pos; 4 | 5 | BNB_OUT(0) vec2 var_uv; 6 | 7 | #ifdef USE_BG_NN 8 | BNB_OUT(1) vec2 var_bg_mask_uv; 9 | #endif 10 | 11 | void main() 12 | { 13 | vec2 v = attrib_pos; 14 | gl_Position = vec4(v, 0., 1.); 15 | var_uv = v * 0.5 + 0.5; 16 | //#ifdef BNB_VK_1 17 | var_uv.y = 1. - var_uv.y; 18 | //#endif 19 | 20 | #ifdef USE_BG_NN 21 | vec4 uv = vec4(v,1.,1.)*background_nn_transform; 22 | var_bg_mask_uv = uv.xy; 23 | #endif 24 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/shaders/finalColorFilter.fsh.frag: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | BNB_IN(0) vec2 var_uv; 4 | 5 | BNB_DECLARE_SAMPLER_2D(0, 1, s_src); 6 | 7 | 8 | BNB_DECLARE_SAMPLER_2D(2, 3, lookupTexture); 9 | 10 | vec4 finalColorFilter(vec4 orgColor) 11 | { 12 | const float EPS = 0.000001; 13 | const float pxSize = 512.0; 14 | 15 | float bValue = (orgColor.b * 255.0) / 4.0; 16 | 17 | vec2 mulB = clamp(floor(bValue) + vec2(0.0, 1.0), 0.0, 63.0); 18 | vec2 row = floor(mulB / 8.0 + EPS); 19 | vec4 row_col = vec4(row, mulB - row * 8.0); 20 | vec4 lookup = orgColor.ggrr * (63.0/pxSize) + row_col * (64.0/pxSize) + (0.5/pxSize); 21 | 22 | float b1w = bValue - mulB.x; 23 | 24 | vec3 sampled1 = BNB_TEXTURE_2D(BNB_SAMPLER_2D(lookupTexture), lookup.zx).rgb; 25 | vec3 sampled2 = BNB_TEXTURE_2D(BNB_SAMPLER_2D(lookupTexture), lookup.wy).rgb; 26 | 27 | vec3 res = mix(sampled1, sampled2, b1w); 28 | return vec4(res, orgColor.a); 29 | } 30 | 31 | 32 | void main() 33 | { 34 | bnb_FragColor = finalColorFilter(BNB_TEXTURE_2D(BNB_SAMPLER_2D(s_src), var_uv)); 35 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/shaders/finalColorFilter.fsh.vert: -------------------------------------------------------------------------------- 1 | #include 2 | BNB_LAYOUT_LOCATION(0) BNB_IN vec2 attrib_pos; 3 | 4 | BNB_OUT(0) vec2 var_uv; 5 | 6 | void main() 7 | { 8 | vec2 v = attrib_pos; 9 | gl_Position = vec4(v, 0., 1.); 10 | var_uv = v * 0.5 + 0.5; 11 | #ifdef BNB_VK_1 12 | var_uv.y = 1. - var_uv.y; 13 | #endif 14 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/shaders/glass.frag: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #define GLFX_IBL 5 | #define GLFX_TBN 6 | #define GLFX_TEX_MRAO 7 | #define GLFX_LIGHTING 8 | 9 | BNB_IN(0) vec2 var_uv; 10 | #ifdef GLFX_TBN 11 | BNB_IN(1) vec3 var_t; 12 | BNB_IN(2) vec3 var_b; 13 | #endif 14 | BNB_IN(3) vec3 var_n; 15 | BNB_IN(4) vec3 var_v; 16 | 17 | 18 | 19 | BNB_DECLARE_SAMPLER_2D(0, 1, tex_diffuse); 20 | #ifdef GLFX_TBN 21 | 22 | BNB_DECLARE_SAMPLER_2D(2, 3, tex_normal); 23 | #endif 24 | #ifdef GLFX_TEX_MRAO 25 | 26 | BNB_DECLARE_SAMPLER_2D(10, 11, tex_mrao); 27 | #else 28 | #ifdef GLFX_AO 29 | #endif 30 | #endif 31 | #ifdef GLFX_TEX_EMI 32 | #endif 33 | 34 | #ifdef BNB_USE_SHADOW 35 | 36 | BNB_IN(5) vec3 var_shadow_coord; 37 | float glfx_shadow_factor() 38 | { 39 | 40 | vec2 offsets[4]; 41 | offsets[0] = vec2( -0.94201624, -0.39906216 ); 42 | offsets[1] = vec2( 0.94558609, -0.76890725 ); 43 | offsets[2] = vec2( -0.094184101, -0.92938870 ); 44 | offsets[3] = vec2( 0.34495938, 0.29387760 ); 45 | float s = 0.; 46 | for( int i = 0; i != 4 /*assume that offsets.length() was called.*/; ++i ) 47 | s += texture( glfx_SHADOW, var_shadow_coord + vec3(offsets[i]/110.,0.1) ); 48 | s *= 0.125; 49 | return s; 50 | } 51 | #endif 52 | 53 | // gamma to linear 54 | vec3 g2l( vec3 g ) 55 | { 56 | return g*(g*(g*0.305306011+0.682171111)+0.012522878); 57 | } 58 | 59 | // combined hdr to ldr and linear to gamma 60 | vec3 l2g( vec3 l ) 61 | { 62 | return sqrt(1.33*(1.-exp(-l)))-0.03; 63 | } 64 | 65 | vec3 fresnel_schlick( float prod, vec3 F0 ) 66 | { 67 | return F0 + ( 1. - F0 )*pow( 1. - prod, 5. ); 68 | } 69 | 70 | vec3 fresnel_schlick_roughness( float prod, vec3 F0, float roughness ) 71 | { 72 | return F0 + ( max( F0, 1. - roughness ) - F0 )*pow( 1. - prod, 5. ); 73 | } 74 | 75 | float distribution_GGX( float cN_H, float roughness ) 76 | { 77 | float a = roughness*roughness; 78 | float a2 = a*a; 79 | float d = cN_H*cN_H*( a2 - 1. ) + 1.; 80 | return a2/(3.14159265*d*d); 81 | } 82 | 83 | float geometry_schlick_GGX( float NV, float roughness ) 84 | { 85 | float r = roughness + 1.; 86 | float k = r*r/8.; 87 | return NV/( NV*( 1. - k ) + k ); 88 | } 89 | 90 | float geometry_smith( float cN_L, float ggx2, float roughness ) 91 | { 92 | return geometry_schlick_GGX( cN_L, roughness )*ggx2; 93 | } 94 | 95 | float diffuse_factor( float n_l, float w ) 96 | { 97 | float w1 = 1. + w; 98 | return pow( max( 0., n_l + w )/w1, w1 ); 99 | } 100 | 101 | #ifdef GLFX_IBL 102 | 103 | BNB_DECLARE_SAMPLER_2D(4, 5, tex_brdf); 104 | 105 | BNB_DECLARE_SAMPLER_CUBE(6, 7, tex_ibl_diff); 106 | 107 | BNB_DECLARE_SAMPLER_CUBE(8, 9, tex_ibl_spec); 108 | #endif 109 | 110 | #ifdef GLFX_LIGHTS 111 | // direction in xyz, lwrap in w 112 | #endif 113 | 114 | void main() 115 | { 116 | #ifdef GLFX_LIGHTS 117 | vec3 radiance[2]; 118 | radiance[1] = vec3(1.,1.,1.)*0.9*2.; 119 | radiance[0] = vec3(1.,1.,1.)*2.; 120 | #endif 121 | #ifdef GLFX_LIGHTS 122 | vec4 lights[2]; 123 | lights[1] = vec4(normalize(vec3(97.6166,-48.185,183.151)),1.); 124 | lights[0] = vec4(0.,0.6,0.8,1.); 125 | #endif 126 | vec4 base_opacity = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_diffuse),var_uv); 127 | 128 | //if( base_opacity.w < 0.5 ) discard; 129 | 130 | vec3 base = g2l(base_opacity.xyz); 131 | float opacity = base_opacity.w; 132 | #ifdef GLFX_TEX_MRAO 133 | vec3 mrao = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_mrao),var_uv).xyz; 134 | #ifdef GLFX_DIELECTRIC 135 | float metallic = 0.; 136 | #else 137 | float metallic = mrao.x; 138 | #endif 139 | float roughness = mrao.y; 140 | #else 141 | #ifdef GLFX_DIELECTRIC 142 | float metallic = 0.; 143 | #else 144 | float metallic = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_metallic),var_uv).x; 145 | #endif 146 | float roughness = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_roughness),var_uv).x; 147 | #endif 148 | 149 | #ifdef GLFX_TBN 150 | #ifdef GLFX_NORMAL_DIRECTX 151 | vec3 N = normalize( mat3(var_t,var_b,var_n)*(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normal),var_uv).xyz*vec3(2.,-2.,2.)-vec3(1.,-1.,1.)) ); 152 | #else 153 | vec3 N = normalize( mat3(var_t,var_b,var_n)*(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normal),var_uv).xyz*2.-1.) ); 154 | #endif 155 | #else 156 | vec3 N = normalize( var_n ); 157 | #endif 158 | 159 | #ifdef GLFX_2SIDED 160 | N *= gl_FrontFacing ? 1. : -1.; 161 | #endif 162 | 163 | vec3 V = normalize( -var_v ); 164 | float cN_V = max( 0., dot( N, V ) ); 165 | vec3 R = reflect( -V, N ); 166 | 167 | vec3 F0 = mix( vec3(0.04), base, metallic ); 168 | 169 | #ifdef GLFX_IBL 170 | vec3 F = fresnel_schlick_roughness( cN_V, F0, roughness ); 171 | vec3 kD = ( 1. - F )*( 1. - metallic ); 172 | 173 | vec3 diffuse = BNB_TEXTURE_CUBE(BNB_SAMPLER_CUBE(tex_ibl_diff), N ).xyz * base; 174 | 175 | const float MAX_REFLECTION_LOD = 7.; // number of mip levels in tex_ibl_spec 176 | vec3 prefilteredColor = BNB_TEXTURE_CUBE_LOD(BNB_SAMPLER_CUBE(tex_ibl_spec), R, roughness*MAX_REFLECTION_LOD ).xyz; 177 | vec2 brdf = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_brdf), vec2( cN_V, roughness ) ).yx; 178 | vec3 specular = prefilteredColor * (F * brdf.x + brdf.y); 179 | 180 | vec3 color = (kD*diffuse + specular); 181 | #else 182 | vec3 color = 0.03*base; // ambient 183 | #endif 184 | 185 | #ifdef GLFX_LIGHTS 186 | float ggx2 = geometry_schlick_GGX( cN_V, roughness ); 187 | for( int i = 0; i != 2 /*assume that lights.length() was called.*/; ++i ) 188 | { 189 | vec3 L = lights[i].xyz; 190 | float lwrap = lights[i].w; 191 | vec3 H = normalize( V + L ); 192 | float N_L = dot( N, L ); 193 | float cN_L = max( 0., N_L ); 194 | float cN_H = max( 0., dot( N, H ) ); 195 | float cH_V = max( 0., dot( H, V ) ); 196 | 197 | float NDF = distribution_GGX( cN_H, roughness ); 198 | float G = geometry_smith( cN_L, ggx2, roughness ); 199 | vec3 F_light = fresnel_schlick( cH_V, F0 ); 200 | 201 | vec3 specular = NDF*G*F_light/( 4.*cN_V*cN_L + 0.001 ); 202 | 203 | vec3 kD_light = ( 1. - F_light )*( 1. - metallic ); 204 | 205 | color += ( kD_light*base/3.14159265 + specular )*radiance[i]*diffuse_factor( N_L, lwrap )/*cN_L*/; 206 | } 207 | #endif 208 | 209 | #ifdef GLFX_AO 210 | #ifdef GLFX_TEX_MRAO 211 | color *= mrao.z; 212 | #else 213 | color *= BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_ao),var_uv).x; 214 | #endif 215 | #endif 216 | 217 | #ifdef GLFX_TEX_EMI 218 | color += g2l(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_emi),var_uv).xyz); 219 | #endif 220 | 221 | #ifdef BNB_USE_SHADOW 222 | 223 | color = mix( color, vec3(0.), glfx_shadow_factor() ); 224 | #endif 225 | 226 | bnb_FragColor = vec4(l2g(color),opacity); 227 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/shaders/glass.vert: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define bnb_IDX_OFFSET 0 5 | #ifdef BNB_VK_1 6 | #ifdef gl_VertexID 7 | #undef gl_VertexID 8 | #endif 9 | #ifdef gl_InstanceID 10 | #undef gl_InstanceID 11 | #endif 12 | #define gl_VertexID gl_VertexIndex 13 | #define gl_InstanceID gl_InstanceIndex 14 | #endif 15 | 16 | 17 | #define GLFX_IBL 18 | #define GLFX_TBN 19 | #define GLFX_TEX_MRAO 20 | #define GLFX_LIGHTING 21 | 22 | BNB_LAYOUT_LOCATION(0) BNB_IN vec3 attrib_pos; 23 | #ifdef GLFX_LIGHTING 24 | #ifdef BNB_VK_1 25 | BNB_LAYOUT_LOCATION(1) BNB_IN uint attrib_n; 26 | #else 27 | BNB_LAYOUT_LOCATION(1) BNB_IN vec4 attrib_n; 28 | #endif 29 | #ifdef GLFX_TBN 30 | #ifdef BNB_VK_1 31 | BNB_LAYOUT_LOCATION(2) BNB_IN uint attrib_t; 32 | #else 33 | BNB_LAYOUT_LOCATION(2) BNB_IN vec4 attrib_t; 34 | #endif 35 | #endif 36 | #endif 37 | BNB_LAYOUT_LOCATION(3) BNB_IN vec2 attrib_uv; 38 | #ifndef BNB_GL_ES_1 39 | BNB_LAYOUT_LOCATION(4) BNB_IN uvec4 attrib_bones; 40 | #else 41 | BNB_LAYOUT_LOCATION(4) BNB_IN vec4 attrib_bones; 42 | #endif 43 | #ifndef BNB_1_BONE 44 | BNB_LAYOUT_LOCATION(5) BNB_IN vec4 attrib_weights; 45 | #endif 46 | 47 | 48 | 49 | BNB_DECLARE_SAMPLER_2D(12, 13, bnb_BONES); 50 | 51 | #ifdef BNB_USE_UVMORPH 52 | 53 | BNB_DECLARE_SAMPLER_2D(14, 15, bnb_UVMORPH); 54 | #ifdef GLFX_USE_BG 55 | 56 | BNB_DECLARE_SAMPLER_2D(16, 17, bnb_STATICPOS); 57 | #endif 58 | #endif 59 | 60 | #ifdef GLFX_USE_BG 61 | BNB_OUT(6) vec2 var_bg_uv; 62 | #endif 63 | 64 | #ifdef BNB_USE_AUTOMORPH 65 | 66 | BNB_DECLARE_SAMPLER_2D(18, 19, bnb_MORPH); 67 | #ifndef BNB_AUTOMORPH_BONE 68 | #else 69 | #endif 70 | #endif 71 | 72 | BNB_OUT(0) vec2 var_uv; 73 | #ifdef GLFX_LIGHTING 74 | #ifdef GLFX_TBN 75 | BNB_OUT(1) vec3 var_t; 76 | BNB_OUT(2) vec3 var_b; 77 | #endif 78 | BNB_OUT(3) vec3 var_n; 79 | BNB_OUT(4) vec3 var_v; 80 | #endif 81 | 82 | #ifdef BNB_USE_SHADOW 83 | 84 | BNB_OUT(5) vec3 var_shadow_coord; 85 | vec3 spherical_proj( vec2 fovM, vec2 fovP, float zn, float zf, vec3 v ) 86 | { 87 | vec2 xy = (atan( v.xy, v.zz )-(fovP+fovM)*0.5)/((fovP-fovM)*0.5); 88 | float z = (length(v)-(zn+zf)*0.5)/((zf-zn)*0.5); 89 | return vec3( xy, z ); 90 | } 91 | #endif 92 | 93 | 94 | #include 95 | #include 96 | void main() 97 | { 98 | mat4 m = bnb_get_bone( 99 | #ifdef BNB_GL_ES_1 100 | (float(attrib_bones[0]) * 3. + 0.5) * (1. / (bnb_ANIM.z * 3.)), 1. / (bnb_ANIM.z * 3.), bnb_ANIMKEY 101 | #else 102 | attrib_bones[0], int(bnb_ANIMKEY) 103 | #endif 104 | ); 105 | #ifndef BNB_1_BONE 106 | if( attrib_weights[1] > 0. ) 107 | { 108 | m = m*attrib_weights[0] + bnb_get_bone( 109 | #ifdef BNB_GL_ES_1 110 | (float(attrib_bones[1]) * 3. + 0.5) * (1. / (bnb_ANIM.z * 3.)), 1. / (bnb_ANIM.z * 3.), bnb_ANIMKEY 111 | #else 112 | attrib_bones[1], int(bnb_ANIMKEY) 113 | #endif 114 | )*attrib_weights[1]; 115 | if( attrib_weights[2] > 0. ) 116 | { 117 | m += bnb_get_bone( 118 | #ifdef BNB_GL_ES_1 119 | (float(attrib_bones[2]) * 3. + 0.5) * (1. / (bnb_ANIM.z * 3.)), 1. / (bnb_ANIM.z * 3.), bnb_ANIMKEY 120 | #else 121 | attrib_bones[2], int(bnb_ANIMKEY) 122 | #endif 123 | )*attrib_weights[2]; 124 | if( attrib_weights[3] > 0. ) 125 | m += bnb_get_bone( 126 | #ifdef BNB_GL_ES_1 127 | (float(attrib_bones[3]) * 3. + 0.5) * (1. / (bnb_ANIM.z * 3.)), 1. / (bnb_ANIM.z * 3.), bnb_ANIMKEY 128 | #else 129 | attrib_bones[3], int(bnb_ANIMKEY) 130 | #endif 131 | )*attrib_weights[3]; 132 | } 133 | } 134 | #endif 135 | 136 | vec3 vpos = attrib_pos; 137 | 138 | #ifdef BNB_USE_UVMORPH 139 | #ifndef BNB_VK_1 140 | vec2 flip_uv = vec2( attrib_uv.x, 1. - attrib_uv.y ); 141 | #else 142 | vec2 flip_uv = vec2( attrib_uv.xy ); 143 | #endif 144 | 145 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_UVMORPH),flip_uv).xyz; 146 | #ifdef GLFX_UVMORPH_Z_UP 147 | vpos += vec3(translation.x,-translation.z,translation.y); 148 | #else 149 | vpos += translation; 150 | #endif 151 | #endif 152 | 153 | vpos = vec3(vec4(vpos,1.)*m); 154 | 155 | #ifdef BNB_USE_AUTOMORPH 156 | #ifndef BNB_AUTOMORPH_BONE 157 | vpos = bnb_auto_morph( vpos ); 158 | #else 159 | vpos = bnb_auto_morph( vpos, m ); 160 | #endif 161 | #endif 162 | 163 | gl_Position = bnb_MVP * vec4(vpos,1.); 164 | 165 | #ifdef GLFX_USE_BG 166 | #ifdef BNB_USE_UVMORPH 167 | vec4 uvmorphed_view = bnb_MVP * vec4( BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_STATICPOS),flip_uv).xyz + translation, 1. ); 168 | #ifndef BNB_VK_1 169 | var_bg_uv = (uvmorphed_view.xy/uvmorphed_view.w)*0.5 + 0.5; 170 | #else 171 | var_bg_uv = (uvmorphed_view.xy/uvmorphed_view.w)*0.5 + 0.5; 172 | var_bg_uv.y = 1. - var_bg_uv.y; 173 | #endif 174 | 175 | #else 176 | var_bg_uv = (gl_Position.xy/gl_Position.w)*0.5 + 0.5; 177 | #endif 178 | #endif 179 | 180 | var_uv = attrib_uv; 181 | 182 | #ifdef GLFX_LIGHTING 183 | var_n = mat3(bnb_MV)*(bnb_decode_int1010102(attrib_n).xyz*mat3(m)); 184 | #ifdef GLFX_TBN 185 | var_t = mat3(bnb_MV)*(bnb_decode_int1010102(attrib_t).xyz*mat3(m)); 186 | var_b = bnb_decode_int1010102(attrib_t).w*cross( var_n, var_t ); 187 | #endif 188 | var_v = (bnb_MV*vec4(vpos,1.)).xyz; 189 | #endif 190 | 191 | #ifdef BNB_USE_SHADOW 192 | 193 | var_shadow_coord = spherical_proj( 194 | vec2(-radians(60.),-radians(20.)),vec2(radians(60.),radians(100.)), 195 | 400.,70., 196 | vpos+vec3(0.,100.,50.))*0.5+0.5; 197 | #endif 198 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/shaders/retouch.frag: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define TEETH_WHITENING 4 | #define teethWhiteningCoeff 1.0 5 | #define EYES_WHITENING 6 | #define eyesWhiteningCoeff 0.5 7 | #define EYES_HIGHLIGHT 8 | #define SOFT_LIGHT_LAYER 9 | #define NORMAL_LAYER 10 | #define SOFT_SKIN 11 | #define skinSoftIntensity 0.7 12 | #define SHARPEN_TEETH 13 | #define teethSharpenIntensity 0.2 14 | #define SHARPEN_EYES 15 | #define eyesSharpenIntensity 0.3 16 | #define PSI 0.1 17 | 18 | 19 | BNB_IN(0) vec2 var_uv; 20 | BNB_IN(1) vec2 var_bg_uv; 21 | BNB_IN(2) mat4 sp; 22 | 23 | 24 | BNB_DECLARE_SAMPLER_2D(0, 1, selection_tex); 25 | 26 | BNB_DECLARE_SAMPLER_2D(4, 5, lookupTexEyes); 27 | 28 | BNB_DECLARE_SAMPLER_2D(2, 3, lookupTexTeeth); 29 | 30 | BNB_DECLARE_SAMPLER_2D(12, 13, glfx_BACKGROUND); 31 | 32 | #if defined(EYES_HIGHLIGHT) 33 | 34 | BNB_DECLARE_SAMPLER_2D(10, 11, tex_highlight); 35 | #endif 36 | #ifdef SOFT_LIGHT_LAYER 37 | 38 | BNB_DECLARE_SAMPLER_2D(6, 7, tex_softLight); 39 | #endif 40 | #ifdef NORMAL_LAYER 41 | 42 | BNB_DECLARE_SAMPLER_2D(8, 9, tex_normalMakeup); 43 | #endif 44 | 45 | vec4 textureLookup(vec4 originalColor, BNB_DECLARE_SAMPLER_2D_ARGUMENT(lookupTexture)) 46 | { 47 | const float epsilon = 0.000001; 48 | const float lutSize = 512.0; 49 | 50 | float blueValue = (originalColor.b * 255.0) / 4.0; 51 | 52 | vec2 mulB = clamp(floor(blueValue) + vec2(0.0, 1.0), 0.0, 63.0); 53 | vec2 row = floor(mulB / 8.0 + epsilon); 54 | vec4 row_col = vec4(row, mulB - row * 8.0); 55 | vec4 lookup = originalColor.ggrr * (63.0 / lutSize) + row_col * (64.0 / lutSize) + (0.5 / lutSize); 56 | 57 | float factor = blueValue - mulB.x; 58 | 59 | vec3 sampled1 = BNB_TEXTURE_2D_LOD(BNB_SAMPLER_2D(lookupTexture), lookup.zx, 0.).rgb; 60 | vec3 sampled2 = BNB_TEXTURE_2D_LOD(BNB_SAMPLER_2D(lookupTexture), lookup.wy, 0.).rgb; 61 | 62 | vec3 res = mix(sampled1, sampled2, factor); 63 | return vec4(res, originalColor.a); 64 | } 65 | 66 | vec4 whitening(vec4 originalColor, float factor, BNB_DECLARE_SAMPLER_2D_ARGUMENT(lookup)) { 67 | vec4 color = textureLookup(originalColor, BNB_PASS_SAMPLER_ARGUMENT(lookup)); 68 | return mix(originalColor, color, factor); 69 | } 70 | 71 | vec4 sharpen(vec4 originalColor, float factor) { 72 | vec4 total = 5.0 * originalColor - BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[0].zw) - BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[1].zw) - BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[2].zw) - BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[3].zw); 73 | vec4 result = mix(originalColor, total, factor); 74 | return clamp(result, 0.0, 1.0);; 75 | } 76 | 77 | vec4 getLuminance4(mat4 color) { 78 | const vec4 rgb2y = vec4(0.299, 0.587, 0.114, 0.0); 79 | return rgb2y * color; 80 | } 81 | 82 | float getLuminance(vec4 color) { 83 | const vec4 rgb2y = vec4(0.299, 0.587, 0.114, 0.0); 84 | return dot(color, rgb2y); 85 | } 86 | 87 | vec4 getWeight(float intensity, vec4 nextIntensity) { 88 | vec4 lglg = log(nextIntensity / intensity) * log(nextIntensity / intensity); 89 | return exp(lglg / (-2.0 * PSI * PSI )); 90 | } 91 | 92 | vec4 softSkin(vec4 originalColor, float factor) { 93 | vec4 screenColor = originalColor; 94 | float intensity = getLuminance(screenColor); 95 | float summ = 1.0; 96 | 97 | mat4 nextColor; 98 | nextColor[0] = BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[0].xy); 99 | nextColor[1] = BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[1].xy); 100 | nextColor[2] = BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[2].xy); 101 | nextColor[3] = BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[3].xy); 102 | vec4 nextIntensity = getLuminance4(nextColor); 103 | vec4 curr = 0.367 * getWeight(intensity, nextIntensity); 104 | summ += dot(curr, vec4(1.0)); 105 | screenColor += nextColor * curr; 106 | screenColor = screenColor / summ; 107 | 108 | screenColor = mix(originalColor, screenColor, factor); 109 | return screenColor; 110 | } 111 | 112 | float blendSoftLight(float a, float b) { 113 | return (a+2.*b*(1.-a))*a; 114 | } 115 | 116 | vec3 blendSoftLight(vec3 base, vec3 blend) { 117 | return vec3(blendSoftLight(base.r,blend.r),blendSoftLight(base.g,blend.g),blendSoftLight(base.b,blend.b)); 118 | } 119 | 120 | vec3 blendSoftLight(vec3 base, vec3 blend, float opacity) { 121 | return (blendSoftLight(base, blend) * opacity + base * (1.0 - opacity)); 122 | } 123 | 124 | void main() 125 | { 126 | vec4 maskColor = BNB_TEXTURE_2D(BNB_SAMPLER_2D(selection_tex), var_uv); 127 | vec4 res = BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), var_bg_uv ); 128 | 129 | #ifdef SOFT_SKIN 130 | res = softSkin(res, maskColor.r * skinSoftIntensity); 131 | #endif 132 | 133 | #ifdef SKIN_TEXTURING 134 | vec4 skinTexture = texture(skin_tex, var_uv); 135 | vec4 diff = abs(skinTexture - res); 136 | res = mix(res, diff, skinTexturingIntensity); 137 | #endif 138 | 139 | #ifdef SHARPEN_TEETH 140 | res = sharpen(res, maskColor.g * teethSharpenIntensity); 141 | #endif 142 | 143 | #if defined(TEETH_WHITENING) 144 | res = whitening(res, maskColor.g * teethWhiteningCoeff, BNB_PASS_SAMPLER_ARGUMENT(lookupTexTeeth)); 145 | #endif 146 | 147 | 148 | #ifdef SHARPEN_EYES 149 | res = sharpen(res, maskColor.b * eyesSharpenIntensity); 150 | #endif 151 | 152 | #if defined(EYES_WHITENING) 153 | res = whitening(res, maskColor.b * eyesWhiteningCoeff, BNB_PASS_SAMPLER_ARGUMENT(lookupTexEyes)); 154 | #endif 155 | 156 | #if defined(EYES_HIGHLIGHT) 157 | res = res + vec4( BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_highlight), var_uv ).xyz, 0. ); 158 | #endif 159 | 160 | vec2 uvh = var_uv; 161 | uvh.x = abs(2.0 * (uvh.x - 0.5)); 162 | 163 | #ifdef SOFT_LIGHT_LAYER 164 | res.xyz = blendSoftLight( res.xyz, BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_softLight), uvh ).xyz ); 165 | #endif 166 | 167 | #ifdef NORMAL_LAYER 168 | vec4 makeup2 = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normalMakeup), uvh ); 169 | res.xyz = mix( res.xyz, makeup2.xyz, makeup2.w ); 170 | #endif 171 | 172 | bnb_FragColor = res; 173 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/shaders/retouch.vert: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define bnb_IDX_OFFSET 0 5 | #ifdef BNB_VK_1 6 | #ifdef gl_VertexID 7 | #undef gl_VertexID 8 | #endif 9 | #ifdef gl_InstanceID 10 | #undef gl_InstanceID 11 | #endif 12 | #define gl_VertexID gl_VertexIndex 13 | #define gl_InstanceID gl_InstanceIndex 14 | #endif 15 | 16 | BNB_LAYOUT_LOCATION(0) BNB_IN vec3 attrib_pos; 17 | BNB_LAYOUT_LOCATION(1) BNB_IN vec3 attrib_pos_static; 18 | BNB_LAYOUT_LOCATION(2) BNB_IN vec2 attrib_uv; 19 | BNB_LAYOUT_LOCATION(3) BNB_IN vec4 attrib_red_mask; 20 | 21 | 22 | BNB_OUT(0) vec2 var_uv; 23 | BNB_OUT(1) vec2 var_bg_uv; 24 | 25 | BNB_OUT(2) mat4 sp; 26 | 27 | invariant gl_Position; 28 | 29 | const float dx = 1.0 / 720.0; 30 | const float dy = 1.0 / 1280.0; 31 | 32 | const float delta = 5.; 33 | 34 | const float sOfssetXneg = -delta * dx; 35 | const float sOffsetYneg = -delta * dy; 36 | const float sOffsetXpos = delta * dx; 37 | const float sOffsetYpos = delta * dy; 38 | 39 | void main() 40 | { 41 | gl_Position = bnb_MVP * vec4( attrib_pos, 1. ); 42 | var_uv = attrib_uv; 43 | var_bg_uv = (gl_Position.xy / gl_Position.w) * 0.5 + 0.5; 44 | 45 | sp[0].xy = var_bg_uv + vec2(sOfssetXneg, sOffsetYneg); 46 | sp[1].xy = var_bg_uv + vec2(sOfssetXneg, sOffsetYpos); 47 | sp[2].xy = var_bg_uv + vec2(sOffsetXpos, sOffsetYneg); 48 | sp[3].xy = var_bg_uv + vec2(sOffsetXpos, sOffsetYpos); 49 | 50 | vec2 delta = vec2(dx, dy); 51 | sp[0].zw = var_bg_uv + vec2(-delta.x, -delta.y); 52 | sp[1].zw = var_bg_uv + vec2(delta.x, -delta.y); 53 | sp[2].zw = var_bg_uv + vec2(-delta.x, delta.y); 54 | sp[3].zw = var_bg_uv + vec2(delta.x, delta.y); 55 | 56 | #ifdef BNB_VK_1 57 | sp[0].y = 1. - sp[0].y; 58 | sp[1].y = 1. - sp[1].y; 59 | sp[2].y = 1. - sp[2].y; 60 | sp[3].y = 1. - sp[3].y; 61 | sp[0].w = 1. - sp[0].w; 62 | sp[1].w = 1. - sp[1].w; 63 | sp[2].w = 1. - sp[2].w; 64 | sp[3].w = 1. - sp[3].w; 65 | #endif 66 | #ifdef BNB_VK_1 67 | var_bg_uv.y = 1. - var_bg_uv.y; 68 | #endif 69 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/videos/Back_F.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/PineappleGlasses/videos/Back_F.mp4 -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/config.js: -------------------------------------------------------------------------------- 1 | function Effect() { 2 | var self = this; 3 | this.play = function() { 4 | now = (new Date()).getTime(); 5 | if (now > self.time) { 6 | Api.hideHint(); 7 | self.faceActions = []; 8 | } 9 | if(Api.isMouthOpen()) { 10 | Api.hideHint(); 11 | self.faceActions = []; 12 | }; 13 | }; 14 | 15 | this.init = function() { 16 | Api.meshfxMsg("spawn", 2, 0, "!glfx_FACE"); 17 | Api.meshfxMsg("spawn", 0, 0, "Trollma_morphing.bsm2"); 18 | Api.meshfxMsg("spawn", 1, 0, "TrollGrandma.bsm2"); 19 | if(Api.getPlatform() == "iOS"){ 20 | Api.showHint("Voice changer"); 21 | }; 22 | self.time = (new Date()).getTime() + 3000; 23 | self.faceActions = [self.play]; 24 | Api.playSound("music.m4a",true,1); 25 | Api.showRecordButton(); 26 | }; 27 | this.restart = function() { 28 | Api.meshfxReset(); 29 | self.init(); 30 | }; 31 | this.stopSound = function () { 32 | if(Api.getPlatform() == "ios") { 33 | Api.hideHint(); 34 | Api.stopSound("music.m4a"); 35 | }; 36 | }; 37 | this.faceActions = []; 38 | this.noFaceActions = []; 39 | this.videoRecordStartActions = [self.stopSound]; 40 | this.videoRecordFinishActions = []; 41 | this.videoRecordDiscardActions = [this.restart]; 42 | } 43 | configure(new Effect()); -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/EYES_medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/EYES_medium.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/FLARE_39_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/FLARE_39_512.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/LUT_bubblegum_bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/LUT_bubblegum_bright.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/REDMASK_v3_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/REDMASK_v3_256.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/TEETH_medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/TEETH_medium.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/brdf.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/brdf.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/facemat_Base_Color.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/facemat_Base_Color.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/ibl_diff.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/ibl_diff.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/ibl_spec.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/ibl_spec.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/null_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/null_image.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/null_lut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/null_lut.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/preview.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/soft_trollma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/soft_trollma.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/trollma_Base_Color.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/trollma_Base_Color.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/trollma_MRAO.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/trollma_MRAO.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/trollma_Normal.ktx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/images/trollma_Normal.ktx -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/meshes/TrollGrandma.bsm2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/meshes/TrollGrandma.bsm2 -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/meshes/Trollma_morphing.bsm2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/meshes/Trollma_morphing.bsm2 -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/preview.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/facemat.frag: -------------------------------------------------------------------------------- 1 | #include 2 | void main(){} -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/facemat.vert: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define bnb_IDX_OFFSET 0 4 | #ifdef BNB_VK_1 5 | #define gl_VertexID gl_VertexIndex 6 | #define gl_InstanceID gl_InstanceIndex 7 | #endif 8 | 9 | #define GLFX_USE_UVMORPH 10 | 11 | BNB_LAYOUT_LOCATION(0) BNB_IN vec3 attrib_pos; 12 | BNB_LAYOUT_LOCATION(3) BNB_IN vec2 attrib_uv; 13 | #ifndef BNB_GL_ES_1 14 | BNB_LAYOUT_LOCATION(4) BNB_IN uvec4 attrib_bones; 15 | #else 16 | BNB_LAYOUT_LOCATION(4) BNB_IN vec4 attrib_bones; 17 | #endif 18 | #ifndef GLFX_1_BONE 19 | BNB_LAYOUT_LOCATION(5) BNB_IN vec4 attrib_weights; 20 | #endif 21 | 22 | 23 | 24 | BNB_DECLARE_SAMPLER_2D(0, 1, bnb_BONES); 25 | 26 | #ifdef GLFX_USE_UVMORPH 27 | 28 | BNB_DECLARE_SAMPLER_2D(2, 3, bnb_UVMORPH); 29 | #ifdef GLFX_USE_BG 30 | 31 | BNB_DECLARE_SAMPLER_2D(4, 5, bnb_STATICPOS); 32 | #endif 33 | #endif 34 | 35 | #ifdef GLFX_USE_AUTOMORPH 36 | 37 | BNB_DECLARE_SAMPLER_2D(6, 7, bnb_MORPH); 38 | vec2 glfx_morph_coord( vec3 v ) 39 | { 40 | const float half_angle = radians(104.); 41 | const float y0 = -110.; 42 | const float y1 = 112.; 43 | float x = atan( v.x, v.z )/half_angle; 44 | float y = ((v.y-y0)/(y1-y0))*2. - 1.; 45 | return vec2(x,y); 46 | } 47 | #ifndef GLFX_AUTOMORPH_BONE 48 | vec3 glfx_auto_morph( vec3 v ) 49 | { 50 | vec2 morph_uv = glfx_morph_coord(v)*0.5 + 0.5; 51 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_MORPH), morph_uv ).xyz; 52 | return v + translation; 53 | } 54 | #else 55 | vec3 glfx_auto_morph_bone( vec3 v, mat3x4 m ) 56 | { 57 | vec2 morph_uv = glfx_morph_coord(vec3(m[0][3],m[1][3],m[2][3]))*0.5 + 0.5; 58 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_MORPH), morph_uv ).xyz; 59 | return v + translation; 60 | } 61 | #endif 62 | #endif 63 | 64 | mat3x4 get_bone( uint bone_idx, float k ) 65 | { 66 | float bx = float( int(bone_idx)*3 ); 67 | vec2 rts = 1./vec2(textureSize(BNB_SAMPLER_2D(bnb_BONES),0)); 68 | return mat3x4( 69 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx,k)+0.5)*rts ), 70 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx+1.,k)+0.5)*rts ), 71 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx+2.,k)+0.5)*rts ) ); 72 | } 73 | 74 | void main() 75 | { 76 | mat3x4 m = get_bone( attrib_bones[0], bnb_ANIMKEY ); 77 | #ifndef GLFX_1_BONE 78 | if( attrib_weights[1] > 0. ) 79 | { 80 | m = m*attrib_weights[0] + get_bone( attrib_bones[1], bnb_ANIMKEY )*attrib_weights[1]; 81 | if( attrib_weights[2] > 0. ) 82 | { 83 | m += get_bone( attrib_bones[2], bnb_ANIMKEY )*attrib_weights[2]; 84 | if( attrib_weights[3] > 0. ) 85 | m += get_bone( attrib_bones[3], bnb_ANIMKEY )*attrib_weights[3]; 86 | } 87 | } 88 | #endif 89 | 90 | vec3 vpos = attrib_pos; 91 | 92 | #ifdef GLFX_USE_UVMORPH 93 | vec2 flip_uv = vec2( attrib_uv.x, 1. - attrib_uv.y ); 94 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_UVMORPH),flip_uv).xyz; 95 | #ifdef GLFX_UVMORPH_Z_UP 96 | vpos += vec3(translation.x,-translation.z,translation.y); 97 | #else 98 | vpos += translation; 99 | #endif 100 | #endif 101 | 102 | vpos = vec4(vpos,1.)*m; 103 | 104 | #ifdef GLFX_USE_AUTOMORPH 105 | #ifndef GLFX_AUTOMORPH_BONE 106 | vpos = glfx_auto_morph( vpos ); 107 | #else 108 | vpos = glfx_auto_morph_bone( vpos, m ); 109 | #endif 110 | #endif 111 | 112 | gl_Position = bnb_MVP * vec4(vpos,1.); 113 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/finalColorFilter.fsh.frag: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | BNB_IN(0) vec2 var_uv; 4 | 5 | BNB_DECLARE_SAMPLER_2D(0, 1, s_src); 6 | 7 | 8 | BNB_DECLARE_SAMPLER_2D(2, 3, lookupTexture); 9 | 10 | vec4 finalColorFilter(vec4 orgColor) 11 | { 12 | const float EPS = 0.000001; 13 | const float pxSize = 512.0; 14 | 15 | float bValue = (orgColor.b * 255.0) / 4.0; 16 | 17 | vec2 mulB = clamp(floor(bValue) + vec2(0.0, 1.0), 0.0, 63.0); 18 | vec2 row = floor(mulB / 8.0 + EPS); 19 | vec4 row_col = vec4(row, mulB - row * 8.0); 20 | vec4 lookup = orgColor.ggrr * (63.0/pxSize) + row_col * (64.0/pxSize) + (0.5/pxSize); 21 | 22 | float b1w = bValue - mulB.x; 23 | 24 | vec3 sampled1 = BNB_TEXTURE_2D(BNB_SAMPLER_2D(lookupTexture), lookup.zx).rgb; 25 | vec3 sampled2 = BNB_TEXTURE_2D(BNB_SAMPLER_2D(lookupTexture), lookup.wy).rgb; 26 | 27 | vec3 res = mix(sampled1, sampled2, b1w); 28 | return vec4(res, orgColor.a); 29 | } 30 | 31 | 32 | void main() 33 | { 34 | bnb_FragColor = finalColorFilter(BNB_TEXTURE_2D(BNB_SAMPLER_2D(s_src), var_uv)); 35 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/finalColorFilter.fsh.vert: -------------------------------------------------------------------------------- 1 | #include 2 | BNB_LAYOUT_LOCATION(0) BNB_IN vec2 attrib_pos; 3 | 4 | BNB_OUT(0) vec2 var_uv; 5 | 6 | void main() 7 | { 8 | vec2 v = attrib_pos; 9 | gl_Position = vec4(v, 0., 1.); 10 | var_uv = v * 0.5 + 0.5; 11 | #ifdef BNB_VK_1 12 | var_uv.y = 1. - var_uv.y; 13 | #endif 14 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/glasses.frag: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #define GLFX_IBL 5 | #define GLFX_TBN 6 | #define GLFX_TEX_MRAO 7 | #define GLFX_LIGHTING 8 | 9 | BNB_IN(0) vec2 var_uv; 10 | #ifdef GLFX_TBN 11 | BNB_IN(1) vec3 var_t; 12 | BNB_IN(2) vec3 var_b; 13 | #endif 14 | BNB_IN(3) vec3 var_n; 15 | BNB_IN(4) vec3 var_v; 16 | 17 | 18 | 19 | BNB_DECLARE_SAMPLER_2D(0, 1, tex_diffuse); 20 | #ifdef GLFX_TBN 21 | 22 | BNB_DECLARE_SAMPLER_2D(2, 3, tex_normal); 23 | #endif 24 | #ifdef GLFX_TEX_MRAO 25 | 26 | BNB_DECLARE_SAMPLER_2D(10, 11, tex_mrao); 27 | #else 28 | #ifdef GLFX_AO 29 | #endif 30 | #endif 31 | #ifdef GLFX_TEX_EMI 32 | #endif 33 | 34 | #ifdef GLFX_USE_SHADOW 35 | BNB_IN(5) vec3 var_shadow_coord; 36 | float glfx_shadow_factor() 37 | { 38 | const vec2 offsets[] = vec2[]( 39 | vec2( -0.94201624, -0.39906216 ), 40 | vec2( 0.94558609, -0.76890725 ), 41 | vec2( -0.094184101, -0.92938870 ), 42 | vec2( 0.34495938, 0.29387760 ) 43 | ); 44 | float s = 0.; 45 | for( int i = 0; i != offsets.length(); ++i ) 46 | s += texture( glfx_SHADOW, var_shadow_coord + vec3(offsets[i]/110.,0.1) ); 47 | s *= 0.125; 48 | return s; 49 | } 50 | #endif 51 | 52 | // gamma to linear 53 | vec3 g2l( vec3 g ) 54 | { 55 | return g*(g*(g*0.305306011+0.682171111)+0.012522878); 56 | } 57 | 58 | // combined hdr to ldr and linear to gamma 59 | vec3 l2g( vec3 l ) 60 | { 61 | return sqrt(1.33*(1.-exp(-l)))-0.03; 62 | } 63 | 64 | vec3 fresnel_schlick( float prod, vec3 F0 ) 65 | { 66 | return F0 + ( 1. - F0 )*pow( 1. - prod, 5. ); 67 | } 68 | 69 | vec3 fresnel_schlick_roughness( float prod, vec3 F0, float roughness ) 70 | { 71 | return F0 + ( max( F0, 1. - roughness ) - F0 )*pow( 1. - prod, 5. ); 72 | } 73 | 74 | float distribution_GGX( float cN_H, float roughness ) 75 | { 76 | float a = roughness*roughness; 77 | float a2 = a*a; 78 | float d = cN_H*cN_H*( a2 - 1. ) + 1.; 79 | return a2/(3.14159265*d*d); 80 | } 81 | 82 | float geometry_schlick_GGX( float NV, float roughness ) 83 | { 84 | float r = roughness + 1.; 85 | float k = r*r/8.; 86 | return NV/( NV*( 1. - k ) + k ); 87 | } 88 | 89 | float geometry_smith( float cN_L, float ggx2, float roughness ) 90 | { 91 | return geometry_schlick_GGX( cN_L, roughness )*ggx2; 92 | } 93 | 94 | float diffuse_factor( float n_l, float w ) 95 | { 96 | float w1 = 1. + w; 97 | return pow( max( 0., n_l + w )/w1, w1 ); 98 | } 99 | 100 | #ifdef GLFX_IBL 101 | 102 | BNB_DECLARE_SAMPLER_2D(4, 5, tex_brdf); 103 | 104 | BNB_DECLARE_SAMPLER_CUBE(6, 7, tex_ibl_diff); 105 | 106 | BNB_DECLARE_SAMPLER_CUBE(8, 9, tex_ibl_spec); 107 | #endif 108 | 109 | #ifdef GLFX_LIGHTS 110 | // direction in xyz, lwrap in w 111 | const vec4 lights[] = vec4[]( 112 | vec4(0.,0.6,0.8,1.), 113 | vec4(normalize(vec3(97.6166,-48.185,183.151)),1.) 114 | ); 115 | const vec3 radiance[] = vec3[]( 116 | vec3(1.,1.,1.)*2., 117 | vec3(1.,1.,1.)*0.9*2. 118 | ); 119 | #endif 120 | 121 | void main() 122 | { 123 | vec4 base_opacity = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_diffuse),var_uv); 124 | 125 | //if( base_opacity.w < 0.5 ) discard; 126 | 127 | vec3 base = g2l(base_opacity.xyz); 128 | float opacity = base_opacity.w; 129 | #ifdef GLFX_TEX_MRAO 130 | vec3 mrao = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_mrao),var_uv).xyz; 131 | #ifdef GLFX_DIELECTRIC 132 | float metallic = 0.; 133 | #else 134 | float metallic = mrao.x; 135 | #endif 136 | float roughness = mrao.y; 137 | #else 138 | #ifdef GLFX_DIELECTRIC 139 | float metallic = 0.; 140 | #else 141 | float metallic = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_metallic),var_uv).x; 142 | #endif 143 | float roughness = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_roughness),var_uv).x; 144 | #endif 145 | 146 | #ifdef GLFX_TBN 147 | #ifdef GLFX_NORMAL_DIRECTX 148 | vec3 N = normalize( mat3(var_t,var_b,var_n)*(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normal),var_uv).xyz*vec3(2.,-2.,2.)-vec3(1.,-1.,1.)) ); 149 | #else 150 | vec3 N = normalize( mat3(var_t,var_b,var_n)*(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normal),var_uv).xyz*2.-1.) ); 151 | #endif 152 | #else 153 | vec3 N = normalize( var_n ); 154 | #endif 155 | 156 | #ifdef GLFX_2SIDED 157 | N *= gl_FrontFacing ? 1. : -1.; 158 | #endif 159 | 160 | vec3 V = normalize( -var_v ); 161 | float cN_V = max( 0., dot( N, V ) ); 162 | vec3 R = reflect( -V, N ); 163 | 164 | vec3 F0 = mix( vec3(0.04), base, metallic ); 165 | 166 | #ifdef GLFX_IBL 167 | vec3 F = fresnel_schlick_roughness( cN_V, F0, roughness ); 168 | vec3 kD = ( 1. - F )*( 1. - metallic ); 169 | 170 | vec3 diffuse = BNB_TEXTURE_CUBE(BNB_SAMPLER_CUBE(tex_ibl_diff), N ).xyz * base; 171 | 172 | const float MAX_REFLECTION_LOD = 7.; // number of mip levels in tex_ibl_spec 173 | vec3 prefilteredColor = BNB_TEXTURE_CUBE_LOD(BNB_SAMPLER_CUBE(tex_ibl_spec), R, roughness*MAX_REFLECTION_LOD ).xyz; 174 | vec2 brdf = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_brdf), vec2( cN_V, roughness ) ).yx; 175 | vec3 specular = prefilteredColor * (F * brdf.x + brdf.y); 176 | 177 | vec3 color = (kD*diffuse + specular); 178 | #else 179 | vec3 color = 0.03*base; // ambient 180 | #endif 181 | 182 | #ifdef GLFX_LIGHTS 183 | float ggx2 = geometry_schlick_GGX( cN_V, roughness ); 184 | for( int i = 0; i != lights.length(); ++i ) 185 | { 186 | vec3 L = lights[i].xyz; 187 | float lwrap = lights[i].w; 188 | vec3 H = normalize( V + L ); 189 | float N_L = dot( N, L ); 190 | float cN_L = max( 0., N_L ); 191 | float cN_H = max( 0., dot( N, H ) ); 192 | float cH_V = max( 0., dot( H, V ) ); 193 | 194 | float NDF = distribution_GGX( cN_H, roughness ); 195 | float G = geometry_smith( cN_L, ggx2, roughness ); 196 | vec3 F_light = fresnel_schlick( cH_V, F0 ); 197 | 198 | vec3 specular = NDF*G*F_light/( 4.*cN_V*cN_L + 0.001 ); 199 | 200 | vec3 kD_light = ( 1. - F_light )*( 1. - metallic ); 201 | 202 | color += ( kD_light*base/3.14159265 + specular )*radiance[i]*diffuse_factor( N_L, lwrap )/*cN_L*/; 203 | } 204 | #endif 205 | 206 | #ifdef GLFX_AO 207 | #ifdef GLFX_TEX_MRAO 208 | color *= mrao.z; 209 | #else 210 | color *= BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_ao),var_uv).x; 211 | #endif 212 | #endif 213 | 214 | #ifdef GLFX_TEX_EMI 215 | color += g2l(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_emi),var_uv).xyz); 216 | #endif 217 | 218 | #ifdef GLFX_USE_SHADOW 219 | color = mix( color, vec3(0.), glfx_shadow_factor() ); 220 | #endif 221 | 222 | bnb_FragColor = vec4(l2g(color),opacity); 223 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/glasses.vert: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define bnb_IDX_OFFSET 0 4 | #ifdef BNB_VK_1 5 | #define gl_VertexID gl_VertexIndex 6 | #define gl_InstanceID gl_InstanceIndex 7 | #endif 8 | 9 | 10 | #define GLFX_IBL 11 | #define GLFX_TBN 12 | #define GLFX_TEX_MRAO 13 | #define GLFX_LIGHTING 14 | 15 | BNB_LAYOUT_LOCATION(0) BNB_IN vec3 attrib_pos; 16 | #ifdef GLFX_LIGHTING 17 | #ifdef BNB_VK_1 18 | BNB_LAYOUT_LOCATION(1) BNB_IN uint attrib_n; 19 | #else 20 | BNB_LAYOUT_LOCATION(1) BNB_IN vec4 attrib_n; 21 | #endif 22 | #ifdef GLFX_TBN 23 | #ifdef BNB_VK_1 24 | BNB_LAYOUT_LOCATION(2) BNB_IN uint attrib_t; 25 | #else 26 | BNB_LAYOUT_LOCATION(2) BNB_IN vec4 attrib_t; 27 | #endif 28 | #endif 29 | #endif 30 | BNB_LAYOUT_LOCATION(3) BNB_IN vec2 attrib_uv; 31 | #ifndef BNB_GL_ES_1 32 | BNB_LAYOUT_LOCATION(4) BNB_IN uvec4 attrib_bones; 33 | #else 34 | BNB_LAYOUT_LOCATION(4) BNB_IN vec4 attrib_bones; 35 | #endif 36 | #ifndef GLFX_1_BONE 37 | BNB_LAYOUT_LOCATION(5) BNB_IN vec4 attrib_weights; 38 | #endif 39 | 40 | 41 | 42 | BNB_DECLARE_SAMPLER_2D(12, 13, bnb_BONES); 43 | 44 | #ifdef GLFX_USE_UVMORPH 45 | 46 | BNB_DECLARE_SAMPLER_2D(14, 15, bnb_UVMORPH); 47 | #ifdef GLFX_USE_BG 48 | 49 | BNB_DECLARE_SAMPLER_2D(16, 17, bnb_STATICPOS); 50 | #endif 51 | #endif 52 | 53 | #ifdef GLFX_USE_BG 54 | BNB_OUT(6) vec2 var_bg_uv; 55 | #endif 56 | 57 | #ifdef GLFX_USE_AUTOMORPH 58 | 59 | BNB_DECLARE_SAMPLER_2D(18, 19, bnb_MORPH); 60 | vec2 glfx_morph_coord( vec3 v ) 61 | { 62 | const float half_angle = radians(104.); 63 | const float y0 = -110.; 64 | const float y1 = 112.; 65 | float x = atan( v.x, v.z )/half_angle; 66 | float y = ((v.y-y0)/(y1-y0))*2. - 1.; 67 | return vec2(x,y); 68 | } 69 | #ifndef GLFX_AUTOMORPH_BONE 70 | vec3 glfx_auto_morph( vec3 v ) 71 | { 72 | vec2 morph_uv = glfx_morph_coord(v)*0.5 + 0.5; 73 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_MORPH), morph_uv ).xyz; 74 | return v + translation; 75 | } 76 | #else 77 | vec3 glfx_auto_morph_bone( vec3 v, mat3x4 m ) 78 | { 79 | vec2 morph_uv = glfx_morph_coord(vec3(m[0][3],m[1][3],m[2][3]))*0.5 + 0.5; 80 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_MORPH), morph_uv ).xyz; 81 | return v + translation; 82 | } 83 | #endif 84 | #endif 85 | 86 | BNB_OUT(0) vec2 var_uv; 87 | #ifdef GLFX_LIGHTING 88 | #ifdef GLFX_TBN 89 | BNB_OUT(1) vec3 var_t; 90 | BNB_OUT(2) vec3 var_b; 91 | #endif 92 | BNB_OUT(3) vec3 var_n; 93 | BNB_OUT(4) vec3 var_v; 94 | #endif 95 | 96 | #ifdef GLFX_USE_SHADOW 97 | BNB_OUT(5) vec3 var_shadow_coord; 98 | vec3 spherical_proj( vec2 fovM, vec2 fovP, float zn, float zf, vec3 v ) 99 | { 100 | vec2 xy = (atan( v.xy, v.zz )-(fovP+fovM)*0.5)/((fovP-fovM)*0.5); 101 | float z = (length(v)-(zn+zf)*0.5)/((zf-zn)*0.5); 102 | return vec3( xy, z ); 103 | } 104 | #endif 105 | 106 | mat3x4 get_bone( uint bone_idx, float k ) 107 | { 108 | float bx = float( int(bone_idx)*3 ); 109 | vec2 rts = 1./vec2(textureSize(BNB_SAMPLER_2D(bnb_BONES),0)); 110 | return mat3x4( 111 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx,k)+0.5)*rts ), 112 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx+1.,k)+0.5)*rts ), 113 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx+2.,k)+0.5)*rts ) ); 114 | } 115 | 116 | void main() 117 | { 118 | mat3x4 m = get_bone( attrib_bones[0], bnb_ANIMKEY ); 119 | #ifndef GLFX_1_BONE 120 | if( attrib_weights[1] > 0. ) 121 | { 122 | m = m*attrib_weights[0] + get_bone( attrib_bones[1], bnb_ANIMKEY )*attrib_weights[1]; 123 | if( attrib_weights[2] > 0. ) 124 | { 125 | m += get_bone( attrib_bones[2], bnb_ANIMKEY )*attrib_weights[2]; 126 | if( attrib_weights[3] > 0. ) 127 | m += get_bone( attrib_bones[3], bnb_ANIMKEY )*attrib_weights[3]; 128 | } 129 | } 130 | #endif 131 | 132 | vec3 vpos = attrib_pos; 133 | 134 | #ifdef GLFX_USE_UVMORPH 135 | vec2 flip_uv = vec2( attrib_uv.x, 1. - attrib_uv.y ); 136 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_UVMORPH),flip_uv).xyz; 137 | #ifdef GLFX_UVMORPH_Z_UP 138 | vpos += vec3(translation.x,-translation.z,translation.y); 139 | #else 140 | vpos += translation; 141 | #endif 142 | #endif 143 | 144 | vpos = vec4(vpos,1.)*m; 145 | 146 | #ifdef GLFX_USE_AUTOMORPH 147 | #ifndef GLFX_AUTOMORPH_BONE 148 | vpos = glfx_auto_morph( vpos ); 149 | #else 150 | vpos = glfx_auto_morph_bone( vpos, m ); 151 | #endif 152 | #endif 153 | 154 | gl_Position = bnb_MVP * vec4(vpos,1.); 155 | 156 | #ifdef GLFX_USE_BG 157 | #ifdef GLFX_USE_UVMORPH 158 | vec4 uvmorphed_view = bnb_MVP * vec4( BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_STATICPOS),flip_uv).xyz + translation, 1. ); 159 | var_bg_uv = (uvmorphed_view.xy/uvmorphed_view.w)*0.5 + 0.5; 160 | #else 161 | var_bg_uv = (gl_Position.xy/gl_Position.w)*0.5 + 0.5; 162 | #endif 163 | #endif 164 | 165 | var_uv = attrib_uv; 166 | 167 | #ifdef GLFX_LIGHTING 168 | var_n = mat3(bnb_MV)*(bnb_decode_int1010102(attrib_n).xyz*mat3(m)); 169 | #ifdef GLFX_TBN 170 | var_t = mat3(bnb_MV)*(bnb_decode_int1010102(attrib_t).xyz*mat3(m)); 171 | var_b = bnb_decode_int1010102(attrib_t).w*cross( var_n, var_t ); 172 | #endif 173 | var_v = (bnb_MV*vec4(vpos,1.)).xyz; 174 | #endif 175 | 176 | #ifdef GLFX_USE_SHADOW 177 | var_shadow_coord = spherical_proj( 178 | vec2(-radians(60.),-radians(20.)),vec2(radians(60.),radians(100.)), 179 | 400.,70., 180 | vpos+vec3(0.,100.,50.))*0.5+0.5; 181 | #endif 182 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/hair_alpha.frag: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #define GLFX_IBL 5 | #define GLFX_TBN 6 | #define GLFX_TEX_MRAO 7 | #define GLFX_LIGHTING 8 | 9 | BNB_IN(0) vec2 var_uv; 10 | #ifdef GLFX_TBN 11 | BNB_IN(1) vec3 var_t; 12 | BNB_IN(2) vec3 var_b; 13 | #endif 14 | BNB_IN(3) vec3 var_n; 15 | BNB_IN(4) vec3 var_v; 16 | 17 | 18 | 19 | BNB_DECLARE_SAMPLER_2D(0, 1, tex_diffuse); 20 | #ifdef GLFX_TBN 21 | 22 | BNB_DECLARE_SAMPLER_2D(2, 3, tex_normal); 23 | #endif 24 | #ifdef GLFX_TEX_MRAO 25 | 26 | BNB_DECLARE_SAMPLER_2D(10, 11, tex_mrao); 27 | #else 28 | #ifdef GLFX_AO 29 | #endif 30 | #endif 31 | #ifdef GLFX_TEX_EMI 32 | #endif 33 | 34 | #ifdef GLFX_USE_SHADOW 35 | BNB_IN(5) vec3 var_shadow_coord; 36 | float glfx_shadow_factor() 37 | { 38 | const vec2 offsets[] = vec2[]( 39 | vec2( -0.94201624, -0.39906216 ), 40 | vec2( 0.94558609, -0.76890725 ), 41 | vec2( -0.094184101, -0.92938870 ), 42 | vec2( 0.34495938, 0.29387760 ) 43 | ); 44 | float s = 0.; 45 | for( int i = 0; i != offsets.length(); ++i ) 46 | s += texture( glfx_SHADOW, var_shadow_coord + vec3(offsets[i]/110.,0.1) ); 47 | s *= 0.125; 48 | return s; 49 | } 50 | #endif 51 | 52 | // gamma to linear 53 | vec3 g2l( vec3 g ) 54 | { 55 | return g*(g*(g*0.305306011+0.682171111)+0.012522878); 56 | } 57 | 58 | // combined hdr to ldr and linear to gamma 59 | vec3 l2g( vec3 l ) 60 | { 61 | return sqrt(1.33*(1.-exp(-l)))-0.03; 62 | } 63 | 64 | vec3 fresnel_schlick( float prod, vec3 F0 ) 65 | { 66 | return F0 + ( 1. - F0 )*pow( 1. - prod, 5. ); 67 | } 68 | 69 | vec3 fresnel_schlick_roughness( float prod, vec3 F0, float roughness ) 70 | { 71 | return F0 + ( max( F0, 1. - roughness ) - F0 )*pow( 1. - prod, 5. ); 72 | } 73 | 74 | float distribution_GGX( float cN_H, float roughness ) 75 | { 76 | float a = roughness*roughness; 77 | float a2 = a*a; 78 | float d = cN_H*cN_H*( a2 - 1. ) + 1.; 79 | return a2/(3.14159265*d*d); 80 | } 81 | 82 | float geometry_schlick_GGX( float NV, float roughness ) 83 | { 84 | float r = roughness + 1.; 85 | float k = r*r/8.; 86 | return NV/( NV*( 1. - k ) + k ); 87 | } 88 | 89 | float geometry_smith( float cN_L, float ggx2, float roughness ) 90 | { 91 | return geometry_schlick_GGX( cN_L, roughness )*ggx2; 92 | } 93 | 94 | float diffuse_factor( float n_l, float w ) 95 | { 96 | float w1 = 1. + w; 97 | return pow( max( 0., n_l + w )/w1, w1 ); 98 | } 99 | 100 | #ifdef GLFX_IBL 101 | 102 | BNB_DECLARE_SAMPLER_2D(4, 5, tex_brdf); 103 | 104 | BNB_DECLARE_SAMPLER_CUBE(6, 7, tex_ibl_diff); 105 | 106 | BNB_DECLARE_SAMPLER_CUBE(8, 9, tex_ibl_spec); 107 | #endif 108 | 109 | #ifdef GLFX_LIGHTS 110 | // direction in xyz, lwrap in w 111 | const vec4 lights[] = vec4[]( 112 | vec4(0.,0.6,0.8,1.), 113 | vec4(normalize(vec3(97.6166,-48.185,183.151)),1.) 114 | ); 115 | const vec3 radiance[] = vec3[]( 116 | vec3(1.,1.,1.)*2., 117 | vec3(1.,1.,1.)*0.9*2. 118 | ); 119 | #endif 120 | 121 | void main() 122 | { 123 | vec4 base_opacity = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_diffuse),var_uv); 124 | 125 | //if( base_opacity.w < 0.5 ) discard; 126 | 127 | vec3 base = g2l(base_opacity.xyz); 128 | float opacity = base_opacity.w; 129 | #ifdef GLFX_TEX_MRAO 130 | vec3 mrao = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_mrao),var_uv).xyz; 131 | #ifdef GLFX_DIELECTRIC 132 | float metallic = 0.; 133 | #else 134 | float metallic = mrao.x; 135 | #endif 136 | float roughness = mrao.y; 137 | #else 138 | #ifdef GLFX_DIELECTRIC 139 | float metallic = 0.; 140 | #else 141 | float metallic = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_metallic),var_uv).x; 142 | #endif 143 | float roughness = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_roughness),var_uv).x; 144 | #endif 145 | 146 | #ifdef GLFX_TBN 147 | #ifdef GLFX_NORMAL_DIRECTX 148 | vec3 N = normalize( mat3(var_t,var_b,var_n)*(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normal),var_uv).xyz*vec3(2.,-2.,2.)-vec3(1.,-1.,1.)) ); 149 | #else 150 | vec3 N = normalize( mat3(var_t,var_b,var_n)*(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normal),var_uv).xyz*2.-1.) ); 151 | #endif 152 | #else 153 | vec3 N = normalize( var_n ); 154 | #endif 155 | 156 | #ifdef GLFX_2SIDED 157 | N *= gl_FrontFacing ? 1. : -1.; 158 | #endif 159 | 160 | vec3 V = normalize( -var_v ); 161 | float cN_V = max( 0., dot( N, V ) ); 162 | vec3 R = reflect( -V, N ); 163 | 164 | vec3 F0 = mix( vec3(0.04), base, metallic ); 165 | 166 | #ifdef GLFX_IBL 167 | vec3 F = fresnel_schlick_roughness( cN_V, F0, roughness ); 168 | vec3 kD = ( 1. - F )*( 1. - metallic ); 169 | 170 | vec3 diffuse = BNB_TEXTURE_CUBE(BNB_SAMPLER_CUBE(tex_ibl_diff), N ).xyz * base; 171 | 172 | const float MAX_REFLECTION_LOD = 7.; // number of mip levels in tex_ibl_spec 173 | vec3 prefilteredColor = BNB_TEXTURE_CUBE_LOD(BNB_SAMPLER_CUBE(tex_ibl_spec), R, roughness*MAX_REFLECTION_LOD ).xyz; 174 | vec2 brdf = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_brdf), vec2( cN_V, roughness ) ).yx; 175 | vec3 specular = prefilteredColor * (F * brdf.x + brdf.y); 176 | 177 | vec3 color = (kD*diffuse + specular); 178 | #else 179 | vec3 color = 0.03*base; // ambient 180 | #endif 181 | 182 | #ifdef GLFX_LIGHTS 183 | float ggx2 = geometry_schlick_GGX( cN_V, roughness ); 184 | for( int i = 0; i != lights.length(); ++i ) 185 | { 186 | vec3 L = lights[i].xyz; 187 | float lwrap = lights[i].w; 188 | vec3 H = normalize( V + L ); 189 | float N_L = dot( N, L ); 190 | float cN_L = max( 0., N_L ); 191 | float cN_H = max( 0., dot( N, H ) ); 192 | float cH_V = max( 0., dot( H, V ) ); 193 | 194 | float NDF = distribution_GGX( cN_H, roughness ); 195 | float G = geometry_smith( cN_L, ggx2, roughness ); 196 | vec3 F_light = fresnel_schlick( cH_V, F0 ); 197 | 198 | vec3 specular = NDF*G*F_light/( 4.*cN_V*cN_L + 0.001 ); 199 | 200 | vec3 kD_light = ( 1. - F_light )*( 1. - metallic ); 201 | 202 | color += ( kD_light*base/3.14159265 + specular )*radiance[i]*diffuse_factor( N_L, lwrap )/*cN_L*/; 203 | } 204 | #endif 205 | 206 | #ifdef GLFX_AO 207 | #ifdef GLFX_TEX_MRAO 208 | color *= mrao.z; 209 | #else 210 | color *= BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_ao),var_uv).x; 211 | #endif 212 | #endif 213 | 214 | #ifdef GLFX_TEX_EMI 215 | color += g2l(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_emi),var_uv).xyz); 216 | #endif 217 | 218 | #ifdef GLFX_USE_SHADOW 219 | color = mix( color, vec3(0.), glfx_shadow_factor() ); 220 | #endif 221 | 222 | bnb_FragColor = vec4(l2g(color),opacity); 223 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/hair_alpha.vert: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define bnb_IDX_OFFSET 0 4 | #ifdef BNB_VK_1 5 | #define gl_VertexID gl_VertexIndex 6 | #define gl_InstanceID gl_InstanceIndex 7 | #endif 8 | 9 | 10 | #define GLFX_IBL 11 | #define GLFX_TBN 12 | #define GLFX_TEX_MRAO 13 | #define GLFX_LIGHTING 14 | 15 | BNB_LAYOUT_LOCATION(0) BNB_IN vec3 attrib_pos; 16 | #ifdef GLFX_LIGHTING 17 | #ifdef BNB_VK_1 18 | BNB_LAYOUT_LOCATION(1) BNB_IN uint attrib_n; 19 | #else 20 | BNB_LAYOUT_LOCATION(1) BNB_IN vec4 attrib_n; 21 | #endif 22 | #ifdef GLFX_TBN 23 | #ifdef BNB_VK_1 24 | BNB_LAYOUT_LOCATION(2) BNB_IN uint attrib_t; 25 | #else 26 | BNB_LAYOUT_LOCATION(2) BNB_IN vec4 attrib_t; 27 | #endif 28 | #endif 29 | #endif 30 | BNB_LAYOUT_LOCATION(3) BNB_IN vec2 attrib_uv; 31 | #ifndef BNB_GL_ES_1 32 | BNB_LAYOUT_LOCATION(4) BNB_IN uvec4 attrib_bones; 33 | #else 34 | BNB_LAYOUT_LOCATION(4) BNB_IN vec4 attrib_bones; 35 | #endif 36 | #ifndef GLFX_1_BONE 37 | BNB_LAYOUT_LOCATION(5) BNB_IN vec4 attrib_weights; 38 | #endif 39 | 40 | 41 | 42 | BNB_DECLARE_SAMPLER_2D(12, 13, bnb_BONES); 43 | 44 | #ifdef GLFX_USE_UVMORPH 45 | 46 | BNB_DECLARE_SAMPLER_2D(14, 15, bnb_UVMORPH); 47 | #ifdef GLFX_USE_BG 48 | 49 | BNB_DECLARE_SAMPLER_2D(16, 17, bnb_STATICPOS); 50 | #endif 51 | #endif 52 | 53 | #ifdef GLFX_USE_BG 54 | BNB_OUT(6) vec2 var_bg_uv; 55 | #endif 56 | 57 | #ifdef GLFX_USE_AUTOMORPH 58 | 59 | BNB_DECLARE_SAMPLER_2D(18, 19, bnb_MORPH); 60 | vec2 glfx_morph_coord( vec3 v ) 61 | { 62 | const float half_angle = radians(104.); 63 | const float y0 = -110.; 64 | const float y1 = 112.; 65 | float x = atan( v.x, v.z )/half_angle; 66 | float y = ((v.y-y0)/(y1-y0))*2. - 1.; 67 | return vec2(x,y); 68 | } 69 | #ifndef GLFX_AUTOMORPH_BONE 70 | vec3 glfx_auto_morph( vec3 v ) 71 | { 72 | vec2 morph_uv = glfx_morph_coord(v)*0.5 + 0.5; 73 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_MORPH), morph_uv ).xyz; 74 | return v + translation; 75 | } 76 | #else 77 | vec3 glfx_auto_morph_bone( vec3 v, mat3x4 m ) 78 | { 79 | vec2 morph_uv = glfx_morph_coord(vec3(m[0][3],m[1][3],m[2][3]))*0.5 + 0.5; 80 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_MORPH), morph_uv ).xyz; 81 | return v + translation; 82 | } 83 | #endif 84 | #endif 85 | 86 | BNB_OUT(0) vec2 var_uv; 87 | #ifdef GLFX_LIGHTING 88 | #ifdef GLFX_TBN 89 | BNB_OUT(1) vec3 var_t; 90 | BNB_OUT(2) vec3 var_b; 91 | #endif 92 | BNB_OUT(3) vec3 var_n; 93 | BNB_OUT(4) vec3 var_v; 94 | #endif 95 | 96 | #ifdef GLFX_USE_SHADOW 97 | BNB_OUT(5) vec3 var_shadow_coord; 98 | vec3 spherical_proj( vec2 fovM, vec2 fovP, float zn, float zf, vec3 v ) 99 | { 100 | vec2 xy = (atan( v.xy, v.zz )-(fovP+fovM)*0.5)/((fovP-fovM)*0.5); 101 | float z = (length(v)-(zn+zf)*0.5)/((zf-zn)*0.5); 102 | return vec3( xy, z ); 103 | } 104 | #endif 105 | 106 | mat3x4 get_bone( uint bone_idx, float k ) 107 | { 108 | float bx = float( int(bone_idx)*3 ); 109 | vec2 rts = 1./vec2(textureSize(BNB_SAMPLER_2D(bnb_BONES),0)); 110 | return mat3x4( 111 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx,k)+0.5)*rts ), 112 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx+1.,k)+0.5)*rts ), 113 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx+2.,k)+0.5)*rts ) ); 114 | } 115 | 116 | void main() 117 | { 118 | mat3x4 m = get_bone( attrib_bones[0], bnb_ANIMKEY ); 119 | #ifndef GLFX_1_BONE 120 | if( attrib_weights[1] > 0. ) 121 | { 122 | m = m*attrib_weights[0] + get_bone( attrib_bones[1], bnb_ANIMKEY )*attrib_weights[1]; 123 | if( attrib_weights[2] > 0. ) 124 | { 125 | m += get_bone( attrib_bones[2], bnb_ANIMKEY )*attrib_weights[2]; 126 | if( attrib_weights[3] > 0. ) 127 | m += get_bone( attrib_bones[3], bnb_ANIMKEY )*attrib_weights[3]; 128 | } 129 | } 130 | #endif 131 | 132 | vec3 vpos = attrib_pos; 133 | 134 | #ifdef GLFX_USE_UVMORPH 135 | vec2 flip_uv = vec2( attrib_uv.x, 1. - attrib_uv.y ); 136 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_UVMORPH),flip_uv).xyz; 137 | #ifdef GLFX_UVMORPH_Z_UP 138 | vpos += vec3(translation.x,-translation.z,translation.y); 139 | #else 140 | vpos += translation; 141 | #endif 142 | #endif 143 | 144 | vpos = vec4(vpos,1.)*m; 145 | 146 | #ifdef GLFX_USE_AUTOMORPH 147 | #ifndef GLFX_AUTOMORPH_BONE 148 | vpos = glfx_auto_morph( vpos ); 149 | #else 150 | vpos = glfx_auto_morph_bone( vpos, m ); 151 | #endif 152 | #endif 153 | 154 | gl_Position = bnb_MVP * vec4(vpos,1.); 155 | 156 | #ifdef GLFX_USE_BG 157 | #ifdef GLFX_USE_UVMORPH 158 | vec4 uvmorphed_view = bnb_MVP * vec4( BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_STATICPOS),flip_uv).xyz + translation, 1. ); 159 | var_bg_uv = (uvmorphed_view.xy/uvmorphed_view.w)*0.5 + 0.5; 160 | #else 161 | var_bg_uv = (gl_Position.xy/gl_Position.w)*0.5 + 0.5; 162 | #endif 163 | #endif 164 | 165 | var_uv = attrib_uv; 166 | 167 | #ifdef GLFX_LIGHTING 168 | var_n = mat3(bnb_MV)*(bnb_decode_int1010102(attrib_n).xyz*mat3(m)); 169 | #ifdef GLFX_TBN 170 | var_t = mat3(bnb_MV)*(bnb_decode_int1010102(attrib_t).xyz*mat3(m)); 171 | var_b = bnb_decode_int1010102(attrib_t).w*cross( var_n, var_t ); 172 | #endif 173 | var_v = (bnb_MV*vec4(vpos,1.)).xyz; 174 | #endif 175 | 176 | #ifdef GLFX_USE_SHADOW 177 | var_shadow_coord = spherical_proj( 178 | vec2(-radians(60.),-radians(20.)),vec2(radians(60.),radians(100.)), 179 | 400.,70., 180 | vpos+vec3(0.,100.,50.))*0.5+0.5; 181 | #endif 182 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/hair_base.frag: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | #define GLFX_IBL 5 | #define GLFX_TBN 6 | #define GLFX_TEX_MRAO 7 | #define GLFX_LIGHTING 8 | 9 | BNB_IN(0) vec2 var_uv; 10 | #ifdef GLFX_TBN 11 | BNB_IN(1) vec3 var_t; 12 | BNB_IN(2) vec3 var_b; 13 | #endif 14 | BNB_IN(3) vec3 var_n; 15 | BNB_IN(4) vec3 var_v; 16 | 17 | 18 | 19 | BNB_DECLARE_SAMPLER_2D(0, 1, tex_diffuse); 20 | #ifdef GLFX_TBN 21 | 22 | BNB_DECLARE_SAMPLER_2D(2, 3, tex_normal); 23 | #endif 24 | #ifdef GLFX_TEX_MRAO 25 | 26 | BNB_DECLARE_SAMPLER_2D(10, 11, tex_mrao); 27 | #else 28 | #ifdef GLFX_AO 29 | #endif 30 | #endif 31 | #ifdef GLFX_TEX_EMI 32 | #endif 33 | 34 | #ifdef GLFX_USE_SHADOW 35 | BNB_IN(5) vec3 var_shadow_coord; 36 | float glfx_shadow_factor() 37 | { 38 | const vec2 offsets[] = vec2[]( 39 | vec2( -0.94201624, -0.39906216 ), 40 | vec2( 0.94558609, -0.76890725 ), 41 | vec2( -0.094184101, -0.92938870 ), 42 | vec2( 0.34495938, 0.29387760 ) 43 | ); 44 | float s = 0.; 45 | for( int i = 0; i != offsets.length(); ++i ) 46 | s += texture( glfx_SHADOW, var_shadow_coord + vec3(offsets[i]/110.,0.1) ); 47 | s *= 0.125; 48 | return s; 49 | } 50 | #endif 51 | 52 | // gamma to linear 53 | vec3 g2l( vec3 g ) 54 | { 55 | return g*(g*(g*0.305306011+0.682171111)+0.012522878); 56 | } 57 | 58 | // combined hdr to ldr and linear to gamma 59 | vec3 l2g( vec3 l ) 60 | { 61 | return sqrt(1.33*(1.-exp(-l)))-0.03; 62 | } 63 | 64 | vec3 fresnel_schlick( float prod, vec3 F0 ) 65 | { 66 | return F0 + ( 1. - F0 )*pow( 1. - prod, 5. ); 67 | } 68 | 69 | vec3 fresnel_schlick_roughness( float prod, vec3 F0, float roughness ) 70 | { 71 | return F0 + ( max( F0, 1. - roughness ) - F0 )*pow( 1. - prod, 5. ); 72 | } 73 | 74 | float distribution_GGX( float cN_H, float roughness ) 75 | { 76 | float a = roughness*roughness; 77 | float a2 = a*a; 78 | float d = cN_H*cN_H*( a2 - 1. ) + 1.; 79 | return a2/(3.14159265*d*d); 80 | } 81 | 82 | float geometry_schlick_GGX( float NV, float roughness ) 83 | { 84 | float r = roughness + 1.; 85 | float k = r*r/8.; 86 | return NV/( NV*( 1. - k ) + k ); 87 | } 88 | 89 | float geometry_smith( float cN_L, float ggx2, float roughness ) 90 | { 91 | return geometry_schlick_GGX( cN_L, roughness )*ggx2; 92 | } 93 | 94 | float diffuse_factor( float n_l, float w ) 95 | { 96 | float w1 = 1. + w; 97 | return pow( max( 0., n_l + w )/w1, w1 ); 98 | } 99 | 100 | #ifdef GLFX_IBL 101 | 102 | BNB_DECLARE_SAMPLER_2D(4, 5, tex_brdf); 103 | 104 | BNB_DECLARE_SAMPLER_CUBE(6, 7, tex_ibl_diff); 105 | 106 | BNB_DECLARE_SAMPLER_CUBE(8, 9, tex_ibl_spec); 107 | #endif 108 | 109 | #ifdef GLFX_LIGHTS 110 | // direction in xyz, lwrap in w 111 | const vec4 lights[] = vec4[]( 112 | vec4(0.,0.6,0.8,1.), 113 | vec4(normalize(vec3(97.6166,-48.185,183.151)),1.) 114 | ); 115 | const vec3 radiance[] = vec3[]( 116 | vec3(1.,1.,1.)*2., 117 | vec3(1.,1.,1.)*0.9*2. 118 | ); 119 | #endif 120 | 121 | void main() 122 | { 123 | vec4 base_opacity = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_diffuse),var_uv); 124 | 125 | //if( base_opacity.w < 0.5 ) discard; 126 | 127 | vec3 base = g2l(base_opacity.xyz); 128 | float opacity = base_opacity.w; 129 | #ifdef GLFX_TEX_MRAO 130 | vec3 mrao = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_mrao),var_uv).xyz; 131 | #ifdef GLFX_DIELECTRIC 132 | float metallic = 0.; 133 | #else 134 | float metallic = mrao.x; 135 | #endif 136 | float roughness = mrao.y; 137 | #else 138 | #ifdef GLFX_DIELECTRIC 139 | float metallic = 0.; 140 | #else 141 | float metallic = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_metallic),var_uv).x; 142 | #endif 143 | float roughness = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_roughness),var_uv).x; 144 | #endif 145 | 146 | #ifdef GLFX_TBN 147 | #ifdef GLFX_NORMAL_DIRECTX 148 | vec3 N = normalize( mat3(var_t,var_b,var_n)*(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normal),var_uv).xyz*vec3(2.,-2.,2.)-vec3(1.,-1.,1.)) ); 149 | #else 150 | vec3 N = normalize( mat3(var_t,var_b,var_n)*(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normal),var_uv).xyz*2.-1.) ); 151 | #endif 152 | #else 153 | vec3 N = normalize( var_n ); 154 | #endif 155 | 156 | #ifdef GLFX_2SIDED 157 | N *= gl_FrontFacing ? 1. : -1.; 158 | #endif 159 | 160 | vec3 V = normalize( -var_v ); 161 | float cN_V = max( 0., dot( N, V ) ); 162 | vec3 R = reflect( -V, N ); 163 | 164 | vec3 F0 = mix( vec3(0.04), base, metallic ); 165 | 166 | #ifdef GLFX_IBL 167 | vec3 F = fresnel_schlick_roughness( cN_V, F0, roughness ); 168 | vec3 kD = ( 1. - F )*( 1. - metallic ); 169 | 170 | vec3 diffuse = BNB_TEXTURE_CUBE(BNB_SAMPLER_CUBE(tex_ibl_diff), N ).xyz * base; 171 | 172 | const float MAX_REFLECTION_LOD = 7.; // number of mip levels in tex_ibl_spec 173 | vec3 prefilteredColor = BNB_TEXTURE_CUBE_LOD(BNB_SAMPLER_CUBE(tex_ibl_spec), R, roughness*MAX_REFLECTION_LOD ).xyz; 174 | vec2 brdf = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_brdf), vec2( cN_V, roughness ) ).yx; 175 | vec3 specular = prefilteredColor * (F * brdf.x + brdf.y); 176 | 177 | vec3 color = (kD*diffuse + specular); 178 | #else 179 | vec3 color = 0.03*base; // ambient 180 | #endif 181 | 182 | #ifdef GLFX_LIGHTS 183 | float ggx2 = geometry_schlick_GGX( cN_V, roughness ); 184 | for( int i = 0; i != lights.length(); ++i ) 185 | { 186 | vec3 L = lights[i].xyz; 187 | float lwrap = lights[i].w; 188 | vec3 H = normalize( V + L ); 189 | float N_L = dot( N, L ); 190 | float cN_L = max( 0., N_L ); 191 | float cN_H = max( 0., dot( N, H ) ); 192 | float cH_V = max( 0., dot( H, V ) ); 193 | 194 | float NDF = distribution_GGX( cN_H, roughness ); 195 | float G = geometry_smith( cN_L, ggx2, roughness ); 196 | vec3 F_light = fresnel_schlick( cH_V, F0 ); 197 | 198 | vec3 specular = NDF*G*F_light/( 4.*cN_V*cN_L + 0.001 ); 199 | 200 | vec3 kD_light = ( 1. - F_light )*( 1. - metallic ); 201 | 202 | color += ( kD_light*base/3.14159265 + specular )*radiance[i]*diffuse_factor( N_L, lwrap )/*cN_L*/; 203 | } 204 | #endif 205 | 206 | #ifdef GLFX_AO 207 | #ifdef GLFX_TEX_MRAO 208 | color *= mrao.z; 209 | #else 210 | color *= BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_ao),var_uv).x; 211 | #endif 212 | #endif 213 | 214 | #ifdef GLFX_TEX_EMI 215 | color += g2l(BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_emi),var_uv).xyz); 216 | #endif 217 | 218 | #ifdef GLFX_USE_SHADOW 219 | color = mix( color, vec3(0.), glfx_shadow_factor() ); 220 | #endif 221 | 222 | bnb_FragColor = vec4(l2g(color),opacity); 223 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/hair_base.vert: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define bnb_IDX_OFFSET 0 4 | #ifdef BNB_VK_1 5 | #define gl_VertexID gl_VertexIndex 6 | #define gl_InstanceID gl_InstanceIndex 7 | #endif 8 | 9 | 10 | #define GLFX_IBL 11 | #define GLFX_TBN 12 | #define GLFX_TEX_MRAO 13 | #define GLFX_LIGHTING 14 | 15 | BNB_LAYOUT_LOCATION(0) BNB_IN vec3 attrib_pos; 16 | #ifdef GLFX_LIGHTING 17 | #ifdef BNB_VK_1 18 | BNB_LAYOUT_LOCATION(1) BNB_IN uint attrib_n; 19 | #else 20 | BNB_LAYOUT_LOCATION(1) BNB_IN vec4 attrib_n; 21 | #endif 22 | #ifdef GLFX_TBN 23 | #ifdef BNB_VK_1 24 | BNB_LAYOUT_LOCATION(2) BNB_IN uint attrib_t; 25 | #else 26 | BNB_LAYOUT_LOCATION(2) BNB_IN vec4 attrib_t; 27 | #endif 28 | #endif 29 | #endif 30 | BNB_LAYOUT_LOCATION(3) BNB_IN vec2 attrib_uv; 31 | #ifndef BNB_GL_ES_1 32 | BNB_LAYOUT_LOCATION(4) BNB_IN uvec4 attrib_bones; 33 | #else 34 | BNB_LAYOUT_LOCATION(4) BNB_IN vec4 attrib_bones; 35 | #endif 36 | #ifndef GLFX_1_BONE 37 | BNB_LAYOUT_LOCATION(5) BNB_IN vec4 attrib_weights; 38 | #endif 39 | 40 | 41 | 42 | BNB_DECLARE_SAMPLER_2D(12, 13, bnb_BONES); 43 | 44 | #ifdef GLFX_USE_UVMORPH 45 | 46 | BNB_DECLARE_SAMPLER_2D(14, 15, bnb_UVMORPH); 47 | #ifdef GLFX_USE_BG 48 | 49 | BNB_DECLARE_SAMPLER_2D(16, 17, bnb_STATICPOS); 50 | #endif 51 | #endif 52 | 53 | #ifdef GLFX_USE_BG 54 | BNB_OUT(6) vec2 var_bg_uv; 55 | #endif 56 | 57 | #ifdef GLFX_USE_AUTOMORPH 58 | 59 | BNB_DECLARE_SAMPLER_2D(18, 19, bnb_MORPH); 60 | vec2 glfx_morph_coord( vec3 v ) 61 | { 62 | const float half_angle = radians(104.); 63 | const float y0 = -110.; 64 | const float y1 = 112.; 65 | float x = atan( v.x, v.z )/half_angle; 66 | float y = ((v.y-y0)/(y1-y0))*2. - 1.; 67 | return vec2(x,y); 68 | } 69 | #ifndef GLFX_AUTOMORPH_BONE 70 | vec3 glfx_auto_morph( vec3 v ) 71 | { 72 | vec2 morph_uv = glfx_morph_coord(v)*0.5 + 0.5; 73 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_MORPH), morph_uv ).xyz; 74 | return v + translation; 75 | } 76 | #else 77 | vec3 glfx_auto_morph_bone( vec3 v, mat3x4 m ) 78 | { 79 | vec2 morph_uv = glfx_morph_coord(vec3(m[0][3],m[1][3],m[2][3]))*0.5 + 0.5; 80 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_MORPH), morph_uv ).xyz; 81 | return v + translation; 82 | } 83 | #endif 84 | #endif 85 | 86 | BNB_OUT(0) vec2 var_uv; 87 | #ifdef GLFX_LIGHTING 88 | #ifdef GLFX_TBN 89 | BNB_OUT(1) vec3 var_t; 90 | BNB_OUT(2) vec3 var_b; 91 | #endif 92 | BNB_OUT(3) vec3 var_n; 93 | BNB_OUT(4) vec3 var_v; 94 | #endif 95 | 96 | #ifdef GLFX_USE_SHADOW 97 | BNB_OUT(5) vec3 var_shadow_coord; 98 | vec3 spherical_proj( vec2 fovM, vec2 fovP, float zn, float zf, vec3 v ) 99 | { 100 | vec2 xy = (atan( v.xy, v.zz )-(fovP+fovM)*0.5)/((fovP-fovM)*0.5); 101 | float z = (length(v)-(zn+zf)*0.5)/((zf-zn)*0.5); 102 | return vec3( xy, z ); 103 | } 104 | #endif 105 | 106 | mat3x4 get_bone( uint bone_idx, float k ) 107 | { 108 | float bx = float( int(bone_idx)*3 ); 109 | vec2 rts = 1./vec2(textureSize(BNB_SAMPLER_2D(bnb_BONES),0)); 110 | return mat3x4( 111 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx,k)+0.5)*rts ), 112 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx+1.,k)+0.5)*rts ), 113 | BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_BONES), (vec2(bx+2.,k)+0.5)*rts ) ); 114 | } 115 | 116 | void main() 117 | { 118 | mat3x4 m = get_bone( attrib_bones[0], bnb_ANIMKEY ); 119 | #ifndef GLFX_1_BONE 120 | if( attrib_weights[1] > 0. ) 121 | { 122 | m = m*attrib_weights[0] + get_bone( attrib_bones[1], bnb_ANIMKEY )*attrib_weights[1]; 123 | if( attrib_weights[2] > 0. ) 124 | { 125 | m += get_bone( attrib_bones[2], bnb_ANIMKEY )*attrib_weights[2]; 126 | if( attrib_weights[3] > 0. ) 127 | m += get_bone( attrib_bones[3], bnb_ANIMKEY )*attrib_weights[3]; 128 | } 129 | } 130 | #endif 131 | 132 | vec3 vpos = attrib_pos; 133 | 134 | #ifdef GLFX_USE_UVMORPH 135 | vec2 flip_uv = vec2( attrib_uv.x, 1. - attrib_uv.y ); 136 | vec3 translation = BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_UVMORPH),flip_uv).xyz; 137 | #ifdef GLFX_UVMORPH_Z_UP 138 | vpos += vec3(translation.x,-translation.z,translation.y); 139 | #else 140 | vpos += translation; 141 | #endif 142 | #endif 143 | 144 | vpos = vec4(vpos,1.)*m; 145 | 146 | #ifdef GLFX_USE_AUTOMORPH 147 | #ifndef GLFX_AUTOMORPH_BONE 148 | vpos = glfx_auto_morph( vpos ); 149 | #else 150 | vpos = glfx_auto_morph_bone( vpos, m ); 151 | #endif 152 | #endif 153 | 154 | gl_Position = bnb_MVP * vec4(vpos,1.); 155 | 156 | #ifdef GLFX_USE_BG 157 | #ifdef GLFX_USE_UVMORPH 158 | vec4 uvmorphed_view = bnb_MVP * vec4( BNB_TEXTURE_2D(BNB_SAMPLER_2D(bnb_STATICPOS),flip_uv).xyz + translation, 1. ); 159 | var_bg_uv = (uvmorphed_view.xy/uvmorphed_view.w)*0.5 + 0.5; 160 | #else 161 | var_bg_uv = (gl_Position.xy/gl_Position.w)*0.5 + 0.5; 162 | #endif 163 | #endif 164 | 165 | var_uv = attrib_uv; 166 | 167 | #ifdef GLFX_LIGHTING 168 | var_n = mat3(bnb_MV)*(bnb_decode_int1010102(attrib_n).xyz*mat3(m)); 169 | #ifdef GLFX_TBN 170 | var_t = mat3(bnb_MV)*(bnb_decode_int1010102(attrib_t).xyz*mat3(m)); 171 | var_b = bnb_decode_int1010102(attrib_t).w*cross( var_n, var_t ); 172 | #endif 173 | var_v = (bnb_MV*vec4(vpos,1.)).xyz; 174 | #endif 175 | 176 | #ifdef GLFX_USE_SHADOW 177 | var_shadow_coord = spherical_proj( 178 | vec2(-radians(60.),-radians(20.)),vec2(radians(60.),radians(100.)), 179 | 400.,70., 180 | vpos+vec3(0.,100.,50.))*0.5+0.5; 181 | #endif 182 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/retouch.frag: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define TEETH_WHITENING 4 | #define teethWhiteningCoeff 1.0 5 | #define EYES_WHITENING 6 | #define eyesWhiteningCoeff 0.5 7 | #define EYES_HIGHLIGHT 8 | #define SOFT_LIGHT_LAYER 9 | #define NORMAL_LAYER 10 | #define SOFT_SKIN 11 | #define skinSoftIntensity 0.7 12 | #define SHARPEN_TEETH 13 | #define teethSharpenIntensity 0.2 14 | #define SHARPEN_EYES 15 | #define eyesSharpenIntensity 0.3 16 | #define PSI 0.1 17 | 18 | 19 | BNB_IN(0) vec2 var_uv; 20 | BNB_IN(1) vec2 var_bg_uv; 21 | BNB_IN(2) mat4 sp; 22 | 23 | 24 | BNB_DECLARE_SAMPLER_2D(0, 1, selection_tex); 25 | 26 | BNB_DECLARE_SAMPLER_2D(4, 5, lookupTexEyes); 27 | 28 | BNB_DECLARE_SAMPLER_2D(2, 3, lookupTexTeeth); 29 | 30 | BNB_DECLARE_SAMPLER_2D(12, 13, glfx_BACKGROUND); 31 | 32 | #if defined(EYES_HIGHLIGHT) 33 | 34 | BNB_DECLARE_SAMPLER_2D(10, 11, tex_highlight); 35 | #endif 36 | #ifdef SOFT_LIGHT_LAYER 37 | 38 | BNB_DECLARE_SAMPLER_2D(6, 7, tex_softLight); 39 | #endif 40 | #ifdef NORMAL_LAYER 41 | 42 | BNB_DECLARE_SAMPLER_2D(8, 9, tex_normalMakeup); 43 | #endif 44 | 45 | vec4 textureLookup(vec4 originalColor, BNB_DECLARE_SAMPLER_2D_ARGUMENT(lookupTexture)) 46 | { 47 | const float epsilon = 0.000001; 48 | const float lutSize = 512.0; 49 | 50 | float blueValue = (originalColor.b * 255.0) / 4.0; 51 | 52 | vec2 mulB = clamp(floor(blueValue) + vec2(0.0, 1.0), 0.0, 63.0); 53 | vec2 row = floor(mulB / 8.0 + epsilon); 54 | vec4 row_col = vec4(row, mulB - row * 8.0); 55 | vec4 lookup = originalColor.ggrr * (63.0 / lutSize) + row_col * (64.0 / lutSize) + (0.5 / lutSize); 56 | 57 | float factor = blueValue - mulB.x; 58 | 59 | vec3 sampled1 = BNB_TEXTURE_2D_LOD(BNB_SAMPLER_2D(lookupTexture), lookup.zx, 0.).rgb; 60 | vec3 sampled2 = BNB_TEXTURE_2D_LOD(BNB_SAMPLER_2D(lookupTexture), lookup.wy, 0.).rgb; 61 | 62 | vec3 res = mix(sampled1, sampled2, factor); 63 | return vec4(res, originalColor.a); 64 | } 65 | 66 | vec4 whitening(vec4 originalColor, float factor, BNB_DECLARE_SAMPLER_2D_ARGUMENT(lookup)) { 67 | vec4 color = textureLookup(originalColor, BNB_PASS_SAMPLER_ARGUMENT(lookup)); 68 | return mix(originalColor, color, factor); 69 | } 70 | 71 | vec4 sharpen(vec4 originalColor, float factor) { 72 | vec4 total = 5.0 * originalColor - BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[0].zw) - BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[1].zw) - BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[2].zw) - BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[3].zw); 73 | vec4 result = mix(originalColor, total, factor); 74 | return clamp(result, 0.0, 1.0);; 75 | } 76 | 77 | vec4 getLuminance4(mat4 color) { 78 | const vec4 rgb2y = vec4(0.299, 0.587, 0.114, 0.0); 79 | return rgb2y * color; 80 | } 81 | 82 | float getLuminance(vec4 color) { 83 | const vec4 rgb2y = vec4(0.299, 0.587, 0.114, 0.0); 84 | return dot(color, rgb2y); 85 | } 86 | 87 | vec4 getWeight(float intensity, vec4 nextIntensity) { 88 | vec4 lglg = log(nextIntensity / intensity) * log(nextIntensity / intensity); 89 | return exp(lglg / (-2.0 * PSI * PSI )); 90 | } 91 | 92 | vec4 softSkin(vec4 originalColor, float factor) { 93 | vec4 screenColor = originalColor; 94 | float intensity = getLuminance(screenColor); 95 | float summ = 1.0; 96 | 97 | mat4 nextColor; 98 | nextColor[0] = BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[0].xy); 99 | nextColor[1] = BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[1].xy); 100 | nextColor[2] = BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[2].xy); 101 | nextColor[3] = BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), sp[3].xy); 102 | vec4 nextIntensity = getLuminance4(nextColor); 103 | vec4 curr = 0.367 * getWeight(intensity, nextIntensity); 104 | summ += dot(curr, vec4(1.0)); 105 | screenColor += nextColor * curr; 106 | screenColor = screenColor / summ; 107 | 108 | screenColor = mix(originalColor, screenColor, factor); 109 | return screenColor; 110 | } 111 | 112 | float blendSoftLight(float a, float b) { 113 | return (a+2.*b*(1.-a))*a; 114 | } 115 | 116 | vec3 blendSoftLight(vec3 base, vec3 blend) { 117 | return vec3(blendSoftLight(base.r,blend.r),blendSoftLight(base.g,blend.g),blendSoftLight(base.b,blend.b)); 118 | } 119 | 120 | vec3 blendSoftLight(vec3 base, vec3 blend, float opacity) { 121 | return (blendSoftLight(base, blend) * opacity + base * (1.0 - opacity)); 122 | } 123 | 124 | void main() 125 | { 126 | vec4 maskColor = BNB_TEXTURE_2D(BNB_SAMPLER_2D(selection_tex), var_uv); 127 | vec4 res = BNB_TEXTURE_2D(BNB_SAMPLER_2D(glfx_BACKGROUND), var_bg_uv ); 128 | 129 | #ifdef SOFT_SKIN 130 | res = softSkin(res, maskColor.r * skinSoftIntensity); 131 | #endif 132 | 133 | #ifdef SKIN_TEXTURING 134 | vec4 skinTexture = texture(skin_tex, var_uv); 135 | vec4 diff = abs(skinTexture - res); 136 | res = mix(res, diff, skinTexturingIntensity); 137 | #endif 138 | 139 | #ifdef SHARPEN_TEETH 140 | res = sharpen(res, maskColor.g * teethSharpenIntensity); 141 | #endif 142 | 143 | #if defined(TEETH_WHITENING) 144 | res = whitening(res, maskColor.g * teethWhiteningCoeff, BNB_PASS_SAMPLER_ARGUMENT(lookupTexTeeth)); 145 | #endif 146 | 147 | 148 | #ifdef SHARPEN_EYES 149 | res = sharpen(res, maskColor.b * eyesSharpenIntensity); 150 | #endif 151 | 152 | #if defined(EYES_WHITENING) 153 | res = whitening(res, maskColor.b * eyesWhiteningCoeff, BNB_PASS_SAMPLER_ARGUMENT(lookupTexEyes)); 154 | #endif 155 | 156 | #if defined(EYES_HIGHLIGHT) 157 | res = res + vec4( BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_highlight), var_uv ).xyz, 0. ); 158 | #endif 159 | 160 | vec2 uvh = var_uv; 161 | uvh.x = abs(2.0 * (uvh.x - 0.5)); 162 | 163 | #ifdef SOFT_LIGHT_LAYER 164 | res.xyz = blendSoftLight( res.xyz, BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_softLight), uvh ).xyz ); 165 | #endif 166 | 167 | #ifdef NORMAL_LAYER 168 | vec4 makeup2 = BNB_TEXTURE_2D(BNB_SAMPLER_2D(tex_normalMakeup), uvh ); 169 | res.xyz = mix( res.xyz, makeup2.xyz, makeup2.w ); 170 | #endif 171 | 172 | bnb_FragColor = res; 173 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/TrollGrandma/shaders/retouch.vert: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define bnb_IDX_OFFSET 0 4 | #ifdef BNB_VK_1 5 | #define gl_VertexID gl_VertexIndex 6 | #define gl_InstanceID gl_InstanceIndex 7 | #endif 8 | 9 | BNB_LAYOUT_LOCATION(0) BNB_IN vec3 attrib_pos; 10 | BNB_LAYOUT_LOCATION(1) BNB_IN vec3 attrib_pos_static; 11 | BNB_LAYOUT_LOCATION(2) BNB_IN vec2 attrib_uv; 12 | BNB_LAYOUT_LOCATION(3) BNB_IN vec4 attrib_red_mask; 13 | 14 | 15 | BNB_OUT(0) vec2 var_uv; 16 | BNB_OUT(1) vec2 var_bg_uv; 17 | 18 | BNB_OUT(2) mat4 sp; 19 | 20 | invariant gl_Position; 21 | 22 | const float dx = 1.0 / 720.0; 23 | const float dy = 1.0 / 1280.0; 24 | 25 | const float delta = 5.; 26 | 27 | const float sOfssetXneg = -delta * dx; 28 | const float sOffsetYneg = -delta * dy; 29 | const float sOffsetXpos = delta * dx; 30 | const float sOffsetYpos = delta * dy; 31 | 32 | void main() 33 | { 34 | gl_Position = bnb_MVP * vec4( attrib_pos, 1. ); 35 | var_uv = attrib_uv; 36 | var_bg_uv = (gl_Position.xy / gl_Position.w) * 0.5 + 0.5; 37 | 38 | sp[0].xy = var_bg_uv + vec2(sOfssetXneg, sOffsetYneg); 39 | sp[1].xy = var_bg_uv + vec2(sOfssetXneg, sOffsetYpos); 40 | sp[2].xy = var_bg_uv + vec2(sOffsetXpos, sOffsetYneg); 41 | sp[3].xy = var_bg_uv + vec2(sOffsetXpos, sOffsetYpos); 42 | 43 | vec2 delta = vec2(dx, dy); 44 | sp[0].zw = var_bg_uv + vec2(-delta.x, -delta.y); 45 | sp[1].zw = var_bg_uv + vec2(delta.x, -delta.y); 46 | sp[2].zw = var_bg_uv + vec2(-delta.x, delta.y); 47 | sp[3].zw = var_bg_uv + vec2(delta.x, delta.y); 48 | #ifdef BNB_VK_1 49 | var_bg_uv.y = 1. - var_bg_uv.y; 50 | #endif 51 | 52 | #ifdef BNB_VK_1 53 | sp[0].y = 1. - sp[0].y; 54 | sp[1].y = 1. - sp[1].y; 55 | sp[2].y = 1. - sp[2].y; 56 | sp[3].y = 1. - sp[3].y; 57 | sp[0].w = 1. - sp[0].w; 58 | sp[1].w = 1. - sp[1].w; 59 | sp[2].w = 1. - sp[2].w; 60 | sp[3].w = 1. - sp[3].w; 61 | #endif 62 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/bnb-resources/effects/watermark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/bnb-resources/effects/watermark.png -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/face_video_1080p.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/face_video_1080p.mp4 -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/face_video_1080p_r180.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/face_video_1080p_r180.mp4 -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/face_video_1080p_r270.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/face_video_1080p_r270.mp4 -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/face_video_1080p_r90.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/face_video_1080p_r90.mp4 -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/assets/face_video_720p.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Banuba/quickstart-android/e8a8023bbdfdf56ab2de1f37a42d933ba95add8c/effect_player_realtime_preview/src/main/assets/face_video_720p.mp4 -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/java/com/banuba/sdk/example/effect_player_realtime_preview/Application.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.effect_player_realtime_preview 2 | 3 | import com.banuba.sdk.manager.BanubaSdkManager 4 | import com.banuba.sdk.example.common.BANUBA_CLIENT_TOKEN 5 | 6 | class Application : android.app.Application() { 7 | 8 | override fun onCreate() { 9 | super.onCreate() 10 | 11 | // It crashes if token is empty string with 12 | // 13 | // RuntimeException: 14 | // Unable to create application com.banuba.sdk.samples.SamplesApp: 15 | // java.lang.RuntimeException: Can't parse client token. 16 | // 17 | // Please, contact Banuba for obtain a correct client token. 18 | 19 | BanubaSdkManager.initialize(this, BANUBA_CLIENT_TOKEN) 20 | } 21 | } -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/java/com/banuba/sdk/example/effect_player_realtime_preview/CameraPreviewActivity.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.effect_player_realtime_preview 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import com.banuba.sdk.input.CameraDevice 6 | import com.banuba.sdk.input.CameraInput 7 | import com.banuba.sdk.output.SurfaceOutput 8 | import com.banuba.sdk.player.Player 9 | import kotlinx.android.synthetic.main.activity_camera_preview.* 10 | 11 | 12 | /** 13 | * Sample activity that shows how to open Android camera with Banuba SDK. 14 | */ 15 | class CameraPreviewActivity : AppCompatActivity(R.layout.activity_camera_preview) { 16 | // The player executes the main pipeline 17 | private val player by lazy(LazyThreadSafetyMode.NONE) { 18 | Player() 19 | } 20 | 21 | // This camera device will pass frames to the CameraInput 22 | private val cameraDevice by lazy(LazyThreadSafetyMode.NONE) { 23 | CameraDevice(requireNotNull(this.applicationContext), this@CameraPreviewActivity) 24 | } 25 | 26 | // The result will be displayed on the surface 27 | private val surfaceOutput by lazy(LazyThreadSafetyMode.NONE) { 28 | SurfaceOutput(surfaceView.holder) 29 | } 30 | 31 | override fun onCreate(savedInstanceState: Bundle?) { 32 | super.onCreate(savedInstanceState) 33 | // Set layer will take input frames from and where the player will display the result 34 | player.use(CameraInput(cameraDevice), surfaceOutput) 35 | } 36 | 37 | override fun onStart() { 38 | super.onStart() 39 | // We start the camera and then player starts taking frames 40 | cameraDevice.start() 41 | } 42 | 43 | 44 | override fun onResume() { 45 | super.onResume() 46 | // Running the player 47 | player.play() 48 | } 49 | 50 | override fun onPause() { 51 | super.onPause() 52 | // Pause the player when activity is inactive 53 | player.pause() 54 | } 55 | 56 | override fun onStop() { 57 | // After this method, the camera will stop capturing frames and transmitting them to player 58 | cameraDevice.stop() 59 | super.onStop() 60 | } 61 | 62 | override fun onDestroy() { 63 | // After you are done using the player, you must free all resources by calling close() method 64 | cameraDevice.close() 65 | surfaceOutput.close() 66 | player.close() 67 | super.onDestroy() 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/java/com/banuba/sdk/example/effect_player_realtime_preview/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.effect_player_realtime_preview 2 | 3 | import android.Manifest 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.content.pm.PackageManager 7 | import android.os.Bundle 8 | import android.widget.Toast 9 | import androidx.appcompat.app.AppCompatActivity 10 | import androidx.core.content.ContextCompat 11 | import kotlinx.android.synthetic.main.activity_main.applyMaskButton 12 | import kotlinx.android.synthetic.main.activity_main.openCameraButton 13 | import kotlinx.android.synthetic.main.activity_main.recordVideoButton 14 | import kotlinx.android.synthetic.main.activity_main.videoMaskButton 15 | 16 | class MainActivity : AppCompatActivity(R.layout.activity_main) { 17 | 18 | companion object { 19 | val REQUIRED_PERMISSIONS = arrayOf( 20 | Manifest.permission.CAMERA, 21 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 22 | Manifest.permission.RECORD_AUDIO 23 | ) 24 | 25 | const val REQUEST_CODE_PERMISSIONS = 1000 26 | } 27 | 28 | 29 | override fun onCreate(savedInstanceState: Bundle?) { 30 | super.onCreate(savedInstanceState) 31 | 32 | openCameraButton.setOnClickListener { 33 | startActivity(Intent(applicationContext, CameraPreviewActivity::class.java)) 34 | } 35 | 36 | applyMaskButton.setOnClickListener { 37 | startActivity(Intent(applicationContext, MaskActivity::class.java)) 38 | } 39 | 40 | recordVideoButton.setOnClickListener { 41 | startActivity(Intent(applicationContext, VideoRecordingActivity::class.java)) 42 | } 43 | 44 | videoMaskButton.setOnClickListener { 45 | startActivity(Intent(applicationContext, VideoMaskActivity::class.java)) 46 | } 47 | } 48 | 49 | override fun onStart() { 50 | super.onStart() 51 | if (!allPermissionsGranted()) { 52 | requestPermissions(REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS) 53 | } 54 | } 55 | 56 | override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, results: IntArray) { 57 | if (!requireAllPermissionsGranted(permissions, results)) { 58 | finish() 59 | } 60 | super.onRequestPermissionsResult(requestCode, permissions, results) 61 | } 62 | 63 | private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all { 64 | ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED 65 | } 66 | } 67 | 68 | fun Context.requireAllPermissionsGranted(permissions: Array, results: IntArray): Boolean { 69 | val notGrantedPermissionIndex = results.indexOfFirst { result -> 70 | result != PackageManager.PERMISSION_GRANTED 71 | } 72 | 73 | return if (notGrantedPermissionIndex != -1) { 74 | val notGrantedPermission = permissions[notGrantedPermissionIndex] 75 | Toast.makeText(applicationContext, 76 | """Not all permissions granted. Please grant $notGrantedPermission permission.""", 77 | Toast.LENGTH_LONG) 78 | .show() 79 | 80 | false 81 | } else { 82 | true 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/java/com/banuba/sdk/example/effect_player_realtime_preview/MaskActivity.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.effect_player_realtime_preview 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import com.banuba.sdk.input.CameraDevice 6 | import com.banuba.sdk.input.CameraInput 7 | import com.banuba.sdk.output.SurfaceOutput 8 | import com.banuba.sdk.player.Player 9 | import com.banuba.sdk.player.PlayerTouchListener 10 | import kotlinx.android.synthetic.main.activity_apply_mask.* 11 | import kotlinx.android.synthetic.main.activity_camera_preview.surfaceView 12 | 13 | 14 | /** 15 | * Sample activity that shows how to apply masks with Banuba SDK. 16 | * Some Banuba masks can change their appearance if tapping on them. 17 | */ 18 | class MaskActivity : AppCompatActivity(R.layout.activity_apply_mask) { 19 | companion object { 20 | private const val MASK_NAME = "effects/TrollGrandma" 21 | } 22 | 23 | // The player executes the main pipeline 24 | private val player by lazy(LazyThreadSafetyMode.NONE) { 25 | Player() 26 | } 27 | 28 | // This camera device will pass frames to the CameraInput 29 | private val cameraDevice by lazy(LazyThreadSafetyMode.NONE) { 30 | CameraDevice(requireNotNull(this.applicationContext), this@MaskActivity) 31 | } 32 | 33 | // The result will be displayed on the surface 34 | private val surfaceOutput by lazy(LazyThreadSafetyMode.NONE) { 35 | SurfaceOutput(surfaceView.holder) 36 | } 37 | 38 | override fun onCreate(savedInstanceState: Bundle?) { 39 | super.onCreate(savedInstanceState) 40 | 41 | // Set layer will take input frames from and where the player will display the result 42 | player.use(CameraInput(cameraDevice), surfaceOutput) 43 | 44 | // Set custom OnTouchListener to change mask style. 45 | surfaceView.setOnTouchListener(PlayerTouchListener(this, player)) 46 | 47 | var shouldApply = false 48 | showMaskButton.setOnClickListener { 49 | shouldApply = !shouldApply 50 | 51 | showMaskButton.text = getString(if (shouldApply) R.string.hide_mask else R.string.show_mask) 52 | 53 | // The mask is loaded asynchronously and applied 54 | player.loadAsync(if (shouldApply) MASK_NAME else "") 55 | } 56 | } 57 | 58 | override fun onStart() { 59 | super.onStart() 60 | // We start the camera and then player starts taking frames 61 | cameraDevice.start() 62 | } 63 | 64 | override fun onResume() { 65 | super.onResume() 66 | // Running the player 67 | player.play() 68 | } 69 | 70 | override fun onPause() { 71 | super.onPause() 72 | // Pause the player when activity is inactive 73 | player.pause() 74 | } 75 | 76 | override fun onStop() { 77 | // After this method, the camera will stop capturing frames and transmitting them to player 78 | cameraDevice.stop() 79 | super.onStop() 80 | } 81 | 82 | override fun onDestroy() { 83 | // After you are done using the player, you must free all resources by calling close() method 84 | cameraDevice.close() 85 | surfaceOutput.close() 86 | player.close() 87 | super.onDestroy() 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/java/com/banuba/sdk/example/effect_player_realtime_preview/VideoMaskActivity.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.effect_player_realtime_preview 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.media.MediaCodec 6 | import android.media.MediaFormat 7 | import android.os.Bundle 8 | import android.util.Pair 9 | import android.view.View 10 | import androidx.appcompat.app.AppCompatActivity 11 | import androidx.core.content.FileProvider 12 | import com.banuba.sdk.input.VideoInput 13 | import com.banuba.sdk.output.VideoOutput 14 | import com.banuba.sdk.player.Player 15 | import com.banuba.sdk.video.IAudioDataProvider 16 | import kotlinx.android.synthetic.main.activity_mask_video.btn_open_original 17 | import kotlinx.android.synthetic.main.activity_mask_video.btn_video_action 18 | import kotlinx.android.synthetic.main.activity_mask_video.progress 19 | import java.io.File 20 | import java.io.FileOutputStream 21 | import java.nio.ByteBuffer 22 | import java.util.LinkedList 23 | 24 | class VideoMaskActivity : AppCompatActivity(R.layout.activity_mask_video) { 25 | companion object { 26 | private const val MASK_NAME = "effects/TrollGrandma" 27 | private const val VIDEO_FILE = "face_video_720p.mp4" 28 | } 29 | 30 | // The player executes the main pipeline 31 | private val player by lazy(LazyThreadSafetyMode.NONE) { 32 | Player() 33 | } 34 | 35 | // This video input will pass frames from the video file to the player 36 | private val videoInput by lazy(LazyThreadSafetyMode.NONE) { 37 | VideoInput() 38 | } 39 | 40 | // The result will be recorded to the file 41 | private val videoOutput by lazy(LazyThreadSafetyMode.NONE) { 42 | VideoOutput() 43 | } 44 | 45 | private var isVideoReady = false 46 | 47 | override fun onCreate(savedInstanceState: Bundle?) { 48 | super.onCreate(savedInstanceState) 49 | 50 | // Synchronized effect loading 51 | player.load(MASK_NAME) 52 | 53 | // Set layer will take input frames from and where the player will display the result 54 | player.use(videoInput, videoOutput) 55 | 56 | val inputFile = copyFromAssetsToFile(VIDEO_FILE) 57 | val outputFile = File(getExternalFilesDir(null), "$VIDEO_FILE.mask.mp4") 58 | 59 | btn_open_original.setOnClickListener { 60 | showVideo(inputFile) 61 | } 62 | 63 | btn_video_action.setOnClickListener { 64 | if (isVideoReady) { 65 | showVideo(outputFile) 66 | } else { 67 | processVideo(inputFile, outputFile) 68 | } 69 | } 70 | } 71 | 72 | override fun onDestroy() { 73 | videoOutput.close() 74 | player.close() 75 | super.onDestroy() 76 | } 77 | 78 | fun processVideo(inputFile: File, outputFile: File) { 79 | // Set callback for video processing 80 | videoInput.processVideoFile(inputFile, object : VideoInput.IVideoFrameStatus { 81 | override fun onStart() { 82 | runOnUiThread { 83 | progress.visibility = View.VISIBLE 84 | btn_video_action.isEnabled = false 85 | btn_video_action.text = getString(R.string.wait_for_processing) 86 | } 87 | 88 | // Set the appropriate rendering mode. For video processing it should be MANUAL 89 | player.setRenderMode(Player.RenderMode.MANUAL) 90 | 91 | // We transfer audio data from the input file to the output file without changes. 92 | // If audio data is not needed, simply remove this call. 93 | videoOutput.startRecording(outputFile, object : IAudioDataProvider { 94 | override fun getAudioFormat(): MediaFormat? = videoInput.audioFormat 95 | override fun getAudioData(): LinkedList?>? = videoInput.audioData 96 | }) 97 | } 98 | 99 | override fun onFrame() { 100 | // Processing the next frame upon request. 101 | player.render() 102 | } 103 | 104 | override fun onError(throwable: Throwable) { 105 | throw throwable; 106 | } 107 | 108 | override fun onFinish() { 109 | // We are waiting for the video file to finish recording. 110 | videoOutput.stopRecordingAndWaitForFinish() 111 | 112 | // Switch the rendering mode to the previous one. 113 | player.setRenderMode(Player.RenderMode.LOOP) 114 | 115 | runOnUiThread { 116 | progress.visibility = View.INVISIBLE 117 | btn_video_action.isEnabled = true 118 | btn_video_action.text = getString(R.string.open_video) 119 | isVideoReady = true 120 | } 121 | } 122 | }) 123 | } 124 | 125 | fun showVideo(videoFile: File) { 126 | val uri = FileProvider.getUriForFile(this, this.packageName, videoFile) 127 | val intent = Intent(Intent.ACTION_VIEW, uri) 128 | intent.setDataAndType(uri, "video/mp4") 129 | intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION 130 | startActivity(intent) 131 | } 132 | 133 | fun copyFromAssetsToFile(filename: String): File { 134 | val file = File(getExternalFilesDir(null), filename) 135 | file.parentFile?.mkdirs() 136 | assets.open(filename).copyTo(FileOutputStream(file)) 137 | return file 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/java/com/banuba/sdk/example/effect_player_realtime_preview/VideoRecordingActivity.kt: -------------------------------------------------------------------------------- 1 | package com.banuba.sdk.example.effect_player_realtime_preview 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.view.View 6 | import androidx.appcompat.app.AppCompatActivity 7 | import androidx.core.content.FileProvider 8 | import com.banuba.sdk.input.CameraDevice 9 | import com.banuba.sdk.input.CameraInput 10 | import com.banuba.sdk.output.SurfaceOutput 11 | import com.banuba.sdk.output.VideoOutput 12 | import com.banuba.sdk.player.Player 13 | import kotlinx.android.synthetic.main.activity_camera_preview.surfaceView 14 | import kotlinx.android.synthetic.main.activity_video_recording.* 15 | import java.io.File 16 | 17 | 18 | /** 19 | * Sample activity that shows how to record video with Banuba SDK PlayerAPI. 20 | * 21 | * NOTE: 22 | * Applied masks are recorded as well. 23 | */ 24 | class VideoRecordingActivity : AppCompatActivity(R.layout.activity_video_recording) { 25 | // The player executes the main pipeline 26 | private val player by lazy(LazyThreadSafetyMode.NONE) { 27 | Player() 28 | } 29 | 30 | // This camera device will pass frames to the CameraInput 31 | private val cameraDevice by lazy(LazyThreadSafetyMode.NONE) { 32 | CameraDevice(requireNotNull(this.applicationContext), this@VideoRecordingActivity) 33 | } 34 | 35 | // The result will be displayed on the surface 36 | private val surfaceOutput by lazy(LazyThreadSafetyMode.NONE) { 37 | SurfaceOutput(surfaceView.holder) 38 | } 39 | 40 | // Also the result will be recorded to the video file 41 | private val videoOutput by lazy(LazyThreadSafetyMode.NONE) { 42 | VideoOutput() 43 | } 44 | 45 | override fun onCreate(savedInstanceState: Bundle?) { 46 | super.onCreate(savedInstanceState) 47 | 48 | // Set layer will take input frames from and where the player will display the result 49 | player.use(CameraInput(cameraDevice), arrayOf(surfaceOutput, videoOutput)) 50 | 51 | var stateVideoButton = 0 52 | var videoFileName = File("") 53 | recordActionButton.setOnClickListener { 54 | if (stateVideoButton == 0) { // Start recording 55 | // Set the option if you need to record audio from the microphone 56 | videoOutput.recordAudioFromMicrophone(recordAudioSwitch.isChecked) 57 | // Start recording to the video file 58 | videoFileName = generateOutputVideoFile() 59 | videoOutput.startRecording(videoFileName) 60 | 61 | recordActionButton.text = getString(R.string.stop) 62 | recordAudioSwitch.visibility = View.GONE 63 | 64 | 65 | } else if (stateVideoButton == 1) { // Stop recording 66 | // Stop recording and wait for finish 67 | videoOutput.stopRecordingAndWaitForFinish() 68 | 69 | recordActionButton.text = getString(R.string.play) 70 | recordAudioSwitch.visibility = View.GONE 71 | } else { // Play video 72 | showVideo(videoFileName) 73 | 74 | recordActionButton.text = getString(R.string.start) 75 | recordAudioSwitch.visibility = View.VISIBLE 76 | } 77 | 78 | stateVideoButton = (stateVideoButton + 1) % 3 79 | } 80 | } 81 | 82 | override fun onStart() { 83 | super.onStart() 84 | // We start the camera and then player starts taking frames 85 | cameraDevice.start() 86 | } 87 | 88 | override fun onResume() { 89 | super.onResume() 90 | // Running the player 91 | player.play() 92 | } 93 | 94 | override fun onPause() { 95 | super.onPause() 96 | // Pause the player when activity is inactive 97 | player.pause() 98 | } 99 | 100 | override fun onStop() { 101 | // After this method, the camera will stop capturing frames and transmitting them to player 102 | cameraDevice.stop() 103 | super.onStop() 104 | } 105 | 106 | override fun onDestroy() { 107 | // After you are done using the player, you must free all resources by calling close() method 108 | player.close() 109 | cameraDevice.close() 110 | surfaceOutput.close() 111 | videoOutput.close() 112 | super.onDestroy() 113 | } 114 | 115 | fun showVideo(videoFile: File) { 116 | val uri = FileProvider.getUriForFile(this, this.packageName, videoFile) 117 | val intent = Intent(Intent.ACTION_VIEW, uri) 118 | intent.setDataAndType(uri, "video/mp4") 119 | intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION 120 | startActivity(intent) 121 | } 122 | 123 | private fun generateOutputVideoFile(): File = File(getExternalFilesDir(null), 124 | "banuba_video_${System.currentTimeMillis()}.mp4") 125 | } 126 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /effect_player_realtime_preview/src/main/res/layout/activity_apply_mask.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 |