OpenGL:Shading/Interpolation 不工作
OpenGL: Shading/Interpolation not working
这段代码的目的是生成一个'surface' 具有随机Y 变化,然后让光源照射它并生成亮度区域并在较暗区域执行阴影。问题是,这并没有真正发生。光要么照亮一侧,要么照亮另一侧,这些侧都均匀地亮或暗。我错过了什么?请记住,还有很多代码尚未删除,但这不是我的首要任务,此时我只是想让着色功能正常运行。
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#ifdef MAC
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
//Camera variables
int xangle = -270;
int yangle = 0;
//Control Mode (Rotate mode by default)
int mode = 0;
//Player Position (Y offset so it would not be straddling the grid)
float cubeX = 0;
float cubeY = 0.5;
float cubeZ = 0;
//Vertex arrays for surface
float surfaceX [11][11];
float surfaceY [11][11];
float surfaceZ [11][11];
//Surface Normal arrays
float Nx[11][11];
float Ny[11][11];
float Nz[11][11];
//Color arrays
float R[11][11];
float G[11][11];
float B[11][11];
// Material properties
float Ka = 0.2;
float Kd = 0.4;
float Ks = 0.4;
float Kp = 0.5;
//Random number generator
float RandomNumber(float Min, float Max)
{
return ((float(rand()) / float(RAND_MAX)) * (Max - Min)) + Min;
}
//---------------------------------------
// Initialize material properties
//---------------------------------------
void init_material(float Ka, float Kd, float Ks, float Kp,
float Mr, float Mg, float Mb)
{
// Material variables
float ambient[] = { Ka * Mr, Ka * Mg, Ka * Mb, 1.0 };
float diffuse[] = { Kd * Mr, Kd * Mg, Kd * Mb, 1.0 };
float specular[] = { Ks * Mr, Ks * Mg, Ks * Mb, 1.0 };
// Initialize material
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, Kp);
}
//---------------------------------------
// Initialize light source
//---------------------------------------
void init_light(int light_source, float Lx, float Ly, float Lz,
float Lr, float Lg, float Lb)
{
// Light variables
float light_position[] = { Lx, Ly, Lz, 0.0 };
float light_color[] = { Lr, Lg, Lb, 1.0 };
// Initialize light source
glEnable(GL_LIGHTING);
glEnable(light_source);
glLightfv(light_source, GL_POSITION, light_position);
glLightfv(light_source, GL_AMBIENT, light_color);
glLightfv(light_source, GL_DIFFUSE, light_color);
glLightfv(light_source, GL_SPECULAR, light_color);
glLightf(light_source, GL_CONSTANT_ATTENUATION, 1.0);
glLightf(light_source, GL_LINEAR_ATTENUATION, 0.0);
glLightf(light_source, GL_QUADRATIC_ATTENUATION, 0.0);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
}
//---------------------------------------
// Initialize surface
//---------------------------------------
void init_surface()
{
//Initialize X, select column
for (int i = 0; i < 11; i++)
{
//Select row
for (int j = 0; j < 11; j++)
{
surfaceX[i][j] = i-5;
surfaceY[i][j] = RandomNumber(5, 7) - 5;
surfaceZ[i][j] = j-5;
//std::cout << "Coordinate "<< i << "," << j << std::endl;
}
//std::cout << "Hello world "<< std::endl;
}
//std::cout << "Coordinate -5,-5" << surfaceX[-5][-5] << std::endl;
}
void define_normals()
{
//Define surface normals
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
//Get two tangent vectors
float Ix = surfaceX[i+1][j] - surfaceX[i][j];
float Iy = surfaceY[i+1][j] - surfaceY[i][j];
float Iz = surfaceZ[i+1][j] - surfaceZ[i][j];
float Jx = surfaceX[i][j+1] - surfaceX[i][j];
float Jy = surfaceY[i][j+1] - surfaceY[i][j];
float Jz = surfaceZ[i][j+1] - surfaceZ[i][j];
//Get two tangent vectors
//float Ix = Px[i+1][j] - Px[i][j];
//float Iy = Py[i+1][j] - Py[i][j];
//float Iz = Pz[i+1][j] - Pz[i][j];
//float Jx = Px[i][j+1] - Px[i][j];
//float Jy = Py[i][j+1] - Py[i][j];
//float Jz = Pz[i][j+1] - Pz[i][j];
//Do cross product
Nx[i][j] = Iy * Jz - Iz * Jy;
Ny[i][j] = Iz * Jx - Ix * Jz;
Nz[i][j] = Ix * Jy - Iy * Jx;
//Nx[i][j] = Nx[i][j] * -1;
//Ny[i][j] = Ny[i][j] * -1;
//Nz[i][j] = Nz[i][j] * -1;
float length = sqrt(
Nx[i][j] * Nx[i][j] +
Ny[i][j] * Ny[i][j] +
Nz[i][j] * Nz[i][j]);
if (length > 0)
{
Nx[i][j] /= length;
Ny[j][j] /= length;
Nz[i][j] /= length;
}
}
}
//std::cout << "Surface normal for 0,0: "<< Nx[0][0] << "," << Ny[0][0] << "," << Nz[0][0] << std::endl;
}
void calc_color()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
//Calculate light vector
//Light position, hardcoded for now 0,1,1
float Lx = -1 - surfaceX[i][j];
float Ly = -1 - surfaceY[i][j];
float Lz = -1 - surfaceZ[i][j];
std::cout << "Lx: " << Lx << std::endl;
std::cout << "Ly: " << Ly << std::endl;
std::cout << "Lz: " << Lz << std::endl;
//Grab surface normals
//These are Nx,Ny,Nz due to compiler issues
float Na = Nx[i][j];
float Nb = Ny[i][j];
float Nc = Nz[i][j];
std::cout << "Na: " << Na << std::endl;
std::cout << "Nb: " << Nb << std::endl;
std::cout << "Nc: " << Nc << std::endl;
//Do cross product
float Color = (Na * Lx) + (Nb * Ly) + (Nc * Lz);
std::cout << "Color: " << Color << std::endl;
//Color = Color * -1;
R[i][j] = Color;
G[i][j] = Color;
B[i][j] = Color;
//std::cout << "Color Value: " << std::endl;
////std::cout << "R: " << R[i][j] << std::endl;
//std::cout << "G: " << G[i][j] << std::endl;
//std::cout << "B: " << B[i][j] << std::endl;
}
}
}
//---------------------------------------
// Init function for OpenGL
//---------------------------------------
void init()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//Viewing Window Modified
glOrtho(-7.0, 7.0, -7.0, 7.0, -7.0, 7.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Rotates camera
//glRotatef(30.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
//Project 3 code
init_surface();
define_normals();
//Shading code
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
init_light(GL_LIGHT0, 0, 1, 1, 0.5, 0.5, 0.5);
//init_light(GL_LIGHT1, 0, 0, 1, 0.5, 0.5, 0.5);
//init_light(GL_LIGHT2, 0, 1, 0, 0.5, 0.5, 0.5);
}
void keyboard(unsigned char key, int x, int y)
{
//Controls
//Toggle Mode
if (key == 'q')
{
if(mode == 0)
{
mode = 1;
std::cout << "Switched to Move mode (" << mode << ")" << std::endl;
}
else if(mode == 1)
{
mode = 0;
std::cout << "Switched to Rotate mode (" << mode << ")" << std::endl;
}
}
////Rotate Camera (mode 0)
//Up & Down
else if (key == 's' && mode == 0)
xangle += 5;
else if (key == 'w' && mode == 0)
xangle -= 5;
//Left & Right
else if (key == 'a' && mode == 0)
yangle -= 5;
else if (key == 'd' && mode == 0)
yangle += 5;
////Move Cube (mode 1)
//Forward & Back
else if (key == 'w' && mode == 1)
{
if (cubeZ > -5)
cubeZ = cubeZ - 1;
else
std::cout << "You have struck an invisible wall! (Min Z bounds)" << std::endl;
}
else if (key == 's' && mode == 1)
{
if (cubeZ < 5)
cubeZ = cubeZ + 1;
else
std::cout << "You have struck an invisible wall! (Max Z bounds)" << std::endl;
}
//Strafe
else if (key == 'd' && mode == 1)
{
if (cubeX < 5)
cubeX = cubeX + 1;
else
std::cout << "You have struck an invisible wall! (Max X bounds)" << std::endl;
}
else if (key == 'a' && mode == 1)
{
if (cubeX > -5)
cubeX = cubeX - 1;
else
std::cout << "You have struck an invisible wall! (Min X bounds)" << std::endl;
}
//Up & Down (Cube offset by +0.5 in Y)
else if (key == 'z' && mode == 1)
{
if (cubeY < 5)
cubeY = cubeY + 1;
else
std::cout << "You've gone too high! Come back! (Max Y bounds)" << std::endl;
}
else if (key == 'x' && mode == 1)
{
if (cubeY > 0.5)
cubeY = cubeY - 1;
else
std::cout << "You've reached bedrock! (Min Y bounds)" << std::endl;
}
//Place/Remove block
else if (key == 'e' && mode == 1)
{
//Occupied(cubeX,cubeY,cubeZ);
}
//Redraw objects
glutPostRedisplay();
}
//---------------------------------------
// Display callback for OpenGL
//---------------------------------------
void display()
{
// Clear the screen
//std::cout << "xangle: " << xangle << std::endl;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Rotation Code
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(xangle, 1.0, 0.0, 0.0);
glRotatef(yangle, 0.0, 1.0, 0.0);
//Light Code
init_material(Ka, Kd, Ks, 100 * Kp, 0.8, 0.6, 0.4);
calc_color();
//Draw the squares, select column
for (int i = 0; i <= 9; i++)
{
//Select row
for (int j = 0; j <= 9; j++)
{
glBegin(GL_POLYGON);
//Surface starts at top left
//Counter clockwise
// CALCULATE COLOR HERE
// - calculate direction from surface to light
// - calculate dot product of normal and light direction vector
// - call glColor function
//Calculate light vector
//Light position, hardcoded for now 0,1,1
///float Lx = 0 - surfaceX[i][j];
//float Ly = 1 - surfaceY[i][j];
//float Lz = 1 - surfaceZ[i][j];
//Grab surface normals
//These are Nx,Ny,Nz due to compiler issues
//float Na = Nx[i][j];
//float Nb = Ny[i][j];
//float Nc = Nz[i][j];
//Do cross product
//float Color = (Na * Lx) + (Nb * Ly) + (Nc * Lz);
//???
//glColor3fv(Color);
//glColor3f(0.5*Color,0.5*Color,0.5*Color);
glColor3f(R[i][j], G[i][j], B[i][j]);
glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
glColor3f(R[i][j+1], G[i][j+1], B[i][j+1]);
glVertex3f(surfaceX[i][j+1], surfaceY[i][j+1], surfaceZ[i][j+1]);
glColor3f(R[i+1][j+1], G[i+1][j+1], B[i+1][j+1]);
glVertex3f(surfaceX[i+1][j+1], surfaceY[i+1][j+1], surfaceZ[i+1][j+1]);
glColor3f(R[i+1][j], G[i+1][j], B[i+1][j]);
glVertex3f(surfaceX[i+1][j], surfaceY[i+1][j], surfaceZ[i+1][j]);
glEnd();
}
}
//Draw the normals
for (int i = 0; i <= 10; i++)
{
for (int j = 0; j <= 10; j++)
{
glBegin(GL_LINES);
//glColor3f(0.0, 1.0, 1.0);
float length = 1;
glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
glVertex3f(surfaceX[i][j]+length*Nx[i][j],
surfaceY[i][j]+length*Ny[i][j],
surfaceZ[i][j]+length*Nz[i][j]);
glEnd();
}
}
glEnd();
glFlush();
//Player Cube
//Cube: midx, midy, midz, size
//+Z = Moving TOWARD camera in opengl
//Origin point for reference
glPointSize(10);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
glVertex3f(0, 0, 0);
glEnd();
//Assign Color of Lines
float R = 1;
float G = 1;
float B = 1;
glBegin(GL_LINES);
glColor3f(R, G, B);
////Drawing the grid
//Vertical lines
for (int i = 0; i < 11; i++)
{
int b = -5 + i;
glVertex3f(b, 0, -5);
glVertex3f(b, 0, 5);
}
//Horizontal lines
for (int i = 0; i < 11; i++)
{
int b = -5 + i;
glVertex3f(-5,0,b);
glVertex3f(5,0,b);
}
glEnd();
glEnd();
glFlush();
}
//---------------------------------------
// Main program
//---------------------------------------
int main(int argc, char *argv[])
{
srand(time(NULL));
//Print Instructions
std::cout << "Project 3 Controls: " << std::endl;
std::cout << "q switches control mode" << std::endl;
std::cout << "w,a,s,d for camera rotation" << std::endl;
//Required
glutInit(&argc, argv);
//Window will default to a different size without
glutInitWindowSize(500, 500);
//Window will default to a different position without
glutInitWindowPosition(250, 250);
//
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
//Required
glutCreateWindow("Project 3");
//Required, calls display function
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
//Required
init();
glutMainLoop();
return 0;
}
正在生成表面和法线以及给定顶点的颜色,我只是不明白为什么它不起作用。
表面的光线或亮度是入射光矢量、观察方向和表面法线矢量的函数。
您在渲染平面时错过了设置法线矢量属性。通过glNormal
设置法向量属性,在指定顶点坐标之前:
for (int i = 0; i <= 9; i++)
{
for (int j = 0; j <= 9; j++)
{
glBegin(GL_POLYGON);
glColor3f(R[i][j], G[i][j], B[i][j]);
glNormal3f(Nx[i][j], Ny[i][j], Nz[i][j]);
glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
glColor3f(R[i][j+1], G[i][j+1], B[i][j+1]);
glNormal3f(Nx[i][j+1], Ny[i][j+1], Nz[i][j+1]);
glVertex3f(surfaceX[i][j+1], surfaceY[i][j+1], surfaceZ[i][j+1]);
glColor3f(R[i+1][j+1], G[i+1][j+1], B[i+1][j+1]);
glNormal3f(Nx[i+1][j+1], Ny[i+1][j+1], Nz[i+1][j+1]);
glVertex3f(surfaceX[i+1][j+1], surfaceY[i+1][j+1], surfaceZ[i+1][j+1]);
glColor3f(R[i+1][j], G[i+1][j], B[i+1][j]);
glNormal3f(Nx[i+1][j], Ny[i+1][j], Nz[i+1][j]);
glVertex3f(surfaceX[i+1][j], surfaceY[i+1][j], surfaceZ[i+1][j]);
glEnd();
}
}
但请注意,由于 Gouraud shading of the Legacy OpenGL 标准灯光模型,灯光质量会很低。
另见 .
此外,法向量是反转的。您可以通过交换叉积中的向量来改变方向:
Nx[i][j] = Iz * Jy - Iy * Jz;
Ny[i][j] = Ix * Jz - Iz * Jx;
Nz[i][j] = Iy * Jx - Ix * Jy;
旁注:
请注意,glBegin
/glEnd
sequences, the fixed function matrix stack and fixed function, per vertex light model, is deprecated since decades. See Fixed Function Pipeline and Legacy OpenGL 绘制的那幅画。
阅读 Vertex Specification and Shader 了解最先进的渲染方式。
这段代码的目的是生成一个'surface' 具有随机Y 变化,然后让光源照射它并生成亮度区域并在较暗区域执行阴影。问题是,这并没有真正发生。光要么照亮一侧,要么照亮另一侧,这些侧都均匀地亮或暗。我错过了什么?请记住,还有很多代码尚未删除,但这不是我的首要任务,此时我只是想让着色功能正常运行。
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#ifdef MAC
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
//Camera variables
int xangle = -270;
int yangle = 0;
//Control Mode (Rotate mode by default)
int mode = 0;
//Player Position (Y offset so it would not be straddling the grid)
float cubeX = 0;
float cubeY = 0.5;
float cubeZ = 0;
//Vertex arrays for surface
float surfaceX [11][11];
float surfaceY [11][11];
float surfaceZ [11][11];
//Surface Normal arrays
float Nx[11][11];
float Ny[11][11];
float Nz[11][11];
//Color arrays
float R[11][11];
float G[11][11];
float B[11][11];
// Material properties
float Ka = 0.2;
float Kd = 0.4;
float Ks = 0.4;
float Kp = 0.5;
//Random number generator
float RandomNumber(float Min, float Max)
{
return ((float(rand()) / float(RAND_MAX)) * (Max - Min)) + Min;
}
//---------------------------------------
// Initialize material properties
//---------------------------------------
void init_material(float Ka, float Kd, float Ks, float Kp,
float Mr, float Mg, float Mb)
{
// Material variables
float ambient[] = { Ka * Mr, Ka * Mg, Ka * Mb, 1.0 };
float diffuse[] = { Kd * Mr, Kd * Mg, Kd * Mb, 1.0 };
float specular[] = { Ks * Mr, Ks * Mg, Ks * Mb, 1.0 };
// Initialize material
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, Kp);
}
//---------------------------------------
// Initialize light source
//---------------------------------------
void init_light(int light_source, float Lx, float Ly, float Lz,
float Lr, float Lg, float Lb)
{
// Light variables
float light_position[] = { Lx, Ly, Lz, 0.0 };
float light_color[] = { Lr, Lg, Lb, 1.0 };
// Initialize light source
glEnable(GL_LIGHTING);
glEnable(light_source);
glLightfv(light_source, GL_POSITION, light_position);
glLightfv(light_source, GL_AMBIENT, light_color);
glLightfv(light_source, GL_DIFFUSE, light_color);
glLightfv(light_source, GL_SPECULAR, light_color);
glLightf(light_source, GL_CONSTANT_ATTENUATION, 1.0);
glLightf(light_source, GL_LINEAR_ATTENUATION, 0.0);
glLightf(light_source, GL_QUADRATIC_ATTENUATION, 0.0);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
}
//---------------------------------------
// Initialize surface
//---------------------------------------
void init_surface()
{
//Initialize X, select column
for (int i = 0; i < 11; i++)
{
//Select row
for (int j = 0; j < 11; j++)
{
surfaceX[i][j] = i-5;
surfaceY[i][j] = RandomNumber(5, 7) - 5;
surfaceZ[i][j] = j-5;
//std::cout << "Coordinate "<< i << "," << j << std::endl;
}
//std::cout << "Hello world "<< std::endl;
}
//std::cout << "Coordinate -5,-5" << surfaceX[-5][-5] << std::endl;
}
void define_normals()
{
//Define surface normals
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
//Get two tangent vectors
float Ix = surfaceX[i+1][j] - surfaceX[i][j];
float Iy = surfaceY[i+1][j] - surfaceY[i][j];
float Iz = surfaceZ[i+1][j] - surfaceZ[i][j];
float Jx = surfaceX[i][j+1] - surfaceX[i][j];
float Jy = surfaceY[i][j+1] - surfaceY[i][j];
float Jz = surfaceZ[i][j+1] - surfaceZ[i][j];
//Get two tangent vectors
//float Ix = Px[i+1][j] - Px[i][j];
//float Iy = Py[i+1][j] - Py[i][j];
//float Iz = Pz[i+1][j] - Pz[i][j];
//float Jx = Px[i][j+1] - Px[i][j];
//float Jy = Py[i][j+1] - Py[i][j];
//float Jz = Pz[i][j+1] - Pz[i][j];
//Do cross product
Nx[i][j] = Iy * Jz - Iz * Jy;
Ny[i][j] = Iz * Jx - Ix * Jz;
Nz[i][j] = Ix * Jy - Iy * Jx;
//Nx[i][j] = Nx[i][j] * -1;
//Ny[i][j] = Ny[i][j] * -1;
//Nz[i][j] = Nz[i][j] * -1;
float length = sqrt(
Nx[i][j] * Nx[i][j] +
Ny[i][j] * Ny[i][j] +
Nz[i][j] * Nz[i][j]);
if (length > 0)
{
Nx[i][j] /= length;
Ny[j][j] /= length;
Nz[i][j] /= length;
}
}
}
//std::cout << "Surface normal for 0,0: "<< Nx[0][0] << "," << Ny[0][0] << "," << Nz[0][0] << std::endl;
}
void calc_color()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
//Calculate light vector
//Light position, hardcoded for now 0,1,1
float Lx = -1 - surfaceX[i][j];
float Ly = -1 - surfaceY[i][j];
float Lz = -1 - surfaceZ[i][j];
std::cout << "Lx: " << Lx << std::endl;
std::cout << "Ly: " << Ly << std::endl;
std::cout << "Lz: " << Lz << std::endl;
//Grab surface normals
//These are Nx,Ny,Nz due to compiler issues
float Na = Nx[i][j];
float Nb = Ny[i][j];
float Nc = Nz[i][j];
std::cout << "Na: " << Na << std::endl;
std::cout << "Nb: " << Nb << std::endl;
std::cout << "Nc: " << Nc << std::endl;
//Do cross product
float Color = (Na * Lx) + (Nb * Ly) + (Nc * Lz);
std::cout << "Color: " << Color << std::endl;
//Color = Color * -1;
R[i][j] = Color;
G[i][j] = Color;
B[i][j] = Color;
//std::cout << "Color Value: " << std::endl;
////std::cout << "R: " << R[i][j] << std::endl;
//std::cout << "G: " << G[i][j] << std::endl;
//std::cout << "B: " << B[i][j] << std::endl;
}
}
}
//---------------------------------------
// Init function for OpenGL
//---------------------------------------
void init()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//Viewing Window Modified
glOrtho(-7.0, 7.0, -7.0, 7.0, -7.0, 7.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Rotates camera
//glRotatef(30.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
//Project 3 code
init_surface();
define_normals();
//Shading code
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
init_light(GL_LIGHT0, 0, 1, 1, 0.5, 0.5, 0.5);
//init_light(GL_LIGHT1, 0, 0, 1, 0.5, 0.5, 0.5);
//init_light(GL_LIGHT2, 0, 1, 0, 0.5, 0.5, 0.5);
}
void keyboard(unsigned char key, int x, int y)
{
//Controls
//Toggle Mode
if (key == 'q')
{
if(mode == 0)
{
mode = 1;
std::cout << "Switched to Move mode (" << mode << ")" << std::endl;
}
else if(mode == 1)
{
mode = 0;
std::cout << "Switched to Rotate mode (" << mode << ")" << std::endl;
}
}
////Rotate Camera (mode 0)
//Up & Down
else if (key == 's' && mode == 0)
xangle += 5;
else if (key == 'w' && mode == 0)
xangle -= 5;
//Left & Right
else if (key == 'a' && mode == 0)
yangle -= 5;
else if (key == 'd' && mode == 0)
yangle += 5;
////Move Cube (mode 1)
//Forward & Back
else if (key == 'w' && mode == 1)
{
if (cubeZ > -5)
cubeZ = cubeZ - 1;
else
std::cout << "You have struck an invisible wall! (Min Z bounds)" << std::endl;
}
else if (key == 's' && mode == 1)
{
if (cubeZ < 5)
cubeZ = cubeZ + 1;
else
std::cout << "You have struck an invisible wall! (Max Z bounds)" << std::endl;
}
//Strafe
else if (key == 'd' && mode == 1)
{
if (cubeX < 5)
cubeX = cubeX + 1;
else
std::cout << "You have struck an invisible wall! (Max X bounds)" << std::endl;
}
else if (key == 'a' && mode == 1)
{
if (cubeX > -5)
cubeX = cubeX - 1;
else
std::cout << "You have struck an invisible wall! (Min X bounds)" << std::endl;
}
//Up & Down (Cube offset by +0.5 in Y)
else if (key == 'z' && mode == 1)
{
if (cubeY < 5)
cubeY = cubeY + 1;
else
std::cout << "You've gone too high! Come back! (Max Y bounds)" << std::endl;
}
else if (key == 'x' && mode == 1)
{
if (cubeY > 0.5)
cubeY = cubeY - 1;
else
std::cout << "You've reached bedrock! (Min Y bounds)" << std::endl;
}
//Place/Remove block
else if (key == 'e' && mode == 1)
{
//Occupied(cubeX,cubeY,cubeZ);
}
//Redraw objects
glutPostRedisplay();
}
//---------------------------------------
// Display callback for OpenGL
//---------------------------------------
void display()
{
// Clear the screen
//std::cout << "xangle: " << xangle << std::endl;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Rotation Code
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(xangle, 1.0, 0.0, 0.0);
glRotatef(yangle, 0.0, 1.0, 0.0);
//Light Code
init_material(Ka, Kd, Ks, 100 * Kp, 0.8, 0.6, 0.4);
calc_color();
//Draw the squares, select column
for (int i = 0; i <= 9; i++)
{
//Select row
for (int j = 0; j <= 9; j++)
{
glBegin(GL_POLYGON);
//Surface starts at top left
//Counter clockwise
// CALCULATE COLOR HERE
// - calculate direction from surface to light
// - calculate dot product of normal and light direction vector
// - call glColor function
//Calculate light vector
//Light position, hardcoded for now 0,1,1
///float Lx = 0 - surfaceX[i][j];
//float Ly = 1 - surfaceY[i][j];
//float Lz = 1 - surfaceZ[i][j];
//Grab surface normals
//These are Nx,Ny,Nz due to compiler issues
//float Na = Nx[i][j];
//float Nb = Ny[i][j];
//float Nc = Nz[i][j];
//Do cross product
//float Color = (Na * Lx) + (Nb * Ly) + (Nc * Lz);
//???
//glColor3fv(Color);
//glColor3f(0.5*Color,0.5*Color,0.5*Color);
glColor3f(R[i][j], G[i][j], B[i][j]);
glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
glColor3f(R[i][j+1], G[i][j+1], B[i][j+1]);
glVertex3f(surfaceX[i][j+1], surfaceY[i][j+1], surfaceZ[i][j+1]);
glColor3f(R[i+1][j+1], G[i+1][j+1], B[i+1][j+1]);
glVertex3f(surfaceX[i+1][j+1], surfaceY[i+1][j+1], surfaceZ[i+1][j+1]);
glColor3f(R[i+1][j], G[i+1][j], B[i+1][j]);
glVertex3f(surfaceX[i+1][j], surfaceY[i+1][j], surfaceZ[i+1][j]);
glEnd();
}
}
//Draw the normals
for (int i = 0; i <= 10; i++)
{
for (int j = 0; j <= 10; j++)
{
glBegin(GL_LINES);
//glColor3f(0.0, 1.0, 1.0);
float length = 1;
glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
glVertex3f(surfaceX[i][j]+length*Nx[i][j],
surfaceY[i][j]+length*Ny[i][j],
surfaceZ[i][j]+length*Nz[i][j]);
glEnd();
}
}
glEnd();
glFlush();
//Player Cube
//Cube: midx, midy, midz, size
//+Z = Moving TOWARD camera in opengl
//Origin point for reference
glPointSize(10);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POINTS);
glVertex3f(0, 0, 0);
glEnd();
//Assign Color of Lines
float R = 1;
float G = 1;
float B = 1;
glBegin(GL_LINES);
glColor3f(R, G, B);
////Drawing the grid
//Vertical lines
for (int i = 0; i < 11; i++)
{
int b = -5 + i;
glVertex3f(b, 0, -5);
glVertex3f(b, 0, 5);
}
//Horizontal lines
for (int i = 0; i < 11; i++)
{
int b = -5 + i;
glVertex3f(-5,0,b);
glVertex3f(5,0,b);
}
glEnd();
glEnd();
glFlush();
}
//---------------------------------------
// Main program
//---------------------------------------
int main(int argc, char *argv[])
{
srand(time(NULL));
//Print Instructions
std::cout << "Project 3 Controls: " << std::endl;
std::cout << "q switches control mode" << std::endl;
std::cout << "w,a,s,d for camera rotation" << std::endl;
//Required
glutInit(&argc, argv);
//Window will default to a different size without
glutInitWindowSize(500, 500);
//Window will default to a different position without
glutInitWindowPosition(250, 250);
//
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
//Required
glutCreateWindow("Project 3");
//Required, calls display function
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
//Required
init();
glutMainLoop();
return 0;
}
正在生成表面和法线以及给定顶点的颜色,我只是不明白为什么它不起作用。
表面的光线或亮度是入射光矢量、观察方向和表面法线矢量的函数。
您在渲染平面时错过了设置法线矢量属性。通过glNormal
设置法向量属性,在指定顶点坐标之前:
for (int i = 0; i <= 9; i++)
{
for (int j = 0; j <= 9; j++)
{
glBegin(GL_POLYGON);
glColor3f(R[i][j], G[i][j], B[i][j]);
glNormal3f(Nx[i][j], Ny[i][j], Nz[i][j]);
glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
glColor3f(R[i][j+1], G[i][j+1], B[i][j+1]);
glNormal3f(Nx[i][j+1], Ny[i][j+1], Nz[i][j+1]);
glVertex3f(surfaceX[i][j+1], surfaceY[i][j+1], surfaceZ[i][j+1]);
glColor3f(R[i+1][j+1], G[i+1][j+1], B[i+1][j+1]);
glNormal3f(Nx[i+1][j+1], Ny[i+1][j+1], Nz[i+1][j+1]);
glVertex3f(surfaceX[i+1][j+1], surfaceY[i+1][j+1], surfaceZ[i+1][j+1]);
glColor3f(R[i+1][j], G[i+1][j], B[i+1][j]);
glNormal3f(Nx[i+1][j], Ny[i+1][j], Nz[i+1][j]);
glVertex3f(surfaceX[i+1][j], surfaceY[i+1][j], surfaceZ[i+1][j]);
glEnd();
}
}
但请注意,由于 Gouraud shading of the Legacy OpenGL 标准灯光模型,灯光质量会很低。
另见
此外,法向量是反转的。您可以通过交换叉积中的向量来改变方向:
Nx[i][j] = Iz * Jy - Iy * Jz;
Ny[i][j] = Ix * Jz - Iz * Jx;
Nz[i][j] = Iy * Jx - Ix * Jy;
旁注:
请注意,glBegin
/glEnd
sequences, the fixed function matrix stack and fixed function, per vertex light model, is deprecated since decades. See Fixed Function Pipeline and Legacy OpenGL 绘制的那幅画。
阅读 Vertex Specification and Shader 了解最先进的渲染方式。