首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

在OpenGl中旋转正方形

在OpenGL中,要旋转一个正方形可以使用以下步骤:

  1. 创建一个窗口和渲染上下文。
  2. 设置视口和投影矩阵,以确保正方形在窗口中正确显示。
  3. 定义正方形的顶点坐标和颜色。
  4. 创建一个顶点缓冲对象(VBO)来存储正方形的顶点数据。
  5. 创建一个顶点数组对象(VAO)来管理顶点属性状态。
  6. 编写一个顶点着色器和片段着色器来处理正方形的渲染。
  7. 编译和链接着色器程序。
  8. 在渲染循环中,绑定VAO和VBO,并使用着色器程序进行渲染。
  9. 在每一帧中,通过修改模型矩阵来实现正方形的旋转。

以下是一个示例的代码片段:

顶点着色器代码:

代码语言:txt
复制
#version 330 core
layout (location = 0) in vec3 aPosition;
uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProjection;

void main()
{
    gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);
}

片段着色器代码:

代码语言:txt
复制
#version 330 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 使用红色作为正方形的颜色
}

C++代码:

代码语言:txt
复制
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>

// 正方形的顶点坐标
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, 1, 2,
    2, 3, 0
};

// 初始化OpenGL窗口和上下文
void initGLFW()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
}

// 创建窗口和上下文
GLFWwindow* createWindow(int width, int height, const char* title)
{
    GLFWwindow* window = glfwCreateWindow(width, height, title, NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        exit(-1);
    }
    glfwMakeContextCurrent(window);
    return window;
}

// 初始化OpenGL函数指针
void initGLAD()
{
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        exit(-1);
    }
}

// 创建顶点缓冲对象(VBO)
unsigned int createVBO()
{
    unsigned int vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    return vbo;
}

// 创建顶点数组对象(VAO)
unsigned int createVAO()
{
    unsigned int vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    return vao;
}

// 绑定顶点属性指针
void bindVertexAttributes()
{
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

// 创建索引缓冲对象(EBO)
unsigned int createEBO()
{
    unsigned int ebo;
    glGenBuffers(1, &ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    return ebo;
}

// 编译和链接着色器程序
unsigned int createShaderProgram()
{
    // 编译顶点着色器
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderCode, NULL);
    glCompileShader(vertexShader);
    
    // 检查顶点着色器是否编译成功
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "Failed to compile vertex shader" << std::endl;
        exit(-1);
    }
    
    // 编译片段着色器
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderCode, NULL);
    glCompileShader(fragmentShader);
    
    // 检查片段着色器是否编译成功
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "Failed to compile fragment shader" << std::endl;
        exit(-1);
    }
    
    // 创建着色器程序并链接着色器
    unsigned int shaderProgram;
    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 << "Failed to link shader program" << std::endl;
        exit(-1);
    }
    
    // 删除着色器对象
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    
    return shaderProgram;
}

// 渲染循环
void renderLoop(GLFWwindow* window, unsigned int vao, unsigned int ebo, unsigned int shaderProgram)
{
    while (!glfwWindowShouldClose(window))
    {
        // 处理输入事件
        processInput(window);
        
        // 清空屏幕颜色
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        
        // 使用着色器程序
        glUseProgram(shaderProgram);
        
        // 更新模型矩阵以实现旋转
        float angle = glfwGetTime() * 50.0f;
        glm::mat4 model = glm::rotate(glm::mat4(1.0f), glm::radians(angle), glm::vec3(0.0f, 0.0f, 1.0f));
        unsigned int modelLocation = glGetUniformLocation(shaderProgram, "uModel");
        glUniformMatrix4fv(modelLocation, 1, GL_FALSE, glm::value_ptr(model));
        
        // 绑定顶点数组对象(VAO)和索引缓冲对象(EBO)
        glBindVertexArray(vao);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
        
        // 绘制正方形
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        
        // 交换缓冲区并查询事件
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
}

int main()
{
    // 初始化GLFW
    initGLFW();
    
    // 创建窗口和上下文
    GLFWwindow* window = createWindow(800, 600, "OpenGL");
    
    // 初始化GLAD
    initGLAD();
    
    // 创建顶点缓冲对象(VBO)
    unsigned int vbo = createVBO();
    
    // 创建顶点数组对象(VAO)
    unsigned int vao = createVAO();
    
    // 绑定顶点属性指针
    bindVertexAttributes();
    
    // 创建索引缓冲对象(EBO)
    unsigned int ebo = createEBO();
    
    // 编译和链接着色器程序
    unsigned int shaderProgram = createShaderProgram();
    
    // 进入渲染循环
    renderLoop(window, vao, ebo, shaderProgram);
    
    // 清理资源
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ebo);
    glDeleteProgram(shaderProgram);
    
    // 终止GLFW
    glfwTerminate();
    
    return 0;
}

