OpenGL: копировать текстуру в основную память

Для проекта в Unity я прибегаю к написанию собственного (C ++) плагина, в котором моей целью является получение данных текстуры в основную системную память. Я знаю, что Unity предоставляет аналогичную функцию для достижения этой цели (Texture2D.GetRawTextureData()). К сожалению, побочным эффектом вызова этой функции является то, что она выделяет большой кусок памяти при каждом вызове, и я запускаю этот вызов каждый кадр, который довольно часто запускает сборку мусора (читай: каждый кадр)

Поэтому я пытаюсь написать аналогичную функцию, которая использует предварительно выделенный буфер, передать адрес буфера плагину C ++ и скопировать в него данные текстуры. Однако все данные текстуры возвращаются черными (поэтому все значения равны 0). Что я делаю неправильно или что я забыл принять во внимание при получении этих данных?

Код в Unity (C #), вызывающий плагин, выглядит следующим образом:

private Texture2D tempTexture = null;
private byte[] textureBuffer = null;
private IntPtr textureHandle;

public void StartStream(StreamerOptions options)
{
...
tempTexture = new Texture2D(options.width, options.height, TextureFormat.RGBA32, false);
textureBuffer = new byte[options.width * options.height * 4];
textureHandle = tempTexture.GetNativeTexturePtr();
...
}

private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (IsStreaming)
{
Graphics.Blit(source, destination, material, 0);
tempTexture.ReadPixels(new Rect(0, 0, attachedCamera.targetTexture.width, attachedCamera.targetTexture.height), 0, 0, false);
tempTexture.Apply();
}
}

private void OnPostRender()
{
if (IsStreaming)
{
FetchTexture(textureHandle, textureBuffer);
pipe.Write(textureBuffer);
// pipe.Write(tempTexture.GetRawTextureData());
}
}

В функции OnPostRender Я вызываю плагин для получения данных текстуры. Код C ++, извлекающий OpenGL, выглядит следующим образом:

void RenderAPI_OpenGLCoreES::FetchTextureData(void *textureHandle, uint8_t *textureData)
{
GLuint glTextureName = static_cast<GLuint>(reinterpret_cast<intptr_t>(textureHandle));
glBindTexture(GL_TEXTURE_2D, glTextureName);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_BYTE, textureData);
}

0

Решение

Отвечая на мой собственный вопрос, воспользовавшись решением, найденным в ответах Unity:
https://answers.unity.com/questions/1305191/glreadpixels-from-a-rendertexture.html

Я использовал пример единого проекта родного плагина в качестве основы и начал отбрасывать ненужную мне функциональность.

Самой важной частью этого была инициализация подсистемы GLEW.

glewExperimental = GL_TRUE;
glewInit();
glGetError(); // Clean up error generated by glewInit

После этого я мог начать читать данные текстуры, используя код в связанном ответе:

void RenderAPI_OpenGLCoreES::ReadPixels(void *data, int textureWidth, int textureHeight)
{
int currentFBORead;
int currentFBOWrite;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &currentFBORead);
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &currentFBOWrite);

glBindFramebuffer(GL_READ_FRAMEBUFFER, currentFBOWrite);
glReadPixels(0, 0, textureWidth, textureHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);
glBindFramebuffer(GL_READ_FRAMEBUFFER, currentFBORead);
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]