예제 #1
0
void
shader::_destroy()
{
  if(m_program_id)
  {
  	glDeleteProgram(m_program_id);
    m_program_id = 0;
    check_and_log_error("shader::_destroy - destroying program.");
  }

  if(m_vertex_id)
  {
    glDeleteShader(m_vertex_id);
    m_vertex_id = 0;
    check_and_log_error("shader::_destroy - destroying vertex shader.");
  }

  if(m_geometry_id)
  {
    glDeleteShader(m_geometry_id);
    m_geometry_id = 0;
    check_and_log_error("shader::_destroy - destroying geometry shader.");
  }

  if(m_fragment_id)
  {
    glDeleteShader(m_fragment_id);
    m_fragment_id = 0;
    check_and_log_error("shader::_destroy - destroying fragment shader.");
  }
}
예제 #2
0
파일: shader.cpp 프로젝트: pablorecio/KGLT
void ShaderProgram::set_uniform(const std::string& name, const kmVec4* vec) {
    GLint loc = get_uniform_loc(name);
    if(loc >= 0) {
        glUniform4fv(get_uniform_loc(name), 1, (GLfloat*) vec);
        check_and_log_error(__FILE__, __LINE__);
    }
}
예제 #3
0
void
index_buffer::bind()
{
  if(is_valid())
  {
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
    check_and_log_error("index_buffer::bind - failed binding buffer");
  }
}
예제 #4
0
파일: shader.cpp 프로젝트: pablorecio/KGLT
void ShaderProgram::set_uniform(const std::string& name, const kmMat3* matrix) {
    GLint loc = get_uniform_loc(name);
    if(loc >= 0) {
        float mat[9];
        unsigned char i = 9;
        while(i--) { mat[i] = (float) matrix->mat[i]; }
        glUniformMatrix3fv(get_uniform_loc(name), 1, false, (GLfloat*)mat);
        check_and_log_error(__FILE__, __LINE__);
    }
}
예제 #5
0
void
vertex_buffer::_destroy()
{
  if(m_vertex_buffer)
  {
  	glDeleteBuffers(1, &m_vertex_buffer);
  	m_vertex_buffer = 0;
    check_and_log_error("vertex_buffer::_destroy - destroying buffer.");
  }
}
예제 #6
0
void
vertex_buffer::bind(const vertex_format &set_vert_fmt, const shader &set_shader) const
{
  if(!is_valid())
  {
    log_error(GL_NO_ERROR, "vertex_buffer::bind - buffer is not valid.");
    return;
  }

  glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
  check_and_log_error("vertex_buffer::bind - binding buffer.");

  // Vertex Format
  {
    for(std::size_t i = 0; i < set_vert_fmt.get_number_of_elements(); ++i)
    {
      const GLint NOT_USED = -1;

      attribute attrib = set_vert_fmt.get_attribute(i);

      GLint index = glGetAttribLocation(set_shader.get_program_gl_id(), attrib.name.c_str());

      if(index != NOT_USED)
      {
        glEnableVertexAttribArray(index);
        glVertexAttribPointer(index,
                              static_cast<GLint>(attrib.size),
                              attrib.type,
                              GL_FALSE,
                              set_vert_fmt.get_stride(),
                              (void*)attrib.pointer);

        check_and_log_error("vertex_buffer::bind - applying vertex format '" + attrib.name + "'.");
      }
    }
  }

  check_and_log_error("vertex_buffer::bind - applying vertex buffer.");
}	
예제 #7
0
파일: shader.cpp 프로젝트: pablorecio/KGLT
ShaderProgram::~ShaderProgram() {
    try {
        for(uint32_t i = 0; i < ShaderType::SHADER_TYPE_MAX; ++i) {
            if(shader_ids_[i] != 0) {
                glDeleteShader(shader_ids_[i]);
            }
        }

        if(program_id_) {
            glDeleteProgram(program_id_);
        }
        check_and_log_error(__FILE__, __LINE__);
    } catch (...) { }
}
예제 #8
0
bool
index_buffer::load_index_buffer(const std::vector<uint32_t> &index)
{
  if(m_index_buffer)
  {
    _destroy();
  }
  
  m_number_of_indices = static_cast<uint32_t>(index.size());

  glGenBuffers(1, &m_index_buffer);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index), &index[0], GL_STATIC_DRAW);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  check_and_log_error("index_buffer::load_index_buffer - loading buffer.");

  return  (is_valid() ? true : false);
}
예제 #9
0
파일: shader.cpp 프로젝트: pablorecio/KGLT
void ShaderProgram::relink() {
    glLinkProgram(program_id_);
    check_and_log_error(__FILE__, __LINE__);

    GLint linked = 0;
    glGetProgramiv(program_id_, GL_LINK_STATUS, &linked);
    if(!linked) {
        GLint length;
        glGetProgramiv(program_id_, GL_INFO_LOG_LENGTH, &length);

        std::vector<char> log;
        log.resize(length);

        glGetProgramInfoLog(program_id_, length, NULL, &log[0]);
        L_ERROR(std::string(log.begin(), log.end()));
    }
    assert(linked);
}
예제 #10
0
bool
vertex_buffer::load_vertex_buffer(const std::vector<float> &vertex_data, const bool is_dynamic)
{
  if(is_valid())
  {
    log_error(GL_NO_ERROR, "vertex_buffer::load_shader - a vertex_buffer already exists, destroying old one.");
    _destroy();
  }

  glGenBuffers(1, &m_vertex_buffer);
  glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
  glBufferData(GL_ARRAY_BUFFER, vertex_data.size() * sizeof(float), vertex_data.data(), is_dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  if(is_valid())
  {
    m_buffer_size = static_cast<GLuint>(vertex_data.size());
    m_number_entries = vertex_data.size();
    return true;
  }

  check_and_log_error("vertex_buffer::load_vertex_buffer - loading vertex buffer.");
  return false;
}
예제 #11
0
void
shader::bind() const
{
  if(!is_valid())
  {
    log_error(GL_NO_ERROR, "vertex_buffer::bind - shader program is not valid.");
  }

  glUseProgram(m_program_id);
  check_and_log_error("shader::bind - failed to use program.");

  // Constants 
  {
    for(const auto &upload : m_pending_upload)
    {
      const constant_type type               = (constant_type)std::get<UPLOAD_TYPE>(upload);
      const uint32_t      index              = std::get<UPLOAD_INDEX>(upload);
      const uint32_t      number_of_elements = std::get<UPLOAD_NUM_ELEMENTS>(upload);
      const void          *data              = &(m_pending_upload_data.at(std::get<UPLOAD_START_INDEX>(upload)));

      switch(type)
      {
        case(constant_type::FLOAT):  glUniform1fv(index, number_of_elements, (GLfloat*)data);  break;
        case(constant_type::VEC2):   glUniform2fv(index, number_of_elements, (GLfloat*)data);  break;
        case(constant_type::VEC3):   glUniform3fv(index, number_of_elements, (GLfloat*)data);  break;
        case(constant_type::VEC4):   glUniform4fv(index, number_of_elements, (GLfloat*)data);  break;
        case(constant_type::INT):    glUniform1iv(index, number_of_elements, (GLint*)data);    break;
        case(constant_type::IVEC2):  glUniform2iv(index, number_of_elements, (GLint*)data);    break;
        case(constant_type::IVEC3):  glUniform3iv(index, number_of_elements, (GLint*)data);    break;
        case(constant_type::IVEC4):  glUniform4iv(index, number_of_elements, (GLint*)data);    break;
        case(constant_type::BOOL):   glUniform1iv(index, number_of_elements, (GLint*)data);    break;
        case(constant_type::BVEC2):  glUniform2iv(index, number_of_elements, (GLint*)data);    break;
        case(constant_type::BVEC3):  glUniform3iv(index, number_of_elements, (GLint*)data);    break;
        case(constant_type::BVEC4):  glUniform4iv(index, number_of_elements, (GLint*)data);    break;
        case(constant_type::MAT2):   glUniformMatrix2fv(index, number_of_elements, GL_FALSE, (GLfloat*)data); break;
        case(constant_type::MAT3):   glUniformMatrix3fv(index, number_of_elements, GL_FALSE, (GLfloat*)data); break;
        case(constant_type::MAT4):   glUniformMatrix4fv(index, number_of_elements, GL_FALSE, (GLfloat*)data); break;
          
        default:
          assert(false); // Why did you get here?
      };
    }
    
    m_pending_upload.clear();
    m_pending_upload_data.clear();
  } // Constants

  // Textures
  {
    const std::size_t number_of_textures = std::min<std::size_t>(m_pending_texture_data.size(), static_cast<std::size_t>(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS));

    for(std::size_t i = 0; i < number_of_textures; ++i)
    {
      const auto &tex = m_pending_texture_data.at(i);

      glActiveTexture(GL_TEXTURE0 + tex.index);
      check_and_log_error("shader::bind - applying active texture.");

      glBindTexture(tex.target, tex.texture_id);
      check_and_log_error("shader::bind - binding texture.");

  	  glTexParameteri(tex.target, GL_TEXTURE_WRAP_S, GL_REPEAT);
		  glTexParameteri(tex.target, GL_TEXTURE_WRAP_T, GL_REPEAT);
		  glTexParameteri(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		  glTexParameteri(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      check_and_log_error("shader::bind - setting texParaeteri.");  
    }

    m_pending_texture_data.clear();
  }
}
예제 #12
0
bool
shader::load_shader(const shader_code &code)
{
  if(is_valid())
  {
    log_error(GL_NO_ERROR, "shader::load_shader - a shader program already exists, destroying old one.");
    _destroy();
  }

 auto compile_shader = [](const std::string &shader_code, const GLenum shader_type, const std::string &shader_name) -> GLuint
  {
    if(shader_code.empty())
    {
      return 0;
    }

    GLuint shader_id = glCreateShader(shader_type);

		const char * vert_source = shader_code.c_str();
		glShaderSource(shader_id, 1, &vert_source, NULL);
		glCompileShader(shader_id);
		
		// Log
		GLint log_length;
		glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
		
		std::vector<GLchar> log;
		log.resize(log_length);
		glGetShaderInfoLog(shader_id, log_length, 0, &log[0]);

		if(log_length > 1)
		{
      std::string log_str;
      log_str.reserve(log.size());
      log_str.append(&log[0]);

		  // Did it compile
		  GLint is_compiled;
		  glGetShaderiv(shader_id, GL_COMPILE_STATUS, &is_compiled);

      auto find_line = [](const std::string &log, const std::string &shader, const std::string &log_tag) -> std::string
      {
        // This needs to work much better.
        return "";
      };

      if(is_compiled == GL_FALSE)
      {
        log_error(GL_NO_ERROR, "shader::load_shader - errors compiling shader.");
        log_error(GL_NO_ERROR, log_str);
        return 0;
      }
      else
      {
        log_error(GL_NO_ERROR, "shader::load_shader - warnings compiling shader.");
        log_error(GL_NO_ERROR, log_str);
      }
		}

    return shader_id;
  };

  m_vertex_id   = compile_shader(code.vs_code, GL_VERTEX_SHADER, "vertex");
  m_geometry_id = compile_shader(code.gs_code, GL_GEOMETRY_SHADER, "geometry");
  m_fragment_id = compile_shader(code.ps_code, GL_FRAGMENT_SHADER, "fragment");

  // Link the shader
  if(m_vertex_id && m_fragment_id)
  {
    m_program_id = glCreateProgram();
    
    glAttachShader(m_program_id, m_vertex_id);
    if(m_geometry_id) { glAttachShader(m_program_id, m_geometry_id); }
    glAttachShader(m_program_id, m_fragment_id);
    glLinkProgram(m_program_id);

    // Check the log
    GLint log_length;
		glGetProgramiv(m_program_id, GL_INFO_LOG_LENGTH, &log_length);
		
		std::vector<GLchar> log;
		log.resize(log_length);
		glGetProgramInfoLog(m_program_id, log_length, 0, &log[0]);

    // Did it link
    GLint is_linked;
		glGetProgramiv(m_program_id, GL_LINK_STATUS, &is_linked);

		if(log_length > 1)
		{
      std::string log_str;
      log_str.reserve(log.size());
      log_str.append(&log[0]);

      if(is_linked == GL_FALSE)
      {
        log_error(GL_NO_ERROR, "shader::load_shader - errors linking program.");
        log_error(GL_NO_ERROR, log_str);
      }
      else
      {
        log_error(GL_NO_ERROR, "shader::load_shader - warnings linking program.");
        log_error(GL_NO_ERROR, log_str);
      }
		}
    
    // Give up there
    if(is_linked == GL_FALSE)
    {
      m_program_id = 0;
      return false;
    }
  } // If linked
  else
  {
    //return false;
  }

  // Get uniforms
  {
    glUseProgram(m_program_id);
    check_and_log_error("shader::load_shader - failed to use program.");

    // Get uniforms.
    GLint uniform_count, uniform_length;
    glGetProgramiv(m_program_id, GL_ACTIVE_UNIFORMS, &uniform_count);
    glGetProgramiv(m_program_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_length);

    m_samplers.reserve(uniform_count);
    m_constants.reserve(uniform_count);

    for(GLint i = 0; i < uniform_count; ++i)
    {
      GLenum gl_type = 0;
      GLint length  = 0;
      GLint size    = 0;

      std::vector<GLchar> uni_name;
      uni_name.reserve(uniform_length);

      glGetActiveUniform(m_program_id, i, uniform_length, &length, &size, &gl_type, uni_name.data());
      const std::string uniform_name(uni_name.data());

      // Is sampler?
      if((gl_type >= GL_SAMPLER_1D) && (gl_type <= GL_SAMPLER_2D_RECT_SHADOW))
      {
        const GLint location = glGetUniformLocation(m_program_id, uniform_name.c_str());
        check_and_log_error("shader::load_shader - getting uniform location.");

        glUniform1i(location, m_samplers.size());
        
        m_samplers.emplace_back(sampler{uniform_name, static_cast<uint32_t>(m_samplers.size())});
      }
      // Then uniform
      else
      {
        const std::string prefix = "gl_";

        if(uniform_name.compare(0, prefix.length(), prefix) != 0)
        {
          const GLint index = glGetUniformLocation(m_program_id, uniform_name.c_str());
          const auto type = get_gl_constant_type(gl_type);

            m_constants.emplace_back(constant{uniform_name, static_cast<uint32_t>(index), static_cast<int32_t>(type), static_cast<int32_t>(size)});
        }
      }
    }

    m_samplers.shrink_to_fit();
    m_constants.shrink_to_fit();

    m_pending_upload_data.reserve(m_constants.size() * (4 * sizeof(float))); // Huristic to resever space for data. constants * vec4
    m_pending_texture_data.reserve(m_constants.size());
    m_pending_upload.reserve(m_constants.size());

  } // getting uniforms and samplers

  glUseProgram(0);

  return true;
}
예제 #13
0
파일: shader.cpp 프로젝트: pablorecio/KGLT
void ShaderProgram::add_and_compile(ShaderType type, const std::string& source) {
    check_and_log_error(__FILE__, __LINE__);

    if(program_id_ == 0) {
        program_id_ = glCreateProgram();
        check_and_log_error(__FILE__, __LINE__);
    }

    if(shader_ids_[type] != 0) {
        glDeleteShader(shader_ids_[type]);
        shader_ids_[type] = 0;
        check_and_log_error(__FILE__, __LINE__);
    }

    GLuint shader_type;
    switch(type) {
        case ShaderType::SHADER_TYPE_VERTEX: {
            L_DEBUG("Adding vertex shader");
            shader_type = GL_VERTEX_SHADER;
        } break;
        case ShaderType::SHADER_TYPE_FRAGMENT: {
            L_DEBUG("Adding fragment shader");
            shader_type = GL_FRAGMENT_SHADER;
        } break;
        default:
            throw std::logic_error("Invalid shader type");
    }
    check_and_log_error(__FILE__, __LINE__);
    GLuint shader = glCreateShader(shader_type);
    check_and_log_error(__FILE__, __LINE__);
    shader_ids_[type] = shader;

    const char* c_str = source.c_str();
    glShaderSource(shader, 1, &c_str, nullptr);
    check_and_log_error(__FILE__, __LINE__);

    glCompileShader(shader);
    check_and_log_error(__FILE__, __LINE__);

    GLint compiled = 0;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    if(!compiled) {
        GLint length;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);

        std::vector<char> log;
        log.resize(length);

        glGetShaderInfoLog(shader, length, NULL, &log[0]);
        L_ERROR(std::string(log.begin(), log.end()));
    }
    assert(compiled);
    assert(program_id_);
    assert(shader);

    check_and_log_error(__FILE__, __LINE__);
    glAttachShader(program_id_, shader);
    check_and_log_error(__FILE__, __LINE__);

    relink();
}
예제 #14
0
파일: shader.cpp 프로젝트: pablorecio/KGLT
void ShaderProgram::bind_attrib(uint32_t idx, const std::string& name) {
    glBindAttribLocation(program_id_, idx, name.c_str());
    check_and_log_error(__FILE__, __LINE__);
}
예제 #15
0
파일: shader.cpp 프로젝트: pablorecio/KGLT
void ShaderProgram::activate() {

    glUseProgram(program_id_);
    check_and_log_error(__FILE__, __LINE__);
}
예제 #16
0
파일: shader.cpp 프로젝트: pablorecio/KGLT
void ShaderProgram::set_uniform(const std::string& name, const int32_t x) {
    glUniform1i(get_uniform_loc(name), x);
    check_and_log_error(__FILE__, __LINE__);
}