我的OpenGL灯光有点问题。
它正在渲染模型(犹他茶壶)很好,但我有一些奇怪的光照模式。模型应该是平面阴影,只有一个环境光照亮了场景,但最终我的茶壶上遍布着斑驳的光线:
使用SFML在C ++中构建模型加载器只是一个简单的练习。
代码如下:
bool modelLoader(string fileName, vector<GLfloat>& vertices, vector<GLushort>& indices, vector<GLfloat>& normals)
{
fstream object;
string face;
string dataLine;
string lineChar;
GLfloat point;
GLfloat uvs;
GLfloat storedNorm;
GLushort ind;
vector<GLfloat> storedNormals;
vector<GLfloat> storedUVs;
vector<GLfloat> localNormals , localVertices;
vertices.clear();
indices.clear();
object.open(fileName);
if(!object.is_open())
{
printf("Cannot open file: %f \n", fileName);
return false;
}
while(object>>lineChar)
{
if(lineChar == "v" /*|| dataLine.find("vt ") == 0*/ || lineChar == "f" || lineChar == "vn")
{
if(lineChar == "v")
{
//cout<<"v ";
for(int i=0;i<3;++i)
{
object >> point;
//cout << point << " ";
localVertices.push_back(point);
}
//cout<<endl;
}
else if(lineChar == "vn")
{
//cout<<"vn";
for(int j=0;j<3;++j)
{
object >> point;
//cout<<point<<" ";
localNormals.push_back(point);
}
//cout<<endl;
}
else if(lineChar == "f")
{
for(int k=0;k<3;++k)
{
getline(object, face, '/');
ind = atoi(face.c_str());
indices.push_back(ind-1);
object.ignore(2);
//getline(object, face, '/');
//uvs = atoi(face.c_str());
//storedUVs.push_back(uvs);
getline(object, face, ' ');
storedNorm = atoi(face.c_str());
storedNormals.push_back(storedNorm);
}
}
}
}
for (unsigned int i=0; i<indices.size(); ++i )
{
vertices.push_back(localVertices[indices[i]*3]);
vertices.push_back(localVertices[indices[i]*3 + 1]);
vertices.push_back(localVertices[indices[i]*3 + 2]);
normals.push_back(localNormals[(unsigned int) storedNormals[i]*3]);
normals.push_back(localNormals[(unsigned int) storedNormals[i]*3 + 1]);
normals.push_back(localNormals[(unsigned int) storedNormals[i]*3 + 2]);
}
return true;
}
主循环:
int main()
{
// Create the main window
sf::Window App(sf::VideoMode(SC_WIDTH, SC_HEIGHT, 32), "SFML OpenGL");
// Create a clock for measuring time elapsed
sf::Clock Clock;
//output version of OpenGL to the console
cout<<"OpenGL version: "<<glGetString(GL_VERSION)<<endl;
// Create the vectors to hold the object data
vector<GLfloat> vertices;
vector<GLushort> indices;
vector<GLfloat> normals;
//Load model
if(!modelLoader("teapot2.obj", vertices, indices, normals))
{
printf("Failed to load model. Make sure the .obj file has no errors.");
system("pause");
return 0;
}
//enable the use of vertex arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
// tell OpenGL where the vertices are with glVertexPointer()
glVertexPointer(3, GL_FLOAT, 0, &vertices[0]);
glNormalPointer(GL_FLOAT, 0, &normals[0]);
//*************************************************************
// Set color and depth clear value
glClearDepth(1.f);
glClearColor(0.f, 0.f, 0.f, 0.f);
// Enable Z-buffer read and write
glDepthMask(GL_TRUE);
// Set up lighting for the scene
GLfloat ambient[4] = {0.f,0.5f,0.5f, 1.f};
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
// Setup a perspective projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.f, 1.f, 1.f, 500.f);
// Start game loop
while (App.IsOpened())
{
// Process events
sf::Event Event;
while (App.GetEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
App.Close();
// Escape key : exit
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
App.Close();
// Resize event : adjust viewport
if (Event.Type == sf::Event::Resized)
glViewport(0, 0, Event.Size.Width, Event.Size.Height);
}
// Set the active window before using OpenGL commands
// It's useless here because active window is always the same,
// but don't forget it if you use multiple windows or controls
App.SetActive();
if((float)Clock.GetElapsedTime()>REFRESH_RATE){
// Clear colour and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Apply some transformations
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.f, 0.f, -5.f);
glRotatef(45.f, 1.f, 1.f, 1.f);
glPushMatrix();
//draw the triangles with glDrawArrays() and then with glDrawElements()
glDrawArrays(GL_TRIANGLES, 0, vertices.size()/3);
//glDrawElements(GL_TRIANGLES, vertices.size(), GL_UNSIGNED_SHORT, &indices[0]);
//glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, &indices[0]);
glPopMatrix();
Clock.Reset();
}
// Finally, display rendered frame on screen
App.Display();
}
//delete the vertex arrays using glDisableClientState()
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
return EXIT_SUCCESS;
}
有人有任何想法吗?
答案 0 :(得分:1)
OpenGL灯具有所有属性的默认值(例如GL_AMBIENT
,GL_DIFFUSE
等)。在GL_LIGHT0
的情况下,漫反射属性不会设置为零(这是您只需要获得环境光照所需的)。要解决这个问题,你需要做
GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glLightfv( GL_LIGHT0, GL_DIFFUSE, black );
因为,IIRC,其余的光属性已经为零,这应该为您提供仅环境照明,这将消除照明的方向分量。此外,glColorMaterial
的默认模式是GL_AMBIENT_AND_DIFFUSE
,它将环境和漫反射材质属性设置为传入的顶点颜色。您也可以考虑将其切换到仅环境(glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT );
)。
然而,我认为阴影奇怪的根本原因可能是由于非单位长度法线。您可以尝试在进行光照计算之前添加glEnable( GL_NORMALIZE );
。