aboutsummaryrefslogtreecommitdiff
path: root/apps/openmb/renderer/Shader.cpp
blob: a7c94e61c4ce249ebf4d1f85b80263e31dbd371f (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
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "Shader.hpp"

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#ifdef __APPLE__
#include <OpenGL/gl3.h>
#endif
#include <fstream>
#include <iostream>
#include <sstream>

namespace renderer {
Shader::Shader () : mID( 0 ) {}

Shader::~Shader () {
    if( mID ) {
        glDeleteProgram( mID );
    }
}

bool Shader::fromSource ( const std::string& vertexSrc, const std::string& fragmentSrc ) {
    return compileShader( vertexSrc.c_str(), fragmentSrc.c_str() );
}

bool Shader::fromFiles ( const std::string& vertexPath, const std::string& fragmentPath ) {
    std::string vs = readFile( vertexPath );
    std::string fs = readFile( fragmentPath );
    if( vs.empty() || fs.empty() ) {
        return false;
    }
    return compileShader( vs.c_str(), fs.c_str() );
}

void Shader::use () const {
    glUseProgram( mID );
}

unsigned int Shader::id () const {
    return mID;
}

void Shader::setInt ( const std::string& name, int value ) const {
    glUniform1i( glGetUniformLocation( mID, name.c_str() ), value );
}

void Shader::setFloat ( const std::string& name, float value ) const {
    glUniform1f( glGetUniformLocation( mID, name.c_str() ), value );
}

void Shader::setVec3 ( const std::string& name, const glm::vec3& v ) const {
    glUniform3f( glGetUniformLocation( mID, name.c_str() ), v.x, v.y, v.z );
}

void Shader::setVec2 ( const std::string& name, const glm::vec2& v ) const {
    glUniform2f( glGetUniformLocation( mID, name.c_str() ), v.x, v.y );
}

void Shader::setMat4 ( const std::string& name, const glm::mat4& m ) const {
    glUniformMatrix4fv( glGetUniformLocation( mID, name.c_str() ), 1, GL_FALSE, &m[0][0] );
}

bool Shader::compileShader ( const char* vSrc, const char* fSrc ) {
    GLuint vert = glCreateShader( GL_VERTEX_SHADER );
    glShaderSource( vert, 1, &vSrc, nullptr );
    glCompileShader( vert );

    GLint success = 0;
    glGetShaderiv( vert, GL_COMPILE_STATUS, &success );
    if( success == GL_FALSE ) {
        GLint len = 0;
        glGetShaderiv( vert, GL_INFO_LOG_LENGTH, &len );
        std::string log( len, '\0' );
        glGetShaderInfoLog( vert, len, &len, &log[0] );
        std::cerr << "Vertex shader compile error:\n"
                  << log << std::endl;
        std::cerr << "[Shader] Vertex shader ID = " << vert << std::endl;
        glDeleteShader( vert );
        return false;
    }

    GLuint frag = glCreateShader( GL_FRAGMENT_SHADER );

    glShaderSource( frag, 1, &fSrc, nullptr );
    glCompileShader( frag );

    glGetShaderiv( frag, GL_COMPILE_STATUS, &success );
    if( success == GL_FALSE ) {
        GLint len = 0;
        glGetShaderiv( frag, GL_INFO_LOG_LENGTH, &len );
        std::string log( len, '\0' );
        glGetShaderInfoLog( frag, len, &len, &log[0] );
        std::cerr << "Fragment shader compile error:\n"
                  << log << std::endl;
        glDeleteShader( frag );
        glDeleteShader( vert );
        return false;
    }

    mID = glCreateProgram();
    glAttachShader( mID, vert );
    glAttachShader( mID, frag );
    glLinkProgram( mID );

    glGetProgramiv( mID, GL_LINK_STATUS, &success );
    if( success == GL_FALSE ) {
        GLint len = 0;
        glGetProgramiv( mID, GL_INFO_LOG_LENGTH, &len );
        std::string log( len, '\0' );
        glGetProgramInfoLog( mID, len, &len, &log[0] );
        std::cerr << "Shader link error:\n"
                  << log << std::endl;
        glDeleteProgram( mID );
        mID = 0;
        glDeleteShader( vert );
        glDeleteShader( frag );
        return false;
    }

    glDetachShader( mID, vert );
    glDetachShader( mID, frag );
    glDeleteShader( vert );
    glDeleteShader( frag );

    return true;
}

std::string Shader::readFile ( const std::string& path ) const {
    std::ifstream in( path );
    if( !in ) {
        return std::string();
    }
    std::stringstream ss;
    ss << in.rdbuf();
    return ss.str();
}

}   // namespace renderer