问题出在我观察房间的角落时。 当我这样做时,镜面闪电会变得更亮:
...当我看到平坦的墙壁时却没有:
我在这里发布完整的代码:
#include <windows.h>
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
#define GLEW_STATIC
#include <glew.h>
#include <GL/glfw.h>
template <typename T>
T clamp(T value, T min, T max) {
if (value < min) return min;
if (value > max) return max;
return value;
}
// CAMERA PROPERTIES
float posX = 0.0f, posY = 0.0f, posZ = 5.0f; // position
float rotX = 0.0f, rotY = 3.0f; // rotation
// movement speed and mouse sensitivity
float speed = 0.05f;
const float mouseSensitivity = 0.005f;
// MOUSE INPUT TRACKING
double lastMouseX, lastMouseY;
// ROOM BOUNDARIES
float x_min = -5.0f, x_max = 5.0f;
float z_min = -5.0f, z_max = 5.0f;
float collision = 0.2f;
void checkCollision(float &posX, float &posZ) {
if (posX < x_min + collision) posX = x_min + collision; // left
if (posX > x_max - collision) posX = x_max - collision; // right
if (posZ < z_min + collision) posZ = z_min + collision; // back
if (posZ > z_max - collision) posZ = z_max - collision; // front
}
void drawLightMarker() {
glDisable(GL_LIGHTING);
glColor3f(1.0f, 1.0f, 0.0f);
glPushMatrix();
glTranslatef(0.0f, 0.5f, 0.0f);
glBegin(GL_QUADS);
// FRONT FACE
glVertex3f(-0.1f, -0.1f, 0.1f);
glVertex3f(0.1f, -0.1f, 0.1f);
glVertex3f(0.1f, 0.1f, 0.1f);
glVertex3f(-0.1f, 0.1f, 0.1f);
// BACK FACE
glVertex3f(-0.1f, -0.1f, -0.1f);
glVertex3f(0.1f, -0.1f, -0.1f);
glVertex3f(0.1f, 0.1f, -0.1f);
glVertex3f(-0.1f, 0.1f, -0.1f);
// LEFT FACE
glVertex3f(-0.1f, -0.1f, -0.1f);
glVertex3f(-0.1f, -0.1f, 0.1f);
glVertex3f(-0.1f, 0.1f, 0.1f);
glVertex3f(-0.1f, 0.1f, -0.1f);
// RIGHT FACE
glVertex3f(0.1f, -0.1f, -0.1f);
glVertex3f(0.1f, -0.1f, 0.1f);
glVertex3f(0.1f, 0.1f, 0.1f);
glVertex3f(0.1f, 0.1f, -0.1f);
// TOP FACE
glVertex3f(-0.1f, 0.1f, 0.1f);
glVertex3f(0.1f, 0.1f, 0.1f);
glVertex3f(0.1f, 0.1f, 0.1f);
glVertex3f(-0.1f, 0.1f, 0.1f);
// BOTTOM FACE
glVertex3f(-0.1f, -0.1f, -0.1f);
glVertex3f(0.1f, -0.1f, -0.1f);
glVertex3f(0.1f, -0.1f, 0.1f);
glVertex3f(-0.1f, -0.1f, 0.1f);
glEnd();
glPopMatrix();
glEnable(GL_LIGHTING);
}
// ********TO FIX********
void setupLightning() {
// PROPERTIES
GLfloat ambient[] = {0.0f, 0.0f, 0.0f, 1.0f};
GLfloat diffuse[] = {2.0f, 2.0f, 2.0f, 1.0f};
GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat mat_specular[] = {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat shininess[] = {20.0f};
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
// ATTENUATION
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.5f);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.1f);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.01f);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_NORMALIZE);
}
void processInput(GLFWwindow *window) {
// FORWARD/BACKWARD MOVEMENT
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
posX += speed * sin(rotY);
posZ += speed * cos(rotY);
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
posX -= speed * sin(rotY);
posZ -= speed * cos(rotY);
}
// LEFT/RIGHT STRAFING
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
posX += speed * cos(rotY);
posZ -= speed * sin(rotY);
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
posX -= speed * cos(rotY);
posZ += speed * sin(rotY);
}
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwDestroyWindow(window);
glfwTerminate();
}
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) speed = 0.5f;
if (glfwGetKey(window, GLFW_KEY_BACKSPACE) == GLFW_PRESS) speed = 0.05f;
//checkCollision(posX, posZ);
}
void mouseCallback(GLFWwindow* window, double xpos, double ypos) {
// calculate mouse delta
double deltaX = xpos - lastMouseX;
double deltaY = ypos - lastMouseY;
lastMouseX = xpos;
lastMouseY = ypos;
// UPDATE ROTATION
rotY -= deltaX * mouseSensitivity; // Horizontal rotation
rotX -= deltaY * mouseSensitivity; // Vertical rotation
rotX = clamp(rotX, -1.5f, 1.5f);
}
void renderRoom() {
glBegin(GL_QUADS);
// FLOOR
glColor3f(0.5f, 0.5f, 0.5f);
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f(-5.0f, -1.0f, -5.0f);
glVertex3f(5.0f, -1.0f, -5.0f);
glVertex3f(5.0f, -1.0f, 5.0f);
glVertex3f(-5.0f, -1.0f, 5.0f);
// CEILING
glColor3f(0.3f, 0.3f, 0.3f);
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f(-5.0f, 1.0f, -5.0f);
glVertex3f(5.0f, 1.0f, -5.0f);
glVertex3f(5.0f, 1.0f, 5.0f);
glVertex3f(-5.0f, 1.0f, 5.0f);
// WALLS
// back wall
glColor3f(0.8f, 0.2f, 0.2f);
glNormal3f(0.0f, 0.0f, 1.0f);
glVertex3f(-5.0f, -1.0f, -5.0f);
glVertex3f(5.0f, -1.0f, -5.0f);
glVertex3f(5.0f, 1.0f, -5.0f);
glVertex3f(-5.0f, 1.0f, -5.0f);
// front wall
glNormal3f(0.0f, 0.0f, -1.0f);
glVertex3f(-5.0f, -1.0f, 5.0f);
glVertex3f(5.0f, -1.0f, 5.0f);
glVertex3f(5.0f, 1.0f, 5.0f);
glVertex3f(-5.0f, 1.0f, 5.0f);
// left wall
glNormal3f(1.0f, 0.0f, 0.0f);
glVertex3f(-5.0f, -1.0f, -5.0f);
glVertex3f(-5.0f, -1.0f, 5.0f);
glVertex3f(-5.0f, 1.0f, 5.0f);
glVertex3f(-5.0f, 1.0f, -5.0f);
// right wall
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(5.0f, -1.0f, -5.0f);
glVertex3f(5.0f, -1.0f, 5.0f);
glVertex3f(5.0f, 1.0f, 5.0f);
glVertex3f(5.0f, 1.0f, -5.0f);
glEnd();
}
GLFWwindow* initWindowFullScreen() {
// INITIALIZE GLFW
if (!glfwInit()) std::cerr << "Failed to initialize GLFW" << std::endl;
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
if (!monitor) {
glfwTerminate();
std::cerr << "Failed to get primary monitor" << std::endl;
}
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
GLFWwindow* window = glfwCreateWindow(mode->width, mode->height, "3D Room full-screen", monitor, NULL);
if (!window) {
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
return window;
}
int main() {
GLFWwindow* window = initWindowFullScreen();
// MOUSE CALLBACK
glfwSetCursorPosCallback(window, mouseCallback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwGetCursorPos(window, &lastMouseX, &lastMouseY);
setupLightning();
// MAIN LOOP
while (!glfwWindowShouldClose(window)) {
processInput(window);
// RENDERING
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70.0, 800.0 / 600.0, 0.1, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// APPLY CAMERA TRANSFORMATIONS
float lookX = posX + sin(rotY) * cos(rotX);
float lookY = posY + sin(rotX);
float lookZ = posZ + cos(rotY) * cos(rotX);
gluLookAt(posX, posY, posZ, lookX, lookY, lookZ, 0.0f, 1.0f, 0.0f);
GLfloat lightPos[] = {0.0f, 0.5f, 0.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
renderRoom();
drawLightMarker();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
我尝试修改镜面反射、环境光、漫反射闪电,但没有任何效果。
在您使用的平滑着色模式中,三角形的片段是根据顶点的属性进行插值的。
所以,假设你有一个三角形:
v0 --- v1
| /
v2
现在照明效果的镜面反射贡献是根据
v0
、v1
、v2
计算的。当渲染三角形时,所有填充三角形的区域都会被插值。要查看镜面反射贡献,光线需要击中某些顶点 v0、v1、v2。在你的场景中很难满足,因为光的位置是(0,0,0),盒子的每个面都有4个顶点,边长是10。
-------------
|
|
| (L) -> L is position of light
|
|
(Y)------------
Y 是相机的位置。镜面效果基于光线照射到盒子表面时视图方向和反射矢量之间的角度。如上所示,以盒子的左面为例,沿着 L 和 Y 之间的距离,您需要更多顶点。
上面的视图是在 X 轴和 Z 轴上将地板渲染为 [-5,5] 范围内的 100 个四边形时创建的。因此 dx 和 dy 偏移量为 1。左脸以 dz = 1 和 dy = 0.2 偏移量渲染(也是 100 个四边形)。
因此,作为结论,您需要使几何体更密集,才能看到光照效果。在地板上可以看到镜面效果。在左脸上我们看到漫反射效果。