OpenGL学习(五) 光照与材质

OpenGL中的光照

    环境光:在环境中进行了充分的散射,无法分辨其方向的光。

散射光:来自某个方向。

镜面光:来自一个特定的方向,并且倾向于从表面某个特定的方向反射。

除了以上三种光外,材料可能具有一种发射颜色,它模拟那些源自某个物体的光。

为了实现明暗效果,必须启用光照计算,而且每种光源也必须被启用。对于单个光源,我们可以这样做:

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0)

注:一旦光照被启用,glColor*()指定的颜色值将不再使用。

指定法向量:

物体的法线向量决定了它相对于光源的方向。表面法线必须为单位长度。

void glNormal3<bsidf>(type x,type y,type z);

void glNormal3<bsidf>(type* v)

光源的指定

    void glLight<if>(GLenum light,GLenum param,type value)

     void glLight<if>v(GLenum light,GLenum param,type* value)

//为OpenGL光源light设置标量类型或向量类型的参数,即将参数param设为type

材质的指定

    void glMaterial<if>(GLenum face,GLenum name,type value)

void glMaterial<if>v(GLenum face,GLenum name,type value)

//为材质的某一面face设置标量或向量参数。参数name类型为type

对于每个面,我们可以为其设置漫反射(GL_DIFFUSE)、镜面反射(GL_SPECULAR)以及环境反射(GL_AMBIENT)属性。通常漫反射和环境反射的属性是相同的,可以将两者一起设置。每个表面都可以向外辐射(GL_EMISSION).这一项不受光照计算的影响,所以无论光源如何,表面看起来都一样的。最后还有一个灰度系数(GL_SHININESS),该参数的值越大,材质的光泽度就越高。

旋转立方体的明暗计算

#include <gl/glut.h>
#include <math.h>
#include <iostream>

using namespace std;

int axis=0;
float theta[3];

GLfloat vertices[][3]={
	{-1.0,-1.0,1.0},
	{-1.0,1.0,1.0},
	{1.0,1.0,1.0},
	{1.0,-1.0,1.0},
	{-1.0,-1.0,-1.0},
	{-1.0,1.0,-1.0},
	{1.0,1.0,-1.0},
	{1.0,-1.0,-1.0}
};                              //定义立方体的8个顶点

GLint index[][4]={
	{0,3,2,1},
	{2,3,7,6},
	{3,0,4,7},
	{1,2,6,5},
	{4,5,6,7},
	{5,4,0,1}
};                              //定义每个面所需要那几个顶点

GLfloat normals[][3]={
	0.0,0.0,-1.0,
	0.0,1.0,0.0,
	-1.0,0.0,0.0,
	1.0,0.0,0.0,
	0.0,0.0,1.0,
	0.0,-1.0,0.0
};                             //定义每个面的法向量

typedef struct  lightingStruct 
{
	GLfloat ambient[4];
	GLfloat diffuse[4];
	GLfloat specular[4];
}lightingStruct;

lightingStruct whiteLighting={
	{0.0,0.0,0.0,1.0},
	{1.0,1.0,1.0,1.0},
	{1.0,1.0,1.0,1.0}
};

lightingStruct coloredLighting={
	{0.2,0.0,0.0,1.0},
	{0.0,1.0,0.0,1.0},
	{0.0,0.0,1.0,1.0}
};

typedef struct materialStruct{
	GLfloat ambient[4];
	GLfloat diffuse[4];
	GLfloat specular[4];
	GLfloat shininess;
}materialStruct;

materialStruct brassMaterials={
	{0.33,0.22,0.03,1.0},
	{0.78,0.57,0.11,1.0},
	{0.99,0.91,0.81,1.0},
	27.8
};

materialStruct redplasticMaterials={
	{0.3,0.0,0.0,1.0},
	{0.6,0.0,0.0,1.0},
	{0.8,0.6,0.6,1.0},
	32.0
};

materialStruct whiteShinyMaterials={
	{1.0,1.0,1.0,1.0},
	{1.0,1.0,1.0,1.0},
	{1.0,1.0,1.0,1.0},
	100.0
};

GLfloat light_0pos[4]={0.9,0.9,2.25,0.0};

materialStruct* currentMaterials;
lightingStruct* currentLighting;

void init()
{
	glClearColor(0.0,0.0,0.0,0.0);      //指定屏幕背景为黑色

	glEnable(GL_LIGHTING);       //启用光照
	glEnable(GL_LIGHT0);        //启用光源0

	glEnable(GL_DEPTH_TEST);

	currentMaterials=&redplasticMaterials;

	glMaterialfv(GL_FRONT,GL_AMBIENT,currentMaterials->ambient);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,currentMaterials->diffuse);
	glMaterialfv(GL_FRONT,GL_SPECULAR,currentMaterials->specular);
	glMaterialfv(GL_FRONT,GL_SHININESS,&currentMaterials->shininess);

	currentLighting=&whiteLighting;

	glLightfv(GL_LIGHT0,GL_AMBIENT,currentLighting->ambient);
	glLightfv(GL_LIGHT0,GL_DIFFUSE,currentLighting->diffuse);
	glLightfv(GL_LIGHT0,GL_SPECULAR,currentLighting->specular);
	glLightfv(GL_LIGHT0,GL_POSITION,light_0pos);

	glEnable(GL_COLOR_MATERIAL);
}

