/**
     * Updates all vertex attributes.
     * This is used when BindingLocation changes after a shader recompile.
     */
    void GLVertexAttributeArray::UpdateVertexAttributes()
    {
        OGL_CALL(glBindBuffer, GL_ARRAY_BUFFER, v_buffer);
        OGL_CALL(glBindVertexArray, vao);
        OGL_CALL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, i_buffer);

        for (const auto& desc : v_desc) {
            if (desc.location->iBinding > 0) {
                OGL_CALL(glEnableVertexAttribArray, desc.location->iBinding);
                switch (desc.shaderType)
                {
                case VAShaderType::FLOAT:
                    OGL_CALL(glVertexAttribPointer, desc.location->iBinding, desc.size,
                        desc.type, desc.normalized, desc.stride,
                        (static_cast<char*> (nullptr)) + desc.offset);
                    break;
                case VAShaderType::INTEGER:
                    OGL_CALL(glVertexAttribIPointer, desc.location->iBinding, desc.size,
                        desc.type, desc.stride, (static_cast<char*> (nullptr)) + desc.offset);
                    break;
                case VAShaderType::DOUBLE:
                    OGL_CALL(glVertexAttribLPointer, desc.location->iBinding, desc.size,
                        desc.type, desc.stride, (static_cast<char*> (nullptr)) + desc.offset);
                    break;
                }
            }
        }

        OGL_CALL(glBindVertexArray, 0);
        OGL_CALL(glBindBuffer, GL_ARRAY_BUFFER, 0);
    }
    /** Disables all vertex attributes in the array. */
    void GLVertexAttributeArray::DisableAttributes()
    {
        OGL_CALL(glBindVertexArray, vao);
        OGL_CALL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, 0);

        for (const auto& desc : v_desc) {
            if (desc.location->iBinding > 0) {
                OGL_CALL(glDisableVertexAttribArray, desc.location->iBinding);
            }
        }

        OGL_CALL(glBindVertexArray, 0);
    }
 /**
  * Adds a new double attribute to the vertex.
  * @param location the binding location
  * @param size the number of components in the attribute
  * @param type the type in which the data is stored in the vertex buffer
  * @param stride the difference in bytes between of this attributes
  * @param offset the offset into the buffer to the first of this attributes
  */
 void GLVertexAttributeArray::AddVertexAttributeL(BindingLocation location, int size, GLenum type,
     GLsizei stride, unsigned int offset)
 {
     vertex_attribute_desc desc;
     desc.shaderType = VAShaderType::DOUBLE;
     desc.location = location;
     desc.size = size;
     desc.type = type;
     desc.stride = stride;
     desc.offset = offset;
     v_desc.push_back(std::move(desc));
     OGL_CALL(glEnableVertexAttribArray, location->iBinding);
     OGL_CALL(glVertexAttribLPointer, location->iBinding, size, type, stride,
         (static_cast<char*> (nullptr)) + offset);
 }
예제 #4
0
 void Shader::UnloadLocal()
 {
     if (this->shader != 0) {
         OGL_CALL(glDeleteShader, shader);
         shader = 0;
     }
 }
