see*_*eek 2 c# c++ android unity-game-engine
我需要在屏幕点读取 C# Unity3D 中的像素颜色。
我正在使用渲染纹理和 ReadPixels 方法。每 0.5f 秒使用一次对性能不利(即使我的渲染纹理大小为 128x128px),我正在尝试找到另一种方法来更快地获取此数据。我在某处看到可以直接使用,glReadPixels但我不知道如何使用它?
我需要检测这个地方(屏幕上的点)是否有东西。
这是我现在拥有的代码。
using UnityEngine;
using System;
using System.Collections;
public class ColController : MonoBehaviour
{
public Camera collCamera;
public Texture2D tex2d;
void Start()
{
collCamera = GetComponent<Camera>();
tex2d = new Texture2D(collCamera.targetTexture.width, collCamera.targetTexture.height, TextureFormat.ARGB32, false);
RenderTexture.active = collCamera.targetTexture;
StartCoroutine (Execute ());
}
IEnumerator Execute()
{
while (true) {
yield return new WaitForEndOfFrame ();
tex2d = GetRTPixels (collCamera.targetTexture);
yield return new WaitForSeconds (0.5f);
}
}
static public Texture2D GetRTPixels(RenderTexture rt)
{
RenderTexture currentActiveRT = RenderTexture.active;
RenderTexture.active = rt;
// Create a new Texture2D and read the RenderTexture image into it
Texture2D tex = new Texture2D(rt.width, rt.height);
tex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
RenderTexture.active = currentActiveRT;
return tex;
}
void Update() {
screenPos = collCamera.WorldToScreenPoint (player.transform.position);
positionColor = tex2d.GetPixel ((int)screenPos.x, (int)screenPos.y);
}
}
Run Code Online (Sandbox Code Playgroud)
你必须使用glReadPixels. 过去,只需从函数中的 C# 调用它即可更轻松地实现OnPostRender,但您不能再这样做了。您必须使用GL.IssuePluginEvent调用将截取屏幕截图的函数。
您还需要位于 的Unity C++ API 标头(IUnityInterface.h和IUnityGraphics.h<UnityInstallationDirecory>\\Editor\\Data\\PluginAPI ) 。
我创建了一个名为UnityPluginHeaders 的文件夹,并将IUnityInterface.h和IUnityGraphics.h头文件放入其中,以便可以使用#include "UnityPluginHeaders/IUnityInterface.h"和 导入它们#include "UnityPluginHeaders/IUnityGraphics.h"。
C++ ( ScreenPointPixel.h):
#ifndef ANDROIDSCREENSHOT_NATIVE_LIB_H\n#define ANDROIDSCREENSHOT_NATIVE_LIB_H\n\n#define DLLExport __declspec(dllexport)\n\nextern "C"\n{\n#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(WINAPI_FAMILY)\nDLLExport void initScreenPointPixel(void* buffer, int x, int y, int width, int height);\nDLLExport void updateScreenPointPixelBufferPointer(void* buffer);\nDLLExport void updateScreenPointPixelCoordinate(int x, int y);\nDLLExport void updateScreenPointPixelSize(int width, int height);\nint GetScreenPixels(void* buffer, int x, int y, int width, int height);\n\n#else\nvoid initScreenPointPixel(void *buffer, int x, int y, int width, int height);\nvoid updateScreenPointPixelBufferPointer(void *buffer);\nvoid updateScreenPointPixelCoordinate(int x, int y);\nvoid updateScreenPointPixelSize(int width, int height);\n\nint GetScreenPixels(void *buffer, int x, int y, int width, int height);\n#endif\n}\n#endif //ANDROIDSCREENSHOT_NATIVE_LIB_H\nRun Code Online (Sandbox Code Playgroud)\n\nC++ ( ScreenPointPixel.cpp):
#include "ScreenPointPixel.h"\n\n#include <string>\n#include <stdlib.h>\n\n//For Debugging\n//#include "DebugCPP.h"\n//http://stackoverflow.com/questions/43732825/use-debug-log-from-c/43735531#43735531\n\n//Unity Headers\n#include "UnityPluginHeaders/IUnityInterface.h"\n#include "UnityPluginHeaders/IUnityGraphics.h"\n\n\n//Headers for Windows\n#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(WINAPI_FAMILY)\n#include <windows.h>\n#include <gl/GL.h>\n#include <gl/GLU.h>\n#include <stdlib.h>\n#include "glext.h"\n#pragma comment(lib, "opengl32.lib")\n\n//--------------------------------------------------\n\n//Headers for Android\n#elif defined(ANDROID) || defined(__ANDROID__)\n#include <jni.h>\n#include <GLES2/gl2.h>\n#include <GLES2/gl2ext.h>\n//Link lGLESv2 in the CMakeList.txt file\n//LOCAL_LDLIBS += \xe2\x88\x92lGLESv2\n\n//--------------------------------------------------\n\n//Headers for MAC and iOS\n//http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system\n#elif defined(__APPLE__) && defined(__MACH__)\n//Apple OSX and iOS (Darwin)\n#include <TargetConditionals.h>\n#if TARGET_IPHONE_SIMULATOR == 1\n//iOS in Xcode simulator\n#include <OpenGLES/ES2/gl.h>\n#include <OpenGLES/ES2/glext.h>\n#elif TARGET_OS_IPHONE == 1\n//iOS on iPhone, iPad, etc.\n#include <OpenGLES/ES2/gl.h>\n#include <OpenGLES/ES2/glext.h>\n#elif TARGET_OS_MAC == 1\n#include <OpenGL/gl.h>\n#include <OpenGL/glu.h>\n#include <GLUT/glut.h>\n#endif\n\n//--------------------------------------------------\n\n//Headers for Linux\n#elif defined(__linux__)\n#include <GL/gl.h>\n#include <GL/glu.h>\n#endif\n\nstatic void* screenPointPixelData = nullptr;\nstatic int _x;\nstatic int _y;\nstatic int _width;\nstatic int _height;\n\n//----------------------------Enable Screenshot-----------------------------\nvoid initScreenPointPixel(void* buffer, int x, int y, int width, int height) {\n screenPointPixelData = buffer;\n _x = x;\n _y = y;\n _width = width;\n _height = height;\n}\n\nvoid updateScreenPointPixelBufferPointer(void* buffer) {\n screenPointPixelData = buffer;\n}\n\nvoid updateScreenPointPixelCoordinate(int x, int y) {\n _x = x;\n _y = y;\n}\n\nvoid updateScreenPointPixelSize(int width, int height) {\n _width = width;\n _height = height;\n}\n\nint GetScreenPixels(void* buffer, int x, int y, int width, int height) {\n if (glGetError())\n return -1;\n\n //glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);\n glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);\n\n if (glGetError())\n return -2;\n return 0;\n}\n\n//----------------------------UNITY RENDERING CALLBACK-----------------------------\n\n// Plugin function to handle a specific rendering event\nstatic void UNITY_INTERFACE_API OnRenderEventScreenPointPixel(int eventID)\n{\n //Put rendering code below\n if (screenPointPixelData == nullptr) {\n //Debug::Log("Pointer is null", Color::Red);\n return;\n }\n int result = GetScreenPixels(screenPointPixelData, _x, _y, _width, _height);\n\n //std::string log_msg = "Cobol " + std::to_string(result);\n //Debug::Log(log_msg, Color::Green);\n}\n\n// Freely defined function to pass a callback to plugin-specific scripts\nextern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API\nGetRenderEventScreenPointPixelFunc()\n{\n return OnRenderEventScreenPointPixel;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n从 Android Studio 编译/构建时,它应该为您提供两个文件夹(目录中的armeabi-v7a和x86<ProjectDirectory>\\app\\build\\intermediates\\cmake\\release\\obj。它们都应该包含共享的 *.so 库。如果您无法为Android Studio编译此库,请使用以下副本我为此制作了 Android Studio 项目,您可以使用它来生成共享的 *.so 库。
将这两个文件夹放置在 Unity 项目文件夹中Assets\\Plugins\\Android\\libs。
您现在应该拥有:
\n\nAssets\\Plugins\\Android\\libs\\armeabi-v7a\\libScreenPointPixel-lib.so。
和
\n\nAssets\\Plugins\\Android\\libs\\x86\\libScreenPointPixel-lib.so。
C#测试代码:
\n\n创建一个简单的RawImage小组件并将其放置在屏幕的右上角。将其拖到RawImage下面脚本中的 rawImageColor 插槽中。当您单击屏幕上的任意位置时,该屏幕点的像素颜色应显示在该屏幕上rawImageColorRawImage 上。
C#:
\n\nusing System;\nusing System.Collections;\nusing System.Runtime.InteropServices;\nusing UnityEngine;\nusing UnityEngine.UI;\n\npublic class ScreenPointPixel : MonoBehaviour\n{\n [DllImport("ScreenPointPixel-lib", CallingConvention = CallingConvention.Cdecl)]\n public static extern void initScreenPointPixel(IntPtr buffer, int x, int y, int width, int height);\n //-------------------------------------------------------------------------------------\n [DllImport("ScreenPointPixel-lib", CallingConvention = CallingConvention.Cdecl)]\n public static extern void updateScreenPointPixelBufferPointer(IntPtr buffer);\n //-------------------------------------------------------------------------------------\n [DllImport("ScreenPointPixel-lib", CallingConvention = CallingConvention.Cdecl)]\n public static extern void updateScreenPointPixelCoordinate(int x, int y);\n //-------------------------------------------------------------------------------------\n [DllImport("ScreenPointPixel-lib", CallingConvention = CallingConvention.Cdecl)]\n public static extern void updateScreenPointPixelSize(int width, int height);\n //-------------------------------------------------------------------------------------\n\n //-------------------------------------------------------------------------------------\n [DllImport("ScreenPointPixel-lib", CallingConvention = CallingConvention.StdCall)]\n private static extern IntPtr GetRenderEventScreenPointPixelFunc();\n //-------------------------------------------------------------------------------------\n int width = 500;\n int height = 500;\n\n //Where Pixel data will be saved\n byte[] screenData;\n //Where handle that pins the Pixel data will stay\n GCHandle pinHandler;\n\n //Used to test the color\n public RawImage rawImageColor;\n\n // Use this for initialization\n void Awake()\n {\n Resolution res = Screen.currentResolution;\n width = res.width;\n height = res.height;\n\n //Allocate array to be used\n screenData = new byte[width * height * 4];\n\n //Pin the Array so that it doesn\'t move around\n pinHandler = GCHandle.Alloc(screenData, GCHandleType.Pinned);\n\n //Register the screenshot and pass the array that will receive the pixels\n IntPtr arrayPtr = pinHandler.AddrOfPinnedObject();\n\n initScreenPointPixel(arrayPtr, 0, 0, width, height);\n\n StartCoroutine(caller());\n }\n\n IEnumerator caller()\n {\n while (true)\n {\n //Use mouse position as the pixel position\n //Input.tou\n\n\n#if UNITY_ANDROID || UNITY_IOS || UNITY_WSA_10_0\n if (!(Input.touchCount > 0))\n {\n yield return null;\n continue;\n }\n\n //Use touch position as the pixel position\n int x = Mathf.FloorToInt(Input.GetTouch(0).position.x);\n int y = Mathf.FloorToInt(Input.GetTouch(0).position.y);\n#else\n //Use mouse position as the pixel position\n int x = Mathf.FloorToInt(Input.mousePosition.x);\n int y = Mathf.FloorToInt(Input.mousePosition.y);\n#endif\n //Change this to any location from the screen you want\n updateScreenPointPixelCoordinate(x, y);\n\n //Must be 1 and 1\n updateScreenPointPixelSize(1, 1);\n\n //Take screenshot of the screen\n GL.IssuePluginEvent(GetRenderEventScreenPointPixelFunc(), 1);\n\n //Get the Color\n Color32 tempColor = new Color32();\n tempColor.r = screenData[0];\n tempColor.g = screenData[1];\n tempColor.b = screenData[2];\n tempColor.a = screenData[3];\n\n //Test it by assigning it to a raw image\n rawImageColor.color = tempColor;\n\n //Wait for a frame\n yield return null;\n }\n }\n\n void OnDisable()\n {\n //Unpin the array when disabled\n pinHandler.Free();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
3459 次 |
| 最近记录: |