void polygon(int* index)
{
	glBegin(GL_QUADS);
	for(int i=0;i<4;i++)
		glVertex3fv(vertices[index[i]]);
	glEnd();
}

void display()
{

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         //清理屏幕颜色为我们指定的颜色
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glRotatef(theta[0],1.0,0.0,0.0);
	glRotatef(theta[1],0.0,1.0,0.0);
	glRotatef(theta[2],0.0,0.0,1.0);

	for(int i=0;i<6;i++)
	{
		glNormal3fv(normals[i]);
		polygon(index[i]);
	}
	glFlush();                       //强制以上绘图操作执行
}

void reshape(int w,int h)
{
	glMatrixMode(GL_PROJECTION);       //设置为投影模式
	glLoadIdentity();
	glOrtho(-2.0,2.0,-2.0,2.0,-2.0,2.0);

	glViewport(0,0,(GLsizei)w,(GLsizei)h);
}

void mouse(int button,int state,int x,int y)
{
	if (button==GLUT_LEFT_BUTTON && state==GLUT_DOWN)
	{
		axis=0;
	}
	if (button==GLUT_MIDDLE_BUTTON && state==GLUT_DOWN)
	{
		axis=1;
	}
	if (button==GLUT_RIGHT_BUTTON && state==GLUT_DOWN)
	{
		axis=2;
	}
}

void SpinIdle()
{
	theta[axis]+=0.1;
	if(theta[axis] >360.0)  theta[axis] -=360.0;
	glutPostRedisplay();
}

void key(unsigned char k,int x,int y)
{
	switch (k)
	{
	case ‘1‘:
		glutIdleFunc(NULL);
		break;
	case ‘2‘:
		glutIdleFunc(SpinIdle);
		break;
	case ‘3‘:
		currentMaterials=&redplasticMaterials;
		break;
	case ‘4‘:
		currentMaterials=&whiteShinyMaterials;
		break;
	case ‘5‘:
		currentMaterials=&brassMaterials;
		break;
	case ‘6‘:
		currentLighting=&whiteLighting;
		break;
	case ‘7‘:
		currentLighting=&coloredLighting;
		break;
	case ‘q‘:
		exit(0);
		break;
	}

	glMaterialfv(GL_FRONT,GL_AMBIENT,currentMaterials->ambient);
	glMaterialfv(GL_FRONT,GL_DIFFUSE,currentMaterials->diffuse);
	glMaterialfv(GL_FRONT,GL_SPECULAR,currentMaterials->specular);
	glMaterialfv(GL_FRONT,GL_SHININESS,&currentMaterials->shininess);

	glLightfv(GL_LIGHT0,GL_AMBIENT,currentLighting->ambient);
	glLightfv(GL_LIGHT0,GL_DIFFUSE,currentLighting->diffuse);
	glLightfv(GL_LIGHT0,GL_SPECULAR,currentLighting->specular);

	glutPostRedisplay();
}

int main(int argc,char**argv)
{
	glutInit(&argc,argv);                           //初始化glut
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);    //设置窗口模式为单缓冲和RGB模式
	glutInitWindowSize(500,500);                    //设置窗口大小
	glutCreateWindow("test");                       //设置窗口标题
	glutDisplayFunc(display);                       //设置绘图回调函数
	glutReshapeFunc(reshape);                       //设置窗口回调函数
	glutMouseFunc(mouse);
	glutIdleFunc(SpinIdle);
	glutKeyboardFunc(key);
	init();
	glutMainLoop();                                 //开始循环,等待响应
	return 0;
}

运行可以得到如下结果:

对明暗计算的控制

    void glLightModel<if>(GLenum param,type value)

void glLightModel<if>v(GLenum param,type value)

//为param(GL_LIGHT_MODEL_AMBIENT,GL_LIGHT_MODEL_LOCAL_VIEWR,GL_LIGHT_MODEL_TWO_SIDE)设置光照模型。

许多情况下,背面不需要计算光照,OpenGL能够利用这种情况,不对背面进行任何的光照计算。如果确实需要两面的光照计算,则可以如下设置:

void glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE)

如果视点距离物体远,则当我们移动物体时,从物体上任一点指向视点的向量几乎没什么变化。所以,可以通知OpenGL视点与场景的距离无穷远:

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWR,GL_TRUE)

若果所有的光源都禁用,环境光将不复存在。但是,我们仍希望少量的环境光存在。则可以设置一个全局环境光源来达到效果:

glLightModeli(GL_LIGHT_MODEL_AMBIENT,global_ambient)

平滑着色

    glShadeModel()

时间: 2024-10-08 10:28:35

OpenGL学习(五) 光照与材质的相关文章

OPENGL学习笔记——光照

