系列五:Shader 与modern opengl是近亲
借用子龙的一句话:不会写Shader,也敢说会OpenGL
参考:https://www.khronos.org/opengl/wiki/Shader_Compilation
Shader使用需要2个过程,1. Shader编译 2.Shader链接,其过程类似于C/C++程序
Shader编译
- 创建打算使用并编译的Shader对象 glCreateShader
- 一旦创建好Shader对象后,需要编辑Shader,即给Shader相应的源代码 glShaderSource
- 编译Shader glCompileShader
- 检查Shader编译的是否正确 glGetShaderiv
- 如果Shader编译有误,查看其相应的输出日志 glGetShaderInfoLog
设置属性槽
如果指明使用Shader中的属性信息,需要在链接Shader前,绑定其属性槽 glBindAttribLocation
Shader链接
- 创建程序对象 glCreateProgame
- 将编译好的Shader对象附加或者作用到链接对象上 glAttachShader
- 链接程序 glLinkProgram
- 检查程序链接是否正确 glGetProgramiv
- 如果程序链接有误,查看其输出日志 glGetProgramInfoLog
- 解除并删除编译对象 glDetachShader glDeleteShader
程序使用
- 使用程序 glUseProgram
- 激活使用的属性槽
GLSPProgram.h
1 #pragma once 2 #include <string> 3 #include <gl/glew.h> 4 5 class GLSLPromgram 6 { 7 public: 8 GLSLPromgram(); 9 ~GLSLPromgram(); 10 11 void compileShaders(const std::string& vertexSharderFilePath, const std::string& fragmentShaderFilePath); 12 13 void linkShaders(); 14 15 void addAttribute(const std::string& attributeName); 16 17 void use(); 18 void unuse(); 19 private: 20 void compileShader(const std::string& filePath, GLuint shaderID); 21 22 GLuint m_progamID; 23 GLuint m_vertexShaderID; 24 GLuint m_fragmentShaderID; 25 int m_numAttributes; 26 };
GLSLProgram.cpp
#include "GLSLPromgram.h" #include "Error.h" #include <fstream> #include <vector> GLSLPromgram::GLSLPromgram() :m_progamID(0), m_vertexShaderID(0), m_fragmentShaderID(0), m_numAttributes(0) { } GLSLPromgram::~GLSLPromgram() { } void GLSLPromgram::compileShaders(const std::string& vertexSharderFilePath, const std::string& fragmentShaderFilePath) { m_vertexShaderID = glCreateShader(GL_VERTEX_SHADER); if (0 == m_vertexShaderID) { faterError("Vertex shader failed to the created!"); } m_fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); if (0 == m_fragmentShaderID) { faterError("Fragment shader failed to the created!"); } compileShader(vertexSharderFilePath, m_vertexShaderID); compileShader(fragmentShaderFilePath, m_fragmentShaderID); } // Now time to link them together into a program. void GLSLPromgram::linkShaders() { // Get a program object. m_progamID = glCreateProgram(); // Attach our shaders to our program glAttachShader(m_progamID, m_vertexShaderID); glAttachShader(m_progamID, m_fragmentShaderID); // Link our program glLinkProgram(m_progamID); // Note the different functions here: glGetProgram* instead of glGetShader*. GLint isLinked(0); glGetProgramiv(m_progamID, GL_LINK_STATUS, &isLinked); if (GL_FALSE == isLinked) { GLint maxLength = 0; glGetProgramiv(m_progamID, GL_INFO_LOG_LENGTH, &maxLength); // The maxLength includes the NULL character std::vector<char> infoLog(maxLength); glGetProgramInfoLog(m_progamID, maxLength, &maxLength, &infoLog[0]); // We don't need the program anymore glDeleteProgram(m_progamID); // Don't leak shaders either glDeleteShader(m_vertexShaderID); glDeleteShader(m_fragmentShaderID); std::printf("%s\n", &(infoLog[0])); faterError("Shaders failed to link"); } // Always detach shaders after a successful link glDetachShader(m_progamID, m_vertexShaderID); glDetachShader(m_progamID, m_fragmentShaderID); // Don't leak shaders either glDeleteShader(m_vertexShaderID); glDeleteShader(m_fragmentShaderID); } void GLSLPromgram::addAttribute(const std::string& attributeName) { glBindAttribLocation(m_progamID, m_numAttributes++, attributeName.c_str()); } void GLSLPromgram::use() { glUseProgram(m_progamID); for (int i = 0; i < m_numAttributes; ++ i) { glEnableVertexAttribArray(i); } } void GLSLPromgram::unuse() { glUseProgram(0); for (int i = 0; i < m_numAttributes; ++ i) { glDisableVertexAttribArray(i); } } void GLSLPromgram::compileShader(const std::string& filePath, GLuint shaderID) { std::ifstream vertexFile(filePath); if (vertexFile.fail()) { perror(filePath.c_str()); faterError("Failed to open " + filePath); } std::string fileContents = ""; std::string line; while (std::getline(vertexFile, line)) { fileContents += line + "\n"; } vertexFile.close(); const char* contentsPtr = fileContents.c_str(); glShaderSource(shaderID, 1, &contentsPtr, nullptr); glCompileShader(shaderID); GLint isCompiled(0); glGetShaderiv(shaderID, GL_COMPILE_STATUS, &isCompiled); if (GL_FALSE == isCompiled) { GLint maxLength(0); glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxLength); std::vector<char> infoLog(maxLength); glGetShaderInfoLog(shaderID, maxLength, &maxLength, &infoLog[0]); glDeleteShader(shaderID); std::printf("%s\n", &(infoLog[0])); faterError("Shader " + filePath + " failed to compile"); } }
标签:
SDL OPENGL
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix