跟着LearnOpenGL学习3--四边形绘制

这篇具有很好参考价值的文章主要介绍了跟着LearnOpenGL学习3--四边形绘制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、前言

通过跟着LearnOpenGL学习2–三角形绘制一文,我们已经知道了怎么配置渲染管线,来绘制三角形;

OpenGL主要处理三角形,当我们需要绘制别的图形时,例如:四边形,应当用三角形去拼接,组成我们想要的四边形;


二、元素缓冲对象

元素缓冲对象(Element Buffer Object,EBO),也叫索引缓冲对象(Index Buffer Object,IBO)

假设我们不再绘制一个三角形,而是绘制一个矩形。我们可以绘制两个三角形来组成一个矩形(OpenGL主要处理三角形)。

顶点数据如下:

float vertices[] = {
    // 第一个三角形
    0.5f, 0.5f, 0.0f,   // 右上角
    0.5f, -0.5f, 0.0f,  // 右下角
    -0.5f, 0.5f, 0.0f,  // 左上角
    // 第二个三角形
    0.5f, -0.5f, 0.0f,  // 右下角
    -0.5f, -0.5f, 0.0f, // 左下角
    -0.5f, 0.5f, 0.0f   // 左上角
};
  • 一个矩形只有4个而不是6个顶点,可以看到,我们指定了右下角和左上角两次;
  • 这样就产生50%的额外开销,当我们有包括上千个三角形的模型之后,这个问题会更糟糕,这会产生一大堆浪费;

更好的解决方案是只储存不同的顶点,并设定绘制这些顶点的顺序;这样子我们只要储存4个顶点就能绘制矩形了,之后只要指定绘制的顺序就行了;

元素缓冲区对象的工作方式正是如此,EBO是一个缓冲区,就像一个顶点缓冲区对象一样,它存储 OpenGL 用来决定要绘制哪些顶点的索引,这种所谓的索引绘制(Indexed Drawing)正是我们问题的解决方案;

定义(不重复的)顶点,和绘制出矩形所需的索引:

float vertices[] = {
    0.5f, 0.5f, 0.0f,   // 右上角
    0.5f, -0.5f, 0.0f,  // 右下角
    -0.5f, -0.5f, 0.0f, // 左下角
    -0.5f, 0.5f, 0.0f   // 左上角
};

unsigned int indices[] = {
    // 注意索引从0开始! 
    // 此例的索引(0,1,2,3)就是顶点数组vertices的下标,
    // 这样可以由下标代表顶点组合成矩形

    0, 1, 3, // 第一个三角形
    1, 2, 3  // 第二个三角形
};

创建元素缓冲对象

unsigned int EBO;
glGenBuffers(1, &EBO);

绑定EBO到GL_ELEMENT_ARRAY_BUFFER缓冲区

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

把索引复制到GL_ELEMENT_ARRAY_BUFFER缓冲区

glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

绘制三角形

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

注意:用glDrawElements函数来绘制,而不是glDrawArrays函数;

  • 第一个参数指定了我们绘制的模式,GL_TRIANGLES表示我们要绘制三角形;
  • 第二个参数是我们打算绘制顶点的个数,这里填6,也就是说我们一共需要绘制6个顶点;
  • 第三个参数是索引的类型,这里是GL_UNSIGNED_INT
  • 最后一个参数里我们可以指定EBO中的偏移量(或者传递一个索引数组,但是这是当你不在使用索引缓冲对象的时候),但是我们会在这里填写0;

glDrawElements函数从当前绑定到GL_ELEMENT_ARRAY_BUFFER目标的EBO中获取其索引。这意味着我们每次想要使用索引渲染对象时都必须绑定相应的EBO,这又有点麻烦。碰巧顶点数组对象也跟元素缓冲区对象绑定。在绑定VAO时,绑定的最后一个元素缓冲区对象存储为VAO的元素缓冲区对象。然后,绑定到VAO也会自动绑定该EBO。

最后的初始化和绘制代码现在看起来像这样:

// ..:: 初始化代码 :: ..
// 1. 绑定顶点数组对象
glBindVertexArray(VAO);
// 2. 把我们的顶点数组复制到一个顶点缓冲中,供OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 3. 复制我们的索引数组到一个索引缓冲中,供OpenGL使用
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 4. 设定顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

[...]

// ..:: 绘制代码(渲染循环中) :: ..
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);

三、完整代码

跟着LearnOpenGL学习3--四边形绘制

#include "mainwindow.h"
#include <QApplication>

