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; }
void studrenDrawTriangle(S_Renderer *pRenderer, S_Coords *v1, S_Coords *v2, S_Coords *v3, S_Coords *n1, S_Coords *n2, S_Coords *n3, S_Coords *t0, S_Coords *t1, S_Coords *t2, int x1, int y1, int x2, int y2, int x3, int y3, double h1, double h2, double h3 ) { 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, gamma, w1, w2, w3, z, u, v; 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); /* 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; if ( !s1 || !s2 || !s3 ) { return; } /* normalizace, aby vzdalenost od primky byla kladna uvnitr trojuhelniku */ if( s1 < 0 ) { a1 *= -1; b1 *= -1; c1 *= -1; } if( s2 < 0 ) { a2 *= -1; b2 *= -1; c2 *= -1; } if( s3 < 0 ) { a3 *= -1; b3 *= -1; c3 *= -1; } /* koeficienty pro barycentricke souradnice */ alpha = 1.0 / ABS(s2); beta = 1.0 / ABS(s3); gamma = 1.0 / ABS(s1); S_RGBA newColor; /* 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 = gamma * e1; /* interpolace z-souradnice */ z = w1 * v1->z + w2 * v2->z + w3 * v3->z; double jmenovatel = w1 / h1 + w2 / h2 + w3 / h3; u = (w1 * t0->x / h1) + (w2 * t1->x / h2) + (w3 * t2->x / h3); v = (w1 * t0->y / h1) + (w2 * t1->y / h2) + (w3 * t2->y / h3); u = u / jmenovatel; v = v / jmenovatel; newColor = studrenTextureValue((S_StudentRenderer *)pRenderer, u, v); /* interpolace barvy */ color.red = ROUND2BYTE(w1 * col1.red + w2 * col2.red + w3 * col3.red) * (newColor.red / 255.0); color.green = ROUND2BYTE(w1 * col1.green + w2 * col2.green + w3 * col3.green) * (newColor.green / 255.0); color.blue = ROUND2BYTE(w1 * col1.blue + w2 * col2.blue + w3 * col3.blue) * (newColor.blue / 255.0); color.alpha = 255; /* vykresleni bodu */ if( z < DEPTH(pRenderer, x, y) ) { PIXEL(pRenderer, x, y) = color; DEPTH(pRenderer, x, y) = z; } } /* hranova fce o pixel vedle */ e1 += a1; e2 += a2; e3 += a3; } } }
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; } } }
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; } } } }
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; }