0% found this document useful (0 votes)
60 views

"Shader.h" "Renderer.h": #Include #Include #Include #Include #Include

This C++ code defines a Shader class that handles loading, compiling, and using shader programs in OpenGL. The Shader class parses shader files, compiles the vertex and fragment shaders, links them into a program, and provides methods for setting uniform values and binding the shader program. Key methods include ParseShader() for parsing shader files, CompileShader() for compiling individual shaders, and CreateShader() for linking and validating the final shader program.

Uploaded by

iDenis
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
60 views

"Shader.h" "Renderer.h": #Include #Include #Include #Include #Include

This C++ code defines a Shader class that handles loading, compiling, and using shader programs in OpenGL. The Shader class parses shader files, compiles the vertex and fragment shaders, links them into a program, and provides methods for setting uniform values and binding the shader program. Key methods include ParseShader() for parsing shader files, CompileShader() for compiling individual shaders, and CreateShader() for linking and validating the final shader program.

Uploaded by

iDenis
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 3

#include "Shader.

h"

#include <sstream>
#include <fstream>
#include <iostream>

#include "Renderer.h"

Shader::Shader(const std::string& filepath)


:m_FilePath(filepath), m_RendererID(0) {
ShaderProgramSource source = ParseShader(filepath);
m_RendererID = CreateShader(source.VertexSource, source.FragmentSource);
}

Shader::~Shader() {
GLCall(glDeleteProgram(m_RendererID));
}

ShaderProgramSource Shader::ParseShader(const std::string& filepath) {


std::ifstream stream(filepath);

enum class ShaderType {


NONE = -1, VERTEX = 0, FRAGMENT = 1
};

std::string line;
std::stringstream ss[2];
ShaderType type = ShaderType::NONE;
while (getline(stream, line)) {
if (line.find("#shader") != std::string::npos) {
if (line.find("vertex") != std::string::npos)
type = ShaderType::VERTEX;
else if (line.find("fragment") != std::string::npos)
type = ShaderType::FRAGMENT;
}
else {
ss[(int)type] << line << '\n';
}
}

m_VertexShader = ss[0].str();
m_FragmentShader = ss[1].str();
return { ss[0].str(), ss[1].str() };
}

void Shader::PrintShaderCode() {
std::cout << m_VertexShader << std::endl;
std::cout << m_FragmentShader << std::endl;
}

unsigned int Shader::CompileShader(unsigned int type, const std::string& source) {


unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);

int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE) {
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)malloc(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
std::cout << "Failed to compile"
<< (type == GL_VERTEX_SHADER ? " vertex " : " fragment ") << "shader" <<
std::endl;
std::cout << message << std::endl;
glDeleteShader(id);
return 0;
}

return id;
}

unsigned int Shader::CreateShader(const std::string& vertexShader, const std::string&


fragmentShader) {
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);

glDeleteShader(vs);
glDeleteShader(fs);

return program;
}

void Shader::Bind() const {


GLCall(glUseProgram(m_RendererID));
}

void Shader::Unbind() const {


GLCall(glUseProgram(0));
}

void Shader::SetUniform1i(const std::string& name, int value) {


GLCall(glUniform1i(GetUniformLocation(name), value));
}

void Shader::SetUniform1f(const std::string& name, float value) {


GLCall(glUniform1f(GetUniformLocation(name), value));
}

void Shader::SetUniform4f(const std::string& name, float v0, float v1, float v2, float
v3) {
GLCall(glUniform4f(GetUniformLocation(name), v0, v1, v2, v3));
}

void Shader::SetUniformMat4f(const std::string& name, const glm::mat4& matrix) {


GLCall(glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, &matrix[0][0]));
}
int Shader::GetUniformLocation(const std::string& name){
if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end())
return m_UniformLocationCache[name];

GLCall(int location = glGetUniformLocation(m_RendererID, name.c_str()));


if (location == -1)
std::cout << "Warning: uniform '" << name << "' doesn't exist" << std::endl;

m_UniformLocationCache[name] = location;
return location;
}

You might also like