как реализовать рендеринг шкалы полутонов в OpenGL?

Вы не можете писать в закрытый файл, поэтому, если вы закрываете его после каждой операции записи, вам также придется (повторно) открывать его перед каждой записью.

Это было бы совершенно неэффективно. Поэтому вместо этого оставьте его открытым и закройте его только после того, как ваше приложение собирается завершить работу (это необходимо, потому что File.Write() не гарантирует, что при возврате данные будут записаны на диск). Поскольку вы пишете файл из обработчиков HTTP, вы должны реализовать корректное завершение работы сервера и после этого закрыть файл. Подробнее см. Server.Shutdown() .

Кроме того, если целью записи вашего общего файла является создание какого-либо регистратора, вы можете воспользоваться пакетом log , чтобы вам не пришлось использовать мьютекс. Подробнее см. net / http set custom logger .

5
задан Community 23 May 2017 в 10:31
поделиться

3 ответа

По умолчанию в буфере кадров OpenGL используется Цветовое пространство RGB, которое не хранит явную насыщенность. Вам нужен подход для извлечения насыщенности, ее изменения и повторного изменения.

Мое предыдущее предложение, которое просто использовало длину вектора RGB для представления 0 яркости, было неверным, так как оно не учитывало масштабирование, прошу прощения.

Благодарность за новый короткий фрагмент принадлежит обычному пользователю "RTFM_FTW "из ## opengl и ## opengl3 на FreeNode / IRC, и это позволяет вам изменять насыщенность напрямую, не вычисляя дорогостоящее преобразование RGB-> HSV-> RGB, что именно то, что вам нужно. Хотя код HSV уступает вашему вопросу, я оставлю его.

void main( void ) 
{ 
    vec3 R0 = texture2DRect( S, gl_TexCoord[0].st ).rgb;
    gl_FragColor = vec4( mix( vec3( dot( R0, vec3( 0.2125, 0.7154, 0.0721 ) ) ),
        R0, T ), gl_Color.a ); 
}

Если вы хотите большего контроля, чем просто насыщенность, вам нужно преобразовать в цветовое пространство HSL или HSV. Как показано ниже, с использованием шейдера фрагментов GLSL.

Прочтите спецификации OpenGL 3.0 и GLSL 1.30, доступные на http://www.opengl.org/registry , чтобы узнать, как использовать функциональность GLSL v1.30 .

#version 130
#define RED 0
#define GREEN 1
#define BLUE 2

in vec4 vertexIn;
in vec4 colorIn;
in vec2 tcoordIn;
out vec4 pixel;
Sampler2D tex;
vec4 texel;
const float epsilon = 1e-6;

vec3 RGBtoHSV(vec3 color)
{
    /* hue, saturation and value are all in the range [0,1> here, as opposed to their
       normal ranges of: hue: [0,360>, sat: [0, 100] and value: [0, 256> */
    int sortindex[3] = {RED,GREEN,BLUE};
    float rgbArr[3] = float[3](color.r, color.g, color.b);

    float hue, saturation, value, diff;
    float minCol, maxCol;
    int minIndex, maxIndex;

    if(color.g < color.r)
        swap(sortindex[0], sortindex[1]);
    if(color.b < color.g)
        swap(sortindex[1], sortindex[2]);
    if(color.r < color.b)
        swap(sortindex[2], sortindex[0]);

    minIndex = sortindex[0];
    maxIndex = sortindex[2];
    minCol = rgbArr[minIndex];
    maxCol = rgbArr[maxIndex];

    diff = maxCol - minCol;

    /* Hue */
    if( diff < epsilon){
        hue = 0.0;
    }
    else if(maxIndex == RED){
        hue = ((1.0/6.0) * ( (color.g - color.b) / diff )) + 1.0;
        hue = fract(hue);
    }
    else if(maxIndex == GREEN){
        hue = ((1.0/6.0) * ( (color.b - color.r) / diff )) + (1.0/3.0);
    }
    else if(maxIndex == BLUE){
        hue = ((1.0/6.0) * ( (color.r - color.g) / diff )) + (2.0/3.0);        
    }

    /* Saturation */
    if(maxCol < epsilon)
        saturation = 0;
    else
        saturation = (maxCol - minCol) / maxCol;

    /* Value */
    value = maxCol;

    return vec3(hue, saturation, value);
}
vec3 HSVtoRGB(vec3 color)
{
    float f,p,q,t, hueRound;
    int hueIndex;
    float hue, saturation, value;
    vec3 result;

    /* just for clarity */
    hue = color.r;
    saturation = color.g;
    value = color.b;

    hueRound = floor(hue * 6.0);
    hueIndex = int(hueRound) % 6;
    f = (hue * 6.0) - hueRound;
    p = value * (1.0 - saturation);
    q = value * (1.0 - f*saturation);
    t = value * (1.0 - (1.0 - f)*saturation);

    switch(hueIndex)
    {
        case 0:
            result = vec3(value,t,p);
        break;
        case 1:
            result = vec3(q,value,p);
        break;
        case 2:
            result = vec3(p,value,t);
        break;
        case 3:
            result = vec3(p,q,value);
        break;
        case 4:
            result = vec3(t,p,value);
        break;
        default:
            result = vec3(value,p,q);
        break;
    }
    return result;
}
void main(void)
{
    vec4 srcColor;
    vec3 hsvColor;
    vec3 rgbColor;
    texel = Texture2D(tex, tcoordIn);
    srcColor = texel*colorIn;
    hsvColor = RGBtoHSV(srcColor.rgb);
    /* You can do further changes here, if you want. */
    hsvColor.g = 0; /* Set saturation to zero */
    rgbColor = HSVtoRGB(hsvColor);
    pixel = vec4(rgbColor.r, rgbColor.g, rgbColor.b, srcColor.a);
}
9
ответ дан 18 December 2019 в 14:51
поделиться

Для большинства рабочих столов Render-To-Texture не так уж и дорог, от этого зависят все compiz, aero и т. Д., А также эффекты, такие как цветение или глубина резкости, наблюдаемые в последних играх. ] На самом деле вы не конвертируете текстуру экрана как таковую в оттенки серого, вам нужно нарисовать четырехугольник размером с экран с текстурой и фрагментным шейдером, преобразующим значения в оттенки серого.

Другой вариант - иметь два набора фрагментов шейдеры для ваших треугольников, один просто копирует атрибут gl_FrontColor как фиксированная функция pieline, а другой записывает значения оттенков серого в экранный буфер.

Третьим вариантом могут быть режимы индексированных цветов, если вы установите uüp палитру оттенков серого, но этот режим может быть устарел и плохо поддерживается в настоящее время; плюс, если я правильно помню, вы теряете много функциональности, например, смешивание.

2
ответ дан 18 December 2019 в 14:51
поделиться

Если вы работаете с достаточно современным OpenGL, я бы сказал, что пиксельные шейдеры являются здесь очень подходящим решением. Либо подключившись к затенению каждого многоугольника во время рендеринга, либо выполнив один полноэкранный четырехугольник за второй проход, который просто считывает каждый пиксель, преобразует его в оттенки серого и записывает его обратно. Если ваше разрешение, графическое оборудование и целевая частота кадров не являются «экстремальными», в большинстве случаев это возможно в наши дни.

2
ответ дан 18 December 2019 в 14:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: