Jump to content

[SOLVED] Как сохранить Texture в List?


photo

Recommended Posts

Posted (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 by sevas55
Posted

День добрый.

Судя по коду выглядит так, что RenderToTexture() всегда возвращает ссылку на одну и ту же текстуру. TextureList в результате заполняется одной и той же текстурой, что мы и видим в итоге. Тут надо смотреть, что происходит внутри RenderToTexture(). Если там нет явного вызова new Texture() внутри, то, получается, одна и та же текстура просто переиспользуется (очищается, затем заполняется).

Лучше переписать этот метод на что-то вроде: RenderToTexture(TextureList[index]);

Posted

Вот код функции, взял как есть из примера, только добавил ей возврат текстуры

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;
	}

 

Posted

О, кажется  понял как надо

 

в 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();

 

Posted

Да, все работает, нужно именно создавать новую new Texture и ее кидать в список, спасибо!

image.thumb.png.4665bfa56a48443abc1621b0c1f2bef8.png

  • Like 1
Posted

Отлично!

На будущее: если производительность со временем станет не устраивать, то имеет смысл заглянуть сюда снова. Создавать текстуры прям в Update - это относительно долгий процесс. Лучше нужное количество в Init()'е сделать, а в Update() просто переиспользовать их. Лучше перетасовывать позицию WidgetSprite'ов, чем переназначать рендер в каждом из них.

 

  • Like 1
Posted

По сравнению с тем что было, когда всё поле канвы эхолота рисовалась полностью процом, то сейчас поле рисуется узкими полосками уже видеокартой, производительность на порядки возросла. Раньше мне приходилось на один борт делать не больше 30 лучей до просадки фпс, сейчас спокойно могу 300 сделать без просадки.

Спасибо за решения!

  • silent changed the title to [SOLVED] Как сохранить Texture в List?
×
×
  • Create New...