После просмотра этого видео я начал думать о том, как мне реализовать что-то подобное в моем текущем проекте. Я думаю, что было бы слишком сложно сделать большую часть моего кода редактируемой в реальном времени, но я думал, что по крайней мере смогу сделать свои шейдеры 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, есть 2 обходных пути для этого:
- Отключите контекст OpenGL в главном потоке пользовательского интерфейса, включите его в другом потоке, выполните мои действия, а затем сбросьте его
- Отправка события обратно в основной поток пользовательского интерфейса
Я не уверен, как бы я реализовал (1), потому что основной поток пронизан вызовами OpenGL ... Я не знаю, где его включить и отключить.
Так что у меня осталась опция (2), за исключением того, что я не могу понять, как отправить событие с измененным файлом обратно в основной поток.
В этой статье говорится:
GLControl предоставляет метод GLControl.BeginInvoke () для упрощения асинхронных вызовов методов из вторичных потоков в основной поток System.Windows.Forms.Application. GameWindow не предоставляет аналогичный API.
К сожалению, я использую GameWindow
, поэтому я не уверен, как получить доступ к этой функции.
Так какой самый простой способ отправить мое событие обратно в основной поток пользовательского интерфейса? Вы используете библиотеку OpenTK или другую , предпочтительно не только для Windows, библиотеку?