这个例子演示了如何在OpenGL中旋转一个正方形。你可以根据自己的需要自定义顶点位置、顶点颜色、旋转角度等参数。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

  • OpenGL ES for Android 绘制旋转的地球

    No 图 No Code,上面旋转的地球是不是很酷炫,下面就让我们开始说说如何绘制旋转地球吧?绘制旋转地球需要3个步骤: 计算球体顶点数据。 地球纹理贴图。 通过MVP矩阵旋转地球。...计算球体顶点数据 我们知道OpenGL中最基本的图元是三角形,任何复杂的图形都可以分解为一个个的三角形,球体也不例外,假设球体上有“经纬度”,通过“经纬度”将球体分割为一个个的四边形,如下图: ?...把这些四边形分割为2个三角形,所以绘制球体的关键是计算“经纬度”相交的点的坐标。...R.drawable.earth) textureId = GLTools.loadTexture(bitmap) } GLTools.loadTexture为封装的工具类方法,OpenGL...ES 绘制纹理文章已经详细介绍,图片纹理的相关内容也可以参考此文章。

    1.6K20

    OpenGL ES for Android 视频缩放、旋转、平移

    在上一篇文章我们介绍了使用OpenGL ES 播放视频,末尾提到如果渲染视频的窗口宽高比和视频宽高比不一致会导致视频拉伸,这篇文章将会介绍如何通过视频的缩放来解决这个问题。...我们OpenGL ES 播放视频的基础进行修改,修改顶点shader attribute vec4 a_Position; attribute vec2 a_TexCoordinate; varying...获取,视频的宽高需要给meidaplay添加OnVideoSizeChangedListener回调,由于视频的播放是onSurfaceCreated调用且这2个回调都是异步的,因此无法判断先后顺序...,因此在这2个回调中都增加判断,只有当视频和渲染窗口的宽高都获取到才计算MVP矩阵,或者我们也可以onSurfaceChanged调用视频播放,这样就可以只OnVideoSizeChangedListener...视频的旋转、平移和缩放是一样的,我们只需要对矩阵进行相应的操作,比如将视频旋转45度,代码如下: Matrix.rotateM(modelMatrix,0,45F,0F,0F,1F) 效果如下: ?

    2.8K20

    OpenGL(五)-- OpenGL矩阵的变换OpenGL(五)-- OpenGL矩阵的变换

    OpenGL(五)-- OpenGL矩阵的变换 前言 照常提出几个问题,希望通过阅读可以找到答案。 对物体3维的2维投影进行位移,有几种方式? 模型视图矩阵代表了什么?...世界坐标系 WORLD SPACE称为世界坐标系,记录物体坐标系的位置; 世界坐标系是由原点经过模型矩阵(Model Matrix)通过矩阵相乘变换得来的。 3....具体可以想象移动的是物体的每一个点,旋转之后物体的每一个点都的方向向量都会旋转,之后平移就会按照方向向量来进行移动 先平移不会修改物体额方向向量,所以旋转就会得到不同的效果。...涉及到的矩阵变换 OpenGL矩阵的计算方式 // 矩阵计算 m3dMatrixMultiply44(ModelViewMatrix(模型视图矩阵),ViewMatrix(观察者矩阵), ModelMatrix...如果想要了解具体矩阵是如何计算的:3D数学 矩阵知识 矩阵栈 计算时会发现这种计算会导致物体唯一无法重置,为了解决这种问题OpenGL提出了矩阵栈的概念。栈这个概念应该是很熟悉了吧!

    2.3K10

    OpenGLOpenGL移动端的应用

    OpenGL移动端的表现形式为OpenGLES,OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计...二.坐标系统 开始绘制图形之前,我们必须先给OpenGL输入一些顶点数据。OpenGL是一个3D图形库,所以我们OpenGL中指定的所有坐标都是3D坐标(x、y和z)。...OpenGL不是简单地把所有的3D坐标变换为屏幕上的2D像素;OpenGL仅当3D坐标3个轴(x、y和z)上都为-1.0到1.0的范围内时才处理它。...image.png 我们可以看到图中茶壶先旋转再平移与先平移再旋转最终的结果是不一样的,因为它都是基于物体本身,学过线性代数我们会知道矩阵乘法不满足交换律。...接着对装配好的图元进行裁剪(clip):保留完全视锥体的图元,丢弃完全不在视锥体的图元,对一半一半不在的图元进行裁剪;接着再对视锥体的图元进行剔除处理(cull):这个过程可编码来决定是剔除正面

    2.7K30

    实验3 OpenGL几何变换

    1.实验目的: 理解掌握一个OpenGL程序平移、旋转、缩放变换的方法。...2.实验内容: (1)阅读实验原理,运行示范实验代码,掌握OpenGL程序平移、旋转、缩放变换的方法; (2)根据示范代码,尝试完成实验作业; 3.实验原理: (1)OpenGL下的几何变换 OpenGL...由于矩阵乘法满足结合率,((RT)v) = R(Tv)),换句话说,实际上是先进行移动,然后进行旋转。即:实际变换的顺序与代码写的顺序是相反的。...(视口变换) 这些,都可以OpenGL实现。 从“相对移动”的观点来看,改变观察点的位置与方向和改变物体本身的位置与方向具有等效性。OpenGL,实现这两种功能甚至使用的是同样的函数。...OpenGL规定堆栈的容量至少可以容纳32个矩阵,某些OpenGL实现,堆栈的容量实际上超过了32个。因此不必过于担心矩阵的容量问题。

    1.2K20

    OpenGL】二十、OpenGL 矩阵变换 ( 矩阵缩放变换 | 矩阵旋转变换 | 矩阵平移变换 )

    文章目录 一、绘制三角形 二、选中矩阵设置 三、矩阵缩放变换 四、矩阵旋转变换 五、矩阵平移变换 六、相关资源 一、绘制三角形 ---- 先绘制一个三角形 , 矩阵变换的主题就是该三角形 ; OpenGL...三角形绘制相关参考 【OpenGL】十三、OpenGL 绘制三角形 ( 绘制单个三角形 | 三角形绘制顺序 | 绘制多个三角形 ) 博客 ; 代码示例 : // 渲染场景 // 清除缓冲区...【OpenGL】十、OpenGL 绘制点 ( 初始化 OpenGL 矩阵 | 设置投影矩阵 | 设置模型视图矩阵 | 绘制点 | 清除缓冲区 | 设置当前颜色值 | 设置点大小 | 绘制点 ) 博客简单介绍了...投影矩阵 和 模型视图矩阵 ; 进行 平移 , 缩放 , 旋转 等矩阵操作 , 主要针对 模型视图矩阵 进行操作 ; 进行 OpenGL 环境渲染时 , 选中了 GL_MODELVIEW 模型视图矩阵后..., 就开始了渲染 , 后面操作的矩阵都是针对该 GL_MODELVIEW 矩阵的 ; 下面的代码是设置矩阵的代码 , 之后就开始了 OpenGL 模型渲染 , 也就是说模型渲染过程 , 全程都选中了模型矩阵

    3.6K00

    必会算法:旋转有序的数组搜索

    大家好,我是戴先生 今天给大家介绍一下如何利用玄学二分法找出目标值元素 想直奔主题的可直接看思路2 ##题目 整数数组 nums 按升序排列,数组的值互不相同 传递给函数之前,nums...: 将数组第一个元素挪到最后的操作,称之为一次旋转 现将nums进行了若干次旋转 给你 旋转后 的数组 nums 和一个整数 target 如果 nums 存在这个目标值 target 则返回它的下标...n次之后就是这样的 所以我们的目标就是在这样的数组里边找目标值 可以非常清晰的看到 第二段的所有值都是小于第一段的值 这样思路就非常清晰了 二分查找的时候可以很容易判断出 当前的中位数是第一段还是第二段...最终问题会简化为一个增序数据的普通二分查找 我们用数组[1,2,3,4,5,6,7,8,9]举例说明 target目标值为7 3次旋转之后是这个样子 使用二分查找的话,首先还是先找到中位数 即下表为...(0+8)/2=4 nums[4] = 8 此时8>nums[start=0]=4的 同时8>target=7 所以可以判断出 此时mid=4是处在第一段的 而且目标值mid=4的前边 此时,查找就简化为了增序数据的查找了

    2.8K20

    OpenGL (二)--OpenGL那些晦涩难懂的名词、动词解析OpenGL (二)--OpenGL那些晦涩难懂的名词、动词解析

    图元 首先需要明确一个概念图元,OpenGl图元包含:点、线、三角形。也就是说我们看到的任何图形都是由这三个基本元素组成的。...将顶点数据保存到内存,就称为顶点数组。 将顶点数据保存到GPU的显存,就称为顶点缓存区 ? 管线 从图片到显示屏幕上需要一个过程。...这就是OpenGL中一个完成的管线流程。 最后一步测试与混合,实际进行了以下几步的操作。 ? 固定管线 OpenGL的早期,提供了很多API来帮助开发者快速完成渲染流程。...OpenGL已经提供了一些固定的混合算法,但是平时开发也会使用自定义片元着色器来完成,但是效率会比固定混合算法差一些。...变换矩阵 OpenGL想要图形发生平移、缩放、旋转就需要变换矩阵进行计算。 投影矩阵 OpenGL想要3D坐标转换为2D坐标,就需要投影矩阵进行计算。

    1.1K20

    第4章代码-图形几何变换

    目录 4.4 编程实例——三角形与矩形变换及动画 4.4.1 自定义矩阵变换实例——三角形变换 4.4.2 OpenGL几何变换实例——矩形变换 4.4.3 变换应用实例——正方形旋转动画 4.4 编程实例...- p1.z); /* 通过平移-旋转-平移复合变换序列完成任意轴的旋转(注意OpenGL的反序表示)*/ glTranslatef (p1.x, p1.y, p1.z); /...glutDisplayFunc(myDisplay); glutReshapeFunc(Reshape); glutMainLoop(); } 4.4.3 变换应用实例——正方形旋转动画...= 0.5f; //正方形边长 GLfloat theta = 0.0f; //旋转初始角度值 void myDisplay() { glClearColor(0.8f, 0.8f, 0.8f,...400);//设置显示窗口大小 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);//设置显示模式为双缓冲和RGB彩色模式) glutCreateWindow("旋转正方形

    67230

    实验4 二维几何变换

    2.实验内容: 根据示范代码1,使用OpenGL平移、旋转、缩放变换函数来改写代码实现所要求的功能。示范代码1的代码运行结果为图1。...3.实验原理: (1)OpenGL下的几何变换 OpenGL的核心库,每一种几何变换都有一个独立的函数,所有变换都在三维空间中定义。...由于矩阵乘法满足结合率,((RT)v) = R(Tv)),换句话说,实际上是先进行移动,然后进行旋转。即:实际变换的顺序与代码写的顺序是相反的。...(视口变换) 这些,都可以OpenGL实现。 从“相对移动”的观点来看,改变观察点的位置与方向和改变物体本身的位置与方向具有等效性。OpenGL,实现这两种功能甚至使用的是同样的函数。...OpenGL规定堆栈至少可以容纳32个矩阵,某些OpenGL实现,堆栈的容量实际上超过了32个。因此不必过于担心矩阵的容量问题。 通常,用这种先保存后恢复的措施,比先变换再逆变换要更方便、更快速。

    1.1K20

    OpenGL】二十三、OpenGL 光照的法线原理

    如果 入射光线与法线角度等于 90 度 , 就不会产生反射 , 此时点是黑色的 ; 如果 入射光线与法线角度大于 90 度 , 也不会产生反射 , 此时点是黑色的 ; 因此法线指向的角度不同 , 屏幕绘制的点的颜色也是不同的...; 法线一定程度上决定这个点是否反射光 , 也就是是否屏幕上绘制指定的颜色值 ; 下面的球法线垂直与球平面 , 当光照从右上角方向打过来时 , 亮的地方就是法线与入射光夹角小于 90 的点 ( 正光面...) , 黑的地方就是法线与入射光夹角大于等于 90 度的点 ( 背光面 ) ; 可编程管线 , 决定某个点是否 正光面 还是 背光面 的判定方法 : 将改点与光源连线 , 计算该连线与法线的夹角...材质颜色值 相乘 , 再乘以反射率 , 就是反射出去的光 , 这也是模型表面呈现的颜色值 ; 二、相关资源 ---- GitHub 地址 : https://github.com/han1202012/OpenGL

    78600

    必会算法:旋转有序的数组找最小值

    大家好,我是戴先生 今天给大家介绍一下如何利用玄学二分法找出最小值 想直奔主题的可直接看思路2 这次的内容跟 必会算法:旋转有序的数组搜索 有类似的地方 都是针对旋转数据的操作 可以放在一块来学习理解...##题目 整数数组 nums 按升序排列,数组的值互不相同 传递给函数之前,nums 预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [...[4,5,6,7,0,1,2] 关于这段描述还有另外一种容易理解的说法: 将数组第一个元素挪到最后的操作,称之为一次旋转 现将nums进行了若干次旋转 找到数组的最小值,并返回结果...n次之后就是这样的 所以我们的目标就是在这样的数组里边找目标值 可以非常清晰的看到 第二段的所有值都是小于第一段的值 所以最小值就是二段的第一个元素 还有一种极端的情况就是 经过多次旋转之后 数组又变成了一个单调递增的数组...所以总的规律就是: 二分法的基础上 当中间值mid比起始值start对应的数据大时 判断一下mid和end对应值的大小 nums[end]<=nums[mid],则最小值mid后边,start=mid

    2.3K20

    Mathematica空间解析几何的应用之旋转曲面

    但是,初次接触解析几何时,由于学生的空间想象能力不够,其学习会有一定的阻碍;而立体空间难以描述对教师的教学也有很大的挑战。...一款强大的通用计算软件-Mathematica能很好的解决这个问题,它通过动态的交互界面直观清晰的向学生展示空间立体图的效果,接下来我们通过两个旋转曲面的例子来讲解Mathematica解析几何方面的应用...注:以一条平面曲线绕其平面上的一条定直线旋转一周所成的曲面称为旋转曲面,该条直线称为该旋转曲面的轴。 曲线f[x]=Sqrt[4-x]R区域绕X轴旋转的图形 ?...曲线p[y]=Sqrt[y-1]和曲线q[y]=(y-1)/2相交而成的图形绕y轴旋转的图形 ?

    2.9K70
    领券