//在包含GLFW的头文件之前包含了GLAD的头文件;
//GLAD的头文件包含了正确的OpenGL头文件(例如GL/gl.h);
//所以需要在其它依赖于OpenGL的头文件之前包含GLAD;
#include <glad/glad.h>
#include <GLFW/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;

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";
const char *fragmentShaderSource = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\n\0";

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    //MainWindow w;
    //w.show();


    //初始化GLFW
    //--------------------
    glfwInit();

    //配置GLFW
    //--------------------
    //告诉GLFW使用的OpenGL本是3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    //告诉GLFW使用的是核心模式(Core-profile)
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    //创建一个新的OpenGL环境和窗口
    //-----------------------------------
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();    //glfw销毁窗口喝OpenGL环境,并释放资源
        return -1;
    }

    //设置参数window中的窗口所关联的OpenGL环境为当前环境
    //-----------------------------------
    glfwMakeContextCurrent(window);

    //设置窗口尺寸改变大小时的回调函数(窗口尺寸发送改变时会自动调用)
    //-----------------------------------
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    //glad加载系统相关的OpenGL函数指针
    //---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    //顶点着色器
    //---------------------------------------------------------------------
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    //检验着色器编译是否成功
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    //片段着色器
    //---------------------------------------------------------------------
    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    //检验着色器编译是否成功
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    //链接着色器到着色器程序
    //---------------------------------------------------------------------
    unsigned int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    //检查链接是否成功
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }
    //链接成功后删除着色器对象
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    //顶点数据
    //---------------------------------------------------------------------
    float vertices[] = {
         0.5f,  0.5f, 0.0f,  // top right
         0.5f, -0.5f, 0.0f,  // bottom right
        -0.5f, -0.5f, 0.0f,  // bottom left
        -0.5f,  0.5f, 0.0f   // top left
    };
    unsigned int indices[] = {  //绘制索引
        0, 1, 3,  //第1个三角形
        1, 2, 3   //第2个三角形
    };

    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);     //创建顶点数组对象
    glGenBuffers(1, &VBO);          //创建顶点缓冲对象
    glGenBuffers(1, &EBO);          //创建元素缓冲对象

    glBindVertexArray(VAO);         //绑定VAO

    glBindBuffer(GL_ARRAY_BUFFER, VBO);     //将VBO与GL_ARRAY_BUFFER缓冲区绑定
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);  //将顶点数据复制到GL_ARRAY_BUFFER缓冲区,之后可通过VBO进行操作

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);     //将EBO与GL_ELEMENT_ARRAY_BUFFER缓冲区绑定
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);    //将索引复制到GL_ELEMENT_ARRAY_BUFFER缓冲区,之后可通过EBO进行操作

    //设定顶点属性指针
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    //调用glVertexAttribPointer将VBO注册为顶点属性的绑定顶点缓冲对象,因此之后我们可以安全地解除绑定
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    //解除对VAO的绑定
    glBindVertexArray(0);


    //渲染循环
    //我们可不希望只绘制一个图像之后我们的应用程序就立即退出并关闭窗口;
    //我们希望程序在我们主动关闭它之前不断绘制图像并能够接受用户输入;
    //因此,我们需要在程序中添加一个while循环,它能在我们让GLFW退出前一直保持运行;
    //------------------------------------------------------------------------------
    while (!glfwWindowShouldClose(window))  //如果用户准备关闭参数window所指定的窗口,那么此接口将会返回GL_TRUE,否则将会返回GL_FALSE
    {
        //用户输入
        //------------------------------------------------------------------------------
        processInput(window);   //检测是否有输入

        //渲染指令
        //------------------------------------------------------------------------------
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        //绘制三角形
        glUseProgram(shaderProgram);        //激活着色器程序对象
        glBindVertexArray(VAO);             //绑定VAO
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);    //绘制三角形
        // glBindVertexArray(0);            //解绑VAO

        //告诉GLFW检查所有等待处理的事件和消息,包括操作系统和窗口系统中应当处理的消息。如果有消息正在等待,它会先处理这些消息再返回;否则该函数会立即返回
        //---------------------------------------------------------------------------------------------------------------------------------
        glfwPollEvents();

        //请求窗口系统将参数window关联的后缓存画面呈现给用户(双缓冲绘图)
        //------------------------------------------------------------------------------
        glfwSwapBuffers(window);
    }

    //释放资源
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shaderProgram);

    //glfw销毁窗口喝OpenGL环境,并释放资源(之后必须再次调用glfwInit()才能使用大多数GLFW函数)
    //------------------------------------------------------------------
    glfwTerminate();


    return a.exec();
}

//检测是否有输入
//---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)   //ESC键,退出
        glfwSetWindowShouldClose(window, true);
}

//给glfw窗口注册的尺寸改变回调函数
//---------------------------------------------------------------------------------------------
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);
}


四、绘制模式

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);		//线框模式
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);		//填充模式(默认模式)

为了清除得看到我们绘制的四边形是由两个三角形拼接而成的,我们可以采用线框模式进行绘制,就一目了然了;

