OpenGL教程一,窗体和图形的渲染(包含OpenGL、GLFW、GLAD)

news2025/1/6 18:59:37

运行环境:Linux 、C++

  • 本教程仅个人学习总结
    • 第一个hello world,渲染一个窗体
    • 渲染一个矩形

本教程仅个人学习总结

一切参考资源:都在官网。

1、安装glfw

首先下载glfw : 点击这里

1、下载
2、解压
3、mkdir build && cd build
4、cmake … && make -j4
5、cd …
6、将此目录下的include目录里面的东西全拷到自己工程的include中
7、cd build/src 这个目录下面的静态库(默认编译是静态库) libglfw3.a ,为我们需要的库

1、 GLFW是一个专门针对OpenGL的C语言库,它提供了一些渲染物体所需的最低限度的接口。它允许用户创建OpenGL上下文、定义窗口参数以及处理用户输入,对我们来说这就够了。

因为OpenGL只是一个标准/规范,具体的实现是由驱动开发商针对特定显卡实现的。由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。所以任务就落在了开发者身上,开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用

2、安装GLAD
GLAD是一个开源的库,它能解决我们上面提到的那个繁琐的问题。GLAD的配置与大多数的开源库有些许的不同,GLAD使用了一个在线服务。在这里我们能够告诉GLAD需要定义的OpenGL版本,并且根据这个版本加载所有相关的OpenGL函数。
打开GLAD的在线服务,将语言(Language)设置为C/C++,在API选项中,选择3.3以上的OpenGL(gl)版本(我们的教程中将使用3.3版本,但更新的版本也能用)。之后将模式(Profile)设置为Core,并且保证选中了生成加载器(Generate a loader)选项。现在可以先(暂时)忽略扩展(Extensions)中的内容。都选择完之后,点击生成(Generate)按钮来生成库文件。

GLAD现在应该提供给你了一个zip压缩文件,包含两个头文件目录,和一个glad.c文件。将两个头文件目录(glad和KHR)复制到你的Include文件夹中(或者增加一个额外的项目指向这些目录),并添加glad.c文件到你的工程中。

3、OpenGL安装。本站一大堆教程这里就不多说了。

第一个hello world,渲染一个窗体

上文中说到GLFW提供了一系列操作OPENGL的接口,首先第一步即为初始化GLFW环境

#include "glfw3.h"

初始化前我们需要先知道GLFW的版本。

    int major = 0, minor = 0, rev = 0;
    glfwGetVersion(&major, &minor, &rev); //查看GLFW版本号
    std::cout << "GLFW version: " << major << "." << minor << "." << rev << std::endl;

然后我们在初始化GLFW环境

    if (glfwInit() == GLFW_FALSE)
    {
        std::cout << "Failed to initialize GLFW" << std::endl;
    }
    std::cout << "Success to initialize GLFW" << std::endl;

glfwInit这个函数有如下需要注意的点:

PS1:如果此函数失败,它会在返回前调用glfwTerminate。如果成功,您应该在应用程序退出之前调用glfwTerminate。
PS2:此函数只能从主线程调用。

我们还需要告诉GLFW我们使用的openGL版本和模式

    //教程都是基于OpenGL 3.3版本展开讨论的,所以我们需要告诉GLFW我们要使用的OpenGL版本是3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);                 //主板本号
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);                 //次
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //核心模式

具体设置GLFW的约束条件,我也没整明白~,目前就这么用。1、版本号,2、使用的openGL模式。

接下来就是创建窗口

    GLFWwindow *window = glfwCreateWindow(800, 600, "HelloWorld", NULL, NULL);//倒数第二个参数是选择的监视器模式
    //最后一个参数,基本用不到。
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }

注意创建失败的话,需要清除所有窗体。glfwTerminate此函数会销毁所有剩余的窗口和光标

接下来我们要设置窗体的归属,简单来说就是设置窗体为那个线程锁持有。