1.隐藏表面消除 隐藏表面消除就是消除实心物体被其他物体所遮挡住的部分,最简单的方法就是使用深度缓冲区. 深度缓冲区的原理是把一个距离观察平面(通常是近侧裁剪平面)的深度值与窗口中的每一个像素相关联.首先使用glClear()函数,把所有像素的深度值设置为最大可能的距离,然后在场景中以任意顺序绘制所有的物体. 深度缓冲区测试可能会影响应用程序的性能,隐藏表面消除丢弃了一些信息,而不是将它们用来绘图,因此会稍稍提高性能,但是深度缓冲区会大大影响性能,用"软件"实现的深度缓冲区(用处理器内

OpenGl学习进程(7)第五课:点、边和图形(二)边

本节是OpenGL学习的第五个课时,下面介绍OpenGL边的相关知识: (1)边的概念: 数学上的直线没有宽度,但OpenGL的直线则是有宽度的.同时,OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的.可以认为,OpenGL的“直线”概念与数学上的“线段”接近,它可以由两个端点来确定.     (2)如何绘制边: 1)OpenGL支持绘制三种类型的边: GL_LINES :指定两个顶点,在它们之间绘制一条直线.如果为GL_LINES指定了奇数个顶点,那么最后一个顶点会被忽略. GL

OpenGL学习之路(五)

1 引子 不知不觉我们已经进入到读书笔记(五)了,我们先对前四次读书笔记做一个总结.前四次读书笔记主要是学习了如何使用OpenGL来绘制几何图形(包括二维几何体和三维几何体),并学习了平移.旋转.缩放坐标变换矩阵的理论推导和实践应用. 这一次读书笔记,我们一起来学习OpenGL中常用的坐标系以及坐标变换.在OpenGL中有几个坐标系,初学者常常被它们搞得晕头转向:为什么需要这些坐标系?各个坐标系有什么作用?……本文就来学习一下这些OpenGL中常用坐标系. 之后来看看投影矩阵的推导,投影变换矩阵

【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&amp;颜色、光照与材质

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 邮箱: [email protected] 本篇文章中,我们学习了Unity Shader的基本写法框架,以及学习了Shader中Properties(属性)的详细写法,光照.材质与颜色的具体写法.写了6个Shader作为本文S

OpenGL学习进程(11)第八课:颜色绘制的详解

    本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿.     (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. RGBA模式与索引模式的区别: 计算机必须为每个像素保存一些数据,在RGBA模式中数据就代表了颜色:而颜色索引模式中数据代表了一个索引,要获取真正的颜色值还需要查索引表.数据的数量是由帧缓存中的位面决定的.一个位面为一个像素的一个位的数据.假如是8位面的颜色,每个像素就有8个颜色位,因此就有2的8次方

OpenGL学习日记-2014.12.21--光照

o(╯□╰)o深患中度拖延症,也是从开始写这篇笔记到结束居然用了一个月...虽然中间是发生了不少事,不过明明就有无数机会可以完成,就是拖着没写代码,各种借口...面对如此拖延症该如何是好QAQ 正文: 突然觉得这些日记写着写着就没什么意思...只是简单梳理一下书中的内容,没经过很多的思考,可不写心里更虚,怕自己几天就把看的书忘了.对于很多概念,都由于没有好好去写代码验证,而理解流于表面.对于光照这章也是下决心细细琢磨一番(现在才下的决心o(╯□╰)o),毕竟这很重要. 一.光照和颜色密切相关,光

OpenGL学习进程(4)第二课:绘制图形

本节是OpenGL学习的第二个课时,下面介绍如何用点和线来绘制图形:     (1)用点的坐标来绘制矩形: #include <GL/glut.h> void display(void) { // clear all pixels glClear(GL_COLOR_BUFFER_BIT); // draw yellow polygon (rectangle) with corners at glColor3f(1.0, 1.0, 0.0); glBegin(GL_POLYGON); //绘制开

拓幻图形学工程师教学手册(第一讲)|一字一字敲出OpenGL学习教程

动机首先申明,我是拓幻科技图形处理工程师,自己接触OpenGL,图形图像等方面也有六年多了,很多人其实并不了解这方面,也不了解如何系统地去学,我觉得基于我硕士时期的课程和经验给大家.这些资料和经验也得感谢我的老师,来自普渡大学的终生教授迈克 贝利(Mike Bailey). 以此连载OpenGL学习教程,给大家讲解,一起学习一下,不对之处,欢迎大家指出讨论. 所有渲染工作都离不开OpenGL, 着色器(Shader)这些,如果你和我一样对图形处理比较感兴趣的话,可能你和当初的我有着同样的困惑:如

Direct3D 光照和材质

  今天我们来学习下Direct3D里面的光源和材质. 四大光照类型: 环境光 Ambient Light 一个物体没有被光照直接照射,通过每一些物体反射的光线到达这个物体,它也有可能被看到.这种称为环境光 漫反射光 Diffuse Light 这种类型光沿着特定的方向传播,当达到某一个表面,它会向四周方向均匀反射(重点考虑反射光的空间位置和方向) 镜面反射光 Specular Light 当此类光到达一个表面时,严格地沿着一个方向反射. 自发光 Emissive Light 自发光就是对象自己