Jump to content
Unity Insider Forum

Probleme mit RenderTexture im Editor


Hellhound

Recommended Posts

Hallo,

irgendwie hab ich grad ein Problem mit dem Rendern der Kamera in eine Textur i.Z.m. dem EditorWindow was ich nicht so ganz verstehe. Das ganze funktioniert hervorragend wenn ich folgenden Aufruf in der OnGUI-Methode mache:

if(this.mainCamera!=null){
  this.mainCamera.targetTexture = new RenderTexture(512, 512, 24, RenderTextureFormat.ARGB32);  
  this.mainCamera.Render();
  GUI.DrawTexture(new Rect(0, 100, position.width, position.height), this.mainCamera.targetTexture); 
}

Nun fand ich es nicht optimal bei jedem OnGUI Aufruf die RenderTexture neu zu instanziieren. Daher habe ich diese als Member angelegt und in der Awake() Methode instanziiert und setze sie beim instanziieren der Kamera als RenderTarget. Was ich jetzt nicht verstehe, ist das ich nun ständig das Warning bekomme die RTT währe null und daher das GUI.DrawTexture auch nicht greift. Wenn die Textur null ist verliert natürlich auch konsequenterweise die Camera die Referenz auf ihr RenderTarget.

Nur warum wird die Textur in jedem RenderCall null?? Kann mir das jemand erklären?

Gruß

Hellhound

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ok, hier mal der Code, der soweit identisch ist, bis auf die Auslagerung der RTT als Member:

private Camera mainCamera;
private RenderTexture mainPreview;

void Awake(){
	this.mainPreview = new RenderTexture(512, 512, 24, RenderTextureFormat.ARGB32); 
}

void OnGUI(){
	if(this.mainCamera!=null){
			this.mainCamera.targetTexture = this.mainPreview;  
            this.mainCamera.Render();
            GUI.DrawTexture(new Rect(0, 100, position.width, position.height), this.mainCamera.targetTexture); 
			//GUI.DrawTexture(new Rect(0, 100, position.width, position.height), this.mainPreview); 
	}
}

An dieser Stelle erhalte ich immer die Fehlermeldung, das die Textur, die an die GUI übergeben wird null ist. Sonst ist alles im Code identisch.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe es mal getestet, funktioniert bei mir ohne Probleme. Was mich an deinem Code stört ist, daß du scheinbar die Mainkamera verwendest. Bei der Funktion "Render()" wird ausdrücklich erwähnt, daß man nicht die Mainkamera verwenden soll, sondern eine 2. Kamera. Ich habe den Code mal dahingehend geändert:

using UnityEngine;
using System.Collections;

public class RenderTextureTest : MonoBehaviour {

    public Camera renderCam;
    private RenderTexture mainPreview;

    void Awake()
    {
        this.mainPreview = new RenderTexture(512, 512, 24, RenderTextureFormat.ARGB32);
        renderCam.CopyFrom(Camera.main);
        this.renderCam.targetTexture = this.mainPreview;
    }

   void OnPreRender()
    {
      	this.renderCam.Render();
    }

    void OnGUI()
    {
       GUI.DrawTexture(new Rect(0, 100, 400, 400), this.renderCam.targetTexture);
    }
}

PS:
Für das gleiche Ergebnis. würde ich ansonsten immer eine 2. Kamera komplett ohne dieses Skript und dem Setzen des Viewports bei der 2. Kamera dieser Methode vorziehen, da ich vermute, daß eine 2. Kamera die in einen Viewport rendert immer schneller ist, als ein Renderaufruf innerhalb der OnGUI-Methode (zumal mir auch nicht ganz wohl dabei ist, jedes Frame auf das Renderergebnis der 2. Kamera zu warten).

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mir fällt gerade auf, dass man das vielleicht echt nicht in OnGUI machen sollte. Schließlich sollte sich sowieso nichts geändert haben zwischen zwei Updates, also warum Render() in einem anderen Zyklus als Update ausführen? Außerdem muss die targetTexture nicht ständig neu zugewiesen werden. Also wieder abgeändert:

using UnityEngine;

[RequireComponent(typeof(Camera))]
public class RenderTextureTest : MonoBehaviour
{
    private Camera renderCam;
    private RenderTexture mainPreview;

    void Awake()
    {
        mainPreview = new RenderTexture(512, 512, 24, RenderTextureFormat.ARGB32);
        renderCam.CopyFrom(Camera.main);
        renderCam.targetTexture = this.mainPreview;
    }
    