예제 #5
0
void ForwardRenderer::Render()
{
    auto totalObjects = scene->GetTotalObjects();
    auto totalLights = scene->GetTotalLights();
    auto totalRenderingPasses = totalLights + 2;

    // Render passes:
    //   0 - Depth Prepass
    //   1 - Global Light for the Objects (Ambient, Emissive)
    //   Rest - Diffuse/Specular/etc Lighting for Objects
    for (decltype(totalRenderingPasses) p = 0; p < totalRenderingPasses; ++p) {
        OGL_CALL(glDepthMask((p == 0) ? GL_TRUE : GL_FALSE));

        bool writeToColor = (p == 0) ? GL_FALSE: GL_TRUE;
        OGL_CALL(glColorMask(writeToColor, writeToColor, writeToColor, writeToColor));
        for (decltype(totalObjects) i = 0; i < totalObjects; ++i) {
            const SceneObject& sceneObject = scene->GetSceneObject(i);

            auto totalRenderObjects = sceneObject.GetTotalRenderObjects();
            for (decltype(totalRenderObjects) r = 0; r < totalRenderObjects; ++r) {
                const RenderingObject* renderObject = sceneObject.GetRenderObject(r);
                if (!renderObject) {
                    continue;
                }
                const ShaderProgram* shaderToUse = renderObject->GetShaderProgramRaw();
                assert(shaderToUse);

                shaderToUse->StartUseShader();

                renderObject->BeginRender();

                // Make the scene object setup its shader with any data its shader might need.
                // Start from the end because the very 'last' light handles the global lighting for the object.
                // A light that is a nullptr will cause the shader to perform default behavior, whatever that may be.
                const Light* lightObject = scene->GetLightObject(totalRenderingPasses - p - 1);
                if (shaderToUse->IsAffectedByLight(lightObject)) {
                    sceneObject.PrepareShaderForRendering(shaderToUse, camera.get(), lightObject);
                    renderObject->Render();
                }
                renderObject->EndRender();

                shaderToUse->StopUseShader();
            }
        }
    }
    OGL_CALL(glDepthMask(GL_TRUE));
}
예제 #6
0
Texture2D::Texture2D(GLubyte* rawData, int width, int height):
    Texture(GL_TEXTURE_2D), texWidth(width), texHeight(height)
{
    OGL_CALL(glGenTextures(1, &glTexture));
    OGL_CALL(glBindTexture(GL_TEXTURE_2D, glTexture));
    OGL_CALL(glTexStorage2D(GL_TEXTURE_2D, 4, GL_RGBA8, texWidth, texHeight));
    OGL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, rawData));

    // Would be useful to expose these settings!
    OGL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
    OGL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
    OGL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
    OGL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
    OGL_CALL(glGenerateMipmap(GL_TEXTURE_2D));

    OGL_CALL(glBindTexture(GL_TEXTURE_2D, 0));
}
 /**
  * Constructor.
  * @param vertexBuffer the vertex buffer used to create the attributes.
  * @param indexBuffer the index buffer to bind
  */
 GLVertexAttributeArray::GLVertexAttributeArray(GLuint vertexBuffer, GLuint indexBuffer) :
     vao(0),
     i_buffer(indexBuffer),
     v_buffer(vertexBuffer),
     v_desc()
 {
     OGL_CALL(glGenVertexArrays, 1, &vao);
 }
