Shader.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "Shader.h"
  2. #include "spdlog/spdlog.h"
  3. #include <QFile>
  4. #include <qglobal.h>
  5. Shader::Shader(const QString vertexPath, const QString fragmentPath)
  6. {
  7. /* 获取OpenGL上下文 */
  8. auto ctx = QOpenGLContext::currentContext();
  9. if(!ctx)
  10. {
  11. SPDLOG_ERROR("获取OpenGL上下文失败");
  12. return;
  13. }
  14. m_glFuncs = ctx->functions();
  15. SPDLOG_DEBUG("加载着色器代码");
  16. QByteArray vertexShaderSource;
  17. QByteArray fragmentShaderSource;
  18. if(!loadShaderSourceFromFile(vertexPath, vertexShaderSource))
  19. {
  20. SPDLOG_ERROR("加载顶点着色器失败: {}", vertexPath.toStdString());
  21. return;
  22. }
  23. if(!loadShaderSourceFromFile(fragmentPath, fragmentShaderSource))
  24. {
  25. SPDLOG_ERROR("加载片段着色器失败: {}", fragmentPath.toStdString());
  26. return;
  27. }
  28. /* 编译着色器 */
  29. SPDLOG_DEBUG("编译着色器...");
  30. GLuint vertexShader = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
  31. GLuint fragmentShader = compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
  32. /* 创建着色器程序 */
  33. m_programID = m_glFuncs->glCreateProgram();
  34. /* 将顶点着色器和片段着色器附加到着色器程序对象上 */
  35. m_glFuncs->glAttachShader(m_programID, vertexShader);
  36. m_glFuncs->glAttachShader(m_programID, fragmentShader);
  37. /* 链接着色器程序 */
  38. m_glFuncs->glLinkProgram(m_programID);
  39. printOpenGLLinkError(m_programID);
  40. /* 删除着色器对象 */
  41. m_glFuncs->glDeleteShader(vertexShader);
  42. m_glFuncs->glDeleteShader(fragmentShader);
  43. SPDLOG_INFO("着色器创建成功");
  44. }
  45. Shader::~Shader()
  46. {
  47. }
  48. void Shader::use()
  49. {
  50. m_glFuncs->glUseProgram(m_programID);
  51. }
  52. GLuint Shader::getProgramID() const
  53. {
  54. return m_programID;
  55. }
  56. /* 设置uniform工具 */
  57. void Shader::setBool(const QString &name, bool value)
  58. {
  59. auto location = m_glFuncs->glGetUniformLocation(m_programID, name.toStdString().c_str());
  60. m_glFuncs->glUniform1i(location, (int)value);
  61. }
  62. void Shader::setInt(const QString &name, int value)
  63. {
  64. auto location = m_glFuncs->glGetUniformLocation(m_programID, name.toStdString().c_str());
  65. m_glFuncs->glUniform1i(location, value);
  66. }
  67. void Shader::setFloat(const QString &name, float value)
  68. {
  69. auto location = m_glFuncs->glGetUniformLocation(m_programID, name.toStdString().c_str());
  70. m_glFuncs->glUniform1f(location, value);
  71. }
  72. /* 打开着色器文件,加载着色器代码 */
  73. bool Shader::loadShaderSourceFromFile(const QString &filePath, QByteArray &outShaderSource)
  74. {
  75. QFile file(filePath);
  76. if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
  77. {
  78. SPDLOG_ERROR("无法打开着色器文件: {}", filePath.toStdString());
  79. SPDLOG_ERROR("错误信息: {}", file.errorString().toStdString());
  80. return false;
  81. }
  82. outShaderSource = file.readAll();
  83. file.close();
  84. return true;
  85. }
  86. /* 编译着色器 */
  87. GLuint Shader::compileShader(const QByteArray &shaderSource, GLenum shaderType)
  88. {
  89. const char* sourceCStr = shaderSource.constData();
  90. /* 创建着色器对象 */
  91. GLuint shader = m_glFuncs->glCreateShader(shaderType);
  92. /* 加载着色器源码 */
  93. m_glFuncs->glShaderSource(shader, 1, &sourceCStr, nullptr);
  94. /* 编译着色器 */
  95. m_glFuncs->glCompileShader(shader);
  96. printOpenGLCompileError(shader);
  97. return shader;
  98. }
  99. /* 打印编译错误 */
  100. void Shader::printOpenGLCompileError(GLuint errorCode)
  101. {
  102. int sucess;
  103. char infoLog[512];
  104. m_glFuncs->glGetShaderiv(errorCode, GL_COMPILE_STATUS, &sucess);
  105. if (!sucess)
  106. {
  107. m_glFuncs->glGetShaderInfoLog(errorCode, 512, nullptr, infoLog);
  108. SPDLOG_ERROR("OpenGL编译错误: {}", infoLog);
  109. }
  110. }
  111. /* 打印着色器链接错误 */
  112. void Shader::printOpenGLLinkError(GLuint errorCode)
  113. {
  114. int sucess;
  115. char infoLog[512];
  116. m_glFuncs->glGetProgramiv(errorCode, GL_LINK_STATUS, &sucess);
  117. if (!sucess)
  118. {
  119. m_glFuncs->glGetProgramInfoLog(errorCode, 512, nullptr, infoLog);
  120. SPDLOG_ERROR("OpenGL链接错误: {}", infoLog);
  121. }
  122. }