c5b57a7954a30cce9e80ad6f91c9608a92f476be
[demo] / src / opengl / shader-gl.cc
1 #include <GL/glew.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "opengl/shader-gl.h"
6
7 ShaderGL::ShaderGL()
8 {
9         sdr = 0;
10 }
11
12 ShaderGL::~ShaderGL()
13 {
14         destroy();
15 }
16
17 bool ShaderGL::create(char *buf, unsigned int bsz, const char *fname)
18 {
19         /* find shader type and create shader */
20         unsigned int stype;
21         switch(type) {
22         case SDR_VERTEX:
23                 stype = GL_VERTEX_SHADER;
24                 break;
25         case SDR_FRAGMENT:
26                 stype = GL_FRAGMENT_SHADER;
27                 break;
28         default:
29                 fprintf(stderr, "Unknown shader type.\n");
30                 return false;
31         }
32         sdr = glCreateShader(stype);
33
34         /* compile */
35         glShaderSource(sdr, 1, (const char **)&buf, 0);
36         glCompileShader(sdr);
37
38         delete [] buf;
39
40         /* check compile status */
41         int status;
42         glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
43         if(status)
44                 printf("Successfully compiled shader: %s\n", fname);
45         else
46                 fprintf(stderr, "Failed to compile %s shader.\n", fname);
47
48         /* print the info log */
49         int loglen;
50         glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen);
51         if(loglen > 0 && (buf = new char[loglen + 1])) {
52                 glGetShaderInfoLog(sdr, loglen, 0, buf);
53                 buf[loglen] = 0;
54                 printf("%s\n", buf);
55
56                 delete [] buf;
57         }
58
59         if(!status) {
60                 destroy();
61                 return false;
62         }
63
64         return true;
65 }
66
67 void ShaderGL::destroy()
68 {
69         if(sdr) {
70                 glDeleteShader(sdr);
71         }
72         sdr = 0;
73         type = SDR_UNKNOWN;
74 }
75
76 void ShaderGL::attach(unsigned int prog)
77 {
78         glAttachShader(prog, sdr);
79 }
80
81 /* Shader Program */
82
83 ShaderProgramGL::ShaderProgramGL()
84 {
85         prog = 0;
86         memset(shaders, 0, sizeof shaders / sizeof *shaders);
87 }
88
89 ShaderProgramGL::~ShaderProgramGL()
90 {
91         destroy();
92 }
93
94 void ShaderProgramGL::destroy()
95 {
96         glDeleteProgram(prog);
97         prog = 0;
98
99         delete_shaders();
100 }
101
102 void ShaderProgramGL::delete_shaders()
103 {
104         for(unsigned int i=0; i<(sizeof shaders) / (sizeof *shaders); ++i) {
105                 delete shaders[i];
106         }
107 }
108
109 bool ShaderProgramGL::link()
110 {
111         glLinkProgram(prog);
112
113         int status;
114         glGetProgramiv(prog, GL_LINK_STATUS, &status);
115         if(status)
116                 printf("Successfully linked shader program.\n");
117         else
118                 printf("Failed to link shader program.\n");
119
120         int loglen;
121         glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &loglen);
122
123         char *buf;
124         if(loglen > 0 && (buf = new char[loglen + 1])) {
125                 glGetProgramInfoLog(prog, loglen, 0, buf);
126                 buf[loglen] = 0;
127                 printf("%s\n", buf);
128                 delete [] buf;
129         }
130
131         return status ? true : false;
132 }
133
134 bool ShaderProgramGL::load(const char *vfname, const char *ffname)
135 {
136         Shader *vsdr = new ShaderGL;
137         if(!vsdr->load(vfname, SDR_VERTEX)) {
138                 delete vsdr;
139                 return false;
140         }
141
142         Shader *fsdr = new ShaderGL;
143         if(!fsdr->load(ffname, SDR_FRAGMENT)) {
144                 delete vsdr;
145                 delete fsdr;
146                 return false;
147         }
148
149         prog = glCreateProgram();
150
151         vsdr->attach(prog);
152         fsdr->attach(prog);
153
154         if(!link()) {
155                 delete vsdr;
156                 delete fsdr;
157                 glDeleteProgram(prog);
158                 return false;
159         }
160
161         /* the order of shaders in the array is the order they have in
162         enum Type, so atm it goes like: VS, FS, ... because we have SDR_VERTEX,
163         SDR_FRAGMENT, ... */
164
165         shaders[0] = vsdr;
166         shaders[1] = fsdr;
167
168         return true;
169 }
170
171 void ShaderProgramGL::use()
172 {
173         glUseProgram(prog);
174 }