Skip to content
  • 首页
  • 留言
  • 关于

Share the joys of programming and technology

OpenGL实现多光源-附项目源码

OpenGL实现多光源-附项目源码

2021年1月8日 liyanliang Comments 1 comment

效果:

创建一个包含六个光源的场景。将模拟一个类似太阳的定向光(Directional Light)光源,四个分散在场景中的点光源(Point Light),以及一个手电筒(Flashlight)。

为了在场景中使用多个光源,我们希望将光照计算封装到GLSL函数中。这样做的原因是,每一种光源都需要一种不同的计算方法,而一旦我们想对多个光源进行光照计算时,代码很快就会变得非常复杂。如果我们只在main函数中进行所有的这些计算,代码很快就会变得难以理解。

GLSL中的函数和C函数很相似,它有一个函数名、一个返回值类型,如果函数不是在main函数之前声明的,我们还必须在代码文件顶部声明一个原型。我们对每个光照类型都创建一个不同的函数:定向光、点光源和聚光。

当我们在场景中使用多个光源时,我们需要有一个单独的颜色向量代表片段的输出颜色。对于每一个光源,它对片段的贡献颜色将会加到片段的输出颜色向量上。所以场景中的每个光源都会计算它们各自对片段的影响,并结合为一个最终的输出颜色。

1.主要实现代码:

main.cpp

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>
​
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
​
#include <learnopengl/shader_m.h>
#include <learnopengl/camera.h>
​
#include <iostream>
​
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow *window);
unsigned int loadTexture(const char *path);
​
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
​
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
bool firstMouse = true;
​
// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;
​
// lighting
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
​
int main()
{
   // glfw: initialize and configure
   // ------------------------------
   glfwInit();
   glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
   glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
   glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
​
#ifdef __APPLE__
       glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
​
   // glfw window creation
   // --------------------
   GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
   if (window == NULL)
  {
       std::cout << "Failed to create GLFW window" << std::endl;
       glfwTerminate();
       return -1;
  }
   glfwMakeContextCurrent(window);
   glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
   glfwSetCursorPosCallback(window, mouse_callback);
   glfwSetScrollCallback(window, scroll_callback);
​
   // tell GLFW to capture our mouse
   glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
​
   // glad: load all OpenGL function pointers
   // ---------------------------------------
   if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
  {
       std::cout << "Failed to initialize GLAD" << std::endl;
       return -1;
  }
​
   // configure global opengl state
   // -----------------------------
   glEnable(GL_DEPTH_TEST);
​
   // build and compile our shader zprogram
   // ------------------------------------
   Shader lightingShader("6.multiple_lights.vs", "6.multiple_lights.fs");
   Shader lightCubeShader("6.light_cube.vs", "6.light_cube.fs");
​
   // set up vertex data (and buffer(s)) and configure vertex attributes
   // ------------------------------------------------------------------
   float vertices[] = {
       // positions         // normals           // texture coords
       -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  0.0f,
        0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  0.0f,
        0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  1.0f,
        0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  1.0f,
       -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  1.0f,
       -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  0.0f,
​
       -0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,
        0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f,
       -0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  1.0f,
       -0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,
​
       -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
       -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  1.0f,
       -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
       -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
       -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  0.0f,
       -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
​
        0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  1.0f,
        0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
        0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
        0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
​
       -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  1.0f,
        0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  0.0f,
        0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  0.0f,
       -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  0.0f,
       -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  1.0f,
​
       -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  1.0f,
        0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  1.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  0.0f,
       -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,
       -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  1.0f
  };
   // positions all containers
   glm::vec3 cubePositions[] = {
       glm::vec3( 0.0f,  0.0f,  0.0f),
       glm::vec3( 2.0f,  5.0f, -15.0f),
       glm::vec3(-1.5f, -2.2f, -2.5f),
       glm::vec3(-3.8f, -2.0f, -12.3f),
       glm::vec3( 2.4f, -0.4f, -3.5f),
       glm::vec3(-1.7f,  3.0f, -7.5f),
       glm::vec3( 1.3f, -2.0f, -2.5f),
       glm::vec3( 1.5f,  2.0f, -2.5f),
       glm::vec3( 1.5f,  0.2f, -1.5f),
       glm::vec3(-1.3f,  1.0f, -1.5f)
  };
   // positions of the point lights
   glm::vec3 pointLightPositions[] = {
       glm::vec3( 0.7f,  0.2f,  2.0f),
       glm::vec3( 2.3f, -3.3f, -4.0f),
       glm::vec3(-4.0f,  2.0f, -12.0f),
       glm::vec3( 0.0f,  0.0f, -3.0f)
  };
   // first, configure the cube's VAO (and VBO)
   unsigned int VBO, cubeVAO;
   glGenVertexArrays(1, &cubeVAO);
   glGenBuffers(1, &VBO);
​
   glBindBuffer(GL_ARRAY_BUFFER, VBO);
   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
​
   glBindVertexArray(cubeVAO);
   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
   glEnableVertexAttribArray(0);
   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
   glEnableVertexAttribArray(1);
   glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
   glEnableVertexAttribArray(2);
​
   // 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)
   unsigned int lightCubeVAO;
   glGenVertexArrays(1, &lightCubeVAO);
   glBindVertexArray(lightCubeVAO);
​
   glBindBuffer(GL_ARRAY_BUFFER, VBO);
   // note that we update the lamp's position attribute's stride to reflect the updated buffer data
   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
   glEnableVertexAttribArray(0);
​
   // load textures (we now use a utility function to keep the code more organized)
   // -----------------------------------------------------------------------------
   unsigned int diffuseMap = loadTexture(FileSystem::getPath("resources/textures/container2.png").c_str());
   unsigned int specularMap = loadTexture(FileSystem::getPath("resources/textures/container2_specular.png").c_str());
​
   // shader configuration
   // --------------------
   lightingShader.use();
   lightingShader.setInt("material.diffuse", 0);
   lightingShader.setInt("material.specular", 1);
​
​
   // render loop
   // -----------
   while (!glfwWindowShouldClose(window))
  {
       // per-frame time logic
       // --------------------
       float currentFrame = glfwGetTime();
       deltaTime = currentFrame - lastFrame;
       lastFrame = currentFrame;
​
       // input
       // -----
       processInput(window);
​
       // render
       // ------
       glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
​
       // be sure to activate shader when setting uniforms/drawing objects
       lightingShader.use();
       lightingShader.setVec3("viewPos", camera.Position);
       lightingShader.setFloat("material.shininess", 32.0f);
​
       /*
          Here we set all the uniforms for the 5/6 types of lights we have. We have to set them manually and index
          the proper PointLight struct in the array to set each uniform variable. This can be done more code-friendly
          by defining light types as classes and set their values in there, or by using a more efficient uniform approach
          by using 'Uniform buffer objects', but that is something we'll discuss in the 'Advanced GLSL' tutorial.
       */
       // directional light
       lightingShader.setVec3("dirLight.direction", -0.2f, -1.0f, -0.3f);
       lightingShader.setVec3("dirLight.ambient", 0.05f, 0.05f, 0.05f);
       lightingShader.setVec3("dirLight.diffuse", 0.4f, 0.4f, 0.4f);
       lightingShader.setVec3("dirLight.specular", 0.5f, 0.5f, 0.5f);
       // point light 1
       lightingShader.setVec3("pointLights[0].position", pointLightPositions[0]);
       lightingShader.setVec3("pointLights[0].ambient", 0.05f, 0.05f, 0.05f);
       lightingShader.setVec3("pointLights[0].diffuse", 0.8f, 0.8f, 0.8f);
       lightingShader.setVec3("pointLights[0].specular", 1.0f, 1.0f, 1.0f);
       lightingShader.setFloat("pointLights[0].constant", 1.0f);
       lightingShader.setFloat("pointLights[0].linear", 0.09);
       lightingShader.setFloat("pointLights[0].quadratic", 0.032);
       // point light 2
       lightingShader.setVec3("pointLights[1].position", pointLightPositions[1]);
       lightingShader.setVec3("pointLights[1].ambient", 0.05f, 0.05f, 0.05f);
       lightingShader.setVec3("pointLights[1].diffuse", 0.8f, 0.8f, 0.8f);
       lightingShader.setVec3("pointLights[1].specular", 1.0f, 1.0f, 1.0f);
       lightingShader.setFloat("pointLights[1].constant", 1.0f);
       lightingShader.setFloat("pointLights[1].linear", 0.09);
       lightingShader.setFloat("pointLights[1].quadratic", 0.032);
       // point light 3
       lightingShader.setVec3("pointLights[2].position", pointLightPositions[2]);
       lightingShader.setVec3("pointLights[2].ambient", 0.05f, 0.05f, 0.05f);
       lightingShader.setVec3("pointLights[2].diffuse", 0.8f, 0.8f, 0.8f);
       lightingShader.setVec3("pointLights[2].specular", 1.0f, 1.0f, 1.0f);
       lightingShader.setFloat("pointLights[2].constant", 1.0f);
       lightingShader.setFloat("pointLights[2].linear", 0.09);
       lightingShader.setFloat("pointLights[2].quadratic", 0.032);
       // point light 4
       lightingShader.setVec3("pointLights[3].position", pointLightPositions[3]);
       lightingShader.setVec3("pointLights[3].ambient", 0.05f, 0.05f, 0.05f);
       lightingShader.setVec3("pointLights[3].diffuse", 0.8f, 0.8f, 0.8f);
       lightingShader.setVec3("pointLights[3].specular", 1.0f, 1.0f, 1.0f);
       lightingShader.setFloat("pointLights[3].constant", 1.0f);
       lightingShader.setFloat("pointLights[3].linear", 0.09);
       lightingShader.setFloat("pointLights[3].quadratic", 0.032);
       // spotLight
       lightingShader.setVec3("spotLight.position", camera.Position);
       lightingShader.setVec3("spotLight.direction", camera.Front);
       lightingShader.setVec3("spotLight.ambient", 0.0f, 0.0f, 0.0f);
       lightingShader.setVec3("spotLight.diffuse", 1.0f, 1.0f, 1.0f);
       lightingShader.setVec3("spotLight.specular", 1.0f, 1.0f, 1.0f);
       lightingShader.setFloat("spotLight.constant", 1.0f);
       lightingShader.setFloat("spotLight.linear", 0.09);
       lightingShader.setFloat("spotLight.quadratic", 0.032);
       lightingShader.setFloat("spotLight.cutOff", glm::cos(glm::radians(12.5f)));
       lightingShader.setFloat("spotLight.outerCutOff", glm::cos(glm::radians(15.0f)));    
​
       // view/projection transformations
       glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
       glm::mat4 view = camera.GetViewMatrix();
       lightingShader.setMat4("projection", projection);
       lightingShader.setMat4("view", view);
​
       // world transformation
       glm::mat4 model = glm::mat4(1.0f);
       lightingShader.setMat4("model", model);
​
       // bind diffuse map
       glActiveTexture(GL_TEXTURE0);
       glBindTexture(GL_TEXTURE_2D, diffuseMap);
       // bind specular map
       glActiveTexture(GL_TEXTURE1);
       glBindTexture(GL_TEXTURE_2D, specularMap);
​
       // render containers
       glBindVertexArray(cubeVAO);
       for (unsigned int i = 0; i < 10; i++)
      {
           // calculate the model matrix for each object and pass it to shader before drawing
           glm::mat4 model = glm::mat4(1.0f);
           model = glm::translate(model, cubePositions[i]);
           float angle = 20.0f * i;
           model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
           lightingShader.setMat4("model", model);
​
           glDrawArrays(GL_TRIANGLES, 0, 36);
      }
​
        // also draw the lamp object(s)
        lightCubeShader.use();
        lightCubeShader.setMat4("projection", projection);
        lightCubeShader.setMat4("view", view);
   
        // we now draw as many light bulbs as we have point lights.
        glBindVertexArray(lightCubeVAO);
        for (unsigned int i = 0; i < 4; i++)
        {
            model = glm::mat4(1.0f);
            model = glm::translate(model, pointLightPositions[i]);
            model = glm::scale(model, glm::vec3(0.2f)); // Make it a smaller cube
            lightCubeShader.setMat4("model", model);
            glDrawArrays(GL_TRIANGLES, 0, 36);
        }
​
​
       // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
       // -------------------------------------------------------------------------------
       glfwSwapBuffers(window);
       glfwPollEvents();
  }
​
   // optional: de-allocate all resources once they've outlived their purpose:
   // ------------------------------------------------------------------------
   glDeleteVertexArrays(1, &cubeVAO);
   glDeleteVertexArrays(1, &lightCubeVAO);
   glDeleteBuffers(1, &VBO);
​
   // glfw: terminate, clearing all previously allocated GLFW resources.
   // ------------------------------------------------------------------
   glfwTerminate();
   return 0;
}
​
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
   if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
       glfwSetWindowShouldClose(window, true);
