#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 device_memory(device_memory_ptr); device_memory->use(); glEnableVertexAttribArray(attrib_location); shader_inputs[name] = std::move(device_memory); return device_memory_ptr; } Result ShaderFrame::get_uniform_by_name(const char *name) { GLint uniform_id = glGetUniformLocation(shader_program_id, name); if(uniform_id == -1) return Result::Err(std::string("Uniform with name ") + name + " was not found"); Uniform uniform(uniform_id, shader_program_id); return Result::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); } }