glfwMakeContextCurrent(window);  

一个窗体,大小肯定是可变的。我们可以通过鼠标去拉伸和缩放,这样窗体的大小就是可变的。因此我们要设置一个回调函数
实时设置我们手动改变窗体的大小。

void set_render_size(GLFWwindow *window, int width, int height);

glfwSetFramebufferSizeCallback(window, set_render_size); //注册这个函数,告诉GLFW我们希望每当窗口调整大小的时候调用这个函数

void set_render_size(GLFWwindow *window, int width, int height)
{
    std::cout<< width<<" "<< height<<std::endl;
    glViewport(0, 0, width, height);
}

下面就是要我们使用openGL来渲染这个窗体,这就要用到GLAD

再次说明一下GLAD的作用便于理解。

到这里还没有结束,我们仍然还有一件事要做。因为OpenGL只是一个标准/规范,具体的实现是由驱动开发商针对特定显卡实现的。由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。所以任务就落在了开发者身上,开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用。

初始化GLAD库:常用接口如下:
int gladLoadGLLoader(GLADloadproc load):任何的OpenGL接口调用都必须在初始化GLAD库后才可以正常访问。如果成功的话,该接口将返回GL_TRUE,否则就会返回GL_FALSE。
其中GLADloadproc函数声明如下:
void* (*GLADloadproc)(const char* name)


GLFWglproc glfwGetProcAddress	(	const char * 	procname	)	
如果当前上下文支持,此函数返回指定 OpenGL 或 OpenGL ES核心或扩展函数的地址。
上下文必须在调用线程上是当前的。在没有当前上下文的情况下调用此函数将导致GLFW_NO_CURRENT_CONTEXT错误。
    //初始化GLAD
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    const GLubyte *OpenGLVersion = glGetString(GL_VERSION); //返回当前OpenGL实现的版本号
    printf("OpenGL实现的版本号:%s\n", OpenGLVersion);
我们不希望只绘制一个图像之后我们的应用程序就立即退出并关闭窗口。
我们希望程序在我们主动关闭它之前不断绘制图像并能够接受用户输入。
因此,我们需要在程序中添加一个while循环,我们可以把它称之为渲染循环(Render Loop),
它能在我们让GLFW退出前一直保持运行。下面几行的代码就实现了一个简单的渲染循环。
    while (!glfwWindowShouldClose(window)) // glfwWindowShouldClose函数在我们每次循环的开始前检查一次GLFW是否被要求退出,
    {                                      //如果是的话该函数返回true然后渲染循环便结束了,之后为我们就可以关闭应用程序了。
        processInput(window);

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glfwSwapBuffers(window); //函数会交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上
        glfwPollEvents();        //函数检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。
    }

最后销毁所有窗体

    //销毁所有窗口
    glfwTerminate();

这样我们渲染一个窗体的大体流程就是这些

完整源码如下

#include <iostream>
#include <cstdio>
#include <sys/unistd.h>

#include "glad.h"
#include "glfw3.h"

void set_render_size(GLFWwindow *window, int width, int height);
void processInput(GLFWwindow *window);
int main()
{
    int major = 0, minor = 0, rev = 0;
    glfwGetVersion(&major, &minor, &rev); //查看GLFW版本号
    std::cout << "GLFW version: " << major << "." << minor << "." << rev << std::endl;
    if (glfwInit() == GLFW_FALSE)
    {
        std::cout << "Failed to initialize GLFW" << std::endl;
    }
    std::cout << "Success to initialize GLFW" << std::endl;

    //教程都是基于OpenGL 3.3版本展开讨论的,所以我们需要告诉GLFW我们要使用的OpenGL版本是3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);                 //主板本号
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);                 //次
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //核心模式

    GLFWwindow *window = glfwCreateWindow(800, 600, "HelloWorld", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);                          //使调用线程的指定窗口的上下文成为当前的
    glfwSetFramebufferSizeCallback(window, set_render_size); //注册这个函数,告诉GLFW我们希望每当窗口调整大小的时候调用这个函数:
    //初始化GLAD
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    const GLubyte *OpenGLVersion = glGetString(GL_VERSION); //返回当前OpenGL实现的版本号
    printf("OpenGL实现的版本号:%s\n", OpenGLVersion);

    /*
    不希望只绘制一个图像之后我们的应用程序就立即退出并关闭窗口。
    我们希望程序在我们主动关闭它之前不断绘制图像并能够接受用户输入。
    因此,我们需要在程序中添加一个while循环,我们可以把它称之为渲染循环(Render Loop),
    它能在我们让GLFW退出前一直保持运行。下面几行的代码就实现了一个简单的渲染循环:
    */
    while (!glfwWindowShouldClose(window)) // glfwWindowShouldClose函数在我们每次循环的开始前检查一次GLFW是否被要求退出,
    {                                      //如果是的话该函数返回true然后渲染循环便结束了,之后为我们就可以关闭应用程序了。
        processInput(window);

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glfwSwapBuffers(window); //函数会交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上
        glfwPollEvents();        //函数检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。
    }
    //销毁所有窗口
    glfwTerminate();
    return 0;
}

void set_render_size(GLFWwindow *window, int width, int height)
{
    std::cout<< width<<" "<< height<<std::endl;
    glViewport(0, 0, width, height);
}

void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

运行结果如下
在这里插入图片描述

渲染一个矩形

接下来我们尝试在渲染窗体中加上图形的渲染,理解起来可能有点抽象。

首先假设渲染图形肯定不可能只是平面图像吧,只是在屏幕上显示的是2D的图像。比如说一个苹果,在现实世界中肯定是3D的存在,但是我们屏幕
只是一个2D的平面,我们如何将一个现实世界3D的物体,转换成屏幕上2D显示呢(2D显示3D的效果)?这就涉及到坐标的转换了。

3D坐标转为2D坐标的处理过程是由OpenGL的图形渲染管线(Graphics Pipeline,大多译为管线,实际上指的是一堆原始图形数据途经一个输送管
道,期间经过各种变化处理最终出现在屏幕的过程)管理的。

图形渲染管线可以被划分为两个主要部分:
1、第一部分把你的3D坐标转换为2D坐标
2、2D坐标转变为实际的有颜色的像素。

图形渲染管线接受一组3D坐标,然后把它们转变为你屏幕上的有色2D像素输出。图形渲染管线可以被划分为几个阶段,每个阶段将会把前一个阶段的输出作为输入。所有这些阶段都是高度专门化的(它们都有一个特定的函数),并且很容易并行执行。正是由于它们具有并行执行的特性,当今大多数显卡都有成千上万的小处理核心,它们在GPU上为每一个(渲染管线)阶段运行各自的小程序,从而在图形渲染管线中快速处理你的数据。这些小程序叫做着色器(Shader)。
.
有些着色器可以由开发者配置,因为允许用自己写的着色器来代替默认的,所以能够更细致地控制图形渲染管线中的特定部分了。因为它们运行在GPU上,所以节省了宝贵的CPU时间。OpenGL着色器是用OpenGL着色器语言(OpenGL Shading > Language, GLSL)写成的,在下一节中我们再花更多时间研究它。
.
下面,你会看到一个图形渲染管线的每个阶段的抽象展示。要注意蓝色部分代表的是我们可以注入自定义的着色器的部分。

要注意蓝色部分代表的是我们可以注入自定义的着色器的部分。
在这里插入图片描述
如上图即是绘制渲染一个图片的流程。按照官网的教程说的话,,,,,,,有点过于抽象繁琐,简单来说就是如下几个过程。