​
   if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
       camera.ProcessKeyboard(FORWARD, deltaTime);
   if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
       camera.ProcessKeyboard(BACKWARD, deltaTime);
   if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
       camera.ProcessKeyboard(LEFT, deltaTime);
   if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
       camera.ProcessKeyboard(RIGHT, deltaTime);
}
​
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
   // make sure the viewport matches the new window dimensions; note that width and
   // height will be significantly larger than specified on retina displays.
   glViewport(0, 0, width, height);
}
​
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
   if (firstMouse)
  {
       lastX = xpos;
       lastY = ypos;
       firstMouse = false;
  }
​
   float xoffset = xpos - lastX;
   float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
​
   lastX = xpos;
   lastY = ypos;
​
   camera.ProcessMouseMovement(xoffset, yoffset);
}
​
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
   camera.ProcessMouseScroll(yoffset);
}
​
// utility function for loading a 2D texture from file
// ---------------------------------------------------
unsigned int loadTexture(char const * path)
{
   unsigned int textureID;
   glGenTextures(1, &textureID);
​
   int width, height, nrComponents;
   unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
   if (data)
  {
       GLenum format;
       if (nrComponents == 1)
           format = GL_RED;
       else if (nrComponents == 3)
           format = GL_RGB;
       else if (nrComponents == 4)
           format = GL_RGBA;
​
       glBindTexture(GL_TEXTURE_2D, textureID);
       glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
       glGenerateMipmap(GL_TEXTURE_2D);
​
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
​
       stbi_image_free(data);
  }
   else
  {
       std::cout << "Texture failed to load at path: " << path << std::endl;
       stbi_image_free(data);
  }
​
   return textureID;
}
​

