質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

690閲覧

OpenTKを用いたUnityによる物体描画

abc_oxox

総合スコア27

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2017/11/21 07:40

unityで物体を描画するにあたって,計算の過程でOpenTKを使用したいのですが,仕様上不可能なのでしょうか.

C#のコードでOpenTKを用いて書かれたコードがあり,それをUnityへ移植しているのですが,コード内ではOpenTKの参照は追加済みでエラーはでていないのですが,Unityで実行すると,
「The type or namespace name 'OpenTK' could not be found.Are you missing an assembly reference?」
というようなエラーがでます.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fiveHundred

2017/11/22 09:23

「OpenTKの参照は追加済み」とのことですが、どのようにして追加したのでしょうか?。また、そのOpenTKを使って行いたい処理とは、具体的になんでしょうか?
guest

回答1

0

ベストアンサー

回答というより失敗報告で申し訳ないのですが...

OpenTK自体はマネージドアセンブリのようですので、NuGet Gallery | OpenTK 2.0.0
から入手したopentk.2.0.0.nupkgを展開、中に入っているOpenTK.dllを、Unityプロジェクト内にPluginsフォルダを作って中に入れるだけでスクリプトから参照することはできました。この状態で、OpenGLと関係ないOpenTKの機能(行列計算とか)は使えるかもしれませんが、OpenTK.Graphics.OpenGL.GLとかOpenTK.Graphics.ES30.GLの機能を使おうとするとUnityが異常終了したり応答不能になったりしてダメでした。

OpenGLの機能を使うには適切なGraphicsContextを用意してやる必要があるはず、それがないからダメなのか...?と思い、Unity - Manual: Low-level Native Plugin Interfaceに載っていたNativeRenderingPluginのサンプルをダウンロード、RenderingPlugin.cppを下記のように書き換えて(C++の知識も各プラットフォームの知識も不十分な状態で見よう見まねで書いたので、とんでもないコードになっている可能性がありますがご容赦下さい)、XcodeでビルドしてRenderingPlugin.bundleを、Visual StudioでビルドしてRenderingPlugin.dllを作り、これらもPluginsフォルダに入れました。

C++

