일단 가상 모니터 추가하는 방법 찾아봤는데

 

아래 링크에서

amyuni 소개해줘서 보고 따라해봄

 

https://quasarzone.com/bbs/qf_sw/views/50718

 

모니터 없이 디스플레이 확장 방법 없을까요?

윈도우7쓸대는 디스플레이 확장 메뉴에서 모니터 없어도 감지눌러서 추가하는게 가능했는데지금 윈도우10 최신버전…

quasarzone.com

 

 

 

설명 글대로

 

 

 

압축 풀고 

cmd 관리자 권한으로 deviceinstaller64.exe install usbmmidd.inf usbmmidd로 드라이버 설치후

deviceinstaller64 enableidd 1을 여러번 하면 가상 모니터가 여러번 추가된다

deviceinstaller64 enableidd 0을 하면 가상모니터가 사라지고

 

 

 

 

 

 

듀얼 모니터(1, 2)를 사용 중인데

가상 모니터(3, 4)를 이렇게 배치시켰다.

 

 

1, 3, 4 모니터 3개를 인게임에 띄우고, 보조보니터 2에는 언리얼로 실행시키기 위함

 

 

가상 모니터는 준비되었고, 언리얼 엔진 실행하고 커서로 다른걸 누르면 화면이 급 느려지는데

찾아보니 에디터 프리퍼런스에서 Use less cpu when in background option이 체크된걸 해제해주면 된다더라

 

 

https://forums.unrealengine.com/t/keeping-editor-running-as-normal-when-not-in-focus/367988

 

Keeping editor running as normal when not in focus

Hey guys, how do you keep a game running as normal when the editor is not in focus? I want to test my multiplayer with two editors open (I know you can have two instances on one editor but I need to run two editors for authentication purposes) but one edit

forums.unrealengine.com

 

 

체크 해재해주면 실행중 다른걸 눌러도 속도가 느려지지않는다.

 

 

 

그리고 계속 텍스처 스트리밍 풀 예산 초과 경고가 뜨는데

 

 

아래 링크대로 해결되지 않는다.

 

https://3dperson1.tistory.com/44

 

언리얼 텍스처 스트리밍 풀이 예산을 초과했습니다 해결 방법

안녕하세요 오랜만입니다. 요즘 언리얼만 공부를 하고 있다보니, 미드저니나 챗지피티 등등에 대해 예전만큼 시간을 쏟지 못하고 있습니다. 거두절미하고 언리얼 텍스쳐 스트리밍 풀이 예산을

3dperson1.tistory.com

 

 

 

 

 

 

 

 

작업 관리자로 보니 메모리가 가득 찼다가 non streaming mips가 해제되면서 내려갔다, 다시 올라갓다를 반복하는듯하다.

생성한 utexture2d들이 제때 제거안되서 그런듯.

 

 

 

 

 

 

 

 

생각해보니 HBITMAP 을 cvMat으로 만드는 코드에서

디바이스 콘텍스트와 비트맵을 해제안시켰었다. 수정

 

cv::Mat ADesktopGameModeBase::GetScreenToCVMat()
{
	HDC hScreenDC = GetDC(NULL);
	HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
	int screenWidth = GetDeviceCaps(hScreenDC, HORZRES);
	int screenHeight = GetDeviceCaps(hScreenDC, VERTRES);

	HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, screenWidth, screenHeight);
	HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
	BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight, hScreenDC, 0, 0, SRCCOPY);
	SelectObject(hMemoryDC, hOldBitmap);

	cv::Mat matImage(screenHeight, screenWidth, CV_8UC4);
	GetBitmapBits(hBitmap, matImage.total() * matImage.elemSize(), matImage.data);

	DeleteDC(hScreenDC);
	DeleteDC(hMemoryDC);

	DeleteObject(hBitmap);
	DeleteObject(hOldBitmap);


	return matImage;
}

 

 

 

 

DC와 비트맵을 cv::Mat 생성 후 해제시켜주니 액세스 위반으로 꺼지는건 해결됬는데

여전히 Non Streaming Pool이 가득차다 풀렸다 반복하는건 여전하다.

 

 

 

 

이미지 텍스처를 제때 해재안해준게 문젠거같아서 

전역 변수로 뺀뒤 중간에 해재하도록 수정

 

void ADesktopGameModeBase::ReadFrame()
{
	/*
	if (!capture.isOpened())
	{
		return;
	}
	capture.read(image);
	*/

	cv::Mat desktopImage = GetScreenToCVMat();
	MatToTexture2D(desktopImage);
}


