openframeworks / openFrameworks

openFrameworks is a community-developed cross platform toolkit for creative coding in C++.
http://openframeworks.cc
Other
9.91k stars 2.55k forks source link

ofxOpenCv textures not drawing with Programmable Renderer. #4378

Closed ofTheo closed 9 years ago

ofTheo commented 9 years ago

OS X 10.10 current master.

Currently trying to debug this. But if you run the openCvExample and set the renderer in main:

    ofGLWindowSettings settings;
    settings.width = 1800;
    settings.height = 900;
    settings.setGLVersion(3, 2);
    ofCreateWindow(settings);

    // this kicks off the running of my app
    // can be OF_WINDOW or OF_FULLSCREEN
    // pass in width and height too:
    ofRunApp( new ofApp());

You will only see the video texture and not the opencv textures.

Also if you try and load the data into a texture to draw it externally the texture is drawn red. Printing out the textures internal format shows it to be 6403 which in hex is 0x1903 = GL_RED

If I switch it back to the non programmable renderer it shows the format to be 6409 ( GL_LUMINANCE )

screen shot 2015-09-18 at 12 50 50 pm

tgfrerer commented 9 years ago

This might be because GL_LUMINANCE was deprecated in OpenGL with the advent of 3.2.

GL_RED is traditionally the correct texture type to take up its place. Most probably the shader used to render the texture is not recognising it properly.

I can look into it once I'm on a proper computer.

On 18 Sep 2015, at 12:51, Theodore Watson notifications@github.com wrote:

OS X 10.10 current master.

Currently trying to debug this. But if you run the openCvExample and set the renderer in main:

ofGLWindowSettings settings;
settings.width = 1800;
settings.height = 900;
settings.setGLVersion(3, 2);
ofCreateWindow(settings);

// this kicks off the running of my app
// can be OF_WINDOW or OF_FULLSCREEN
// pass in width and height too:
ofRunApp( new ofApp());

You will only see the video texture and not the opencv textures.

Also if you try and load the data into a texture to draw it externally the texture is drawn red. Printing out the textures internal format shows it to be 6403 which in hex is 0x1903 = GL_RED

If I switch it back to the non programmable renderer it shows the format to be 6409 ( GL_LUMINANCE )

— Reply to this email directly or view it on GitHub.

arturoc commented 9 years ago

you need to allocate the texture using the pixels directly instead of passing any GL enum like:

tex.allocate(pixels);

then ofTexture will do the right thing. to solve the red texture you can call:

tex.setRGToRGBASwizzles(true)

i though all these were already fixed

arturoc commented 9 years ago

that fixes it, i remember now that i started fixing it but didn't because the structure is pretty convoluted. i've added a couple of methods that allocate the corresponding texture and pixels on each image type. there's some really weird things like the ofPixels in the base image that is then not used in the short and float images.

we should switch or at least include ofxCv for next release

ofTheo commented 9 years ago

@arturoc oh great! just tested this with both the regular and programmable renderer. both work fine now in terms of drawing the cv images.

however in the programmable renderer the texture allocated from grayImage.getPixels() is still showing up red.

to reproduce:

        myTex.loadData(grayImage.getPixels());
    ofSetColor(255, 255, 255);
    myTex.draw(ofGetMouseX(), ofGetMouseY());
ofTheo commented 9 years ago

ps: agree on having a more modern CV implementation. ofxOpenCv is about as legacy as it gets ( though still pretty useful for what it covers )

arturoc commented 9 years ago

yes that can't be fixed just like that, there's no LUMINANCE target in GL 3+ so you always have to use GL_RED. the swizzles thing tells the shaders that r -> rgb and g -> a but i don't think we should enable it by default, it's just how opengl 3+ works, any image with 1 channel goes in a GL_RED texture which by default has b and g as 0

arturoc commented 9 years ago

you can do:

myTex.setRGToRGBASwizzles(true);

in setup and that will make the image show as grayscale

ofTheo commented 9 years ago

hmm if I do:

        myTex.loadData(grayImage.getPixels());
        myTex.setRGToRGBASwizzles(true);

it still shows red. same with:

        myTex.setRGToRGBASwizzles(true);
        myTex.loadData(grayImage.getPixels());

assuming this can be fixed for 1.0 to 3.2 compatibility couldn't we do something inside of ofTexture::loadData that would do the swizzle automatically if the incoming target is a single channel?

or maybe better do this at the default shader level?

ofTheo commented 9 years ago

hmm if I do:

        myTex.allocate(grayImage.getPixels());
        myTex.setRGToRGBASwizzles(true);

then it comes through fine. looks like something with loadData?

DomAmato commented 9 years ago

we should switch or at least include ofxCv for next release

Is this something like a 0.9.1 release or a 0.10.0 idea. I am open to looking into updating the openCV implementation since it might actually cover some of the other issues that occasionally get brought up. I am curious about how their videoWriter compares to ffmpegs which has been slightly a PITA to work with.

arturoc commented 9 years ago

the auto allocation in ofTexture just uses the passed format as internal format which is not very correct and won't always work. it's kind of a workaround and the only way to ensure that a texture will do the right thing is to allocate it first and then load data onto it.

there's even a todo comment in that part of the code:

// TODO: guess correct internal from glFormat

which can more or less be done but won't always work.

i've added some checks when calling loadData with ofPixels so it allocates from that instead of trying to pass the glFormat as internal but when loading data from raw memory it'll still fail.

i've also added a check on allocate with ofPixels so if the pixel format of the pixels is gray or gray alpha then it auto enables the RG->RGBA swizzles.