小弟使用OpenGL ES2.0在WinCE下画一个三角形,但结果出来的只有空白的窗口,其它什么都没有。请高手帮忙看下,不甚感激!!!!
小弟使用OpenGL ES2.0在WinCE下画一个三角形,但结果出来的只有空白的窗口,其它什么都没有。请高手帮忙看下,小弟不甚感激!!!!
以下是代码:
// Subproject1.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include <windows.h>
#include <commctrl.h>
#include <stdlib.h>
#include "esUtil.h"
#include "esUtil_win.h"
#include <stdio.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <auirt.h>
#include <auirt_i.c>
#define CLASSNAMEL"OpenGL ES2.0"
#define APPLICATIONNAMEL"OpenGL ES2.0"
#define MAX_LOADSTRING 100
// Global Variables:
TCHAR szTitle[MAX_LOADSTRING];
TCHAR szWindowClass[MAX_LOADSTRING];
HINSTANCE g_hInst = NULL;
ESContext g_esContext = {0};
typedef struct
{
// Handle to a program object
GLuint programObject;
} UserData;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
BOOL bRet;
int done = 0;
UserData userData;
g_hInst = hInstance;
esInitContext ();
g_esContext.userData = &userData;
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
bRet = esCreateWindow ("OpenGL ES2.0", 800, 480, ES_WINDOW_RGB);
if(0 == bRet)
{
return 0;
}
if ( !Init () )
{
return 0;
}
while (!done)
{
int gotMsg = (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0);
if ( gotMsg )
{
if (msg.message==WM_QUIT)
{
done = 1;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
SendMessage( g_esContext.hWnd, WM_PAINT, 0, 0 );
}
}
return msg.wParam;
}
GLuint LoadShader ( GLenum type, const char *shaderSrc )
{
GLuint shader;
GLint compiled;
// Create the shader object
shader = glCreateShader ( type );
if ( shader == 0 )
{
RETAILMSG(1, (TEXT("shader = 0\r\n")));
return 0;
}
// Load the shader source
glShaderSource ( shader, 1, &shaderSrc, NULL );
// Compile the shader
glCompileShader ( shader );
// Check the compile status
glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled )
{
glDeleteShader ( shader );
return 0;
}
return shader;
}
int Init ()
{
UserData *userData = (UserData *)g_esContext.userData;
GLbyte vShaderStr[] =
"attribute vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
GLbyte fShaderStr[] =
"precision mediump float;\n"\
"void main() \n"
"{ \n"
" gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
"} \n";
GLuint vertexShader;
GLuint fragmentShader;
GLuint programObject;
GLint linked;
// Load the vertex/fragment shaders
vertexShader = LoadShader ( GL_VERTEX_SHADER, (const char *)vShaderStr );
fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, (const char *)fShaderStr );
// Create the program object
programObject = glCreateProgram();
if ( programObject == 0 )
{
RETAILMSG(1, (TEXT("programObject = 0\r\n")));
return 0;
}
glAttachShader ( programObject, vertexShader );
glAttachShader ( programObject, fragmentShader );
// Bind vPosition to attribute 0
glBindAttribLocation ( programObject, 0, "vPosition" );
// Link the program
glLinkProgram ( programObject );
// Check the link status
glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );
if ( !linked )
{
glDeleteProgram ( programObject );
return FALSE;
}
// Store the program object
userData->programObject = programObject;
glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
return TRUE;
}
///
// Draw a triangle using the shader pair created in Init()
//
void Draw ()
{
UserData *userData = (UserData *)g_esContext.userData;
GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f };
// Set the viewport
glViewport ( 0, 0, g_esContext.width, g_esContext.height );
// Clear the color buffer --.> glClearColor
glClear ( GL_COLOR_BUFFER_BIT );
// Use the program object
glUseProgram ( userData->programObject );
// Load the vertex data
glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
glEnableVertexAttribArray ( 0 );
glDrawArrays ( GL_TRIANGLES, 0, 3 );
// glFlush();
eglSwapBuffers ( g_esContext.eglDisplay, g_esContext.eglSurface );
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage is only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = (WNDPROC) ESWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szWindowClass;
return RegisterClass(&wc);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
g_esContext.hWnd = CreateWindow(szWindowClass, szTitle, (WS_VISIBLE | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION),
0, 0, 800, 480, NULL, NULL, hInstance, NULL);
if (!g_esContext.hWnd)
{
return FALSE;
}
ShowWindow(g_esContext.hWnd, nCmdShow);
UpdateWindow(g_esContext.hWnd);
return TRUE;
}
///
// CreateEGLContext()
//
// Creates an EGL rendering context and all associated elements
//
EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
EGLContext* eglContext, EGLSurface* eglSurface,
EGLint attribList[])
{
EGLint numConfigs = 0;
EGLint majorVersion;
EGLint minorVersion;
EGLDisplay display;
EGLContext context;
EGLSurface surface;
EGLConfig eglConfig[68];
EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
// Get Display
display = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
if ( display == EGL_NO_DISPLAY )
{
return EGL_FALSE;
}
// Initialize EGL
if ( !eglInitialize(display, &majorVersion, &minorVersion) )
{
return EGL_FALSE;
}
// Get configs
if ( !eglGetConfigs(display, eglConfig, 68, &numConfigs) )
{
return EGL_FALSE;
}
// Choose config
if ( !eglChooseConfig(display, attribList, eglConfig, 20, &numConfigs) )
{
return EGL_FALSE;
}
// Create a surface
surface = eglCreateWindowSurface(display, eglConfig[0], hWnd, NULL);
if ( surface == EGL_NO_SURFACE )
{
return EGL_FALSE;
}
context = eglCreateContext(display, eglConfig[0], EGL_NO_CONTEXT, contextAttribs );
if ( context == EGL_NO_CONTEXT )
{
return EGL_FALSE;
}
// Make the context current
if ( !eglMakeCurrent(display, surface, surface, context) )
{
return EGL_FALSE;
}
*eglDisplay = display;
*eglSurface = surface;
*eglContext = context;
return EGL_TRUE;
}
//////////////////////////////////////////////////////////////////
//
// Public Functions
//
//
///
// esInitContext()
//
// Initialize ES utility context. This must be called before calling any other
// functions.
//
void ESUTIL_API esInitContext ()
{
memset( &g_esContext, 0, sizeof(ESContext) );
}
///
// esCreateWindow()
//
// title - name for title bar of window
// width - width of window to create
// height - height of window to create
// flags - bitwise or of window creation flags
// ES_WINDOW_ALPHA - specifies that the framebuffer should have alpha
// ES_WINDOW_DEPTH - specifies that a depth buffer should be created
// ES_WINDOW_STENCIL - specifies that a stencil buffer should be created
// ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
//
GLboolean ESUTIL_API esCreateWindow (const char* title, GLint width, GLint height, GLuint flags)
{
EGLint attribList[] =
{
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_DEPTH_SIZE, 1,
EGL_NONE
};
g_esContext.width = width;
g_esContext.height = height;
if ( !CreateEGLContext ( g_esContext.hWnd,
&g_esContext.eglDisplay,
&g_esContext.eglContext,
&g_esContext.eglSurface,
attribList) )
{
return GL_FALSE;
}
return GL_TRUE;
}
///
// ESWindowProc()
//
// Main window procedure
//
LRESULT WINAPI ESWindowProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT lRet = 1;
RECT rRect = {0,0,800,480};
PAINTSTRUCT ps;
switch (uMsg)
{
case WM_PAINT:
BeginPaint(g_esContext.hWnd, &ps);
Draw();
EndPaint(g_esContext.hWnd, &ps);
ValidateRect( g_esContext.hWnd, &rRect);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}
return FALSE;
}
/******************************************************************************
@File OGLES2HelloTriangle_Windows.cpp
@Title OpenGL ES 2.0 Hello Triangle Tutorial
@Version
@Copyright Copyright (c) Imagination Technologies Limited.
@Platform .
@Description Basic Tutorial that shows step-by-step how to initialize OpenGL ES
2.0, use it for drawing a triangle and terminate it.
******************************************************************************/
#include <stdio.h>
#include <windows.h>
#include <TCHAR.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
/******************************************************************************
Defines
******************************************************************************/
//#define NO_GDI 1 /* Remove the GDI functions */
#ifndef NO_GDI
// Windows class name to register
#defineWINDOW_CLASS _T("PVRShellClass")
// Width and height of the window
#define WINDOW_WIDTH640
#define WINDOW_HEIGHT480
#endif
// Index to bind the attributes to vertex shaders
#define VERTEX_ARRAY0
/******************************************************************************
Global variables
******************************************************************************/
// Variable set in the message handler to finish the demo
boolg_bDemoDone = false;
/*!****************************************************************************
@FunctionWndProc
@InputhWndHandle to the window
@InputmessageSpecifies the message
@InputwParamAdditional message information
@InputlParamAdditional message information
@ReturnLRESULTresult code to OS
@DescriptionProcesses messages for the main window
******************************************************************************/
#ifndef NO_GDI
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
/*
Here we are handling 2 system messages: screen saving and monitor power.
They are especially relevent on mobile devices.
*/
#ifndef UNDER_CE
case WM_SYSCOMMAND:
{
switch (wParam)
{
case SC_SCREENSAVE:// Screensaver trying to start ?
case SC_MONITORPOWER:// Monitor trying to enter powersave ?
return 0;// Prevent this from happening
}
break;
}
#endif
// Handles the close message when a user clicks the quit icon of the window
case WM_CLOSE:
g_bDemoDone = true;
PostQuitMessage(0);
return 1;
default:
break;
}
// Calls the default window procedure for messages we did not handle
return DefWindowProc(hWnd, message, wParam, lParam);
}
#endif
/*!****************************************************************************
@FunctionTestEGLError
@InputpszLocationlocation in the program where the error took
place. ie: function name
@Returnbooltrue if no EGL error was detected
@DescriptionTests for an EGL error and prints it
******************************************************************************/
bool TestEGLError(HWND hWnd, char* pszLocation)
{
/*
eglGetError returns the last error that has happened using egl,
not the status of the last called function. The user has to
check after every single egl call or at least once every frame.
*/
EGLint iErr = eglGetError();
if (iErr != EGL_SUCCESS)
{
#ifndef NO_GDI
TCHAR pszStr[256];
_stprintf(pszStr, _T("%s failed (%d).\n"), pszLocation, iErr);
MessageBox(hWnd, pszStr, _T("Error"), MB_OK
[解决办法]
MB_ICONEXCLAMATION);
#endif
return false;
}
return true;
}