예제 #8
0
void BlinnPhongShader::UpdateMaterialBlock() const
{
    StartUseShader();

    memcpy((void*)(materialStorage.data() + materialOffsets[0]), glm::value_ptr(diffuse), sizeof(glm::vec4));
    memcpy((void*)(materialStorage.data() + materialOffsets[1]), glm::value_ptr(specular), sizeof(glm::vec4));
    memcpy((void*)(materialStorage.data() + materialOffsets[2]), &shininess, sizeof(float));
    memcpy((void*)(materialStorage.data() + materialOffsets[3]), glm::value_ptr(ambient), sizeof(glm::vec4));

    if (materialBuffer && materialBlockLocation != GL_INVALID_INDEX) {
        OGL_CALL(glBindBuffer(GL_UNIFORM_BUFFER, materialBuffer));
        OGL_CALL(glBufferData(GL_UNIFORM_BUFFER, materialBlockSize, materialStorage.data(), GL_STATIC_DRAW));
        OGL_CALL(glBindBufferBase(GL_UNIFORM_BUFFER, MATERIAL_BINDING_POINT, materialBuffer));
        OGL_CALL(glUniformBlockBinding(shaderProgram, materialBlockLocation, MATERIAL_BINDING_POINT));
        OGL_CALL(glBindBuffer(GL_UNIFORM_BUFFER, 0));
    }

    StopUseShader();
}
예제 #9
0
void EpicShader::SetupShaderMaterials() const
{
    // Need to make sure the material buffer is bound.
    OGL_CALL(glBindBufferBase(GL_UNIFORM_BUFFER, MATERIAL_BINDING_POINT, materialBuffer));

    // Make sure the right textures are bound.
    const Texture* diffuseTexture = defaultTexture.get();
    if (textureSlotMapping.find(TextureSlots::DIFFUSE) != textureSlotMapping.end()) {
        diffuseTexture = textureSlotMapping.at(TextureSlots::DIFFUSE).get();
    }
    assert(diffuseTexture);
    diffuseTexture->BeginRender(static_cast<int>(TextureSlots::DIFFUSE));

    // While we're here, also setup the textures too.
    SetShaderUniform("diffuseTexture", static_cast<int>(TextureSlots::DIFFUSE));
}
예제 #10
0
void MediaLayer::InitializeOpenGL()
{
    if (!sdlInitialized) {
        std::cerr << "ERROR: Can not initialize OpenGL before setting up SDL." << std::endl;
        return;
    }

    glContext = SDL_GL_CreateContext(sdlWindow);
    if (glContext == NULL) {
        std::cerr << "ERROR: SDL failed to create an OpenGL context" << std::endl;
        return;
    }

    // 0 - Disables Vsync, 1 - Enables Vsync
    // More information: https://www.opengl.org/wiki/Swap_Interval
    // Documentation: https://wiki.libsdl.org/SDL_GL_SetSwapInterval
    SDL_GL_SetSwapInterval(0);

    // Initialize GLEW 
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if (err != GLEW_OK) {
        std::cerr << "ERROR: GLEW failed to initialize." << std::endl;
        return;
    }
    // At this point we want to flush out all of the OpenGL errors that might have been caused by GLEW.
    while ((err = glGetError()) != GL_NO_ERROR);

    openglInitialized = true;

    // Sane default settings for OpenGL rendering
    OGL_CALL(glEnable(GL_DEPTH_TEST));
    OGL_CALL(glDepthFunc(GL_LEQUAL));

    OGL_CALL(glEnable(GL_BLEND));
    OGL_CALL(glBlendFunc(GL_ONE, GL_ONE));

    OGL_CALL(glEnable(GL_CULL_FACE));
    OGL_CALL(glCullFace(GL_BACK));

    OGL_CALL(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
}
예제 #11
0
    /**
     * Loads a shader from file and compiles it.
     * @param filename the shaders file name
     * @param type the shaders type
     * @param strType the shaders type as string
     * @return the compiled shader if successful
     */
    GLuint Shader::CompileShader(const std::string& filename, const std::vector<std::string>& defines, GLenum type, const std::string& strType) const
    {
        unsigned int firstFileId = 0;
        if (!boost::filesystem::exists(filename)) {
            LOG(ERROR) << "Cannot open shader file \"" << filename.c_str() << "\".";
            throw resource_loading_error() << ::boost::errinfo_file_name(filename) << fileid_info(firstFileId) << resid_info(id)
                << errdesc_info("Cannot open shader file.");
        }
        auto shaderText = LoadShaderFile(filename, defines, firstFileId, 0);

        auto shader = OGL_CALL(glCreateShader, type);
        if (shader == 0) {
            LOG(ERROR) << L"Could not create shader!";
            throw std::runtime_error("Could not create shader!");
        }
        auto shaderTextArray = shaderText.c_str();
        auto shaderLength = static_cast<int>(shaderText.length());
        OGL_CALL(glShaderSource, shader, 1, &shaderTextArray, &shaderLength);
        OGL_CALL(glCompileShader, shader);

        GLint status;
        OGL_CALL(glGetShaderiv, shader, GL_COMPILE_STATUS, &status);
        if (status == GL_FALSE) {
            GLint infoLogLength;
            OGL_CALL(glGetShaderiv, shader, GL_INFO_LOG_LENGTH, &infoLogLength);

            auto strInfoLog = new GLchar[infoLogLength + 1];
            OGL_CALL(glGetShaderInfoLog, shader, infoLogLength, NULL, strInfoLog);

            std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
            LOG(ERROR) << L"Compile failure in " << converter.from_bytes(strType) << L" shader ("
                << filename.c_str() << "): " << std::endl << strInfoLog;
            std::string infoLog = strInfoLog;
            delete[] strInfoLog;
            OGL_CALL(glDeleteShader, shader);
            throw shader_compiler_error() << ::boost::errinfo_file_name(filename)
                << compiler_error_info(infoLog) << resid_info(id)
                << errdesc_info("Shader compilation failed.");
        }
        return shader;
    }
예제 #12
0
BlinnPhongShader::~BlinnPhongShader()
{
    OGL_CALL(glDeleteBuffers(1, &materialBuffer));
}
 /** Disables the vertex attribute array. */
 void GLVertexAttributeArray::DisableVertexAttributeArray() const
 {
     OGL_CALL(glBindVertexArray, 0);
 }
 /** Enables the vertex attribute array. */
 void GLVertexAttributeArray::EnableVertexAttributeArray() const
 {
     OGL_CALL(glBindVertexArray, vao);
 }
 /** Ends the vertex attribute setup. */
 void GLVertexAttributeArray::EndAttributeSetup() const
 {
     OGL_CALL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, i_buffer);
     OGL_CALL(glBindVertexArray, 0);
     OGL_CALL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, 0);
 }
 GLVertexAttributeArray::~GLVertexAttributeArray()
 {
     if (vao != 0) {
         OGL_CALL(glDeleteVertexArrays, 1, &vao);
     }
 }
예제 #17
0
EpicShader::~EpicShader()
{
    OGL_CALL(glDeleteBuffers(1, &materialBuffer));
}
 /** Initializes the vertex attribute setup. */
 void GLVertexAttributeArray::StartAttributeSetup() const
 {
     OGL_CALL(glBindVertexArray, vao);
     OGL_CALL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, 0);
 }