1、你想渲染一个苹果,首先你得知道这个苹果在坐标系中的位置坐标吧。
在这里插入图片描述
那么顶点着色器它把一个单独的顶点作为输入。顶点着色器主要的目的是把3D坐标转为另一种3D坐标(后面会解释),同时顶点着色器允许我们对顶点属性进行一些基本处理。

再粗暴点理解就一句话顶点着色器 : 坐标转换用的

需要注意

2、图元装配阶段将就是将顶点着色器输出的所有顶点作为输入(如果是GL_POINTS,那么就是一个顶点),并所有的点装配成指定图元的形状

简单点来说将顶点着色器输出的点,绘制出对应的形状

3、几何着色器这玩意是干啥的捏???上个图
在这里插入图片描述
几何着色器其实就是决定线怎么连,最终绘制成什么样子的图形!这样说还无法理解,那对着上图悟吧!!!!!!1

4、光栅化阶段,这里它会把图元映射为最终屏幕上相应的像素,生成供片段着色器(Fragment Shader)使用的片段(Fragment)。在片段着色器运行之前会执行裁切(Clipping)。裁切会丢弃超出你的视图以外的所有像素,用来提升执行效率。

简单点理解就是,将几何着色器生成的形状,这块形状包含的像素块圈起来。裁切会丢弃超出你的视图以外的所有像素,用来提升执行效率。

5、片段着色器的主要目的是计算一个像素的最终颜色,这也是所有OpenGL高级效果产生的地方。通常,片段着色器包含3D场景的数据(比如光照、阴影、光的颜色等等),这些数据可以被用来计算最终像素的颜色。

这部分作用一句话概括就是:确认像素的颜色。

6、Alpha测试和混合(Blending)阶段 这最后一步是干啥的呢?????就是。。。。。。上色!

接下来我们在窗体中渲染一个矩形
首先GLFW、GLAD的初始化是不可少的,除去循环渲染的部分,其他部分和上一小节完全是一样的,我们直接copy即可。

#include <glad.h>
#include <glfw3.h>

#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;


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);

    // glad: load all OpenGL function pointers
    // ---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
	...


			//todo


	...
    glfwTerminate();
    return 0;
}

void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

// 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)
{
    glViewport(0, 0, width, height);
}

接下来我们要开始渲染一个矩形了

首先我们现创建顶点着色器。

    // 创建顶点着色器 
    //glCreateShader 创建着色器 参数是着色器类型:GL_VERTEX_SHADER是顶点着色器
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);

注意一下上文有这样一句话

有些着色器可以由开发者配置,因为允许用自己写的着色器来代替默认的,所以能够更细致地控制图形渲染管线中的特定部分了。因为它们运行在GPU上,所以节省了宝贵的CPU时间。OpenGL着色器是用OpenGL着色器语言(OpenGL Shading Language, GLSL)写成的

我们创建了顶点着色器,接下来我们就要编写着色器的程序。

const char *vertexShaderSource = "#version 330 core\n"
    "layout (location = 0) in vec3 aPos;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "}\0";

    // 创建顶点着色器
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    //替换着色器中的代码:顶点
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    //编译已存储在由 指定的着色器对象中的源代码字符串
    glCompileShader(vertexShader);

后续明日更完!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/126419.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习poi导出excel之XSSFWorkbook

1 基本介绍 POI提供了HSSF、XSSF以及SXSSF三种方式操作Excel。 HSSF&#xff1a;Excel97-2003版本&#xff0c;扩展名为.xls。一个sheet最大行数65536&#xff0c;最大列数256。 XSSF&#xff1a;Excel2007版本开始&#xff0c;扩展名为.xlsx。一个sheet最大行数1048576&…

电脑桌面主题(28)和动态视频壁纸(31)合集(收藏)

最近就是突然被身边朋友的电脑壁纸给吸引到了&#xff0c;在这之前的我一直遵循着 “大道至简” 的原则&#xff0c;一张Windows原生态静态壁纸走天下&#xff0c;但是作为一个00后我还是 “破戒” 了&#xff0c;其实我认为特别像程序员之类的有一张自己满意的桌面壁纸是非常重…

