sevas55 Posted October 30, 2025 Posted October 30, 2025 (edited) Подскажите как правильно сохранить текстуру в список? Столкнулся с тем, что в список помещается одна и та же текстура, хотя она точно изменяется, проверил сохранением в файл, полученные текстуры 100% разные, а при обращении к текстуре из списка - во всех элементах списках почемуто одинаковая. Код примерно такой. Часть отбросил для упрощения функция RenderTexture взят из примера gui to texture List<Texture> TextureList = new List<Texture>();// List<WidgetSprite> SpriteList = new List<WidgetSprite>(); void Init() { //иницииализация списка текстур на всякий случай for (int i = 0; i < SpritesCount; i++) { SpriteList.Add(new WidgetSprite()); TextureList.Add(new Texture()); } } void Update() { Texture tex; //рендерим текстуру, 100% работает, взято из примеров tex = RenderToTexture();//полный код для упрощения не привожу //кидаем текстуру в список и ограничиваем до нужного количества TextureList.Add(tex); if (TextureList.Count > SpritesCount) TextureList.RemoveAt(0); //рисуем спрайт со смещением и назначаем ей текстуру из списка for (int i = 0; i < SpriteList.Count; i++) { SpriteList[i].SetRender(TextureList[i]); SpriteList[i].PositionY = i * LinesHorizontal; } } В итоге получаю вот такое, во всех спрайтах одна и таже текстура, хотя по коду явно прохожусь по всему списку. А список, соответственно, должен сохранять предыдущие текстуры Нагуглить особо ничего не получилось, в основном ссылки на код юнити выдаются. Может просто так в список нельзя добавлять текстуру, а надо както её копировать? спасибо! Edited October 30, 2025 by sevas55
alexander Posted October 30, 2025 Posted October 30, 2025 День добрый. Судя по коду выглядит так, что RenderToTexture() всегда возвращает ссылку на одну и ту же текстуру. TextureList в результате заполняется одной и той же текстурой, что мы и видим в итоге. Тут надо смотреть, что происходит внутри RenderToTexture(). Если там нет явного вызова new Texture() внутри, то, получается, одна и та же текстура просто переиспользуется (очищается, затем заполняется). Лучше переписать этот метод на что-то вроде: RenderToTexture(TextureList[index]);
sevas55 Posted October 30, 2025 Author Posted October 30, 2025 Вот код функции, взял как есть из примера, только добавил ей возврат текстуры Texture RenderToTexture() { // Render gui onto texture // Save render state and put it at the top of the stack // To pop current settings, we will need to call RenderState.RestoreState() at the and of this method RenderState.SaveState(); // Now we clear state, so that our rendered texture won't be affected by other render activities RenderState.ClearStates(); // Set viewport size matching texture resolution RenderState.SetViewport(0, 0, TextureSize.x, TextureSize.y); // Now we bind gui texture to slot 0, because gui renders in slot 0 renderTarget.BindColorTexture(0, TextureRender); // Enable render target renderTarget.Enable(); // Clear texture and fill it with black color RenderState.ClearBuffer(RenderState.BUFFER_COLOR, vec4.BLACK); // Now we need to perform the whole gui render loop // Enable gui so that it will be updated and rendered guiRender.Enable(); // Update all widgets guiRender.Update(); // Render gui guiRender.PreRender(); guiRender.Render(); // Disable gui guiRender.Disable(); // Now we need to free render target and unbind texture renderTarget.Disable(); renderTarget.UnbindColorTexture(0); // Create texture mipmaps (set of textures of different resolutions to ensure correct rendering at longer distances) // TextureRender.CreateMipmaps(); // Pop render state from top of the stack to let render pipeline continue as usual RenderState.RestoreState(); //вовд в png файл // Render.AsyncTransferTextureToImage( // null, // (Image image) => // { // if (!Render.IsFlipped) // image.FlipY(); // string timenow = System.DateTime.Now.ToString("yyyyMMdd-HHmmss.sss"); // string fullName = "WIP/" + $"{timenow}.png"; // image.Save(fullName); // Unigine.Console.OnscreenMessageLine(vec4.GREEN, $"{fullName} saved."); // }, // TextureRender); return TextureRender; }
sevas55 Posted October 30, 2025 Author Posted October 30, 2025 О, кажется понял как надо в Update так Texture tex = new Texture(); tex.Create2D(TextureSize.x, TextureSize.y, Texture.FORMAT_RGBA8, Texture.FORMAT_USAGE_RENDER); // tex = RenderToTexture(); RenderToTexture2(ref tex); а функция так Texture RenderToTexture2(ref Texture texture2) { // Render gui onto texture // Save render state and put it at the top of the stack // To pop current settings, we will need to call RenderState.RestoreState() at the and of this method RenderState.SaveState(); // Now we clear state, so that our rendered texture won't be affected by other render activities RenderState.ClearStates();
sevas55 Posted October 30, 2025 Author Posted October 30, 2025 Да, все работает, нужно именно создавать новую new Texture и ее кидать в список, спасибо! 1
alexander Posted October 30, 2025 Posted October 30, 2025 Отлично! На будущее: если производительность со временем станет не устраивать, то имеет смысл заглянуть сюда снова. Создавать текстуры прям в Update - это относительно долгий процесс. Лучше нужное количество в Init()'е сделать, а в Update() просто переиспользовать их. Лучше перетасовывать позицию WidgetSprite'ов, чем переназначать рендер в каждом из них. 1
sevas55 Posted October 30, 2025 Author Posted October 30, 2025 По сравнению с тем что было, когда всё поле канвы эхолота рисовалась полностью процом, то сейчас поле рисуется узкими полосками уже видеокартой, производительность на порядки возросла. Раньше мне приходилось на один борт делать не больше 30 лучей до просадки фпс, сейчас спокойно могу 300 сделать без просадки. Спасибо за решения!
Recommended Posts