void ADesktopGameModeBase::MatToTexture2D(const cv::Mat InMat)
{
	imageTexture->ReleaseResource();
	//create new texture, set its values
	imageTexture = UTexture2D::CreateTransient(InMat.cols, InMat.rows, PF_B8G8R8A8);
	if (InMat.type() == CV_8UC3)//example for pre-conversion of Mat
	{
		cv::Mat bgraImage;
		//if the Mat is in BGR space, convert it to BGRA. There is no three channel texture in UE (at least with eight bit)
		cv::cvtColor(InMat, bgraImage, cv::COLOR_BGR2BGRA);

		//Texture->SRGB = 0;//set to 0 if Mat is not in srgb (which is likely when coming from a webcam)
		//other settings of the texture can also be changed here
		//Texture->UpdateResource();

		//actually copy the data to the new texture
		FTexture2DMipMap& Mip = imageTexture->GetPlatformData()->Mips[0];
		void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);//lock the texture data
		FMemory::Memcpy(Data, bgraImage.data, bgraImage.total() * bgraImage.elemSize());//copy the data
		Mip.BulkData.Unlock();
		imageTexture->PostEditChange();
		imageTexture->UpdateResource();
	}
	else if (InMat.type() == CV_8UC4)
	{
		//actually copy the data to the new texture
		FTexture2DMipMap& Mip = imageTexture->GetPlatformData()->Mips[0];
		void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);//lock the texture data
		FMemory::Memcpy(Data, InMat.data, InMat.total() * InMat.elemSize());//copy the data
		Mip.BulkData.Unlock();
		imageTexture->PostEditChange();
		imageTexture->UpdateResource();
	}
	//if the texture hasnt the right pixel format, abort.
	imageTexture->PostEditChange();
	imageTexture->UpdateResource();
}

 

 

 

public:
	cv::VideoCapture capture;
	cv::Mat image;

	UFUNCTION(BlueprintCallable)
	void ReadFrame();

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UTexture2D* imageTexture;
	void MatToTexture2D(const cv::Mat InMat);


	cv::Mat GetScreenToCVMat();
};

 

이랬더니 release Resouce한후에 CreateTransient해서 그런지 또 액세스 위반 크래시 예외발생

 

 

 

 

 

beginPlay에서 imageTexture를 한번 초기화해주고 

mat to texture2d에서 cvmat -> texture 변환 후 imaget texture에 복사하기만 했더니

스트리밍 풀 문제는 해결됬는데

 

void ADesktopGameModeBase::BeginPlay()
{
	Super::BeginPlay();

	capture = cv::VideoCapture(0);

	if (!capture.isOpened())
	{
		UE_LOG(LogTemp, Log, TEXT("Open Webcam failed"));
		return;
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Open Webcam Success"));
	}
	imageTexture = UTexture2D::CreateTransient(1080, 1920, PF_B8G8R8A8);
}


void ADesktopGameModeBase::ReadFrame()
{
	/*
	if (!capture.isOpened())
	{
		return;
	}
	capture.read(image);
	*/

	cv::Mat desktopImage = GetScreenToCVMat();
	MatToTexture2D(desktopImage);
}


void ADesktopGameModeBase::MatToTexture2D(const cv::Mat InMat)
{
	if (InMat.type() == CV_8UC3)//example for pre-conversion of Mat
	{
		cv::Mat bgraImage;
		//if the Mat is in BGR space, convert it to BGRA. There is no three channel texture in UE (at least with eight bit)
		cv::cvtColor(InMat, bgraImage, cv::COLOR_BGR2BGRA);

		//Texture->SRGB = 0;//set to 0 if Mat is not in srgb (which is likely when coming from a webcam)
		//other settings of the texture can also be changed here
		//Texture->UpdateResource();

		//actually copy the data to the new texture
		FTexture2DMipMap& Mip = imageTexture->GetPlatformData()->Mips[0];
		void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);//lock the texture data
		FMemory::Memcpy(Data, bgraImage.data, bgraImage.total() * bgraImage.elemSize());//copy the data
		Mip.BulkData.Unlock();
		imageTexture->PostEditChange();
		imageTexture->UpdateResource();
	}
	else if (InMat.type() == CV_8UC4)
	{
		//actually copy the data to the new texture
		FTexture2DMipMap& Mip = imageTexture->GetPlatformData()->Mips[0];
		void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);//lock the texture data
		FMemory::Memcpy(Data, InMat.data, InMat.total() * InMat.elemSize());//copy the data
		Mip.BulkData.Unlock();
		imageTexture->PostEditChange();
		imageTexture->UpdateResource();
	}
	//if the texture hasnt the right pixel format, abort.
	imageTexture->PostEditChange();
	imageTexture->UpdateResource();
}

 

 

 

nonstreamingpool 가득안차는건 좋은데 

imagetexture에 복붙되는게 쌓여서 그런가 겹친듯한 화면이나온다.

 

 

 

인줄 알았는데 

 

createTransient에서 row와 col을 모르고 반대로 적었더라.

원래 순서대로 1920 x 1080 해주면 

void ADesktopGameModeBase::BeginPlay()
{
	Super::BeginPlay();

	capture = cv::VideoCapture(0);

	if (!capture.isOpened())
	{
		UE_LOG(LogTemp, Log, TEXT("Open Webcam failed"));
		return;
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Open Webcam Success"));
	}
	imageTexture = UTexture2D::CreateTransient(1920, 1080, PF_B8G8R8A8);
}

 

 

 

액세스 위반도 없고, 스트리밍 풀 문제도 해결

 

+ Recent posts