2.完整的项目代码 VS2012

链接:https://pan.baidu.com/s/17sjY756zaTE3yaWsG55JWA 提取码:9nmh

3.参考资料

https://learnopengl-cn.github.io/02%20Lighting/06%20Multiple%20lights/

相关文章

  • OpenGL 几何着色器的应用OpenGL 几何着色器的应用
  • OpenGL绘制桥梁模型OpenGL绘制桥梁模型
  • Modern OpenGL绘制圆柱体Modern OpenGL绘制圆柱体
  • OpenGL绘制旋转立方体OpenGL绘制旋转立方体
  • OpenGL模型加载-附源码OpenGL模型加载-附源码
  • OpenGL开发环境搭建-GLFW与GLAD配置 超详细OpenGL开发环境搭建-GLFW与GLAD配置 超详细

OpenGL
OpenGL

Post navigation

PREVIOUS
OpenGL开发环境搭建-GLFW与GLAD配置 超详细
NEXT
ODA的基本操作-平移、旋转、矩阵变换

One thought on “OpenGL实现多光源-附项目源码”

  1. 王晓说道:
    2021年1月9日 23:23

    Great

    回复

发表回复 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

近期文章

  • IBL计算总结
  • Filament加载并渲染glTF模型
  • 在mapbox中实现3dtiles的加载和绘制(移动端)
  • 视锥体与AABB和OBB包围盒相交判断
  • 倾斜摄影在mapbox中的坐标转换
  • 解析3dTiles数据和提取b3dm模型文件
  • C++实现一个简单的语言解释器
  • OpenGL-法线贴图(Normal Mapping)
  • OpenGL-卡通着色(Cartoon)
  • OpenGL几何着色器实现贝塞尔曲线
  • WinDbg检查内存泄漏
  • OpenGL雾化效果实现-每像素雾化
  • OpenGL实现billboard效果(CPU)
  • 算法:寻找异常数字
  • OpenGL 几何着色器的应用
  • Midas XD-构件详图开发
  • Midas XD-选筋助手开发
  • Civil Designer开发-检测规范自动生成控制截面
  • Civil Designer开发-公路桥梁承载能力检算评定
  • Midas W-满堂支架快速建模助手开发

