opengl 绘制三角形(一)
1 win 操作系统:需要Visual studio,glfw, glad;详细安装和配置请自行百度
知识:(来源于奇境)
1 MVP变换
模型变换:平移,旋转,缩放
观察变换:计算机在摄像机视角下的位置
投影变换:将摄像机坐标系下的物体,投影到渲染平面
2 shader:着色器语言,是一种运行在GPU上的语言;
3渲染管线:顶点->顶点着色器->片元着色器->显示;一条链路
4 双缓存:主要是为了解决当你电子枪逐行画图很慢的时候,屏幕能看到逐行画图的现象,画面就会出现上半边是后一帧,下半边还是前一帧的;
5基础函数:
GlclearColor:用什么颜色清除当前画布,glClear:擦除画布上的内容
Glviewport设置视窗大小;然后就开始画东西了;画完swapbuffer交换前后缓冲,进行显示
6 shader 是如何从CPU读数据的
(1) 数据传入GPU buffer
(2) 告诉GPU数据是啥意思,怎么解析这些数据
(3) 让GPU开始画画
7 VAO,VBO
Vertex Buffer Object,在GPU上开辟空间,装入顶点数据
(1) 获取VBO的index
(2) 绑定VBO的index
(3) 给VBO分配显存空间,传输数据
(4) 告诉shader数据解析方式
(5) 激活锚点,激活一个个布局
做完VBO之后;初始化着色器,创建着色器,编译链接成着色器程序;
创建VAO;VOB就可以包含在VAO内使用;
然后就是使用VAO,着色器program,进行画图;
8 如果你使用VBO直接渲染,同一个锚点只能指定到最后一次设置的VBO缓冲对象;但是如果你使用不同的VAO分别包住各自的VBO,那同一个锚点可以分别绘制多个不同VBO的图形
cpp : 定义应用程序的入口点。 // #include "stdafx.h" #include#include #include<string> #include #include #include #include // settings const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 600; unsigned int VBO = 0; unsigned int VAO = 0; int shaderProgram = 0; //画图 void render() { glBindVertexArray(VAO); glUseProgram(shaderProgram); glDrawArrays(GL_TRIANGLES,0,3); glUseProgram(0); } void initmodule() { //做个一模型 float vertexs[] = { 0.0f,0.0f,0.0f, 0.5f,0.0f,0.0f, 0.0f,0.5f,0.0f, }; //做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); //设置第0个锚点,3个点,不需要归一化,跨度3个float可以读下一个点 glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0); //打开顶点 glEnableVertexAttribArray(0); //解除绑定VBO glBindBuffer(GL_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; }
//顶点着色器和片元着色器的 GLSL 语言;
#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); };