Hellhound Geschrieben 27. Juli 2017 Melden Share Geschrieben 27. Juli 2017 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 More sharing options...
Sascha Geschrieben 27. Juli 2017 Melden Share Geschrieben 27. Juli 2017 Ist nicht so einfach, einen Fehler zu entdecken, wenn du uns nicht den Code zeigt, in dem der Fehler auftritt, sondern eine ganz andere Version davon Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Hellhound Geschrieben 27. Juli 2017 Autor Melden Share Geschrieben 27. Juli 2017 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 More sharing options...
Zer0Cool Geschrieben 27. Juli 2017 Melden Share Geschrieben 27. Juli 2017 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 More sharing options...
Sascha Geschrieben 27. Juli 2017 Melden Share Geschrieben 27. Juli 2017 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 More sharing options...
Zer0Cool Geschrieben 27. Juli 2017 Melden Share Geschrieben 27. Juli 2017 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 More sharing options...
Hellhound Geschrieben 27. Juli 2017 Autor Melden Share Geschrieben 27. Juli 2017 Wow. Danke für Eure ausführlichen Codebeispiele. Das mit der 2ten Camera klingt plausibel, ich werde meinen Code dementsprechend nachbessern. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 27. Juli 2017 Melden Share Geschrieben 27. Juli 2017 Hah, hab die GetComponent-Zeile vergessen. Clever Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Hellhound Geschrieben 28. Juli 2017 Autor Melden Share Geschrieben 28. Juli 2017 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 More sharing options...
Zer0Cool Geschrieben 28. Juli 2017 Melden Share Geschrieben 28. Juli 2017 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 More sharing options...
Hellhound Geschrieben 28. Juli 2017 Autor Melden Share Geschrieben 28. Juli 2017 Danke für den Hinweis. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 28. Juli 2017 Melden Share Geschrieben 28. Juli 2017 Die Frage ist ja, ob man Render überhaupt braucht. Prinzipiell rendern wir ja sowieso im Renderzyklus, warum also nicht alles so lassen wie es ist? In dem Fall braucht man ja nur noch die RenderTexture zu setzen und diese anzuzeigen. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 28. Juli 2017 Melden Share Geschrieben 28. Juli 2017 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 More sharing options...
Hellhound Geschrieben 28. Juli 2017 Autor Melden Share Geschrieben 28. Juli 2017 Hab es ausprobiert, der Renderer Call wird wirklich nicht benötigt. Danke Euch noch einmal. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Recommended Posts
Archiviert
Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.