Fundamentalmente, como os bitmaps 2D são renderizados?


9

Suponha que tenhamos um computador endereçável por palavras de 64 bits e desejamos programá-lo para gerar um caractere 5x7 armazenado como um bitmap de imagem binária (como o abaixo) para uma exibição mapeada na memória.

insira a descrição da imagem aqui insira a descrição da imagem aqui

Como temos 5 x 7 = 35 pixels por caractere, podemos armazenar um caractere usando 35 bits em uma única palavra. Com o bit menos significativo a partir do lado esquerdo da palavra e com cada pixel na imagem a ser representado por o n ésimo bit, como mostrado acima, o número "3" acima seria armazenado na memória como: 01110100010000100110000011000101110, seguido por 29 não utilizada bits definidos como 0.

É assim que os caracteres foram / são armazenados em computadores antigos / modernos? Ou eles usam um único byte / palavra por pixel?

Se eles forem armazenados dessa maneira, qual seria a rotina em montagem / código de máquina (usando nada mais do que instruções elementares, como operações bit a bit, aritmética e de transporte de dados da Arquitetura do conjunto de instruções do computador) usada para converter esses dados em uma imagem no a tela se parece? Seria algo como:

  1. Armazene as coordenadas de exibição x e y para o pixel atual a ser atualizado em um determinado registro.
  2. Armazene os dois valores RGB escolhidos (neste caso, 0,255,0 para verde e 0,0,0 para preto) em outros dois registros separados.
  3. Faça com que dois outros registradores atuem como contadores inicializados em 5 e 7 para acompanhar a linha e a coluna atuais da imagem que está sendo renderizada.
  4. Teste se o registro da coluna não é 0. Se não estiver, teste se o LSB do bitmap está definido como 1, E o respectivo valor RGB registra-se com o registro de coordenadas xey, dependendo do resultado, e MOV esse resultado no registro de saída do visor.
  5. Reduza o registro do contador de linhas em 1, teste para ver se é 0. Se estiver, defina-o novamente como 5 e aumente a coordenada y em 1 e diminua o contador da coluna em 1.
  6. Mude o registro segurando o bitmap 1 bit para a esquerda.
  7. JMP à instrução 4.

Existe uma maneira mais simples ou mais eficiente de fazer isso? Parece que mesmo algo tão simples quanto renderizar um único caractere de texto pequeno requer um número bastante grande de operações e levaria cerca de 200 ciclos de CPU.

Finalmente, existem bons livros ou recursos no código no nível da máquina para exibir imagens do zero, porque não consegui encontrar nenhum, pois eles encobrem esse assunto específico ou o código está escrito em um idioma de alto nível ou em um assembler usando macros, que estão "trapaceando" e não explicam o que está acontecendo fundamentalmente no nível mais baixo.


3
O Black Book de Programação Gráfica é certamente um clássico que vale a pena ler. Um monte de oldschool de magia negra nele;)
glampert

Sim, eu apóio o livro de Michael Abrash. É uma ótima leitura. Há um truque muito mais na manga para o que está escrito neste livro, mas a filosofia por trás é importante (até hoje!)
Romain Piquois

Respostas:


7

Você precisa distinguir os modos de texto e gráfico da placa gráfica da sua máquina.

Antigamente, principalmente o modo de texto era suportado. Nesse modo, o quadro cuidava de armazenar a definição de bitmap dos caracteres e exibi-los na posição atual do cursor. Tudo o que você precisava fazer era fornecer o código ASCII do caractere (um byte por caractere) em um pequeno buffer de texto.

Atualmente, é fornecido um buffer de varredura de alta resolução, acessível em pixels e para o qual você grava informações de cores em algum formato suportado (no modo "mais alto", 3 bytes (RGB) por pixel, para um megapixel ou mais).

Originalmente, bitmaps binários simples (compactados) de tamanhos diferentes eram usados ​​e " manchados " na memória rasterizada por meio de uma solicitação ao driver do dispositivo, com possível tradução do formato.

Atualmente, os caracteres são definidos principalmente como desenhos vetoriais , que são uma descrição independente da resolução dos contornos e precisam passar por um processo de renderização complexo que inclui antialiasing para obter resultados suaves.

A saída renderizada pode ser armazenada em cache para exibição rápida, mais uma vez.

O processo geral é complexo, pode ser acelerado por hardware e é tratado pelo sistema operacional (gerenciamento da GUI) de forma transparente, juntamente com outras operações gráficas de desenho primitivo.


1

A resposta curta é SIM, você não pode evitar muita manipulação de bits se o seu formato precisar.

Desenhar um bitmap significa basicamente copiar um pixel de uma fonte para um destino e você deve fazer o que for necessário. (Citando o capitão Óbvio)

Uma resposta mais longa é que, se você escrever um rasterizador de software, poderá ter algum algoritmo e truque para economizar tempo de CPU (sabendo qual parte NÃO PRECISA DESENHAR (otimização da transparência), tendo o mesmo formato de pixel da fonte. como destino (diretamente ou em uma forma de cache), execute oticamente a cópia em memória, etc ... Basicamente, considere o loop de desenho do seu rasterizador e veja como você pode reestruturá-lo para economizar tempo de CPU (por exemplo: você pode gerar em tempo de execução um parte do código do assembler especificamente para imprimir a letra A ou obter meta para obter as informações de bitmap de origem para mostrar como ignorar a área transparente, etc.) Cada caso de uso pode ter uma solução diferente com base no conjunto de instruções da CPU, no formato do buffer, no algoritmo da sua primitiva de renderização (rotativa? alongando bitmaps? que tipo de filtragem? etc ...), registro da CPU e cache etc ...

Então, sim, de qualquer forma, foi necessário muito ciclo de CPU para escrever um único pixel nos velhos tempos, quando codificação estranha e pouca memória eram a norma. :-) Mas não proibiu que máquinas de 16/32 bits com CPU de 8 MHZ fizessem coisas assim: https://www.youtube.com/watch?v=GWwPJU6pp30 (E uma grande parte da CPU também foi usada para a música)

No caso da renderização HW, o HW executará a conversão do formato de origem para o formato de destino e, embora não utilize muitos truques disponíveis para o rasterizador SW, sua implementação genérica no HW provavelmente superará a maior parte da implementação SW.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.