看完这个视频后,我开始思考如何在我当前的项目中实现类似的东西。我认为让我的大部分代码实时可编辑太难了,但我认为我至少可以在玩游戏时让我的 OpenGL 着色器可编辑。
所以我设置了一个FileSystemWatcher
:
protected void WatchShaders()
{
_uiDispatcher = Dispatcher.CurrentDispatcher;
const string shaderDir = @"path\to\my\shaders";
_shaderFileWatcher = new FileSystemWatcher(shaderDir);
_shaderFileWatcher.NotifyFilter = NotifyFilters.LastWrite;
//fw.Filter = "*.frag;*.vert";
_shaderFileWatcher.Changed += ShaderChanged;
_shaderFileWatcher.EnableRaisingEvents = true;
}
现在我想在文件更改时更新着色器:
void ShaderChanged(object sender, FileSystemEventArgs e)
{
_shaderFileWatcher.EnableRaisingEvents = false; // prevent more/duplicate events from firing before we've finished processing the current one
lock (_bfShader)
{
_bfShader.AttachShader(Shader.FromFile(e.FullPath));
_bfShader.Link();
_bfShader.Use();
_bfProjUniform = new Uniform(_bfShader, "ProjectionMatrix");
_bfSampler = new Uniform(_bfShader, "TexSampler");
_bfSampler.Set1(0);
}
_shaderFileWatcher.EnableRaisingEvents = true;
}
问题是,一旦我编辑我的着色器文件,就会抛出异常:
调用线程中没有当前上下文
所以我做了一些挖掘,发现 OpenGL 上下文本质上是绑定到单个线程的。AFAIK,有两种解决方法:
- 在主 UI 线程上禁用 OpenGL 上下文,在另一个线程上启用它,做我的事情,然后重置它
- 将事件分派回主 UI 线程
我不确定我将如何实现 (1),因为主线程充满了 OpenGL 调用......我不知道在哪里启用和禁用它。
所以我只剩下选项(2),除了我不知道如何将文件更改事件分派回主线程。
这篇文章说:
GLControl 提供 GLControl.BeginInvoke() 方法来简化从辅助线程到主 System.Windows.Forms.Application 线程的异步方法调用。GameWindow 不提供类似的 API。
不幸的是,我使用的是GameWindow
,所以我不确定如何访问该功能。
那么将我的事件分派回主 UI 线程的最简单方法是什么?使用 OpenTK 库还是另一个最好的非 Windows 库?