C++ 真实光可视化(数学相关)

C++ 真实光可视化(数学相关),c++,math,C++,Math,我确实有一个真实灯光可视化的问题(在应用程序中)。当前的可视化看起来像: 它所做的是——如果光的亮度很低——只有椭圆的中间部分是全亮度,这是一种更好地可视化弱光情况的方法,同时还能看到光的颜色,等等 使用的公式: current_ellipse_count = 15; // draw 15 ellipses from small to big one. brightness = 100; // range is 0 to 255 ! lets say its 'white' light onl

我确实有一个真实灯光可视化的问题(在应用程序中)。当前的可视化看起来像:

它所做的是——如果光的亮度很低——只有椭圆的中间部分是全亮度,这是一种更好地可视化弱光情况的方法,同时还能看到光的颜色,等等

使用的公式:

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--;
}
这是我正在做的事情的简化方式

这种方法成功地将低亮度情况可视化,但在高亮度值下,例如200(超出0-255范围),只有椭圆的最后一个、最大的1像素边框显示灯光不是完全明亮的

我需要一个更好的公式来正确显示低亮度情况,而高亮度情况应该降低。
我想我需要一个公式来降低给定的亮度值,以某种方式使其从一半的125(超出0-255范围)影响到255范围,或者更好-更新整个亮度调整影响。

您对漫反射和镜面反射明暗处理的查找强度也为
1/(半径*半径)
。我将其修改为
1/(4*pi*radius*radius)
。只要图像看起来很好,你就可以对它进行实验

您可以在谷歌上搜索漫反射和镜面反射着色。有很多来源

// 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: ellipse_brightness = (int) (pow(brightness, 0.5) * current_ellipse_count * 2);
这将使您在高亮度水平下获得更好的可视化效果。您可以调整功率(0.5)和系数(2)以满足您的需要

2: ellipse_brightness = (int) (brightness * 200 / pow(16 - current_ellipse_count, 2));
这将使用平方反比定律,通过更改现有的线性衰减,该定律将提供类似的效果。根据需要调整恒定系数(200)和功率(2)

您可以将这两种方法结合起来,以获得可能更好的效果(通过反复试验,我发现亮度平方看起来更好):

最后,@Furkan的回答让我想到了使用
cos()

所有这些方法的输出如下图所示(原始,#1-4从上到下,从左到右的亮度为0-255,以16步为单位):


你可以使用所有方法的参数来调整一些东西,或者根据需要组合多种方法。

在现实世界中,光强度以
1/(半径*半径)
的速率衰减。谢谢,我将在不久的将来尝试调整你给出的公式,并看看我将从中得到什么。但是我不需要确切的真实情况,我只需要给用户一个关于应用程序输出的想法(一种颜色为0-255)。@Cornstalks和我要说的完全一样。如果你关心亮度的感知,可以加入对数。看看费希纳定律<代码>功率(…,0.5)和
功率(…,2)
。为什么不将
sqrt
用于
0.5
,并与
*
平方
pow
不是最有效或最准确的功能。。。我知道图形中充满了近似技巧,但如果OP是为了“真实光可视化”,那么使用正确的值是有意义的,因为这样你就可以轻松地调整它们以使用任何功率。这不是一个现实的尝试,而是简单地得到一些看起来不错的东西。很好,我可能会从中得到我想要的东西。因为FurkAn的答案离我目前在C++中的代码太远了。谢谢,我很高兴。稍后我会接受你的回答。你可以找到有关漫反射和镜面反射着色的大学文档。你是从头开始写的,你用哪一个算法,但是你的答案离我目前的知识太远了,那是我的第一个C++应用程序。尽管如此,我还是会在不久的将来投入一些时间来分析“漫反射和镜面反射着色”。是的,我正在从头开始编写简单的PICPLE C++(当前的灯光可视化作品,投掷绘制椭圆)。学习C++。
3: ellipse_brightness = (int) (pow(brightness, 2) * 0.75 / pow(16 - current_ellipse_count, 2));
   if (ellipse_brightness > brightness*4) ellipse_brightness = brightness*4;
4: ellipse_brightness = (int) (brightness * cos((16 - current_ellipse_count)/15*3.1415926/2) * 2);