{"id":83,"date":"2021-01-08T22:16:39","date_gmt":"2021-01-08T14:16:39","guid":{"rendered":"http:\/\/liyanliang.net\/?p=83"},"modified":"2021-01-11T14:04:31","modified_gmt":"2021-01-11T06:04:31","slug":"opengl%e5%ae%9e%e7%8e%b0%e5%a4%9a%e5%85%89%e6%ba%90-%e9%99%84%e9%a1%b9%e7%9b%ae%e6%ba%90%e7%a0%81","status":"publish","type":"post","link":"http:\/\/liyanliang.net\/index.php\/2021\/01\/08\/opengl%e5%ae%9e%e7%8e%b0%e5%a4%9a%e5%85%89%e6%ba%90-%e9%99%84%e9%a1%b9%e7%9b%ae%e6%ba%90%e7%a0%81\/","title":{"rendered":"OpenGL\u5b9e\u73b0\u591a\u5149\u6e90-\u9644\u9879\u76ee\u6e90\u7801"},"content":{"rendered":"\n<div id=\"toc_container\" class=\"no_bullets\"><p class=\"toc_title\">Contents<\/p><ul class=\"toc_list\"><li><a href=\"#i\"><span class=\"toc_number toc_depth_1\">1<\/span> \u6548\u679c\uff1a<\/a><\/li><li><a href=\"#1\"><span class=\"toc_number toc_depth_1\">2<\/span> 1.\u4e3b\u8981\u5b9e\u73b0\u4ee3\u7801\uff1a<\/a><\/li><li><a href=\"#2_VS2012\"><span class=\"toc_number toc_depth_1\">3<\/span> 2.\u5b8c\u6574\u7684\u9879\u76ee\u4ee3\u7801 VS2012<\/a><\/li><li><a href=\"#3\"><span class=\"toc_number toc_depth_1\">4<\/span> 3.\u53c2\u8003\u8d44\u6599<\/a><\/li><\/ul><\/div>\n<h3 class=\"wp-block-heading\"><span id=\"i\">\u6548\u679c\uff1a<\/span><\/h3>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/liyanliangpublic.oss-cn-hongkong.aliyuncs.com\/img\/OpenGL%20Lighting.gif\" alt=\"\"\/><\/figure>\n\n\n\n<p>  \u521b\u5efa\u4e00\u4e2a\u5305\u542b\u516d\u4e2a\u5149\u6e90\u7684\u573a\u666f\u3002\u5c06\u6a21\u62df\u4e00\u4e2a\u7c7b\u4f3c\u592a\u9633\u7684\u5b9a\u5411\u5149(Directional Light)\u5149\u6e90\uff0c\u56db\u4e2a\u5206\u6563\u5728\u573a\u666f\u4e2d\u7684\u70b9\u5149\u6e90(Point Light)\uff0c\u4ee5\u53ca\u4e00\u4e2a\u624b\u7535\u7b52(Flashlight)\u3002<\/p>\n\n\n\n<p> \u4e3a\u4e86\u5728\u573a\u666f\u4e2d\u4f7f\u7528\u591a\u4e2a\u5149\u6e90\uff0c\u6211\u4eec\u5e0c\u671b\u5c06\u5149\u7167\u8ba1\u7b97\u5c01\u88c5\u5230GLSL\u51fd\u6570\u4e2d\u3002\u8fd9\u6837\u505a\u7684\u539f\u56e0\u662f\uff0c\u6bcf\u4e00\u79cd\u5149\u6e90\u90fd\u9700\u8981\u4e00\u79cd\u4e0d\u540c\u7684\u8ba1\u7b97\u65b9\u6cd5\uff0c\u800c\u4e00\u65e6\u6211\u4eec\u60f3\u5bf9\u591a\u4e2a\u5149\u6e90\u8fdb\u884c\u5149\u7167\u8ba1\u7b97\u65f6\uff0c\u4ee3\u7801\u5f88\u5feb\u5c31\u4f1a\u53d8\u5f97\u975e\u5e38\u590d\u6742\u3002\u5982\u679c\u6211\u4eec\u53ea\u5728main\u51fd\u6570\u4e2d\u8fdb\u884c\u6240\u6709\u7684\u8fd9\u4e9b\u8ba1\u7b97\uff0c\u4ee3\u7801\u5f88\u5feb\u5c31\u4f1a\u53d8\u5f97\u96be\u4ee5\u7406\u89e3\u3002<\/p>\n\n\n\n<p>  GLSL\u4e2d\u7684\u51fd\u6570\u548cC\u51fd\u6570\u5f88\u76f8\u4f3c\uff0c\u5b83\u6709\u4e00\u4e2a\u51fd\u6570\u540d\u3001\u4e00\u4e2a\u8fd4\u56de\u503c\u7c7b\u578b\uff0c\u5982\u679c\u51fd\u6570\u4e0d\u662f\u5728main\u51fd\u6570\u4e4b\u524d\u58f0\u660e\u7684\uff0c\u6211\u4eec\u8fd8\u5fc5\u987b\u5728\u4ee3\u7801\u6587\u4ef6\u9876\u90e8\u58f0\u660e\u4e00\u4e2a\u539f\u578b\u3002\u6211\u4eec\u5bf9\u6bcf\u4e2a\u5149\u7167\u7c7b\u578b\u90fd\u521b\u5efa\u4e00\u4e2a\u4e0d\u540c\u7684\u51fd\u6570\uff1a\u5b9a\u5411\u5149\u3001\u70b9\u5149\u6e90\u548c\u805a\u5149\u3002<\/p>\n\n\n\n<p>  \u5f53\u6211\u4eec\u5728\u573a\u666f\u4e2d\u4f7f\u7528\u591a\u4e2a\u5149\u6e90\u65f6\uff0c\u6211\u4eec\u9700\u8981\u6709\u4e00\u4e2a\u5355\u72ec\u7684\u989c\u8272\u5411\u91cf\u4ee3\u8868\u7247\u6bb5\u7684\u8f93\u51fa\u989c\u8272\u3002\u5bf9\u4e8e\u6bcf\u4e00\u4e2a\u5149\u6e90\uff0c\u5b83\u5bf9\u7247\u6bb5\u7684\u8d21\u732e\u989c\u8272\u5c06\u4f1a\u52a0\u5230\u7247\u6bb5\u7684\u8f93\u51fa\u989c\u8272\u5411\u91cf\u4e0a\u3002\u6240\u4ee5\u573a\u666f\u4e2d\u7684\u6bcf\u4e2a\u5149\u6e90\u90fd\u4f1a\u8ba1\u7b97\u5b83\u4eec\u5404\u81ea\u5bf9\u7247\u6bb5\u7684\u5f71\u54cd\uff0c\u5e76\u7ed3\u5408\u4e3a\u4e00\u4e2a\u6700\u7ec8\u7684\u8f93\u51fa\u989c\u8272\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span id=\"1\">1.\u4e3b\u8981\u5b9e\u73b0\u4ee3\u7801\uff1a<\/span><\/h3>\n\n\n\n<p>main.cpp<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#include &lt;glad\/glad.h&gt;<br>#include &lt;GLFW\/glfw3.h&gt;<br>#include &lt;stb_image.h&gt;<br>\u200b<br>#include &lt;glm\/glm.hpp&gt;<br>#include &lt;glm\/gtc\/matrix_transform.hpp&gt;<br>#include &lt;glm\/gtc\/type_ptr.hpp&gt;<br>\u200b<br>#include &lt;learnopengl\/shader_m.h&gt;<br>#include &lt;learnopengl\/camera.h&gt;<br>\u200b<br>#include &lt;iostream&gt;<br>\u200b<br>void framebuffer_size_callback(GLFWwindow* window, int width, int height);<br>void mouse_callback(GLFWwindow* window, double xpos, double ypos);<br>void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);<br>void processInput(GLFWwindow *window);<br>unsigned int loadTexture(const char *path);<br>\u200b<br>\/\/ settings<br>const unsigned int SCR_WIDTH = 800;<br>const unsigned int SCR_HEIGHT = 600;<br>\u200b<br>\/\/ camera<br>Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));<br>float lastX = SCR_WIDTH \/ 2.0f;<br>float lastY = SCR_HEIGHT \/ 2.0f;<br>bool firstMouse = true;<br>\u200b<br>\/\/ timing<br>float deltaTime = 0.0f;<br>float lastFrame = 0.0f;<br>\u200b<br>\/\/ lighting<br>glm::vec3 lightPos(1.2f, 1.0f, 2.0f);<br>\u200b<br>int main()<br>{<br> &nbsp; &nbsp;\/\/ glfw: initialize and configure<br> &nbsp; &nbsp;\/\/ ------------------------------<br> &nbsp; &nbsp;glfwInit();<br> &nbsp; &nbsp;glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);<br> &nbsp; &nbsp;glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);<br> &nbsp; &nbsp;glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);<br>\u200b<br>#ifdef __APPLE__<br> &nbsp; &nbsp; &nbsp; &nbsp;glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);<br>#endif<br>\u200b<br> &nbsp; &nbsp;\/\/ glfw window creation<br> &nbsp; &nbsp;\/\/ --------------------<br> &nbsp; &nbsp;GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, \"LearnOpenGL\", NULL, NULL);<br> &nbsp; &nbsp;if (window == NULL)<br> &nbsp;  {<br> &nbsp; &nbsp; &nbsp; &nbsp;std::cout &lt;&lt; \"Failed to create GLFW window\" &lt;&lt; std::endl;<br> &nbsp; &nbsp; &nbsp; &nbsp;glfwTerminate();<br> &nbsp; &nbsp; &nbsp; &nbsp;return -1;<br> &nbsp;  }<br> &nbsp; &nbsp;glfwMakeContextCurrent(window);<br> &nbsp; &nbsp;glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);<br> &nbsp; &nbsp;glfwSetCursorPosCallback(window, mouse_callback);<br> &nbsp; &nbsp;glfwSetScrollCallback(window, scroll_callback);<br>\u200b<br> &nbsp; &nbsp;\/\/ tell GLFW to capture our mouse<br> &nbsp; &nbsp;glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);<br>\u200b<br> &nbsp; &nbsp;\/\/ glad: load all OpenGL function pointers<br> &nbsp; &nbsp;\/\/ ---------------------------------------<br> &nbsp; &nbsp;if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))<br> &nbsp;  {<br> &nbsp; &nbsp; &nbsp; &nbsp;std::cout &lt;&lt; \"Failed to initialize GLAD\" &lt;&lt; std::endl;<br> &nbsp; &nbsp; &nbsp; &nbsp;return -1;<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;\/\/ configure global opengl state<br> &nbsp; &nbsp;\/\/ -----------------------------<br> &nbsp; &nbsp;glEnable(GL_DEPTH_TEST);<br>\u200b<br> &nbsp; &nbsp;\/\/ build and compile our shader zprogram<br> &nbsp; &nbsp;\/\/ ------------------------------------<br> &nbsp; &nbsp;Shader lightingShader(\"6.multiple_lights.vs\", \"6.multiple_lights.fs\");<br> &nbsp; &nbsp;Shader lightCubeShader(\"6.light_cube.vs\", \"6.light_cube.fs\");<br>\u200b<br> &nbsp; &nbsp;\/\/ set up vertex data (and buffer(s)) and configure vertex attributes<br> &nbsp; &nbsp;\/\/ ------------------------------------------------------------------<br> &nbsp; &nbsp;float vertices[] = {<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ positions &nbsp; &nbsp; &nbsp; &nbsp;  \/\/ normals &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ texture coords<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, -0.5f, -0.5f, &nbsp;0.0f, &nbsp;0.0f, -1.0f, &nbsp;0.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, -0.5f, -0.5f, &nbsp;0.0f, &nbsp;0.0f, -1.0f, &nbsp;1.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, &nbsp;0.5f, -0.5f, &nbsp;0.0f, &nbsp;0.0f, -1.0f, &nbsp;1.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, &nbsp;0.5f, -0.5f, &nbsp;0.0f, &nbsp;0.0f, -1.0f, &nbsp;1.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, &nbsp;0.5f, -0.5f, &nbsp;0.0f, &nbsp;0.0f, -1.0f, &nbsp;0.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, -0.5f, -0.5f, &nbsp;0.0f, &nbsp;0.0f, -1.0f, &nbsp;0.0f, &nbsp;0.0f,<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, -0.5f, &nbsp;0.5f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, -0.5f, &nbsp;0.5f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;1.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, &nbsp;0.5f, &nbsp;0.5f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;1.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, &nbsp;0.5f, &nbsp;0.5f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;1.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, &nbsp;0.5f, &nbsp;0.5f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, -0.5f, &nbsp;0.5f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;0.0f,<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, &nbsp;0.5f, &nbsp;0.5f, -1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, &nbsp;0.5f, -0.5f, -1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, -0.5f, -0.5f, -1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, -0.5f, -0.5f, -1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, -0.5f, &nbsp;0.5f, -1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, &nbsp;0.5f, &nbsp;0.5f, -1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f,<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, &nbsp;0.5f, &nbsp;0.5f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, &nbsp;0.5f, -0.5f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, -0.5f, -0.5f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, -0.5f, -0.5f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, -0.5f, &nbsp;0.5f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, &nbsp;0.5f, &nbsp;0.5f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f,<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, -0.5f, -0.5f, &nbsp;0.0f, -1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, -0.5f, -0.5f, &nbsp;0.0f, -1.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, -0.5f, &nbsp;0.5f, &nbsp;0.0f, -1.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, -0.5f, &nbsp;0.5f, &nbsp;0.0f, -1.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, -0.5f, &nbsp;0.5f, &nbsp;0.0f, -1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, -0.5f, -0.5f, &nbsp;0.0f, -1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f,<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, &nbsp;0.5f, -0.5f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, &nbsp;0.5f, -0.5f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;1.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, &nbsp;0.5f, &nbsp;0.5f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp; 0.5f, &nbsp;0.5f, &nbsp;0.5f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, &nbsp;0.5f, &nbsp;0.5f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;0.0f,<br> &nbsp; &nbsp; &nbsp; &nbsp;-0.5f, &nbsp;0.5f, -0.5f, &nbsp;0.0f, &nbsp;1.0f, &nbsp;0.0f, &nbsp;0.0f, &nbsp;1.0f<br> &nbsp;  };<br> &nbsp; &nbsp;\/\/ positions all containers<br> &nbsp; &nbsp;glm::vec3 cubePositions[] = {<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3( 0.0f, &nbsp;0.0f, &nbsp;0.0f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3( 2.0f, &nbsp;5.0f, -15.0f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3(-1.5f, -2.2f, -2.5f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3(-3.8f, -2.0f, -12.3f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3( 2.4f, -0.4f, -3.5f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3(-1.7f, &nbsp;3.0f, -7.5f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3( 1.3f, -2.0f, -2.5f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3( 1.5f, &nbsp;2.0f, -2.5f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3( 1.5f, &nbsp;0.2f, -1.5f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3(-1.3f, &nbsp;1.0f, -1.5f)<br> &nbsp;  };<br> &nbsp; &nbsp;\/\/ positions of the point lights<br> &nbsp; &nbsp;glm::vec3 pointLightPositions[] = {<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3( 0.7f, &nbsp;0.2f, &nbsp;2.0f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3( 2.3f, -3.3f, -4.0f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3(-4.0f, &nbsp;2.0f, -12.0f),<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::vec3( 0.0f, &nbsp;0.0f, -3.0f)<br> &nbsp;  };<br> &nbsp; &nbsp;\/\/ first, configure the cube's VAO (and VBO)<br> &nbsp; &nbsp;unsigned int VBO, cubeVAO;<br> &nbsp; &nbsp;glGenVertexArrays(1, &amp;cubeVAO);<br> &nbsp; &nbsp;glGenBuffers(1, &amp;VBO);<br>\u200b<br> &nbsp; &nbsp;glBindBuffer(GL_ARRAY_BUFFER, VBO);<br> &nbsp; &nbsp;glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);<br>\u200b<br> &nbsp; &nbsp;glBindVertexArray(cubeVAO);<br> &nbsp; &nbsp;glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);<br> &nbsp; &nbsp;glEnableVertexAttribArray(0);<br> &nbsp; &nbsp;glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));<br> &nbsp; &nbsp;glEnableVertexAttribArray(1);<br> &nbsp; &nbsp;glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));<br> &nbsp; &nbsp;glEnableVertexAttribArray(2);<br>\u200b<br> &nbsp; &nbsp;\/\/ second, configure the light's VAO (VBO stays the same; the vertices are the same for the light object which is also a 3D cube)<br> &nbsp; &nbsp;unsigned int lightCubeVAO;<br> &nbsp; &nbsp;glGenVertexArrays(1, &amp;lightCubeVAO);<br> &nbsp; &nbsp;glBindVertexArray(lightCubeVAO);<br>\u200b<br> &nbsp; &nbsp;glBindBuffer(GL_ARRAY_BUFFER, VBO);<br> &nbsp; &nbsp;\/\/ note that we update the lamp's position attribute's stride to reflect the updated buffer data<br> &nbsp; &nbsp;glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);<br> &nbsp; &nbsp;glEnableVertexAttribArray(0);<br>\u200b<br> &nbsp; &nbsp;\/\/ load textures (we now use a utility function to keep the code more organized)<br> &nbsp; &nbsp;\/\/ -----------------------------------------------------------------------------<br> &nbsp; &nbsp;unsigned int diffuseMap = loadTexture(FileSystem::getPath(\"resources\/textures\/container2.png\").c_str());<br> &nbsp; &nbsp;unsigned int specularMap = loadTexture(FileSystem::getPath(\"resources\/textures\/container2_specular.png\").c_str());<br>\u200b<br> &nbsp; &nbsp;\/\/ shader configuration<br> &nbsp; &nbsp;\/\/ --------------------<br> &nbsp; &nbsp;lightingShader.use();<br> &nbsp; &nbsp;lightingShader.setInt(\"material.diffuse\", 0);<br> &nbsp; &nbsp;lightingShader.setInt(\"material.specular\", 1);<br>\u200b<br>\u200b<br> &nbsp; &nbsp;\/\/ render loop<br> &nbsp; &nbsp;\/\/ -----------<br> &nbsp; &nbsp;while (!glfwWindowShouldClose(window))<br> &nbsp;  {<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ per-frame time logic<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ --------------------<br> &nbsp; &nbsp; &nbsp; &nbsp;float currentFrame = glfwGetTime();<br> &nbsp; &nbsp; &nbsp; &nbsp;deltaTime = currentFrame - lastFrame;<br> &nbsp; &nbsp; &nbsp; &nbsp;lastFrame = currentFrame;<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ input<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ -----<br> &nbsp; &nbsp; &nbsp; &nbsp;processInput(window);<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ render<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ ------<br> &nbsp; &nbsp; &nbsp; &nbsp;glClearColor(0.1f, 0.1f, 0.1f, 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ be sure to activate shader when setting uniforms\/drawing objects<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.use();<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"viewPos\", camera.Position);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"material.shininess\", 32.0f);<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;\/*<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Here we set all the uniforms for the 5\/6 types of lights we have. We have to set them manually and index <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; the proper PointLight struct in the array to set each uniform variable. This can be done more code-friendly<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; by defining light types as classes and set their values in there, or by using a more efficient uniform approach<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; by using 'Uniform buffer objects', but that is something we'll discuss in the 'Advanced GLSL' tutorial.<br> &nbsp; &nbsp; &nbsp; &nbsp;*\/<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ directional light<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"dirLight.direction\", -0.2f, -1.0f, -0.3f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"dirLight.ambient\", 0.05f, 0.05f, 0.05f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"dirLight.diffuse\", 0.4f, 0.4f, 0.4f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"dirLight.specular\", 0.5f, 0.5f, 0.5f);<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ point light 1<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[0].position\", pointLightPositions[0]);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[0].ambient\", 0.05f, 0.05f, 0.05f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[0].diffuse\", 0.8f, 0.8f, 0.8f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[0].specular\", 1.0f, 1.0f, 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[0].constant\", 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[0].linear\", 0.09);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[0].quadratic\", 0.032);<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ point light 2<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[1].position\", pointLightPositions[1]);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[1].ambient\", 0.05f, 0.05f, 0.05f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[1].diffuse\", 0.8f, 0.8f, 0.8f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[1].specular\", 1.0f, 1.0f, 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[1].constant\", 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[1].linear\", 0.09);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[1].quadratic\", 0.032);<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ point light 3<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[2].position\", pointLightPositions[2]);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[2].ambient\", 0.05f, 0.05f, 0.05f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[2].diffuse\", 0.8f, 0.8f, 0.8f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[2].specular\", 1.0f, 1.0f, 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[2].constant\", 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[2].linear\", 0.09);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[2].quadratic\", 0.032);<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ point light 4<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[3].position\", pointLightPositions[3]);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[3].ambient\", 0.05f, 0.05f, 0.05f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[3].diffuse\", 0.8f, 0.8f, 0.8f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"pointLights[3].specular\", 1.0f, 1.0f, 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[3].constant\", 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[3].linear\", 0.09);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"pointLights[3].quadratic\", 0.032);<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ spotLight<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"spotLight.position\", camera.Position);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"spotLight.direction\", camera.Front);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"spotLight.ambient\", 0.0f, 0.0f, 0.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"spotLight.diffuse\", 1.0f, 1.0f, 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setVec3(\"spotLight.specular\", 1.0f, 1.0f, 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"spotLight.constant\", 1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"spotLight.linear\", 0.09);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"spotLight.quadratic\", 0.032);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"spotLight.cutOff\", glm::cos(glm::radians(12.5f)));<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setFloat(\"spotLight.outerCutOff\", glm::cos(glm::radians(15.0f))); &nbsp; &nbsp; <br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ view\/projection transformations<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH \/ (float)SCR_HEIGHT, 0.1f, 100.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::mat4 view = camera.GetViewMatrix();<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setMat4(\"projection\", projection);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setMat4(\"view\", view);<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ world transformation<br> &nbsp; &nbsp; &nbsp; &nbsp;glm::mat4 model = glm::mat4(1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setMat4(\"model\", model);<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ bind diffuse map<br> &nbsp; &nbsp; &nbsp; &nbsp;glActiveTexture(GL_TEXTURE0);<br> &nbsp; &nbsp; &nbsp; &nbsp;glBindTexture(GL_TEXTURE_2D, diffuseMap);<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ bind specular map<br> &nbsp; &nbsp; &nbsp; &nbsp;glActiveTexture(GL_TEXTURE1);<br> &nbsp; &nbsp; &nbsp; &nbsp;glBindTexture(GL_TEXTURE_2D, specularMap);<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ render containers<br> &nbsp; &nbsp; &nbsp; &nbsp;glBindVertexArray(cubeVAO);<br> &nbsp; &nbsp; &nbsp; &nbsp;for (unsigned int i = 0; i &lt; 10; i++)<br> &nbsp; &nbsp; &nbsp;  {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ calculate the model matrix for each object and pass it to shader before drawing<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;glm::mat4 model = glm::mat4(1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;model = glm::translate(model, cubePositions[i]);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;float angle = 20.0f * i;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lightingShader.setMat4(\"model\", model);<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;glDrawArrays(GL_TRIANGLES, 0, 36);<br> &nbsp; &nbsp; &nbsp;  }<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp; \/\/ also draw the lamp object(s)<br> &nbsp; &nbsp; &nbsp; &nbsp; lightCubeShader.use();<br> &nbsp; &nbsp; &nbsp; &nbsp; lightCubeShader.setMat4(\"projection\", projection);<br> &nbsp; &nbsp; &nbsp; &nbsp; lightCubeShader.setMat4(\"view\", view);<br> &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; \/\/ we now draw as many light bulbs as we have point lights.<br> &nbsp; &nbsp; &nbsp; &nbsp; glBindVertexArray(lightCubeVAO);<br> &nbsp; &nbsp; &nbsp; &nbsp; for (unsigned int i = 0; i &lt; 4; i++)<br> &nbsp; &nbsp; &nbsp; &nbsp; {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; model = glm::mat4(1.0f);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; model = glm::translate(model, pointLightPositions[i]);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; model = glm::scale(model, glm::vec3(0.2f)); \/\/ Make it a smaller cube<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lightCubeShader.setMat4(\"model\", model);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; glDrawArrays(GL_TRIANGLES, 0, 36);<br> &nbsp; &nbsp; &nbsp; &nbsp; }<br>\u200b<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ glfw: swap buffers and poll IO events (keys pressed\/released, mouse moved etc.)<br> &nbsp; &nbsp; &nbsp; &nbsp;\/\/ -------------------------------------------------------------------------------<br> &nbsp; &nbsp; &nbsp; &nbsp;glfwSwapBuffers(window);<br> &nbsp; &nbsp; &nbsp; &nbsp;glfwPollEvents();<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;\/\/ optional: de-allocate all resources once they've outlived their purpose:<br> &nbsp; &nbsp;\/\/ ------------------------------------------------------------------------<br> &nbsp; &nbsp;glDeleteVertexArrays(1, &amp;cubeVAO);<br> &nbsp; &nbsp;glDeleteVertexArrays(1, &amp;lightCubeVAO);<br> &nbsp; &nbsp;glDeleteBuffers(1, &amp;VBO);<br>\u200b<br> &nbsp; &nbsp;\/\/ glfw: terminate, clearing all previously allocated GLFW resources.<br> &nbsp; &nbsp;\/\/ ------------------------------------------------------------------<br> &nbsp; &nbsp;glfwTerminate();<br> &nbsp; &nbsp;return 0;<br>}<br>\u200b<br>\/\/ process all input: query GLFW whether relevant keys are pressed\/released this frame and react accordingly<br>\/\/ ---------------------------------------------------------------------------------------------------------<br>void processInput(GLFWwindow *window)<br>{<br> &nbsp; &nbsp;if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)<br> &nbsp; &nbsp; &nbsp; &nbsp;glfwSetWindowShouldClose(window, true);<br>\u200b<br> &nbsp; &nbsp;if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)<br> &nbsp; &nbsp; &nbsp; &nbsp;camera.ProcessKeyboard(FORWARD, deltaTime);<br> &nbsp; &nbsp;if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)<br> &nbsp; &nbsp; &nbsp; &nbsp;camera.ProcessKeyboard(BACKWARD, deltaTime);<br> &nbsp; &nbsp;if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)<br> &nbsp; &nbsp; &nbsp; &nbsp;camera.ProcessKeyboard(LEFT, deltaTime);<br> &nbsp; &nbsp;if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)<br> &nbsp; &nbsp; &nbsp; &nbsp;camera.ProcessKeyboard(RIGHT, deltaTime);<br>}<br>\u200b<br>\/\/ glfw: whenever the window size changed (by OS or user resize) this callback function executes<br>\/\/ ---------------------------------------------------------------------------------------------<br>void framebuffer_size_callback(GLFWwindow* window, int width, int height)<br>{<br> &nbsp; &nbsp;\/\/ make sure the viewport matches the new window dimensions; note that width and <br> &nbsp; &nbsp;\/\/ height will be significantly larger than specified on retina displays.<br> &nbsp; &nbsp;glViewport(0, 0, width, height);<br>}<br>\u200b<br>\/\/ glfw: whenever the mouse moves, this callback is called<br>\/\/ -------------------------------------------------------<br>void mouse_callback(GLFWwindow* window, double xpos, double ypos)<br>{<br> &nbsp; &nbsp;if (firstMouse)<br> &nbsp;  {<br> &nbsp; &nbsp; &nbsp; &nbsp;lastX = xpos;<br> &nbsp; &nbsp; &nbsp; &nbsp;lastY = ypos;<br> &nbsp; &nbsp; &nbsp; &nbsp;firstMouse = false;<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;float xoffset = xpos - lastX;<br> &nbsp; &nbsp;float yoffset = lastY - ypos; \/\/ reversed since y-coordinates go from bottom to top<br>\u200b<br> &nbsp; &nbsp;lastX = xpos;<br> &nbsp; &nbsp;lastY = ypos;<br>\u200b<br> &nbsp; &nbsp;camera.ProcessMouseMovement(xoffset, yoffset);<br>}<br>\u200b<br>\/\/ glfw: whenever the mouse scroll wheel scrolls, this callback is called<br>\/\/ ----------------------------------------------------------------------<br>void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)<br>{<br> &nbsp; &nbsp;camera.ProcessMouseScroll(yoffset);<br>}<br>\u200b<br>\/\/ utility function for loading a 2D texture from file<br>\/\/ ---------------------------------------------------<br>unsigned int loadTexture(char const * path)<br>{<br> &nbsp; &nbsp;unsigned int textureID;<br> &nbsp; &nbsp;glGenTextures(1, &amp;textureID);<br>\u200b<br> &nbsp; &nbsp;int width, height, nrComponents;<br> &nbsp; &nbsp;unsigned char *data = stbi_load(path, &amp;width, &amp;height, &amp;nrComponents, 0);<br> &nbsp; &nbsp;if (data)<br> &nbsp;  {<br> &nbsp; &nbsp; &nbsp; &nbsp;GLenum format;<br> &nbsp; &nbsp; &nbsp; &nbsp;if (nrComponents == 1)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;format = GL_RED;<br> &nbsp; &nbsp; &nbsp; &nbsp;else if (nrComponents == 3)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;format = GL_RGB;<br> &nbsp; &nbsp; &nbsp; &nbsp;else if (nrComponents == 4)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;format = GL_RGBA;<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;glBindTexture(GL_TEXTURE_2D, textureID);<br> &nbsp; &nbsp; &nbsp; &nbsp;glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);<br> &nbsp; &nbsp; &nbsp; &nbsp;glGenerateMipmap(GL_TEXTURE_2D);<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);<br> &nbsp; &nbsp; &nbsp; &nbsp;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);<br> &nbsp; &nbsp; &nbsp; &nbsp;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);<br> &nbsp; &nbsp; &nbsp; &nbsp;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);<br>\u200b<br> &nbsp; &nbsp; &nbsp; &nbsp;stbi_image_free(data);<br> &nbsp;  }<br> &nbsp; &nbsp;else<br> &nbsp;  {<br> &nbsp; &nbsp; &nbsp; &nbsp;std::cout &lt;&lt; \"Texture failed to load at path: \" &lt;&lt; path &lt;&lt; std::endl;<br> &nbsp; &nbsp; &nbsp; &nbsp;stbi_image_free(data);<br> &nbsp;  }<br>\u200b<br> &nbsp; &nbsp;return textureID;<br>}<br>\u200b<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span id=\"2_VS2012\">2.\u5b8c\u6574\u7684\u9879\u76ee\u4ee3\u7801 VS2012<\/span><\/h3>\n\n\n\n<p>\u94fe\u63a5\uff1a<a href=\"https:\/\/pan.baidu.com\/s\/17sjY756zaTE3yaWsG55JWA\">https:\/\/pan.baidu.com\/s\/17sjY756zaTE3yaWsG55JWA<\/a> \u63d0\u53d6\u7801\uff1a9nmh<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span id=\"3\">3.\u53c2\u8003\u8d44\u6599<\/span><\/h3>\n\n\n\n<p><a href=\"https:\/\/learnopengl-cn.github.io\/02%20Lighting\/06%20Multiple%20lights\/\">https:\/\/learnopengl-cn.github.io\/02%20Lighting\/06%20Multiple%20lights\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Contents1 \u6548\u679c\uff1a2 1.\u4e3b\u8981\u5b9e\u73b0\u4ee3\u7801\uff1a3 2.\u5b8c\u6574\u7684\u9879\u76ee\u4ee3\u7801 VS20124 3.\u53c2\u8003\u8d44\u6599 \u6548\u679c\uff1a \u521b\u5efa\u4e00\u4e2a\u5305\u542b\u516d\u4e2a\u5149\u6e90\u7684\u573a\u666f\u3002\u5c06\u6a21\u62df\u4e00\u4e2a\u7c7b\u4f3c\u592a\u9633\u7684\u5b9a\u5411\u5149(Directional Light)\u5149\u6e90\uff0c\u56db\u4e2a\u5206\u6563\u5728\u573a\u666f\u4e2d\u7684\u70b9\u5149\u6e90(Point Light)\uff0c\u4ee5\u53ca\u4e00\u4e2a\u624b\u7535\u7b52(Flashlight)\u3002 \u4e3a\u4e86\u5728\u573a\u666f\u4e2d\u4f7f\u7528\u591a\u4e2a\u5149\u6e90\uff0c\u6211\u4eec\u5e0c\u671b\u5c06\u5149\u7167\u8ba1\u7b97\u5c01\u88c5\u5230GLSL\u51fd\u6570\u4e2d\u3002\u8fd9\u6837\u505a\u7684\u539f\u56e0\u662f\uff0c\u6bcf\u4e00\u79cd\u5149\u6e90\u90fd\u9700\u8981\u4e00\u79cd\u4e0d\u540c\u7684\u8ba1\u7b97\u65b9\u6cd5\uff0c\u800c\u4e00\u65e6\u6211\u4eec\u60f3\u5bf9\u591a\u4e2a\u5149\u6e90\u8fdb\u884c\u5149\u7167\u8ba1\u7b97\u65f6\uff0c\u4ee3\u7801\u5f88\u5feb\u5c31\u4f1a\u53d8\u5f97\u975e\u5e38\u590d\u6742\u3002\u5982\u679c\u6211\u4eec\u53ea\u5728main\u51fd\u6570\u4e2d\u8fdb\u884c\u6240\u6709\u7684\u8fd9\u4e9b\u8ba1\u7b97\uff0c\u4ee3\u7801\u5f88\u5feb\u5c31\u4f1a\u53d8\u5f97\u96be\u4ee5\u7406\u89e3\u3002 GLSL\u4e2d\u7684\u51fd\u6570\u548cC\u51fd\u6570\u5f88\u76f8\u4f3c\uff0c\u5b83\u6709\u4e00\u4e2a\u51fd\u6570\u540d\u3001\u4e00\u4e2a\u8fd4\u56de\u503c\u7c7b\u578b\uff0c\u5982\u679c\u51fd\u6570\u4e0d\u662f\u5728main\u51fd\u6570\u4e4b\u524d\u58f0\u660e\u7684\uff0c\u6211\u4eec\u8fd8\u5fc5\u987b\u5728\u4ee3\u7801\u6587\u4ef6\u9876\u90e8\u58f0\u660e\u4e00\u4e2a\u539f\u578b\u3002\u6211\u4eec\u5bf9\u6bcf\u4e2a\u5149\u7167\u7c7b\u578b\u90fd\u521b\u5efa\u4e00\u4e2a\u4e0d\u540c\u7684\u51fd\u6570\uff1a\u5b9a\u5411\u5149\u3001\u70b9\u5149\u6e90\u548c\u805a\u5149\u3002 \u5f53\u6211\u4eec\u5728\u573a\u666f\u4e2d\u4f7f\u7528\u591a\u4e2a\u5149\u6e90\u65f6\uff0c\u6211\u4eec\u9700\u8981\u6709\u4e00\u4e2a\u5355\u72ec\u7684\u989c\u8272\u5411\u91cf\u4ee3\u8868\u7247\u6bb5\u7684\u8f93\u51fa\u989c\u8272\u3002\u5bf9\u4e8e\u6bcf\u4e00\u4e2a\u5149\u6e90\uff0c\u5b83\u5bf9\u7247\u6bb5\u7684\u8d21\u732e\u989c\u8272\u5c06\u4f1a\u52a0\u5230\u7247\u6bb5\u7684\u8f93\u51fa\u989c\u8272\u5411\u91cf\u4e0a\u3002\u6240\u4ee5\u573a\u666f\u4e2d\u7684\u6bcf\u4e2a\u5149\u6e90\u90fd\u4f1a\u8ba1\u7b97\u5b83\u4eec\u5404\u81ea\u5bf9\u7247\u6bb5\u7684\u5f71\u54cd\uff0c\u5e76\u7ed3\u5408\u4e3a\u4e00\u4e2a\u6700\u7ec8\u7684\u8f93\u51fa\u989c\u8272\u3002 1.\u4e3b\u8981\u5b9e\u73b0\u4ee3\u7801&#8230;<\/p>\n<p class=\"read-more\"><a class=\"btn btn-default\" href=\"http:\/\/liyanliang.net\/index.php\/2021\/01\/08\/opengl%e5%ae%9e%e7%8e%b0%e5%a4%9a%e5%85%89%e6%ba%90-%e9%99%84%e9%a1%b9%e7%9b%ae%e6%ba%90%e7%a0%81\/\"> Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":136,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14],"tags":[15],"class_list":["post-83","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-opengl","tag-opengl"],"_links":{"self":[{"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/posts\/83","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/comments?post=83"}],"version-history":[{"count":3,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/posts\/83\/revisions"}],"predecessor-version":[{"id":89,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/posts\/83\/revisions\/89"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/media\/136"}],"wp:attachment":[{"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/media?parent=83"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/categories?post=83"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/liyanliang.net\/index.php\/wp-json\/wp\/v2\/tags?post=83"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}