Tenho alguma experiência em programação de geometria e computação de sombreadores - mas nunca me aventurei em realmente brincar com os sombreadores de fragmento. Atualmente, estou tentando entender melhor como eles funcionam e seu potencial. Uma das coisas que li em vários lugares é que um fragmento (isto é, um pixel da tela) não pode se estender além de si mesmo dentro do sombreador de fragmentos. O que significa que um determinado fragmento sendo iterado só pode afetar a si mesmo.
Portanto, e para o aprendizado, eu gostaria de saber se o seguinte é possível (e se é, como, em linhas gerais, ele pode ser alcançado). Suponha que tenhamos, por uma questão de simplicidade, uma malha de pontos que consiste em apenas dois vértices (localizados no espaço do mundo 3D). Podemos programar um sombreador de forma que cada um desses dois vértices seja pintado na tela na posição exata do WorldToViewport, mas também que um círculo ao redor de cada um deles de raio = R também seja pintado nos pixels adjacentes, mesmo que eles se estendam além da malha original à qual o shader está conectado? Como na figura abaixo (onde o quadrado vermelho no centro dos círculos representa os vértices pintados na tela):
Se isso for possível, um sombreador também pode ser programado de tal forma que esses círculos que se estendem além dos vértices influenciam a cor (RGBA) um do outro? Como na figura abaixo:
Como eu disse, se essas são possíveis, eu gostaria de ouvir um pouco de como conseguir isso - em termos conceituais ou práticos. Isso é feito no shader de fragmento ou precisa ser calculado antes no shader de vértice ou geometria? Como calcular e passar "fragmentos adicionais" que se estendem além dos fragmentos ocupados pelo corpo da malha?
fonte
Respostas:
Quando você usa largura de linha ou antialiasing de linha ou largura de ponto ou pontos, o OpenGL cria para você um pequeno retângulo em vez da linha ou ponto, com coordenadas de textura. Atualmente, você pode programar você mesmo usando sombreadores de geometria ou até mesmo o mosaico.
Uma abordagem totalmente diferente é usar sombreamento adiado, usando uma passagem geométrica apenas para armazenar informações no buffer RGBAZ e, em seguida, uma segunda passagem que você executa em todos os pixels da tela para realizar algum processo. (para atuar em todos os pixels, basta desenhar um retângulo em tela cheia). Hoje em dia você pode até fazer a primeira passagem como uma ou várias "renderizar para textura" e depois mapear MIP essas texturas, para que a passagem final possa acessar facilmente valores menos locais.
fonte
Uma boa maneira de organizar um círculo (ou outra forma) a ser desenhado para cada vértice de uma malha é usar instâncias geométricas . Esse é um recurso da GPU que permite desenhar várias instâncias (cópias) de uma malha de uma só vez, com os vértices / índices da malha fornecidos por um conjunto de buffers e outro buffer de vértice que pode fornecer dados adicionais por instância. O sombreador de vértice pode ser usado para combinar os dados de ambos os buffers da maneira que você escolher.
Para ser concreto, no seu caso, você pode criar uma malha representando um círculo do raio desejado, com seus vértices especificados diretamente nas coordenadas do espaço da tela e centralizados na origem. Em seguida, você usaria instanciamento para fazer a GPU renderizar uma nova cópia da malha circular para cada vértice da malha pontual original. No sombreador de vértice, você calcula a posição no espaço da tela do ponto (usando as transformações de projeção de visão de mundo como de costume) e depois traduz a malha do círculo para centralizar nessa posição.
Quanto à segunda parte da sua pergunta, sobre como os círculos influenciam a cor um do outro: depende especificamente do que você deseja fazer. A mistura de hardware pode ser usada para lidar com casos simples, como adicionar ou multiplicar as cores ou mistura alfa. Se você quiser algo mais complicado que isso, talvez seja possível fazer isso com um algoritmo de várias passagens ou (nas GPUs mais recentes) mistura programável.
fonte