프레임 버퍼없이 그래픽 데모를 만들려면 어떻게해야합니까?
저는 마이크로 컨트롤러를 프로그래밍하고 있습니다.-약 100Mhz-300Mhz CPU 클럭 속도와 64K 응용 프로그램 RAM (실제로는 ROM)을 가지고 있지만 RAM (6K)의 양이 적지 만 그래픽 프레임 버퍼에 충분하지 않은 작은 8 비트 컴퓨터입니다.
그래서이 컴퓨터에 애니메이션 그래픽 데모를 표시하고 싶습니다. 어떤 종류의 애니메이션 그래픽을 계산하기에 충분한 컴퓨팅 파워를 가지고있는 것 같습니다.
애니메이션 그래픽을 표시하려면 호출 될 때마다 한 이미지 프레임의 픽셀 한 줄을 반환 한 다음 표시되는 컴퓨터 프로그램이 필요합니다. 디스플레이 컨트롤러 프로그램은 전체 프레임을 표시 할 때까지 한 줄씩 호출하고 다음 프레임에 대해 다시 맨 위에서 시작하여이 작업을 계속합니다.
명확하게 말하면 디스플레이를 제어하는 프로그램에 대해 묻는 것이 아닙니다. 데모 프로그램에 대해 묻고 있습니다. 한 번에 한 줄씩 그래픽을 생성하는 데모 프로그램이 필요합니다. 그러면 디스플레이 컨트롤러가 화면에 표시됩니다.
나는 어떤 종류의 그래픽 프로그램이 이런 식으로 작동 할 수 있는지 상상하려고합니다. 아마도 일종의 수학 공식의 표시 일 것입니다.
누구든지 이러한 방식으로 작동하는 그래픽 프로그래밍 기술을 제안 할 수 있습니까? 즉, 요청이있을 때만 프레임의 한 줄을 계산하고 반환하는 함수를 호출 할 수 있습니까? 이와 같이 작동하는 기존 프로그램이 있는지 검토 할 수 있습니까?
질문이 이해되기를 바랍니다. 올바른 방향이나 힌트에 대한 모든 포인터를 주시면 감사하겠습니다.
답변
이것은 더 복고풍 하드웨어 의 작동을 보는 것이 합리적 인 경우입니다. 오래된 하드웨어는 메모리와 처리 능력 모두에서 강력한 제한을 가졌습니다. 100 + Mhz 칩은 80 년대 이전의 대부분의 소비자 등급 칩보다 훨씬 빠릅니다. 따라서 이러한 CPU는 렌더링 할 수있는 전용 그래픽 칩이 필요했지만 훨씬 빠른 CPU가 작업을 적절하게 처리 할 수 있습니다.
NES의 타일 맵 및 스프라이트 아키텍처와 같은 것으로 시작하는 것이 좋습니다. 이러한 아키텍처는 픽셀 데이터를 생성하고 예상되는 속도로 디스플레이 장치로 직접 전송하므로 메모리 효율적 (제한된 저장 공간에서 많은 것을 얻음)과 라인 별 출력에서 계산적으로 효율적으로 설계되었습니다. CRT.
광범위한 아이디어는 이것입니다. 타일 맵은 두 부분, 즉 일련의 타일과 생성되는 이미지를 나타내는 타일 맵에 대한 인덱스의 2D 배열로 구성됩니다. 타일은 일반적으로 8x8이고 NES에서는 픽셀 당 2 비트이고 타일은 팔레트를 사용했습니다. 또는 더 구체적으로, 타일 맵에 대한 인덱스에는 타일의 인덱스뿐만 아니라 해당 타일과 함께 사용할 팔레트의 인덱스도 포함됩니다. 따라서 타일은 본질적으로 팔레트와 연관되지 않습니다. 연결은 사용 시점에서 이루어집니다 (기술적으로 NES에서는 타일 맵과 팔레트 맵이 분리되어 있습니다. 타일의 각 2x2 블록은 모두 동일한 팔레트를 사용해야했기 때문입니다).
스크롤을 허용하기 위해 타일 맵은 보이는 화면보다 크고, 보이는 화면의 왼쪽 상단 모서리가 타일 맵 내에있는 위치를 나타내는 오프셋이 있습니다. 이 오프셋을 Xoff
및 위치에 둡니다 Yoff
.
이것이 어떻게 행 단위 처리를 사소하게 만드는지 알 수 있습니다. 수평 위치 Ypos
(화면 공간)에 대한 수평 행을 생성하려면 타일 맵 내에서 시작 픽셀을 가져와야합니다. 이를 위해서는 XY 위치 (0, Ypos)
를 화면 공간에서 타일 맵 공간으로 변환해야 합니다. 따라서 (Xoff, Yoff)
벡터``Xoff, Yoff + Ypos)` 를 사용하여 벡터를 추가합니다 .
화면 공간에서 타일 맵 공간으로 매핑을 수행 할 때 타일 맵 공간은 X 축과 Y 축 모두에서 둘러싸여 야합니다. 따라서 타일 맵 공간에서 새 픽셀을 계산할 때마다 타일 맵 공간의 크기를 감싸 야합니다.
이제이 타일 맵 픽셀을 두 개의 2D 구성 요소로 분해해야합니다.이 픽셀을 제공하는 타일 맵 내의 타일 인덱스와이 픽셀에 대해 가져와야하는 해당 타일 내의 픽셀입니다. 타일 인덱스는 타일 크기로 정수 나눈 타일 맵 공간 픽셀입니다. 픽셀 좌표는 정수로 인 tilemap 공간 픽셀입니다 modded하게 타일 크기. 8x8 타일 크기가 주어지면 다음을 수행합니다.
ivec2 tilemap_pixel = ...; //Compute the tilemap starting pixel as above.
ivec2 tilemap_tile = ivec2(tilemap_pixel.x & ~0x7, tilemap_pixel.y & ~0x7); //Mask off the lower 3 bits.
ivec2 pixel_in_tile = ivec2(tilemap_pixel.x & 0x7, tilemap_pixel.y & 0x7); //Mask off all but the lower 3 bits.
따라서 tilemap_tile
, 현재 작업중인 타일의 인덱스가 있습니다. 그리고 pixel_in_tile
우리가 작업중인 픽셀을 제공합니다. 따라서 해당 픽셀의 값을 팔레트에 매핑하여 해당 픽셀의 최종 색상을 생성 할 수있는 해당 픽셀을 가져올 수 있습니다. 또는 직접 사용할 수 있습니다.
다음 픽셀을 얻는 것은 매우 간단합니다. pixel_in_tile.x
타일 크기를 모듈로 1 씩 증가시킵니다 . 증분이 타일 크기를 초과하면 타일 tilemap_tile.x
맵 크기를 모듈로 1 씩 증분 합니다. 그리고 픽셀 행을 채울 때까지 계속 진행합니다.
이러한 알고리즘의 성능 최적화를위한 많은 기회가 있습니다.
타일은 아마도 가장 큰 데이터를 나타냅니다. 2bpp에서도 8x8 타일의 128 요소 타일 세트는 2K입니다. 그러나 문제는 타일 자체를 변경하지 않기 때문에 ROM에 저장할 수 있다는 것입니다. 타일 맵의 크기 (RAM에 있어야한다고 가정)는 원하는 출력 해상도와 타일 크기에 따라 다릅니다. 320x240 화면을 덮을 수있는 8x8 타일의 타일 맵은 1,200 바이트입니다. 정확히 작지는 않습니다. 부드러운 스크롤 (따라서 더 큰 타일 맵)을위한 공간을 원한다면 더 많은 메모리를 차지해야합니다.
즉, "출력 크기"가 디스플레이 장치 의 실제 크기 일 필요는 없다는 점에 유의하는 것도 중요합니다 . 예를 들어 1080p 디스플레이 장치에 그리려는 경우 8 배 더 작은 240x135와 같은 내부 해상도로 렌더링 할 수 있습니다. 이 알고리즘을 수정하여 기본적으로 동일한 픽셀 값을 연속으로 8 번 생성하고 1080p 라인 당 8 번 동일한 라인을 재사용하는 것은 쉽습니다. 실제로이 알고리즘이 하위 픽셀 스크롤 (135p 공간이 아닌 1080p 공간에서 스크롤)을 허용하고 픽셀 값 사이에 일부 필터링을 추가하는 것은 그리 어렵지 않습니다. 240x135 "출력 크기"타일 맵은 가시 영역에 510 바이트 만 필요하므로 더 큰 스크롤 영역을위한 더 많은 공간이 필요합니다.