OGLES2Texturing.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /******************************************************************************
  2. @File OGLES2Texturing.cpp
  3. @Title Texturing
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform Independant
  7. @Description Shows how to use textures in OpenGL ES 2.0
  8. ******************************************************************************/
  9. #include <stdio.h>
  10. #include <string.h>
  11. #if defined(__APPLE__)
  12. #import <OpenGLES/ES2/gl.h>
  13. #import <OpenGLES/ES2/glext.h>
  14. #else
  15. #if defined(__BADA__)
  16. #include <FGraphicsOpengl2.h>
  17. using namespace Osp::Graphics::Opengl;
  18. #else
  19. #include <GLES2/gl2.h>
  20. #endif
  21. #endif
  22. #include "PVRShell.h"
  23. /******************************************************************************
  24. Defines
  25. ******************************************************************************/
  26. // Index to bind the attributes to vertex shaders
  27. #define VERTEX_ARRAY 0
  28. #define TEXCOORD_ARRAY 1
  29. // Size of the texture we create
  30. #define TEX_SIZE 128
  31. /*!****************************************************************************
  32. Class implementing the PVRShell functions.
  33. ******************************************************************************/
  34. class OGLES2Texturing : public PVRShell
  35. {
  36. // The vertex and fragment shader OpenGL handles
  37. GLuint m_uiVertexShader, m_uiFragShader;
  38. // The program object containing the 2 shader objects
  39. GLuint m_uiProgramObject;
  40. // Texture handle
  41. GLuint m_uiTexture;
  42. // VBO handle
  43. GLuint m_ui32Vbo;
  44. //
  45. unsigned int m_ui32VertexStride;
  46. public:
  47. virtual bool InitApplication();
  48. virtual bool InitView();
  49. virtual bool ReleaseView();
  50. virtual bool QuitApplication();
  51. virtual bool RenderScene();
  52. };
  53. /*!****************************************************************************
  54. @Function InitApplication
  55. @Return bool true if no error occured
  56. @Description Code in InitApplication() will be called by PVRShell once per
  57. run, before the rendering context is created.
  58. Used to initialize variables that are not dependant on it
  59. (e.g. external modules, loading meshes, etc.)
  60. If the rendering context is lost, InitApplication() will
  61. not be called again.
  62. ******************************************************************************/
  63. bool OGLES2Texturing::InitApplication()
  64. {
  65. return true;
  66. }
  67. /*!****************************************************************************
  68. @Function QuitApplication
  69. @Return bool true if no error occured
  70. @Description Code in QuitApplication() will be called by PVRShell once per
  71. run, just before exiting the program.
  72. If the rendering context is lost, QuitApplication() will
  73. not be called.
  74. ******************************************************************************/
  75. bool OGLES2Texturing::QuitApplication()
  76. {
  77. return true;
  78. }
  79. /*!****************************************************************************
  80. @Function InitView
  81. @Return bool true if no error occured
  82. @Description Code in InitView() will be called by PVRShell upon
  83. initialization or after a change in the rendering context.
  84. Used to initialize variables that are dependant on the rendering
  85. context (e.g. textures, vertex buffers, etc.)
  86. ******************************************************************************/
  87. bool OGLES2Texturing::InitView()
  88. {
  89. // Fragment and vertex shaders code
  90. const char* pszFragShader = "\
  91. uniform sampler2D sampler2d;\
  92. varying mediump vec2 myTexCoord;\
  93. void main (void)\
  94. {\
  95. gl_FragColor = texture2D(sampler2d,myTexCoord);\
  96. }";
  97. const char* pszVertShader = "\
  98. attribute highp vec4 myVertex;\
  99. attribute mediump vec4 myUV;\
  100. uniform mediump mat4 myPMVMatrix;\
  101. varying mediump vec2 myTexCoord;\
  102. void main(void)\
  103. {\
  104. gl_Position = myPMVMatrix * myVertex;\
  105. myTexCoord = myUV.st;\
  106. }";
  107. // Create the fragment shader object
  108. m_uiFragShader = glCreateShader(GL_FRAGMENT_SHADER);
  109. // Load the source code into it
  110. glShaderSource(m_uiFragShader, 1, (const char**)&pszFragShader, NULL);
  111. // Compile the source code
  112. glCompileShader(m_uiFragShader);
  113. // Check if compilation succeeded
  114. GLint bShaderCompiled;
  115. glGetShaderiv(m_uiFragShader, GL_COMPILE_STATUS, &bShaderCompiled);
  116. if (!bShaderCompiled)
  117. {
  118. // An error happened, first retrieve the length of the log message
  119. int i32InfoLogLength, i32CharsWritten;
  120. glGetShaderiv(m_uiFragShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
  121. // Allocate enough space for the message and retrieve it
  122. char* pszInfoLog = new char[i32InfoLogLength];
  123. glGetShaderInfoLog(m_uiFragShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
  124. /*
  125. Displays the message in a dialog box when the application quits
  126. using the shell PVRShellSet function with first parameter prefExitMessage.
  127. */
  128. char* pszMsg = new char[i32InfoLogLength+256];
  129. strcpy(pszMsg, "Failed to compile fragment shader: ");
  130. strcat(pszMsg, pszInfoLog);
  131. PVRShellSet(prefExitMessage, pszMsg);
  132. delete [] pszMsg;
  133. delete [] pszInfoLog;
  134. return false;
  135. }
  136. // Loads the vertex shader in the same way
  137. m_uiVertexShader = glCreateShader(GL_VERTEX_SHADER);
  138. glShaderSource(m_uiVertexShader, 1, (const char**)&pszVertShader, NULL);
  139. glCompileShader(m_uiVertexShader);
  140. glGetShaderiv(m_uiVertexShader, GL_COMPILE_STATUS, &bShaderCompiled);
  141. if (!bShaderCompiled)
  142. {
  143. int i32InfoLogLength, i32CharsWritten;
  144. glGetShaderiv(m_uiVertexShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
  145. char* pszInfoLog = new char[i32InfoLogLength];
  146. glGetShaderInfoLog(m_uiVertexShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
  147. char* pszMsg = new char[i32InfoLogLength+256];
  148. strcpy(pszMsg, "Failed to compile vertex shader: ");
  149. strcat(pszMsg, pszInfoLog);
  150. PVRShellSet(prefExitMessage, pszMsg);
  151. delete [] pszMsg;
  152. delete [] pszInfoLog;
  153. return false;
  154. }
  155. // Create the shader program
  156. m_uiProgramObject = glCreateProgram();
  157. // Attach the fragment and vertex shaders to it
  158. glAttachShader(m_uiProgramObject, m_uiFragShader);
  159. glAttachShader(m_uiProgramObject, m_uiVertexShader);
  160. // Bind the custom vertex attribute "myVertex" to location VERTEX_ARRAY
  161. glBindAttribLocation(m_uiProgramObject, VERTEX_ARRAY, "myVertex");
  162. // Bind the custom vertex attribute "myUV" to location TEXCOORD_ARRAY
  163. glBindAttribLocation(m_uiProgramObject, TEXCOORD_ARRAY, "myUV");
  164. // Link the program
  165. glLinkProgram(m_uiProgramObject);
  166. // Check if linking succeeded in the same way we checked for compilation success
  167. GLint bLinked;
  168. glGetProgramiv(m_uiProgramObject, GL_LINK_STATUS, &bLinked);
  169. if (!bLinked)
  170. {
  171. int i32InfoLogLength, i32CharsWritten;
  172. glGetProgramiv(m_uiProgramObject, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
  173. char* pszInfoLog = new char[i32InfoLogLength];
  174. glGetProgramInfoLog(m_uiProgramObject, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
  175. char* pszMsg = new char[i32InfoLogLength+256];
  176. strcpy(pszMsg, "Failed to link program: ");
  177. strcat(pszMsg, pszInfoLog);
  178. PVRShellSet(prefExitMessage, pszMsg);
  179. delete [] pszMsg;
  180. delete [] pszInfoLog;
  181. return false;
  182. }
  183. // Actually use the created program
  184. glUseProgram(m_uiProgramObject);
  185. // Sets the sampler2D variable to the first texture unit
  186. glUniform1i(glGetUniformLocation(m_uiProgramObject, "sampler2d"), 0);
  187. // Sets the clear color
  188. glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
  189. /*
  190. Creates the texture
  191. */
  192. // Allocates one texture handle
  193. glGenTextures(1, &m_uiTexture);
  194. // Binds this texture handle so we can load the data into it
  195. glBindTexture(GL_TEXTURE_2D, m_uiTexture);
  196. // Creates the data as a 32bits integer array (8bits per component)
  197. GLuint* pTexData = new GLuint[TEX_SIZE*TEX_SIZE];
  198. for (int i=0; i<TEX_SIZE; i++)
  199. for (int j=0; j<TEX_SIZE; j++)
  200. {
  201. // Fills the data with a fancy pattern
  202. GLuint col = (255L<<24) + ((255L-j*2)<<16) + ((255L-i)<<8) + (255L-i*2);
  203. if ( ((i*j)/8) % 2 ) col = (GLuint) (255L<<24) + (255L<<16) + (0L<<8) + (255L);
  204. pTexData[j*TEX_SIZE+i] = col;
  205. }
  206. /*
  207. glTexImage2D loads the texture data into the texture object.
  208. void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
  209. GLint border, GLenum format, GLenum type, const GLvoid *pixels );
  210. target must be GL_TEXTURE_2D.
  211. level specify the mipmap level we want to upload.
  212. internalformat and format must be the same. Here we use GL_RGBA for 4 component colors (r,g,b,a).
  213. We could use GL_RGB, GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA to use different color component combinations.
  214. width, height specify the size of the texture. Both of the dimensions must be power of 2.
  215. border must be 0.
  216. type specify the format of the data. We use GL_UNSIGNED_BYTE to describe a color component as an unsigned byte.
  217. So a pixel is described by a 32bits integer.
  218. We could also use GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, and GL_UNSIGNED_SHORT_5_5_5_1
  219. to specify the size of all 3 (or 4) color components. If we used any of these 3 constants,
  220. a pixel would then be described by a 16bits integer.
  221. */
  222. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, pTexData);
  223. /*
  224. glTexParameterf is used to set the texture parameters
  225. void glTexParameterf(GLenum target, GLenum pname, GLfloat param);
  226. target must be GL_TEXTURE_2D.
  227. pname is the parameter name we want to modify.
  228. If pname is GL_TEXTURE_MIN_FILTER, param is used to set the way the texture is rendered when made smaller.
  229. We can tell OpenGL to interpolate between the pixels in a mipmap level but also between different mipmap levels.
  230. We are not using mipmap interpolation here because we didn't defined the mipmap levels of our texture.
  231. If pname is GL_TEXTURE_MAG_FILTER, param is used to set the way the texture is rendered when made bigger.
  232. Here we can only tell OpenGL to interpolate between the pixels of the first mipmap level.
  233. if pname is GL_TEXTURE_WRAP_S or GL_TEXTURE_WRAP_T, then param sets the way a texture tiles in both directions.
  234. The default if GL_REPEAT to wrap the texture (repeat it). We could also set it to GL_CLAMP or GL_CLAMP_TO_EDGE
  235. to clamp the texture.
  236. On OpenGL ES 1.1 and 2.0, if pname is GL_GENERATE_MIPMAP, param tells OpenGL to create mipmap levels automatically.
  237. */
  238. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  239. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  240. // Deletes the texture data, it's now in OpenGL memory
  241. delete [] pTexData;
  242. // Create VBO for the triangle from our data
  243. // Interleaved vertex data
  244. GLfloat afVertices[] = {-0.4f,-0.4f,0.0f, // Pos
  245. 0.0f,0.0f , // UVs
  246. 0.4f,-0.4f,0.0f,
  247. 1.0f,0.0f ,
  248. 0.0f,0.4f ,0.0f,
  249. 0.5f,1.0f};
  250. glGenBuffers(1, &m_ui32Vbo);
  251. m_ui32VertexStride = 5 * sizeof(GLfloat); // 3 floats for the pos, 2 for the UVs
  252. // Bind the VBO
  253. glBindBuffer(GL_ARRAY_BUFFER, m_ui32Vbo);
  254. // Set the buffer's data
  255. glBufferData(GL_ARRAY_BUFFER, 3 * m_ui32VertexStride, afVertices, GL_STATIC_DRAW);
  256. // Unbind the VBO
  257. glBindBuffer(GL_ARRAY_BUFFER, 0);
  258. return true;
  259. }
  260. /*!****************************************************************************
  261. @Function ReleaseView
  262. @Return bool true if no error occured
  263. @Description Code in ReleaseView() will be called by PVRShell when the
  264. application quits or before a change in the rendering context.
  265. ******************************************************************************/
  266. bool OGLES2Texturing::ReleaseView()
  267. {
  268. // Frees the texture
  269. glDeleteTextures(1, &m_uiTexture);
  270. // Release Vertex buffer object.
  271. glDeleteBuffers(1, &m_ui32Vbo);
  272. // Frees the OpenGL handles for the program and the 2 shaders
  273. glDeleteProgram(m_uiProgramObject);
  274. glDeleteShader(m_uiVertexShader);
  275. glDeleteShader(m_uiFragShader);
  276. return true;
  277. }
  278. /*!****************************************************************************
  279. @Function RenderScene
  280. @Return bool true if no error occured
  281. @Description Main rendering loop function of the program. The shell will
  282. call this function every frame.
  283. eglSwapBuffers() will be performed by PVRShell automatically.
  284. PVRShell will also manage important OS events.
  285. Will also manage relevent OS events. The user has access to
  286. these events through an abstraction layer provided by PVRShell.
  287. ******************************************************************************/
  288. bool OGLES2Texturing::RenderScene()
  289. {
  290. // Clears the color buffer
  291. glClear(GL_COLOR_BUFFER_BIT);
  292. /*
  293. Bind the projection model view matrix (PMVMatrix) to
  294. the associated uniform variable in the shader
  295. */
  296. // Matrix used for projection model view
  297. float afIdentity[] = {
  298. 1,0,0,0,
  299. 0,1,0,0,
  300. 0,0,1,0,
  301. 0,0,0,1
  302. };
  303. // First gets the location of that variable in the shader using its name
  304. int i32Location = glGetUniformLocation(m_uiProgramObject, "myPMVMatrix");
  305. // Then passes the matrix to that variable
  306. glUniformMatrix4fv(i32Location, 1, GL_FALSE, afIdentity);
  307. /*
  308. Draw a triangle.
  309. Please refer to HelloTriangle or IntroducingPVRShell for a detailed explanation.
  310. */
  311. // Bind the VBO
  312. glBindBuffer(GL_ARRAY_BUFFER, m_ui32Vbo);
  313. // Pass the vertex data
  314. glEnableVertexAttribArray(VERTEX_ARRAY);
  315. glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, m_ui32VertexStride, 0);
  316. // Pass the texture coordinates data
  317. glEnableVertexAttribArray(TEXCOORD_ARRAY);
  318. glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, m_ui32VertexStride, (void*) (3 * sizeof(GLfloat)));
  319. // Draws a non-indexed triangle array
  320. glDrawArrays(GL_TRIANGLES, 0, 3);
  321. // Unbind the VBO
  322. glBindBuffer(GL_ARRAY_BUFFER, 0);
  323. return true;
  324. }
  325. /*!****************************************************************************
  326. @Function NewDemo
  327. @Return PVRShell* The demo supplied by the user
  328. @Description This function must be implemented by the user of the shell.
  329. The user should return its PVRShell object defining the
  330. behaviour of the application.
  331. ******************************************************************************/
  332. PVRShell* NewDemo()
  333. {
  334. return new OGLES2Texturing();
  335. }
  336. /******************************************************************************
  337. End of file (OGLES2Texturing.cpp)
  338. ******************************************************************************/