A base física das cores de uma mancha de óleo é a iridescência e também está relacionada aos anéis de Newton . Especificamente, a espessura da camada de óleo é da ordem do comprimento de onda da luz. Como a luz reflete da superfície superior e inferior do óleo, em qualquer comprimento de onda, em alguns ângulos, as duas reflexões estarão fora de fase e se cancelarão; em outros ângulos, as reflexões estarão em fase e serão somadas. Isso acontece em ângulos diferentes para cada comprimento de onda, portanto, iluminar o óleo com luz branca produz todas essas cores. Se você a iluminasse com uma frequência única (por exemplo, luz laser), você veria apenas uma série de anéis claros e escuros.
Se você ignorar a refração na camada de óleo, apenas calculando a geometria da situação, poderá descobrir que o brilho da luz refletida para qualquer comprimento de onda deve variar como
sin(2.0 * pi * oilThickness / (dot(L, H) * wavelength)) * 0.5 + 0.5
Teoricamente, isso deve ser integrado em todos os comprimentos de onda, mas, na prática, você provavelmente pode fazê-lo apenas em vermelho, verde e azul - digamos 700, 550 e 400 nm, respectivamente. Alterar a espessura do óleo alterará o raio aparente dos anéis de cor. Eu provavelmente agruparia o valor 2.0 * pi * oilThickness / wavelength
em um único RGB fornecido ao shader como um valor uniforme. Você pode multiplicá-lo por uma textura para simular diferentes espessuras de óleo, se desejado - provavelmente é o que fornece a maior parte da textura interessante na imagem acima.
Isso produz um valor de cor RGB que você pode multiplicar em seu BRDF. O dot(L, H)
fator seria usado para luzes pontuais / direcionais, e você pode substituir dot(N, V)
por aplicar isso também a uma reflexão do mapa do ambiente.
Isenção de responsabilidade: eu não tentei isso em um shader, apenas desenhei alguns diagramas e me convenci de que "deveria funcionar" ... então, deixe-me saber os resultados, se você tentar! :)