You definitely have to use the mapStream functionality in Horde, which dynamically uploads the new texture data.
Internally it does use glTexImage2D (replacing the old texture, which seems a bit faster than using glTexSubImage2D).
We use this approach to dynamically upload new textures, and even a decent graphics card will allow an upload of 500MB/sec (e.g. NVIDIA 8600M GT, running Linux in Parallels, so virtualized).
The basic outline is:
Code:
- Use
dynTex = ::h3dCreateTexture("$DYN_TEXTURE", videoWidth, videoHeight, TEX_BGRA8, H3DResFlags::NoTexMipmaps);
to create a new texture - be careful to chose a name which is not yet occupied!
Use TEX_BGRA8 as format - your video needs to be converted in this format or you have to patch the renderer to support BGR only
- Find the material resource you want to apply the video texture to
matRes = ::h3dFindResource(H3DResTypes::Material, matName);
- Find the sampler index within the material
int samplerIndex = h3dFindResElem(matRes, H3DMatRes::SamplerElem, H3DMatRes::SampNameStr, samplerName); // samplerName sth like "albedoMap"
- Apply the dynTex to the material
h3dSetResParamI(matRes, H3DMatRes::SamplerElem, samplerIndex, H3DMatRes::SampTexResI, dynTex);
- You do this only once.
Then after getting a video frame from ffmpeg, upload it to horde (which will upload it to GL)
void *mappedData = h3dMapResStream(dynTex, H3DTexRes::ImageElem, i*countsPerSlice+mip, H3DTexRes::ImgPixelStream, false, true );
// (i, countsPerSlice and mip are only relevant if you have a mipmapped and/or cube texture, otherwise just set it to 0)
// copy image data over to horde's internal buffer
memcpy(mappedData, ffmpegVideoFrame, textureSize); // with texture size being videoWidth*videoHeight*4 in case of BGRA8
// tell horde to upload data to GL
h3dUnmapResStream(dynTex);
Hope this gets you going.
In our case a PBO approach wasn't really worth it. One could also avoid the memcpy, if horde accepts a raw memory pointer, but this might only work for OpenGL.
Alex