Files
2025-03-03 03:44:55 +08:00

149 lines
4.5 KiB
C++

#include "shader.h"
#include <cstring>
#include <cstdio>
#include <iostream>
using namespace std;
Shader::Shader(const char* shaderBasePath) {
if (BuildShadersFromFiles(shaderBasePath, "vertexShader.glsl",
"fragmentShader.glsl") != 0) {
cout << "Failed to build the pipeline program." << endl;
exit(1);
}
}
Shader::~Shader() {
glDeleteProgram(programHandle);
}
int Shader::BuildShadersFromFiles(const char* filenameBasePath,
const char* vertexShaderFilename,
const char* fragmentShaderFilename) {
// load vertex shader
char vertex_shader_code[128 * 1024];
char vertex_shader_filepath[1024] = { 0 };
strcpy(vertex_shader_filepath, filenameBasePath);
strcat(vertex_shader_filepath, "/");
strcat(vertex_shader_filepath, vertexShaderFilename);
// load vertex shader
if (LoadShader(vertex_shader_filepath, vertex_shader_code, 128 * 1024) != 0) {
cout << "shader " << vertex_shader_filepath << " file not found." << endl;
return 1;
}
// load fragment shader
char fragment_shader_code[128 * 1024];
char fragment_shader_filepath[1024] = { 0 };
strcpy(fragment_shader_filepath, filenameBasePath);
strcat(fragment_shader_filepath, "/");
strcat(fragment_shader_filepath, fragmentShaderFilename);
// load vertex shader
if (LoadShader(fragment_shader_filepath, fragment_shader_code, 128 * 1024) != 0) {
cout << "shader " << fragment_shader_filepath << " file not found." << endl;
return 1;
}
// create a program handle
programHandle = glCreateProgram();
if (programHandle == 0) {
cout << "shader initialize failed" << endl;
return -1;
}
// compile vertex shader
GLuint h_vertex_shaders;
if (CompileShader(vertex_shader_code, GL_VERTEX_SHADER, h_vertex_shaders) != 0) {
cout << "vertex shader compile error" << endl;
return 1;
}
else
glAttachShader(programHandle, h_vertex_shaders);
// compile fragment shader
GLuint h_fragment_shaders;
if (CompileShader(fragment_shader_code, GL_FRAGMENT_SHADER, h_fragment_shaders) != 0) {
cout << "fragment shader compile error" << endl;
return 1;
}
else
glAttachShader(programHandle, h_fragment_shaders);
// link the program
glLinkProgram(programHandle);
// get program error if possible
int status;
glGetProgramiv(programHandle, GL_LINK_STATUS, &status);
if (status == 0) {
GLchar infoLog[512];
glGetProgramInfoLog(programHandle, 512, nullptr, infoLog);
cout << "Errors:\n" << infoLog << endl;
return 1;
}
// delete shaders
glDeleteShader(h_vertex_shaders);
glDeleteShader(h_fragment_shaders);
// get model view matrix handle and projection matrix handle
h_modelViewMatrix = glGetUniformLocation(programHandle, "modelViewMatrix");
if (h_modelViewMatrix == -1)
cout << "model view Matrix not found \n" << endl;
h_projectionMatrix = glGetUniformLocation(programHandle, "projectionMatrix");
if (h_modelViewMatrix == -1)
cout << "projection Matrix not found \n" << endl;
return 0;
}
void Shader::Bind() {
glUseProgram(programHandle);
}
int Shader::LoadShader(const char* filename, char* code, int len) {
FILE* file = fopen(filename, "rb");
if (file == nullptr) {
return 1;
}
size_t length = fread(code, 1, len, file);
code[length] = '\0';
fclose(file);
return 0;
}
int Shader::CompileShader(const char* shaderCode, GLenum shaderType, GLuint& shaderHandle) {
shaderHandle = glCreateShader(shaderType);
if (shaderHandle == 0) {
cout << "shader creation failed" << endl;
return 1;
}
const int numShaderCodes = 1;
const GLchar* shaderCodes[] = { shaderCode };
GLint codeLength[] = { (GLint)strlen(shaderCode) };
// compile the shader (the entire source is in one string)
glShaderSource(shaderHandle, numShaderCodes, shaderCodes, codeLength);
glCompileShader(shaderHandle);
// check if compilation was successful
GLint status;
glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &status);
if (status == 0) {
GLchar infoLog[512];
glGetShaderInfoLog(shaderHandle, 512, nullptr, infoLog);
cout << infoLog << endl;
return 1;
}
return 0;
}
void Shader::SetModelViewMatrix(const float* m)
{
glUniformMatrix4fv(h_modelViewMatrix, 1, GL_FALSE, m);
}
void Shader::SetProjectionMatrix(const float* m)
{
glUniformMatrix4fv(h_projectionMatrix, 1, GL_FALSE, m);
}