Mybatis-Plus分页与条件查询

目录 标准分页功能制作 条件查询 条件查询-null值处理 标准分页功能制作 1&#xff1a;设置分页拦截器作为Spring管理的bean Configuration public class MpConfig {Beanpublic MybatisPlusInterceptor mpInterceptor(){//1.定义MP拦截器MybatisPlusInterceptor mpIntercept…

Python中使用的流行数据科学库

Python中使用的流行数据科学库 数据科学是用于采购、组织、打包和以可理解的格式呈现数据的程序和方法。在不同的领域可能有不同种类的数据&#xff0c;这些数据可能是结构化的&#xff0c;也可能是非结构化的。 为什么Python在人们开始他们的编码之旅时如此受欢迎&#xff1…

删除数组中符合指定条件的元素

不符合指定条件&#xff0c;可能是指定数组array中的某一项不符合某一值的要求&#xff1b;或者是拿另一个数组arr对比&#xff0c;要求array只留下复合arr中的值或者删除掉复合arr中的值。 1.不符合某一值的要求 <!DOCTYPE html> <html lang"en"> <…

一篇文章轻松掌握java图实现

图的基本概念&#xff1a;这里就不予介绍了&#xff0c;这里主要是讲图的代码实现 荔枝目录&#xff1a;1.图的存储结构1.1邻接矩阵1.2邻接表2.图的遍历2.1广度优先2.2深度优先3.最小生成树3.1Kruskal算法&#xff08;全局&#xff09;3.2Prim算法&#xff08;局部&#xff09;…

[UE][UE5]在UE中画一个线框球,网格连接画球,高阶画球并操控

[UE][UE5]在UE中画一个线框球&#xff0c;网格连接画球&#xff0c;高阶画球并操控1.材质法2.绘制调试球体3.网格连接4.高阶画球并操控1.材质法 缺点&#xff1a;是实体的&#xff0c;只能欺骗视觉&#xff0c;实际还是一个实体体积球&#xff0c;往里放东西显示不出来放进去的…

Python中ArcPy基于矢量要素批量将栅格影像切割为多个小部分

本文介绍基于Python中ArcPy模块&#xff0c;基于具有多个面要素的要素类&#xff0c;批量分割大量栅格图像的方法。 首先明确一下我们的需求。现在需要基于一个面要素类&#xff0c;对一个栅格遥感影像加以分割&#xff1b;如下图所示。这个面要素类中有3个部分&#xff0c;我们…

MMdetection框架速成系列 第02部分:整体算法流程+模型搭建流程+detection训练与测试核心组件+训练部分与测试部分的核心算法

MMdetection框架速成系列 第02部分1 MMDetection是什么1.1 模型分类2. 整体算法流程3 detection训练核心组件3.1 Backbone3.2 Neck3.3 Head3.4 Enhance3.5 BBox Assigner3.9 BBox Sampler3.10 BBox Encoder3.11 Loss3.12 Training tricks4 detection测试核心组件4.1 BBox Decod…

python源码打包exe、exe反编译

一、python3打包为exe文件 这里有个hello.py文件 step1&#xff1a;安装pyinstaller包 pip install pyinstaller step2&#xff1a;在cmd中进入hello.py文件所在路径。可以直接在hello.py文件路径下直接进入cmd step3&#xff1a;打包生成exe文件&#xff0c;使用如下命令&…

Linux网络协议之IP协议(网络层)

Linux网络协议之IP协议(网络层) 文章目录Linux网络协议之IP协议(网络层)1.IP协议基本概念2.IPV4协议格式3.分片与组装4.IP网段划分4.1 IP地址组成4.2 IP地址分类4.3 特殊的IP地址4.4 IP地址的数量限制4.5 私网IP地址与公网IP地址5.对路由的了解1.IP协议基本概念 IP协议全称为“…

