{"id":26,"date":"2021-10-13T22:15:56","date_gmt":"2021-10-13T22:15:56","guid":{"rendered":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/?p=26"},"modified":"2021-10-13T22:16:05","modified_gmt":"2021-10-13T22:16:05","slug":"light-setting-in-opengl","status":"publish","type":"post","link":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/2021\/10\/13\/light-setting-in-opengl\/","title":{"rendered":"Light Setting in OpenGL"},"content":{"rendered":"\n<p><strong>Introduction:&nbsp;<\/strong><\/p>\n\n\n\n<p>Have you ever tried to set lights for your 3D objects? To me, light setting is a hard topic; I spend time doing small increments of codes and debugging to try to understand the light effects. When there is a need for creating multiple light sources, things get complicated. Lights are interestingly blended to create wanted and unwanted effects. A solid understanding of basic light setting is helpful for any graphic designer. Otherwise, the 3D objects just look like 2D boring blobs of colored shapes.\u00a0<\/p>\n\n\n\n<p><strong>Visual effects of different light sources and light components<\/strong><\/p>\n\n\n\n<p>Figure1 shows us a scene with a small yellow light shining on a cube. From the picture, we notice that a light source needs to have a <em>location<\/em>, and involved light components are <em>ambient <\/em>and <em>diffuse <\/em>[1]. Also, we realize that when only ambient and diffuse features are used, the surface of the object looks <em>dull<\/em>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"594\" height=\"628\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/1-3.png\" alt=\"\" class=\"wp-image-36\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/1-3.png 594w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/1-3-284x300.png 284w\" sizes=\"auto, (max-width: 594px) 100vw, 594px\" \/><figcaption> Figure 1: Ambient \/Diffuse light source. <br>Source: Adapted from https:\/\/www.just.edu.jo\/~yaser\/courses\/cs480\/Tutorials [1]  <\/figcaption><\/figure>\n\n\n\n<p>In contrast, an object looks <em>shiny<\/em> when its surface reflects most of the incoming light. In order to create a shiny object, a specular light component is added. <em>Specular <\/em>color determines the color of the highlight(<strong><em>GL_SPECULAR<\/em><\/strong>). In addition, users need to determine how shiny a surface is (<strong>GL_SHININESS<\/strong>). Figure 2 shows specular color changes from the same color to white from bottom to the top. Also, <em>shininess <\/em>is increasing from left to right (5, 25, 45,65,85).\u00a0<\/p>\n\n\n\n<p>In OpenGL, to enable or disable lighting, users need to call <strong>glEnable(GL_LIGHTING)<\/strong> or <strong>glDisable(GL_LIGHTING)<\/strong>. When lighting is enabled, colors that are specified by <strong>glColor<\/strong>*() will become invalid.\u00a0Light position is set using <strong>GL_POSITION<\/strong>. Light components are set using <strong>GL_AMBIENT, GL_DIFFUSE<\/strong>.\u00a0<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"848\" height=\"804\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/2-1.png\" alt=\"\" class=\"wp-image-31\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/2-1.png 848w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/2-1-300x284.png 300w\" sizes=\"auto, (max-width: 848px) 100vw, 848px\" \/><figcaption>Figure 2: specular and shiny settings decide shininess of the object. <br>Source: http:\/\/cgkit.sourceforge.net\/tutorials\/materials.html [2]<\/figcaption><\/figure>\n\n\n\n<p><strong>Per-vertex lighting vs. per-face lighting:<\/strong><\/p>\n\n\n\n<p>Like the name might suggest, for per-vertex lighting, users need to define a normal vector using glNormal3f(x,y,z) at each vertex. Similarly, for per-face lighting, normal vectors are defined at each face of the object. If it is desired to have a lit <em>smooth <\/em>surface, per-vertex should be used. If it is desired to have a <em>flat <\/em>surface, per-face should be used. The smaller the face and the larger the number of vertices, the better the object will look when it is lit.\u00a0<\/p>\n\n\n\n<p>In OpenGL,<strong> glShadeModel(GL_FLAT)<\/strong> is used when using per-face lighting and <strong>glShadeModel(GL_SMOOTH)<\/strong> is used when applying per-vertex lighting. Also, we need to enable normalization by using <strong>glEnable(GL_NORMALIZE).<\/strong><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>Alpha blending and transparency<\/strong><\/p>\n\n\n\n<p><em>Alpha value<\/em> is the 4th component of a color (rgba); it determines the opacity of an object when it is used with<em> blend factors<\/em> <strong>GL_SRC_ALPHA<\/strong> and <strong>GL_ONE_MINUS_SRC_ALPHA<\/strong>. With alpha blending, the output pixel is a weighted sum of the existing pixel and newly calculated pixel.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1182\" height=\"1038\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/3-3.png\" alt=\"\" class=\"wp-image-35\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/3-3.png 1182w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/3-3-300x263.png 300w\" sizes=\"auto, (max-width: 1182px) 100vw, 1182px\" \/><figcaption> Figure 3: Alpha Blending and transparency feature. <br>Source: http:\/\/www.opengl-tutorial.org\/intermediate-tutorials\/tutorial-10-transparency\/ [3]  <\/figcaption><\/figure>\n\n\n\n<p><strong>Difference light sources: directional light, pointlight, and spotlight&nbsp;<\/strong><\/p>\n\n\n\n<p>Figure 4 shows us some important features of different light sources. Directional light creates parallel light rays because the light position is very far away (infinite). As a result, it doesn&#8217;t matter any more how each object in world space relates to the light source. While the point light equally radiates in all directions, the spotlight is focused and forms a cone shape.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1246\" height=\"500\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/source.png\" alt=\"\" class=\"wp-image-30\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/source.png 1246w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/source-300x120.png 300w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/source-768x308.png 768w\" sizes=\"auto, (max-width: 1246px) 100vw, 1246px\" \/><figcaption>Figure 4: Characteristics of different light sources. Source: https:\/\/gdbooks.gitbooks.io\/legacyopengl\/content\/Chapter5\/light_spotlight.html [4]<\/figcaption><\/figure>\n\n\n\n<p><strong>Spotlights\u2019 features<\/strong><\/p>\n\n\n\n<p>Although point light and spot light have different light effects, setting those lights are pretty much the same, except that in spotlight, some spotlight\u2019s specifications are added: <strong>GL_SPOT_DIRECTION, GL_SPOT_EXPONENT, and GL_SPOT_CUTOFF<\/strong>.&nbsp;<\/p>\n\n\n\n<p>By default, GL_SPOT_DIRECTION points towards the negative z axis (0,0,-1).<\/p>\n\n\n\n<p>GL_SPOT_EXPONENT ranges from 0 to 128. By default, its value is 0, which means there is no light attenuation as the spotlight spreads toward the side edges of the cone. In other words, the cone of light is evenly distributed.&nbsp;<\/p>\n\n\n\n<p>GL_SPOT_CUTOFF determines how wide the light cone is. It specifies the angle between the cone\u2019s axis and the cone\u2019s edge. It ranges from 0 to 90 degrees. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"404\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/spot-1024x404.png\" alt=\"\" class=\"wp-image-29\" srcset=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/spot-1024x404.png 1024w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/spot-300x118.png 300w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/spot-768x303.png 768w, https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/spot.png 1272w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Figure 5: Spotlight settings and meaning. Source: [4]<\/figcaption><\/figure>\n\n\n\n<p><strong>Two-sided light vs. one-sided light:&nbsp;<\/strong><\/p>\n\n\n\n<p>Light can be performed for all faces: front-faces (GL_FRONT) or back faces (GL_BACK). To disable this two-sided light, use GL_FALSE instead of GL_TRUE in the following function:&nbsp;<\/p>\n\n\n\n<p><strong>glLightModeli<\/strong><em>(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);<\/em><\/p>\n\n\n\n<p><strong>Local viewpoint vs. infinite viewpoint:<\/strong><\/p>\n\n\n\n<p>By default, the viewpoint is infinite; the direction between light source and any vertex in the scene is constant. In contrast, for the local viewpoint, direction from the light source to each vertex is taken into account. As a result, the local viewpoint seems to be more realistic. The following function sets the local viewpoint at (0,0,0). To choose an infinite viewpoint, use the GL_FALSE.&nbsp;<\/p>\n\n\n\n<p><strong><em>glLightModeli<\/em><\/strong><em>(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);<\/em><\/p>\n\n\n\n<p><strong>Static lights vs. perspective lights vs. dynamic lights<\/strong><\/p>\n\n\n\n<p><em>Static lights<\/em> will never move. To set static light, light is positioned after setting the camera (after the call to gluLookAt() and before performing matrix transformation.&nbsp;<\/p>\n\n\n\n<p><em>Perspective light,<\/em> in contrast, will relatively fix with the camera position. For example, headlights are perspective lights when a passenger is sitting in the car and the car is moving. The headlight in this case will relatively fix relative to the passengers\u2019 eyes. To have a perspective light effect, Light should be defined after setting the modelview matrix to identity matrix and before calling gluLookAt().&nbsp;<\/p>\n\n\n\n<p>For dynamic light, the light will move as the object moves. Light transformation in this case is done after the object transformation. Push and pop matrices are also used in this case. A useful example that I find is shown below (figure 6). <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1032\" height=\"912\" src=\"https:\/\/osu-wams-blogs-uploads.s3.amazonaws.com\/blogs.dir\/4779\/files\/2021\/10\/example-1.png\" alt=\"\" class=\"wp-image-28\" \/><figcaption>Figure 6: Example of dynamic light setting for Mr. Roboto. Source: https:\/\/gdbooks.gitbooks.io\/legacyopengl\/content\/Chapter5\/move_and_rotate.html[6]<\/figcaption><\/figure>\n\n\n\n<p><strong>Conclusion<\/strong>: <\/p>\n\n\n\n<p>We have discussed some basic background of lights: light sources, light models in OpenGL, and light interactions. Hopefully, this could benefit learners when implementing multiple lights in a program. Proper light setting brings \u201csoul\u201d to the scene and object. Through clever light usage, lights bring valuable meanings and engage viewers into the scene.\u00a0<\/p>\n\n\n\n<p><strong>Reference<\/strong>\u00a0<\/p>\n\n\n\n<p>[1] J\u00e9r\u00f4me Jouvie. <em>Tutorial8-1: Light [Part I]<\/em>. [Online]. Available:   <a href=\"https:\/\/www.just.edu.jo\/~yaser\/courses\/cs480\/Tutorials\/OpenGl%20-%20Tutorial8-1%20Light%20Part%20I.htm\">https:\/\/www.just.edu.jo\/~yaser\/courses\/cs480\/Tutorials\/OpenGl%20-%20Tutorial8-1%20Light%20Part%20I.htm<\/a>. Accessed Oct 13th, 2021. <\/p>\n\n\n\n<p>[2] cgkit. <em>Materials: How to change the visual appearance of your objects<\/em>. [Online]. Available: <a href=\"http:\/\/cgkit.sourceforge.net\/tutorials\/materials.html\">http:\/\/cgkit.sourceforge.net\/tutorials\/materials.html<\/a>. Accessed Oct 13th, 2021. <\/p>\n\n\n\n<p>[3] openGL_tutorial. <em>Tutorial 10: Transparency<\/em>. [Online]. Available:  http:\/\/www.opengl-tutorial.org\/intermediate-tutorials\/tutorial-10-transparency\/. Accessed Oct 13th, 2021. <\/p>\n\n\n\n<p>[4]LegacyOpenGL. <em>Spotlights<\/em>. [Online]. Available: <a href=\"https:\/\/gdbooks.gitbooks.io\/legacyopengl\/content\/Chapter5\/light_spotlight.html\">https:\/\/gdbooks.gitbooks.io\/legacyopengl\/content\/Chapter5\/light_spotlight.html<\/a>. Accessed Oct 13th, 2021. <\/p>\n\n\n\n<p>[5] LegacyOpenGL.<em> Moving and rotating<\/em>. [Online]. Available: <a href=\"https:\/\/gdbooks.gitbooks.io\/legacyopengl\/content\/Chapter5\/light_spotlight.html\">https:\/\/gdbooks.gitbooks.io\/legacyopengl\/content\/Chapter5\/move_and_rotate.html<\/a>. Accessed Oct 13th, 2021. <\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction:&nbsp; Have you ever tried to set lights for your 3D objects? To me, light setting is a hard topic; I spend time doing small increments of codes and debugging to try to understand the light effects. When there is a need for creating multiple light sources, things get complicated. Lights are interestingly blended to&hellip; <a class=\"more-link\" href=\"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/2021\/10\/13\/light-setting-in-opengl\/\">Continue reading <span class=\"screen-reader-text\">Light Setting in OpenGL<\/span><\/a><\/p>\n","protected":false},"author":11550,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-26","post","type-post","status-publish","format-standard","hentry","category-uncategorized","entry"],"_links":{"self":[{"href":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/wp-json\/wp\/v2\/posts\/26","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/wp-json\/wp\/v2\/users\/11550"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/wp-json\/wp\/v2\/comments?post=26"}],"version-history":[{"count":1,"href":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/wp-json\/wp\/v2\/posts\/26\/revisions"}],"predecessor-version":[{"id":37,"href":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/wp-json\/wp\/v2\/posts\/26\/revisions\/37"}],"wp:attachment":[{"href":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/wp-json\/wp\/v2\/media?parent=26"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/wp-json\/wp\/v2\/categories?post=26"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.oregonstate.edu\/learnfromscratch\/wp-json\/wp\/v2\/tags?post=26"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}