    void OnPreRender()
    {
      	this.renderCam.Render();
    }
  
    void OnGUI()
    {
       GUI.DrawTexture(new Rect(0, 100, 400, 400), this.renderCam.targetTexture);
    }
}

Hab mal OnPreRender genommen, weiß nicht ob das optimal ist. Dazu muss das Skript jedenfalls direkt auf der Kamera liegen, darum RequireComponent.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja das stimmt Sascha, OnGUI wird ja mehrfach aufgerufen, ich hab mein Skript auch mal dementsprechend angepasst. Bei dem Skript von mir muss die Renderkamera über das Skript übergeben werden, sonst gibt es ein NPE. Ansonsten macht es nun am meisten Sinn dieses Skript an die Renderkamera zu hängen (dann könnte man sich die Renderkamera auch vom GO selbst holen):

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Camera))]
 /// <summary>
 /// Skript für eine 2. Kamera, um einen Auschnitt der aktuellen Szene in einer GUI-Textur abzubilden.
 /// </summary>
public class RenderTextureTest : MonoBehaviour {

    private Camera renderCam; 
    private RenderTexture mainPreview;

    void Awake()
    {
        renderCam = GetComponent<Camera>();
        this.mainPreview = new RenderTexture(512, 512, 24, RenderTextureFormat.ARGB32);
        renderCam.CopyFrom(Camera.main);
        renderCam.targetTexture = this.mainPreview;
    }

    void OnPreRender()
    {
        renderCam.Render();
    }

    void OnGUI()
    {
         GUI.DrawTexture(new Rect(0, 100, 400, 400), renderCam.targetTexture);
    }
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe Euren Code einmal ausprobiert, klappt soweit hervorragend für eine normale Scene. Da ich allerdings ein EditorWindow baue und hier keine Laufzeitumgebung habe konnte ich das ganze so nicht anwenden und OnPrerender kann dann nicht verwendet werden. Habe Aber Eure Mechanismen genutzt und initialisiere nun die Cameras in einer separaten Methode die ich beim Laden des Modells einmal explizit ausführe:

private void InitPreviewScene()
{
	// initialize a new empty scene for the model
	previewScene =  EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
			
	// create main camera
	var goCamera = new GameObject("Main Camera");
	mainCamera = goCamera.AddComponent<Camera>();
			
	mainCamera.transform.position = new Vector3(0,0,-1.8f);			
	mainCamera.transform.RotateAround(model.transform.position, Vector3.down, 25f);
	mainCamera.transform.RotateAround(model.transform.position, Vector3.left, 2f);
						
	// initalize render to texture for preview
	this.previewTexture = new RenderTexture(512, 512, 24, RenderTextureFormat.ARGB32); 
						
	// create 2nd camera for preview
	var goPVCamera = new GameObject("Preview Camera");
	previewCamera = goPVCamera.AddComponent<Camera>();
			
	previewCamera.CopyFrom(mainCamera);
	previewCamera.targetTexture = this.weaponPreviewTexture;	
						
	// create a directional light
	var goLight = new GameObject("Directional Light");
	var light = 	goLight.AddComponent<Light>();
	light.type = LightType.Directional;
	light.transform.position = new Vector3(0,0,-80f);		
			
	//finaly make scene active
	EditorSceneManager.SetActiveScene(previewScene); 	
}

Klappt soweit sehr gut. Die Preview-Kamera wird nun in Update gerendert und in OnGUI wird die PreviewTexture im Editor plaziert. Danke Euch noch Einmal! Denke das passt soweit oder seht Ihr da noch ein Problem?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Sollte passen, allerdings hatte ich mir noch überlegt, daß die Kamera die Szene vermutlich immer noch 2x rendert und in der Doku nachgeschaut und siehe da dort steht, man sollte die Renderkamera deaktivieren (disable), wenn man Render() verwendet. Ansonsten rendert sie die Rendertexture auch in ihrem "normalen Renderzyklus".

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja, wäre auch der sauberste Weg (dann die Kamera aber wieder aktivieren) und die Textur sollte sogar bereits vorhanden sein bevor das 1. Mal OnGUI aufgerufen wird (siehe "Execution Order of Event Functions")
Ich denke "Render()" zu verwenden macht Sinn, wenn man die Rendertexture nicht in jedem Frame rendert, sondern beispielsweise nur dann wenn der Anwender einen Button drückt oder ähnliches.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...