aboutsummaryrefslogtreecommitdiff
path: root/src/RenderBackend/OpenGL/ShaderFrame.cpp
blob: 3f7ff01f4d3bba23400407e87b05cf7b5262f31d (plain)
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
#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() {
        glDeleteVertexArrays(1, &vertex_array_object_id);
    }

    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)
        int num_vertices = 0;
        for(const auto &it : shader_inputs) {
            num_vertices = std::max(num_vertices, it.second->get_num_vertices());
        }
        // TODO: Allow specifying mode different than GL_TRIANGLES
        glDrawArrays(GL_TRIANGLES, 0, num_vertices);
    }
}