Eu gostaria de carregar malhas arbitrárias e desenhar linhas pretas grossas ao longo das bordas para obter uma aparência de sombreamento. Consegui desenhar uma silhueta preta ao redor dos objetos usando o buffer de estêncil. Você pode ver o resultado aqui:
Mas o que falta são as linhas pretas no próprio objeto. Pensei em verificar descontinuidades normais: Verificar se um pixel vizinho tem um vetor normal diferente do atual. Se sim, uma borda foi encontrada. Infelizmente, não tenho idéia de como implementar essa abordagem, nem no OpenGL nem no GLSL vertex / fragment shader.
Ficaria muito feliz por alguma ajuda com relação a essa abordagem ou qualquer outra sobre detecção de borda.
Edit: Eu não uso nenhuma textura para minhas malhas.
Para ser mais preciso, eu gostaria de criar uma solução CAD / CAM com a maior aparência possível (retirada do Top Solid https://www.youtube.com/watch?v=-qTJZtYUDB4 ):
fonte
Respostas:
Geralmente, a detecção de borda se resume a detectar áreas da imagem com alto valor de gradiente.
No nosso caso, podemos ver grosseiramente o gradiente como a derivada da função de imagem; portanto, a magnitude do gradiente fornece informações sobre o quanto sua imagem muda localmente (em relação aos pixels / texels vizinhos).
Agora, uma vantagem é, como você diz, uma indicação de descontinuidade; portanto, agora que definimos o gradiente, fica claro que essas informações são tudo o que precisamos. Depois de encontrarmos o gradiente de uma imagem, basta aplicar um limite a ela para obter um valor binário edge / non-edge.
Como você acha que esse gradiente é realmente o que você está perguntando e ainda estou para responder :)
Muitas maneiras! Aqui estão algumas :)
Funções de sombreador incorporadas
Tanto hlsl quanto glsl oferecem funções derivadas. No GLSL, você tem dFdx e dFdy que fornecem, respectivamente, informações de gradiente nas direções x e y. Normalmente essas funções são avaliadas em um bloco de fragmentos 2x2.
A menos que você esteja interessado em uma única direção, uma boa maneira de obter um resultado compacto que indique quão forte é o gradiente na região é uma largura que não fornece mais nada além da soma do valor absoluto de dFdy e dFdy.
É provável que você esteja interessado em uma borda na imagem geral em vez de em um canal específico; portanto, convém transformar sua função de imagem em luma. Com isso em mente, quando se trata de detecção de borda, seu shader pode incluir algo parecido com:
Com um limite alto, você encontrará arestas mais grossas e poderá perder algumas, por outro lado, com um limite baixo, poderá detectar arestas falsas. Você precisa experimentar para encontrar o limite que melhor se adapte às suas necessidades.
Vale a pena mencionar a razão pela qual essas funções funcionam, mas não tenho tempo para isso agora, provavelmente atualizarei esta resposta mais tarde :)
Pós-processo do espaço na tela
Você pode ficar mais chique do que isso, agora o campo de detecção de Borda no processamento de imagens é imenso. Eu poderia citar dezenas de boas maneiras de detectar a detecção de bordas de acordo com suas necessidades, mas vamos simplificar por enquanto, se você estiver interessado, posso citar mais opções!
Portanto, a idéia seria semelhante à acima, com a diferença de que você poderia olhar para uma vizinhança mais ampla e usar um conjunto de pesos em amostras envolventes, se desejar. Normalmente, você executa uma convolução sobre sua imagem com um kernel que fornece como resultado uma boa informação de gradiente.
Uma escolha muito comum é o kernel Sobel
Que, respectivamente, fornecem gradientes nas direções x e y:
Então você pode limiar da mesma maneira que mencionei acima.
Esse kernel, como você pode ver, dá mais peso ao pixel central, e efetivamente calcula o gradiente + um pouco de suavização que tradicionalmente ajuda (geralmente a imagem é gaussiana borrada para eliminar pequenas arestas).
O exemplo acima funciona muito bem, mas se você não gosta da suavização, pode usar os kernels Prewitt:
(Observe que estou com pressa, em breve escreverei o texto formatado adequado em vez de imagens!)
Realmente, existem muito mais kernels e técnicas para encontrar a detecção de bordas no processo de imagem, em vez de gráficos em tempo real, então excluí métodos mais complicados (trocadilhos não pretendidos), pois provavelmente você ficaria bem com as funções dFdx / y .
fonte
Caso alguém também precise detectar arestas: Aqui está um bom artigo sobre como exibir uma estrutura de arame e este artigo explica como mostrar apenas as arestas.
fonte