Skip to content

About

Repositório para guardar tarefas e trabalho final da disciplina Computação Gráfica

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ray Casting — Trabalho Final de Computação Gráfica

Renderizador 3D implementado do zero em C++17 utilizando a técnica de ray casting. A cena é renderizada pixel a pixel com modelo de iluminação de Phong, sombras, texturas UV e transformações geométricas via matrizes homogêneas. A saída é uma imagem no formato PPM.

A cena renderizada é uma releitura estilizada de um cenário do universo Super Mario, composta por plataformas gramadas, canos, blocos de tijolo, cogumelo, árvores, casco de tartaruga e bandeira.


Galeria


Sumário


Pré-requisitos

Ferramenta Versão mínima
CMake 3.10
GCC 9+ (suporte a C++17)

Como compilar e executar

# 1. Clone o repositório
git clone <url-do-repositorio>
cd computacao-grafica

# 2. Configure o build
cmake -B build

# 3. Compile e execute
cmake --build build

A imagem é salva em output/cena.ppm.

Visualizando o PPM

O formato PPM pode ser aberto por:

  • GIMP (Linux / Windows / macOS)
  • Preview (macOS)
  • IrfanView (Windows)
  • Via terminal com ImageMagick: convert output/cena.ppm output/cena.png
  • Conversores online como convertio.co

Estrutura do projeto

computacao-grafica/
│
├── CMakeLists.txt
│
├── assets/                        # Texturas da cena
│   ├── marTextura01.jpg
│   ├── gramaTextura01.jpg
│   ├── tijoloMarioTextura01.png
│   └── blocoMarioTextura02.png
│
├── include/
│   ├── auxiliares/                # Núcleo do renderizador
│   │   ├── Camera.h               # Câmera com lookAt e múltiplas projeções
│   │   ├── Canvas.h               # Buffer de pixels (resolução da imagem)
│   │   ├── Iluminacao.h           # Cor, Propriedades de material, IluminacaoCena
│   │   ├── Intersecao.h           # Estrutura de resultado de interseção
│   │   ├── Janela.h               # Janela de projeção
│   │   ├── Matrizes.h             # Matriz 4×4 + namespace Transformacao
│   │   ├── Pontos.h               # Tipo Ponto (x, y, z)
│   │   ├── Quaternios.h           # Quaternios para rotações
│   │   ├── Ray.h                  # Raio (origem + direção)
│   │   ├── Renderizacao.h         # Pipeline de renderização (classe estática)
│   │   ├── Textura.h              # Carregamento e amostragem de texturas
│   │   └── Vetores.h              # Tipo Vetor + operações algébricas
│   │
│   └── objetos/                   # Primitivas e objetos compostos
│       ├── Objeto.h               # Classe base abstrata
│       ├── ObjetoComplexo.h       # Objeto composto por sub-objetos
│       ├── Esfera.h
│       ├── Plano.h
│       ├── Cilindro.h
│       ├── Cone.h
│       ├── Cubo.h
│       ├── Paralelepipedo.h
│       ├── Triangulo.h
│       ├── SemiEsfera.h
│       ├── Arvore.h               # Cone (copa) + Cilindro (tronco)
│       ├── Bandeira.h             # Cilindro (haste) + Paralelepipedo (bandeirola)
│       ├── Cano.h                 # Dois cilindros concêntricos
│       ├── Casco.h                # SemiEsfera + base
│       └── Cogumelo.h             # SemiEsfera + Cilindro
│
├── src/
│   ├── auxiliares/                # Implementações do núcleo
│   └── objetos/                   # Implementações dos objetos
│
├── TrabalhoFinal/
│   └── TrabalhoFinal.cpp          # Ponto de entrada: monta e renderiza a cena
│
└── output/                        # Gerado automaticamente
    ├── cena                       # Executável
    └── cena.ppm                   # Imagem renderizada

Aspectos teóricos

Ray Casting

O renderizador opera lançando um raio primário por pixel a partir da câmera em direção à cena. Para cada pixel (L, C) do canvas, o pipeline executa:

1. Gerar raio primário                →  Camera::gerarRaioParaPixel(L, C, canvas)
2. Encontrar interseção mais próxima  →  Renderiza::encontrarIntersecaoMaisProxima()
3. Calcular normal no ponto de impacto→  Objeto::calcularNormal()
4. Verificar oclusão (sombra)         →  Renderiza::verificarSombra()
5. Aplicar modelo de Phong            →  CorResultante()
6. Amostrar textura (se houver)       →  Textura::amostrarRepetir()
7. Gravar cor no buffer               →  canvasArray[L][C]

Ao final: escrever buffer em PPM

Cada raio é parametrizado como P(t) = origem + t * direção, e a interseção com cada objeto resolve analiticamente a equação correspondente (quadrática para esferas e cilindros, linear para planos, etc.).

Modelo de iluminação de Phong

A cor final de cada pixel combina três componentes:

I = Kamb ⊗ IA  +  Kdif ⊗ IF · max(0, n·l)  +  Kesp ⊗ IF · max(0, r·v)^m
Símbolo Significado
Kamb, Kdif, Kesp Coeficientes de reflexão ambiente, difusa e especular do material
IA, IF Intensidade ambiente e da fonte de luz
n Normal da superfície no ponto de impacto (unitária)
l Vetor unitário em direção à fonte de luz
v Vetor unitário em direção ao observador
r Vetor de reflexão: r = 2(n·l)n - l
m Expoente de brilho (shininess)
⊗ Produto componente a componente (arroba)

Os coeficientes de material são definidos por objeto via Propriedades(Kdif, Kesp, Kamb).

Sombras

Após encontrar um ponto de interseção, é lançado um raio de sombra da superfície em direção à fonte de luz. Se este raio colidir com qualquer outro objeto antes de atingir a luz, o ponto é considerado em sombra e a componente difusa e especular é suprimida — apenas a componente ambiente permanece.

O parâmetro EPS (bias) é aplicado na origem do raio de sombra para evitar auto-interseção numérica com a superfície de origem.

Texturas

As texturas são carregadas via stb_image e aplicadas por mapeamento UV. Cada objeto com textura implementa o método calcularUV(ponto), que converte o ponto 3D de impacto em coordenadas (u, v) ∈ [0, 1]. A amostragem usa repetição (fmod) para permitir tiling, com escala controlada por setEscalaTextura(fator).

Transformações geométricas

Todos os objetos suportam transformações via matrizes homogêneas 4×4 (namespace Transformacao):

Método Descrição
transladar(tx, ty, tz) Translação
escalar(sx, sy, sz, ponto_fixo) Escala em relação a um ponto fixo
rotacionarX/Y/Z(graus) Rotação nos eixos canônicos
rotacionarEmEixoArbitrario(eixo, graus, ponto) Rotação em eixo arbitrário
espelharXY/XZ/YZ() Reflexão nos planos coordenados
cisalharX_XZ / cisalharY_XZ / ... Cisalhamento

As matrizes de transformação são acumuladas e aplicadas aos vértices e normais dos objetos antes da renderização.

Câmera e projeção

A câmera é configurada via lookAt(eye, atPoint, up), que define o sistema de coordenadas local (frente, direita, acima). Três tipos de projeção são suportados:

Tipo Enum
Perspectiva PERSPECTIVA
Ortográfica ORTOGRAFICA
Oblíqua OBLIQUA

A distância focal e as dimensões da janela de projeção controlam o campo de visão.


Objetos disponíveis

Classe Descrição Textura
Esfera Esfera analítica com normal suavizada ✓
Plano Plano infinito com normal constante ✓
Cilindro Cilindro com tampas, eixo arbitrário ✓
Cone Cone com base, eixo arbitrário ✓
Cubo Cubo axis-aligned ✓
Paralelepipedo Paralelepípedo com largura, altura e profundidade independentes ✓
Triangulo Triângulo por três vértices (Möller–Trumbore) ✗
SemiEsfera Metade superior de uma esfera ✗
Arvore Cone (copa) + Cilindro (tronco) ✗
Bandeira Cilindro (haste) + Paralelepipedo (bandeirola) ✗
Cano Dois cilindros concêntricos (exterior + interior) ✗
Casco SemiEsfera + base plana ✗
Cogumelo SemiEsfera (chapéu) + Cilindro (corpo) ✗

Configurando a cena

Câmera

Ponto eye(250.0f, 250.0f, 0.0f);        // posição do observador
Ponto atpoint(250.0f, 75.0f, 250.0f);   // ponto para onde a câmera aponta
Vetor up(0.0f, 1.0f, 0.0f);             // vetor "para cima"

camera.lookAt(eye, atpoint, up);
camera.setDistanciaFocal(30.0f);

Iluminação

IluminacaoCena iluminacao(IF, IA, PF);

// Luz pontual (padrão)
iluminacao.setPontual(Ponto(250, 400, 250), Cor(0.8f, 0.8f, 0.8f));

// Luz direcional
iluminacao.setDirecional(Vetor(1, -1, 1), Cor(0.8f, 0.8f, 0.8f));

// Luz spot
iluminacao.setSpot(posicao, direcao, 30.0f, Cor(1, 1, 1));

Adicionando objetos

// 1. Declare o objeto
Esfera esfera01(
    Ponto(250.0f, 100.0f, 250.0f),   // centro
    30.0f,                            // raio
    Propriedades(
        Cor(0.8f, 0.2f, 0.2f),       // Kdif
        Cor(0.6f, 0.6f, 0.6f),       // Kesp
        Cor(0.2f, 0.0f, 0.0f)        // Kamb
    ),
    50                                // shininess
);

// 2. Aplique textura (opcional)
esfera01.setTextura(&minhaTextura);

// 3. Aplique transformações (opcional)
esfera01.transladar(0.0f, 20.0f, 0.0f);

// 4. Adicione à cena
objetos.push_back(&esfera01);

About

Repositório para guardar tarefas e trabalho final da disciplina Computação Gráfica

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages