Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 12

BÀI THỰC HÀNH SỐ 6 - 3D

1 – VẬT LIỆU VÀ ÁNH SÁNG

Trong bài thực hành này, chúng ta tạo một hình cầu bán kính 2 đơn vị có tâm trùng với gốc tọa
độ, camera nằm trên phía dương trục z. Ngoài ra, chúng ta tạo hai nguồn sáng nằm trên trục x, một
nguồn sáng nằm ở phía dương trục x, một nguồn sáng nằm ở phía âm của trục x. Vị trí và màu của hai
nguồn sáng này được định nghĩa như sau:

const GLfloat leftLightDiffColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };


const GLfloat leftLightSpecColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat leftLightAmbColor[] = { 0.1f, 0.1f, 0.1f, 1.0f};
const GLfloat leftLightPos[] = { -5.0, 0.0, 0.0, 0.0 };

const GLfloat rightLightDiffColor[] = { 0.0f, 1.0f, 0.0f, 1.0f };


const GLfloat rightLightSpecColor[] = { 0.0f, 1.0f, 0.0f, 1.0f };
const GLfloat rightLightAmbColor[] = { 0.1f, 0.1f, 0.1f, 1.0f};
const GLfloat rightLightPos[] = { 5.0, 0.0, 0.0, 0.0 };
Để thiết lập màu, vị trí và kích hoạt hai nguồn sáng này, trong hàm myInit() chúng ta sử dụng câu lệnh
sau:
void myInit()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);

//set up right light


glLightfv(GL_LIGHT0, GL_POSITION, rightLightPos);
glLightfv(GL_LIGHT0, GL_AMBIENT, rightLightAmbColor);
glLightfv(GL_LIGHT0, GL_DIFFUSE, rightLightDiffColor);
glLightfv(GL_LIGHT0, GL_SPECULAR, rightLightSpecColor);
glEnable(GL_LIGHT0);

//set up left light


glLightfv(GL_LIGHT1, GL_POSITION, leftLightPos);
glLightfv(GL_LIGHT1, GL_AMBIENT, leftLightAmbColor);
glLightfv(GL_LIGHT1, GL_DIFFUSE, leftLightDiffColor);
glLightfv(GL_LIGHT1, GL_SPECULAR, leftLightSpecColor);
glEnable(GL_LIGHT1);
}
Như chúng ta thấy, nguồn sáng nằm phía âm của trục x phát ra ánh sáng trắng còn nguồn sáng nằm
phía dương trục x phát ra ánh sáng màu lục.
Bước tiếp theo, chúng ta phải định nghĩa các hệ số phản xạ ánh sáng cho hình cầu như sau:

GLfloat ambient[] = { 0.1, 0.1, 0.1, 1.0f };


GLfloat diffuse[] = { 0.0, 1.0, 0.0, 1.0f };
GLfloat specular[] = { 0.0, 1.0, 0.0, 1.0f };

1
GLfloat shiness = 100;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shiness);
Như chúng ta thấy,
- Đối với thành phần ánh sáng khuyếch tán, hình cầu này phản xạ 100% ánh sáng màu lục và
hấp thụ hoàn tòan thành phần ánh sáng màu đỏ và màu xanh của nguồn sáng. Vì thế hai nửa
của hình cầu đều có ánh sáng khuyếch tán màu lục.
- Đối với thành phần ánh sáng phản chiếu, hình cầu này cũng phản xạ 100% ánh sáng màu lục
và hấp thụ hoàn tòan thành phần ánh sáng màu đỏ và màu xanh của nguồn sáng. Vì thế hai nửa
của hình cầu đều có ánh sáng phản chiếu màu lục.
- Tham số shiness phản ánh độ tập trung của phần sáng phản chiếu và có giá trị từ 0 đến 128.
Trong đoạn chương trình trên, shiness có giá trị là 100 và vùng sáng phản chiếu cũng khá tập
trung.

Sau đây là toàn bộ mã nguồn của chương trình:


#include "stdafx.h"

#include "Canvas.h"

#define PI 3.1415926

int nHeight = 600;


int nWidth = 600;

Canvascvs(nWidth, nHeight, "Material");

const GLfloat leftLightDiffColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };


const GLfloat leftLightSpecColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat leftLightAmbColor[] = { 0.1f, 0.1f, 0.1f, 1.0f};
const GLfloat leftLightPos[] = { -5.0, 0.0, 0.0, 0.0 };

const GLfloat rightLightDiffColor[] = { 0.0f, 1.0f, 0.0f, 1.0f };


const GLfloat rightLightSpecColor[] = { 0.0f, 1.0f, 0.0f, 1.0f };
const GLfloat rightLightAmbColor[] = { 0.1f, 0.1f, 0.1f, 1.0f};
const GLfloat rightLightPos[] = { 5.0, 0.0, 0.0, 0.0 };

void myInit()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);

//set up right light


glLightfv(GL_LIGHT0, GL_POSITION, rightLightPos);
glLightfv(GL_LIGHT0, GL_AMBIENT, rightLightAmbColor);
glLightfv(GL_LIGHT0, GL_DIFFUSE, rightLightDiffColor);

2
glLightfv(GL_LIGHT0, GL_SPECULAR, rightLightSpecColor);
glEnable(GL_LIGHT0);

//set up left light


glLightfv(GL_LIGHT1, GL_POSITION, leftLightPos);
glLightfv(GL_LIGHT1, GL_AMBIENT, leftLightAmbColor);
glLightfv(GL_LIGHT1, GL_DIFFUSE, leftLightDiffColor);
glLightfv(GL_LIGHT1, GL_SPECULAR, leftLightSpecColor);
glEnable(GL_LIGHT1);
}
void mySetup(int width, int height)
{
glViewport(0, 0, width, height); // reset the viewport to new dimensions
glMatrixMode(GL_PROJECTION); // set projection matrix current matrix
glLoadIdentity(); // reset projection matrix

// calculate aspect ratio of window


gluPerspective(60.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);

glMatrixMode(GL_MODELVIEW); // set modelview matrix


glLoadIdentity(); // reset modelview matrix
}
void myDisplay()
{
cvs.clearScreen();

glLoadIdentity();
gluLookAt(0.0, 0.0, 6.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

//draw the chest


GLfloat ambient[] = { 0.1, 0.1, 0.1, 1.0f };
GLfloat diffuse[] = { 0.0, 1.0, 0.0, 1.0f };
GLfloat specular[] = { 0.0, 1.0, 0.0, 1.0f };
GLfloat shiness = 100.8;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shiness);

glutSolidSphere(2.0, 100, 100);

glutSwapBuffers();
glFlush();
}

void myReshape(int cx, int cy)


{
cvs.setViewport(0, nWidth, 0, nHeight);
mySetup(cx, cy);
myDisplay();

3
}

int main(int argc, char* argv[])


{
cvs.setBackgroundColor(0.0, 0.0, 0.0);
cvs.setColor(0.0, 0.0, 0.0);

myInit();

glutReshapeFunc(myReshape);
glutDisplayFunc(myDisplay);

glutMainLoop();
return 0;
}

Đọc hiểu và hiện thực chương trình trên.

Hãy thực hiện những sửa đổi sau đây:


a) Đối với nguồn sáng phía dương trục x, thay đổi ánh sáng khuyếch tán của nó như sau:
const GLfloat rightLightDiffColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };
khi đó nửa hình cầu bên tay phải có màu đen, bởi vì phần ánh sáng khuyếch tán của nguồn sáng
không có thành phần ánh sáng màu lục. Tuy nhiên phần ánh sáng phản chiếu vẫn có màu lục, bởi
vì thành phần phản chiếu của nguồn sáng có ánh sáng màu lục.
Hãy dịch và chạy chương trình.

b) Bây giờ thay đổi hệ số phản chiếu của vật liệu để cho nó phản xạ 100% cả ba thành phần ánh
sáng của nguồn sáng:
GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0f };
Khi đó phần ánh sáng phản chiếu của nửa tay trái của hình cầu có màu trắng, giống như màu
sắc của nguồn sáng.
Hãy dịch và chạy chương trình.

c) Tiến hành sửa đổi nguồn sáng và hệ số phản xạ của vật liệu để cảm nhận được sự ảnh hưởng
của các tham số đến màu sắc của vật thể.

