хроматический ключ с открытой рамой / opengl - PullRequest
5 голосов
/ 24 января 2011

Мне нужно реализовать хроматическую клавиатуру (удаление сплошного цветного фона) в приложении openFrameworks.

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

Существует ли простой режим наложения OpenGL или операция маскирования, которая позволяет избежать рисования всех пикселей определенного значения цвета?Или есть другая openFrameworks или openFrameworks-совместимая библиотека C ++, которая может сделать это эффективно?

В качестве альтернативы, есть ли хороший (экономичный) способ хранения альфа-канала в видеофайлах, совместимых с быстрым временем?Мы собираемся хранить терабайты видео (недели непрерывной записи), поэтому важно использовать компактные форматы.

Одно замечание: цвет хроматического ключа в исходных файлах будет "идеальным""- добавлено в цифровом виде.Поэтому, если для этого есть какой-то трюк с пороговой или битовой логикой, это тоже может сработать.


EDIT : Вот что сработало, следуя предложению VJo для пиксельного шейдера.Мы использовали glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) и следующий пиксельный шейдер (для пурпурного цвета в качестве заменяемого цвета):

"data / shaders / chromakey.frag":

#extension GL_ARB_texture_rectangle : enable

uniform sampler2DRect src_tex_unit0;
vec4 color;

void main( void )
{
        vec2 st = gl_TexCoord[0].st;
        vec4 sample = texture2DRect(src_tex_unit0, st );
        gl_FragColor = sample;
        if((sample.r > 0.5) && (sample.g < 0.5) && (sample.b > 0.5)) {
                gl_FragColor.a = 0.0;
        }
}

"data / shaders /chromakey.vert ":

void main()
{
    gl_Position = ftransform();
    gl_TexCoord[0] = gl_MultiTexCoord[0];
}

Прокси-классы C ++ для шейдеров - shaderChromakey.h:

#include "ofMain.h"
#include "ofxShader.h"
#include "ofxFBOTexture.h"

class shaderChromakey{

    public:
        void setup(int fboW, int fboH);

        void beginRender();
        void endRender();

        void draw(int x, int y, int width, int height);

        ofxShader shader;

        ofxFBOTexture fbo;

};

shaderChromakey.cpp:

#include "shaderChromakey.h"

//--------------------------------------------------------------
void shaderChromakey::setup(int fboW, int fboH){ 

    ofBackground(255,255,255);
    ofSetVerticalSync(true);

    fbo.allocate(fboW, fboH, true);

    shader.loadShader("shaders/chromakey");
}

//--------------------------------------------------------------
void shaderChromakey::beginRender(){
    fbo.swapIn();
}

//--------------------------------------------------------------
void shaderChromakey::endRender(){
    fbo.swapOut();
}

//--------------------------------------------------------------
void shaderChromakey::draw(int x, int y, int width, int height){

    shader.setShaderActive(true);
    fbo.draw(x, y, width, height);
    shader.setShaderActive(false);
}

Комусоздать экземпляр шейдера в проекте:

shaderChromakey chromakey;
chromakey.setup(HORIZONTAL, VERTICAL)

В цикле рисования, чтобы включить шейдер:

chromakey.beginRender();
    // draw chomakeyed frame here
chromakey.endRender();

1 Ответ

2 голосов
/ 24 января 2011

Вы можете использовать glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_DST_ALPHA), а затем, когда вы включаете смешивание, вы можете использовать пиксельный шейдер, чтобы делать то, что вы хотите, если пиксель имеет определенный цвет (установите альфа в 0).

...