forked from benschreyer/ParticleSimulator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathShader.cpp
121 lines (109 loc) · 3.13 KB
/
Shader.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "Shader.h"
#include "Renderer.h"
#include <iostream>
#include <fstream>
#include <sstream>
Shader::Shader(const std::string& filename)
:m_FilePath(filename), m_RendererID(0)
{
ShaderProgramSource source = ParseShader(filename);
m_RendererID = CreateShader(source.VertexSource,source.FragmentSource);
}
Shader::~Shader()
{
GLCall(glDeleteProgram(m_RendererID));
}
void Shader::Bind() const
{
GLCall(glUseProgram(m_RendererID));
}
void Shader::Unbind() const
{
GLCall(glUseProgram(0));
}
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::SetUniform1i(const std::string& name, int v0)
{
GLCall(glUniform1i(GetUniformLocation(name), v0));
}
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 << name << " Does Not Exist\n";
}
m_UniformLocationCache[name] = location;
return location;
}
unsigned int Shader::CompileShader(unsigned int type, const std::string& source)
{
GLCall(unsigned int id = glCreateShader(type));
const char* src = source.c_str();
GLCall(glShaderSource(id, 1, &src, nullptr));
GLCall(glCompileShader(id));
int result;
GLCall(glGetShaderiv(id, GL_COMPILE_STATUS, &result));
if (result == GL_FALSE)
{
int length;
GLCall(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
char* message = (char*)malloc(sizeof(char) * length);
GLCall(glGetShaderInfoLog(id, length, &length, message));
std::cout << "failed to compile shader\n" << message << '\n';
return 0;
}
return id;
}
unsigned int Shader::CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{
GLCall(unsigned int program = glCreateProgram());
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
GLCall(glAttachShader(program, vs));
GLCall(glAttachShader(program, fs));
GLCall(glLinkProgram(program));
GLCall(glValidateProgram(program));
GLCall(glDeleteShader(vs));
GLCall(glDeleteShader(fs));
return program;
}
ShaderProgramSource Shader::ParseShader(const std::string& filepath)
{
enum class ShaderType
{
NONE = -1, VERTEX = 0, FRAGMENT = 1
};
ShaderType type = ShaderType::NONE;
std::ifstream stream(filepath);
std::string line;
std::stringstream ss[2];
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';
}
}
return { ss[0].str(),ss[1].str() };
}