1#include "PlatformBase.h" 2#include "RenderAPI.h" 3 4#include <assert.h> 5#include <math.h> 6#include <vector> 7 8// -------------------------------------------------------------------------- 9// UnitySetInterfaces 10 11static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType); 12 13static IUnityInterfaces* s_UnityInterfaces = NULL; 14static IUnityGraphics* s_Graphics = NULL; 15 16extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) { 17 s_UnityInterfaces = unityInterfaces; 18 s_Graphics = s_UnityInterfaces->Get<IUnityGraphics>(); 19 s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); 20 21 // Run OnGraphicsDeviceEvent(initialize) manually on plugin load 22 OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize); 23} 24 25extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() { 26 s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent); 27} 28 29#if UNITY_WEBGL 30typedef void (UNITY_INTERFACE_API * PluginLoadFunc)(IUnityInterfaces* unityInterfaces); 31typedef void (UNITY_INTERFACE_API * PluginUnloadFunc)(); 32 33extern "C" void UnityRegisterRenderingPlugin(PluginLoadFunc loadPlugin, PluginUnloadFunc unloadPlugin); 34 35extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API RegisterPlugin() { 36 UnityRegisterRenderingPlugin(UnityPluginLoad, UnityPluginUnload); 37} 38#endif 39 40// -------------------------------------------------------------------------- 41// GraphicsDeviceEvent 42 43static RenderAPI* s_CurrentAPI = NULL; 44static UnityGfxRenderer s_DeviceType = kUnityGfxRendererNull; 45 46static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { 47 // Create graphics API implementation upon initialization 48 if (eventType == kUnityGfxDeviceEventInitialize) { 49 assert(s_CurrentAPI == NULL); 50 s_DeviceType = s_Graphics->GetRenderer(); 51 s_CurrentAPI = CreateRenderAPI(s_DeviceType); 52 } 53 54 // Let the implementation process the device related events 55 if (s_CurrentAPI) { 56 s_CurrentAPI->ProcessDeviceEvent(eventType, s_UnityInterfaces); 57 } 58 59 // Cleanup graphics API implementation upon shutdown 60 if (eventType == kUnityGfxDeviceEventShutdown) { 61 delete s_CurrentAPI; 62 s_CurrentAPI = NULL; 63 s_DeviceType = kUnityGfxRendererNull; 64 } 65} 66 67// -------------------------------------------------------------------------- 68// OnRenderEvent 69// This will be called for GL.IssuePluginEvent script calls; eventID will 70// be the integer passed to IssuePluginEvent. In this example, we just ignore 71// that value. 72 73typedef void (*OpenTKRenderingCallback)(void* context, int eventID); 74 75static OpenTKRenderingCallback s_RenderingCallback; // レンダリング時のコールバック...この中でOpenTKの機能を使う(ようにすればうまくいくかと思ったが失敗) 76 77extern "C" UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetCurrentGLContext(); 78extern "C" UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetGLProcAddress(const char* name); 79 80static void UNITY_INTERFACE_API OnRenderEvent(int eventID) { 81 // Unknown / unsupported graphics device type? Do nothing 82 if (s_CurrentAPI == NULL) 83 return; 84 85 if (s_RenderingCallback) { 86 s_RenderingCallback(GetCurrentGLContext(), eventID); 87 } 88} 89 90// -------------------------------------------------------------------------- 91// GetRenderEventFunc, an example function we export which is used to get a rendering event callback function. 92 93extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFunc() { 94 return OnRenderEvent; 95} 96 97// -------------------------------------------------------------------------- 98// コールバックを登録 99extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SetRenderingCallback(OpenTKRenderingCallback callback) { 100 s_RenderingCallback = callback; 101} 102 103// -------------------------------------------------------------------------- 104// 現在のOpenGLコンテキストを取得/OpenGL関数を名前から取得 105 106#if SUPPORT_OPENGL_LEGACY || SUPPORT_OPENGL_UNIFIED || SUPPORT_OPENGL_CORE || SUPPORT_OPENGL_ES 107#if UNITY_WIN 108#include <windows.h> 109 110extern "C" UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetCurrentGLContext() { 111 return wglGetCurrentContext(); 112} 113 114extern "C" UNITY_INTERFACE_EXPORT void* UNITY_INTERFACE_API GetGLProcAddress(const char* name) { 115 return wglGetProcAddress(name); 116} 117#elif UNITY_LINUX // Linux版はテストしていないが、多分こんな感じだろうか? 118#include "glxew.h" 119 120extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetCurrentGLContext() { 121 return glXGetCurrentContext(); 122} 123 124extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetGLProcAddress(const char* name) { 125 return glXGetProcAddress(name); 126} 127#elif UNITY_OSX // iOSはコンテキスト取得のAPIがObjective-C用しかない?やりようはありそうだが、過度な複雑化を避けるためiOSはさしあたり無視 128#include <OpenGL/OpenGL.h> 129#include <dlfcn.h> 130 131extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetCurrentGLContext() { 132 return CGLGetCurrentContext(); 133} 134 135extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetGLProcAddress(const char *name) { 136 // https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_entrypts/opengl_entrypts.html#//apple_ref/doc/uid/TP40001987-CH402-SW6 掲載のサンプルコードは古いので 137 // https://sourceforge.net/p/glew/patches/17/ の方法を採用 138 139 static void* image = NULL; 140 void* symbol; 141 char* symbolName; 142 143 if (!image) { 144 image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); 145 } 146 147 symbolName = (char*)malloc(strlen(name) + 2); 148 strcpy(symbolName + 1, name); 149 symbolName[0] = '_'; 150 symbol = image ? dlsym(image, symbolName) : NULL; 151 free(symbolName); 152 153 return symbol; 154} 155#else 156extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetCurrentGLContext() { 157 return NULL; 158} 159 160extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetGLProcAddress(const char* name) { 161 return NULL; 162} 163#endif 164#else 165extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetCurrentGLContext() { 166 return NULL; 167} 168 169extern "C" void* UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetGLProcAddress(const char* name) { 170 return NULL; 171} 172#endif

