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
|
#include "../../../include/RenderBackend/OpenGL/ShaderFrame.hpp"
#include "../../../include/RenderBackend/OpenGL/opengl.hpp"
namespace amalgine {
ShaderFrame::ShaderFrame(u32 shader_program_id) : shader_program_id(shader_program_id), vertex_array_object_id(-1) {
glGenVertexArrays(1, &vertex_array_object_id);
}
ShaderFrame::~ShaderFrame() {
if(vertex_array_object_id != -1)
glDeleteVertexArrays(1, &vertex_array_object_id);
}
ShaderFrame::ShaderFrame(ShaderFrame &&other) {
this->operator=(std::move(other));
}
ShaderFrame& ShaderFrame::operator=(ShaderFrame &&other) {
shader_program_id = other.shader_program_id;
vertex_array_object_id = other.vertex_array_object_id;
shader_inputs = std::move(other.shader_inputs);
other.shader_program_id = -1;
other.vertex_array_object_id = -1;
return *this;
}
DeviceMemory* ShaderFrame::get_input_by_name(const char *name) {
auto it = shader_inputs.find(name);
if(it != shader_inputs.end())
return it->second.get();
GLint attrib_location = glGetAttribLocation(shader_program_id, name);
if(attrib_location == -1) {
fprintf(stderr, "No such attribute in shader: %s\n", name);
return nullptr;
}
glBindVertexArray(vertex_array_object_id); // Encapsulate DeviceMemory (vertex buffer object) inside the active vertex array object
DeviceMemory *device_memory_ptr = new DeviceMemory(vertex_array_object_id, attrib_location);
std::unique_ptr<DeviceMemory> device_memory(device_memory_ptr);
device_memory->use();
glEnableVertexAttribArray(attrib_location);
shader_inputs[name] = std::move(device_memory);
return device_memory_ptr;
}
Result<Uniform> ShaderFrame::get_uniform_by_name(const char *name) {
GLint uniform_id = glGetUniformLocation(shader_program_id, name);
if(uniform_id == -1)
return Result<Uniform>::Err(std::string("Uniform with name ") + name + " was not found");
Uniform uniform(uniform_id, shader_program_id);
return Result<Uniform>::Ok(std::move(uniform));
}
void ShaderFrame::draw() {
glUseProgram(shader_program_id);
glBindVertexArray(vertex_array_object_id); // Set the active shader to use the data encapsulated by the vertex array object
// TODO: Cache this num_vertices count (and reset it when device memory has changed)
#if 0
int num_vertices = 0;
for(const auto &it : shader_inputs) {
num_vertices = std::max(num_vertices, it.second->get_num_vertices());
}
#endif
int num_vertices = 0;
for(const auto &it : shader_inputs) {
int new_num_vertices = std::max(num_vertices, it.second->get_num_vertices());
#if 0
if(num_vertices != 0 && new_num_vertices != num_vertices) {
fprintf(stderr, "All inputs for shaders need to be of the same size!\n");
abort();
}
#endif
num_vertices = new_num_vertices;
}
// TODO: Allow specifying mode different than GL_TRIANGLES
glDrawArrays(GL_TRIANGLES, 0, num_vertices);
}
}
|