Exemplo n.º 1
0
Vector4 Shading(const Vector3 &pos, const Vector3 &normal, const Material &mat, const Light &light)
{
    // 光线方向,由物体指向光源
    Vector3 L = light.position - pos;
    // 光源距离
    float dist = L.Magnitude();
    L.SetNormalize();
    // 光强,按点光源计算
    float I = 1.0f / (light.attenuation0 + light.attenuation1 * dist + light.attenuation2 * dist * dist);
    // 环境光
    Vector4 amb_color = light.ambient * mat.ambient * I;
    amb_color = clamp(amb_color, 0.0f, 1.0f);
    Vector3 N = normal;
    N.SetNormalize();
    // 顶点法线
    float light_angle = DotProduct(L, N);
    light_angle = max_t(light_angle, 0.0f);
    // 漫反射
    Vector4 diff_color = light.diffuse * mat.diffuse * light_angle * I;
    diff_color = clamp(diff_color, 0.0f, 1.0f);
    // 观察方向(相机空间)
    Vector3 V = -pos;
    V.SetNormalize();
    // 半角向量
    Vector3 H = L + V;
    H.SetNormalize();
    // 镜面反射
    float view_angle = DotProduct(H, N);
    view_angle = max_t(view_angle, 0.0f);
    Vector4 spec_color = light.specular * mat.specular * powf(view_angle, mat.specular.w) * I;
    spec_color = clamp(spec_color, 0.0f, 1.0f);
    Vector4 ret = amb_color + diff_color + spec_color;    
    return ret;
}
Exemplo n.º 2
0
void Renderer::Lighting(void)
{
    if (shading_mode_ == kFrame || shading_mode_ == kNoLightingEffect)
    {
        return;
    }
    else if (shading_mode_ == kFlat)
    {
        assert(light_);
        if (!light_) 
            return;
        for (int i = 2; i < rend_primitive_.size; i += 3)
        {
            // 假设为三角形
            if ((i + 1) % 3 != 0)
                continue;

            Vector3 p0 = rend_primitive_.vertexs[i - 2].position.GetVector3();
            Vector3 p1 = rend_primitive_.vertexs[i - 1].position.GetVector3();
            Vector3 p2 = rend_primitive_.vertexs[i].position.GetVector3();

            Vector3 pos = (p0 + p1 + p2) * (1.0f / 3.0f);

            Vector3 e0 = p1 - p0;
            Vector3 e1 = p2 - p1;

            Vector3 normal = CrossProduct(e0, e1);
            normal.SetNormalize();

            Vector4 color = Shading(pos, normal, *mat_, *light_);
            rend_primitive_.vertexs[i - 2].color = color;
            rend_primitive_.vertexs[i - 1].color = color;
            rend_primitive_.vertexs[i].color = color;
        }
    }
    else if (shading_mode_ == kGouraud)
    {
        assert(light_);
        if (!light_) 
            return;
        for (int i = 0; i < rend_primitive_.size; ++i)
        {
            // 顶点位置
            const Vector3 pos = rend_primitive_.vertexs[i].position.GetVector3();
            const Vector3 &normal = rend_primitive_.vertexs[i].normal;
            Vector4 color = Shading(pos, normal, *mat_, *light_);
            rend_primitive_.vertexs[i].color = color;
        }
    }
    else if (shading_mode_ == kPhong)
    {
        for (int i = 0; i < rend_primitive_.size; ++i)
        {
            // 记录物体原来的位置
            rend_primitive_.vertexs[i].global_pos = rend_primitive_.vertexs[i].position.GetVector3();
        }
        return;
    }
}
Exemplo n.º 3
0
    /*              v0
                    /\
                   /  \
                  /    \
                 /      \
                /        \
            v2 ------------ v1
    */
