Compare commits
34
Commits
ac43d3b0aa
...
all_sample
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a43bd12970 | ||
|
|
1852717ae3 | ||
|
|
af56b1e5c4 | ||
|
|
4e7ef7ed93 | ||
|
|
1b201b8831 | ||
|
|
ad8ce037fd | ||
|
|
41756e71df | ||
|
|
adf45c1b55 | ||
|
|
f63f46e975 | ||
|
|
3ca95b90f8 | ||
|
|
225591bf22 | ||
|
|
baa6733872 | ||
|
|
00106ac0f6 | ||
|
|
cbdbdb5698 | ||
|
|
203b211bde | ||
|
|
fc9f9d7054 | ||
|
|
2026c41a23 | ||
|
|
6a5b5d9d5d | ||
|
|
0a2a5c45be | ||
|
|
8e721b9c42 | ||
|
|
0d90c33380 | ||
|
|
ea602c4f8f | ||
|
|
e4c89a2651 | ||
|
|
64ebe51ea4 | ||
|
|
541b610c87 | ||
|
|
ef7318dd35 | ||
|
|
2b4066fa32 | ||
|
|
a8eebf519f | ||
|
|
742635813b | ||
|
|
7cb94d268c | ||
|
|
a418be886c | ||
|
|
3d205ab184 | ||
|
|
e6bef08ecf | ||
|
|
fab00f8466 |
@@ -97,5 +97,5 @@ dependencies {
|
||||
implementation "androidx.camera:camera-lifecycle:$camerax_version"
|
||||
implementation "androidx.camera:camera-view:$camerax_version"
|
||||
//noinspection Aligned16KB
|
||||
implementation 'com.google.mediapipe:tasks-vision:0.20230731'
|
||||
implementation 'com.google.mediapipe:tasks-vision:0.10.26'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
task downloadTaskFile(type: Download) {
|
||||
src 'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task'
|
||||
dest project.ext.ASSET_DIR + '/face_landmarker.task'
|
||||
overwrite false
|
||||
}
|
||||
|
||||
preBuild.dependsOn downloadTaskFile
|
||||
Binary file not shown.
@@ -28,12 +28,15 @@
|
||||
<!-- Declare permissions -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<application android:label="@string/app_name"
|
||||
android:debuggable="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:theme="@style/AppTheme"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
tools:ignore="GoogleAppIndexingWarning,HardcodedDebugMode">
|
||||
|
||||
<activity android:name="com.khronos.vulkan_samples.MainActivity"
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
package com.khronos.vulkan_samples;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
import org.json.JSONObject;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
public class CameraDataFetcher {
|
||||
|
||||
public interface CameraDataCallback {
|
||||
void onSuccess(CameraData data);
|
||||
void onError(String errorMessage);
|
||||
}
|
||||
|
||||
// 数据模型类
|
||||
public static class CameraData {
|
||||
public float fov;
|
||||
public float x;
|
||||
public float y;
|
||||
public float z;
|
||||
public float sx;
|
||||
public float sy;
|
||||
public float sz;
|
||||
public float rotx;
|
||||
public float roty;
|
||||
public float rotz;
|
||||
public float camx;
|
||||
public float camy;
|
||||
public float camz;
|
||||
public float z_rate;
|
||||
|
||||
// 从JSONObject解析数据
|
||||
public static CameraData fromJson(JSONObject json) {
|
||||
CameraData data = new CameraData();
|
||||
try {
|
||||
data.fov = (float) json.getDouble("fov");
|
||||
data.x = (float)json.getDouble("x");
|
||||
data.y = (float)json.getDouble("y");
|
||||
data.z = (float)json.getDouble("z");
|
||||
data.sx = (float)json.getDouble("sx");
|
||||
data.sy = (float)json.getDouble("sy");
|
||||
data.sz = (float)json.getDouble("sz");
|
||||
data.rotx = (float)json.getDouble("rotx");
|
||||
data.roty = (float)json.getDouble("roty");
|
||||
data.rotz = (float)json.getDouble("rotz");
|
||||
data.camx = (float)json.getDouble("camx");
|
||||
data.camy = (float)json.getDouble("camy");
|
||||
data.camz = (float)json.getDouble("camz");
|
||||
data.z_rate = (float)json.getDouble("z_rate");
|
||||
} catch (Exception e) {
|
||||
Log.e("CameraData", "解析JSON失败: " + e.getMessage());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"CameraData{fov=%.2f, x=%.2f, y=%.2f, z=%.2f," +
|
||||
"rotx=%.2f, roty=%.2f, rotz=%.2f, camx=%.2f, camy=%.2f, camz=%.2f}",
|
||||
fov, x, y, z, rotx, roty, rotz, camx, camy, camz
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步获取相机数据
|
||||
* @param apiUrl 接口URL
|
||||
* @param callback 回调接口
|
||||
*/
|
||||
public static void fetchCameraData(String apiUrl, CameraDataCallback callback) {
|
||||
new FetchCameraDataTask(callback).execute(apiUrl);
|
||||
}
|
||||
|
||||
// 异步任务类
|
||||
private static class FetchCameraDataTask extends AsyncTask<String, Void, CameraData> {
|
||||
private CameraDataCallback callback;
|
||||
private String errorMessage;
|
||||
|
||||
public FetchCameraDataTask(CameraDataCallback callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CameraData doInBackground(String... urls) {
|
||||
if (urls.length == 0) {
|
||||
errorMessage = "URL不能为空";
|
||||
return null;
|
||||
}
|
||||
|
||||
String apiUrl = urls[0];
|
||||
HttpURLConnection connection = null;
|
||||
BufferedReader reader = null;
|
||||
|
||||
try {
|
||||
URL url = new URL(apiUrl);
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(10000); // 10秒连接超时
|
||||
connection.setReadTimeout(10000); // 10秒读取超时
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
InputStream inputStream = connection.getInputStream();
|
||||
reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
|
||||
StringBuilder response = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
|
||||
JSONObject jsonObject = new JSONObject(response.toString());
|
||||
return CameraData.fromJson(jsonObject);
|
||||
} else {
|
||||
errorMessage = "HTTP请求失败,响应码: " + responseCode;
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessage = "获取相机数据时发生错误: " + e.getMessage();
|
||||
Log.e("CameraDataFetcher", errorMessage, e);
|
||||
return null;
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
connection.disconnect();
|
||||
}
|
||||
try {
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("CameraDataFetcher", "关闭流时出错", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(CameraData result) {
|
||||
if (callback != null) {
|
||||
if (result != null) {
|
||||
callback.onSuccess(result);
|
||||
} else {
|
||||
callback.onError(errorMessage != null ? errorMessage : "未知错误");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.mediapipe.examples.facelandmarker
|
||||
package com.khronos.vulkan_samples
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
@@ -176,7 +176,7 @@ class FaceLandmarkerHelper(
|
||||
}
|
||||
}
|
||||
val rotatedBitmap = Bitmap.createBitmap(
|
||||
bitmapBuffer, 0, 0, bitmapBuffer.width, bitmapBuffer.height,
|
||||
bitmapBuffer, (640-480)/2, 0, bitmapBuffer.height, bitmapBuffer.height,
|
||||
matrix, true
|
||||
)
|
||||
|
||||
|
||||
@@ -3,17 +3,11 @@ package com.khronos.vulkan_samples;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.TextureView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -21,21 +15,27 @@ import androidx.camera.core.AspectRatio;
|
||||
import androidx.camera.core.CameraSelector;
|
||||
import androidx.camera.core.ImageAnalysis;
|
||||
import androidx.camera.core.ImageProxy;
|
||||
import androidx.camera.core.Preview;
|
||||
import androidx.camera.core.SurfaceRequest;
|
||||
import androidx.camera.lifecycle.ProcessCameraProvider;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.google.androidgamesdk.GameActivity;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.mediapipe.tasks.components.containers.NormalizedLandmark;
|
||||
import com.google.mediapipe.tasks.vision.core.RunningMode;
|
||||
import com.google.mediapipe.tasks.vision.facelandmarker.FaceLandmarkerResult;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class MainActivity extends GameActivity {
|
||||
public class MainActivity extends GameActivity implements FaceLandmarkerHelper.LandmarkerListener, CameraDataFetcher.CameraDataCallback {
|
||||
private ProcessCameraProvider cameraProvider;
|
||||
private void initCamera(){
|
||||
backgroundExecutor = Executors.newSingleThreadExecutor();
|
||||
@@ -46,6 +46,15 @@ public class MainActivity extends GameActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void detectFace(ImageProxy imageProxy) {
|
||||
faceLandmarkerHelper.detectLiveStream(
|
||||
imageProxy,false
|
||||
);
|
||||
}
|
||||
|
||||
private Handler handler = new Handler(Looper.getMainLooper());
|
||||
private Runnable cameraDataRunnable;
|
||||
private static final long INTERVAL = 1000; // 5秒间隔
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -61,11 +70,66 @@ public class MainActivity extends GameActivity {
|
||||
sendArgumentsToPlatform(argArray);
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// 隐藏状态栏
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
|
||||
initCamera();
|
||||
|
||||
backgroundExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
faceLandmarkerHelper = new FaceLandmarkerHelper(
|
||||
0.5f,
|
||||
0.5f,
|
||||
0.5f,
|
||||
1,
|
||||
0,
|
||||
RunningMode.LIVE_STREAM,
|
||||
MainActivity.this,
|
||||
MainActivity.this
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化Runnable
|
||||
cameraDataRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fetchCameraData();
|
||||
handler.postDelayed(this, INTERVAL); // 再次调度
|
||||
}
|
||||
};
|
||||
|
||||
// 开始周期性调用
|
||||
startPeriodicFetching();
|
||||
|
||||
|
||||
Log.i("MainActivity", "onCreate: ");
|
||||
}
|
||||
|
||||
boolean canFetch = true;
|
||||
private void fetchCameraData() {
|
||||
if(canFetch)
|
||||
{
|
||||
CameraDataFetcher.fetchCameraData("http://175.178.100.240:5000/data", MainActivity.this);
|
||||
canFetch = false;
|
||||
}
|
||||
}
|
||||
private void startPeriodicFetching() {
|
||||
handler.postDelayed(cameraDataRunnable, INTERVAL);
|
||||
}
|
||||
|
||||
private void stopPeriodicFetching() {
|
||||
handler.removeCallbacks(cameraDataRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
stopPeriodicFetching(); // 避免内存泄漏
|
||||
}
|
||||
|
||||
private boolean hasCameraPermission() {
|
||||
return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
@@ -80,6 +144,7 @@ public class MainActivity extends GameActivity {
|
||||
private static final int REQUEST_CAMERA_PERMISSION = 1001;
|
||||
ImageAnalysis imageAnalyzer;
|
||||
ExecutorService backgroundExecutor;
|
||||
FaceLandmarkerHelper faceLandmarkerHelper;
|
||||
|
||||
private void startCamera() {
|
||||
ListenableFuture<ProcessCameraProvider> cameraProviderFuture =
|
||||
@@ -90,7 +155,7 @@ public class MainActivity extends GameActivity {
|
||||
cameraProvider = cameraProviderFuture.get();
|
||||
|
||||
CameraSelector cameraSelector = new CameraSelector.Builder()
|
||||
.requireLensFacing(CameraSelector.LENS_FACING_FRONT)
|
||||
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
|
||||
.build();
|
||||
|
||||
imageAnalyzer = new ImageAnalysis.Builder()
|
||||
@@ -105,11 +170,12 @@ public class MainActivity extends GameActivity {
|
||||
@Override
|
||||
public void analyze(@NonNull ImageProxy image) {
|
||||
try {
|
||||
Log.d("Camera", "Received image: " + image.getWidth() + "x" + image.getHeight());
|
||||
//Log.d("Camera", "Received image: " + image.getWidth() + "x" + image.getHeight());
|
||||
processImageForVulkan(image);
|
||||
detectFace(image);
|
||||
} finally {
|
||||
image.close(); // 确保在这里关闭
|
||||
Log.d("Camera", "Image closed, ready for next frame");
|
||||
//image.close(); // 确保在这里关闭
|
||||
//Log.d("Camera", "Image closed, ready for next frame");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -122,6 +188,7 @@ public class MainActivity extends GameActivity {
|
||||
}, ContextCompat.getMainExecutor(this));
|
||||
}
|
||||
|
||||
|
||||
private void processImageForVulkan(ImageProxy image) {
|
||||
// 获取图像信息
|
||||
int width = image.getWidth();
|
||||
@@ -177,4 +244,72 @@ public class MainActivity extends GameActivity {
|
||||
}
|
||||
|
||||
private native void sendArgumentsToPlatform(String[] args);
|
||||
|
||||
@Override
|
||||
public void onError(@NotNull String error, int errorCode) {
|
||||
Log.e(TAG, "onError: Face Error");
|
||||
}
|
||||
|
||||
private ByteBuffer nativeBuffer = null;
|
||||
float[] points = new float[480 * 3];
|
||||
|
||||
|
||||
@Override
|
||||
public void onResults(FaceLandmarkerHelper.@NotNull ResultBundle resultBundle) {
|
||||
FaceLandmarkerResult faceLandmarkerResult = resultBundle.getResult();
|
||||
int height = resultBundle.getInputImageHeight();
|
||||
int width = resultBundle.getInputImageWidth();
|
||||
int bufferSize = 480 * 3 * 4;
|
||||
|
||||
if(nativeBuffer == null)
|
||||
{
|
||||
// 创建直接ByteBuffer(在native内存中)
|
||||
nativeBuffer = ByteBuffer.allocateDirect(bufferSize);
|
||||
nativeBuffer.order(ByteOrder.nativeOrder());
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
// Iterate through each detected face
|
||||
for (List<NormalizedLandmark> faceLandmarks : faceLandmarkerResult.faceLandmarks()) {
|
||||
//should be 1
|
||||
|
||||
int arrayIndex = 0;
|
||||
for (NormalizedLandmark p : faceLandmarks)
|
||||
{
|
||||
//Log.i(TAG, "Index" + index + " x:"+p.x() + " y:"+p.y() + " z:"+p.z());
|
||||
points[arrayIndex++] = p.x();
|
||||
points[arrayIndex++] = p.y();
|
||||
points[arrayIndex++] = p.z() * z_rate;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// 转换为FloatBuffer并填充数据
|
||||
FloatBuffer floatBuffer = nativeBuffer.asFloatBuffer();
|
||||
floatBuffer.put(points);
|
||||
floatBuffer.position(0);
|
||||
passDataToNative(nativeBuffer, index, width, height);
|
||||
}
|
||||
|
||||
public float z_rate = 1.0f;
|
||||
|
||||
public native void passDataToNative(ByteBuffer buffer, int pointCount, int width, int height);
|
||||
public native void upDateCameraData(float fov, float x, float y, float z, float sx, float sy, float sz, float rotx, float roty, float rotz, float camx, float camy, float camz);
|
||||
|
||||
@Override
|
||||
public void onSuccess(CameraDataFetcher.CameraData data) {
|
||||
z_rate = data.z_rate;
|
||||
upDateCameraData(data.fov, data.x, data.y, data.z, data.sx, data.sy, data.sz,
|
||||
data.rotx, data.roty, data.rotz,
|
||||
data.camx, data.camy, data.camz
|
||||
);
|
||||
canFetch = true;
|
||||
Log.e(TAG, "GetCameraData " + data.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String errorMessage) {
|
||||
Log.e(TAG, "GetCameraData Error");
|
||||
canFetch = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<!-- 如果需要兼容非常旧的Android版本(API 23及以下),可以加上 user -->
|
||||
<!-- <certificates src="user" /> -->
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
@@ -109,7 +109,8 @@ Java_com_khronos_vulkan_1samples_MainActivity_nativeButtonClicked(JNIEnv *env, j
|
||||
LOGI("call MainActivity_nativeButtonClicked.");
|
||||
}
|
||||
|
||||
extern void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int format, int rowStride, size_t dataSize);
|
||||
extern void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize);
|
||||
extern void ReceiveFacePoint(float* pos, int count, int width, int height);
|
||||
|
||||
void processWithVulkan(uint8_t* data, int width, int height, int format,
|
||||
int rowStride, size_t dataSize) {
|
||||
@@ -118,8 +119,8 @@ void processWithVulkan(uint8_t* data, int width, int height, int format,
|
||||
// 2. 将数据复制到 Vulkan 图像内存
|
||||
// 3. 执行 Vulkan 渲染或计算操作
|
||||
|
||||
LOGI("ProcessingImage: %dx%d, stride: %d, size: %zu", width, height, rowStride, dataSize);
|
||||
TextureLoadProcessWithVulkan(data, width, height, format, rowStride, dataSize);
|
||||
//LOGI("ProcessingImage: %dx%d, stride: %d, size: %zu", width, height, rowStride, dataSize);
|
||||
TextureLoadProcessWithVulkan(data, width, height, rowStride, dataSize);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@@ -143,3 +144,32 @@ Java_com_khronos_vulkan_1samples_MainActivity_processImageNative(JNIEnv *env, jo
|
||||
// 创建 Vulkan 图像或更新现有图像
|
||||
processWithVulkan(imageData, width, height, format, row_stride, capacity);
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_khronos_vulkan_1samples_MainActivity_passDataToNative(JNIEnv *env, jobject thiz,
|
||||
jobject buffer, jint pointCount, jint width, jint height) {
|
||||
// TODO: implement passDataToNative()
|
||||
|
||||
// 获取直接缓冲区的指针
|
||||
float* pos = static_cast<float*>(env->GetDirectBufferAddress(buffer));
|
||||
|
||||
if (pos == nullptr) {
|
||||
// 处理错误
|
||||
return;
|
||||
}
|
||||
|
||||
// 或者直接将指针传递给Vulkan
|
||||
ReceiveFacePoint(pos, pointCount, width, height);
|
||||
}
|
||||
|
||||
extern void global_update_mvp(float fov, float x, float y, float z, float sx, float sy, float sz, float rotx, float roty, float rotz, float camx, float camy, float camz);
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_khronos_vulkan_1samples_MainActivity_upDateCameraData(JNIEnv *env, jobject thiz,
|
||||
jfloat fov, jfloat x, jfloat y,jfloat z,
|
||||
jfloat sx, jfloat sy,jfloat sz,
|
||||
jfloat rotx, jfloat roty,jfloat rotz,
|
||||
jfloat camx,jfloat camy, jfloat camz) {
|
||||
global_update_mvp(fov, x, y, z, sx, sy, sz, rotx, roty, rotz, camx, camy, camz);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2019-2025, Sascha Willems
|
||||
/* Copyright (c) 2019-2025, Sascha Willems
|
||||
* Copyright (c) 2024-2025, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
@@ -644,6 +644,9 @@ void ApiVulkanSample::create_command_pool()
|
||||
{
|
||||
VkCommandPoolCreateInfo command_pool_info = {};
|
||||
command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
// --- 新增:设置允许重置命令缓冲区的标志 ---
|
||||
command_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
// --- 新增结束 ---
|
||||
command_pool_info.queueFamilyIndex = get_device().get_queue_by_flags(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 0).get_family_index();
|
||||
VK_CHECK(vkCreateCommandPool(get_device().get_handle(), &command_pool_info, nullptr, &cmd_pool));
|
||||
}
|
||||
|
||||
@@ -409,8 +409,8 @@ class ApiVulkanSample : public vkb::VulkanSampleC
|
||||
|
||||
public:
|
||||
bool prepared = false;
|
||||
uint32_t width = 1280;
|
||||
uint32_t height = 720;
|
||||
uint32_t width = 480;
|
||||
uint32_t height = 480;
|
||||
|
||||
VkClearColorValue default_clear_color = {{0.002f, 0.002f, 0.002f, 1.0f}};
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class Window
|
||||
Mode mode = Mode::Default;
|
||||
bool resizable = true;
|
||||
Vsync vsync = Vsync::Default;
|
||||
Extent extent = {1280, 720};
|
||||
Extent extent = {480, 480};
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,6 +30,8 @@ add_sample_with_tags(
|
||||
"texture_loading/glsl/texture.frag"
|
||||
"texture_loading/glsl/bg.vert"
|
||||
"texture_loading/glsl/bg.frag"
|
||||
"texture_loading/glsl/pointcloud.vert"
|
||||
"texture_loading/glsl/pointcloud.frag"
|
||||
SHADER_FILES_HLSL
|
||||
"texture_loading/hlsl/texture.vert.hlsl"
|
||||
"texture_loading/hlsl/texture.frag.hlsl")
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,33 @@
|
||||
#pragma once
|
||||
/* Copyright (c) 2019-2024, Sascha Willems
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 the "License";
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Texture loading (and display) example (including mip maps)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ktx.h>
|
||||
|
||||
#include "api_vulkan_sample.h"
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
// 顶点结构保持不变,因为背景 quad 可能不需要顶点缓冲区
|
||||
// Vertex layout for this example
|
||||
struct TextureLoadingVertexStructure
|
||||
{
|
||||
float pos[3];
|
||||
@@ -12,6 +35,11 @@ struct TextureLoadingVertexStructure
|
||||
float normal[3];
|
||||
};
|
||||
|
||||
struct PointVertex {
|
||||
float x, y, z; // 位置
|
||||
float r, g, b; // 颜色 (可以根据需要修改)
|
||||
};
|
||||
|
||||
class TextureLoading : public ApiVulkanSample
|
||||
{
|
||||
public:
|
||||
@@ -27,13 +55,15 @@ public:
|
||||
};
|
||||
|
||||
Texture texture = { 0 };
|
||||
Texture cam_text = { 0 }; // 将由外部函数初始化
|
||||
Texture texture_point = { 0 };
|
||||
Texture cam_text = { 0 };
|
||||
|
||||
std::unique_ptr<vkb::core::BufferC> vertex_buffer;
|
||||
std::unique_ptr<vkb::core::BufferC> index_buffer;
|
||||
uint32_t index_count;
|
||||
|
||||
std::unique_ptr<vkb::core::BufferC> uniform_buffer_vs;
|
||||
std::unique_ptr<vkb::core::BufferC> vertex_buffer_point;
|
||||
uint32_t point_count = 0;
|
||||
|
||||
struct
|
||||
{
|
||||
@@ -45,56 +75,106 @@ public:
|
||||
|
||||
struct
|
||||
{
|
||||
VkPipeline solid; // 原有前景管线
|
||||
VkPipeline background; // 新增背景管线
|
||||
glm::mat4 projection;
|
||||
glm::mat4 model;
|
||||
glm::mat4 view;
|
||||
} ubo_vs_point;
|
||||
|
||||
std::unique_ptr<vkb::core::BufferC> uniform_buffer_vs;
|
||||
std::unique_ptr<vkb::core::BufferC> uniform_buffer_vs_point;
|
||||
|
||||
|
||||
//glm::vec3 camear_pos_point = {0, 0, -2.f};
|
||||
//glm::vec3 face_pos_point;
|
||||
|
||||
struct
|
||||
{
|
||||
VkPipeline solid;
|
||||
VkPipeline background;
|
||||
VkPipeline point;
|
||||
} pipelines;
|
||||
|
||||
// 管线布局
|
||||
VkPipelineLayout pipeline_layout; // 前景管线布局
|
||||
VkPipelineLayout pipeline_layout_bg; // 背景管线布局
|
||||
|
||||
// 描述符集
|
||||
VkDescriptorSet descriptor_set; // 前景描述符集
|
||||
VkDescriptorSet descriptor_set_bg; // 背景描述符集
|
||||
VkPipelineLayout pipeline_layout;
|
||||
VkPipelineLayout pipeline_layout_bg;
|
||||
VkPipelineLayout pipeline_layout_point;
|
||||
|
||||
// 描述符集布局
|
||||
VkDescriptorSetLayout descriptor_set_layout; // 前景描述符集布局
|
||||
VkDescriptorSetLayout descriptor_set_layout_bg; // 背景描述符集布局 (仅包含 combined image sampler)
|
||||
VkDescriptorSet descriptor_set;
|
||||
VkDescriptorSet descriptor_set_bg;
|
||||
VkDescriptorSet descriptor_set_point;
|
||||
|
||||
VkDescriptorSetLayout descriptor_set_layout;
|
||||
VkDescriptorSetLayout descriptor_set_layout_bg;
|
||||
VkDescriptorSetLayout descriptor_set_layout_point;
|
||||
|
||||
static TextureLoading* Get() {
|
||||
return loadTextIns;
|
||||
return this_instance;
|
||||
}
|
||||
static TextureLoading* loadTextIns;
|
||||
|
||||
static TextureLoading* this_instance;
|
||||
|
||||
TextureLoading();
|
||||
~TextureLoading();
|
||||
virtual void request_gpu_features(vkb::PhysicalDevice& gpu) override;
|
||||
void load_texture();
|
||||
void destroy_texture(Texture texture);
|
||||
void build_command_buffers() override;
|
||||
|
||||
void draw();
|
||||
void generate_quad(); // 生成前景 quad
|
||||
void draw_point_cloud(VkCommandBuffer command_buffer);
|
||||
void generate_quad();
|
||||
|
||||
void setup_descriptor_pool();
|
||||
|
||||
void setup_descriptor_set_layout();
|
||||
void setup_descriptor_set_layout_bg(); // 新增:设置背景描述符集布局
|
||||
void setup_descriptor_set();
|
||||
void setup_descriptor_set_bg(); // 新增:设置背景描述符集
|
||||
void prepare_pipelines();
|
||||
void prepare_pipeline_bg(); // 新增:准备背景管线
|
||||
|
||||
void setup_descriptor_set_layout_bg();
|
||||
void setup_descriptor_set_bg();
|
||||
|
||||
void setup_descriptor_set_layout_point();
|
||||
void setup_descriptor_set_point();
|
||||
|
||||
void prepare_uniform_buffers();
|
||||
void update_uniform_buffers();
|
||||
|
||||
void prepare_uniform_buffers_point();
|
||||
void update_uniform_buffers_point(float fov, float x, float y, float z, float sx, float sy, float sz, float rotx, float roty, float rotz, float camx, float camy, float camz);
|
||||
|
||||
|
||||
void prepare_pipelines();
|
||||
void prepare_pipeline_bg();
|
||||
void prepare_pipeline_point();
|
||||
|
||||
|
||||
bool prepare(const vkb::ApplicationOptions& options) override;
|
||||
virtual void render(float delta_time) override;
|
||||
virtual void view_changed() override;
|
||||
virtual void on_update_ui_overlay(vkb::Drawer& drawer) override;
|
||||
void destroy_texture(Texture texture);
|
||||
|
||||
// 现有函数保持不变
|
||||
void processWithVulkan(uint8_t* data, int width, int height, int format, int rowStride, size_t dataSize, Texture& out_texture);
|
||||
void createTexture(VkDevice device, VkPhysicalDevice physicalDevice, int width, int height, int format, Texture& texture);
|
||||
void updateTexture(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue queue, uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& texture);
|
||||
uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||
void processWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& out_texture);
|
||||
void createTexture(VkDevice device, VkPhysicalDevice physicalDevice, int width, int height, Texture& texture);
|
||||
void updateTexture(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue queue, uint8_t* data, int width, int height, int rowStride, size_t dataSize, Texture& texture);
|
||||
uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||
VkCommandBuffer beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool);
|
||||
void endSingleTimeCommands(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkCommandBuffer commandBuffer);
|
||||
void transitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout);
|
||||
void endSingleTimeCommands(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkCommandBuffer commandBuffer);
|
||||
void transitionImageLayout(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout);
|
||||
|
||||
public:
|
||||
|
||||
void update_point_vertex_buffer(float* pos, int pointCount);
|
||||
private:
|
||||
std::thread workerThread;
|
||||
bool running = false;
|
||||
|
||||
public:
|
||||
//void run();
|
||||
//void start();
|
||||
std::mutex mtx;
|
||||
std::mutex mtx_point;
|
||||
std::mutex mtx_mvp;
|
||||
//void stop();
|
||||
//void updateTexture();
|
||||
};
|
||||
|
||||
std::unique_ptr<vkb::Application> create_texture_loading();
|
||||
@@ -1,11 +1,15 @@
|
||||
#version 450
|
||||
|
||||
layout(binding = 0) uniform sampler2D backgroundTexture; // Binding 0
|
||||
// 输入变量(与顶点着色器输出对应)
|
||||
layout(location = 0) in vec2 inTexCoord;
|
||||
|
||||
layout(location = 0) in vec2 inUV;
|
||||
// 输出颜色
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
// 纹理采样器
|
||||
layout(binding = 0) uniform sampler2D texSampler;
|
||||
|
||||
void main() {
|
||||
//outColor = texture(backgroundTexture, inUV);
|
||||
outColor = vec4(1.0, 0.0, 0.0, 1.0); // 输出红色
|
||||
// 采样纹理
|
||||
outColor = texture(texSampler, inTexCoord);
|
||||
}
|
||||
Binary file not shown.
@@ -1,14 +1,65 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) out vec2 uv;
|
||||
// 硬编码的顶点数据 - 4个顶点组成三角形带覆盖整个屏幕
|
||||
// const vec2 positions[6] = vec2[6](
|
||||
// vec2( 1.0, 1.0), // 右上 - 三角形1
|
||||
// vec2(-1.0, 1.0), // 左上 - 三角形1
|
||||
// vec2(-1.0, -1.0), // 左下 - 三角形1
|
||||
|
||||
// vec2(-1.0, -1.0), // 左下 - 三角形2
|
||||
// vec2( 1.0, -1.0), // 右下 - 三角形2
|
||||
// vec2( 1.0, 1.0) // 右上 - 三角形2
|
||||
// );
|
||||
|
||||
const float offset = (640-480)/(480.0);
|
||||
|
||||
|
||||
const vec2 positions[6] = vec2[6](
|
||||
vec2( 1.0, -1.0 -offset), // 右下
|
||||
vec2(1.0, 1.0 + offset), // 右上 - 三角形1
|
||||
vec2(-1.0, 1.0 + offset), // 左上 - 三角形1
|
||||
|
||||
vec2(-1.0, 1.0 + offset), // 左上 - 三角形2
|
||||
vec2( -1.0, -1.0-offset), // 左下 - 三角形2
|
||||
vec2( 1.0, -1.0-offset) // 右下 - 三角形2
|
||||
);
|
||||
|
||||
|
||||
//const float offset = (640-480)/(640.0*2); // 假设宽高比为4:3
|
||||
// const float offset = 0;
|
||||
|
||||
// const vec2 positions[6] = vec2[6](
|
||||
// vec2( -1.0 - offset, 1.0), // 右上 -> 左上
|
||||
// vec2(-1.0 - offset, -1.0), // 左上 - 左下
|
||||
// vec2(1.0 + offset, -1.0), // 左下 - 右下
|
||||
|
||||
// vec2(1.0 + offset, -1.0), // 左下 - 右下
|
||||
// vec2( 1.0 + offset, 1.0), // 右下 - 右上
|
||||
// vec2( -1.0 - offset, 1.0) // 右上 - 左上
|
||||
// );
|
||||
|
||||
|
||||
|
||||
const vec2 texCoords[6] = vec2[6](
|
||||
vec2(1.0, 1.0), // 右上
|
||||
vec2(0.0, 1.0), // 左上
|
||||
vec2(0.0, 0.0), // 左下
|
||||
|
||||
vec2(0.0, 0.0), // 左下
|
||||
vec2(1.0, 0.0), // 右下
|
||||
vec2(1.0, 1.0) // 右上
|
||||
);
|
||||
|
||||
// 输出变量
|
||||
layout(location = 0) out vec2 outTexCoord;
|
||||
|
||||
void main() {
|
||||
// 使用NDC坐标(-1到1),并为四个顶点分配位置
|
||||
vec2 positions[4] = vec2[](
|
||||
vec2(-1.0, -1.0), vec2(1.0, -1.0),
|
||||
vec2(-1.0, 1.0), vec2(1.0, 1.0)
|
||||
);
|
||||
// 获取顶点位置
|
||||
vec2 position = positions[gl_VertexIndex];
|
||||
|
||||
uv = positions[gl_VertexIndex].xy * 0.5 + 0.5;
|
||||
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||
// 设置输出位置(Vulkan使用不同的坐标系)
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
|
||||
// 输出纹理坐标
|
||||
outTexCoord = texCoords[gl_VertexIndex];
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
#version 450
|
||||
|
||||
// 从顶点着色器接收的颜色
|
||||
layout(location = 0) in vec3 fragColor;
|
||||
|
||||
// 输出颜色
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = vec4(fragColor, 1.0); // 使用传入的颜色
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,21 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 inPosition;
|
||||
layout(location = 1) in vec3 inColor;
|
||||
|
||||
layout(location = 0) out vec3 fragColor;
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject {
|
||||
mat4 proj;
|
||||
mat4 model;
|
||||
mat4 view;
|
||||
} ubo;
|
||||
|
||||
void main() {
|
||||
// 预计算MVP矩阵以减少乘法次数
|
||||
mat4 mvp = ubo.proj * ubo.view * ubo.model;
|
||||
//vec3 pos = vec3(2.0, inPosition.y, inPosition.z);
|
||||
gl_Position = mvp * vec4(inPosition, 1.0);
|
||||
fragColor = inColor;
|
||||
gl_PointSize = 2.0;
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user