Realistic light rendering (math related)

I have a real light rendering problem (in an app). The current rendering looks like this:

enter image description here

and what it does is if the light brightness is low - only the middle ellipse is full brightness, and this is a way to better visualize low light situations while keeping the light color, etc.

Formula used:

current_ellipse_count = 15; // draw 15 ellipses from small to big one.
brightness = 100; // range is 0 to 255 ! lets say its 'white' light only, so r,g,b are equal.

while (current_ellipse_count > 0) {
    //DRAW small-to-big ELLIPSE AND FILL IT WITH ellipse_brightness. first drawn ellipse is small, and highest current_ellipse_count. so highest amplifying effect of brightness.
    ellipse_brightness = brightness*current_ellipse_count; // so the last ellipse will be real brightness(the biggest one) and the smallest one is always amplified by 15, bigger by 14, etc till the last one is amplified by 1. 
    if (ellipse_brightness > 255) ellipse_brightness = 255; // if it peaks its full brightness then.
    current_ellipse_count--;
}

      

This is a simplified way of what I am doing

This method successfully renders low light situations, but with a high luminance value, say 200 (from the range 0-255), only the last, largest, 1 pixel edge of the ellipse indicates that the light is not fully bright.

I need a better formula to correctly show low light situations and high brightness situations should be reduced. I think I need a formula that reduces a given luminance value, one way or another, so that it affects it from half way 125 (from the range 0-255) to a range of 255 or better - update the effect of approximating all luminance.

+3


source to share


2 answers


Several ways I can think that might work well:

1: ellipse_brightness = (int) (pow(brightness, 0.5) * current_ellipse_count * 2);

      

This should give you better rendering at high brightness levels. You can adjust the power (0.5) and ratio (2) according to your needs.

2: ellipse_brightness = (int) (brightness * 200 / pow(16 - current_ellipse_count, 2));

      

This uses the inverse square law, which should give you a similar effect by modifying the existing linear falloff. Adjust constant factor (200) and power (2) if necessary.

You can combine these two to possibly improve the effect (through trial and error, I found the luminance square looks better):



3: ellipse_brightness = (int) (pow(brightness, 2) * 0.75 / pow(16 - current_ellipse_count, 2));
   if (ellipse_brightness > brightness*4) ellipse_brightness = brightness*4;

      

Finally @ Furkan's answer gave me the idea to use cos()

:

4: ellipse_brightness = (int) (brightness * cos((16 - current_ellipse_count)/15*3.1415926/2) * 2);

      

The result of all these methods is as follows (original, # 1-4 top to bottom, left to right - brightness from 0 to 255 in increments of 16):

enter image description here

You can play with the parameters of all methods to tweak a little, or combine multiple methods as you like.

+1


source


You are looking for diffuse and specular shading as well as intensity like 1/(radius*radius)

. I changed it like 1/(4 * pi * radius * radius)

. You can experiment with it as long as the image looks fine.

You can google diffuse and specular shading. There are many sources.



// Diffuse Shading (Lambertian)
            RGB diffuse;
            float cosineAlpha = objectNormal.dot(lightVector);
            cosineAlpha = abs(cosineAlpha);
            if(cosineAlpha > 0)
            {
                diffuse.r = intensity.r * cosineAlpha * objects[closestObjectId]->matProperty.diffuse.r;
                diffuse.g = intensity.g * cosineAlpha * objects[closestObjectId]->matProperty.diffuse.g;
                diffuse.b = intensity.b * cosineAlpha * objects[closestObjectId]->matProperty.diffuse.b;

                objectColor.r += diffuse.r;
                objectColor.g += diffuse.g;
                objectColor.b += diffuse.b;
            }

// Specular Shading (Blinn-Phong)
            RGB specular;
            Vector3 halfVector;
            halfVector.setX((lightVector + v).x() / ((lightVector + v).length()));
            halfVector.setY((lightVector + v).y() / ((lightVector + v).length()));
            halfVector.setZ((lightVector + v).z() / ((lightVector + v).length()));
            float cosineTeta = objectNormal.dot(halfVector);   
            cosineTeta = abs(cosineTeta); 
            if(cosineTeta > 0)
            {
                float coeff = pow(cosineTeta, objects[closestObjectId]->matProperty.specExp);
                specular.r = intensity.r * coeff * objects[closestObjectId]->matProperty.specular.r;
                specular.g = intensity.g * coeff * objects[closestObjectId]->matProperty.specular.g;
                specular.b = intensity.b * coeff * objects[closestObjectId]->matProperty.specular.b;

                objectColor.r += specular.r;
                objectColor.g += specular.g;
                objectColor.b += specular.b;                        
            }

      

+1


source







All Articles