2016-09-13 1 views
0

Je tente de dessiner un RenderTexture dans un Texture2D dans le but de l'enregistrer sur le disque. Cette approche a fonctionné dans l'éditeur OSX, ainsi que sur Android.iOS se bloque lors de l'appel Texture2D.readPixels

Je ne vois pas d'erreur dans la console XCode, et mon application devient complètement gelé quand je l'appelle Texture2D.ReadPixels()

Voici un résumé du code:

// declaring variables... 
    RenderTexture outputTexture; 
    RenderTextureFormat RTFormat = RenderTextureFormat.ARGB32; 

    // use an appropriate format for render textures 
    if(SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBFloat)){ 
     RTFormat = RenderTextureFormat.ARGBFloat; 
    }else if(SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)){ 
     RTFormat = RenderTextureFormat.ARGBHalf; 
    } 

    // create instance of output texture 
    outputTexture = new RenderTexture (res.x, res.y, 0, RTFormat); 

    // in Update, draw stuff to outputTexture 
    Graphics.Blit (outputTexture, canvasTexture); 
    Graphics.Blit (canvasTexture, outputTexture, material); 

    // later... user wants to save the image 
    // draw rendertexture to a Texture2D so we can write to disk 
    RenderTexture.active = outputTexture; 
    tmpTexture = new Texture2D (outputTexture.width, outputTexture.height, TextureFormat.ARGB32, false); 
    tmpTexture.ReadPixels (new Rect (0, 0, outputTexture.width, outputTexture.height), 0, 0, false); 
    tmpTexture.Apply(); 
    RenderTexture.active = null; 

J'ai essayé d'utiliser une variété de RenderTextureFormat et TextureFormat, mais rien ne semble fonctionner!

+0

Où appelez-vous ce code? Est-ce dans une fonction personnalisée ou une méthode Unity Callback? –

+0

En outre, sur quel appareil testez-vous? Vérifiez si vous manquez de mémoire. RenderTexture est une méthode coûteuse. –

Répondre

1

Je crois que ceci est provoqué par votre appel de format de texture de rendu. Quelque chose de similaire s'est passé avant.

Ce morceau de code attribue un format de texture par défaut, modifie ensuite le format par défaut si l'environnement en cours d'exécution supporte (mes commentaires sont ajoutés)

//set a default render texture of RenderTextureFormat.ARGB32; 
RenderTextureFormat RTFormat = RenderTextureFormat.ARGB32; 

// if my system supports it, switch to either ARGBFloat or ARGBHalf 

// use an appropriate format for render textures 
if(SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBFloat)){ 
    RTFormat = RenderTextureFormat.ARGBFloat; 
}else if(SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)){ 
    RTFormat = RenderTextureFormat.ARGBHalf; 
} 

Toutefois, lorsque vous réellement définir plus tard votre texture de température à remplir avec readPixels(), vous définissez seulement d'une façon (encore une fois, mes commentaires ajoutés)

//define a new tmpTexture container, ALWAYS with a TextureFormat of ARGB32 
tmpTexture = new Texture2D (outputTexture.width, outputTexture.height, TextureFormat.ARGB32, false); 

Ainsi sur certains systèmes (selon supporte le format), vous essayez de readPixels() d'un format de texture en un autre. Ceci est probablement à l'origine de votre problème.

Vous pouvez résoudre ce problème en modifiant également dynamiquement le format de la texture de destination. Ainsi, dans la première section, vous changeriez à:

RenderTextureFormat RTFormat = RenderTextureFormat.ARGB32; 

//add another variable here for the destination Texture format 
var destinationFormat = TextureFormat.ARGB32; 


// use an appropriate format for render textures 
if(SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBFloat)){ 
    RTFormat = RenderTextureFormat.ARGBFloat; 

    //also set destination format 
    destinationFormat = TextureFormat.RGBAFloat; 
}else if(SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)){ 
    RTFormat = RenderTextureFormat.ARGBHalf; 

    //also set destination format 
    destinationFormat = TextureFormat.RGBAHalf; 
} 

puis bien sûr, consommer plus tard, le format défini dynamiquement lors de la déclaration de l'objet de destination:

//define a new tmpTexture container, with a dynamically set destination format that always matches the input texture 
tmpTexture = new Texture2D (outputTexture.width, outputTexture.height, destinationFormat, false); 

Faites-moi savoir si vous avez encore problèmes dans les commentaires.

+0

Wow, merci pour un article si détaillé. Mon problème a fini par être super simple, et vous m'avez aidé à le voir. J'avais essayé de placer le destinationFormat à TextureFormat.RGFloat! Je suis vraiment déconcerté de savoir qu'il fonctionnait sur Android, malgré cette erreur flagrante. Je vais soumettre une modification à votre réponse, par souci d'exactitude et de postérité. –

+0

Désolé, j'ai accepté votre réponse à titre préventif. Je l'ai fait fonctionner une fois, mais la reconstruction avec le même code a échoué à nouveau. –

+0

Même chose, rien dans la sortie XCode? Et fonctionne encore sur Android? – HBomb