I know that this subject was already touched upon here a couple of years ago but I want to refresh it.
I'm interested in implementing OpenGL in After Effects' plugin. Is is possible yet? If yes - how?
This is my simple example code I would like to use in After Effects plugin:
int size = 500;
glColor4f(1, 0, 0, 1);
Any help would be appreciated.
There is an example called "GLator" in the AE SDK which apparently shows how to use OpenGL and AE together (by getting the input buffer, copying that to a texture, using that texture on a FBO, then reading the pixels form that FBO back into the output buffer), but this example crashes on my PCs (because of an incomplete FBO configuration). Maybe you have more luck :-)
I have been trying to get an OpenGL example plugin in AfterEffects working for about 2 weeks now, but no success yet.
If you manage to come up with even a simple example of drawing something in OpenGL and then copying that back to the AE buffer, I would be so happy to see it :-)
did you have any success getting OpenGL to work?
And for anyone else - did the "GLator" example from the SDK ever work for you?
I tried it with the CS4 SDK as a 32bit plugin and the 64-bit versions from the CS5 and CS6 SDKs, with different ATI and NVidia graphic cards.
Although it compiles and loads, it crashes immediately. On debugging, I found out that the OpenGL FBO framebuffer initialisation return OK, but when wanting to use it in the render function,
glCheckFramebufferStatus complains with GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT.
The same OpenGL code put into a standalone program works correctly, so I assume that one of the needed ressources has gone out of scope between the init and render functions.
Therefore my question if this specific "GLator" SDK example ever worked for anyone? I assume so, since it wouldn't have made sense to put it in the SDK, but I would like to have positive feedback from anyone.
And I am still very much looking for any OpenGL related integration into AE, so if anyone has only the simplest code example to share, I would be very happy :-)
I did use openGL in AE but not directly... not like GLator.
I used MesaGL and software rendering... so i did not use the graphic card.
I used a Offscreen context: OSMesaContext
I did not check if ti worked without offscreen methods.
Here are a few pointers, I have learned from the past years with OpenGL in AE. I can't give you the code for specific things, but this might help you in the general direction.
1. Don't use AE's OpenGL Context. In the GLator example, the plugin uses AE's OpenGL context directly and it can cause many issues. You should always create your own context (Offscreen/Hidden Window/Native GL Context). On the Mac look into CGL Framework for context management. For Windows, the GLator sample already should give you an idea on how to create contexts, but you can use libraries like WGL to ease the pain. Also, having your own context gives you more control over the pixel types and other things.
2. Create and Store Contexts/Textures/Shaders. If you are using multiple contexts or multiple textures and using shaders, its always wise to create them once and re-use them every frame later. I usually create them and store them in the Sequence data. You can always do this globally using global data, instead of Sequence data, but you should be extra careful. If you are using shaders, always compile them at startup, since compiling them every frame takes too much time.
3. Switching Contexts: Since AE already has a context, when it executes the plugin, make sure to switch the GL context to your plugin's context and most importantly switch the context back to AE's default context after you are done rendering, every frame. This is very important, since AE doesn't expect its context to change during rendering process. If you don't do this, severe pain will ensue.
4. Pixel Packing/Unpacking: OpenGL buffers are usually created with RGBA pixel order (depends on what you choose), whereas AE's Effectworld's are in ARGB pixel order. So make sure to convert the Pixel Order approriately while downloading/uploading textures/frame buffers.
These are the few things I can think of right now.
Hope that helps!
Mike, I finally made GLator work. I added a Carbon framework and set the compilation to 32-bit, beacuse Carbon is only 32-bit... I made it work in After Effects CS4 but I want my plugin to work with 64-bit. By the way, gutsbow wrote that there's a better way to use OpenGL in After.
Good luck, Dave
Wow gutsbow, thank you very much for the information!
I'll see how far I can get with that regarding OpenGL, but especially for cross platform (Mac+Win), it might be a bit difficult fo rme yet.
Dave - you mind sharing your working GLator example?
While I've never used the GLator plugin, I've gotten opengl rendering to work in AE. A few thoughts:
1. Like gutsbow says, don't use the AE context. Create a hidden window and use that context.
2. Do *everything* opengl related on one thread. I'd recommend making a background "worker" thread. In theory, opengl is thread safe. In reality, opengl drivers have so many bugs that you're just asking for trouble. So I'd make sure to create/destroy all shaders/textures/buffers/etc on a single thread, and ideally do all opengl calls there.
3. A good percentage of your users won't actually have support for things you need, like FBOs. For example, on windows, the ATI legacy driver doesn't support ANY opengl extensions (at least when I checked).
So make sure you have a CPU backup!
I managed to make opengl work within AE. I'm creating an offset window with nsopenglview, grab all the pixels and add them to the footage. That works ok.
But I have some quetsions about opengl in AE.
1. I have an Edit button to change some opengl shapes.
When I click Edit, AE waits till I change for example the color of the shapes.
After applying the changes I use the following commands in UserChangedParam to force render in AE:
params[slider_rerender_id]->u.sd.value += 1;
params[slider_rerender_id]->uu.change_flags |= PF_ChangeFlag_CHANGED_VALUE;
params[slider_rerender_id]->uu.change_flags |= PF_OutFlag_FORCE_RERENDER;
For this I use this reRender slider:
After these lines of code, AE increments reRender slider's value but nothing changes in the scene. I have to change parameter manually to force render...
Is there any way to force render in AE? I know that AE remembers frames but in that situation I want AE to force render every time I change something in opengl.
2. I don't know why opengl commands tend to crash Premiere. In AE opengl works ok, but in Premiere it crashes or even hangs my Mac every time I load my plugin. Is there any solution for that?
3. Is there a way to put an uneditable/hidden text field within the plugin? I know that there's nothing like textfield parameter. How can I create my textfield parameter or save my text in some of the available parameters?
Thanks for your answer!
1. forcing a re-render.
the PF_OutFlag_FORCE_RERENDER flag goes to the "out_data->out_flags", and not the param UI flags.
having set it there might be the reason that setting PF_ChangeFlag_CHANGED_VALUE doesn't trigger the render.
in any case, you can use setStreamValue() to change your slider's value, which seems to work much better than the "regular" method you're using, and triggers the render with no additional flags needed to be set.
in my humble opinion, you should do just fine with the PF_OutFlag_FORCE_RERENDER flag and you shouldn't have that re-render slider at all.
2. openGL in premier.
i have no idea.
3. text filed.
as you said, there is no text field param.
you can store text either in the sequence_data, or in a param of type "arbitrary", which let's you keep a chunk of memory containing anything you like.
OpenGL in PPro could definitely be it's own forum topic since the original question here was about AE. But one big difference with PPro that you'd need to take into account is the multiple render threads. However, it sounds like the crash you're seeing is when the plug-in is first loaded?
Thank you for your answer shachar.
I still have problems with render in After Effects.
1. When I save a project with my plugin that uses opengl and reopen it, After draws artefacts:
Here is what should be drawn:
It seems like After Effects doesn't call Render function in my plugin when I open the project... I need to change some parameter and then the render is correct for a while.
2. I also noticed artefacts during work with keyframes and parameter changing. It seems that After Effects remembers some old renders setting and doesn't draw correct scene. Am I doing something wrong? Is there any way to force render to draw everything correctly?
Here's linear animation from one point to another. Animation jumps and in the first frame you can see what I mentiond in the first point.
3. Also I use global variables and they seem to be shared between for example 3 plugins which prevent me to use differnt values in every plugin. Again, is that a problem on my side?
Thank you for any help!
Are you sure you are clearing your buffer before drawing? That looks like some memory junk in the FBO. AE does call Render when you open a new project.
Global Variables - Avoid using them, it will get very complicated to find issues as the project gets more complex.
Here's my code concerning drawing:
[[myOpenglView openGLContext] makeCurrentContext];
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[[myOpenglView openGLContext] flushBuffer];
I use offscreen context created in objective-c - I don't think it matters that this is objective-c - it's just NSOpenglView... Maybe I should force switch to AE context somehow but I don't know how to do that... Could you help me with that?
as i mentioned earlier, i have 0 (zero, none, null) experience with openGL, but what you're seeing reminds me of a problem i had with a non-openGL plug-in in AE.
eventually, i found that the problem was that the output buffer AE hands me to fill, was not clean.
(it actually contained my last output... it drove me insane!)
the solution was to clean the output world before i operate on it.
now, i don't know if you copy your openGL buffer into the output world, or if it's done by other means in an openGL plug-in, but i suggest a methodic strip down of the code.
disable the draw_scene() function. are the artifacts still there?
try to gradually disable all the openGL code and see if the artifacts are still there.
you might be surprised to see where the error sprouts.
i know this advice is kind of vague, but in the absence of any other solution... perhaps it's time to brute-force the problem.
Oh my god... The worst problems have the easiest solutions!
After Effects doesn't allow me to use objective-c's double buffer in opengl.
So I changed my render refresh method from:
[[myOpenglView openGLContext] flushBuffer];
and everything works like a charm! AE + opengl rock now.
Two days of pulling hair and finally it works... when I changed one line of code.
Thank you guys for help and all the answers!
Ok, so my plugin started to work very well now but I have one more question.
Here's what I do in my plugin:
When I click the Edit button and make some changes in opengl I update values of my parameters in UserChangedParam function like that:
params[some_parameter_id]->u.fd.value = newValue;
params[some_parameter_id]->uu.change_flags |= PF_ChangeFlag_CHANGED_VALUE;
and everything is applied and renders correctly.
But when I want to do that for example in Render function it does nothing. I noticed that parameters are changed only for 1 render and then they return to their previous values.
Is there any way to change parameters' values from Render function? I only do that on one condition so it's not dangerous ;] I really need that functionality.
you can change param values at any time using SetStreamValue().
but if you do so while rendering, you're actually invalidating the render
the result would be that AE will not cache that frame for ram preview and
will regard it as no yet rendered.
Thank you for your answer! Could you tell me in which library I can find a definition of SetStreamValue()? I can't find ".h" file to include it...
One more question - sorry ;] Is there any way to use some kind of timer or thread that works during plugin's life and when timer/thread for example reads something from a file it forces the render with different values of parameters?
you don't have to include anything out of the ordinary.
AEGP_SetStreamValue() is part of the stream suite.
in some cases it's easier to access params as streams as opposed to
accessing them directly.
OK, I had to add "AE_GeneralPlug.h" to my project and now AEGP_SetStreamValue() is visible fo my compiler.
But... that Stream world is really weird for me at the moment. I don't know if I miss something or my code is incorrect.
Here's what I'm trying to code:
in the header:
static SPBasicSuite *S_sp_basic_suiteP = 0;
in the function (I don't know how to put value in the "val" variable and what to do with new_streamH...):
AEGP_StreamRefH new_streamH = NULL;
My "param_id" is an int slider.
Could you help me with that because it's driving me crazy...
dude! you really messed up the stream thingie!
you start with:
AEGP_GetNewEffectForEffect to get the effectRef for your own effect.
AEGP_GetNewEffectStreamByIndex to get the specific param from the effectRef
by it's index.
now you can access set the value of the stream with the gotten stream ref.
Europe, Middle East and Africa