1 / 83

RGB Color Models in Computer Graphics

Explore advanced RGB color models, color addition, modulation, and light modulation techniques in computer graphics. Learn about representation, operations, and visualization in this detailed guide.

donnaporter
Download Presentation

RGB Color Models in Computer Graphics

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lighting Models CIS 488/588 Bruce R. Maxim UM-Dearborn

  2. Lighting • Huge topic in computer graphics • Nearly all 3D rendering packages make use of ray tracing to determine the shadows and reflective surfaces in the screen images • Software-based graphics engines cannot support the same complex lighting models that hardware (e.g. pixel and vertex shaders)

  3. Color Models • Color can be represented using separate RGB values or using an index into a table • Some RGB models use integers 0-255 for each color and some use real numbers with values 0.0-1.0 for each • Float values are easier to work with mathematically, but integers can be faster for rendering since they can be written straight to the video buffer

  4. Color Addition • When adding two RGB integer colors you need to catch overflow problems C1 = (r1, g1, b1) C2 = (r2, g2, b2) C = C1 + C2 C = (max(r1 + r2, 255), max(r1 + r2, 255), max(r1 + r2, 255))

  5. Color Modulation • Color modulation is basically multiplication • Can be done using a real scalar (brightness modulation) or by multiplying the RGB values in a pairwise manner C1 = (r1, g1, b1) C2 = (r2, g2, b2) C = s * C1 = (s * r1, s *g1, s * b1) C = C1 * C2 = (r1 * r2, g1 * g2, b1 * b2) • Again, we need to beware of overflow

  6. Demo8_1 // copy texture into temp for rendering and scaling Copy_Bitmap(&temp_text,0,0, &textures[curr_texture],0,0,TEXTSIZE, TEXTSIZE); /////////////////////////////////////////// // our little image processing algorithm :) //Cmodulated = s*C1 = (s*r1, s*g1, s*b1) USHORT *pbuffer = (USHORT *)temp_text.buffer;

  7. Demo8_1 // perform RGB transformation on bitmap for (int iy = 0; iy < temp_text.height; iy++) for (int ix = 0; ix < temp_text.width; ix++) { USHORT pixel = pbuffer[iy*temp_text.width + ix]; int ri,gi,bi; // used to extract the rgb values _RGB565FROM16BIT(pixel, &ri,&gi,&bi); // perform scaling operation and test for overflow if ((ri = (float)ri * scalef) > 255) ri=255; if ((gi = (float)gi * scalef) > 255) gi=255; if ((bi = (float)bi * scalef) > 255) bi=255; // rebuild RGB and test for overflow and copy to buffer pbuffer[iy*temp_text.width + ix] = _RGB16BIT565(ri,gi,bi); } // end for ix // draw texture Draw_Bitmap16(&temp_text, back_buffer, back_lpitch,0);

  8. Light Modulation • Pixel Shading plus Modulation (Demo8_2) Pixel_dest[x][y]rgb = pixel_source[x][y]rgb * ambient + pixel_source[x][y]rgb * light_map[x][y]rgb • Pixel Shading plus Modulation (Demo8_2b) Pixel_dest[x][y]rgb = pixel_source[x][y]rgb * ambient + light_map[x][y]rgb • Please note: these are done separately for each RGB value

  9. Demo8_2 // Pixel_dest[x,y]rgb = pixel_source[x,y]rgb * ambient + // pixel_source[x,y]rgb * light_map[x,y]rgb USHORT *sbuffer = (USHORT *)textures[curr_texture].buffer; USHORT *lbuffer = (USHORT *)lightmaps[curr_lightmap].buffer; USHORT *tbuffer = (USHORT *)temp_text.buffer;  // perform RGB transformation on bitmap for (int iy = 0; iy < temp_text.height; iy++) for (int ix = 0; ix < temp_text.width; ix++) { int rs,gs,bs; // used to extract the source rgb values int rl, gl, bl; // light map rgb values int rf,gf,bf; // the final rgb terms // extract pixel from source bitmap USHORT spixel = sbuffer[iy*temp_text.width + ix]; 

  10. Demo8_2 // extract RGB value _RGB565FROM16BIT(spixel, &rs,&gs,&bs); // extract pixel from lightmap bitmap USHORT lpixel = lbuffer[iy*temp_text.width + ix]; // extract RGB values _RGB565FROM16BIT(lpixel, &rl,&gl,&bl); // ambient base texture term + modulation term rf = ( scalef * (float)rs ) + ( (float)rs*(float)rl/(float)64 ); gf = ( scalef * (float)gs ) + ( (float)gs*(float)rl/(float)64 ); bf = ( scalef * (float)bs ) + ( (float)bs*(float)rl/(float)64 );

  11. Demo8_2 // test for overflow if (rf > 255) rf=255; if (gf > 255) gf=255; if (bf > 255) bf=255; // rebuild RGB and test for overflow and write back to buffer tbuffer[iy*temp_text.width + ix] = _RGB16BIT565(rf,gf,bf); } // end for ix // draw textures Draw_Bitmap16(&temp_text, back_buffer, back_lpitch,0); Draw_Bitmap16 (&textures[curr_texture], back_buffer, back_lpitch,0); Draw_Bitmap16 (&lightmaps[curr_lightmap], back_buffer, back_lpitch,0);

  12. Demo8_2b // Pixel_dest[x,y]rgb = pixel_source[x,y]rgb * ambient + // light_map[x,y]rgb USHORT *sbuffer = (USHORT *)textures[curr_texture].buffer; USHORT *lbuffer = (USHORT *)lightmaps[curr_lightmap].buffer; USHORT *tbuffer = (USHORT *)temp_text.buffer; // perform RGB transformation on bitmap for (int iy = 0; iy < temp_text.height; iy++) for (int ix = 0; ix < temp_text.width; ix++) { int rs,gs,bs; // used to extract the source rgb values int rl, gl, bl; // light map rgb values int rf,gf,bf; // the final rgb terms // extract pixel from source bitmap USHORT spixel = sbuffer[iy*temp_text.width + ix];

  13. Demo8_2b   // extract RGB values _RGB565FROM16BIT(spixel, &rs,&gs,&bs);  // extract pixel from lightmap bitmap USHORT lpixel = lbuffer[iy*temp_text.width + ix];   // extract RGB values _RGB565FROM16BIT(lpixel, &rl,&gl,&bl);   // simple formula base + scale * lightmap rf = ( scalef * (float)rl ) + ( (float)rs ); gf = ( scalef * (float)gl ) + ( (float)gs ); bf = ( scalef * (float)bl ) + ( (float)bs );   // test for overflow if (rf > 255) rf=255; if (gf > 255) gf=255; if (bf > 255) bf=255;

  14. Demo8_2b   // rebuild RGB and test for overflow and write back to buffer tbuffer[iy*temp_text.width + ix] = _RGB16BIT565(rf,gf,bf); } // end for ix // draw textures Draw_Bitmap16(&temp_text, back_buffer, back_lpitch,0); Draw_Bitmap16 (&textures[curr_texture], back_buffer, back_lpitch,0); Draw_Bitmap16 (&lightmaps[curr_lightmap], back_buffer, back_lpitch,0);

  15. Alpha Blending • Process of adding two or more pixel colors together to arrive at a destination pixel • Blending means that percentages of each source are used to arrive a final pixel • Used to simulate transparency and shadows • Basic Two-Source Alpha Blending Pixel_dest[x][y]rgb = alpha * pixel_source1[x][y]rgb + (1 – alpha) * pixel_source2[x][y]rgb

  16. Demo8_3 //Pixel_dest[x][y]rgb = alpha * pixel_source1[x][y]rgb + // (1-alpha)* pixel_source2[x][y]rgb USHORT *s1buffer = (USHORT *)textures1[curr_texture1].buffer; USHORT *s2buffer = (USHORT *)textures2[curr_texture2].buffer; USHORT *tbuffer = (USHORT *)temp_text.buffer;  // perform RGB transformation on bitmap for (int iy = 0; iy < temp_text.height; iy++) for (int ix = 0; ix < temp_text.width; ix++) { int rs1,gs1,bs1; // used to extract the source rgb values int rs2, gs2, bs2; // light map rgb values int rf,gf,bf; // the final rgb terms // extract pixel from source bitmap USHORT s1pixel = s1buffer[iy*temp_text.width + ix];

  17. Demo8_3   // extract RGB values _RGB565FROM16BIT(s1pixel, &rs1,&gs1,&bs1); // extract pixel from lightmap bitmap USHORT s2pixel = s2buffer[iy*temp_text.width + ix]; // extract RGB values _RGB565FROM16BIT(s2pixel, &rs2,&gs2,&bs2);   // alpha blend them rf = (alphaf * (float)rs1 ) + ((1 - alphaf) * (float)rs2 ); gf = (alphaf * (float)gs1 ) + ((1 - alphaf) * (float)gs2 ); bf = (alphaf * (float)bs1 ) + ((1 - alphaf) * (float)bs2 );   // test for overflow if (rf > 255) rf=255; if (gf > 255) gf=255; if (bf > 255) bf=255;

  18. Demo8_3   // rebuild RGB and test for overflow copy to buffer tbuffer[iy*temp_text.width + ix] = _RGB16BIT565(rf,gf,bf); } // end for ix // draw textures Draw_Bitmap16(&temp_text, back_buffer, back_lpitch,0); Draw_Bitmap16 (&textures1[curr_texture1], back_buffer, back_lpitch,0); Draw_Bitmap16 (&textures2[curr_texture2], back_buffer, back_lpitch,0);

  19. Ambient Light • This is the light that is all around us with no specific light source • Ambient lighting can be modeled using an additive tem that is the product of and ambient reflective surface color and the ambient light intensity (use floating point RGB values) Itotala = Csambient * Iambient

  20. Diffuse Light - 1 • The light that is scattered off an object due to a light source and the reflectivity of the surface itself • Diffuse light is irrelevant to viewer position • Intensity of Diffuse Light as a Function of Angle Between Surface Normal and Incident Light Source Vectors I = (n•l) = cos 

  21. Diffuse Lighting Models • Single Source Diffuse Itotald = Rsdiffuse * Idiffuse * (n• l) • Single-Source Ambient and Diffuse Itotalad = Rsdiffuse * Idiffuse + [Rsdiffuse * Idiffuse * (n• l)] • Ambient and Diffuse for Multiple Sources Itotalad = Rsdiffuse * Idiffuse + Rsdiffuse*  [I(i)diffuse * (ni• li)]

  22. Specular Lighting • Objects the seem to be shiny reflections of the light sources themselves • Caused by lots of microfacets on the surface have the same orientations • Related to the light source position (l), surface normal (n), viewer position (v), and reflection (r) vectors

  23. Specular Lighting Models • Single Source Specular Itotals = Rsspecular * Ispecular * max(r• v, 0)sp • Single-Source Specular with Source Test Itotals = Rsspecular * Ispecular * max(r• v, 0)sp * [(n • l) > 0 ? 1:0] • Specular for Multiple Sources Itotals = Rsspecular *  [I(i)specular * max(ri• vi, 0)sp * [(ni • li) > 0 ? 1:0]

  24. Emissive Lighting • Easiest lighting model to implement • It is the surface self-illumination • Could almost be thought of as a light source that does not illuminate other objects Itotale = Rsemission

  25. Total Lighting Equation • Single Pixel with Multiple Light Sources Itotalaeds = Rsambient * Iambient * Rsemission + Rsdiffuse*  [I(i)diffuse * (ni• li)] + Rsspecular *  [I(i)specular * max(ri• vi, 0)sp * [(ni • li) > 0 ? 1:0]

  26. Directional Lights • Lights so far away that all the light rays that strike the surface are parallel (also known as infinite lights) • The intensity is always the same as the initial intensity and color independent of distance I(d)dir = I0dir * Cldir

  27. Point Lights • Modeled as single points in 3D space • Falloff (attenuation) based on distance from light is modeled with constants (kc, kl, kq) • Model is (kq can be set to zero) d = |p – s| p = point light source s = point on surface I(d)point = I0point * Clpoint / (kc + kl * d + kq * d2)

  28. Spotlights • Extremely expensive computationally • Spotlight at position p, with direction l, strikes surface point s • The angle  to define region known as the umbra and angle  to define the region known as the penumbra

  29. Spotlight – Cases 1 & 2 • Case 1: If  >  then don’t light the point I(d)spotlight = 0 • Case 2: If  >  then inside umbra d = |p – s| I(d)spotlight = I0spotlight * Clspotlight / (kc + kl * d + kq * d2)

  30. Spotlight – Case 3 • Case 3: If /2 <  < /2 then outside umbra and inside penumbra d = |p – s| pf = power factor I(d)spotlight = I0spotlight * Clspotlight * max((l • s),0)pf/ (kc + kl * d + kq * d2) • Can be simplified to I(d)spotlight = I0spotlight * Clspotlight / (kc + kl * d + kq * d2) * (cos  - cos /2 )pf / (cos /2 - cos /2 )

  31. New 3D Pipeline • Object • Local to World • Object Removal • Back-face Removal • Lighting • World to Camera • Camera to Perspective • Perspective to Screen • Rasterize

  32. Support for Materials • PLG/PLX format does not have any support for materials (textures) • The graphics engine needed to have a number of materials that can applied to polygons during rendering by looking up a material ID or pointer to use access the material

  33. Initializing Material Library int Reset_Materials_MATV1(void) { // this function resets all the materials static int first_time = 1;  // if this is the first time then zero EVERYTHING out if (first_time) { memset(materials, 0, MAX_MATERIALS*sizeof(MATV1)); first_time = 0; } // end if

  34. Initializing Material Library // scan thru materials and release all textures, if any? for (int curr_matt = 0; curr_matt < MAX_MATERIALS; curr_matt++) { // regardless if the material is active check to see if there // is a dangling texture map Destroy_Bitmap(&materials[curr_matt].texture); // now it's safe to zero memory out memset(&materials[curr_matt], 0, sizeof(MATV1)); } // end if return(1); } // end Reset_Materials_MATV1 • Functions to access the material library will come later

  35. Initializing All Lights to Off int Reset_Lights_LIGHTV1(void) { // function simply resets all lights in the system static int first_time = 1;  memset(lights, 0, MAX_LIGHTS*sizeof(LIGHTV1)); // reset number of lights num_lights = 0; // reset first time first_time = 0; // return success return(1); } // end Reset_Lights_LIGHTV1

  36. Creating Lights int Init_Light_LIGHTV1(int index,// index to (0..MAX_LIGHTS-1) int _state, // state of light int _attr, // type of light RGBAV1 _c_ambient, // ambient light intensity RGBAV1 _c_diffuse, // diffuse light intensity RGBAV1 _c_specular, // specular light intensity POINT4D_PTR _pos, // position of light VECTOR4D_PTR _dir, // direction of light float _kc, // attenuation factors float _kl, float _kq, float _spot_inner, // inner angle for spotlight float _spot_outer, // outer angle for spotlight float _pf) // power factor spotlights

  37. Creating Lights { // this function initializes a light based on the flags sent // in _attr, values thataren't needed are set to 0 by caller // make sure light is in range if (index < 0 || index >= MAX_LIGHTS)return(0); // all good, initialize the light (many fields may be dead) lights[index].state = _state; // state of light lights[index].id = index; // id of light lights[index].attr = _attr; // type of light lights[index].c_ambient = _c_ambient; // ambient light lights[index].c_diffuse = _c_diffuse; // diffuse light lights[index].c_specular = _c_specular; // specular light  lights[index].kc = _kc; // attenuation lights[index].kl = _kl; lights[index].kq = _kq;

  38. Creating Lights if (_pos) VECTOR4D_COPY(&lights[index].pos, _pos); if (_dir) { VECTOR4D_COPY(&lights[index].dir, _dir); // normalize it VECTOR4D_Normalize(&lights[index].dir); } // end if lights[index].spot_inner = _spot_inner; // inner angle spot lights[index].spot_outer = _spot_outer; // outer angle spot lights[index].pf = _pf; // power factor // return light index as success return(index); } // end Create_Light_LIGHTV1

  39. Creating Ambient Light ambient_light = Init_Light_LIGHTV1(0, // 0 for ambient LIGHTV1_STATE_ON, // turn on LIGHTV1_ATTR_AMBIENT, // light type _RGBA32BOT(255,255,255,0), // pure white 0, 0, NULL, NULL, // NA for ambient 0, 0, 0, 0, 0, 0); • Once created changing state can be done globally Lights[ambient_light].state = LIGHTV1_STATE_OFF;

  40. Creating Directional Light VECTOR4D sun_dir = {0, -1, 0, 0}; sun_light = Init_Light_LIGHTV1(1, // 1 for sunlight LIGHTV1_STATE_ON, // turn on LIGHTV1_ATTR_INFINITE, // light type 0, _RGBA32BOT(255,255,0 ,0), // pure yellow 0, NULL, &sun_dir, // dir = (0,-1,0) 0, 0, 0, 0, 0, 0); // NA

  41. Creating Point Light VECTOR4D sun_pos = {0, 10000, 0, 0}; sun_light = Init_Light_LIGHTV1(1, // 1 for sunlight LIGHTV1_STATE_ON, // turn on LIGHTV1_ATTR_POINT, // light type 0, _RGBA32BOT(255,255,0 ,0), // pure yellow 0, &sun_pos, NULL, // pos on y-axis 0.0f, 0.001f, 0.0f, // linear atten 0.0f, 0.0f, 0.0f); // NA

  42. Creating Spotlight VECTOR4D spot_pos = {1000, 1000, -1000, 0}; VECTOR4D spot_dir = {-1, -1, 1, 0}; float umbra= 30; float penumbra = 60; falloff = 1.0; sun_light = Init_Light_LIGHTV1(5, // 5 for spot LIGHTV1_STATE_ON, // turn on LIGHTV1_SPOTLIGHT, // light type 0, _RGBA32BOT(128,128,128,0), // 50% white 0, &sun_pos, &sun_dir, // pos & dir 0.0f, 0.0f, 0.0f, // NA umbra, penumbra, falloff); // spot info

  43. Shading • 8-bit modes are 3 times faster than 16-bit • 16-bit modes are easier to track since there are 1:1 mapping of intensities in RGB space to pixels • If you have blue material and red ambient light nothing will be visible in RGB space (0,0,255) * (1.0,0,0) = (0,0,0) • Easier to assume white ambient light (0,0,255) * (1.0,1.0,1.0) = (0,0,255)

  44. Indexed Mode Lighting • We to convert RGB values into color indices and then write those values to the screen • We will need to do a closest-match scan of the color pallet and select the one that comes closest (similar to hashing/lookup) • As a good compromise use a 16-bit look up table (0-65535) translate 16-bit to 8-bit color pallet (0-255) final_pixel_index = rgblookup[final_pixelrgb16];

  45. Simplified Intensity Model • The expensive part of shading is calculation of the final RGB value • If we ignore light color and material color we can simplify the model a great deal • We can create a a table that has 256 rows (one for each pallet color) and each row has 256 entries (the best matches for each intensity value) • We write a shader translation lookup is Rgbintensityloopup[color][intensity]

  46. Color Intensity Algorithm - 1 Given: color c = RGB(50,20,100) c* = RGB(red*,green*,blue*) Step 1: Compute largest component value for this example blue = 100 Step 2: Set maximum component to 255 and compute ratio blue=100, blue* = 255, ratio = 255/100 = 2.55

  47. Color Intensity Algorithm - 2 Step 3: scale all other channels by ratio red* = red * ratio = 50 * 2.55 = 127.5 green* = green * ratio = 20 * 2.55 = 51.0 blue*= blue * ratio = 100 * 2.55 = 255 c* = RGB(128,51,255)

  48. Indexed_Intensity_Table_Builder // these look up tables are used by the 8-bit lighting engine // the first one holds a color translation table in the form of each // row is a color 0..255, and each row consists of 256 shades of that // color the data in each row is the color/intensity indices and the // resulting value is an 8-bit index into the real color lookup that // should be used as the color // the second table works by each index being a compressed 16bit RG // value the data indexed by that RGB value IS the index 0..255 of // the real color lookup that matches the desired color the closest UCHAR rgbilookup[256][256]; // intensity RGB 8-bit lookup storage UCHAR rgblookup[65536]; // RGB 8-bit color lookup

  49. Indexed_Intensity_Table_Builder int RGB_16_8_Indexed_Intensity_Table_Builder (LPPALETTEENTRY src_palette, // source palette UCHAR rgbilookup[256][256], // lookup table int intensity_normalization) // this function takes the source palette to compute the intensity // shading table withthe table will be formatted such that each row // is a color index, and each columnis the shade 0..255 desired, the // output is a single byte indexin either case, it's up to the caller // to send in the rgbilookup table pre-allocated64k buffer byte // [256][256]the function doesn't allocate memory for the caller // the function builds the table by looping thru each color in the // color palette and thenfor each color, it scales the color to // maximum intensity without overflow the RGB channels and then uses // this as the 100% intensity value of the color, then the algorithm // computesthe 256 shades of the color, and then uses the standard // least squares scan the find the colors in the palette and stores // them in the row of the current color under intensity translation

More Related