そしてUnity側ではカメラに下記スクリプトをアタッチし、OnPostRenderのタイミングでコンテキストを取得(ここまではMac版、Windows版ともにできたように見えましたが)、いざOpenGLの機能を使えるか...と思ったらやっぱりダメでした。

C#

1using UnityEngine; 2using OpenTK; 3using OpenTK.Graphics; 4using OpenTK.Graphics.OpenGL; 5using System; 6using System.Runtime.InteropServices; 7 8using TKGL = OpenTK.Graphics.OpenGL.GL; // UnityEngineのGLと名前かぶりするので別名を用意 9 10[RequireComponent(typeof(Camera))] 11public class OpenTKTest : MonoBehaviour 12{ 13 private static GraphicsContext OpenGLContext; 14 15 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 16 private delegate void RenderingCallback(IntPtr contextPointer, int eventID); 17 18 [DllImport("RenderingPlugin")] 19 private static extern void SetRenderingCallback([MarshalAs(UnmanagedType.FunctionPtr)] RenderingCallback callback); 20 21 [DllImport("RenderingPlugin")] 22 private static extern IntPtr GetRenderEventFunc(); 23 24 [DllImport("RenderingPlugin")] 25 private static extern IntPtr GetCurrentGLContext(); 26 27 [DllImport("RenderingPlugin")] 28 private static extern IntPtr GetGLProcAddress([MarshalAs(UnmanagedType.LPStr)] string name); 29 30 private static ContextHandle GetCurrentContextAsContextHandle() 31 { 32 return new ContextHandle(GetCurrentGLContext()); 33 } 34 35 private void Start() 36 { 37 SetRenderingCallback(this.RenderWithOpenTK); 38 } 39 40 // Unityの描画終了後にOpenTKにより追加描画 41 private void OnPostRender() 42 { 43 UnityEngine.GL.IssuePluginEvent(GetRenderEventFunc(), 1234); // イベントIDに適当な値を渡し、値が伝達されるかテスト 44 } 45 46 private void RenderWithOpenTK(IntPtr contextPointer, int eventID) 47 { 48 if (OpenGLContext == null) 49 { 50 Debug.LogFormat("Context:{0} Event ID:{1}", contextPointer, eventID); // Mac、Windowsともに一応コンテキストのポインタらしきものは取れて、ダミーコンテキストもエラーなく生成できるのだが... 51 OpenGLContext = new GraphicsContext(new ContextHandle(contextPointer), GetGLProcAddress, GetCurrentContextAsContextHandle); 52 OpenGLContext.MakeCurrent(null); 53 // Debug.Log(TKGL.GetString(StringName.Version)); // GLの機能を使おうとするとUnityがクラッシュ、または応答しなくなる 54 } 55 56 Debug.Log(GraphicsContext.CurrentContext); 57 // TKGL.Clear(ClearBufferMask.ColorBufferBit); 58 } 59}

OpenTK用のコードをそのまま動かそうとするのはハードルが高そうです。追記修正欄にてfiveHundredさんもご指摘なさっていますが、その「OpenTKを用いて書かれたコード」はどういったものでしょうか?さほど規模が大きくなければ、それをOpenTK不使用の完全Unityオンリーなコードに書き換える方が、より現実的かもしれません。

投稿2017/11/23 02:15

Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

abc_oxox

2017/11/23 08:48

大変丁寧な回答ありがとうございます. 「OpenTKを用いて書かれたコード」ですが,OpenTK.Graphics.OpenGL.GLを用いて描画するコードがありますが,Unityで代用できそうです. 他はOpenTK.dllを、Unityプロジェクト内のPluginsフォルダに入れることでエラーは消えてくれました. ありがとうございました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問