It's possible convert this DCTL into s SparkSL?

Hello! I would like to use this effect into a new one Spark Ar filter :slight_smile:

If I remember correctly, nVidia had an article about this, but unfortunately I couldn’t find it to send you the link.
But as I remember, usually such scenes are seen in forested and plant-covered spaces in computer games, such as Tomb Raider games, or in spaces such as churches that have large windows.


In my opinion, this effect can be achieved by combining Bloom and Real Time Glow effects

Of course, I think the Bloom shader has already been designed in SparkSL language, you can find it in the link below

I already designed the Real Time Glow shader, but I am still working on optimizing it

The big problem in the design of these effects is that these effects are usually designed for computer games, which definitely have a much more powerful GPU and CPU than mobile phones, and you may experience a drop in FPS after the design.

1 Like

I don’t understand why the rgb channels are separated, but here’s the shader mostly directly ported. The effect was too subtle to see, so I added an offset scale. Overall, it feels too heavy for Spark, but you could try optimizing it.

spark-halation.arexport (33.1 KB)

vec3 sample(std::Texture2d texR, std::Texture2d texG, std::Texture2d texB, vec2 uv) {
  return vec3(

float exp_k(float x, float y, float r0) {
  return exp(-sqrt(x * x + y * y) / r0);

vec3 exp_blur(std::Texture2d texR, std::Texture2d texG, std::Texture2d texB, vec2 uv, float size, float scale) {
  vec2 u_resolution = std::getRenderTargetSize();
  float radius = floor(ceil(4.5 * size));
  vec3 sum = vec3(0.);
  float weight_sum = 0.;

  for (float i = -radius; i <= radius; i += 1.) {
    for (float j = -radius; j <= radius; j += 1.) {
      vec2 offset = vec2(i / u_resolution.x * scale, j / u_resolution.y * scale);
      float weight = exp_k(i, j, size);
      sum += weight * sample(texR, texG, texB, uv + offset);
      weight_sum += weight;

  return sum / weight_sum;

vec4 main(
  std::Texture2d u_texR,
  std::Texture2d u_texG,
  std::Texture2d u_texB,
  float u_size,
  float u_color,
  float u_method, // 0 for Proosa, 1 for Minuth
  float scale
) {
  vec4 fragColor;
  vec2 uv = std::getVertexTexCoord();
  vec3 rgb = sample(u_texR, u_texG, u_texB, uv);

  if (u_size < 1e-10) {
    return fragColor = vec4(rgb, 1.0);

  vec3 blurred = exp_blur(u_texR, u_texG, u_texB, uv, u_size, scale);
  vec3 result, color, halated;

  if (u_method == 0.) { // Proosa
    color = vec3(1.0, u_color, 0.0);
    halated = rgb + (blurred * color);
    result = halated / (color + 1.0);
  } else { // Minuth
    color = vec3(0.7, 1.0 - u_color / 3.0, 1.0);
    halated = (rgb - blurred) * color;
    result = halated + blurred;

  return fragColor = vec4(result, 1.0);