GLSL着色器
1|0uniform
顶点着色器的输出out和片段着色器的输入in变量名一样的话可以由链接器将他们连接起来。
uniform是全局的,变量名必须独一无二,它允许cpu向gpu传数据,要先useShaderProgram才能更改uniform的值,在更改之前要获得位置,获得位置可以在useprogram之前。
2|0顶点包含多个属性
在顶点加颜色值,顶点pointer那里的初始地址、size、偏移都需要改,激活顶点的位置为1
#include<glad/glad.h>
#include<GLFW/glfw3.h>
#include<iostream>
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aColor;\n"
"out vec4 color;"
"void main()\n"
"{\n"
" color = vec4(aColor, 1.0);\n"
" gl_Position = vec4(aPos, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;"
"in vec4 color;"
"void main()\n"
"{\n"
" FragColor = color;"
"}\0";
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//创建窗口对象
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
//初始化GLAD管理指针,加载系统OpenGL函数指针
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to init GLAD" << std::endl;
return -1;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
//shader
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float vertices[] = {
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f,//右上
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,//右下
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f,//左上
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f,//左下
};
int indice[] = {
0, 1, 2,
2, 3, 1
};
unsigned int VBO, VAO, EBO;
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //第一个是类型,第二个是大小,第三个是数据
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indice), indice, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
while (!glfwWindowShouldClose(window))
{
processInput(window);
glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
//关闭窗口
glfwTerminate();
return 0;
}
3|0分开文件
先把VS中include的范围加入项目目录
把顶点着色器命名为shader.vs,像素着色器命名为shader.fs
在Shader里面,构造函数用流加载两个shader,注意要写调试信息,然后再实例化use函数,再main函数里面好用
main里面就可以用Shader类直接加载
shader.vs
#version 330 core
layout (location=0) in vec3 aPos;
layout (location=1) in vec3 aColor;
out vec4 color;
void main()
{
gl_Position = vec4(aPos, 1.0f);
color = vec4(aColor, 1.0f);
}
shader.fs
#version 330 core
in vec4 color;
out vec4 fragColor;
void main()
{
fragColor = color;
}
shader.cpp
#ifndef SHADER_H
#endif SHADER_H
#include<glad/glad.h>
#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
class Shader
{
public:
unsigned int ID;
Shader(const char* vertexPath, const char* fragmentPath)
{
using namespace std;
string vertexCode;
string fragmentCode;
ifstream vShaderFile;
ifstream fShaderFile;
vShaderFile.exceptions(ifstream::failbit | ifstream::badbit);
fShaderFile.exceptions(ifstream::failbit | ifstream::badbit);
try
{
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
stringstream vShaderStream, fShaderStream;
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
vShaderFile.close();
fShaderFile.close();
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch (ifstream::failure e)
{
cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << endl;
}
const char* vShaderCode = vertexCode.c_str();
const char* fShaderCode = fragmentCode.c_str();
unsigned int vertexShader, fragmentShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vShaderCode, NULL);
glCompileShader(vertexShader);
int success;
char infolog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infolog);
cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infolog << endl;
}
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fShaderCode, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infolog);
cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infolog << endl;
}
ID = glCreateProgram();
glAttachShader(ID, vertexShader);
glAttachShader(ID, fragmentShader);
glLinkProgram(ID);
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(ID, 512, NULL, infolog);
cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infolog << endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
void use()
{
glUseProgram(ID);
}
};
main.cpp
#include<glad/glad.h>
#include<GLFW/glfw3.h>
#include<iostream>
#include<Shader.cpp>
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//创建窗口对象
GLFWwindow* window = glfwCreateWindow(800, 600, "LJHyyds", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
//初始化GLAD管理指针,加载系统OpenGL函数指针
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to init GLAD" << std::endl;
return -1;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
Shader myshader("shader.vs", "shader.fs");
float vertices[] = {
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f,//右上
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,//右下
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f,//左上
};
unsigned int VBO, VAO;
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //第一个是类型,第二个是大小,第三个是数据
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
while (!glfwWindowShouldClose(window))
{
processInput(window);
glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
myshader.use();
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
//关闭窗口
glfwTerminate();
return 0;
}
4|0纪念
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
__EOF__

本文作者:Liujiahang
本文链接:https://www.cnblogs.com/IamIron-Man/p/16601916.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/IamIron-Man/p/16601916.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!