• OpenGL绘制(二)


    上节学会了绘制三角形,我们开始绘制正方形


    1 顶点坐标,纹理坐标(图片来源于其他博友)

    (1)顶点坐标系

     

    (2)纹理坐标系

     

    2.索引缓冲对象(Element Buffer Object,EBO)

    索引缓冲对象EBO相当于OpenGL中的顶点索引数组,是为了解决同一个顶点多次重复调用的问题,可以减少内存空间浪费,提高执行效率。当需要使用重复的顶点时,通过顶点的位置索引来调用顶点,而不是对重复的顶点信息重复记录,重复调用。

    3 画一个正方形= 画两个三角形拼在一起。顶点着色程序和片元着色程序无需改动

     定义应用程序的入口点。
    //
    
    #include "stdafx.h"
    
    #include <glad/glad.h>
    #include <GLFW/glfw3.h>
    #include<string>
    #include<fstream>
    #include<sstream>
    #include<iostream>
    
    #include <stdio.h>
    
    // settings
    const unsigned int SCR_WIDTH = 800;
    const unsigned int SCR_HEIGHT = 600;
    unsigned int VBO = 0;
    unsigned int VAO = 0;
    unsigned int EBO = 0;
    int shaderProgram = 0;
    
    void render()
    {
        glBindVertexArray(VAO);
        glUseProgram(shaderProgram);
        glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
        glUseProgram(0);
        glBindVertexArray(0);
    }
    
    void initmodule()
    {
        //做个一模型;正方形四个顶点;顶点坐标系
        float vertexs[] = {
    
            0.0f,0.0f,0.0f,
            0.0f,0.5f,0.0f,
            0.5f,0.5f,0.0f,
            0.5f,0.0f,0.0f,
            
            
        };
        //一个正方形是由两个三角形得来的;记录顶点的索引顺序;0 1 2 3分别是四个顶点的排序,就可以画出两个三角形
        unsigned int indexs[] = {
            0,1,3,
            1,2,3,
        };
        
        //做VAO
        glGenVertexArrays(1,&VAO);
        glBindVertexArray(VAO);
    
        //做VBO
    
        glGenBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        //创建显存空间
        glBufferData(GL_ARRAY_BUFFER,sizeof(vertexs), vertexs, GL_STATIC_DRAW);
        
        //设置索引缓冲
        glGenBuffers(1,&EBO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indexs),indexs,GL_STATIC_DRAW);
        
        
        //设置第0个锚点,3个点,不需要归一化,跨度3个float可以读下一个点
        glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
        //打开顶点
        glEnableVertexAttribArray(0);
        //解除绑定VBO
        glBindBuffer(GL_ARRAY_BUFFER,0);
        //解除绑定VEO???
        //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);会崩溃,目前不知道原因,后序补充
    
        //解绑VAO
        glBindVertexArray(0);
    
    }
    
    void initshader(const char* verpath,const char* fragpath)
    {
        //编译shader,并记录shaderID
        std::string VerCode("");
        std::string fregCode("");
        //读文件
        std::ifstream  vShaderFile;
        std::ifstream  fShaderFile;
    
        vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        
        try
        {
            vShaderFile.open(verpath);
            fShaderFile.open(fragpath);
    
            std::stringstream vsstream, fsstream;
            vsstream << vShaderFile.rdbuf();
            fsstream << fShaderFile.rdbuf();
            VerCode = vsstream.str();
            fregCode = fsstream.str();
            
        }
        catch (const std::exception&)
        {
            std::cout << "read file error" << std::endl;
        }
    
        const char* vshader = VerCode.c_str();
        const char* fshader = fregCode.c_str();
    
        //shader 编译连接
        unsigned int vertexID = 0, fragID = 0;
        char infoLog[512];//存储错误信息
        int  successflag = 0;
        vertexID = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertexID,1,&vshader,NULL );
        glCompileShader(vertexID);
        //获取编译是否成功
        glGetShaderiv(vertexID,GL_COMPILE_STATUS,&successflag);
        if (!successflag)
        {
            glGetShaderInfoLog(vertexID,512,NULL,infoLog);
            std::string errstr(infoLog);
            std::cout << "v shader err"<<infoLog;
        }
        //frag
        fragID = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragID, 1, &fshader, NULL);
        glCompileShader(fragID);
        //获取编译是否成功
        glGetShaderiv(fragID, GL_COMPILE_STATUS, &successflag);
        if (!successflag)
        {
            glGetShaderInfoLog(fragID, 512, NULL, infoLog);
            std::string errstr(infoLog);
            std::cout << "f shader err"<<infoLog;
        }
        //链接
        shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram,vertexID);
        glAttachShader(shaderProgram,fragID);
        glLinkProgram(shaderProgram);
        glGetProgramiv(shaderProgram,GL_LINK_STATUS,&successflag);
        if (!successflag)
        {
            glGetShaderInfoLog(shaderProgram, 512, NULL, infoLog);
            std::string errstr(infoLog);
            std::cout << "link error";
        }
    
        //编译完成后,可以把中间的步骤程序删除
        glDeleteShader(vertexID);
        glDeleteShader(fragID);
    }
    void processInput(GLFWwindow *window)
    {
        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        {
            //将窗口设置为关闭,跳出循环
            glfwSetWindowShouldClose(window, true);
        }
    }
    
    void framebuffer_size_callback(GLFWwindow* window, int width, int height)
    {
        glViewport(0, 0, width, height);
    }
    
    int main()
    {
        //glfw初始化
        glfwInit();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
        //glfw创建窗口
        GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
        if (window == NULL)
        {
            printf("创建窗口失败");
            //终止
            glfwTerminate();
            return -1;
        }
        //显示窗口
        glfwMakeContextCurrent(window);
    
        //设置回调,当窗口大小调整后将调用该回调函数
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    
        // glad初始化
        if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
        {
            printf("加载失败");
            return -1;
        }
        initmodule();
        initshader("vertexShader.glsl","fragmentShader.glsl");
    
        // 使用循环达到循环渲染效果
        while (!glfwWindowShouldClose(window))
        {
            //自定义输入事件
            processInput(window);
    
            glClearColor(0.5f,0.5f,0.3f,1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
            render();
            //交互缓冲区,否则显示空白
            glfwSwapBuffers(window);
            //输入输出事件,否则无法对窗口进行交互
            glfwPollEvents();
        }
    
        //终止渲染 关闭并清理glfw本地资源
        glfwTerminate();
        return 0;
    }
    #version 330 core
    layout(location = 0) in vec3 aPos;
    void main()
    {
       gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0);
    };
    
    #version 330 core
    out vec4 FragColor;
    void main()
    {
        FragColor = vec4(0.5f,0.9f,0.5f,1.0f);
    };

  • 相关阅读:
    鼠标移开事件(onmouseout)
    IOS iPhone 屏幕尺寸 判断设备屏幕尺寸、分辨率
    iOS 程序图标Logo设置
    关闭iOS虚拟键盘的几种方法
    Xcode5.1离线下载安装及使用iOS5模拟器进行开发调试的方法
    按钮创建
    Mac 截图 快捷键
    UserDefaultes 数据存储使用
    NSUserDefaults 使用方法
    IOS中NSUserDefaults的用法(轻量级本地数据存储)
  • 原文地址:https://www.cnblogs.com/8335IT/p/16183898.html
Copyright © 2020-2023  润新知