软件光栅化渲染器(十)

光照计算

环境光,一般场景中只有一个环境光源

//环境光
class Light
{
public:
    int id;
    int state;
    int attr;
    Point3D position;
    Color color;

    //计算光强
    virtual Color CalculateColor(const Vertex3D &vertex, const Material &material, const Point3D &objectPos)
    {
        double r = material.ka;
        double g = material.ka;
        double b = material.ka;
        //判断是否溢出
        r = r > 1.0 ? 1.0 : r;
        g = g > 1.0 ? 1.0 : g;
        b = b > 1.0 ? 1.0 : b;
        return Color(color.r *r, color.g *g, color.b *b);
    }
};

定向光源,方向一定,并且光不会衰减

//方向光源
class DirectionLight :public Light
{
public:
    Vector3D direction;

    Color CalculateColor(const Vertex3D &vertex, const Material &material, const Point3D &objectPos)
    {
        double r = 0;
        double g = 0;
        double b = 0;

        //计算散射光
        Vector3D l;
        l.x = -direction.x;
        l.y = -direction.y;
        l.z = -direction.z;
        VectorNormalize(l);
        double dp = VectorDot(vertex.normal, direction);
        //光衰减系数
        double atten = 1;

        if (dp > 0)
        {
            r += material.kd * dp / atten;
            g += material.kd * dp / atten;
            b += material.kd * dp / atten;
        }

        //计算镜面高光
        l = direction;
        double x = l.x - 2 * VectorDot(l, vertex.normal) * vertex.normal.x;
        double y = l.y - 2 * VectorDot(l, vertex.normal) * vertex.normal.y;
        double z = l.z - 2 * VectorDot(l, vertex.normal) * vertex.normal.z;
        Vector3D rVector = { x, y, z, 1 };
        Vector3D v = objectPos - vertex.vertex;
        VectorNormalize(rVector);
        VectorNormalize(v);
        double is = pow(VectorDot(rVector, v), material.shininess);
        if (is > 0)
        {
            r += material.ks * is / atten;
            g += material.ks * is / atten;
            b += material.ks * is / atten;
        }

        //判断是否溢出
        r = r > 1.0 ? 1.0 : r;
        g = g > 1.0 ? 1.0 : g;
        b = b > 1.0 ? 1.0 : b;
        return Color(color.r *r, color.g *g, color.b *b);
    }
};

聚光灯
//聚光灯
class SpotLight :public Light
{
public:

//衰减系数
double kc;
double kl;
double kq;

Vector3D direction;
double inAngle;     //内锥角度
double outAngle;    //外锥角度
double pf;          //指数因子

void SetInAngle(double inAngle)
{
    this->inAngle = inAngle / 180.0 * PI;
}

void SetOutAngle(double outAngle)
{
    this->outAngle = outAngle / 180.0 * PI;
}

Color CalculateColor(const Vertex3D &vertex, const Material &material, const Point3D &objectPos)
{
    Vector3D l = vertex.vertex - position;
    VectorNormalize(l);
    VectorNormalize(direction);
    double dp = VectorDot(l, direction);

    double r = 0.0;
    double g = 0.0;
    double b = 0.0;
    if (dp <= 0.0)
    {
        return Color(r, g, b);
    }
    double angle = acos(dp);



    //本影
    if (angle < inAngle)
    {
        //计算散射光
        Vector3D l = position - vertex.vertex;
        double d = CalculateVector3DLength(l);
        VectorNormalize(l);
        double dp = VectorDot(vertex.normal, l);
        //光衰减系数
        double atten = kc + kl * d + kq *d * d;

        if (dp > 0)
        {
            r += material.kd * dp / atten;
            g += material.kd * dp / atten;
            b += material.kd * dp / atten;
        }

        //计算镜面高光
        l = vertex.vertex - position;
        double x = l.x - 2 * VectorDot(l, vertex.normal) * vertex.normal.x;
        double y = l.y - 2 * VectorDot(l, vertex.normal) * vertex.normal.y;
        double z = l.z - 2 * VectorDot(l, vertex.normal) * vertex.normal.z;
        Vector3D rVector = { x, y, z, 1 };
        Vector3D v = objectPos - vertex.vertex;
        VectorNormalize(rVector);
        VectorNormalize(v);
        double is = pow(VectorDot(rVector, v), material.shininess);
        if (is > 0)
        {
            r += material.ks * is / atten;
            g += material.ks * is / atten;
            b += material.ks * is / atten;
        }
    }
    //半影
    else if (angle >= inAngle && angle < outAngle)
    {
        //计算散射光
        Vector3D l = position - vertex.vertex;
        double d = CalculateVector3DLength(l);
        VectorNormalize(l);
        double dp = VectorDot(vertex.normal, l);
        //光衰减系数
        double atten = (kc + kl * d + kq *d * d);
        double pfValue = pow((cos(angle) - cos(2 * outAngle)) / (cos(2 * inAngle) - cos(2 * outAngle)), pf);
        atten = pfValue * atten;
        if (dp > 0)
        {
            r += material.kd * dp / atten;
            g += material.kd * dp / atten;
            b += material.kd * dp / atten;
        }

        //计算镜面高光
        l = vertex.vertex - position;
        double x = l.x - 2 * VectorDot(l, vertex.normal) * vertex.normal.x;
        double y = l.y - 2 * VectorDot(l, vertex.normal) * vertex.normal.y;
        double z = l.z - 2 * VectorDot(l, vertex.normal) * vertex.normal.z;
        Vector3D rVector = { x, y, z, 1 };
        Vector3D v = objectPos - vertex.vertex;
        VectorNormalize(rVector);
        VectorNormalize(v);
        double is = pow(VectorDot(rVector, v), material.shininess);
        if (is > 0)
        {
            r += material.ks * is / atten;
            g += material.ks * is / atten;
            b += material.ks * is / atten;
        }
    }

    //判断是否溢出
    r = r > 1.0 ? 1.0 : r;
    g = g > 1.0 ? 1.0 : g;
    b = b > 1.0 ? 1.0 : b;
    return Color(r, g, b);
}

};

业余时间搞了差不多2个月,功能基本实现了,但只是实现了, 优化和代码水平太渣,不忍直视。收货也不小,理解了3d立体到2D平面上是怎样一个过程了。

这里写图片描述
Github地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值