跟着LearnOpenGL学习3--四边形绘制文章来源地址https://www.toymoban.com/news/detail-448601.html

#include "mainwindow.h"
#include <QApplication>

//在包含GLFW的头文件之前包含了GLAD的头文件;
//GLAD的头文件包含了正确的OpenGL头文件(例如GL/gl.h);
//所以需要在其它依赖于OpenGL的头文件之前包含GLAD;
#include <glad/glad.h>
#include <GLFW/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;

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";
const char *fragmentShaderSource = "#version 330 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\n\0";

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    //MainWindow w;
    //w.show();


    //初始化GLFW
    //--------------------
    glfwInit();

    //配置GLFW
    //--------------------
    //告诉GLFW使用的OpenGL本是3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    //告诉GLFW使用的是核心模式(Core-profile)
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    //创建一个新的OpenGL环境和窗口
    //-----------------------------------
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();    //glfw销毁窗口喝OpenGL环境,并释放资源
        return -1;
    }

    //设置参数window中的窗口所关联的OpenGL环境为当前环境
    //-----------------------------------
    glfwMakeContextCurrent(window);

    //设置窗口尺寸改变大小时的回调函数(窗口尺寸发送改变时会自动调用)
    //-----------------------------------
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    //glad加载系统相关的OpenGL函数指针
    //---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    //顶点着色器
    //---------------------------------------------------------------------
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    //检验着色器编译是否成功
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    //片段着色器
    //---------------------------------------------------------------------
    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    //检验着色器编译是否成功
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    //链接着色器到着色器程序
    //---------------------------------------------------------------------
    unsigned int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    //检查链接是否成功
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }
    //链接成功后删除着色器对象
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    //顶点数据
    //---------------------------------------------------------------------
    float vertices[] = {
         0.5f,  0.5f, 0.0f,  // top right
         0.5f, -0.5f, 0.0f,  // bottom right
        -0.5f, -0.5f, 0.0f,  // bottom left
        -0.5f,  0.5f, 0.0f   // top left
    };
    unsigned int indices[] = {  //绘制索引
        0, 1, 3,  //第1个三角形
        1, 2, 3   //第2个三角形
    };

    unsigned int VBO, VAO, EBO;
    glGenVertexArrays(1, &VAO);     //创建顶点数组对象
    glGenBuffers(1, &VBO);          //创建顶点缓冲对象
    glGenBuffers(1, &EBO);          //创建元素缓冲对象

    glBindVertexArray(VAO);         //绑定VAO

    glBindBuffer(GL_ARRAY_BUFFER, VBO);     //将VBO与GL_ARRAY_BUFFER缓冲区绑定
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);  //将顶点数据复制到GL_ARRAY_BUFFER缓冲区,之后可通过VBO进行操作

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);     //将EBO与GL_ELEMENT_ARRAY_BUFFER缓冲区绑定
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);    //将索引复制到GL_ELEMENT_ARRAY_BUFFER缓冲区,之后可通过EBO进行操作

    //设定顶点属性指针
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    //调用glVertexAttribPointer将VBO注册为顶点属性的绑定顶点缓冲对象,因此之后我们可以安全地解除绑定
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    //解除对VAO的绑定
    glBindVertexArray(0);

    //启用线框模式
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    //渲染循环
    //我们可不希望只绘制一个图像之后我们的应用程序就立即退出并关闭窗口;
    //我们希望程序在我们主动关闭它之前不断绘制图像并能够接受用户输入;
    //因此,我们需要在程序中添加一个while循环,它能在我们让GLFW退出前一直保持运行;
    //------------------------------------------------------------------------------
    while (!glfwWindowShouldClose(window))  //如果用户准备关闭参数window所指定的窗口,那么此接口将会返回GL_TRUE,否则将会返回GL_FALSE
    {
        //用户输入
        //------------------------------------------------------------------------------
        processInput(window);   //检测是否有输入

        //渲染指令
        //------------------------------------------------------------------------------
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        //绘制三角形
        glUseProgram(shaderProgram);        //激活着色器程序对象
        glBindVertexArray(VAO);             //绑定VAO
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);    //绘制三角形
        // glBindVertexArray(0);            //解绑VAO

        //告诉GLFW检查所有等待处理的事件和消息,包括操作系统和窗口系统中应当处理的消息。如果有消息正在等待,它会先处理这些消息再返回;否则该函数会立即返回
        //---------------------------------------------------------------------------------------------------------------------------------
        glfwPollEvents();

        //请求窗口系统将参数window关联的后缓存画面呈现给用户(双缓冲绘图)
        //------------------------------------------------------------------------------
        glfwSwapBuffers(window);
    }

    //释放资源
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shaderProgram);

    //glfw销毁窗口喝OpenGL环境,并释放资源(之后必须再次调用glfwInit()才能使用大多数GLFW函数)
    //------------------------------------------------------------------
    glfwTerminate();


    return a.exec();
}

