Beispiel #1
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
                         )
{
    /* zaklad fce zkopirujte z render.c */
    /* ??? */
    int         minx, miny, maxx, maxy;
    int         a1, a2, a3, b1, b2, b3, c1, c2, c3;
    int         /*s1,*/ s2, s3;
    int         x, y, e1, e2, e3;
    double      alpha, beta, w1, w2, w3, z;
    S_RGBA      col1, col2, col3, color;
    S_StudentRenderer * renderer;
    S_Frag * tmpFrag;
    int next = 0;
    int i = 0;

    IZG_ASSERT(pRenderer && v1 && v2 && v3 && n1 && n2 && n3);
    renderer = (S_StudentRenderer *)pRenderer;

    /* vypocet barev ve vrcholech */
    col1 = pRenderer->calcReflectanceFunc(pRenderer, v1, n1);
    col2 = pRenderer->calcReflectanceFunc(pRenderer, v2, n2);
    col3 = pRenderer->calcReflectanceFunc(pRenderer, v3, n3);

    /* obalka trojuhleniku */
    minx = MIN(x1, MIN(x2, x3));
    maxx = MAX(x1, MAX(x2, x3));
    miny = MIN(y1, MIN(y2, y3));
    maxy = MAX(y1, MAX(y2, y3));

    /* oriznuti podle rozmeru okna */
    miny = MAX(miny, 0);
    maxy = MIN(maxy, pRenderer->frame_h - 1);
    minx = MAX(minx, 0);
    maxx = MIN(maxx, pRenderer->frame_w - 1);

    /* vektory urcene vrcholy 1-2 a 1-3 */
    a1 = x2 - x1;
    a3 = x3 - x1;
    b1 = y2 - y1;
    b3 = y3 - y1;

    /* overeni counterclockwise orientace troj. pomoci vektoroveho soucinu */
    if( (a1 * b3 - b1 * a3) < 0 )
    {
        /* spatna orientace -> prohodime vrcholy 2 a 3 */
        SWAP(x2, x3);
        SWAP(y2, y3);

        /* a take barvy vrcholu */
        SWAP(col2.red, col3.red);
        SWAP(col2.green, col3.green);
        SWAP(col2.blue, col3.blue);
        SWAP(col2.alpha, col3.alpha);
    }

    /* Pineduv alg. rasterizace troj.
       hranova fce je obecna rovnice primky Ax + By + C = 0
       primku prochazejici body (x1, y1) a (x2, y2) urcime jako
       (y1 - y2)x + (x2 - x1)y + x1y2 - x2y1 = 0 */

    /* normala primek - vektor kolmy k vektoru mezi dvema vrcholy, tedy (-dy, dx) */
    a1 = y1 - y2;
    a2 = y2 - y3;
    a3 = y3 - y1;
    b1 = x2 - x1;
    b2 = x3 - x2;
    b3 = x1 - x3;

    /* koeficient C */
    c1 = x1 * y2 - x2 * y1;
    c2 = x2 * y3 - x3 * y2;
    c3 = x3 * y1 - x1 * y3;

    /* vypocet hranove fce (vzdalenost od primky) pro protejsi body */
    /*s1 = a1 * x3 + b1 * y3 + c1;*/
    s2 = a2 * x1 + b2 * y1 + c2;
    s3 = a3 * x2 + b3 * y2 + c3;

    /* uprava koeficientu C pro korektni vyplnovani, viz "OpenGL top-left rule" */
    /* https://books.google.cz/books?id=3ljRBQAAQBAJ&pg=PA73 */
    if( (y1 == y2 && x2 > x1) || y2 < y1 )
    {
        c1 -= 1;
    }
    if( (y2 == y3 && x3 > x2) || y3 < y2 )
    {
        c2 -= 1;
    }
    if( (y3 == y1 && x1 > x3) || y1 < y3 )
    {
        c3 -= 1;
    }

    /* koeficienty pro barycentricke souradnice */
    alpha = 1.0 / (ABS(s2) + 1);
    beta = 1.0 / (ABS(s3) + 1);

    /* vyplnovani... */
    for( y = miny; y <= maxy; ++y )
    {
        /* inicilizace hranove fce v bode (minx, y) */
        e1 = a1 * minx + b1 * y + c1;
        e2 = a2 * minx + b2 * y + c2;
        e3 = a3 * minx + b3 * y + c3;

        for( x = minx; x <= maxx; ++x )
        {
            if( e1 >= 0 && e2 >= 0 && e3 >= 0 )
            {
                /* interpolace pomoci barycentrickych souradnic
                   e1, e2, e3 je aktualni vzdalenost bodu (x, y) od primek */
                w1 = alpha * e2;
                w2 = beta * e3;
                w3 = 1.0 - w1 - w2;

                /* interpolace z-souradnice */
                z = w1 * v1->z + w2 * v2->z + w3 * v3->z;

                /* interpolace barvy */
                color.red = ROUND2BYTE(w1 * col1.red + w2 * col2.red + w3 * col3.red);
                color.green = ROUND2BYTE(w1 * col1.green + w2 * col2.green + w3 * col3.green);
                color.blue = ROUND2BYTE(w1 * col1.blue + w2 * col2.blue + w3 * col3.blue);
                color.alpha = ROUND2BYTE(w1 * col1.alpha + w2 * col2.alpha + w3 * col3.alpha);

                // vykresleni bodu
                i = y * pRenderer->frame_w + x;
                next = renderer->hBuffer[i];

                if (next == -1) renderer->hBuffer[i] = fragvecPushBack(renderer->nBuffer, makeFrag(color, z, -1));
                else if(fragvecGetPtr(renderer->nBuffer, next)->depth > z) renderer->hBuffer[i] = fragvecPushBack(renderer->nBuffer, makeFrag(color, z, next));
                else
                {
                    // razeni fragmetu
                    tmpFrag = fragvecGetPtr(renderer->nBuffer, next);
                    while (tmpFrag->depth > z) tmpFrag = fragvecGetPtr(renderer->nBuffer, tmpFrag->next);
                    fragvecGetPtr(renderer->nBuffer, next)->next = fragvecPushBack(renderer->nBuffer, makeFrag(color, z, tmpFrag->next));
                }
            }

            /* hranova fce o pixel vedle */
            e1 += a1;
            e2 += a2;
            e3 += a3;
        }
    }
}
Beispiel #2
0
void renderStudentScene(S_Renderer *pRenderer, S_Model *pModel)
{
    S_StudentRenderer * renderer = (S_StudentRenderer *) pRenderer;
    S_Frag * frag;
    S_RGBA resultColor;
    int x = 0;
    int y = 0;
    int i = 0;
    double transparency = 0.0;

    /* test existence frame bufferu a modelu */
    IZG_ASSERT(pModel && pRenderer);

    /* nastavit projekcni matici */
    trProjectionPerspective(pRenderer->camera_dist, pRenderer->frame_w, pRenderer->frame_h);

    /* vycistit model matici */
    trLoadIdentity();

    /* nejprve nastavime posuv cele sceny od/ke kamere */
    trTranslate(0.0, 0.0, pRenderer->scene_move_z);

    /* nejprve nastavime posuv cele sceny v rovine XY */
    trTranslate(pRenderer->scene_move_x, pRenderer->scene_move_y, 0.0);

    /* natoceni cele sceny - jen ve dvou smerech - mys je jen 2D... :( */
    trRotateX(pRenderer->scene_rot_x);
    trRotateY(pRenderer->scene_rot_y);

    ///////////////////////////////// cerveny kralik ///////////////////////////////////
    /* nastavime material */
    renMatAmbient(pRenderer, &MAT_RED_AMBIENT);
    renMatDiffuse(pRenderer, &MAT_RED_DIFFUSE);
    renMatSpecular(pRenderer, &MAT_RED_SPECULAR);

    /* nejprve nastavime posuv cele sceny v rovine XY */
    trTranslate(pRenderer->scene_move_x - 1.2, pRenderer->scene_move_y, 0.0);

    /* a vykreslime nas model */
    renderModel(pRenderer, pModel);

    ///////////////////////////////// zeleny kralik ///////////////////////////////////
    /* nastavime material */
    renMatAmbient(pRenderer, &MAT_STUD_AMBIENT);
    renMatDiffuse(pRenderer, &MAT_STUD_DIFFUSE);
    renMatSpecular(pRenderer, &MAT_STUD_SPECULAR);
	
    /* nejprve nastavime posuv cele sceny v rovine XY */
    trTranslate(pRenderer->scene_move_x + 2.4, pRenderer->scene_move_y, 0.0);

    /* a vykreslime nas model */
    renderModel(pRenderer, pModel);
    ///////////////////////////////////////////////////////////////////////////////////

    // vypocet barvy a jeji vykresleni
    for(x = 0; x < pRenderer->frame_h; x++)
    {
        for(y = 0; y < pRenderer->frame_w; y++)
        {
            // inicializace
            transparency = 1.0;
            resultColor.red = 0;
            resultColor.green = 0;
            resultColor.blue = 0;
            resultColor.alpha = 0;

            i = renderer->hBuffer[y * pRenderer->frame_w + x];
            if(i < 0) resultColor = COLOR_BLACK;

            // vypocet smichane barvy
            while(i >= 0)
            {
                frag = fragvecGetPtr(renderer->nBuffer, i);
                resultColor.blue += transparency * frag->color.blue;
                resultColor.red += transparency * frag->color.red;
                resultColor.green += transparency * frag->color.green;
                transparency *= (1.0 - (frag->color.alpha / 255.0));
                i = frag->next;
            }

            // vykresleni vypocteneho pixelu
            PIXEL(pRenderer, x, y) = resultColor;
        }
    }
}
Beispiel #3
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
                         )
{

	S_StudentRenderer   * renderer;

	/* ukazatel na studentsky renderer */
	renderer = (S_StudentRenderer *)pRenderer;

	int         minx, miny, maxx, maxy;
	int         a1, a2, a3, b1, b2, b3, c1, c2, c3;
	int         /*s1,*/ s2, s3;
	int         x, y, e1, e2, e3;
	double      alpha, beta, w1, w2, w3, z;
	S_RGBA      col1, col2, col3, color;

	IZG_ASSERT(pRenderer && v1 && v2 && v3 && n1 && n2 && n3);

	/* vypocet barev ve vrcholech */
	col1 = pRenderer->calcReflectanceFunc(pRenderer, v1, n1);
	col2 = pRenderer->calcReflectanceFunc(pRenderer, v2, n2);
	col3 = pRenderer->calcReflectanceFunc(pRenderer, v3, n3);

	/* obalka trojuhleniku */
	minx = MIN(x1, MIN(x2, x3));
	maxx = MAX(x1, MAX(x2, x3));
	miny = MIN(y1, MIN(y2, y3));
	maxy = MAX(y1, MAX(y2, y3));

	/* oriznuti podle rozmeru okna */
	miny = MAX(miny, 0);
	maxy = MIN(maxy, pRenderer->frame_h - 1);
	minx = MAX(minx, 0);
	maxx = MIN(maxx, pRenderer->frame_w - 1);

	/* vektory urcene vrcholy 1-2 a 1-3 */
	a1 = x2 - x1;
	a3 = x3 - x1;
	b1 = y2 - y1;
	b3 = y3 - y1;

	/* overeni counterclockwise orientace troj. pomoci vektoroveho soucinu */
	if ((a1 * b3 - b1 * a3) < 0)
	{
		/* spatna orientace -> prohodime vrcholy 2 a 3 */
		SWAP(x2, x3);
		SWAP(y2, y3);

		/* a take barvy vrcholu */
		SWAP(col2.red, col3.red);
		SWAP(col2.green, col3.green);
		SWAP(col2.blue, col3.blue);
		SWAP(col2.alpha, col3.alpha);
	}

	/* Pineduv alg. rasterizace troj.
	hranova fce je obecna rovnice primky Ax + By + C = 0
	primku prochazejici body (x1, y1) a (x2, y2) urcime jako
	(y1 - y2)x + (x2 - x1)y + x1y2 - x2y1 = 0 */

	/* normala primek - vektor kolmy k vektoru mezi dvema vrcholy, tedy (-dy, dx) */
	a1 = y1 - y2;
	a2 = y2 - y3;
	a3 = y3 - y1;
	b1 = x2 - x1;
	b2 = x3 - x2;
	b3 = x1 - x3;

	/* koeficient C */
	c1 = x1 * y2 - x2 * y1;
	c2 = x2 * y3 - x3 * y2;
	c3 = x3 * y1 - x1 * y3;

	/* vypocet hranove fce (vzdalenost od primky) pro protejsi body */
	/*s1 = a1 * x3 + b1 * y3 + c1;*/
	s2 = a2 * x1 + b2 * y1 + c2;
	s3 = a3 * x2 + b3 * y2 + c3;

	/* uprava koeficientu C pro korektni vyplnovani, viz "OpenGL top-left rule" */
	/* https://books.google.cz/books?id=3ljRBQAAQBAJ&pg=PA73 */
	if ((y1 == y2 && x2 > x1) || y2 < y1)
	{
		c1 -= 1;
	}
	if ((y2 == y3 && x3 > x2) || y3 < y2)
	{
		c2 -= 1;
	}
	if ((y3 == y1 && x1 > x3) || y1 < y3)
	{
		c3 -= 1;
	}

	// moje deklarace
	int * index;
	S_Frag tmp_frag;

	/* koeficienty pro barycentricke souradnice */
	alpha = 1.0 / (ABS(s2) + 1);
	beta = 1.0 / (ABS(s3) + 1);

	/* vyplnovani... */
	for (y = miny; y <= maxy; ++y)
	{
		/* inicilizace hranove fce v bode (minx, y) */
		e1 = a1 * minx + b1 * y + c1;
		e2 = a2 * minx + b2 * y + c2;
		e3 = a3 * minx + b3 * y + c3;

		for (x = minx; x <= maxx; ++x)
		{
			if (e1 >= 0 && e2 >= 0 && e3 >= 0)
			{
				/* interpolace pomoci barycentrickych souradnic
				e1, e2, e3 je aktualni vzdalenost bodu (x, y) od primek */
				w1 = alpha * e2;
				w2 = beta * e3;
				w3 = 1.0 - w1 - w2;

				/* interpolace z-souradnice */
				z = w1 * v1->z + w2 * v2->z + w3 * v3->z;

				/* interpolace barvy */
				color.red = ROUND2BYTE(w1 * col1.red + w2 * col2.red + w3 * col3.red);
				color.green = ROUND2BYTE(w1 * col1.green + w2 * col2.green + w3 * col3.green);
				color.blue = ROUND2BYTE(w1 * col1.blue + w2 * col2.blue + w3 * col3.blue);
				color.alpha = ROUND2BYTE(w1 * col1.alpha + w2 * col2.alpha + w3 * col3.alpha);


				/* vykresleni bodu */
				if (z < DEPTH(pRenderer, x, y))
				{
					/*PIXEL(pRenderer, x, y) = color;
					DEPTH(pRenderer, x, y) = z;*/

					index = (int *)vecGetPtr(renderer->vecHeadBuff, y * renderer->base.frame_w + x);

					//tmp_index = *index;

					tmp_frag = makeFrag(color, z, *index);
					*index = fragvecPushBack(renderer->vecNodeBuff, tmp_frag);

					//printf("%d\n", fragvecGetPtr(renderer->vecNodeBuff, 0)->next);
				}
			}

			/* hranova fce o pixel vedle */
			e1 += a1;
			e2 += a2;
			e3 += a3;
		}
	}

	/* Razeni a pocitani vyslednych barev */
	// deklarace pro sorting
	int sortStart, sortIndex;
	int myDepth;

	// michani barev
	S_RGBA mixColor;
	double col_R, col_G, col_B, col_A;
	double aSrc;

	// pomocne fragmenty
	S_Frag * pattern;
	S_Frag myFragTMP;
	S_Frag * myFragment;

	// pruchod pro razeni
	for (y = miny; y <= maxy; ++y)
	{
		for (x = minx; x <= maxx; ++x)
		{
			// index byl deklarovan uz vyse
			index = (int *)(vecGetPtr(renderer->vecHeadBuff, y * renderer->base.frame_w + x));

			if (*index != -1)
			{
				sortStart = *index;
				
				/* K razeni je pouzit radici algoritmus Select Sort */
				while ((myFragment = fragvecGetPtr(renderer->vecNodeBuff, sortStart))->next != -1)
				{
					sortStart = myFragment->next;
					sortIndex = myFragment->next;

					// dokud se neprojde "pole" na sebe navazujicich(indexujicich) prvku
					while (sortIndex != -1)
					{
						pattern = fragvecGetPtr(renderer->vecNodeBuff, sortIndex);

						// dojde k prohozeni hodnot, najde-li se mensi hloubka
						if (pattern->depth < myFragment->depth)
						{
							myFragTMP.depth = myFragment->depth;
							myFragTMP.color = myFragment->color;
							myFragment->depth = pattern->depth;
							myFragment->color = pattern->color;
							pattern->depth = myFragTMP.depth;
							pattern->color = myFragTMP.color;
						}

						sortIndex = pattern->next;
					}
				}
			}
		}
	}

	// pruchod pro michani barev
	for (y = miny; y <= maxy; ++y)
	{
		for (x = minx; x <= maxx; ++x)
		{
			// index byl deklarovan uz vyse
			index = (int *)(vecGetPtr(renderer->vecHeadBuff, y * renderer->base.frame_w + x));

			if (*index != -1)
			{
				sortStart = *index;

				// michani barvy
				myDepth = 0;
				col_R = 0.0;
				col_G = 0.0;
				col_B = 0.0;
				col_A = 1.0;

				while (sortStart != -1)
				{
					pattern = fragvecGetPtr(renderer->vecNodeBuff, sortStart);

					aSrc = pattern->color.alpha / 255.0;

					col_R = col_A * pattern->color.red + col_R;
					col_G = col_A * pattern->color.green + col_G;
					col_B = col_A * pattern->color.blue + col_B;

					col_A = (1.0 - aSrc) * col_A;

					sortStart = pattern->next;
				}

				mixColor.alpha = 255;
				mixColor.red = ROUND2BYTE(col_R);
				mixColor.green = ROUND2BYTE(col_G);
				mixColor.blue = ROUND2BYTE(col_B);

				PIXEL(pRenderer, x, y) = mixColor;
				DEPTH(pRenderer, x, y) = myDepth;
			}
		}
	}
}