2 – VẼ CÂY THÔNG NOEL VÀ ÔNG GIÀ NOEL


Chương trình sau đây vẽ cây thông Noel và ông già Noel
#include "stdafx.h"

#include "Canvas.h"

#define PI 3.1415926

int nHeight = 600;


int nWidth = 600;

Canvascvs(nWidth, nHeight, "Material");

4
const GLfloat leftLightColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat leftLightAmbColor[] = { 0.1f, 0.1f, 0.1f, 1.0f};
const GLfloat leftLightPos[] = { 5.0, 0.0, 0.0, 0.0 };

const GLfloat rightLightColor[] = { 0.0f, 1.0f, 0.0f, 1.0f };


const GLfloat rightLightAmbColor[] = { 0.1f, 0.1f, 0.1f, 1.0f};
const GLfloat rightLightPos[] = { -5.0, 0.0, 0.0, 0.0 };

GLboolean m_leftlightOn = GL_TRUE;


GLboolean m_rightlightOn = GL_TRUE;

GLboolean m_wireframeOn = GL_FALSE;


GLboolean m_smoothshadeModeOn = GL_FALSE;

float m_angle = 0.0;

void myInit()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);

//set up right light


glLightfv(GL_LIGHT0, GL_AMBIENT, rightLightAmbColor);
glLightfv(GL_LIGHT0, GL_DIFFUSE, rightLightColor);
glLightfv(GL_LIGHT0, GL_SPECULAR, rightLightColor);

//set up left light


glLightfv(GL_LIGHT1, GL_AMBIENT, leftLightAmbColor);
glLightfv(GL_LIGHT1, GL_DIFFUSE, leftLightColor);
glLightfv(GL_LIGHT1, GL_SPECULAR, leftLightColor);
}
void mySetup(int width, int height)
{
glViewport(0, 0, width, height); // reset the viewport to new dimensions
glMatrixMode(GL_PROJECTION); // set projection matrix current matrix
glLoadIdentity(); // reset projection matrix

// calculate aspect ratio of window


gluPerspective(60.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);

glMatrixMode(GL_MODELVIEW); // set modelview matrix


glLoadIdentity(); // reset modelview matrix

}
void myDisplay()
{
int i;
float size;
size = 1.0;

5
cvs.clearScreen();

glLoadIdentity();
gluLookAt(6.0, 4.0, 6.0, 0.0, 0.0, 2.0*size, 0.0, 1.0, 0.0);

glRotatef(m_angle, 0.0, 1.0, 0.0);

//draw the chest


//copper
GLfloat ambient[] = { 0.19125, 0.0735, 0.0225, 1.0f };
GLfloat diffuse[] = { 0.7038, 0.27048, 0.0828, 1.0f };
GLfloat specular[] = { 0.256777, 0.137622, 0.086014, 1.0f };
GLfloat shiness = 100.8;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shiness);

glPushMatrix();
glutSolidSphere(size, 100, 100);
glPopMatrix();

//draw the abdomen


glPushMatrix();
glTranslated(0.0, -1.8*size, 0.0);
glutSolidSphere(1.3*size, 20, 20);
glPopMatrix();

//draw the head


glPushMatrix();
glTranslated(0.0, 1.4*size, 0.0);
glutSolidSphere(0.8*size, 20, 20);
glPopMatrix();

//draw nose
ambient[0] = 1.0; ambient[1] = 0.0;ambient[2] = 0.0;
diffuse[0] = 1.0; diffuse[1] = 0.0;diffuse[2] = 0.0;
specular[0] = 1.0; specular[1] = 0.0;specular[2] = 0.0;
shiness = 100.8;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shiness);

glPushMatrix();
glTranslated(0.0, 1.4*size, 0.0);
glTranslated(0.0, 0.0, 0.8*size);
glutSolidSphere(0.3*size, 20, 20);

6
glPopMatrix();

//draw left eye


glPushMatrix();
glTranslated(0.0, 1.5*size, 0.0);
glTranslated(0.0, 0.0, 0.60*size);
glTranslated(0.4*size, 0.0, 0.0);
glutSolidSphere(0.15*size, 20, 20);
glPopMatrix();

//draw right eye