//检测是否有输入
//---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)   //ESC键,退出
        glfwSetWindowShouldClose(window, true);
}

//给glfw窗口注册的尺寸改变回调函数
//---------------------------------------------------------------------------------------------
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);
}

到了这里,关于跟着LearnOpenGL学习3--四边形绘制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VC++中使用OpenCV对原图像中的四边形区域做透视变换

    最近闲着跟着油管博主murtazahassan,学习了一下LEARN OPENCV C++ in 4 HOURS | Including 3x Projects | Computer Vision,对应的Github源代码地址为:Learn-OpenCV-cpp-in-4-Hours 视频里面讲到到原图中的扑克牌四个顶点标记画圆,并且将扑克牌K做透视变换后摆正重新显示,资源图像文件 cards.png 下载地

    2024年01月17日
    浏览(38)
  • 石子合并一章通(环形石子合并,四边形不等式,GarsiaWachs算法)(内附封面)

    在一个圆形操场的四周摆放 N N N 堆石子,现要将石子有次序地合并成一堆,规定每次只能选相邻的 2 2 2 堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 试设计出一个算法,计算出将 N N N 堆石子合并成 1 1 1 堆的最小得分和最大得分。 数据的第 1 1 1 行是正

    2024年02月14日
    浏览(38)
  • 跟着LearnOpenGL学习5--纹理

    通过前面着色器博文的学习,我们已经了解到,我们可以为每个顶点添加颜色来增加图形的细节,从而创建出有趣的图像。但是,如果想让图形看起来更真实,我们就必须有足够多的顶点,从而指定足够多的颜色。这将会产生很多额外开销,因为每个模型都会需求更多的顶点

    2024年02月07日
    浏览(35)
  • cesium学习记录08-鼠标绘制多边形

    上一篇学习了创建实体的一些基础知识,但有时还需要我们使用鼠标进行手动绘制,这一篇就来进行鼠标绘制实体的实现(点,线,矩形,圆,多边形)。 (这里需要掌握三个知识点,一是上一篇中的创建实体、二是鼠标事件、三是回调函数) 既然是鼠标绘制,自然离不开

    2024年02月12日
    浏览(48)
  • LearnOpenGL - Android OpenGL ES 3.0 绘制三角形

    LearnOpenGL 笔记 - 入门 01 OpenGL LearnOpenGL 笔记 - 入门 02 创建窗口 LearnOpenGL 笔记 - 入门 03 你好,窗口 LearnOpenGL 笔记 - 入门 04 你好,三角形 OpenGL - 如何理解 VAO 与 VBO 之间的关系 经过一段时间 OpenGL 的学习,我们已经掌握了如何使用 glwf 在桌面端绘制简单图形。现在让我们把目光

    2024年02月12日
    浏览(40)
  • css 绘制直角梯形 和 平行四边形

            

    2024年02月16日
    浏览(37)
  • cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形)

    上一篇学习了创建实体的一些基础知识,但有时还需要我们使用鼠标进行手动绘制,这一篇就来进行鼠标绘制实体的实现(点,线,矩形,圆,多边形)。 (这里需要掌握三个知识点,一是上一篇中的创建实体、二是鼠标事件、三是回调函数) 既然是鼠标绘制,自然离不开

    2024年02月12日
    浏览(63)
  • OpenCV-Python学习(13)—— OpenCV 多边形填充与绘制(cv.fillPoly、cv.polylines)

    1. 知识点 学习 cv.polylines 函数的使用; 学习 cv.fillPoly 函数的使用。 2. 绘制折线或多边形 cv.polylines 函数说明 2.1 函数使用 2.2 参数说明 参数 说明 img 表示要在其上绘制矩形的图像的img对象。 pts 表示一个或多个点集。 isClosed 表示标志,决定所绘制的多边形是否闭合。若为 T

    2024年02月16日
    浏览(58)
  • 基于C++ 的OpenCV绘制多边形,多边形多条边用不用的颜色绘制

    使用基于C++的OpenCV库来绘制多边形,并且为多边形的不同边使用不同的颜色,可以按照以下步骤进行操作: 首先,确保你已经安装了OpenCV库并配置好了你的开发环境。 导入必要的头文件: 创建一个空白的图像,然后绘制多边形,并为每条边选择不同的颜色: 在这个示例中,

    2024年02月13日
    浏览(58)
  • Unity绘制六边形体

    现在steam上面有很多下棋类/经营类的游戏都是用六边形的地形,比较美观而且实用,去年在版本末期我也自己尝试做了一个绘制六边体的demo,一年没接触unity竟然都要忘光了,赶紧在这边记录一下。 想cv代码可以直接拉到代码章节 能够动态生成一系列可以“挖空中心”的六边

    2024年03月15日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包