Guest User

Untitled

a guest
May 25th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.82 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////
  2. // Headers
  3. ////////////////////////////////////////////////////////////
  4.  
  5. /// GLEW is needed to provide OpenGL extensions.
  6. #include <GL/glew.h>
  7.  
  8. #include <SFML/Graphics.hpp>
  9. #include <SFML/OpenGL.hpp>
  10.  
  11. /// GLM is needed to provide 3D math properties, particularly matrices for 3D transformations.
  12. #define GLM_ENABLE_EXPERIMENTAL
  13. #include "glm/glm.hpp"
  14. #include "glm/gtx/transform.hpp"
  15.  
  16. #include <iostream>
  17.  
  18. #ifndef GL_SRGB8_ALPHA8
  19. #define GL_SRGB8_ALPHA8 0x8C43
  20. #endif
  21.  
  22. ///Basic vertex shader that transforms the vertex position based on a projection view matrix and passes the texture coordinate to the fragment shader.
  23. const std::string defaultVertexShader =
  24. "#version 330\n"\
  25. "attribute vec3 position;"\
  26. "attribute vec2 texCoord;" \
  27. "uniform mat4 pvm;" \
  28.  
  29. "varying vec2 uv;" \
  30.  
  31. "void main() {"\
  32. " gl_Position = pvm * vec4(position, 1.0);"\
  33. " uv = texCoord;"\
  34. "}";
  35.  
  36. ///Basic fragment shader that returns the colour of a pixel based on the input texture and its coordinate.
  37. const std::string defaultFragShader =
  38. "#version 330\n" \
  39. "uniform sampler2D texture;" \
  40. "varying vec2 uv;" \
  41.  
  42. "void main() {" \
  43. " gl_FragColor = texture2D(texture, uv);" \
  44. "}";
  45.  
  46. ///Shader Types
  47. enum class ShaderType { Vertex, Fragment, Geometry, Count };
  48. ///Standard Uniforms in the shader.
  49. enum class UniformType { TransformPVM, Count };
  50. ///Vertex attributes for shaders and the input vertex array.
  51. enum class VertexAttribute { Position, TexCoord, COUNT };
  52.  
  53. ///Shader Program
  54. GLuint program = 0;
  55.  
  56. ///List of shaders set up for a 3D scene.
  57. GLuint shader[static_cast<unsigned int>(ShaderType::Count)];
  58. ///List of uniforms that can be defined values for the shader.
  59. GLint uniform[static_cast<unsigned int>(UniformType::Count)];
  60.  
  61. ///Vertex Array Object ID.
  62. GLuint vao = 0;
  63. ///Vertex Buffer Object for Vertices.
  64. GLuint vertexVBO = 0;
  65. ///Vertex Buffer Object for Indices.
  66. GLuint indexVBO = 0;
  67. ///Depending on input, the amount of vertices or indices that are needed to be drawn for this object.
  68. unsigned int drawCount;
  69.  
  70. ///Checks for any errors specific to the shaders. It will output any errors within the shader if it's not valid.
  71. void checkError(GLuint l_shader, GLuint l_flag, bool l_program, const std::string& l_errorMsg)
  72. {
  73. GLint success = 0;
  74. GLchar error[1024] = { 0 };
  75. if (l_program) { glGetProgramiv(l_shader, l_flag, &success); }
  76. else { glGetShaderiv(l_shader, l_flag, &success); }
  77.  
  78. if (success) { return; }
  79. if (l_program) {
  80. glGetProgramInfoLog(l_shader, sizeof(error), nullptr, error);
  81. }
  82. else {
  83. glGetShaderInfoLog(l_shader, sizeof(error), nullptr, error);
  84. }
  85.  
  86. std::cout << l_errorMsg << "\n";
  87. }
  88.  
  89. ///Creates and compiles a shader.
  90. GLuint buildShader(const std::string& l_src, unsigned int l_type)
  91. {
  92. GLuint shaderID = glCreateShader(l_type);
  93. if (!shaderID) {
  94. std::cout << "Bad shader type!";
  95. return 0;
  96. }
  97. const GLchar* sources[1];
  98. GLint lengths[1];
  99. sources[0] = l_src.c_str();
  100. lengths[0] = l_src.length();
  101. glShaderSource(shaderID, 1, sources, lengths);
  102. glCompileShader(shaderID);
  103. checkError(shaderID, GL_COMPILE_STATUS, false, "Shader compile error: ");
  104. return shaderID;
  105. }
  106.  
  107. ///Function to load the shaders from string data.
  108. void LoadFromMemory(const std::string& shaderData, ShaderType type)
  109. {
  110. if (shaderData.empty())
  111. return;
  112.  
  113. if (shader[static_cast<unsigned int>(type)])
  114. {
  115. glDetachShader(program, shader[static_cast<unsigned int>(type)]);
  116. glDeleteShader(shader[static_cast<unsigned int>(type)]);
  117. }
  118.  
  119. switch (type)
  120. {
  121. case ShaderType::Vertex:
  122. shader[static_cast<unsigned int>(type)] = buildShader(shaderData, GL_VERTEX_SHADER);
  123. break;
  124. case ShaderType::Geometry:
  125. shader[static_cast<unsigned int>(type)] = buildShader(shaderData, GL_GEOMETRY_SHADER);
  126. break;
  127. case ShaderType::Fragment:
  128. shader[static_cast<unsigned int>(type)] = buildShader(shaderData, GL_FRAGMENT_SHADER);
  129. break;
  130. default:
  131. break;
  132. }
  133.  
  134. if (program == 0)
  135. {
  136. program = glCreateProgram();
  137. }
  138.  
  139. glAttachShader(program, shader[static_cast<unsigned int>(type)]);
  140. glBindAttribLocation(program, static_cast<GLuint>(VertexAttribute::Position), "position");
  141. glBindAttribLocation(program, static_cast<GLuint>(VertexAttribute::TexCoord), "texCoord");
  142.  
  143. glLinkProgram(program);
  144. checkError(program, GL_LINK_STATUS, true, "Shader link error:");
  145. glValidateProgram(program);
  146. checkError(program, GL_VALIDATE_STATUS, true, "Invalid shader:");
  147.  
  148. uniform[static_cast<unsigned int>(UniformType::TransformPVM)] = glGetUniformLocation(program, "pvm");
  149. }
  150.  
  151. ////////////////////////////////////////////////////////////
  152. /// Entry point of application
  153. ///
  154. /// \return Application exit code
  155. ///
  156. ////////////////////////////////////////////////////////////
  157. int main()
  158. {
  159. bool exit = false;
  160. bool sRgb = false;
  161.  
  162. while (!exit)
  163. {
  164. // Request a 24-bits depth buffer when creating the window
  165. sf::ContextSettings contextSettings;
  166. contextSettings.depthBits = 24;
  167. contextSettings.sRgbCapable = sRgb;
  168.  
  169. // Create the main window
  170. sf::RenderWindow window(sf::VideoMode(800, 600), "SFML graphics with OpenGL", sf::Style::Default, contextSettings);
  171. window.setVerticalSyncEnabled(true);
  172.  
  173. // Initialise GLEW for the extended functions.
  174. glewExperimental = GL_TRUE;
  175. if (glewInit() != GLEW_OK)
  176. return EXIT_FAILURE;
  177.  
  178. // Create a sprite for the background
  179. sf::Texture backgroundTexture;
  180. backgroundTexture.setSrgb(sRgb);
  181. if (!backgroundTexture.loadFromFile("resources/background.jpg"))
  182. return EXIT_FAILURE;
  183. sf::Sprite background(backgroundTexture);
  184.  
  185. // Create some text to draw on top of our OpenGL object
  186. sf::Font font;
  187. if (!font.loadFromFile("resources/sansation.ttf"))
  188. return EXIT_FAILURE;
  189. sf::Text text("SFML / OpenGL demo", font);
  190. sf::Text sRgbInstructions("Press space to toggle sRGB conversion", font);
  191. sf::Text mipmapInstructions("Press return to toggle mipmapping", font);
  192. text.setFillColor(sf::Color(255, 255, 255, 170));
  193. sRgbInstructions.setFillColor(sf::Color(255, 255, 255, 170));
  194. mipmapInstructions.setFillColor(sf::Color(255, 255, 255, 170));
  195. text.setPosition(250.f, 450.f);
  196. sRgbInstructions.setPosition(150.f, 500.f);
  197. mipmapInstructions.setPosition(180.f, 550.f);
  198.  
  199. // Load a texture to apply to our 3D cube
  200. sf::Texture texture;
  201. if (!texture.loadFromFile("resources/texture.jpg"))
  202. return EXIT_FAILURE;
  203.  
  204. // Attempt to generate a mipmap for our cube texture
  205. // We don't check the return value here since
  206. // mipmapping is purely optional in this example
  207. texture.generateMipmap();
  208.  
  209. // Make the window the active window for OpenGL calls
  210. window.setActive(true);
  211.  
  212. // Load the shaders we need.
  213. if (program == 0)
  214. {
  215. LoadFromMemory(defaultVertexShader, ShaderType::Vertex);
  216. LoadFromMemory(defaultFragShader, ShaderType::Fragment);
  217. }
  218.  
  219. // Enable Z-buffer read and write and culling.
  220. glEnable(GL_DEPTH_TEST);
  221. glEnable(GL_CULL_FACE);
  222. glCullFace(GL_BACK);
  223.  
  224. // Setup a perspective projection
  225. GLfloat ratio = static_cast<float>(window.getSize().x) / window.getSize().y;
  226. glm::mat4 projection = glm::frustum(-ratio, ratio, -1.f, 1.f, 1.f, 500.0f);
  227.  
  228. // Define a 3D cube (6 faces made of 2 triangles composed by 3 indices of a list of vertices)
  229. static const GLfloat cube[] =
  230. {
  231. // positions // texture coordinates
  232. //front
  233. -20, -20, -20, 0, 0,
  234. 20, -20, -20, 1, 0,
  235. 20, 20, -20, 1, 1,
  236. -20, 20, -20, 0, 1,
  237. //right
  238. 20, 20, -20, 1, 1,
  239. 20, 20, 20, 0, 1,
  240. 20, -20, 20, 0, 0,
  241. 20, -20, -20, 1, 0,
  242. //back
  243. -20, -20, 20, 0, 0,
  244. 20, -20, 20, 1, 0,
  245. 20, 20, 20, 1, 1,
  246. -20, 20, 20, 0, 1,
  247. //left
  248. -20, -20, 20, 0, 0,
  249. -20, -20, -20, 1, 0,
  250. -20, 20, -20, 1, 1,
  251. -20, 20, 20, 0, 1,
  252. //upper
  253. 20, -20, 20, 0, 1,
  254. -20, -20, 20, 1, 1,
  255. -20, -20, -20, 1, 0,
  256. 20, -20, -20, 0, 0,
  257. //bottom
  258. -20, 20, -20, 0, 1,
  259. 20, 20, -20, 1, 1,
  260. 20, 20, 20, 1, 0,
  261. -20, 20, 20, 0, 0,
  262. };
  263.  
  264. // Define indices for 3D cube.
  265. static const unsigned int indices[] =
  266. {
  267. 2, 1, 0, 3, 2, 0, //front
  268. 4, 5, 6, 4, 6, 7, //right
  269. 8, 9, 10, 8, 10, 11, //back
  270. 14, 13, 12, 15, 14, 12, //left
  271. 16, 17, 18, 16, 18, 19, //upper
  272. 22, 21, 20, 23, 22, 20 //bottom
  273. };
  274.  
  275. // Stride is the number of bytes per array element.
  276. auto stride = sizeof(GLfloat) * 5;
  277. // Data offset for texture coordinate in bytes.
  278. auto textureCoordOffset = sizeof(GLfloat) * 3;
  279. // Amount of index elements in total.
  280. drawCount = sizeof(indices) / sizeof(unsigned int);
  281.  
  282.  
  283. // Generate Vertex Array and Vertex Buffer and point the area of data to assign to each attribute.
  284. glGenVertexArrays(1, &vao);
  285. glBindVertexArray(vao);
  286. glGenBuffers(1, &vertexVBO);
  287. glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
  288. glBufferData(GL_ARRAY_BUFFER, drawCount * stride, cube, GL_STATIC_DRAW);
  289. glEnableVertexAttribArray(static_cast<GLuint>(VertexAttribute::Position));
  290. glVertexAttribPointer(static_cast<GLuint>(VertexAttribute::Position), 3, GL_FLOAT, GL_FALSE, stride, 0);
  291. glEnableVertexAttribArray(static_cast<GLuint>(VertexAttribute::TexCoord));
  292. glVertexAttribPointer(static_cast<GLuint>(VertexAttribute::TexCoord), 2, GL_FLOAT, GL_FALSE, stride, (void*)textureCoordOffset);
  293.  
  294. // Generate Index Buffer and define the amount of indices to point to.
  295. glGenBuffers(1, &indexVBO);
  296. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
  297. glBufferData(GL_ELEMENT_ARRAY_BUFFER, drawCount * sizeof(indices[0]), indices, GL_STATIC_DRAW);
  298.  
  299. //Make sure to bind the vertex array to null if you wish to define more objects.
  300. glBindVertexArray(0);
  301.  
  302. // Make the window no longer the active window for OpenGL calls
  303. window.setActive(false);
  304.  
  305. // Create a clock for measuring the time elapsed
  306. sf::Clock clock;
  307.  
  308. // Flag to track whether mipmapping is currently enabled
  309. bool mipmapEnabled = true;
  310.  
  311. // Start game loop
  312. while (window.isOpen())
  313. {
  314. // Process events
  315. sf::Event event;
  316. while (window.pollEvent(event))
  317. {
  318. // Close window: exit
  319. if (event.type == sf::Event::Closed)
  320. {
  321. exit = true;
  322. window.close();
  323. }
  324.  
  325. // Escape key: exit
  326. if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape))
  327. {
  328. exit = true;
  329. window.close();
  330. }
  331.  
  332. // Return key: toggle mipmapping
  333. if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Return))
  334. {
  335. if (mipmapEnabled)
  336. {
  337. // We simply reload the texture to disable mipmapping
  338. if (!texture.loadFromFile("resources/texture.jpg"))
  339. return EXIT_FAILURE;
  340.  
  341. mipmapEnabled = false;
  342. }
  343. else
  344. {
  345. texture.generateMipmap();
  346.  
  347. mipmapEnabled = true;
  348. }
  349. }
  350.  
  351. // Space key: toggle sRGB conversion
  352. if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space))
  353. {
  354. sRgb = !sRgb;
  355. window.close();
  356. }
  357.  
  358. // Adjust the viewport when the window is resized
  359. if (event.type == sf::Event::Resized)
  360. {
  361. // Make the window the active window for OpenGL calls
  362. window.setActive(true);
  363.  
  364. glViewport(0, 0, event.size.width, event.size.height);
  365.  
  366. // Make the window no longer the active window for OpenGL calls
  367. window.setActive(false);
  368. }
  369. }
  370.  
  371. // Clear the depth buffer
  372. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  373.  
  374. // Configure the viewport (the same size as the window)
  375. glViewport(0, 0, window.getSize().x, window.getSize().y);
  376.  
  377. // Draw the background
  378. window.pushGLStates();
  379. window.draw(background);
  380. window.popGLStates();
  381.  
  382. // Make the window the active window for OpenGL calls
  383. window.setActive(true);
  384.  
  385. // Bind the texture
  386. sf::Texture::bind(&texture);
  387. glBindVertexArray(vao);
  388.  
  389. // We get the position of the mouse cursor, so that we can move the box accordingly
  390. float x = sf::Mouse::getPosition(window).x * 200.f / window.getSize().x - 100.f;
  391. float y = -sf::Mouse::getPosition(window).y * 200.f / window.getSize().y + 100.f;
  392.  
  393. // Apply some transformations
  394. glm::mat4 matrix_pos = glm::translate(glm::vec3(x, y, -100.f));
  395. glm::mat4 matrix_rotX = glm::rotate(clock.getElapsedTime().asSeconds() * 50.f * (3.1415926f / 180.0f), glm::vec3(1.f, 0.f, 0.f));
  396. glm::mat4 matrix_rotY = glm::rotate(clock.getElapsedTime().asSeconds() * 30.f * (3.1415926f / 180.0f), glm::vec3(0.f, 1.f, 0.f));
  397. glm::mat4 matrix_rotZ = glm::rotate(clock.getElapsedTime().asSeconds() * 90.f * (3.1415926f / 180.0f), glm::vec3(0.f, 0.f, 1.f));
  398.  
  399. glm::mat4 matrix_rotation = matrix_rotZ * matrix_rotY * matrix_rotX;
  400. glm::mat4 transform = matrix_pos * matrix_rotation;
  401.  
  402. glm::mat4 identity;
  403. glm::mat4 viewProj = projection * transform;
  404.  
  405. //Bind the shaders.
  406. glUseProgram(program);
  407.  
  408. //Set the uniforms for the shader to use.
  409. if (uniform[(int)UniformType::TransformPVM] >= 0)
  410. glUniformMatrix4fv((unsigned int)uniform[(int)UniformType::TransformPVM], 1, GL_FALSE, &viewProj[0][0]);
  411.  
  412. // Draw the cube
  413. glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_INT, 0);
  414.  
  415. // Reset the vertex array bound, shader and texture for other assets to draw.
  416. glBindVertexArray(0);
  417. glUseProgram(0);
  418. glBindTexture(GL_TEXTURE_2D, 0);
  419.  
  420. // Make the window no longer the active window for OpenGL calls
  421. window.setActive(false);
  422.  
  423. // Draw some text on top of our OpenGL object
  424. window.pushGLStates();
  425. window.draw(text);
  426. window.draw(sRgbInstructions);
  427. window.draw(mipmapInstructions);
  428. window.popGLStates();
  429.  
  430. // Finally, display the rendered frame on screen
  431. window.display();
  432. }
  433.  
  434. //Destroy all buffers, shaders and programs.
  435. glDeleteBuffers(1, &vertexVBO);
  436. glDeleteBuffers(1, &indexVBO);
  437. glDeleteVertexArrays(1, &vao);
  438.  
  439. //Setting these values to zero will allow them to be initialised with new data on reset.
  440. vertexVBO = 0;
  441. indexVBO = 0;
  442. vao = 0;
  443.  
  444. for (unsigned int i = 0; i < static_cast<unsigned int>(ShaderType::Count); i++)
  445. {
  446. glDetachShader(program, shader[i]);
  447. glDeleteShader(shader[i]);
  448. shader[i] = 0;
  449. }
  450.  
  451. for (unsigned int i = 0; i < static_cast<unsigned int>(UniformType::Count); i++)
  452. {
  453. uniform[i] = -1;
  454. }
  455.  
  456. glDeleteProgram(program);
  457. program = 0;
  458. }
  459.  
  460. return EXIT_SUCCESS;
  461. }
Add Comment
Please, Sign In to add comment