Lighting

Introduction

LightingIn the previous tutorials, many of the scenes have appeared a bit bland. This tutorial will explain how lighting can be added to your scenes. This increases the overall realism and look of your programs.

Lights

There are a number of different types of lighting that can be added to your OpenGL scenes :

Ambient Light

Ambient light does not come from any particular direction. When ambient light hits a surface, the light is reflected in all directions.

Diffuse Light

Diffuse light is different from ambient light in that it comes from a particular direction. Diffuse light is similar to ambient light in that it is reflected in all directions.

Specular Light

Like diffuse light, specular light is directional but it is reflected sharply back in a particular direction. You may have seen a bright highlight on a surface before. This is known as a specular highlight.

Emissive Light

Emissive light is light that comes from a specific object. The object gives off an amount of light, but it does not reflect off any surfaces.

Materials

Not only can you specify lighting properties, but you can specify how various surfaces must react to light. This is known as specifying material properties.

This specifies how much of a particular light source must reflect off of a surface.

Normals

Normals are vectors perpendicular(at 90 degrees) to a particular surface. These are used in lighting calculations. You need to specify a normal for every polygon that is drawn if you wish for it to be affected by lighting. This will be shown further below.

Another important note is that normals should be normalized. We will not go into the maths of this as it is not needed for this tutorial. It may be explained in a future tutorial if need be. In short, the length of a vector is calculated by taking the square root of the sum of the squares of each value in the vector. Each value in the vector must then be divided by the vector length. Do not worry too much about this for now.

Contents of main.cpp :


Below, we create 2 color arrays, one for ambient and for diffuse light. This will be the color of the light source.

float lightAmbient[] = { 0.2f, 0.3f, 0.6f, 1.0f };
float lightDiffuse[] = { 0.2f, 0.3f, 0.6f, 1.0f };

Next, we create an array for the material properties. One for the ambient and one for the diffuse light source.

What this essentially does is multiply the light values by the material values to get the resultant color reflecting off of the surface. The arrays below therefore cause the surface to lose 40% of the light. Each value represents the amount that a particular color is reflected.

float matAmbient[] = { 0.6f, 0.6f, 0.6f, 1.0f };
float matDiffuse[] = { 0.6f, 0.6f, 0.6f, 1.0f };

void init()
{

Our first step in creating lighting effects is to pass the GL_LIGHTING flag onto the glEnable function. This enables lighting for your OpenGL scene.

	glEnable(GL_LIGHTING);

OpenGL allows you to have a maximum of 8 lights at any particular point in time. To enable one of these lights, you need to pass GL_LIGHTX onto the glEnable function where X is a value from 0 to 7.

	glEnable(GL_LIGHT0);

To specify material properties, the glMaterialfv and glMaterialf functions can be used. The glMaterialfvfunction is used to for parameters with multiple values and the glMaterialf function is used when one value is needed. This will become more evident later. The first parameter specifies what faces are being updated. In OpenGL ES, the GL_FRONT_AND_BACK flag is the only flag that can be passed. Any other flag will not have any effect. The only reason the parameter is here is because standard OpenGL allows other values.

The second parameter is used to specify what type of light you are setting properties for eg. GL_AMBIENT,GL_DIFFUSEGL_SPECULARGL_EMISSION and GL_AMBIENT_AND_DIFFUSE.

The last parameter accepts an array or a single value depending on if you are using the glMaterialfv orglMaterialf function respectively.

The next two lines set the material properties for our surface.

	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmbient);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiffuse);

Like setting material properties, light properties can be set in the same way. This can be done using theglLightfv and glLightf functions. They work in the same way as the functions above.

The code below sets the properties for the light.

	glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);

The rest of the init method remains the same.

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepthf(1.0f);

	glVertexPointer(3, GL_FLOAT, 0, box);
	glEnableClientState(GL_VERTEX_ARRAY);

	glEnable(GL_CULL_FACE);
	glShadeModel(GL_SMOOTH);
}

The beginning of our display function remains the same.

void display()
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glLoadIdentity();

   gluLookAtf(
		0.0f, 0.0f, 3.0f,
		0.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f);

   glRotatef(xrot, 1.0f, 0.0f, 0.0f);
   glRotatef(yrot, 0.0f, 1.0f, 0.0f);

Above, we spoke about normals. These normals need to be perpendicular to the surface. The front surface therefore has a normal vector of (0,0,1) and the back surface has a normal of (0,0,-1). The length of both vectors is 1 and therefore both are already normalized.

Normals are specified by placing a glNormal3f function call before rendering the primitives. This function takes 3floats making up the normalized vector.

   // FRONT AND BACK
   glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
   glNormal3f(0.0f, 0.0f, 1.0f);
   glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   glNormal3f(0.0f, 0.0f, -1.0f);
   glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);

The same is done for the top, bottom and sides. Like the color and vertex arrays, there is also a normal array. You can set the normal array by making a call to the glNormalPointer function. This works in the same way as theglVertexPointer function. To enable the array, the GL_NORMAL_ARRAY flag needs to be passed onto theglEnableClientState function.

   // LEFT AND RIGHT
   glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
   glNormal3f(-1.0f, 0.0f, 0.0f);
   glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
   glNormal3f(1.0f, 0.0f, 0.0f);
   glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);

   // TOP AND BOTTOM
   glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
   glNormal3f(0.0f, 1.0f, 0.0f);
   glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
   glNormal3f(0.0f, -1.0f, 0.0f);
   glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);

   glFlush();
   glutSwapBuffers();
}