glPushMatrix();
glTranslated(0.0, 1.5*size, 0.0);
glTranslated(0.0, 0.0, 0.60*size);
glTranslated(-0.4*size, 0.0, 0.0);
glutSolidSphere(0.15*size, 20, 20);
glPopMatrix();

//draw the hat


GLUquadricObj* obj;
glPushMatrix();
glTranslated(0.0, 2.0*size, 0.0);
glRotated(90, 1.0, 0.0, 0.0);
obj = gluNewQuadric();
gluQuadricDrawStyle(obj, GLU_LINE);
gluCylinder(obj, size, size, 0.1*size, 30, 1);
glPopMatrix();

glPushMatrix();
glTranslated(0.0, 2.9*size, 0.0);
glRotated(90, 1.0, 0.0, 0.0);
obj = gluNewQuadric();
gluQuadricDrawStyle(obj, GLU_LINE);
gluCylinder(obj, 0.7*size, 0.7*size, size, 30, 10);
glPopMatrix();

//draw left hand


glPushMatrix();
glTranslated(0.0, 0.5*size, 0.0);
glRotated(90, 0.0, 1.0, 0.0);
obj = gluNewQuadric();
gluQuadricDrawStyle(obj, GLU_FILL);
gluCylinder(obj, 0.4*size, 0.4*size, 3*size, 30, 10);
glPopMatrix();

//draw right hand

7
glPushMatrix();
glTranslated(0.0, 0.5*size, 0.0);
glRotated(-90, 0.0, 1.0, 0.0);
obj = gluNewQuadric();
gluQuadricDrawStyle(obj, GLU_FILL);
gluCylinder(obj, 0.4*size, 0.4*size, 3*size, 30, 10);
glPopMatrix();

//draw noel tree


glPushMatrix();
glTranslated(0.0, 0.0, 5.0*size);
glRotated(-90, 1.0, 0.0, 0.0);
glutSolidCone(0.8*size, 2.5*size, 30, 20);
glPopMatrix();

glPushMatrix();
glTranslated(0.0, 0.0, 5.0*size);
glTranslated(0.0, -1.0*size, 0.0);
glRotated(-90, 1.0, 0.0, 0.0);
glutSolidCone(0.8*size, 2.5*size, 30, 20);
glPopMatrix();

glPushMatrix();
glTranslated(0.0, 0.0, 5.0*size);
glTranslated(0.0, 1.0*size, 0.0);
glRotated(-90, 1.0, 0.0, 0.0);
glutSolidCone(0.8*size, 2.5*size, 30, 20);
glPopMatrix();

glPushMatrix();
glTranslated(0.0, 0.0, 5.0*size);
glTranslated(0.0, -3.0*size, 0.0);
glRotated(-90, 1.0, 0.0, 0.0);
obj = gluNewQuadric();
gluQuadricDrawStyle(obj, GLU_FILL);
gluCylinder(obj, 0.4*size, 0.4*size, 3*size, 30, 10);
glPopMatrix();

//left light
if(m_leftlightOn)
{
glPushMatrix();
glLightfv(GL_LIGHT1, GL_POSITION, leftLightPos);
glTranslatef(leftLightPos[0], leftLightPos[1], leftLightPos[2]);
glEnable(GL_LIGHT1);
glPopMatrix();
}
else
glDisable(GL_LIGHT1);

8
//right light
if(m_rightlightOn)
{
glPushMatrix();
glLightfv(GL_LIGHT0, GL_POSITION, rightLightPos);
glTranslatef(rightLightPos[0], rightLightPos[1], rightLightPos[2]);
glEnable(GL_LIGHT0);
glPopMatrix();
}
else
glDisable(GL_LIGHT0);

if(m_wireframeOn)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

if(m_smoothshadeModeOn)
glShadeModel(GL_SMOOTH);
else
glShadeModel(GL_FLAT);

glutSwapBuffers();
glFlush();
}

void myReshape(int cx, int cy)


