我有一个我写过的课来画一个平面并在上面放一个纹理。我也做了一个照明课。看来我的光线会影响固体物体,但它不会改变我飞机上的光线。无论如何,我的飞机似乎总是拥有相同的照明。知道为什么它不工作吗?
这是我运行项目时的样子(圆锥显示灯光的来源):http://i.imgur.com/uEHe7Ea.png
这是我的代码:
class Light
{
public:
//light constructor
void Draw();
private:
GLenum m_LightSource;
float m_Ambient[4];//ambient is light all around
float m_Specular[4];//gleem that hits an object
float m_Diffuse[4];//lights oart of an object
float m_SpotlightWidth;
float m_Position[4];
float m_Attenuation;
float m_MaterialSpecular[4];
float m_MaterialShine[1];
};
void Light::Draw()
{
glPushMatrix();
glTranslatef(m_Position[0], m_Position[1], m_Position[2]); // Move the spotlight.
// Light properties.
glLightfv(m_LightSource, GL_AMBIENT, m_Ambient);
glLightfv(m_LightSource, GL_DIFFUSE, m_Diffuse);
glLightfv(m_LightSource, GL_SPECULAR, m_Specular);
glEnable(m_LightSource);// Enable particular light source.
// Material properties shared by all the spheres.
glMaterialfv(GL_FRONT, GL_SPECULAR, m_MaterialSpecular);
glMaterialfv(GL_FRONT, GL_SHININESS, m_MaterialShine);
if(m_DrawCone)
{
// Draw the spotlight cone in wireframe after disabling lighting
glPushMatrix();
glDisable(GL_LIGHTING);
glRotatef(-90.0, 1.0, 0.0, 0.0);
glColor3f(1.0, 1.0, 1.0);
glutWireCone(3.0 * tan( m_SpotlightWidth/180.0 * PI ), 3.0, 20, 20);
glEnable(GL_LIGHTING);
glPopMatrix();
}
float lightPos[] = { 0.0, 3.0, 0.0, 1.0 }; // Spotlight position.
float spotDirection[] = {0.0, -1.0, 0.0}; // Spotlight direction.
// Spotlight properties including position.
glLightfv(m_LightSource, GL_POSITION, lightPos);
glLightf(m_LightSource, GL_SPOT_CUTOFF, m_SpotlightWidth);
glLightfv(m_LightSource, GL_SPOT_DIRECTION, spotDirection);
glLightf(m_LightSource, GL_SPOT_EXPONENT, m_Attenuation);
glPopMatrix();
}
class Plane
{
public:
Plane();
Plane(float x, float y, float z, float width, float height, float depth, string textureName);
void Draw();
private:
float m_CenterX, m_CenterY, m_CenterZ, m_Width, m_Height, m_Depth;
unsigned int m_Texture[1];
unsigned char m_Colour[3];
string m_TextureName;
};
void Plane::Draw()
{
if(m_HasTexture)
{
// Turn on OpenGL texturing.
glEnable(GL_TEXTURE_2D);
// Activate a texture.
glBindTexture(GL_TEXTURE_2D, m_Texture[0]);
// Map the texture onto a square polygon.
glBegin(GL_POLYGON);
glTexCoord2f(0.0, 1.0); glVertex3f(m_CenterX - m_Width, m_CenterY - m_Height, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(m_CenterX + m_Width, m_CenterY - m_Height, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(m_CenterX + m_Width, m_CenterY + m_Height, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(m_CenterX - m_Width, m_CenterY + m_Height, 0.0);
glEnd();
// Turn off OpenGL texturing.
glDisable(GL_TEXTURE_2D);
}
void Plane::LoadTexture(string textureName)
{
// Create texture index array.
glGenTextures(1, m_Texture);
// Local storage for bmp image data.
PNGFile *image[1];
// Load the texture.
image[0] = GetPNGData(textureName);
// Bind image to texture index[0].
glBindTexture(GL_TEXTURE_2D, m_Texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//used to make the image look blocky
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image[0]->sizeX, image[0]->sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, image[0]->pixels.data() );
delete image[0];
}
void drawScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//glulookat
// Turn on OpenGL lighting.
glEnable(GL_LIGHTING);
//Light.Draw();
// Draw 10 x 10 array of multi-colored spheres.
int i,j;
for (i = 0; i < 9; i++)
for (j = 0; j < 9; j++)
{
glPushMatrix();
glTranslatef(-4.0+i, 0.0, -4.0+j);
// Ambient and diffuse colors of the spheres specified to alternate.
if ((i+j)%3 == 0) glColor4f(1.0, 0.0, 0.0, 1.0);
else if ((i+j)%3 == 1) glColor4f(0.0, 1.0, 0.0, 1.0);
else glColor4f(0.0, 0.0, 1.0, 1.0);
glutSolidSphere (0.5, 20.0, 16.0);
glPopMatrix();
}
plane.Draw();
glutSwapBuffers();
}
void setup(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
plane = Plane(0,0,-10,5,5,0, "launch.png");
glShadeModel (GL_SMOOTH);
// stops GL_QUAD from showing faces by priority
glEnable(GL_DEPTH_TEST);
// Specify how texture values combine with current surface color values.
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_BLEND); // Enable blending.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Enable color material mode:
// The ambient and diffuse color of the front faces will track the color set by glColor().
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
}
答案 0 :(得分:3)
至少有两个问题会妨碍您获得良好的照明。第一个应该很容易解决。第二个更深入。
以下调用确定如何将光照计算的结果与从纹理中读取的颜色组合:
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
如名称所示,GL_REPLACE
表示由光照产生的颜色由纹理颜色替换。因此,根据定义,如果在启用纹理的情况下使用此设置,则不会获得光照。
将灯光颜色与纹理颜色相结合的最常见设置是GL_MODULATE
:
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
这意味着两种颜色(来自光照和纹理)相乘。
OpenGL中的传统固定功能管道使用每顶点照明。这意味着每个顶点仅评估一次光照方程,结果是在整个多边形上进行插值。
对于非常大的图元,每顶点光照效果很差,例如在将整个平面绘制为单个大的多边形的情况下。特别是镜面高光通常会以这种方式丢失,如果基元是两个大的话,甚至漫反射项也会受到影响。
要解决此问题,有两个主要选项:
如果您之前没有处理过,那么转移到可编程管道对您来说是一个更大的步骤,我仍然会考虑它。在现代版本的OpenGL(Core Profile,以及ES 2.x及更高版本)中,固定管道甚至不再可用,因此您无论如何都要迟早了解着色器编程。