OpenGLDemo.dpr 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. {
  2. Vampyre Imaging Library Demo
  3. OpenGL Demo (ObjectPascal, low level/OpenGL extension, Win32/Linux)
  4. tested in Delphi 7/10, Free Pascal 2.0.4 (Win32/Linux)
  5. written by Marek Mauder
  6. Demo that shows how to create OpenGL textures from files
  7. and Imaging's images and vice versa. This sample uses SDL to create
  8. window and process messages. Background and sprite textures are loaded from
  9. files and rendered. Sprite is mapped on the spinning cube in the
  10. center of the window. You can change sprite's texture format
  11. by pressing SPACE key (it cycles trough all TImageFormat values).
  12. Background texture can be saved to file by pressing S key and sprite texture
  13. can be saved by pressing D key.
  14. }
  15. program OpenGLDemo;
  16. {$I ImagingOptions.inc}
  17. {$R OpenGLDemo.res}
  18. uses
  19. {$IFDEF MSWINDOWS}
  20. Windows,
  21. {$ENDIF}
  22. SysUtils,
  23. ImagingTypes,
  24. Imaging,
  25. ImagingUtility,
  26. sdl,
  27. gl,
  28. glext,
  29. ImagingOpenGL,
  30. DemoUtils;
  31. const
  32. SWindowTitle = 'Vampyre Imaging Library (%s) - OpenGL Demo (format: %s)';
  33. SWindowIconTitle = 'OpenGL Demo';
  34. SBackImageFile = 'Tigers.jng';
  35. SSpriteImageFile = 'Vezyr.png';
  36. SOutScreenFile = 'GLScreen.png';
  37. SOutSpriteFile = 'GLSprite.dds';
  38. SIconFile = 'Icon.bmp';
  39. DisplayWidth = 640;
  40. DisplayHeight = 480;
  41. CubeSize = 200.0;
  42. var
  43. BackTex: GLuint = 0;
  44. SpriteTex: GLuint = 0;
  45. DisplaySurface: PSDL_Surface = nil;
  46. SpriteImage: TImageData;
  47. SpriteFormat: TImageFormat = ifA8R8G8B8;
  48. Event : TSDL_Event;
  49. Running: Boolean = True;
  50. Frames: LongInt = 0;
  51. FPS: LongInt = 0;
  52. LastTime: LongInt = 0;
  53. Angle: Single = 0.0;
  54. TextureCaps: TGLTextureCaps;
  55. {$IFDEF MSWINDOWS}
  56. WindowHandle: THandle;
  57. {$ENDIF}
  58. procedure MessageOut(const Msg: string; const Args: array of const);
  59. begin
  60. {$IFDEF MSWINDOWS}
  61. MessageBox(GetActiveWindow, PChar(Format(Msg, Args)), 'Message',
  62. MB_ICONINFORMATION or MB_OK);
  63. {$ENDIF}
  64. {$IFDEF UNIX}
  65. WriteLn(Format(Msg, Args));
  66. {$ENDIF}
  67. end;
  68. procedure MessageOutAndHalt(const Msg: string; const Args: array of const);
  69. begin
  70. {$IFDEF MSWINDOWS}
  71. MessageBox(GetActiveWindow, PChar(Format(Msg, Args)), 'Error',
  72. MB_ICONERROR or MB_OK);
  73. {$ENDIF}
  74. {$IFDEF UNIX}
  75. WriteLn('Error: ');
  76. MessageOut(' ' + Msg, Args);
  77. WriteLn('Press RETURN to exit');
  78. ReadLn;
  79. {$ENDIF}
  80. SDL_Quit;
  81. Halt(1);
  82. end;
  83. procedure UpdateCaption;
  84. begin
  85. SDL_WM_SetCaption(PChar(Format(SWindowTitle + ' FPS: %d',
  86. [Imaging.GetVersionStr, GetFormatName(SpriteFormat), FPS])), SWindowIconTitle);
  87. end;
  88. procedure CreateSpriteTexture(Format: TImageFormat);
  89. var
  90. Info: TImageFormatInfo;
  91. begin
  92. // Delete old texture and create new one in the different format
  93. glDeleteTextures(1, @SpriteTex);
  94. SpriteTex := ImagingOpenGL.CreateGLTextureFromImage(SpriteImage,
  95. 256, 256, True, SpriteFormat);
  96. if SpriteTex = 0 then
  97. MessageOut('Sprite texture creation failed.', []);
  98. // Set tex parameters
  99. glBindTexture(GL_TEXTURE_2D, SpriteTex);
  100. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  101. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  102. if TextureCaps.MaxAnisotropy > 0 then
  103. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, TextureCaps.MaxAnisotropy);
  104. if Imaging.GetImageFormatInfo(SpriteFormat, Info) then
  105. begin
  106. if Info.IsFloatingPoint and (Info.BytesPerPixel in [4, 16]) then
  107. begin
  108. // Floating point textures (not half float though) should use nearest
  109. // filter on current hardware. I get 900 fps with nearest filter
  110. // and only 2 fps with linear filter
  111. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  112. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
  113. end
  114. else
  115. begin
  116. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  117. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  118. end;
  119. end;
  120. end;
  121. procedure Initialize;
  122. {$IFDEF MSWINDOWS}
  123. var
  124. Caption, Icon: PChar;
  125. {$ENDIF}
  126. begin
  127. {$IFDEF MSWINDOWS}
  128. SDL_WM_GetCaption(Caption, Icon);
  129. WindowHandle := FindWindow('SDL_app', Caption);
  130. if WindowHandle <> 0 then
  131. begin
  132. // Place window to the center of the screen
  133. SetWindowPos(WindowHandle, 0, (GetSystemMetrics(SM_CXSCREEN) - DisplayWidth) div 2,
  134. (GetSystemMetrics(SM_CYSCREEN) - DisplayHeight - 20) div 2, 0, 0, SWP_NOSIZE or SWP_NOZORDER);
  135. end;
  136. {$ENDIF}
  137. ImagingOpenGL.GetGLTextureCaps(TextureCaps);
  138. // Disable some GL states
  139. glDisable(GL_LIGHTING);
  140. // Enable some GL states
  141. glEnable(GL_BLEND);
  142. glEnable(GL_TEXTURE_2D);
  143. // Prepare for alpha blending
  144. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  145. // Set projections and model view transformations
  146. glViewport(0, 0, DisplayWidth, DisplayHeight);
  147. glMatrixMode(GL_PROJECTION);
  148. glLoadIdentity;
  149. glOrtho(0, DisplayWidth, DisplayHeight, 0, -1000.0, 1000.0);
  150. // Load background texture from file
  151. BackTex := ImagingOpenGL.LoadGLTextureFromFile(GetDataDir + PathDelim + SBackImageFile);
  152. // Set tex parameters
  153. glBindTexture(GL_TEXTURE_2D, BackTex);
  154. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  155. Imaging.InitImage(SpriteImage);
  156. // Load sprite image from file
  157. Imaging.LoadImageFromFile(GetDataDir + PathDelim + SSpriteImageFile, SpriteImage);
  158. // Create sprite texture from image
  159. CreateSpriteTexture(SpriteFormat);
  160. end;
  161. procedure Present;
  162. begin
  163. // Clear depth and color buffers
  164. glClearColor(0.0, 0.8, 1.0, 1.0);
  165. glClearDepth(1.0);
  166. glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  167. glMatrixMode(GL_MODELVIEW);
  168. glLoadIdentity;
  169. // First draw background
  170. glBindTexture(GL_TEXTURE_2D, BackTex);
  171. glDisable(GL_DEPTH_TEST);
  172. glBegin(GL_QUADS);
  173. glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
  174. glTexCoord2f(1.0, 0.0); glVertex2f(DisplayWidth, 0.0);
  175. glTexCoord2f(1.0, 1.0); glVertex2f(DisplayWidth, DisplayHeight);
  176. glTexCoord2f(0.0, 1.0); glVertex2f(0.0, DisplayHeight);
  177. glEnd;
  178. // Then draw the spinning cube
  179. glEnable(GL_DEPTH_TEST);
  180. glTranslatef(DisplayWidth / 2.0, DisplayHeight / 2.0, 0.0);
  181. glRotatef(-30.0, 1.0, 0.0, 0.0);
  182. glRotatef(Angle, 0.0, 1.0, 0.0);
  183. glTranslatef(-CubeSize / 2.0, -CubeSize / 2.0, -CubeSize / 2.0);
  184. glBindTexture(GL_TEXTURE_2D, SpriteTex);
  185. glBegin(GL_QUADS);
  186. glTexCoord2f(1.0, 0.0); glVertex3f(0.0, 0.0, 0.0);
  187. glTexCoord2f(0.0, 0.0); glVertex3f(CubeSize, 0.0, 0.0);
  188. glTexCoord2f(0.0, 1.0); glVertex3f(CubeSize, CubeSize, 0.0);
  189. glTexCoord2f(1.0, 1.0); glVertex3f(0.0, CubeSize, 0.0);
  190. glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, CubeSize);
  191. glTexCoord2f(1.0, 0.0); glVertex3f(CubeSize, 0.0, CubeSize);
  192. glTexCoord2f(1.0, 1.0); glVertex3f(CubeSize, CubeSize, CubeSize);
  193. glTexCoord2f(0.0, 1.0); glVertex3f(0.0, CubeSize, CubeSize);
  194. glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, 0.0);
  195. glTexCoord2f(0.0, 1.0); glVertex3f(0.0, CubeSize, 0.0);
  196. glTexCoord2f(1.0, 1.0); glVertex3f(0.0, CubeSize, CubeSize);
  197. glTexCoord2f(1.0, 0.0); glVertex3f(0.0, 0.0, CubeSize);
  198. glTexCoord2f(1.0, 0.0); glVertex3f(CubeSize, 0.0, 0.0);
  199. glTexCoord2f(1.0, 1.0); glVertex3f(CubeSize, CubeSize, 0.0);
  200. glTexCoord2f(0.0, 1.0); glVertex3f(CubeSize, CubeSize, CubeSize);
  201. glTexCoord2f(0.0, 0.0); glVertex3f(CubeSize, 0.0, CubeSize);
  202. glEnd;
  203. Angle := Angle + 0.025;
  204. SDL_GL_SwapBuffers;
  205. end;
  206. procedure Finalize;
  207. begin
  208. // Free textures and images
  209. glDeleteTextures(1, @BackTex);
  210. glDeleteTextures(1, @SpriteTex);
  211. Imaging.FreeImage(SpriteImage);
  212. end;
  213. procedure TakeScreenShot;
  214. var
  215. RenderTarget: Gluint;
  216. begin
  217. // Setup render target texture
  218. glGenTextures(1, @RenderTarget);
  219. glBindTexture(GL_TEXTURE_2D, RenderTarget);
  220. glTexImage2D(GL_TEXTURE_2D, 0, 3, DisplayWidth, DisplayHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, nil);
  221. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  222. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  223. // Render all
  224. Present;
  225. // Copy framebuffer to texture
  226. glBindTexture(GL_TEXTURE_2D, RenderTarget);
  227. glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, DisplayWidth, DisplayHeight, 0);
  228. // Save texture & delete it
  229. ImagingOpenGL.SaveGLTextureToFile(SOutScreenFile, RenderTarget);
  230. glDeleteTextures(1, @RenderTarget);
  231. end;
  232. begin
  233. // Initialize SDL
  234. if (SDL_Init(SDL_INIT_VIDEO) < 0) then
  235. MessageOutAndHalt('SDL initialization failed: %s', [SDL_GetError]);
  236. SDL_WM_SetCaption(PChar(Format(SWindowTitle, [Imaging.GetVersionStr,
  237. GetFormatName(SpriteFormat)])), SWindowIconTitle);
  238. SDL_WM_SetIcon(SDL_LoadBMP(PChar(GetDataDir + PathDelim + SIconFile)), 0);
  239. // Set GL attributes using SDL
  240. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  241. SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  242. SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  243. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
  244. SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0);
  245. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  246. // Initialize video mode
  247. DisplaySurface := SDL_SetVideoMode(DisplayWidth, DisplayHeight, 32, SDL_OPENGL);
  248. if DisplaySurface = nil then
  249. MessageOutAndHalt('SDL SetVideoMode failed: %s', [SDL_GetError]);
  250. // Initialize surfaces and enter main loop
  251. Initialize;
  252. LastTime := SDL_GetTicks;
  253. while Running do
  254. begin
  255. while SDL_PollEvent(@Event) = 1 do
  256. begin
  257. case Event.type_ of
  258. SDL_QUITEV:
  259. begin
  260. Running := False;
  261. end;
  262. SDL_KEYDOWN:
  263. begin
  264. with Event.key.keysym do
  265. if ((sym = SDLK_F4) and ((modifier and KMOD_ALT) <> 0)) or
  266. (Event.key.keysym.sym = SDLK_ESCAPE) then
  267. Running := False;
  268. // Using S and D keys you can take screen shots and texture
  269. // shots easily
  270. // SPACE key can be used to cycle sprite image formats
  271. case Event.key.keysym.sym of
  272. SDLK_S: TakeScreenShot;
  273. SDLK_D: ImagingOpenGL.SaveGLTextureToFile(SOutSpriteFile, SpriteTex);
  274. SDLK_SPACE:
  275. begin
  276. SpriteFormat := NextFormat(SpriteFormat);
  277. CreateSpriteTexture(SpriteFormat);
  278. UpdateCaption;
  279. end;
  280. end;
  281. end;
  282. end;
  283. end;
  284. // Calculate FPS
  285. if LongInt(SDL_GetTicks) - LastTime > 1000 then
  286. begin
  287. FPS := Frames;
  288. UpdateCaption;
  289. Frames := 0;
  290. LastTime := SDL_GetTicks;
  291. end;
  292. Inc(Frames);
  293. // Renders background and sprites to the window
  294. Present;
  295. end;
  296. // Frees everything
  297. Finalize;
  298. SDL_Quit;
  299. {
  300. File Notes:
  301. -- 0.19 Changes/Bug Fixes -----------------------------------
  302. - screenshots now work in all OSs and ImagingComponents is no longer needed
  303. -- 0.17 Changes/Bug Fixes -----------------------------------
  304. - S key now saves screenshot to file
  305. - anisotropic filtering enabled if supported by hardware
  306. }
  307. end.