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

Share the joys of programming and technology

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

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

2021年1月8日 liyanliang Comments 1 comment
阅读次数: 110

Contents

  • 1 效果:
  • 2 1.主要实现代码:
  • 3 2.完整的项目代码 VS2012
  • 4 3.参考资料
  • 5 相关文章

效果:

创建一个包含六个光源的场景。将模拟一个类似太阳的定向光(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/

相关文章

  • LearnOpenGL脑图汇总LearnOpenGL脑图汇总
  • OpenGL 几何着色器的应用OpenGL 几何着色器的应用
  • OpenGL绘制桥梁模型OpenGL绘制桥梁模型
  • Modern OpenGL绘制圆柱体Modern OpenGL绘制圆柱体
  • OpenGL绘制旋转立方体OpenGL绘制旋转立方体
  • OpenGL模型加载-附源码OpenGL模型加载-附源码

OpenGL
OpenGL

Post navigation

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

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

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

    Great

    回复

发表回复 取消回复

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

近期文章

  • ANR崩溃日志查看方法
  • 通过数学方法来计算short类型的变量w的低八位x和高八位
  • 3dTiles数据解析
  • Games101和Games202脑图汇总
  • LearnOpenGL脑图汇总
  • IBL计算总结
  • C++实现一个简单的语言解释器
  • OpenGL-法线贴图(Normal Mapping)
  • OpenGL-卡通着色(Cartoon)
  • OpenGL几何着色器实现贝塞尔曲线
  • WinDbg检查内存泄漏
  • OpenGL雾化效果实现-每像素雾化
  • OpenGL实现billboard效果(CPU)
  • 算法:寻找异常数字
  • OpenGL 几何着色器的应用
  • Midas XD-构件详图开发
  • Midas XD-选筋助手开发
  • Civil Designer开发-检测规范自动生成控制截面
  • Civil Designer开发-公路桥梁承载能力检算评定
  • Midas W-满堂支架快速建模助手开发

全站热点

  • C++编写的情人节小程序 (2,078)
  • 提取最小封闭区域 (1,692)
  • Modern OpenGL绘制圆柱体 (1,604)
  • OpenGL开发环境搭建-GLFW与GLAD配置 超详细 (1,455)
  • 截面特性计算程序-附源码 (1,287)
  • OpenGL绘制旋转立方体 (1,103)
  • 判断一个点是否在闭合区域内 (1,031)
  • WordPress分页插件 – WP-PageNavi的使用(替换现有脚本) (947)
  • OpenGL实现billboard效果(CPU) (864)
  • Midas W-满堂支架快速建模助手开发 (832)
  • 从DLL中动态加载一个函数:LoadLibrary和GetProcAddress的使用 (746)
  • Midas XD [错误] 右侧挡土墙的最下端深度必须小于地基的最下端深度 (707)
  • 两跨连续梁影响线绘制-附源码 (685)
  • 土木想往土木软件开发方向发展,应该如何准备 (678)
  • OpenGL几何着色器实现贝塞尔曲线 (662)
  • 通过Spy++抓取窗口以查询对话框id (611)
  • 使用ODA数据库出现 “ODA_ASSUME”: 找不到标识符的错误 (547)
  • #pragma message 编译时提示信息 (525)
  • OpenGL雾化效果实现-每像素雾化 (507)
  • midas XD2020的开发 (472)

分类

  • C# (3)
  • C++ (19)
  • GIS (1)
  • MFC (3)
  • ObjectARX (2)
  • OpenGL (11)
  • Revit开发 (1)
  • 学习笔记 (2)
  • 岩土 (2)
  • 算法 (1)
  • 结构设计 (7)
  • 职场生涯 (1)
  • 计算几何 (3)

归档

  • 2024 年 12 月 (1)
  • 2024 年 10 月 (1)
  • 2024 年 9 月 (1)
  • 2023 年 3 月 (2)
  • 2022 年 10 月 (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 anr Bezier Curves BillBoard C++ CDN CivilDesigner DLL EasyX fog glTF MFC Midas W Midas XD NormalMapping ObjectARX ODA OpenGL OpenXML Open XML PBR revit WinDbg 基坑设计 影响线 截面特性 桥梁 桥梁检测 桥梁设计 算法 计算几何 设计模式

书签

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

统计

  • 0
  • 248
  • 126
  • 472
  • 198
  • 266,566
  • 76,756

实时访问地域

© 2025   liyanliang.net Copyright. All Rights Reserved.