第四章 vi和vim 编辑器-[实操篇]

一&#xff1a;vi 和 vim 的基本介绍 所有的 Linux 系统都会内建vi文本编辑器。 Vim 具有程序编辑的能力&#xff0c;可以看做是 Vi的增强版本&#xff0c;可以主动的以字体颜色辨别语法的正确性&#xff0c;方便程序设计。代码补完&#xff0c;编译及错误跳转等方便编程的功…

Linux安装【入门学习适用】

Linux安装安装1、安装VMware激活码&#xff1a;ZF3R0-FHED2-M80TY-8QYGC-NPKYF2、安装CentOS3、FinalShell安装4、FinalShell的使用安装 1、安装VMware VMware-workstation-full-16.2.4无脑下一步即可 激活码&#xff1a;ZF3R0-FHED2-M80TY-8QYGC-NPKYF 2、安装CentOS 1、…

TensorFlow笔记之多元线性回归

文章目录前言一、数据处理二、TensorFlow1.x1.定义模型2.训练模型3.结果可视化4.模型预测5.TensorBoard可视化三、TensorFlow2.x1.定义模型2.训练模型3.结果可视化4.模型预测总结前言 记录使用TensorFlow1.x和TensorFlow2.x完成多元线性回归的过程。 一、数据处理 在此使用波…

dll修复工具哪个比较好?好的修复工具怎么选择

最近有小伙伴咨询小编&#xff0c;问dll修复工具的选择&#xff0c;因为他的电脑经常出现dll缺失&#xff0c;一缺失就打开不了各种软件程序&#xff0c;非常的让他烦恼&#xff0c;所以今天小编就来给大家详细的说说dll修复工具哪个比较好&#xff1f;要怎么去选择。 一.什么…

36 氪发布《研发项目管理软件应用指南》,ONES 入选典型厂商案例

近日&#xff0c;36氪企服点评发布了《研发项目管理软件应用指南》&#xff08;下称「指南」&#xff09;。36氪企服点评致力于帮助每个需求企业服务的人做出正确的决策&#xff0c;携手每个企服行业者为大众提供更高的价值与服务。在该指南中&#xff0c;36氪企服点评综合了海…

大数据系列——ClickHouse表引擎与分布式查询

目录 一、ClickHouse的表引擎 1、MergeTree的创建方式与存储结构 2、ReplacingMergeTree 二、数据分片与分布式查询 三、Clickhouse-ETL常见业务使用 一、ClickHouse的表引擎 表引擎体系&#xff0c;包括合并树、外部存储、内存、文件、接口和其他6大类20多种表引擎。而在…

全流量回溯分析为您解决应用性能问题(一)

前言 信息中心老师反应&#xff0c;用户反馈办公系统有访问慢的情况&#xff0c;需要通过流量分析系统来了解系统的运行情况&#xff0c;此报告专门针对系统的性能数据做了分析。 信息中心已部署NetInside流量分析系统&#xff0c;使用流量分析系统提供实时和历史原始流量&am…

【网络安全篇】浅谈web应用程序的安全风险

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;浅谈web应用程序的安全风险 ✅创作者&#xff1a;贤鱼 ⏰预计时间&#xff1a;25分钟 &#x1f389;个人主页&#xff1a;贤鱼的个人主页 &#x1f525;专栏系列&#xff1a;网络安全 &#x1f341;贤鱼的个人社区&#xf…

使用FastJson进行驼峰下划线相互转换写法及误区

PropertyNamingStrategy 有四种序列化方式。 CamelCase策略&#xff0c;Java对象属性&#xff1a;personId&#xff0c;序列化后属性&#xff1a;persionId – 实际只改了首字母 大写变小写 PascalCase策略&#xff0c;Java对象属性&#xff1a;personId&#xff0c;序列化后属…