bloboland

annotate src/shaders.cc @ 1:cfe68befb7cc

some progress
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 15 Dec 2012 23:43:03 +0200
parents
children
rev   line source
nuclear@1 1 #include <stdio.h>
nuclear@1 2 #include <assert.h>
nuclear@1 3 #include <map>
nuclear@1 4 #ifdef _MSC_VER
nuclear@1 5 #include <memory.h>
nuclear@1 6 #else
nuclear@1 7 #include <alloca.h>
nuclear@1 8 #endif
nuclear@1 9 #include <GL/glew.h>
nuclear@1 10 #include "shaders.h"
nuclear@1 11
nuclear@1 12 Shader::Shader(unsigned int type)
nuclear@1 13 {
nuclear@1 14 sdr = glCreateShader(type);
nuclear@1 15 compiled = false;
nuclear@1 16
nuclear@1 17 assert(glGetError() == GL_NO_ERROR);
nuclear@1 18 }
nuclear@1 19
nuclear@1 20 Shader::~Shader()
nuclear@1 21 {
nuclear@1 22 glDeleteShader(sdr);
nuclear@1 23 }
nuclear@1 24
nuclear@1 25 void Shader::set_source(const char *src)
nuclear@1 26 {
nuclear@1 27 glShaderSource(sdr, 1, &src, 0);
nuclear@1 28 compiled = false;
nuclear@1 29
nuclear@1 30 assert(glGetError() == GL_NO_ERROR);
nuclear@1 31 }
nuclear@1 32
nuclear@1 33 bool Shader::compile()
nuclear@1 34 {
nuclear@1 35 if(compiled) {
nuclear@1 36 return true;
nuclear@1 37 }
nuclear@1 38
nuclear@1 39 glCompileShader(sdr);
nuclear@1 40
nuclear@1 41 int len;
nuclear@1 42 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &len);
nuclear@1 43 if(len) {
nuclear@1 44 char *buf = (char*)alloca(len + 1);
nuclear@1 45 glGetShaderInfoLog(sdr, len, &len, buf);
nuclear@1 46 fprintf(stderr, "compiler: %s\n", buf);
nuclear@1 47 }
nuclear@1 48
nuclear@1 49 int status;
nuclear@1 50 glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
nuclear@1 51 if(!status) {
nuclear@1 52 fprintf(stderr, "shader compilation failed\n");
nuclear@1 53 return false;
nuclear@1 54 }
nuclear@1 55
nuclear@1 56 compiled = true;
nuclear@1 57 return true;
nuclear@1 58 }
nuclear@1 59
nuclear@1 60 bool Shader::is_compiled() const
nuclear@1 61 {
nuclear@1 62 return compiled;
nuclear@1 63 }
nuclear@1 64
nuclear@1 65 bool Shader::load(const char *fname)
nuclear@1 66 {
nuclear@1 67 FILE *fp;
nuclear@1 68
nuclear@1 69 if(!(fp = fopen(fname, "rb"))) {
nuclear@1 70 fprintf(stderr, "failed to open shader file: %s\n", fname);
nuclear@1 71 return false;
nuclear@1 72 }
nuclear@1 73
nuclear@1 74 fseek(fp, 0, SEEK_END);
nuclear@1 75 long sz = ftell(fp);
nuclear@1 76 rewind(fp);
nuclear@1 77
nuclear@1 78 char *buf = new char[sz + 1];
nuclear@1 79 if((long)fread(buf, 1, sz, fp) < sz) {
nuclear@1 80 fprintf(stderr, "failed to read shader contents\n");
nuclear@1 81 fclose(fp);
nuclear@1 82 return false;
nuclear@1 83 }
nuclear@1 84 fclose(fp);
nuclear@1 85
nuclear@1 86 set_source(buf);
nuclear@1 87 delete [] buf;
nuclear@1 88
nuclear@1 89 return compile();
nuclear@1 90 }
nuclear@1 91
nuclear@1 92 // ---- shader manager ----
nuclear@1 93 static std::map<std::string, Shader*> sdrcache;
nuclear@1 94
nuclear@1 95 Shader *get_shader(const char *fname, unsigned int type)
nuclear@1 96 {
nuclear@1 97 std::map<std::string, Shader*>::const_iterator it;
nuclear@1 98
nuclear@1 99 if((it = sdrcache.find(std::string(fname))) != sdrcache.end()) {
nuclear@1 100 return it->second;
nuclear@1 101 }
nuclear@1 102
nuclear@1 103 Shader *sdr = new Shader(type);
nuclear@1 104 if(!sdr->load(fname)) {
nuclear@1 105 delete sdr;
nuclear@1 106 return 0;
nuclear@1 107 }
nuclear@1 108 sdrcache[fname] = sdr;
nuclear@1 109 return sdr;
nuclear@1 110 }
nuclear@1 111
nuclear@1 112
nuclear@1 113 // ---- class SdrProg ----
nuclear@1 114
nuclear@1 115 SdrProg::SdrProg()
nuclear@1 116 {
nuclear@1 117 prog = glCreateProgram();
nuclear@1 118 linked = false;
nuclear@1 119 assert(glGetError() == GL_NO_ERROR);
nuclear@1 120 }
nuclear@1 121
nuclear@1 122 SdrProg::~SdrProg()
nuclear@1 123 {
nuclear@1 124 glDeleteProgram(prog);
nuclear@1 125 }
nuclear@1 126
nuclear@1 127 void SdrProg::add_shader(Shader *sdr)
nuclear@1 128 {
nuclear@1 129 if(sdr->compile()) {
nuclear@1 130 glAttachShader(prog, sdr->sdr);
nuclear@1 131 assert(glGetError() == GL_NO_ERROR);
nuclear@1 132
nuclear@1 133 shaders.push_back(sdr);
nuclear@1 134 linked = false;
nuclear@1 135 }
nuclear@1 136 }
nuclear@1 137
nuclear@1 138 bool SdrProg::link()
nuclear@1 139 {
nuclear@1 140 if(linked) {
nuclear@1 141 return true;
nuclear@1 142 }
nuclear@1 143
nuclear@1 144 glLinkProgram(prog);
nuclear@1 145
nuclear@1 146 int len;
nuclear@1 147 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
nuclear@1 148 if(len) {
nuclear@1 149 char *buf = (char*)alloca(len + 1);
nuclear@1 150 glGetProgramInfoLog(prog, len, &len, buf);
nuclear@1 151 assert(glGetError() == GL_NO_ERROR);
nuclear@1 152 fprintf(stderr, "linker: %s\n", buf);
nuclear@1 153 }
nuclear@1 154
nuclear@1 155 int status;
nuclear@1 156 glGetProgramiv(prog, GL_LINK_STATUS, &status);
nuclear@1 157 if(!status) {
nuclear@1 158 fprintf(stderr, "program linking failed\n");
nuclear@1 159 return false;
nuclear@1 160 }
nuclear@1 161
nuclear@1 162 linked = true;
nuclear@1 163 return true;
nuclear@1 164 }
nuclear@1 165
nuclear@1 166 bool SdrProg::load(const char *vsfname, const char *psfname)
nuclear@1 167 {
nuclear@1 168 Shader *sdr;
nuclear@1 169
nuclear@1 170 if(vsfname) {
nuclear@1 171 if(!(sdr = get_shader(vsfname, GL_VERTEX_SHADER))) {
nuclear@1 172 return false;
nuclear@1 173 }
nuclear@1 174 add_shader(sdr);
nuclear@1 175 }
nuclear@1 176
nuclear@1 177 if(psfname) {
nuclear@1 178 if(!(sdr = get_shader(psfname, GL_FRAGMENT_SHADER))) {
nuclear@1 179 return false;
nuclear@1 180 }
nuclear@1 181 add_shader(sdr);
nuclear@1 182 }
nuclear@1 183 return link();
nuclear@1 184 }
nuclear@1 185
nuclear@1 186 int SdrProg::get_uniform_location(const char *name)
nuclear@1 187 {
nuclear@1 188 bind_program(this);
nuclear@1 189 return glGetUniformLocation(prog, name);
nuclear@1 190 }
nuclear@1 191
nuclear@1 192 int SdrProg::get_attribute_location(const char *name)
nuclear@1 193 {
nuclear@1 194 bind_program(this);
nuclear@1 195 return glGetAttribLocation(prog, name);
nuclear@1 196 }
nuclear@1 197
nuclear@1 198 void SdrProg::set_uniform(const char *name, int val)
nuclear@1 199 {
nuclear@1 200 set_uniform(get_uniform_location(name), val);
nuclear@1 201 }
nuclear@1 202
nuclear@1 203 void SdrProg::set_uniform(const char *name, float val)
nuclear@1 204 {
nuclear@1 205 set_uniform(get_uniform_location(name), val);
nuclear@1 206 }
nuclear@1 207
nuclear@1 208 void SdrProg::set_uniform(const char *name, const Vector2 &v)
nuclear@1 209 {
nuclear@1 210 set_uniform(get_uniform_location(name), v);
nuclear@1 211 }
nuclear@1 212
nuclear@1 213 void SdrProg::set_uniform(const char *name, const Vector3 &v)
nuclear@1 214 {
nuclear@1 215 set_uniform(get_uniform_location(name), v);
nuclear@1 216 }
nuclear@1 217
nuclear@1 218 void SdrProg::set_uniform(const char *name, const Vector4 &v)
nuclear@1 219 {
nuclear@1 220 set_uniform(get_uniform_location(name), v);
nuclear@1 221 }
nuclear@1 222
nuclear@1 223 void SdrProg::set_uniform(const char *name, const Matrix4x4 &mat)
nuclear@1 224 {
nuclear@1 225 set_uniform(get_uniform_location(name), mat);
nuclear@1 226 }
nuclear@1 227
nuclear@1 228
nuclear@1 229 void SdrProg::set_uniform(int loc, int val)
nuclear@1 230 {
nuclear@1 231 if(loc >= 0) {
nuclear@1 232 bind_program(this);
nuclear@1 233 glUniform1i(loc, val);
nuclear@1 234 }
nuclear@1 235 }
nuclear@1 236
nuclear@1 237 void SdrProg::set_uniform(int loc, float val)
nuclear@1 238 {
nuclear@1 239 if(loc >= 0) {
nuclear@1 240 bind_program(this);
nuclear@1 241 glUniform1f(loc, val);
nuclear@1 242 }
nuclear@1 243 }
nuclear@1 244
nuclear@1 245 void SdrProg::set_uniform(int loc, const Vector2 &v)
nuclear@1 246 {
nuclear@1 247 if(loc >= 0) {
nuclear@1 248 bind_program(this);
nuclear@1 249 glUniform2f(loc, v.x, v.y);
nuclear@1 250 }
nuclear@1 251 }
nuclear@1 252
nuclear@1 253 void SdrProg::set_uniform(int loc, const Vector3 &v)
nuclear@1 254 {
nuclear@1 255 if(loc >= 0) {
nuclear@1 256 bind_program(this);
nuclear@1 257 glUniform3f(loc, v.x, v.y, v.z);
nuclear@1 258 }
nuclear@1 259 }
nuclear@1 260
nuclear@1 261 void SdrProg::set_uniform(int loc, const Vector4 &v)
nuclear@1 262 {
nuclear@1 263 if(loc >= 0) {
nuclear@1 264 bind_program(this);
nuclear@1 265 glUniform4f(loc, v.x, v.y, v.z, v.w);
nuclear@1 266 }
nuclear@1 267 }
nuclear@1 268
nuclear@1 269 void SdrProg::set_uniform(int loc, const Matrix4x4 &mat)
nuclear@1 270 {
nuclear@1 271 if(loc >= 0) {
nuclear@1 272 bind_program(this);
nuclear@1 273 // loading transpose matrix (3rd arg true)
nuclear@1 274 #ifdef SINGLE_PRECISION_MATH
nuclear@1 275 glUniformMatrix4fv(loc, 1, GL_TRUE, (float*)mat.m);
nuclear@1 276 #else
nuclear@1 277 glUniformMatrix4dv(loc, 1, GL_TRUE, (double*)mat.m);
nuclear@1 278 #endif
nuclear@1 279 }
nuclear@1 280 }
nuclear@1 281
nuclear@1 282 bool bind_program(const SdrProg *prog)
nuclear@1 283 {
nuclear@1 284 if(!prog) {
nuclear@1 285 glUseProgram(0);
nuclear@1 286 return true;
nuclear@1 287 }
nuclear@1 288
nuclear@1 289 if(!((SdrProg*)prog)->link()) {
nuclear@1 290 return false;
nuclear@1 291 }
nuclear@1 292 glUseProgram(prog->prog);
nuclear@1 293 if(glGetError()) {
nuclear@1 294 return false;
nuclear@1 295 }
nuclear@1 296 return true;
nuclear@1 297 }