OpenGL для PSP
Попробую описать основы использования OpenGL про программировании для PSP.
Использоваться будут следующие библиотеки: libGL, libGLU, libglut. libGL и libGLU — собственно для отрисовки графики, а libglut для того, чтобы не заморачиваться с базовыми вещами OpenGL, такими как создание окна. Версия прошивки на которой тестилось все это — 3.90-M33-3(4.01-M33-2)
Для примеров я использовал cygwin с установленным psptoolchain, подробнее об настройке см статью на хабре отличия в настройке роли играть не должны. Все вышеуказанные библиотеки как и SDK идут вместе с psptoolchain.
Рассматривать использование OpenGL и как написать HelloWorld в статье не буду, только приведу пример с комментариями. Подробнее читайте у NeHe 🙂
Примерный порядок действий приложения таков:
- Инициализация OpenGL
- установка размеров окна
- установка обработчиков различных событий: нажатия конпок, отрисовка сцены, изменение размера окна и т.д.
- запуск цикла приложения.
На самом деле на этом этапе все очень просто. Создаем main:
int main(int argc, char* argv[]){ glutInit(&argc, argv); //инициализация OpenGL glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); //Установка режима окна glutInitWindowSize(480, 272); // установка размеров окна glutCreateWindow( __FILE__ ); // как ни странно - создание окна :) //установка обработчиков кнопок glutKeyboardFunc(keyPressed); glutKeyboardUpFunc(keyReleased); //обработчики изменения размера окна и отрисовки сцены glutReshapeFunc(glSceneResize); glutDisplayFunc(glScene); // собственно запуск основного цикла программы glutMainLoop(); return 0; } /* обработчик нажатия кнопки. */ void keyPressed(unsigned char key, int x, int y) { switch (key) { case 'd': /* delta, triangle */ break; case 'o': /* round */ break; case 'q': /* square*/ break; case 'x': /* cross */ break; case 'n': /* key with the music note */ break; case 's': /* select */ break; case 'a': /* startbutton */ /* If START is pressed, kill everything. */ /* exit the program...normal termination. */ exit(0); default: ; } } /* обработчик на отпускание кнопки. */ void keyReleased(unsigned char key, int x, int y) { switch (key) { case 'd': /* delta, triangle */ break; case 'o': /* round */ break; case 'q': /* square*/ break; case 'x': /* cross */ break; case 'n': /* key with the music note */ break; case 's': /* select */ break; case 'a': /* startbutton */ break; default: ; } } // Обработчики resize и отрисовки сцены GLvoid glScene(GLvoid){ glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units //And Into The Screen 6.0 // draw a triangle glBegin(GL_POLYGON); // start drawing a polygon glVertex3f( 0.0f, 1.0f, 0.0f); // Top glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left glEnd(); // we're done with the polygon glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units // draw a square (quadrilateral) glBegin(GL_QUADS); // start drawing a polygon (4 sided) glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left glEnd(); // done with the polygon // swap buffers to display, since we're double buffered. glutSwapBuffers(); } GLvoid glSceneResize(GLsizei Width, GLsizei Height) { if (Height==0) // Предотвращение деления на ноль, если окно слишком мало Height=1; glViewport(0, 0, Width, Height); // Сброс текущей области вывода // и перспективных преобразований glMatrixMode(GL_PROJECTION); // Выбор матрицы проекций glLoadIdentity(); // Сброс матрицы проекции gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Вычисление соотношения геометрических размеров для окна glMatrixMode(GL_MODELVIEW); // Выбор матрицы просмотра модели } Также нужно взять фаил psp-setup.c для установки всех необходимых для работы действий на pspsdk: /** * This file handles all the PSP-specific kernel setup and exit stuff. * * Is there some general interest for this file, so that we can place it * somewhere in the compiler toolchain include path? * * Usage: Simply add * -DMODULE_NAME="your-module-name" psp-setup.c * to the LFLAGS or LDFLAGS of your project, so that this file is * compiled in when gcc collects and links the final ELF binary. * * Options: * -DMODULE_NAME="name" -- set the name (default NONAME) * -DMODULE_ATTR=0 -- module attributes (default 0) * -DVERSION_MAJOR=1 -- version 1.x (default 1) * -DVERSION_MINOR=0 -- version x.0 (default 0) * * Note: The linker flags and library lists need to be placed after this * entry on the LFLAG or LDFLAGS command line, otherwise gcc won't * be able to to resolve all symbols. */ #include <pspkerneltypes.h> #include <pspuser.h> #if !defined(MODULE_NAME) #define MODULE_NAME NONAME #endif #if !defined(MODULE_VERSION_MAJOR) #define MODULE_VERSION_MAJOR 1 #endif #if !defined(MODULE_VERSION_MINOR) #define MODULE_VERSION_MINOR 0 #endif #if !defined(MODULE_ATTR) #define MODULE_ATTR 0 #endif #define __stringify(s) __tostring(s) #define __tostring(s) #s PSP_MODULE_INFO(__stringify(MODULE_NAME), MODULE_ATTR, MODULE_VERSION_MAJOR, MODULE_VERSION_MINOR); static int exit_callback (int arg1, int arg2, void *common) { sceKernelExitGame(); return 0; } static int update_thread (SceSize args, void *argp) { int cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); sceKernelRegisterExitCallback(cbid); sceKernelSleepThreadCB(); return 0; } static void setup_callbacks (void) __attribute__((constructor)); static void setup_callbacks (void) { int id; if ((id = sceKernelCreateThread("update_thread", update_thread, 0x11, 0xFA0, 0, 0)) >= 0) sceKernelStartThread(id, 0, 0); } static void back_to_kernel (void) __attribute__((destructor)); static void back_to_kernel (void) { sceKernelExitGame(); }
Домашнее задание — разобраться с тем, что делает вышеуказанный фаил 🙂
Пример Makefile для всего этого безобразия:
TARGET = lesson02 OBJS = lesson02.o INCDIR = CFLAGS = -O2 -G0 -Wall -DPSPFW3X ASFLAGS = $(CFLAGS) LIBDIR = LDFLAGS = EXTRA_TARGETS = EBOOT.PBP PSP_EBOOT_TITLE = NeHe lesson 2 PSPSDK=$(shell psp-config --pspsdk-path) PSPBIN = $(PSPSDK)/../bin PSP_FW_VERSION=371 BUILD_PRX=1 CFLAGS += -I$(PSPSDK)/../include -fsingle-precision-constant -g -Wall -O2 LIBS += -lglut -lGLU -lGL -lm -lc -lpsputility -lpspdebug -lpspge \ -lpspdisplay -lpspctrl -lpspsdk -lpspvfpu -lpsplibc -lpspuser \ -lpspkernel -lpsprtc -lpsppower LDFLAGS += -DMODULE_NAME="lesson2" psp-setup.c include $(PSPSDK)/lib/build.mak
В итоге после запуска на PSP, приложение должно показать белые квадрат и треугольник и выходить по кнопке Home 🙂
Передиралось из следующих источников:
- http://www.qj.net/portage-of-nehe-tutorials-1-to-10-for-pspgl-v0-1-/pg/49/aid/47390 — Nehe tutorials переделаные под PSP
- http://nehe.gamedev.net — собственно уроки по OpenGL, которые прочитать настойчиво рекомендую
Спасибо за внимание. Критику в каменты 🙂