39 Commits
Author SHA1 Message Date
xsl a43bd12970 阿斯蒂芬 2025-09-20 23:14:15 +08:00
xsl 1852717ae3 脸型匹配完成 2025-09-20 23:13:56 +08:00
xsl af56b1e5c4 asdf 2025-09-20 21:54:08 +08:00
xsl 4e7ef7ed93 完成mvp矩阵和shader 2025-09-20 21:48:43 +08:00
xsl 1b201b8831 完成mvp 矩阵,和shader 2025-09-20 21:48:19 +08:00
xsl ad8ce037fd 跑通点的渲染。 2025-09-19 18:06:16 +08:00
xsl 41756e71df windows端运行通过 2025-09-19 15:54:03 +08:00
xsl adf45c1b55 加入face点mvp和纹理,重构完成,还未自测验证 2025-09-19 11:36:34 +08:00
xsl f63f46e975 重构point 代码 2025-09-18 22:32:43 +08:00
xsl 3ca95b90f8 开始写,脸的点云了。 2025-09-18 18:15:10 +08:00
xsl 225591bf22 修改纹理背景拉伸 2025-09-18 18:05:24 +08:00
xsl baa6733872 修改纹理背景拉伸 2025-09-18 18:04:54 +08:00
xsl 00106ac0f6 放弃画3d 2025-09-18 11:41:28 +08:00
xsl cbdbdb5698 放弃画3d 2025-09-18 11:40:53 +08:00
xsl 203b211bde 放弃画3d,修改平台代码 2025-09-18 11:40:35 +08:00
xsl fc9f9d7054 放弃画3d 2025-09-18 11:39:58 +08:00
xsl 2026c41a23 放弃画3d 2025-09-18 11:39:31 +08:00
xsl 6a5b5d9d5d 更新shader , 还没调试。 2025-09-17 23:36:27 +08:00
xsl 0a2a5c45be 描述符池,增加为4。 不知道为什么 2025-09-17 23:35:50 +08:00
xsl 8e721b9c42 命令缓冲池需要,隐式重置。 2025-09-17 23:34:58 +08:00
xsl 0d90c33380 加入渲染点的代码 2025-09-17 22:49:40 +08:00
xsl ea602c4f8f 加入渲染点的代码 2025-09-17 22:48:56 +08:00
xsl e4c89a2651 加入渲染点的代码 2025-09-17 22:47:48 +08:00
xsl 64ebe51ea4 人脸检测成功 2025-09-17 10:28:47 +08:00
xsl 541b610c87 人脸检测成功 2025-09-17 10:27:42 +08:00
xsl ef7318dd35 人脸检测成功 2025-09-17 10:27:13 +08:00
xsl 2b4066fa32 接入人脸检测报错 2025-09-16 23:48:35 +08:00
xsl a8eebf519f 修复 crash 的问题 2025-09-16 23:04:08 +08:00
xsl 742635813b asdf 2025-09-16 20:34:08 +08:00
xsl 7cb94d268c asdf 2025-09-16 20:33:44 +08:00
xsl a418be886c asdf 2025-09-16 19:25:18 +08:00
xsl 3d205ab184 asdf 2025-09-16 19:24:55 +08:00
xsl e6bef08ecf asdf 2025-09-16 18:56:06 +08:00
xsl fab00f8466 asdf 2025-09-16 18:55:32 +08:00
xsl ac43d3b0aa asdf 2025-09-15 22:32:11 +08:00
xsl 2e059eef07 asdf 2025-09-15 22:31:52 +08:00
xsl bf8a14f549 save code 2025-09-15 22:03:51 +08:00
xsl 8e1c574122 通议灵码修改过的。 2025-09-14 21:52:08 +08:00
xsl ef5f391ef5 save code 2025-09-14 20:37:53 +08:00
23 changed files with 1641 additions and 461 deletions
+1 -1
View File
@@ -97,5 +97,5 @@ dependencies {
implementation "androidx.camera:camera-lifecycle:$camerax_version" implementation "androidx.camera:camera-lifecycle:$camerax_version"
implementation "androidx.camera:camera-view:$camerax_version" implementation "androidx.camera:camera-view:$camerax_version"
//noinspection Aligned16KB //noinspection Aligned16KB
implementation 'com.google.mediapipe:tasks-vision:0.20230731' implementation 'com.google.mediapipe:tasks-vision:0.10.26'
} }
+22
View File
@@ -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.
+3
View File
@@ -28,12 +28,15 @@
<!-- Declare permissions --> <!-- Declare permissions -->
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <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" <application android:label="@string/app_name"
android:debuggable="true" android:debuggable="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config"
tools:ignore="GoogleAppIndexingWarning,HardcodedDebugMode"> tools:ignore="GoogleAppIndexingWarning,HardcodedDebugMode">
<activity android:name="com.khronos.vulkan_samples.MainActivity" <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 * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.mediapipe.examples.facelandmarker package com.khronos.vulkan_samples
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
@@ -176,7 +176,7 @@ class FaceLandmarkerHelper(
} }
} }
val rotatedBitmap = Bitmap.createBitmap( val rotatedBitmap = Bitmap.createBitmap(
bitmapBuffer, 0, 0, bitmapBuffer.width, bitmapBuffer.height, bitmapBuffer, (640-480)/2, 0, bitmapBuffer.height, bitmapBuffer.height,
matrix, true matrix, true
) )
@@ -3,17 +3,11 @@ package com.khronos.vulkan_samples;
import android.Manifest; import android.Manifest;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.SurfaceTexture;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log; import android.util.Log;
import android.view.Surface; import android.view.WindowManager;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -21,21 +15,27 @@ import androidx.camera.core.AspectRatio;
import androidx.camera.core.CameraSelector; import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageAnalysis; import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageProxy; import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.core.SurfaceRequest;
import androidx.camera.lifecycle.ProcessCameraProvider; import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import com.google.androidgamesdk.GameActivity; import com.google.androidgamesdk.GameActivity;
import com.google.common.util.concurrent.ListenableFuture; 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.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
public class MainActivity extends GameActivity { public class MainActivity extends GameActivity implements FaceLandmarkerHelper.LandmarkerListener, CameraDataFetcher.CameraDataCallback {
private ProcessCameraProvider cameraProvider; private ProcessCameraProvider cameraProvider;
private void initCamera(){ private void initCamera(){
backgroundExecutor = Executors.newSingleThreadExecutor(); 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 @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@@ -61,11 +70,66 @@ public class MainActivity extends GameActivity {
sendArgumentsToPlatform(argArray); sendArgumentsToPlatform(argArray);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// 隐藏状态栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
initCamera(); 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: "); 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() { private boolean hasCameraPermission() {
return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED; == PackageManager.PERMISSION_GRANTED;
@@ -80,6 +144,7 @@ public class MainActivity extends GameActivity {
private static final int REQUEST_CAMERA_PERMISSION = 1001; private static final int REQUEST_CAMERA_PERMISSION = 1001;
ImageAnalysis imageAnalyzer; ImageAnalysis imageAnalyzer;
ExecutorService backgroundExecutor; ExecutorService backgroundExecutor;
FaceLandmarkerHelper faceLandmarkerHelper;
private void startCamera() { private void startCamera() {
ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ListenableFuture<ProcessCameraProvider> cameraProviderFuture =
@@ -90,7 +155,7 @@ public class MainActivity extends GameActivity {
cameraProvider = cameraProviderFuture.get(); cameraProvider = cameraProviderFuture.get();
CameraSelector cameraSelector = new CameraSelector.Builder() CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_FRONT) .requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build(); .build();
imageAnalyzer = new ImageAnalysis.Builder() imageAnalyzer = new ImageAnalysis.Builder()
@@ -105,11 +170,12 @@ public class MainActivity extends GameActivity {
@Override @Override
public void analyze(@NonNull ImageProxy image) { public void analyze(@NonNull ImageProxy image) {
try { try {
Log.d("Camera", "Received image: " + image.getWidth() + "x" + image.getHeight()); //Log.d("Camera", "Received image: " + image.getWidth() + "x" + image.getHeight());
processImageForVulkan(image); processImageForVulkan(image);
detectFace(image);
} finally { } finally {
image.close(); // 确保在这里关闭 //image.close(); // 确保在这里关闭
Log.d("Camera", "Image closed, ready for next frame"); //Log.d("Camera", "Image closed, ready for next frame");
} }
} }
}); });
@@ -122,6 +188,7 @@ public class MainActivity extends GameActivity {
}, ContextCompat.getMainExecutor(this)); }, ContextCompat.getMainExecutor(this));
} }
private void processImageForVulkan(ImageProxy image) { private void processImageForVulkan(ImageProxy image) {
// 获取图像信息 // 获取图像信息
int width = image.getWidth(); int width = image.getWidth();
@@ -177,4 +244,72 @@ public class MainActivity extends GameActivity {
} }
private native void sendArgumentsToPlatform(String[] args); 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>
+33 -3
View File
@@ -109,7 +109,8 @@ Java_com_khronos_vulkan_1samples_MainActivity_nativeButtonClicked(JNIEnv *env, j
LOGI("call MainActivity_nativeButtonClicked."); 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, void processWithVulkan(uint8_t* data, int width, int height, int format,
int rowStride, size_t dataSize) { int rowStride, size_t dataSize) {
@@ -118,8 +119,8 @@ void processWithVulkan(uint8_t* data, int width, int height, int format,
// 2. 将数据复制到 Vulkan 图像内存 // 2. 将数据复制到 Vulkan 图像内存
// 3. 执行 Vulkan 渲染或计算操作 // 3. 执行 Vulkan 渲染或计算操作
LOGI("ProcessingImage: %dx%d, stride: %d, size: %zu", width, height, rowStride, dataSize); //LOGI("ProcessingImage: %dx%d, stride: %d, size: %zu", width, height, rowStride, dataSize);
TextureLoadProcessWithVulkan(data, width, height, format, rowStride, dataSize); TextureLoadProcessWithVulkan(data, width, height, rowStride, dataSize);
} }
extern "C" extern "C"
@@ -142,4 +143,33 @@ Java_com_khronos_vulkan_1samples_MainActivity_processImageNative(JNIEnv *env, jo
// 在这里将图像数据传递给 Vulkan // 在这里将图像数据传递给 Vulkan
// 创建 Vulkan 图像或更新现有图像 // 创建 Vulkan 图像或更新现有图像
processWithVulkan(imageData, width, height, format, row_stride, capacity); 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);
} }
+4 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (c) 2019-2025, Sascha Willems /* Copyright (c) 2019-2025, Sascha Willems
* Copyright (c) 2024-2025, Arm Limited and Contributors * Copyright (c) 2024-2025, Arm Limited and Contributors
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
@@ -644,6 +644,9 @@ void ApiVulkanSample::create_command_pool()
{ {
VkCommandPoolCreateInfo command_pool_info = {}; VkCommandPoolCreateInfo command_pool_info = {};
command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_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(); 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)); VK_CHECK(vkCreateCommandPool(get_device().get_handle(), &command_pool_info, nullptr, &cmd_pool));
} }
+2 -2
View File
@@ -409,8 +409,8 @@ class ApiVulkanSample : public vkb::VulkanSampleC
public: public:
bool prepared = false; bool prepared = false;
uint32_t width = 1280; uint32_t width = 480;
uint32_t height = 720; uint32_t height = 480;
VkClearColorValue default_clear_color = {{0.002f, 0.002f, 0.002f, 1.0f}}; VkClearColorValue default_clear_color = {{0.002f, 0.002f, 0.002f, 1.0f}};
+1 -1
View File
@@ -72,7 +72,7 @@ class Window
Mode mode = Mode::Default; Mode mode = Mode::Default;
bool resizable = true; bool resizable = true;
Vsync vsync = Vsync::Default; Vsync vsync = Vsync::Default;
Extent extent = {1280, 720}; Extent extent = {480, 480};
}; };
/** /**
@@ -28,6 +28,10 @@ add_sample_with_tags(
SHADER_FILES_GLSL SHADER_FILES_GLSL
"texture_loading/glsl/texture.vert" "texture_loading/glsl/texture.vert"
"texture_loading/glsl/texture.frag" "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 SHADER_FILES_HLSL
"texture_loading/hlsl/texture.vert.hlsl" "texture_loading/hlsl/texture.vert.hlsl"
"texture_loading/hlsl/texture.frag.hlsl") "texture_loading/hlsl/texture.frag.hlsl")
File diff suppressed because it is too large Load Diff
+91 -28
View File
@@ -1,4 +1,4 @@
/* Copyright (c) 2019-2024, Sascha Willems /* Copyright (c) 2019-2024, Sascha Willems
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
@@ -15,17 +15,19 @@
* limitations under the License. * limitations under the License.
*/ */
/* /*
* Texture loading (and display) example (including mip maps) * Texture loading (and display) example (including mip maps)
*/ */
#pragma once #pragma once
#include <ktx.h> #include <ktx.h>
#include "api_vulkan_sample.h" #include "api_vulkan_sample.h"
#include <thread>
#include <mutex>
// Vertex layout for this example // Vertex layout for this example
struct TextureLoadingVertexStructure struct TextureLoadingVertexStructure
{ {
float pos[3]; float pos[3];
@@ -33,11 +35,14 @@ struct TextureLoadingVertexStructure
float normal[3]; float normal[3];
}; };
struct PointVertex {
float x, y, z; // 位置
float r, g, b; // 颜色 (可以根据需要修改)
};
class TextureLoading : public ApiVulkanSample class TextureLoading : public ApiVulkanSample
{ {
public: public:
// Contains all Vulkan objects that are required to store and use a texture
// Note that this repository contains a texture class (vulkan_texture.h) that encapsulates texture loading functionality in a class that is used in subsequent demos
struct Texture struct Texture
{ {
VkSampler sampler; VkSampler sampler;
@@ -49,14 +54,16 @@ class TextureLoading : public ApiVulkanSample
uint32_t mip_levels; uint32_t mip_levels;
}; };
Texture texture = {0}; 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> vertex_buffer;
std::unique_ptr<vkb::core::BufferC> index_buffer; std::unique_ptr<vkb::core::BufferC> index_buffer;
uint32_t index_count; 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 struct
{ {
@@ -66,52 +73,108 @@ class TextureLoading : public ApiVulkanSample
float lod_bias = 0.0f; float lod_bias = 0.0f;
} ubo_vs; } ubo_vs;
struct
{
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 struct
{ {
VkPipeline solid; VkPipeline solid;
VkPipeline background;
VkPipeline point;
} pipelines; } pipelines;
VkPipelineLayout pipeline_layout; VkPipelineLayout pipeline_layout;
VkPipelineLayout pipeline_layout_bg;
VkPipelineLayout pipeline_layout_point;
VkDescriptorSet descriptor_set; VkDescriptorSet descriptor_set;
VkDescriptorSet descriptor_set_bg;
VkDescriptorSet descriptor_set_point;
VkDescriptorSetLayout descriptor_set_layout; VkDescriptorSetLayout descriptor_set_layout;
VkDescriptorSetLayout descriptor_set_layout_bg;
VkDescriptorSetLayout descriptor_set_layout_point;
static TextureLoading* Get() { static TextureLoading* Get() {
return loadTextIns; return this_instance;
} }
static TextureLoading* loadTextIns;
static TextureLoading* this_instance;
TextureLoading(); TextureLoading();
~TextureLoading(); ~TextureLoading();
virtual void request_gpu_features(vkb::PhysicalDevice &gpu) override; virtual void request_gpu_features(vkb::PhysicalDevice& gpu) override;
void load_texture(); void load_texture();
void destroy_texture(Texture texture); void destroy_texture(Texture texture);
void build_command_buffers() override; void build_command_buffers() override;
void draw(); void draw();
void draw_point_cloud(VkCommandBuffer command_buffer);
void generate_quad(); void generate_quad();
void setup_descriptor_pool(); void setup_descriptor_pool();
void setup_descriptor_set_layout(); void setup_descriptor_set_layout();
void setup_descriptor_set(); void setup_descriptor_set();
void prepare_pipelines();
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 prepare_uniform_buffers();
void update_uniform_buffers(); void update_uniform_buffers();
bool prepare(const vkb::ApplicationOptions &options) override;
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 render(float delta_time) override;
virtual void view_changed() override; virtual void view_changed() override;
virtual void on_update_ui_overlay(vkb::Drawer &drawer) override; virtual void on_update_ui_overlay(vkb::Drawer& drawer) override;
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);
public: public:
void processWithVulkan(uint8_t* data, int width, int height, int format, int rowStride, size_t dataSize); void update_point_vertex_buffer(float* pos, int pointCount);
private:
void createTexture(VkDevice device, VkPhysicalDevice physicalDevice, int width, int height, int format, Texture& texture); std::thread workerThread;
bool running = false;
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);
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(); std::unique_ptr<vkb::Application> create_texture_loading();
+15
View File
@@ -0,0 +1,15 @@
#version 450
// 输入变量(与顶点着色器输出对应)
layout(location = 0) in vec2 inTexCoord;
// 输出颜色
layout(location = 0) out vec4 outColor;
// 纹理采样器
layout(binding = 0) uniform sampler2D texSampler;
void main() {
// 采样纹理
outColor = texture(texSampler, inTexCoord);
}
Binary file not shown.
+65
View File
@@ -0,0 +1,65 @@
#version 450
// 硬编码的顶点数据 - 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() {
// 获取顶点位置
vec2 position = positions[gl_VertexIndex];
// 设置输出位置(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.