Acho que o principal problema é o alcance dinâmico, seu algoritmo provavelmente está certo, mas você está trabalhando no tipo errado de dados.
Uma fonte de luz pontual que, de outra forma, cortaria e tornaria branco puro, se espalhará por uma lente desfocada em uma área maior, de modo a formar um disco que não seja tão brilhante e, portanto, não cortará.
É por isso que você obtém esses círculos agradáveis em sua imagem bokeh real. Se você capturar o sinal (tornando-o menos brilhante do que seria de outro modo e depois espalhá-lo com sua simulação de bokeh, você obtém um círculo escuro (ou hexágono ou qualquer outro)) que não se destaque e, portanto, não parece realista.
O que você tem em uma cadeia de imagens real é:
bokeh (from the lens) -> digitisation (clipping) -> gamma correction & dynamic range compression
O que você está fazendo é
sharp image -> digitisation (clipping) -> gamma correction & dynamic range compression -> bokeh simulation
Você não obterá o resultado correto porque não está trabalhando com dados lineares.
O que você pode fazer é tentar linearizar os dados, substituir qualquer faixa dinâmica que foi perdida para cortar, executar sua simulação de bokeh e refazer as operações não lineares!
Aqui está um exemplo. Comecei com uma imagem HDR que foi mapeada por tom, fornecendo um resultado altamente não-linear. Este é o pior tipo de imagem para tentar a simulação de bokeh!
Fazer uma operação de convolução padrão para simular bokeh (usando a ferramenta de desfoque de lente do photoshop) gera esse resultado, que é muito semelhante ao que você está obtendo:
Para obter um resultado melhor, apliquei uma curva extrema para tentar recuperar a imagem mais ou menos do que teria sido antes do mapeamento de tom, onde os realces são muito, muito mais brilhantes que o restante da imagem. Fiz isso usando a ferramenta de níveis, empurrando a entrada central para a direita, de 1,0 a 0,2). Apliquei a ferramenta Desfoque de lente, como antes. Finalmente, apliquei uma curva extrema na direção oposta à primeira curva. O resultado, embora muito longe da perfeição, parece muito mais com o bokeh de lente real:
Se você estiver fazendo isso no código, tente cubar cada valor, aplicando sua rotina de simulação de bokeh e pegue a raiz do cubo de cada valor. Você deve ver uma melhoria. Pode levar alguns ajustes.
tl; dr mesmo se você tiver implementado um modelo matemático perfeita de bokeh, ele deve ser aplicado em dados lineares unclipped. Se você aplicar os mesmos cálculos aos dados fortemente modificados (mesmo um padrão no JPEG da câmera é fortemente modificado do ponto de vista matemático), obterá um resultado muito diferente.