{
cvs.setViewport(0, nWidth, 0, nHeight);
mySetup(cx, cy);
myDisplay();
}
void myIdle()
{

float dt = 0.5;
m_angle = m_angle + dt;
if(m_angle >= 360)
m_angle = 0;
myDisplay();
}
void myKeyboard(unsigned char theKey, int mouseX, int mouseY)
{
switch(theKey)
{
case 'r':
m_rightlightOn = !m_rightlightOn;
break;
case 'l':

9
m_leftlightOn = !m_leftlightOn;
break;
case 'w':
m_wireframeOn = !m_wireframeOn;
break;
case 's':
m_smoothshadeModeOn = !m_smoothshadeModeOn;
break;
default:
break;
}
}
int main(int argc, char* argv[])
{
cvs.setBackgroundColor(0.0, 0.0, 0.0);
cvs.setColor(0.0, 0.0, 0.0);

myInit();

glutReshapeFunc(myReshape);
glutDisplayFunc(myDisplay);
glutIdleFunc(myIdle);
glutKeyboardFunc(myKeyboard);

glutMainLoop();
return 0;
}

Đọc hiểu và hiện thực đoạn chương trình trên.


Đoạn chương trình trên mới tiến hành gán vật liệu cho phần ngực và mũi của ông già Noel. Hãy gán
vật liệu cho các phần khác của ông già Noel cũng như cây thông Noel. Tham khảo bảng sau đây:
nền:
khuyếch tán: phản chiếu: hệ số mũ:
Vật liệu ρ ar, ρ ag,
ρ dr, ρ dg, ρ db ρ sr, ρ sg, ρ sb f
ρ ab
Nhựa đen 0.0 0.01 0.5 32
0.0 0.01 0.5
0.0 0.01 0.5
Đồng thau 0.329412 0.780392 0.992157 27.8974
0.223529 0.568627 0.941176
0.027451 0.113725 0.807843
Đồng thiếc 0.2125 0.714 0.393548 25.6
0.1275 0.4284 0.271906
0.027451 0.18144 0.166721
Crom 0.25 0.4 0.774597 76.8
0.25 0.4 0.774597
0.25 0.4 0.774597
Đồng 0.19125 0.7038 0.256777 12.8
0.0735 0.27048 0.137622

10
0.025 0.0828 0.086014
Vàng 0.24725 0.75164 0.628281 51.2
0.1995 0.60648 0.555802
0.0745 0.22648 0.366065
Hợp kim 0.10588 0.427451 0.3333 9.84615
thiếc 0.058824 0.470588 0.3333
0.113725 0.541176 0.521569
Bạc 0.19225 0.50754 0.508273 51.2
0.19225 0.50754 0.508273
0.19225 0.50754 0.508273
Bạc đánh 0.23125 0.2775 0.773911 89.6
bóng 0.23125 0.2775 0.773911
0.23125 0.2775 0.773911

3 – THÊM CHỨC NĂNG TÔ MÀU CHO ASSIGNMENT 2

Để có thể tô màu cho đối tượng, cần phải thực hiện các công việc sau:
- Thiết lập nguồn sáng ở vị trí (0, 10, 0), nguồn sáng có màu sắc là màu trắng.
- Thiết lập đặc tính của vật liệu.
- Cần phải gửi pháp tuyến xuống đường ống đồ họa. Thêm vào hàm Draw(…) của lớp Mesh
đoạn mã cho phép tô màu cho đối tượng. Khi tô màu, ngoài việc gửi tọa độ đỉnh xuống đường
ống đồ họa, còn phải gửi thêm vector pháp tuyến của đỉnh đó. Ở đây, chúng ta sử dụng hai
phương pháp tô màu là tô màu phẳng và tô màu trơn.
o Đối với phương pháp tô màu phẳng: vector pháp tuyến của đỉnh chính là vector pháp
tuyến của mặt chứa đỉnh đó. Nhược điểm của phương pháp này là nhìn thấy đường biên
giữa các mặt của lưới đa giác.

Dùng phương pháp tô màu phẳng, có thể nhìn thấy rõ ranh giới

11
giữa các mặt tam giác của lưới đa giác
o Đối với phương pháp tô màu trơn: vector pháp tuyến của đỉnh được tính là trung bình
cộng của các vector pháp tuyến của các mặt xung quanh đỉnh đó. Chính vì thế ranh giới
giữa các mặt của lưới đa giác sẽ biến mất.

Trong phương pháp tô màu trơn,


ranh giới giữa các mặt tam giác biến mất, bề mặt nhìn trơn tru hơn

12

You might also like