Exemplo n.º 1
0
void renProjectTriangle(S_Renderer *pRenderer, S_Model *pModel, int i)
{
    S_Coords    aa, bb, cc;             /* souradnice vrcholu po transformaci */
    S_Coords    naa, nbb, ncc;          /* normaly ve vrcholech po transformaci */
    S_Coords    nn;                     /* normala trojuhelniku po transformaci */
    int         u1, v1, u2, v2, u3, v3; /* souradnice vrcholu po projekci do roviny obrazovky */
    S_Triangle  * triangle;

    IZG_ASSERT(pRenderer && pModel && i >= 0 && i < trivecSize(pModel->triangles));

    /* z modelu si vytahneme trojuhelnik */
    triangle = trivecGetPtr(pModel->triangles, i);

    /* transformace vrcholu matici model */
    trTransformVertex(&aa, cvecGetPtr(pModel->vertices, triangle->v[0]));
    trTransformVertex(&bb, cvecGetPtr(pModel->vertices, triangle->v[1]));
    trTransformVertex(&cc, cvecGetPtr(pModel->vertices, triangle->v[2]));

    /* promitneme vrcholy trojuhelniku na obrazovku */
    trProjectVertex(&u1, &v1, &aa);
    trProjectVertex(&u2, &v2, &bb);
    trProjectVertex(&u3, &v3, &cc);

    /* pro osvetlovaci model transformujeme take normaly ve vrcholech */
    trTransformVector(&naa, cvecGetPtr(pModel->normals, triangle->v[0]));
    trTransformVector(&nbb, cvecGetPtr(pModel->normals, triangle->v[1]));
    trTransformVector(&ncc, cvecGetPtr(pModel->normals, triangle->v[2]));

    /* normalizace normal */
    coordsNormalize(&naa);
    coordsNormalize(&nbb);
    coordsNormalize(&ncc);

    /* transformace normaly trojuhelniku matici model */
    trTransformVector(&nn, cvecGetPtr(pModel->trinormals, triangle->n));
    
    /* normalizace normaly */
    coordsNormalize(&nn);

    /* je troj. privraceny ke kamere, tudiz viditelny? */
    if( !renCalcVisibility(pRenderer, &aa, &nn) )
    {
        /* odvracene troj. vubec nekreslime */
        return;
    }

    /* rasterizace trojuhelniku */
    renDrawTriangle(pRenderer,
                    &aa, &bb, &cc,
                    &naa, &nbb, &ncc,
                    u1, v1, u2, v2, u3, v3
                    );
}
Exemplo n.º 2
0
int renCalcVisibility(S_Renderer *pRenderer, const S_Coords *point, const S_Coords *normal)
{
    S_Coords cvec;

    IZG_ASSERT(pRenderer && point && normal);

    /* vektor od kamery k plosce, pozice kamery je (0, 0, -camera_dist) */
    cvec = makeCoords(point->x, point->y, point->z + pRenderer->camera_dist);
    coordsNormalize(&cvec);

    /* test zda je normala privracena
     * skalarni soucin vektoru od kamery a normaly */
    return (normal->x * cvec.x + normal->y * cvec.y + normal->z * cvec.z > 0) ? 0 : 1;
}
Exemplo n.º 3
0
S_RGBA renLambertianReflectance(S_Renderer *pRenderer, const S_Coords *point, const S_Coords *normal)
{
    S_Coords    lvec;
    double      diffuse, r, g, b;
    S_RGBA      color;

    IZG_ASSERT(pRenderer && point && normal);

    /* vektor ke zdroji svetla */
    lvec = makeCoords(pRenderer->light_position.x - point->x,
                      pRenderer->light_position.y - point->y,
                      pRenderer->light_position.z - point->z);
    coordsNormalize(&lvec);

    /* ambientni cast */
    r = pRenderer->light_ambient.red * pRenderer->mat_ambient.red;
    g = pRenderer->light_ambient.green * pRenderer->mat_ambient.green;
    b = pRenderer->light_ambient.blue * pRenderer->mat_ambient.blue;

    /* difuzni cast */
    diffuse = lvec.x * normal->x + lvec.y * normal->y + lvec.z * normal->z;
    if( diffuse > 0 )
    {
        r += diffuse * pRenderer->light_diffuse.red * pRenderer->mat_diffuse.red;
        g += diffuse * pRenderer->light_diffuse.green * pRenderer->mat_diffuse.green;
        b += diffuse * pRenderer->light_diffuse.blue * pRenderer->mat_diffuse.blue;
    }
    
    /* saturace osvetleni*/
    r = MIN(1, r);
    g = MIN(1, g);
    b = MIN(1, b);

    /* kreslici barva */
    color.red = ROUND2BYTE(255 * r);
    color.green = ROUND2BYTE(255 * g);
    color.blue = ROUND2BYTE(255 * b);
    return color;
}
Exemplo n.º 4
0
void studrenProjectTriangle(S_Renderer *pRenderer, S_Model *pModel, int i, float n)
{
    S_Coords    aa, bb, cc;             /* souradnice vrcholu po transformaci */
    S_Coords    naa, nbb, ncc;          /* normaly ve vrcholech po transformaci */
    S_Coords    nn;                     /* normala trojuhelniku po transformaci */
    int         u1, v1, u2, v2, u3, v3; /* souradnice vrcholu po projekci do roviny obrazovky */
    S_Triangle  * triangle;
    int         vertexOffset, normalOffset; /* offset pro vrcholy a normalove vektory trojuhelniku */
    int         i0, i1, i2, in;             /* indexy vrcholu a normaly pro i-ty trojuhelnik n-teho snimku */
    S_Coords    aa1, bb1, cc1;             /* souradnice vrcholu po transformaci */
    S_Coords    naa1, nbb1, ncc1;          /* normaly ve vrcholech po transformaci */
    S_Coords    nn1;                     /* normala trojuhelniku po transformaci */
    int vertexOffset1, normalOffset1;
    int i01, i11, i21, in1;				/* indexy vrcholu a normaly pro i-ty trojuhelnik (n+1)-teho snimku */
    IZG_ASSERT(pRenderer && pModel && i >= 0 && i < trivecSize(pModel->triangles) && n >= 0 );

    int N = (int) floor(n);
    float xN = n - floor(n);

    /* z modelu si vytahneme i-ty trojuhelnik */
    triangle = trivecGetPtr(pModel->triangles, i);

    /* ziskame offset pro vrcholy n-teho snimku */
    vertexOffset = (N % pModel->frames) * pModel->verticesPerFrame;
    vertexOffset1 = ((N + 1) % pModel->frames) * pModel->verticesPerFrame;
    /* ziskame offset pro normaly trojuhelniku n-teho snimku */
    normalOffset = (N % pModel->frames) * pModel->triangles->size;
    normalOffset1 = ((N + 1) % pModel->frames) * pModel->triangles->size;

    /* indexy vrcholu pro i-ty trojuhelnik n-teho snimku - pricteni offsetu */
    i0 = triangle->v[ 0 ] + vertexOffset;
    i1 = triangle->v[ 1 ] + vertexOffset;
    i2 = triangle->v[ 2 ] + vertexOffset;

    i01 = triangle->v[ 0 ] + vertexOffset1;
	i11 = triangle->v[ 1 ] + vertexOffset1;
	i21 = triangle->v[ 2 ] + vertexOffset1;

    /* index normaloveho vektoru pro i-ty trojuhelnik n-teho snimku - pricteni offsetu */
    in = triangle->n + normalOffset;
    in1 = triangle->n + normalOffset1;

    /* transformace vrcholu matici model */
    trTransformVertex(&aa, cvecGetPtr(pModel->vertices, i0));
    trTransformVertex(&bb, cvecGetPtr(pModel->vertices, i1));
    trTransformVertex(&cc, cvecGetPtr(pModel->vertices, i2));
    trTransformVertex(&aa1, cvecGetPtr(pModel->vertices, i01));
	trTransformVertex(&bb1, cvecGetPtr(pModel->vertices, i11));
	trTransformVertex(&cc1, cvecGetPtr(pModel->vertices, i21));

	/* Interpolace vrcholu*/
	aa.x = (1 - xN) * aa.x + xN * aa1.x;
	aa.y = (1 - xN) * aa.y + xN * aa1.y;
	aa.z = (1 - xN) * aa.z + xN * aa1.z;

	bb.x = (1 - xN) * bb.x + xN * bb1.x;
	bb.y = (1 - xN) * bb.y + xN * bb1.y;
	bb.z = (1 - xN) * bb.z + xN * bb1.z;

	cc.x = (1 - xN) * cc.x + xN * cc1.x;
	cc.y = (1 - xN) * cc.y + xN * cc1.y;
	cc.z = (1 - xN) * cc.z + xN * cc1.z;

    /* promitneme vrcholy trojuhelniku na obrazovku */
    double h0 = trProjectVertex(&u1, &v1, &aa);
    double h1 = trProjectVertex(&u2, &v2, &bb);
    double h2 = trProjectVertex(&u3, &v3, &cc);

    /* pro osvetlovaci model transformujeme take normaly ve vrcholech */
    trTransformVector(&naa, cvecGetPtr(pModel->normals, i0));
    trTransformVector(&nbb, cvecGetPtr(pModel->normals, i1));
    trTransformVector(&ncc, cvecGetPtr(pModel->normals, i2));
    trTransformVector(&naa1, cvecGetPtr(pModel->normals, i01));
	trTransformVector(&nbb1, cvecGetPtr(pModel->normals, i11));
	trTransformVector(&ncc1, cvecGetPtr(pModel->normals, i21));

	/* Interpolace normal */
	naa.x = (1 - xN) * naa.x + xN * naa1.x;
	naa.y = (1 - xN) * naa.y + xN * naa1.y;
	naa.z = (1 - xN) * naa.z + xN * naa1.z;

	nbb.x = (1 - xN) * nbb.x + xN * nbb1.x;
	nbb.y = (1 - xN) * nbb.y + xN * nbb1.y;
	nbb.z = (1 - xN) * nbb.z + xN * nbb1.z;

	ncc.x = (1 - xN) * ncc.x + xN * ncc1.x;
	ncc.y = (1 - xN) * ncc.y + xN * ncc1.y;
	ncc.z = (1 - xN) * ncc.z + xN * ncc1.z;

    /* normalizace normal */
    coordsNormalize(&naa);
    coordsNormalize(&nbb);
    coordsNormalize(&ncc);

    /* transformace normaly trojuhelniku matici model */
    trTransformVector(&nn, cvecGetPtr(pModel->trinormals, in));
    trTransformVector(&nn1, cvecGetPtr(pModel->trinormals, in1));

    /* Interpolace normaly */
    nn.x = (1 - xN) * nn.x + xN * nn1.x;
    nn.y = (1 - xN) * nn.y + xN * nn1.y;
    nn.z = (1 - xN) * nn.z + xN * nn1.z;


    /* normalizace normaly */
    coordsNormalize(&nn);

    /* je troj. privraceny ke kamere, tudiz viditelny? */
    if( !renCalcVisibility(pRenderer, &aa, &nn) )
    {
        /* odvracene troj. vubec nekreslime */
        return;
    }
    S_Triangle *texture = trivecGetPtr(pModel->triangles, i);

    /* rasterizace trojuhelniku */
    studrenDrawTriangle(pRenderer,
                    &aa, &bb, &cc,
                    &naa, &nbb, &ncc,
					&triangle->t[0], &triangle->t[1], &triangle->t[2],
                    u1, v1, u2, v2, u3, v3,
					h0, h1, h2
                    );
}
Exemplo n.º 5
0
S_RGBA studrenPhongReflectance(S_Renderer *pRenderer, const S_Coords *point, const S_Coords *normal)
{
    S_Coords    lvec, eyevec, reflect;
    double      diffuse, specular, reflect_scalar;
    double      r, g, b;

    /* If = Ia + Id + Is */
    S_RGBA      color;

    IZG_ASSERT(pRenderer && point && normal);

    /* vektor ke zdroji svetla */
    lvec = makeCoords(pRenderer->light_position.x - point->x,
                      pRenderer->light_position.y - point->y,
                      pRenderer->light_position.z - point->z);
    coordsNormalize(&lvec);

    /* vektor ke kamere */
    eyevec = makeCoords(-point->x,
                        -point->y,
                        -pRenderer->camera_dist - point->z);
    coordsNormalize(&eyevec);

    /* ambientni cast -- Ia = (Al * Am) + (As * Am) */
    /* As je barva sceny, muzeme zanedbat */
    r = pRenderer->light_ambient.red * pRenderer->mat_ambient.red;
    g = pRenderer->light_ambient.green * pRenderer->mat_ambient.green;
    b = pRenderer->light_ambient.blue * pRenderer->mat_ambient.blue;

    /* difuzni cast -- Id = Dl * Dm * LambertTerm */
    /* LambertTerm = dot(N, L) */
    diffuse = lvec.x * normal->x + lvec.y * normal->y + lvec.z * normal->z;
    if( diffuse > 0 )
    {
        r += diffuse * pRenderer->light_diffuse.red * pRenderer->mat_diffuse.red;
        g += diffuse * pRenderer->light_diffuse.green * pRenderer->mat_diffuse.green;
        b += diffuse * pRenderer->light_diffuse.blue * pRenderer->mat_diffuse.blue;
    }

    /* odraziva cast -- Is = Sm * Sl * pow( max( dot(R, E), 0.0), f ) */
    /* R = reflect(-L, N) = 2 * dot(N, L) * N - L */
    reflect_scalar = 2 * (normal->x * lvec.x + normal->y * lvec.y + normal->z * lvec.z);
    reflect.x = reflect_scalar * normal->x - lvec.x;
    reflect.y = reflect_scalar * normal->y - lvec.y;
    reflect.z = reflect_scalar * normal->z - lvec.z;

    specular = pow(
        MAX(reflect.x * eyevec.x + reflect.y * eyevec.y + reflect.z * eyevec.z, 0.0f),
        ((S_StudentRenderer*)pRenderer)->mat_shininess);

    r += specular * pRenderer->light_specular.red * pRenderer->mat_specular.red;
    g += specular * pRenderer->light_specular.green * pRenderer->mat_specular.green;
    b += specular * pRenderer->light_specular.blue * pRenderer->mat_specular.blue;

    /* saturace osvetleni*/
    r = MIN(1, r);
    g = MIN(1, g);
    b = MIN(1, b);

    /* kreslici barva */
    color.red = ROUND2BYTE(255 * r);
    color.green = ROUND2BYTE(255 * g);
    color.blue = ROUND2BYTE(255 * b);
    return color;
}
Exemplo n.º 6
0
void studrenDrawTriangle(S_Renderer *pRenderer,
                         S_Coords *v1, S_Coords *v2, S_Coords *v3,
                         S_Coords *n1, S_Coords *n2, S_Coords *n3,
                         int x1, int y1,
                         int x2, int y2,
                         int x3, int y3
                         )
{
    // oblast trojuhelniku
    int min[2] = {
        MIN(x1, MIN(x2, x3)),
        MIN(y1, MIN(y2, y3))
    };
    int max[2] = {
        MAX(x1, MAX(x2, x3)),
        MAX(y1, MAX(y2, y3))
    };

    // oriznuti rozmerem okna
    min[0] = MAX(min[0], 0);
    min[1] = MAX(min[1], 0);
    max[0] = MIN(max[0], pRenderer->frame_w - 1);
    max[1] = MIN(max[1], pRenderer->frame_h - 1);

    // pro urceni hranic trojuhelnika pouzijeme pineduv algoritmus
    // hranova funkce je rovnice Ax + By + C = 0
    // A,B je normalovy vektor primky, tzn. (-dy, dx)
    // C vyjadrime jako x1y2 - x2y1
    int A[3] = {
        { y1 - y2 },
        { y2 - y3 },
        { y3 - y1 }
    };
    int B[3] = {
        { x2 - x1 },
        { x3 - x2 },
        { x1 - x3 }
    };
    int C[3] = {
        { x1 * y2 - x2 * y1 },
        { x2 * y3 - x3 * y2 },
        { x3 * y1 - x1 * y3 }
    };

    // do hranove funkce dosadime protejsi vrcholy
    // provedeme normalizaci, aby kladna strana byla uvnitr oblasti
    int s0 = A[0] * x3 + B[0] * y3 + C[0];
    int s1 = A[1] * x1 + B[1] * y1 + C[1];
    int s2 = A[2] * x2 + B[2] * y2 + C[2];

    if (s0 < 0) {
        A[0] *= -1; B[0] *= -1; C[0] *= -1;
        s0 *= -1;
    }
    if (s1 < 0) {
        A[1] *= -1; B[1] *= -1; C[1] *= -1;
        s1 *= -1;
    }
    if (s2 < 0) {
        A[2] *= -1; B[2] *= -1; C[2] *= -1;
        s2 *= -1;
    }

    double _s0 = 1.0f / (double)s0;
    double _s1 = 1.0f / (double)s1;
    double _s2 = 1.0f / (double)s2;

    /* gourandovo stinovani */
    //S_RGBA color, b1, b2, b3;
    //b1 = pRenderer->calcReflectanceFunc(pRenderer, v1, n1);
    //b2 = pRenderer->calcReflectanceFunc(pRenderer, v2, n2);
    //b3 = pRenderer->calcReflectanceFunc(pRenderer, v3, n3);

    // vyplnovani pinedovim algoritmem
    for (int y = min[1]; y <= max[1]; ++y) {
        int e[3] = {
            A[0] * min[0] + B[0] * y + C[0],
            A[1] * min[0] + B[1] * y + C[1],
            A[2] * min[0] + B[2] * y + C[2]
        };

        for (int x = min[0]; x <= max[0]; ++x) {
            // uvnitr trojuhelniku jsou cisla kladna
            if (e[0] >= 0 && e[1] >= 0 && e[2] >= 0) {

                // spocitame barycentricke koeficienty u,v,w
                double u = e[1] * _s1;
                double v = e[2] * _s2;
                double w = e[0] * _s0;

                // nemelo by nastat, protoze jsme uvnitr trojuhelniku
                //if (u < 0.0f || u > 1.0f) continue;
                //if (v < 0.0f || v > 1.0f) continue;
                //if (w < 0.0f || w > 1.0f) continue;

                // bod v trojuhelniku pred projekci ve 3D
                S_Coords pt = makeCoords(
                    u * v1->x + v * v2->x + w * v3->x,
                    u * v1->y + v * v2->y + w * v3->y,
                    u * v1->z + v * v2->z + w * v3->z);

                /* gourandovo stinovani */
                //double r = u * b1.red   + v * b2.red   + w * b3.red;
                //double g = u * b1.green + v * b2.green + w * b3.green;
                //double b = u * b1.blue  + v * b2.blue  + w * b3.blue;
                //double a = u * b1.alpha + v * b2.alpha + w * b3.alpha;

                //r = MIN(255.0f, MAX(r, 0.0f));
                //g = MIN(255.0f, MAX(g, 0.0f));
                //b = MIN(255.0f, MAX(b, 0.0f));
                //a = MIN(255.0f, MAX(a, 0.0f));

                //color.red   = ROUND2BYTE(r);
                //color.green = ROUND2BYTE(g);
                //color.blue  = ROUND2BYTE(b);
                //color.alpha = ROUND2BYTE(a);

                // vektor smerujici od bodu ke kamere
                S_Coords P_Cam = makeCoords(
                    -pt.x,
                    -pt.y,
                    -pRenderer->camera_dist - pt.z);

                // vykreslime jen blizsi body
                double depth = sqrt(P_Cam.x * P_Cam.x + P_Cam.y * P_Cam.y + P_Cam.z * P_Cam.z);
                if (depth <= DEPTH(pRenderer, x, y))
                {
                    // normala bodu
                    S_Coords n = makeCoords(
                        u * n1->x + v * n2->x + w * n3->x,
                        u * n1->y + v * n2->y + w * n3->y,
                        u * n1->z + v * n2->z + w * n3->z);
                    coordsNormalize(&n);

                    S_RGBA color;
                    color = pRenderer->calcReflectanceFunc(pRenderer, &pt, &n);

                    /* vybarvi objekt normalou */
                    //color.red = ROUND2BYTE(255.0f * (n.x / 2.0f + 0.5f));
                    //color.green = ROUND2BYTE(255.0f * (n.y / 2.0f + 0.5f));
                    //color.blue = ROUND2BYTE(255.0f * (-n.z / 2.0f + 0.5f));
                    //color.alpha = 255;

                    DEPTH(pRenderer, x, y) = depth;
                    PIXEL(pRenderer, x, y) = color;
                }
            }

            // Ei(x+1,y) = Ei(x,y) + dy
            e[0] += A[0];
            e[1] += A[1];
            e[2] += A[2];
        }
    }
}