00001
00007 #include "Renderer.h"
00008
00009
00010
00011
00012 Renderer::Renderer() {
00013 lockFlags = 0xFFFFFFFF;
00014 }
00015
00016
00017
00018
00019 Renderer::~Renderer() {
00020 }
00021
00022
00023
00024
00025 void Renderer::lock(const unsigned int flag) {
00026 lockFlags &= ~flag;
00027 }
00028
00029
00030
00031
00032 void Renderer::unlock(const unsigned int flag) {
00033 lockFlags |= flag;
00034 }
00035
00036
00037
00038
00039 void Renderer::apply() {
00040 if (lockFlags & LF_SHADING) changeShader(selectedShader);
00041
00042 assignNamedTextures();
00043
00044 for (int tex = 0; tex < maxTextures; tex++) {
00045 changeTextureUnit(tex);
00046 changeTexture(selectedTextures[tex]);
00047 }
00048
00049 changeBlending(selectedBlendSrc, selectedBlendDest, selectedBlendMode);
00050 changeDepthFunc(selectedDepthFunc);
00051 changeMask(selectedMask);
00052
00053 reset();
00054 }
00055
00056
00057
00058
00059 void Renderer::resetToDefaults() {
00060 for (int tex = 0; tex < maxTextures; tex++) {
00061 currentTextures[tex] = TEXTURE_NONE;
00062 }
00063
00064 currentTextureUnit = 0;
00065
00066 currentBlendSrc = BLENDING_NONE;
00067 currentBlendDest = BLENDING_NONE;
00068 currentBlendMode = BLENDMODE_ADD;
00069 currentDepthFunc = LEQUAL;
00070 currentMask = ALL;
00071
00072 currentShader = SHADER_NONE;
00073
00074 reset();
00075 }
00076
00077
00078
00079
00080 void Renderer::reset() {
00081 for (int tex = 0; tex < maxTextures; tex++) {
00082 selectedTextures[tex] = TEXTURE_NONE;
00083 }
00084
00085 nNamedTextures = 0;
00086
00087 selectedBlendSrc = BLENDING_NONE;
00088 selectedBlendDest = BLENDING_NONE;
00089 selectedBlendMode = BLENDMODE_ADD;
00090 selectedDepthFunc = LEQUAL;
00091 selectedMask = ALL;
00092
00093 selectedShader = SHADER_NONE;
00094 }
00095
00096
00097
00098
00099 TextureID Renderer::addTexture(const char *filename, unsigned int flags) {
00100 Image *image = new Image();
00101
00102 if (image->loadImage(filename)) {
00103 return addTexture(image, flags);
00104 }
00105
00106 delete image;
00107 return TEXTURE_NONE;
00108 }
00109
00110
00111
00112
00113 TextureID Renderer::addTexture(Image *image, unsigned int flags) {
00114 Texture texture;
00115
00116 if (flags & TEXTURE_NORMALMAP) {
00117 image->toGrayScale();
00118 image->toNormalMap(true, (flags & TEXTURE_HEIGHTMAP) != 0);
00119 }
00120
00121 texture.clampS = ((flags & TEXTURE_CLAMP_S) != 0);
00122 texture.clampT = ((flags & TEXTURE_CLAMP_T) != 0);
00123
00124 texture.textureKind = TEXTURE_2D;
00125 texture.height = image->getHeight();
00126 texture.width = image->getWidth();
00127 texture.depth = 1;
00128 texture.images[0] = image;
00129 texture.format = image->getFormat();
00130
00131 if (createTexture(texture))
00132 return insertTexture(texture);
00133
00134 delete image;
00135 return TEXTURE_NONE;
00136 }
00137
00138
00139
00140
00141 TextureID Renderer::addCubemap(const char *fNegX, const char *fPosX, const char *fNegY, const char *fPosY, const char *fNegZ, const char *fPosZ) {
00142 const char *filenames[] = { fPosX, fNegX, fNegY, fPosY, fPosZ, fNegZ };
00143
00144 Image *images[6];
00145
00146 for (int i=0; i<6; i++) {
00147 images[i] = new Image();
00148
00149 if (!images[i]->loadImage(filenames[i])) {
00150 do {
00151 delete images[i];
00152 } while (i--);
00153
00154 LOG_ERROR(("Unable to load cubemap images"));
00155 return TEXTURE_NONE;
00156 }
00157 }
00158
00159 return addCubemap(images);
00160 }
00161
00162
00163
00164
00165 TextureID Renderer::addCubemap(Image *images[6]) {
00166 Texture texture;
00167
00168 texture.textureKind = TEXTURE_CUBEMAP;
00169 texture.width = images[0]->getWidth();
00170 texture.height = images[0]->getHeight();
00171 texture.depth = 1;
00172 texture.format = images[0]->getFormat();
00173
00174 memcpy(texture.images, images, 6*sizeof(Image *));
00175
00176 if (createTexture(texture)) {
00177 LOG_SUCCESS(("Cubemap created"));
00178 return insertTexture(texture);
00179 }
00180
00181 LOG_ERROR(("Unable to create cubemap"));
00182 return TEXTURE_NONE;
00183 }
00184
00185
00186
00187
00188 TextureID Renderer::insertTexture(Texture &texture) {
00189 int len = textures.getCount();
00190 for (unsigned int i = 0; i < len; i++) {
00191 if (textures[i].textureID == UNDEFINED) {
00192 textures[i] = texture;
00193 break;
00194 }
00195 }
00196
00197 if (i == len) i = textures.add(texture);
00198
00199 texture.images[0]->clear();
00200
00201 return i;
00202 }
00203
00204
00205
00206
00207 void Renderer::deleteTexture(const int i) {
00208 if (textures[i].textureID != UNDEFINED) {
00209 removeTexture(textures[i]);
00210
00211 switch (textures[i].textureKind) {
00212 case TEXTURE_2D:
00213 delete textures[i].images[0];
00214 break;
00215 case TEXTURE_CUBEMAP:
00216 for (int n=0; n<6; n++) delete textures[i].images[n];
00217 break;
00218 }
00219
00220 textures[i].textureID = UNDEFINED;
00221
00222 LOG_SUCCESS(("Texture (%d) removed", i));
00223 return;
00224 }
00225
00226 LOG_ERROR(("Unable to unload texture (%d)", i));
00227 }
00228
00229
00230
00231
00232 ShaderID Renderer::addShader(const char *fileName, const char *extraDefines) {
00233 FILE *file = fopen(fileName, "rb");
00234 if (file == NULL) {
00235
00236 }
00237 else {
00238 fseek(file, 0, SEEK_END);
00239 int length = ftell(file);
00240 fseek(file, 0, SEEK_SET);
00241
00242 char *shaderText = new char[length+1];
00243 fread(shaderText, length, 1, file);
00244 fclose(file);
00245 shaderText[length] = '\0';
00246
00247 char *vertexShader = strstr(shaderText, "[Vertex shader]");
00248 char *fragmentShader = strstr(shaderText, "[Fragment shader]");
00249
00250 if (vertexShader != NULL) {
00251 *vertexShader = '\0';
00252 vertexShader += 15;
00253 }
00254
00255 if (fragmentShader != NULL) {
00256 *fragmentShader = '\0';
00257 fragmentShader += 17;
00258 }
00259
00260 String vShaderString, fShaderString;
00261 if (vertexShader != NULL) {
00262 int n = 0;
00263 char *str = shaderText;
00264 while (str < vertexShader) {
00265 if (*str == '\n') n++;
00266 str++;
00267 }
00268 if (extraDefines) vShaderString = extraDefines;
00269 vShaderString += vertexShader;
00270 }
00271
00272 if (fragmentShader != NULL) {
00273 int n = 0;
00274 char *str = shaderText;
00275 while (str < fragmentShader) {
00276 if (*str == '\n') n++;
00277 str++;
00278 }
00279 if (extraDefines) fShaderString = extraDefines;
00280 fShaderString += fragmentShader;
00281 }
00282
00283 Shader shader;
00284 bool res = createShader(shader, (vertexShader ? (const char *)vShaderString : NULL), (fragmentShader ? (const char *)fShaderString : NULL));
00285
00286 if (res) {
00287 LOG_SUCCESS(("Shader << %s >> loaded", fileName));
00288 return insertShader(shader);
00289 }
00290 }
00291
00292 LOG_ERROR(("Could not load shader << %s >>", fileName));
00293 return SHADER_NONE;
00294 }
00295
00296
00297
00298
00299 ShaderID Renderer::insertShader(Shader &shader) {
00300 int i, len = shaders.getCount();
00301 for (i=0; i<len; i++) {
00302 if (shaders[i].programObj == UNDEFINED) {
00303 shaders[i] = shader;
00304 return i;
00305 }
00306 }
00307
00308 return shaders.add(shader);
00309 }
00310
00311
00312
00313
00314 void Renderer::deleteShader(const int i) {
00315 if (shaders[i].programObj != UNDEFINED) {
00316 removeShader(shaders[i]);
00317 shaders[i].programObj = UNDEFINED;
00318 LOG_SUCCESS(("Shader (%d) removed", i));
00319 }
00320 }
00321
00322
00323
00324
00325 ShaderID Renderer::addFragmentShader(unsigned int type, char *filename) {
00326 FragmentShader fragmentShader;
00327 fragmentShader.type = type;
00328
00329 createFragmentShader(fragmentShader);
00330
00331 if (filename != NULL) {
00332 FILE *file = fopen(filename, "rb");
00333
00334 if (file == NULL) return SHADER_NONE;
00335
00336 fseek(file, 0, SEEK_END);
00337 fragmentShader.length = ftell(file);
00338 fseek(file, 0, SEEK_SET);
00339
00340 fragmentShader.program = new char[fragmentShader.length];
00341 fread(fragmentShader.program, fragmentShader.length, 1, file);
00342 fclose(file);
00343
00344 uploadFragmentShader(fragmentShader);
00345 delete fragmentShader.program;
00346
00347 LOG_SUCCESS(("Fragment shader << %s >> added", filename));
00348 }
00349 else {
00350 LOG_SUCCESS(("Unable to find fragment shader file << %s >>", filename));
00351 }
00352
00353 return insertFragmentShader(fragmentShader);
00354 }
00355
00356
00357
00358
00359 ShaderID Renderer::addFragmentShader(unsigned int type, unsigned int shaderID) {
00360 FragmentShader fragmentShader;
00361 fragmentShader.type = type;
00362 fragmentShader.shaderID = shaderID;
00363
00364 return insertFragmentShader(fragmentShader);
00365 }
00366
00367
00368
00369
00370 ShaderID Renderer::addVertexShader(char *filename) {
00371 VertexShader vertexShader;
00372
00373 createVertexShader(vertexShader);
00374
00375 FILE *file;
00376 if ((file = fopen(filename, "rb")) != NULL) {
00377 fseek(file, 0, SEEK_END);
00378 vertexShader.length = ftell(file);
00379 fseek(file, 0, SEEK_SET);
00380
00381 vertexShader.program = new char[vertexShader.length];
00382 fread(vertexShader.program, vertexShader.length, 1, file);
00383 fclose(file);
00384
00385 uploadVertexShader(vertexShader);
00386 delete vertexShader.program;
00387 return insertVertexShader(vertexShader);
00388 }
00389
00390 return SHADER_NONE;
00391 }
00392
00393
00394
00395
00396 ShaderID Renderer::insertFragmentShader(FragmentShader &fragmentShader) {
00397 int i, len = fragmentShaders.getCount();
00398 for (i = 0; i<len; i++) {
00399 if (fragmentShaders[i].shaderID == UNDEFINED) {
00400 fragmentShaders[i] = fragmentShader;
00401 return i;
00402 }
00403 }
00404
00405 return fragmentShaders.add(fragmentShader);
00406 }
00407
00408
00409
00410
00411 void Renderer::deleteFragmentShader(const int index) {
00412 if (fragmentShaders[index].shaderID != UNDEFINED) {
00413 removeFragmentShader(fragmentShaders[index]);
00414 fragmentShaders[index].shaderID = UNDEFINED;
00415 }
00416 }
00417
00418
00419
00420
00421 ShaderID Renderer::insertVertexShader(VertexShader &vertexShader) {
00422 int i, len = vertexShaders.getCount();
00423 for (i=0; i<len; i++) {
00424 if (vertexShaders[i].shaderID == UNDEFINED) {
00425 vertexShaders[i] = vertexShader;
00426 return i;
00427 }
00428 }
00429
00430 return vertexShaders.add(vertexShader);
00431 }
00432
00433
00434
00435
00436 void Renderer::deleteVertexShader(const int index) {
00437 if (vertexShaders[index].shaderID == UNDEFINED) {
00438 removeVertexShader(vertexShaders[index]);
00439 vertexShaders[index].shaderID = UNDEFINED;
00440 }
00441 }