我正在OpenGL中为一个项目做游戏。我尝试导入PNG,然后使用glEnable2D函数在我的3D游戏上绘制GUI。功能是
void glEnable2D()
{
int vPort[4];
glGetIntegerv(GL_VIEWPORT, vPort);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, vPort[2], 0, vPort[3], -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
它有效。然后,我还有第二个函数,用于返回3D环境。然后我有这个功能,可以绘制带有纹理的四边形并将其绘制到屏幕上(也可以读取Alpha)
void drawImage(GLuint file, float x, float y, float w, float h, float angle)
{
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND_SRC);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPushMatrix();
glTranslatef(x, y, 0.0);
glRotatef(angle, 0.0, 0.0, 1.0);
glBindTexture(GL_TEXTURE_2D, file);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(x, y, 0.0f);
glTexCoord2f(0.0, 1.0); glVertex3f(x, y + h, 0.0f);
glTexCoord2f(1.0, 1.0); glVertex3f(x + w, y + h, 0.0f);
glTexCoord2f(1.0, 0.0); glVertex3f(x + w, y, 0.0f);
glEnd();
glFlush();
glPopMatrix();
}
如果我运行该函数,则其行为异常。它适用于Alpha,但只要图像靠近右下角,就可以使图像变暗
如果我不注释设置glTextEnvF的行,则它实际上以正确的方式点亮了事物,但不再读取Alphas。如何在不应用奇怪的照明的情况下使函数也读取alpha通道?
答案 0 :(得分:1)
请注意,自几十年来,不赞成使用glBegin
/ glEnd
序列绘制每个顶点光模型的固定功能管线矩阵堆栈和固定功能管线。
阅读有关Fixed Function Pipeline的信息,并参阅Vertex Specification和Shader了解最新的渲染方式。
无论如何,问题在于GUI上没有适当的照明。有两种可能性,即在绘制GUI之前禁用灯光(glDisable(GL_LIGHTING)
)。或确保指示灯照亮了GUI。
为此,您必须确保光源在GUI元素的前面,这意味着光源位置必须比GUI更靠近摄像机,甚至在摄像机后面。
但这还不够,还必须确保GUI元素能够反射光线。对于光的反射,最重要的是曲面的法线向量,因为标准的OpenGL Blinn-Phong光照模型是这样计算的:
Ka ... ambient material
Kd ... difusse material
Ks ... specular material
La ... ambient light
Ld ... diffuse light
Ls ... specular light
sh ... shininess
N ... norlmal vector
L ... light vector (from the vertex position to the light)
V ... view vector (from the vertex position to the eye)
Id = max(dot(N, L), 0.0);
H = normalize(V + L);
NdotH = max(dot(N, H), 0.0);
Is = (sh + 2.0) * pow(NdotH, sh) / (2.0 * 3.14159265);
fs = Ka*La + Id*Kd*Ld + Is*Ks*Ls;
您根本不设置任何法线向量。由于OpenGL是状态引擎,因此您上次由glNormal
设置的法向矢量仍然有效。当顶点坐标由glVertex
设置时,此法向矢量将与之关联。这可能会导致任意结果。
由于GUI几何图形是在视口的xy平面中绘制的,并且视空间z轴指向视口之外(在Right-handed坐标系中),因此我建议定义一个法向矢量到z轴:
glBegin(GL_QUADS);
glNormal3f(0.0, 0.0, 1.0);
glTexCoord2f(0.0, 0.0); glVertex3f(x, y, 0.0f);
glTexCoord2f(0.0, 1.0); glVertex3f(x, y + h, 0.0f);
glTexCoord2f(1.0, 1.0); glVertex3f(x + w, y + h, 0.0f);
glTexCoord2f(1.0, 0.0); glVertex3f(x + w, y, 0.0f);
glEnd();
当然,必须适当设置灯光位置才能进行这项工作。请注意,灯光位置(GL_POSITION
)和点方向(GL_SPOT_DIRECTION
)在设置时会由当前模型视图矩阵进行变换。