фоновый поток, отображающий текстуру

Я пишу простой рейкастер на C#, используя OpenTK. Я хочу, чтобы мое представление обновлялось 60 раз в секунду, поэтому у меня есть таймер, вызывающий мою функцию Render(), которая показывает текстуру на экране.

Я хочу использовать рекурсивную функцию для рендеринга моей сцены, разделив ее на меньшие прямоугольники и рендеринг каждого из них до тех пор, пока размер прямоугольника не станет равным 1px. Моя рекурсия записывает цвета пикселей в массив байтов, которые мне нужно преобразовать в текстуру. Рекурсия довольно медленная, поэтому я хочу запускать ее в фоновом потоке всякий раз, когда моя сцена меняется.

Как правильно синхронизировать потоки, чтобы один писал в массив текстур (это занимает около секунды), а другой поток читал его каждые 1/60 секунды и выводил на экран?

    byte[, ,] texture;

рекурсия:

    public void RenderAdaptively(int top, int left, int width, int height)
    {
        Color color = getColor(top, left);
        for (int i = top; i < top + width + 1; i++)
        {
            for (int j = left; j < left + height; j++)
            {
                texture[i, j, 0] = color.R;
                texture[i, j, 1] = color.G;
                texture[i, j, 2] = color.B;
            }
        }

        int halfw = width / 2;
        int halfh = height / 2;
        int newwidth = width - halfw;
        int newheight = height - halfh;

        if (width > 1 && height > 1)
        {
            RenderAdaptively(top, left, halfw, halfh, false);
            RenderAdaptively(top + halfw, left + halfh, newwidth, newheight, false);
            RenderAdaptively(top, left + halfh, halfw, newheight, false);
            RenderAdaptively(top + halfw, left, newwidth, halfh, false);
        }
    }

в другой теме:

    raycasting_texture = TexUtil.CreateRGBTexture(width, height, texture);

person 4gn3s    schedule 10.03.2013    source источник
comment
Покажи свою работу здесь..   -  person Soner Gönül    schedule 10.03.2013


Ответы (1)


У вас есть несколько вариантов, но я бы сделал так:

  • иметь два буфера для хранения текстуры в виде массива байтов, скажем, 0 и 1,

  • сделать вычисление текстуры в одном буфере,

  • когда это будет сделано, сообщите об этом, установив volatile int updated_buffer для обновленного индекса буфера.

  • пусть другой поток периодически читает updated_buffer и сохраняет копию его последнего значения. Когда эта копия и int не синхронизированы, обновите копию и загрузите текстуру в память,

Обратите внимание, что это решение зависит от нескольких вещей:

  1. есть только два потока, работающих с буферами массива байтов,

  2. updated_buffer читается только потоком-потребителем (текстуры) и записывается потоком-производителем,

  3. и самое главное, загрузка текстуры заметно быстрее, чем вычисление.

Если № 2 или № 3 не работают, вам придется использовать более строгий подход к синхронизации буферов текстур, например мьютексы, чтобы убедиться, что буферы текстур не перезаписываются во время загрузки.

Наконец, ваши рекурсивные вычисления могут получить небольшое ускорение, перейдя к итерации ниже определенного порога (скажем, блока 8 * 8 пикселей), вместо того, чтобы идти полностью до 1 пикселя. На самом деле делать все это итеративно должно быть быстрее (если делать в одном потоке на одном ядре), хотя это сильно зависит от алгоритма вычисления пикселей.

person didierc    schedule 10.03.2013