wordpress 网站制作新手怎么做网页
一.关键名词解释
VAO: Vertex Array Object, 顶点数组对象,你要绘制的图形。
VBO:Vertex Buffer Object, 顶点缓冲对象,所有顶点的集合。
EBO:Element Buffer Object, 元素缓冲对象,顶点的索引值。
IBO: Index Buffer Object, 索引缓冲对象。
管线:又称图像渲染管线,将原始的3D坐标转换为屏幕上有颜色的像素。分为两部分:
第一部分就是将3D坐标转成平面的2D坐标,第二部分将2D坐标转成屏幕有颜色的像素。
着色器:管线接受3D坐标,然后转化成有颜色的像素。期间的工作很复杂,GPU上有成千上万个小处理器核心,它们能够并行处理小程序,这些小程序可以是默认的,也可以是开发者自定义的,这些用来最终处理成2D有颜色的像素的程序,统称为着色器。
顶点着色器:可编程的着色器,前面所说的并行小程序的其中一种,它的作用是将用户输入的3D坐标空间位置(向量vec3)转成空间位置(向量vec4)。向量4中最后个参数w原文作者后续会说,这里先记着。
图元装配:告诉opengl你要绘制的图片是什么类型的,绘制指令需要指定你要绘制成什么样的形状,这里,常用的有:GL_POINTS(点), GL_TRIANGLES(三角形), GL_LINE_STRIPS(线)。
几何着色器:根据图元装配指定的类型,会生成新的顶点和新的三角形。(具体还未清楚具体作用)。
光栅化阶段:将图元映射到屏幕上真正的像素点,生成供片段着色器使用的片段。在使用片段着色器之前,裁切掉视图以外的像素点,提高效率。
片段着色器:可编程的着色器,主要是计算一个像素真正的颜色。通常片段着色器包含3D厂场景的数据(包含光照,阴影,光的颜色), 这些都被计算在内。
测试与混合:所有颜色确定之后,那就是透明度的问题对吧,当然,还会确认这个像素呈现的深度和模板值。深度原文作者理解的就是z轴的值,代表离你的距离,是代表在物体的前面还是后面,能理解吗?模板值,原文作者后续会讲,后面再整理。
总之,着色器渲染的过程:顶点输入(接受用户输入的3D坐标数组)==》顶点着色器==》图元装配==》几何着色器==》光栅化阶段==》片段着色器==》测试与混合
二.开始创建六边形编码
1.创建两个着色器顶点和片段
// 顶点着色器的代码
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";
// 构建顶点着色器// 1.创建着色器对象unsigned int vertexShader;vertexShader = glCreateShader(GL_VERTEX_SHADER);// 2.将着色器代码关联到对象上并编译glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);// 3.检查编译是否成功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;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;}
2.编译完成之后链接到程序对象
// 编译完成之后链接到程序对象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);}// 删除着色器对象,在把着色器对象链接到程序对象以后,// 记得删除着色器对象,我们不再需要它们glDeleteShader(vertexShader);glDeleteShader(fragmentShader);
3.构建顶点,创建VBO,VAO,EBO
// 顶点输入六边形float vertices[] = {-0.5f, 0.5f, 0.0f,0.0f, 0.5f, 0.0f,0.5f, 0.5f, 0.0f,1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.0f,0.0f, -0.5f, 0.0f,-0.5f, -0.5f, 0.0f,-1.0f, 0.0f, 0.0f};unsigned int indices[] = {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 0};// 建立缓冲对象unsigned int VBO;unsigned int VAO;unsigned int EBO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);glBindVertexArray(VAO);// 绑定到缓冲bufferglBindBuffer(GL_ARRAY_BUFFER, VBO);// 刷入缓冲bufferglBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);// 解析顶点数据// 第一个参数: 0, 着色器的location = 0,对应这里的0// 第二个参数: 3, 顶点数据是3个坐标构成,这里是3// 第三个参数: 数据类型GL_FLOAT// 第四个参数: 是否标准化,标准化就会映射到0~1之间// 第五个参数步长: 表示每个顶点的所占空间的大小// 第六个参数: 代表偏移,默认位置为0glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);// 启动顶点属性glEnableVertexAttribArray(0);// 解绑VAOglBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);
4.绘制使用VAO,释放资源
// 等待用户关闭窗口while(!glfwWindowShouldClose(window)){processInput(window);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glUseProgram(shaderProgram);// 绘制物体glBindVertexArray(VAO);glDrawElements(GL_LINES, 16, GL_UNSIGNED_INT, 0);// 双缓冲交换glfwSwapBuffers(window);// 响应各种交互事件glfwPollEvents();}// 释放资源glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteBuffers(1, &EBO);glfwTerminate();return 0;