Our menu has been modified to include a Color Material menu option. This enables and disables what is calledcolor tracking and is specified with the GL_COLOR_MATERIAL flag.

What color tracking does is that it automatically sets material properties according to your calls made toglColor4f. Enabling this will cause the different sides to reflect their respective color.

	case 2 : 
		if (glIsEnabled(GL_COLOR_MATERIAL))
			glDisable(GL_COLOR_MATERIAL);
		else
			glEnable(GL_COLOR_MATERIAL);
		break;

The two images below show the difference between the standard lighting we specified above and the same scenario with color tracking enabled.

Normal LightingColor Tracking
Normal LightingColor Tracking

You should now be able to add lighting to your scenes. This provides great flexibility and allows your scenes to appear more lifelike.

Please let me know of any comments you may have : Contact Me

资源下载链接为: https://pan.quark.cn/s/f989b9092fc5 在 Android 应用开发中,开发一款仿 OPPO 手机计算器的应用是极具实践价值的任务,它融合了 UI 设计、事件处理以及数学逻辑等多方面的技术要点。当前的“最新版仿 OPPO 手机计算器--android.rar”压缩包中,提供了该计算器应用的源代码,这为开发者深入学习 Android 编程提供了宝贵的资源。 UI 设计是构建此类计算器应用的基石。OPPO 手机的计算器界面以清晰的布局和良好的用户交互体验著称,其中包括数字键、运算符键以及用于显示结果的区域等关键元素。开发者需借助 Android Studio 中的 XML 布局文件来定义这些界面元素,可选用 LinearLayout、GridLayout 或 ConstraintLayout 等布局管理器,并搭配 Button 控件来实现各个按键功能。同时,还需考虑不同分辨率屏幕和设备尺寸的适配问题,这通常涉及 Density Independent Pixel(dp)单位的应用以及 Android 尺寸资源的合理配置。 事件处理构成了计算器的核心功能。开发者要在每个按钮的点击事件中编写相应的处理代码,通常通过实现 OnClickListener 接口来完成。例如,当用户点击数字键时,相应的值会被添加到显示区域;点击运算符键时,则会保存当前操作数并设定运算类型。而对于等号(=)按钮,需要执行计算操作,这往往需要借助栈数据结构来存储操作数和运算符,并运用算法解析表达式以完成计算。 数学逻辑的实现则是计算器功能的关键体现。在 Android 应用中,开发者可以利用 Java 内置的 Math 类,或者自行设计算法来完成计算任务。基本的加减乘除运算可通过简单的算术操作实现,而像求幂、开方等复杂运算则需调用 Math 类的相关方法。此外
### Unity 中与光照相关的功能或设置 在 Unity 的渲染引擎中,光照是一个非常重要的组成部分。通过合理配置光照参数和使用不同的光源类型,可以显著提升场景的真实感和视觉效果[^1]。 #### 光源类型 Unity 提供了多种类型的光源来满足不同需求: - **Directional Light(方向光)**: 模拟太阳光的效果,适用于大面积均匀照明。 - **Point Light(点光源)**: 类似于灯泡发出的光线,在各个方向上均匀发光。 - **Spot Light(聚光灯)**: 创建锥形区域内的集中光照,类似于手电筒或舞台灯光。 - **Area Light(区域光)**: 虽然仅支持烘焙模式,但它能提供更自然柔和的阴影效果。 每种光源都可以调整强度、颜色以及衰减属性等基本参数,并且可以通过混合这些光源创建复杂的环境氛围。 #### 实时光照 vs 烘焙光照 为了平衡性能表现与画质质量之间的关系,开发者可以选择实时光照或者静态烘焙方式处理模型表面反射情况: - **Realtime Lighting (实时)**: 对动态对象特别有用;但是计算成本较高可能影响帧率。 - **Baked Lighting (烘培)**: 将最终结果保存成纹理贴图应用到物体表面上从而减少运行时开销。适合不经常改变的大规模建筑结构之类的静止物件。 此外还有混合模式允许部分元素采用即时更新而其他保持固定状态以便优化资源消耗水平。 #### GI(全局光照) Global Illumination 是指间接光照传播过程中的相互作用现象。Unity 支持两种主要形式的GI解决方案: - **Light Probes**: 用于捕捉周围空间平均亮度信息并将其应用于非网格形状上的角色或其他移动实体之上。 - **Reflection Probes**: 反射探针则记录特定视角下的全景图像作为镜像材质的基础数据来源之一。 对于更加高级的需求来说还可以探索 HDRenderPipeline 或者 UniversalRenderPipeline 所带来的额外选项比如物理基础渲染(PBR)材料定义等等[^4]。 ```csharp // Example C# script demonstrating basic light manipulation. using UnityEngine; public class BasicLightControl : MonoBehaviour { public float intensityChangeRate; private Light myLightComponent; void Start(){ myLightComponent = GetComponent<Light>(); } void Update() { if(myLightComponent != null){ myLightComponent.intensity += Time.deltaTime * intensityChangeRate; } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值