void Renderer::DiffTriangleUp(const RendVertex &v0, const RendVertex &v1, const RendVertex &v2)
{
    float dy = v1.position.y - v0.position.y;
    float dx_left = (v2.position.x - v0.position.x) / dy;
    float dx_right = (v1.position.x - v0.position.x) / dy;

    float done_over_z_left = (1.0f / v2.position.w - 1.0f / v0.position.w) / dy;
    float done_over_z_right = (1.0f / v1.position.w - 1.0f / v0.position.w) / dy;

    Vector4 dc_left = (v2.color - v0.color) / dy;
    Vector4 dc_right = (v1.color - v0.color) / dy;

    // 透视差值uv
    Vector2 uv_over_z_top = v0.uv / v0.position.w;
    Vector2 uv_over_z_left = v2.uv / v2.position.w;
    Vector2 uv_over_z_right = v1.uv / v1.position.w;

    Vector2 duv_over_z_left = (uv_over_z_left - uv_over_z_top) / dy;
    Vector2 duv_over_z_right = (uv_over_z_right - uv_over_z_top) / dy;
    
    // 仿射映射差值uv
    Vector2 duv_left = (v2.uv - v0.uv) / dy;
    Vector2 duv_right = (v1.uv - v0.uv) / dy;

    // 对法线差值
    Vector3 dnormal_left = (v2.normal - v0.normal) / dy;
    Vector3 dnormal_right = (v1.normal - v0.normal) / dy;

    // 对物体原来位置做差值
    Vector3 dpos_left = (v2.global_pos - v0.global_pos) / dy;
    Vector3 dpos_right = (v1.global_pos - v0.global_pos) / dy;
    
    float x_begin = v0.position.x;
    float x_end = v0.position.x;
    float one_over_z_begin = 1.0f / v0.position.w;
    float one_over_z_end = 1.0f / v0.position.w;
    Vector4 color_begin = v0.color;
    Vector4 color_end = v0.color;
    Vector2 uv_over_z_begin = uv_over_z_top;
    Vector2 uv_over_z_end = uv_over_z_top;
    Vector2 uv_begin = v0.uv;
    Vector2 uv_end = v0.uv;
    Vector3 normal_begin = v0.normal;
    Vector3 normal_end = v0.normal;
    Vector3 pos_begin = v0.global_pos;
    Vector3 pos_end = v0.global_pos;

    int y = (int)v0.position.y;
    if (y < 0)
    {
        float d = -v0.position.y;
        x_begin += dx_left * d;
        x_end += dx_right * d;
        one_over_z_begin += done_over_z_left * d;
        one_over_z_end += done_over_z_right * d;
        color_begin += dc_left * d;
        color_end += dc_right * d;
        uv_over_z_begin += duv_over_z_left * d;
        uv_over_z_end += duv_over_z_right * d;
        uv_begin += duv_left * d;
        uv_end += duv_right * d;
        normal_begin += dnormal_left * d;
        normal_end += dnormal_right * d;
        pos_begin += dpos_left * d;
        pos_end += dpos_right * d;
        y = 0;
    }
    
    int bumpmap_width = 0;
    int bumpmap_height = 0;
    float s1 = v1.uv.u - v0.uv.u;
    float s2 = v2.uv.u - v0.uv.u;
    float t1 = v1.uv.v - v0.uv.v;
    float t2 = v2.uv.v - v0.uv.v;
    float div = s1 * t2 - s2 * t1;
    Vector3 Q1 = v1.position.GetVector3() - v0.position.GetVector3();
    Vector3 Q2 = v2.position.GetVector3() - v0.position.GetVector3();
    Vector3 B = (s2 * Q1 - s1 * Q2) / div;
    B.SetNormalize();
    Vector3 T = (t2 * Q1 - t1 * Q2) / div;
    T.SetNormalize();
    if (bumpmap_ && shading_mode_ == kPhong)
    {
        bumpmap_width = bumpmap_->get_width();
        bumpmap_height = bumpmap_->get_height();
    }

    // floor v1.position.y
    for (; y < min_t((int)v1.position.y, height_); ++y)
    {
        int x = (int)x_begin;
        float done_over_z = (one_over_z_begin - one_over_z_end) / (x_begin - x_end);
        float one_over_z = one_over_z_begin;
        Vector4 dc = (color_begin - color_end) / (x_begin - x_end);
        Vector4 c = color_begin;
        Vector2 duv_over_z = (uv_over_z_begin - uv_over_z_end) / (x_begin - x_end);
        Vector2 uv_over_z = uv_over_z_begin;
        Vector2 duv = (uv_begin - uv_end) / (x_begin - x_end);
        Vector2 uv = uv_begin;
        Vector3 dnormal = (normal_begin - normal_end) / (x_begin - x_end);
        Vector3 normal = normal_begin;
        Vector3 dpos = (pos_begin - pos_end) / (x_begin - x_end);
        Vector3 pos = pos_begin;
        if (x_begin < 0)
        {
            one_over_z += done_over_z * (-x_begin);
            c += dc * (-x_begin);
            uv_over_z += duv_over_z * (-x_begin);
            uv += duv * (-x_begin);
            normal += dnormal * (-x_begin);
            pos += dpos * (-x_begin);
            x = 0;
        }

        // floor x_end
        for (; x < min_t((int)(x_end), width_); ++x,
                                              one_over_z += done_over_z,
                                              c += dc,
                                              uv += duv,
                                              uv_over_z += duv_over_z,
                                              normal += dnormal,
                                              pos += dpos)
        {
            // 1/z buffer 
            float prev_one_over_z = get_one_over_z_buffer(x, y);
            if (one_over_z < prev_one_over_z)
                continue;
            set_one_over_z_buffer(x, y, one_over_z);

            if (shading_mode_ == kPhong)
            {
                if (bumpmap_)
                {
                    int x = uv.x * (bumpmap_width - 3) + 1;
                    int y = uv.y * (bumpmap_height - 3) + 1;
//                    uint8 off_x = bumpmap_->GetDumpData(x + 1, y) - bumpmap_->GetDumpData(x - 1, y);
//                    uint8 off_y = bumpmap_->GetDumpData(x, y + 1) - bumpmap_->GetDumpData(y, y - 1);
//                    normal += (off_x / 255.0f) * B + (off_y / 255.0f) * T;
                }
                // Phong着色时,c每次重新计算
                c = Shading(pos, normal, *mat_, *light_);
            }

            Vector4 cvtex(1.0f, 1.0f, 1.0f, 1.0f);
            if (texture_)
            {
                Vector2 uv_ = uv;
                if (diff_perspective)
                {
                    uv_ = uv_over_z / one_over_z;
                }
                uv_.u = clamp(uv_.u, 0.0f, 1.0f);
                uv_.v = clamp(uv_.v, 0.0f, 1.0f);
                cvtex = texture_->GetDataUV(uv_.u, uv_.v);
            }
            uint32 cl = vector4_to_ARGB32(clamp(c * cvtex, 0.0f, 1.0f));
            set_pixel(x, y, cl);
        }
        x_begin += dx_left;
        x_end += dx_right;
        one_over_z_begin += done_over_z_left;
        one_over_z_end += done_over_z_right;
        color_begin += dc_left;
        color_end += dc_right;
        uv_over_z_begin += duv_over_z_left;
        uv_over_z_end += duv_over_z_right;
        uv_begin += duv_left;
        uv_end += duv_right;
        normal_begin += dnormal_left;
        normal_end += dnormal_right;
        pos_begin += dpos_left;
        pos_end += dpos_right;
    }
}
Exemplo n.º 4
0
// rend_primitive 相机空间
void Renderer::ModelViewTransform(const Matrix44 &model_view)
{
    Matrix33 normal_trans = model_view.GetMatrix33();
    normal_trans.SetInverse();
    normal_trans.SetTranspose();

    // 转换灯光位置
    if (light_)
    {
        Vector4 pl;
        pl.SetVector3(light_->position);
        pl.w = 1.0f;
        pl = pl * model_view;
        light_pos_ = pl.GetVector3();
    }

#if 0
    for (int i = 0; i < rend_primitive_.size; ++i)
    {
        if (((i + 1) % 3) == 0)
        {
            Vector3 p0 = rend_primitive_.vertexs[i - 2].position.GetVector3();
            Vector3 p1 = rend_primitive_.vertexs[i - 1].position.GetVector3();
            Vector3 p2 = rend_primitive_.vertexs[i].position.GetVector3();

            Vector3 e0 = p0 - p1;
            Vector3 e1 = p1 - p2;

            Vector3 n = rend_primitive_.vertexs[i-1].normal;
            float dot = DotProduct(e0, n);
//            Logger::GtLogInfo("before:0\t%f", dot);
            assert(equalf(dot, 0, 0.001));
            dot = DotProduct(e1, n);
//            Logger::GtLogInfo("before:1\t%f", dot);
            assert(equalf(dot, 0, 0.001));
        }
    }
#endif

    for (int i = 0; i < rend_primitive_.size; ++i)
    {
        Vector4 &position = rend_primitive_.vertexs[i].position;
        position = position * model_view;
        Vector3 &normal = rend_primitive_.vertexs[i].normal;
        normal = normal * normal_trans;
        normal.SetNormalize();
    }

#if 0
    for (int i = 0; i < rend_primitive_.size; ++i)
    {
        if (((i + 1) % 3) == 0)
        {
            Vector4 p0 = rend_primitive_.vertexs[i - 2].position;
            Vector4 p1 = rend_primitive_.vertexs[i - 1].position;
            Vector4 p2 = rend_primitive_.vertexs[i].position;

            Vector3 e0 = (p0 - p1).GetVector3();
            Vector3 e1 = (p1 - p2).GetVector3();

            Vector3 N = CrossProduct(e0, e1);
            N.SetNormalize();

            float dot = DotProduct(N, e0);
            Logger::GtLogInfo("dot e0 \t%f", dot);
            dot = DotProduct(N, e1);
            Logger::GtLogInfo("dot e1 \t%f", dot);

            Vector3 n0 = rend_primitive_.vertexs[i - 2].normal;
            Vector3 n1 = rend_primitive_.vertexs[i - 1].normal;
            Vector3 n2 = rend_primitive_.vertexs[i].normal;
            Vector3 zero = CrossProduct(N, n1);
            zero.Display();

            dot = DotProduct(e0, n0);
            Logger::GtLogInfo("after:0\t%f", dot);
            dot = DotProduct(e1, n0);
            Logger::GtLogInfo("after:1\t%f", dot);
        }
    }
#endif
}