openGL系列文章目录

文章目录

  • openGL系列文章目录
  • 前言
  • 一、金字塔顶点组成
  • 二、给金字塔贴纹理
    • 1.纹理坐标:侧面
    • 2.纹理坐标底座
  • 代码:
    • 1. c++
    • 2.顶点着色器
    • 片元着色器
  • 运行效果
  • 源码下载

前言

金字塔由6个三角形组成——侧面4 个,底面2 个,总共6×3=18 个顶点。

一、金字塔顶点组成

// 金字塔有18 个顶点,由6 个三角形组成(侧面4 个,底面2 个)

float pyramidPositions[54] =
{ -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 前面
1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // 右面
1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // 后面
-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 左面
-1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, // 底面 — 左前一半
1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f // 底面 — 右后一半
};

二、给金字塔贴纹理

1.纹理坐标:侧面

                           图1 纹理图像的顶部中心对应金字塔的尖顶

2.纹理坐标底座


图2 为金字塔底面添加纹理

代码:

1. c++

#include "glew/glew.h"
#include "glfw/glfw3.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "Utils.h"
#include <iostream>
#include <string>
#include <fstream>using namespace std;static const int screen_width = 1920;
static const int screen_height = 1080;int width = 0;
int height = 0;
float aspect = 0.f;float cameraX = 0.f, cameraY = 0.f, cameraZ = 0.f;
float pyramidLocX = 0.f, pyramidLocY = 0.f, pyramidLocZ = 0.f;
int mvLoc = 0, projLoc = 0;GLuint renderingProgram = 0;
static const int numberVAOs = 1;
static const int numberVBOs = 2;
GLuint vao[numberVAOs] = { 0 };
GLuint vbo[numberVBOs] = { 0 };GLuint textureId;
float rotAmt = 0.f;
glm::mat4 mMat(1.f), vMat(1.f), pMat(1.f), mvMat(1.f);void setupVertices()
{float pyramidPositions[54] ={-1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f,    //front1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f,    //right1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f,  //back-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f,  //left-1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, //LF1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f  //RR};float textureCoordinates[36] ={0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 1.0f,0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 1.0f,0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 1.0f,0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 1.0f,0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f};glGenVertexArrays(numberVAOs, vao);glBindVertexArray(vao[0]);glGenBuffers(numberVBOs, vbo);glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidPositions), pyramidPositions, GL_STATIC_DRAW);glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);glBufferData(GL_ARRAY_BUFFER, sizeof(textureCoordinates), textureCoordinates, GL_STATIC_DRAW);
}void init(GLFWwindow* window)
{renderingProgram = Utils::createShaderProgram("vertShader.glsl", "fragShader.glsl");cameraX = 0.f, cameraY = 0.f; cameraZ = 10.f;pyramidLocX = 0.f, pyramidLocY = 0.f, pyramidLocZ = 0.f;glfwGetWindowSize(window, &width, &height);//glfwGetFramebufferSize(window, &width, &height);aspect = (float)width / (float)height;pMat = glm::perspective(glm::radians(45.f), aspect, 0.01f, 1000.f);setupVertices();textureId = Utils::loadTexture("resource/brick1upArrow.jpg");
}void display(GLFWwindow* window, float currentTime)
{//参数要完全正确,否则窗口不会显示模型glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//设置窗口背景glClearColor(0.f, 0.4f, 1.f, 1.f);//必不可少!!!否则窗口是黑的,不会渲染任何东西glUseProgram(renderingProgram);mvLoc = glGetUniformLocation(renderingProgram, "mv_matrix");projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");//移动相机矩阵:这里必须是-cameraZ,否则相机看不到立方体和金字塔vMat = glm::translate(glm::mat4(1.f), glm::vec3(cameraX, cameraY, -cameraZ));mMat = glm::translate(glm::mat4(1.f), glm::vec3(pyramidLocX, pyramidLocY, pyramidLocZ));mMat = glm::rotate(mMat, currentTime, glm::vec3(1.f, 0.f, 0.f));//mMat = glm::rotate(mMat, currentTime, glm::vec3(0.f, 1.f, 0.f));mMat = glm::rotate(mMat, rotAmt, glm::vec3(0.f, 1.f, 0.f));   //试着修改mMat = glm::rotate(mMat, currentTime, glm::vec3(0.f, 0.f, 1.f));//右乘规则//mvMat = mMat * vMat;   //金字塔会离开视口mvMat = vMat * mMat;     //金字塔始终控制在视口//更改一个uniform矩阵变量或数组的值。要更改的uniform变量的位置由location指定,location的值应该由glGetUniformLocation函数返回// 将透视矩阵和MV 矩阵复制给相应的统一变量/*通过一致变量(uniform修饰的变量)引用将一致变量值传入渲染管线。location : uniform的位置。count : 需要加载数据的数组元素的数量或者需要修改的矩阵的数量。transpose : 指明矩阵是列优先(column major)矩阵(GL_FALSE)还是行优先(row major)矩阵(GL_TRUE)。value : 指向由count个元素的数组的指针。*/glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvMat));glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));//绑定到金字塔顶点缓冲区glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);//指定了渲染时索引值为 index 的顶点属性数组的数据格式和位置/*Parametersindex指定要修改的顶点属性的索引值size指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(梦维:如position是由3个(x, y, z)组成,而颜色是4个(r, g, b, a))type指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT。normalized指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)。stride指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。pointer指定一个指针,指向数组中第一个顶点属性的第一个组件。初始值为0。*/glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);//启用或禁用通用顶点属性数组,参数0索引和着色器中的layout(location = 0)中的0相对应,顶点位置glEnableVertexAttribArray(0);//绑定金字塔纹理坐标glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);//启用或禁用通用顶点属性数组,参数0索引和着色器中的layout(location = 1)中的1相对应,纹理坐标glEnableVertexAttribArray(1);//激活纹理坐标glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, textureId);glDrawArrays(GL_TRIANGLES, 0, 18);  //绘制金字塔glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LEQUAL);
}void window_size_callback(GLFWwindow* window, int newWidth, int newHeight)
{glViewport(0, 0, newWidth, newHeight);aspect = (float)newWidth / (float)newHeight;pMat = glm::perspective(glm::radians(45.f), aspect, 0.01f, 1000.f);
}int main(int argc, char** argv)
{int glfwState = glfwInit();if (GLFW_FALSE == glfwState){cout << "GLFW initialize failed,invoke glfwInit()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl;glfwTerminate();exit(EXIT_FAILURE);}/*因为我们要使用OpenGL 4.6,所以我们把GLFW_CONTEXT_VERSION_MAJOR和GLFW_CONTEXT_VERSION_MINOR对应的hint都设置为4和6。因为我们要使用OpenGL核心模式(这个后面会提到更多),所以我们把GLFW_OPENGL_PROFILE对应的hint设置为GLFW_OPENGL_CORE_PROFILE,表示使用OpenGL核心模式。最后,把GLFW_RESIZABLE对应的hint设置为GLFW_FALSE,表示窗口不允许用户调整大小。之所以这样做是因为如果允许用户调整大小,大小发生变化后,窗口的绘制区域默认不变(依然是原来窗口的区域),也就是说窗口上绘制的图像的大小、位置不会发生改变。为了避免这种现象发生,我们就简单地不让用户调整窗口大小(当然也有更好的方法,就是用GLFW设置一个窗口大小的回调函数,但这样比较简单)。*/glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);glfwWindowHint(GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_PROFILE);glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);GLFWwindow* window = glfwCreateWindow(screen_width, screen_height, "Texture Pyramid mipmap aniso", nullptr, nullptr);if (!window){cout << "GLFW create window failed,invoke glfwCreateWindow()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl;;glfwTerminate();exit(EXIT_FAILURE);}/*此函数使调用线程上的指定窗口的 OpenGL 或 OpenGL ES 上下文成为当前上下文。一次只能在单个线程上使上下文成为当前上下文,并且每个线程一次只能有一个当前上下文。在线程之间移动上下文时,必须先使其在旧线程上变为非当前状态,然后再在新线程上变为当前状态。*/glfwMakeContextCurrent(window);//窗口大小改变回调函数glfwSetWindowSizeCallback(window, window_size_callback);int glewState = glewInit();if (GLEW_OK != glewState){cout << "GLEW initialize failed,invoke glewInit()......Error file:" << __FILE__ << "......Error line:" << __LINE__ << endl;exit(EXIT_FAILURE);}/*此函数设置当前 OpenGL 或 OpenGL ES 上下文的交换间隔,即从调用glfwSwapBuffers开始等待的屏幕更新次数,然后再交换缓冲区并返回。这有时称为垂直同步、垂直回扫同步或仅vsync。支持WGL_EXT_swap_control_tear和GLX_EXT_swap_control_tear扩展的上下文也接受负交换间隔,这允许驱动程序立即交换,即使帧到达有点晚。您可以使用glfwExtensionSupported检查这些扩展。上下文必须在调用线程上是最新的。在没有当前上下文的情况下调用此函数将导致GLFW_NO_CURRENT_CONTEXT错误。此功能不适用于 Vulkan。如果您使用 Vulkan 进行渲染,请改为查看交换链的当前模式。*/glfwSwapInterval(1);init(window);/*默认情况下,出于性能考虑,所有顶点着色器的属性(Attribute)变量都是关闭的,意味着数据在着色器端是不可见的,哪怕数据已经上传到GPU,由glEnableVertexAttribArray启用指定属性,才可在顶点着色器中访问逐顶点的属性数据。glVertexAttribPointer或VBO只是建立CPU和GPU之间的逻辑连接,从而实现了CPU数据上传至GPU。但是,数据在GPU端是否可见,即,着色器能否读取到数据,由是否启用了对应的属性决定,这就是glEnableVertexAttribArray的功能,允许顶点着色器读取GPU(服务器端)数据。*/int nrAttributes;glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes);std::cout << "Maximum nr of vertex attributes supported: " << nrAttributes << std::endl;while (!glfwWindowShouldClose(window)){display(window, (float)glfwGetTime());glfwSwapBuffers(window);glfwPollEvents();}glfwDestroyWindow(window);glfwTerminate();exit(EXIT_SUCCESS);return 0;
}

2.顶点着色器

#version 460 corelayout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoords;uniform mat4 mv_matrix;
uniform mat4 proj_matrix;uniform sampler2D samp;out vec2 tc;void main()
{gl_Position = proj_matrix * mv_matrix * vec4(position, 1.f);tc = texCoords;
}

片元着色器

#version 460 corein vec2 tc;
vec4 fragColor;out vec4 color;uniform mat4 mv_matrix;
uniform mat4 proj_matrix;uniform sampler2D samp;void main()
{color = texture(samp, tc);
}

运行效果

源码下载

工程源码下载

opengl绘制金字塔相关推荐

  1. openGL绘制带纹理地球,并实现鼠标键盘控制

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一.绘制球体 二.关键代码 球体类(Sphere) 主函数 顶点着色器 片元着色器 显示效果 源码下载 参考 前言 openGL绘制 ...

  2. openGL绘制带纹理太阳、地球、月亮,并且地球自转并且围绕太阳旋转。月亮自转也会围绕地球旋转

    openGL系列文章目录 前言 使用openGL绘制太阳.地球.月亮,太阳自转,地球自转并且围绕太阳旋转.月亮自转也会围绕地球旋转,其实月亮也会围绕太阳旋转的. 一.效果 还是有不满意的地方: 1.没 ...

  3. 如何用 OpenGL 绘制雪花?

    作者 | 许向武 责编 | 张红月 出品 | CSDN博客 看冬奥才知道,阿勒泰不但是中国的"雪都",还是"人类滑雪起源地".这个说法是否成立,姑且不论,阿勒泰 ...

  4. 使用OpenGL绘制圆环体(Torus)

    本篇介绍一下使用OpenGL绘制圆环体的方法.程序是在C#和OpenTK环境下编译的. 代码: /// <summary> /// 绘制圆环体 /// </summary> / ...

  5. 【OpenGL】十三、OpenGL 绘制三角形 ( 绘制单个三角形 | 三角形绘制顺序 | 绘制多个三角形 )

    文章目录 一.绘制三角形 二.三角形绘制顺序 1.绘制正面 2.三个点逆时针方向排列 3.三个点顺时针方向排列 4.设置点的正面方向 三.绘制多个三角形 四.相关资源 一.绘制三角形 三角形绘制即绘制 ...

  6. 【OpenGL】十一、OpenGL 绘制多个点 ( 绘制单个点 | 绘制多个点 )

    文章目录 一.绘制单个点 二.绘制多个点 三.相关资源 在上一篇博客 [OpenGL]十.OpenGL 绘制点 ( 初始化 OpenGL 矩阵 | 设置投影矩阵 | 设置模型视图矩阵 | 绘制点 | ...

  7. 【OpenGL】十、OpenGL 绘制点 ( 初始化 OpenGL 矩阵 | 设置投影矩阵 | 设置模型视图矩阵 | 绘制点 | 清除缓冲区 | 设置当前颜色值 | 设置点大小 | 绘制点 )

    文章目录 一.初始化 OpenGL 矩阵 1.设置投影矩阵 2.设置模型视图矩阵 二.绘制点 1.清除缓冲区 2.设置当前颜色值 3.设置绘制点的大小 4.绘制点 5.将缓冲区绘制到前台 三.部分代码 ...

  8. 【OpenGL】九、OpenGL 绘制基础 ( OpenGL 状态机概念 | OpenGL 矩阵概念 )

    文章目录 一.OpenGL 状态机概念 二.OpenGL 矩阵概念 上一篇博客 [OpenGL]八.初始化 OpenGL 渲染环境 ( 导入 OpenGL 头文件 | 链接 OpenGL 库 | 将窗 ...

  9. OpenGL绘制二个不同颜色的三角形的实例

    OpenGL绘制二个不同颜色的三角形 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> #include & ...

最新文章

  1. (纪录片)统计的乐趣 The Joy of Stats (2010)
  2. 绘制三维散点图_质量工具--之散点图
  3. 【算法】9 散列表【待补充】
  4. 云计算技术 — 云原生
  5. python绘制函数怎么去掉原点_python – 更改绘图的原点
  6. vue 组件不受全局样式影响_组件库引入全局样式lib/style/index.css,会污染全局基础样式...
  7. 零基础入门深度学习(4) - 卷积神经网络
  8. VS2010下如何改变Button颜色、背景、边框
  9. Python连接DB2数据库
  10. 【FPGA初级】4选一数据选择器的verilog实现(含testbench与波形)
  11. 医学图像加密算法研究_项目笔记
  12. 读书寄语:有一种感动叫守口如瓶
  13. 三年两转型 打造大宗商品交易大数据生态圈
  14. 地理信息系统GIS基础知识
  15. PC微信机器人之实战分析微信图片加密解密
  16. php关键词回复源码,PHP对接微信公众号实现简单自动回复
  17. 如何进行MQ技术选型
  18. Webpack基础应用篇 -[9]管理资源(下)
  19. MySQL8数据库中如何查询分组后每组中的最新一条记录
  20. java整合openoffice实现word、execl、ppt转换为pdf

热门文章

  1. win10安装sshpass_Win10自带的ssh客户端key权限设置
  2. ORACLE ORDER BY用法总结
  3. 【主题词——百合花】
  4. Java到底能干什么?
  5. 【工大SCIR】首次探索中文词信息增强中文口语语言理解!
  6. 扫描文件转换成word软件
  7. vue tsx render函数 transition动画不生效
  8. 皕杰基础平台的登录方式
  9. UVa 10041 - Vito's Family
  10. 【离散数学】编程练习:求关系的传递闭包