全站热点

  • C++编写的情人节小程序 (1,503)
  • Modern OpenGL绘制圆柱体 (703)
  • 提取最小封闭区域 (634)
  • 判断一个点是否在闭合区域内 (536)
  • 截面特性计算程序-附源码 (524)
  • OpenGL开发环境搭建-GLFW与GLAD配置 超详细 (487)
  • OpenGL绘制旋转立方体 (435)
  • Midas XD [错误] 右侧挡土墙的最下端深度必须小于地基的最下端深度 (411)
  • WordPress分页插件 – WP-PageNavi的使用(替换现有脚本) (375)
  • 使用ODA数据库出现 “ODA_ASSUME”: 找不到标识符的错误 (350)
  • 解析3dTiles数据和提取b3dm模型文件 (345)
  • 土木想往土木软件开发方向发展,应该如何准备 (330)
  • #pragma message 编译时提示信息 (322)
  • midas XD2020的开发 (317)
  • 从DLL中动态加载一个函数:LoadLibrary和GetProcAddress的使用 (308)
  • 两跨连续梁影响线绘制-附源码 (300)
  • Midas W-满堂支架快速建模助手开发 (290)
  • 算法:寻找异常数字 (249)
  • OpenGL几何着色器实现贝塞尔曲线 (174)
  • 通过Spy++抓取窗口以查询对话框id (173)

分类

  • C# (3)
  • C++ (17)
  • Filament (1)
  • GIS (3)
  • MFC (3)
  • ObjectARX (2)
  • OpenGL (12)
  • Revit开发 (1)
  • 岩土 (2)
  • 算法 (1)
  • 结构设计 (7)
  • 职场生涯 (1)
  • 计算几何 (3)

归档

  • 2022年10月 (3)
  • 2022年7月 (2)
  • 2022年4月 (1)
  • 2022年3月 (1)
  • 2022年2月 (1)
  • 2022年1月 (5)
  • 2021年11月 (7)
  • 2021年6月 (3)
  • 2021年5月 (2)
  • 2021年3月 (2)
  • 2021年2月 (8)
  • 2021年1月 (18)

标签

3dtiles b3dm Bezier Curves BillBoard C++ CDN CivilDesigner DLL EasyX filament fog GIS glTF json mapbox MFC Midas W Midas XD NormalMapping ObjectARX ODA OpenGL OpenXML Open XML PBR revit WinDbg 基坑设计 影响线 截面特性 桥梁 桥梁检测 桥梁设计 算法 计算几何 设计模式

书签

  • 李燕良的CSDN
  • 崔济东的博客
  • C++爱好者博客
  • 陈学伟的博客
  • 贾苏的博客
  • 陈睦锋的博客
  • 孙勇的博客

统计

  • 0
  • 43
  • 8
  • 57
  • 23
  • 69,989
  • 21,750

实时访问地域

© 2023   liyanliang.net Copyright. All Rights Reserved.