赞
踩
—— 2024-07-20 中午
bilibili赵新政老师的教程看后笔记
code review!
注意:每一帧都是从起始位姿旋转而至
代码
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; layout (location = 2) in vec2 aUV; out vec3 color; out vec2 uv; uniform mat4 transform; //aPos作为attribute(属性)传入shader //不允许更改的 void main() { vec4 position = vec4(aPos, 1.0); position = transform * position; gl_Position = position; color = aColor; uv = aUV; }
代码
#version 330 core
out vec4 FragColor;
in vec3 color;
in vec2 uv;
uniform sampler2D sampler;
void main()
{
FragColor = texture(sampler, uv);
}
main.cpp完整代码
#include <iostream> #include "glframework/core.h" #include "glframework/shader.h" #include <string> #include <assert.h>//断言 #include "wrapper/checkError.h" #include "application/Application.h" #include "glframework/texture.h" /* *┌────────────────────────────────────────────────┐ *│ 目 标: 初步学习GLM库的平移/旋转/缩放 *│ 讲 师: 赵新政(Carma Zhao) *│ 拆分目标: * -1 引入GLM的头文件 * -2 更改vertexShader,加入uniform变量mat4 transform * -3 使用传入的transform给我们的顶点坐标进行变换 * -4 为shader类增加uniform矩阵传输的功能 * -5 使用矩阵做复合变换 * -6 连续转动三角形(动画) *└────────────────────────────────────────────────┘ */ GLuint vao; Shader* shader = nullptr; Texture* texture = nullptr; glm::mat4 transform(1.0f); void OnResize(int width, int height) { GL_CALL(glViewport(0, 0, width, height)); std::cout << "OnResize" << std::endl; } void OnKey(int key, int action, int mods) { std::cout << key << std::endl; } void doRotationTransform() { //构建一个旋转矩阵,绕着z轴旋转45度角 //rotate函数:用于生成旋转矩阵 //bug1:rotate必须得到一个float类型的角度,c++的template //bug2:rotate函数接受的不是角度(degree),接收的弧度(radians) //注意点:radians函数也是模板函数,切记要传入float类型数据,加f后缀 transform = glm::rotate(glm::mat4(1.0f),glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0)); } //平移变换 void doTranslationTransform() { transform = glm::translate(glm::mat4(1.0f), glm::vec3(0.5f, 0.0f, 0.0f)); } //缩放变换 void doScaleTransform() { transform = glm::scale(glm::mat4(1.0f), glm::vec3(0.1f, 0.5f, 1.0f)); } //复合变换 void doTransform() { glm::mat4 rotateMat = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0)); glm::mat4 translateMat = glm::translate(glm::mat4(1.0f), glm::vec3(0.5f, 0.0f, 0.0f)); //先旋转 再平移 // transform = translateMat * rotateMat; //先平移 后旋转 transform = rotateMat * translateMat; } float angle = 0.0f; void doRotation() { angle += 2.0f; //每一帧都会“重新”构建一个旋转矩阵 transform = glm::rotate(glm::mat4(1.0f), glm::radians(angle), glm::vec3(0.0, 0.0, 1.0)); } void prepareVAO() { //1 准备positions colors float positions[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, }; float colors[] = { 1.0f, 0.0f,0.0f, 0.0f, 1.0f,0.0f, 0.0f, 0.0f,1.0f, }; float uvs[] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 1.0f, }; unsigned int indices[] = { 0, 1, 2, }; //2 VBO创建 GLuint posVbo, colorVbo, uvVbo; glGenBuffers(1, &posVbo); glBindBuffer(GL_ARRAY_BUFFER, posVbo); glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW); glGenBuffers(1, &colorVbo); glBindBuffer(GL_ARRAY_BUFFER, colorVbo); glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW); glGenBuffers(1, &uvVbo); glBindBuffer(GL_ARRAY_BUFFER, uvVbo); glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW); //3 EBO创建 GLuint ebo; glGenBuffers(1, &ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); //4 VAO创建 glGenVertexArrays(1, &vao); glBindVertexArray(vao); //5 绑定vbo ebo 加入属性描述信息 //5.1 加入位置属性描述信息 glBindBuffer(GL_ARRAY_BUFFER, posVbo); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*)0); //5.2 加入颜色属性描述数据 glBindBuffer(GL_ARRAY_BUFFER, colorVbo); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*)0); //5.3 加入uv属性描述数据 glBindBuffer(GL_ARRAY_BUFFER, uvVbo); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)0); //5.4 加入ebo到当前的vao glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBindVertexArray(0); } void prepareShader() { shader = new Shader("assets/shaders/vertex.glsl","assets/shaders/fragment.glsl"); } void prepareTexture() { texture = new Texture("assets/textures/goku.jpg", 0); } void render() { //执行opengl画布清理操作 GL_CALL(glClear(GL_COLOR_BUFFER_BIT)); //绑定当前的program shader->begin(); shader->setInt("sampler", 0); shader->setMatrix4x4("transform", transform); //绑定当前的vao GL_CALL(glBindVertexArray(vao)); //发出绘制指令 GL_CALL(glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0)); GL_CALL(glBindVertexArray(0)); shader->end(); } int main() { if (!app->init(800, 600)) { return -1; } app->setResizeCallback(OnResize); app->setKeyBoardCallback(OnKey); //设置opengl视口以及清理颜色 GL_CALL(glViewport(0, 0, 800, 600)); GL_CALL(glClearColor(0.2f, 0.3f, 0.3f, 1.0f)); prepareShader(); prepareVAO(); prepareTexture(); // doRotationTransform(); // doTranslationTransform(); // doScaleTransform(); doTransform(); while (app->update()) { // doRotation(); render(); } app->destroy(); return 0; }
void setMatrix4x4(const std::string& name, glm::mat4 value);
shader.h完整代码
#pragma once #include "core.h" #include<string> class Shader { public: Shader(const char* vertexPath, const char* fragmentPath); ~Shader(); void begin();//开始使用当前Shader void end();//结束使用当前Shader void setFloat(const std::string& name, float value); void setVector3(const std::string& name, float x, float y, float z); void setVector3(const std::string& name, const float* values); void setInt(const std::string& name, int value); void setMatrix4x4(const std::string& name, glm::mat4 value); private: //shader program //type:COMPILE LINK void checkShaderErrors(GLuint target,std::string type); private: GLuint mProgram{ 0 }; };
void Shader::setMatrix4x4(const std::string& name, glm::mat4 value) {
//1 通过名称拿到Uniform变量的位置Location
GLint location = GL_CALL(glGetUniformLocation(mProgram, name.c_str()));
//2 通过Location更新Uniform变量的值
//transpose参数:表示是否对传输进去的矩阵数据进行转置
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(value));
}
shader.cpp完整代码
#include"shader.h" #include"../wrapper/checkError.h" #include<string> #include<fstream> #include<sstream> #include<iostream> Shader::Shader(const char* vertexPath, const char* fragmentPath) { //声明装入shader代码字符串的两个string std::string vertexCode; std::string fragmentCode; //声明用于读取vs跟fs文件的inFileStream std::ifstream vShaderFile; std::ifstream fShaderFile; //保证ifstream遇到问题的时候可以抛出异常 vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { //1 打开文件 vShaderFile.open(vertexPath); fShaderFile.open(fragmentPath); //2 将文件输入流当中的字符串输入到stringStream里面 std::stringstream vShaderStream, fShaderStream; vShaderStream << vShaderFile.rdbuf(); fShaderStream << fShaderFile.rdbuf(); //3 关闭文件 vShaderFile.close(); fShaderFile.close(); //4 将字符串从stringStream当中读取出来,转化到code String当中 vertexCode = vShaderStream.str(); fragmentCode = fShaderStream.str(); } catch (std::ifstream::failure& e) { std::cout << "ERROR: Shader File Error: " << e.what() << std::endl; } const char* vertexShaderSource = vertexCode.c_str(); const char* fragmentShaderSource = fragmentCode.c_str(); //1 创建Shader程序(vs、fs) GLuint vertex, fragment; vertex = glCreateShader(GL_VERTEX_SHADER); fragment = glCreateShader(GL_FRAGMENT_SHADER); //2 为shader程序输入shader代码 glShaderSource(vertex, 1, &vertexShaderSource, NULL); glShaderSource(fragment, 1, &fragmentShaderSource, NULL); //3 执行shader代码编译 glCompileShader(vertex); //检查vertex编译结果 checkShaderErrors(vertex, "COMPILE"); glCompileShader(fragment); //检查fragment编译结果 checkShaderErrors(fragment, "COMPILE"); //4 创建一个Program壳子 mProgram = glCreateProgram(); //6 将vs与fs编译好的结果放到program这个壳子里 glAttachShader(mProgram, vertex); glAttachShader(mProgram, fragment); //7 执行program的链接操作,形成最终可执行shader程序 glLinkProgram(mProgram); //检查链接错误 checkShaderErrors(mProgram, "LINK"); //清理 glDeleteShader(vertex); glDeleteShader(fragment); } Shader::~Shader() { } void Shader::begin() { GL_CALL(glUseProgram(mProgram)); } void Shader::end() { GL_CALL(glUseProgram(0)); } void Shader::setFloat(const std::string& name, float value) { //1 通过名称拿到Uniform变量的位置Location GLint location = GL_CALL(glGetUniformLocation(mProgram, name.c_str())); //2 通过Location更新Uniform变量的值 GL_CALL(glUniform1f(location, value)); } void Shader::setVector3(const std::string& name, float x, float y, float z) { //1 通过名称拿到Uniform变量的位置Location GLint location = GL_CALL(glGetUniformLocation(mProgram, name.c_str())); //2 通过Location更新Uniform变量的值 GL_CALL(glUniform3f(location, x, y, z)); } //重载 overload void Shader::setVector3(const std::string& name, const float* values) { //1 通过名称拿到Uniform变量的位置Location GLint location = GL_CALL(glGetUniformLocation(mProgram, name.c_str())); //2 通过Location更新Uniform变量的值 //第二个参数:你当前要更新的uniform变量如果是数组,数组里面包括多少个向量vec3 GL_CALL(glUniform3fv(location, 1, values)); } void Shader::setInt(const std::string& name, int value) { //1 通过名称拿到Uniform变量的位置Location GLint location = GL_CALL(glGetUniformLocation(mProgram, name.c_str())); //2 通过Location更新Uniform变量的值 glUniform1i(location, value); } void Shader::setMatrix4x4(const std::string& name, glm::mat4 value) { //1 通过名称拿到Uniform变量的位置Location GLint location = GL_CALL(glGetUniformLocation(mProgram, name.c_str())); //2 通过Location更新Uniform变量的值 //transpose参数:表示是否对传输进去的矩阵数据进行转置 glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(value)); } void Shader::checkShaderErrors(GLuint target, std::string type) { int success = 0; char infoLog[1024]; if (type == "COMPILE") { glGetShaderiv(target, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(target, 1024, NULL, infoLog); std::cout << "Error: SHADER COMPILE ERROR" << "\n" << infoLog << std::endl; } } else if (type == "LINK") { glGetProgramiv(target, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(target, 1024, NULL, infoLog); std::cout << "Error: SHADER LINK ERROR " << "\n" << infoLog << std::endl; } } else { std::cout << "Error: Check shader errors Type is wrong" << std::endl; } }
core.h
#pragma once
//注意:glad头文件必须在glfw引用之前引用
#include <glad/glad.h>
#include <GLFW/glfw3.h>
//GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。