照明在opengl中不起作用 [英] Lighting not working in opengl
问题描述
我在MFC中的opengl纹理中使用了一些灯光代码,但它不起作用
我尝试过:
我的代码是
i used some lighting codes in opengl texture in MFC, but it does not work
What I have tried:
My code is
GLuint glTexture ;
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable( GL_TEXTURE_2D );
// glEnable(GL_BLEND);
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable( GL_LIGHTING );
glEnable(GL_LIGHT1);
// glEnable(GL_ALPHA_TEST);
// glAlphaFunc(GL_GREATER,0.01);;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Light
GLfloat lightColor0[] = {0.9f, 0.9f, 0.9f, 1.0f};
GLfloat lightPos0[] = {0.0f, 30.0f, 0.0f, 1};
glLightfv(GL_LIGHT1, GL_SPECULAR, lightColor0);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos0);
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 45.0);
GLfloat spot_direction[] = { 0.0, -1.0, 0.0 };
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 2.0);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 2.0);
//Material
GLfloat mcolor[] = {0.1, 0.9, 0.4, 1.0};
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mcolor);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mcolor);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
glEnable(GL_COLOR_MATERIAL);
glGenTextures( 1, &glTexture );
glBindTexture( GL_TEXTURE_2D, glTexture );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); // Select modulate to mix texture with color for shading
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); // When texture area is small, bilinear filter the closest mipmap
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); // When texture area is large, bilinear filter the original
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); // The texture wraps over at the edges (repeat)
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
// GLfloat globalAmbient[] = { g_nRedSlider, g_nGreenSlider, g_nBlueSlider, g_nAlphaSlider };
// glLightModelfv( GL_LIGHT_MODEL_AMBIENT, globalAmbient );
glColor4f( float( ( float )g_nRedSlider / 10 ), float( ( float )g_nGreenSlider/ 10 ), float( ( float )g_nBlueSlider / 10 ), float( ( float )g_nAlphaSlider / 10 ));
glTexImage2D( GL_TEXTURE_2D, 0, GL_INTENSITY, WIDTH, HEIGHT, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_pbyImageData );
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, glTexture );
glBegin( GL_QUADS );
glTexCoord2d(0.0,0.0);
glVertex2f(-0.8f, -0.8f);
glTexCoord2d(1.0,0.0);
glVertex2f( 0.8f, -0.8f);
glTexCoord2d(1.0,1.0);
glVertex2f( 0.8f, 0.8f);
glTexCoord2d(0.0,1.0);
glVertex2f(-0.8f, 0.8f);
glEnd();
SwapBuffers( m_hDeviceContextDC );
glDisable( GL_TEXTURE_2D );
glDisable( GL_COLOR_MATERIAL );
它不会产生任何光照效果只显示纹理图像。
it does not produce any lighting effects just shows the texture image.
推荐答案
我用你的光和材料代码
这是我的本能化代码...光是一个bool并开始是的,所以glEnable被称为在那里打开它
I used your code for light and material
This is my inintialization code ... light is a bool and starts true so glEnable is called turning it on in there
int InitGL(GLvoid) // All Setup For OpenGL Goes Here
{
if (!BMP2GLTexture("Bitmaps/Crate.bmp", &glTexture[0])) // Jump To Texture Loading Routine
{
return FALSE; // If Texture Didn't Load Return FALSE
}
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
//Light
GLfloat lightColor0 [] = { 0.9f, 0.9f, 0.9f, 1.0f };
GLfloat lightPos0 [] = { 0.0f, 30.0f, 0.0f, 1 };
glLightfv(GL_LIGHT1, GL_SPECULAR, lightColor0);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos0);
glEnable(GL_LIGHT1);
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 45.0);
GLfloat spot_direction [] = { 0.0, -1.0, 0.0 };
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 2.0);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 2.0);
glEnable(GL_LIGHT1);
// Material
GLfloat mcolor [] = { 0.1f, 0.9f, 0.4f, 1.0f };
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mcolor);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mcolor);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0);
glEnable(GL_COLOR_MATERIAL);
if (light) glEnable(GL_LIGHTING);
return TRUE; // Initialization Went OK
}
接下来会有一个例程来设置场景到窗口大小...你目前没有的代码,不知道你做了什么。宽度和高度是我的OpenGL窗口大小。
Next will come a routine to set the scene to the window size ... code you don't currently have and not sure what you do. Width and Height are my OpenGL window size.
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}
glViewport(0,0,width,height); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}
最后我绘制了一个场景,它将是你MFC窗口的绘图调用..有几个位所以我可以旋转纹理你可以忽略它们
Finally I draw the scene which will be the draw call of your MFC window .. there are a couple of bits so I can rotate the texture you can ignore them
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// Translate some Depth Into The Screen in this case -5.0
glTranslatef(0.0f, 0.0f, -5.0f);
// these just rotate the texture my addition you can leave out
glRotatef(xrot, 1.0f, 0.0f, 0.0f);
glRotatef(yrot, 0.0f, 1.0f, 0.0f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, glTexture[0]);
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2d(0.0, 0.0); glVertex2f(-0.8f, -0.8f);
glTexCoord2d(1.0, 0.0); glVertex2f(0.8f, -0.8f);
glTexCoord2d(1.0, 1.0); glVertex2f(0.8f, 0.8f);
glTexCoord2d(0.0, 1.0); glVertex2f(-0.8f, 0.8f);
glEnd();
// These are the rotations being added ... again you can ignore
xrot+=xspeed;
yrot+=yspeed;
return TRUE; // Keep Going
}
在消息循环中,swapbuffers就像你一样。
这是运行序列的伪代码
1.)InitGL ...被称为opengl窗口是创建并运行一次
2.)ReSizeGLScene ...作为opengl创建调用一次任何时候窗口调整大小都会运行..我把它挂钩到windows resize事件
3.)DrawGLScene ....绘制场景
4.)交换缓冲区
5.)循环回3 ...只会在程序退出时停止循环
In the message loop the swapbuffers happens just like you.
This is the Pseudocode for the running sequence
1.) InitGL ... Called as opengl window is create and runs just the once
2.) ReSizeGLScene ... Called once as opengl create and runs anytime the window is resized .. I hook it to windows resize event
3.) DrawGLScene .... draws the scence
4.) Swap the buffers
5.) Loop back to 3 ... will only stop looping when program quits
你的代码实际上不能以你应该拥有的那种形式使用至少2个部分,你有两个混合组件
1.)一个初始设置部分(在开始时调用一次)
2。 )一个叫做每帧画的部分
当我把这个代码放在骨架OpenGL代码中时ng有效,但有一个我无法测试并且有问题的元素,我必须为我的应用程序定位视图位置。你的代码给我一个黑屏,因为视图位置没有设置。
我关心的是这条线的纹理文件实际是什么
glTexImage2D(GL_TEXTURE_2D,0,GL_INTENSITY,WIDTH,HEIGHT,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,m_pbyImageData);
你的图像纹理是否真的在GL_LUMINANCE中保存在m_pbyImageData中格式?
我的等效代码,因为我正在加载一个标准的Windows位图是
glTexImage2D(GL_TEXTURE_2D,0,3,BMP.bmWidth, BMP.bmHeight,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,m_pbyImageData);
普通的Windows DIB格式是GL_BGR_EXT,但你没有在m_pbyImageData中显示创建纹理的代码/>
我已经上传了VS2013格式的粗略检查代码..按L打开和关闭灯光,箭头键旋转纹理,这样你就可以找到方向灯了。 />
TinyUpload.com - 最佳文件托管解决方案,无限制,完全免费 [ ^ ]
骨架代码有3个部分BTW
1.)初始设置部分(在开始时调用一次)
2.)一个部分称为每个帧绘制
3.)在调整窗口大小时运行的一段代码
Your code can't really be used in that form you are supposed to have a minimum 2 sections and you have mixed components of both
1.) An intial setup section (called once at start)
2.) A section called each frame draw
When I put that code in a skeleton OpenGL code the lighting works but there is one element I can not test and and have concerns with, and I have to position the view position for my application. You code for me gives me a black screen because the view position is not setup.
My concern is what the texture file actually is with this line
glTexImage2D( GL_TEXTURE_2D, 0, GL_INTENSITY, WIDTH, HEIGHT, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_pbyImageData );
Is your image texture held in m_pbyImageData really in GL_LUMINANCE format?
My equivalent code because I am loading a standard windows bitmap is
glTexImage2D(GL_TEXTURE_2D, 0, 3, BMP.bmWidth, BMP.bmHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, m_pbyImageData);
The normal windows DIB format is GL_BGR_EXT but you havent shown the code that creates your texture in m_pbyImageData
I have uploaded the roughcheck code in VS2013 format .. press L to turn the lights on and off and arrow keys rotates the texture so you can look for direction lights.
TinyUpload.com - best file hosting solution, with no limits, totaly free[^]
The skeleton code has 3 sections BTW
1.) An intial setup section (called once at start)
2.) A section called each frame draw
3.) A section of code that runs when you resize the window
当然我的代码是更通用的代码,只使用Win32 api加载位图
Sure my code is more generic code that loads a bitmap using just the Win32 api
bool BMP2GLTexture(LPCSTR bmpFilename, GLuint* glTexture) { // Load Bitmaps And Convert To a texture
HBITMAP hBMP; // Handle Of The Bitmap
BITMAP BMP; // Bitmap Structure
if (glTexture == NULL) return false; // Return texture pointer invalid so fail out
hBMP = (HBITMAP) LoadImage(GetModuleHandle(NULL), bmpFilename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
if (!hBMP) return FALSE; // If bitmap does not exist return false
GetObject(hBMP, sizeof(BMP), &BMP); // Get The bitmap details
int P2Width = (BMP.bmWidth) >> 2; // Divid width by 4
if ((P2Width << 2) < (BMP.bmWidth)) P2Width++; // Inc by 1 if width x 4 is less than original
P2Width = P2Width << 2; // Power of two width
long imageSize = (long) P2Width * (long) BMP.bmHeight * (long)sizeof(RGBQUAD);
// Create the pixel buffer
BYTE* m_pbyImageData = (BYTE*) malloc(imageSize);
// Fetch desktop DC to use
HDC Dc = GetDC(GetDesktopWindow());
// Create and fill BITMAPINFO structure to pass to GetDIBits
BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = BMP.bmWidth;
bmi.bmiHeader.biHeight = BMP.bmHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = 0;
bmi.bmiHeader.biSizeImage = imageSize;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
// Load m_pbyImageData with the pixels in DIB format
GetDIBits(Dc, hBMP, 0, BMP.bmHeight, m_pbyImageData, &bmi, DIB_RGB_COLORS);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // Pixel Storage Mode (Word Alignment / 4 Bytes)
glGenTextures(1, glTexture); // Create a texture
glBindTexture(GL_TEXTURE_2D, glTexture[0]);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // Select modulate to mix texture with color for shading
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // When texture area is small, bilinear filter the closest mipmap
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // When texture area is large, bilinear filter the original
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // The texture wraps over at the edges (repeat)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, 3, BMP.bmWidth, BMP.bmHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, m_pbyImageData);
free(m_pbyImageData); // Free allocated pixel memory
ReleaseDC(GetDesktopWindow(), Dc); // Release the desktop DC
DeleteObject(hBMP); // Delete The Object
return TRUE; // Return true Status
}
我的加载纹理调用直接只是filname和指向GLUint的指针来存储结果
My load texture call is straight forward just the filname and a pointer to the GLUint to store the result
BMP2GLTexture("somepath/xyz.bmp", &glTexture[0]);
这篇关于照明在opengl中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!