Again, OptiX is a general purpose ray casting SDK. It allows to implement pretty much any algorithm which requires to shoot rays, and as such you can also define arbitrary methods to light your scene.
The OptiX SDK examples also use light sources made from parallelograms (for example inside the path_tracer sample), and it is of course also possible to implement lights with other shapes like spheres or even arbitrary triangle meshes.
It’s always the same mechanism, you need a function to explicitly sample a point, emission (radiance, flux, etc.), and its probability density function value on the light source for direct lighting, and a function to return the emission when it’s hit by a ray (aka. implicit light sampling).
You should be able to find more information on things like these inside standard ray tracing literature and the internet.
In OptiX I implement the explicit light sampling function as callable program so that when multiple closest hit programs use that, they don’t duplicate the code.
The implicit light sampling is done inside the closest hit programs attached to the material assigned to the different light types.
If you approximate your flame volume by a mesh geometry and the appropriate emission on its surface, you would need to have the mesh geometry information available inside both of the light’s sampling functions.
You can do that in OptiX by using bindless buffers. Your light definition structure would need to contain the bindless buffer IDs of the mesh geometry (and indices if needed) to be able to access the mesh vertices for sampling. Bindless buffer IDs are explained inside the OptiX Programming Guide.
Be careful to either specify lights in world coordinates (recommended) or to add the necessary transformations in your light sampling functions when required.
Note that proper light sampling is already a slightly advanced topic which requires solid understanding of Monte Carlo methods for global illumination algorithms.