material.cpp
上传用户:qccn516
上传日期:2013-05-02
资源大小:3382k
文件大小:9k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /* Material
  2.  *
  3.  * Copyright (C) 2003-2004, Alexander Zaprjagaev <frustum@frustum.org>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19. #include "engine.h"
  20. #include "light.h"
  21. #include "texture.h"
  22. #include "shader.h"
  23. #include "parser.h"
  24. #include "material.h"
  25. /*
  26.  */
  27. Material *Material::old_material;
  28. /*
  29.  */
  30. Material::Material(const char *name) {
  31. load(name);
  32. }
  33. Material::~Material() {
  34. }
  35. /*****************************************************************************/
  36. /*                                                                           */
  37. /* load material                                                             */
  38. /*                                                                           */
  39. /*****************************************************************************/
  40. /*
  41.  */
  42. void Material::load(const char *name) {
  43. blend = 0;
  44. alpha_test = 0;
  45. light_shader = NULL;
  46. ambient_shader = NULL;
  47. Parser *parser = new Parser(name);
  48. if(parser->get("blend")) {
  49. blend = 1;
  50. char s[1024];
  51. char d[1024];
  52. sscanf(parser->get("blend"),"%s %s",s,d);
  53. sfactor = getBlendFactor(s);
  54. dfactor = getBlendFactor(d);
  55. }
  56. if(parser->get("alpha_test")) {
  57. alpha_test = 1;
  58. char func[1024];
  59. sscanf(parser->get("alpha_test"),"%s %f",func,&alpha_ref);
  60. alpha_func = getAlphaFunc(func);
  61. }
  62. for(int i = 0; i < Shader::NUM_PARAMETERS; i++) {
  63. parameters[i] = vec4(0,0,0,0);
  64. char buf[1024];
  65. sprintf(buf,"parameter%d",i);
  66. if(parser->get(buf)) sscanf(parser->get(buf),"%f %f %f %f",&parameters[i].x,&parameters[i].y,&parameters[i].z,&parameters[i].w);
  67. }
  68. if(parser->get("light_shader")) {
  69. light_shader = Engine::loadShader(parser->get("light_shader"));
  70. }
  71. if(parser->get("ambient_shader")) {
  72. ambient_shader = Engine::loadShader(parser->get("ambient_shader"));
  73. }
  74. if(parser->get("shader")) {
  75. light_shader = ambient_shader = Engine::loadShader(parser->get("shader"));
  76. }
  77. for(int i = 0; i < Shader::NUM_TEXTURES; i++) {
  78. textures[i] = NULL;
  79. char buf[1024];
  80. sprintf(buf,"texture%d",i);
  81. char *s = parser->get(buf);
  82. if(s) {
  83. GLuint target = Texture::TEXTURE_2D;
  84. int flag = 0;
  85. int format = 0;
  86. int filter = 0;
  87. char name[1024];
  88. char *d = name; // read name
  89. while(*s != '' && !strchr(" tnr",*s)) *d++ = *s++;
  90. *d = '';
  91. d = buf; // read flags
  92. while(*s != '' && *s != 'n' && strchr(" tr",*s)) s++;
  93. while(1) {
  94. if(*s == '' || strchr(" tnr",*s)) {
  95. if(d == buf) break;
  96. *d = '';
  97. d = buf;
  98. while(*s != 'n' && *s != '' && strchr(" tr",*s)) s++;
  99. if(!strcmp(buf,"2D")) target = Texture::TEXTURE_2D;
  100. else if(!strcmp(buf,"RECT")) target = Texture::TEXTURE_RECT;
  101. else if(!strcmp(buf,"CUBE")) target = Texture::TEXTURE_CUBE;
  102. else if(!strcmp(buf,"3D")) target = Texture::TEXTURE_3D;
  103. else if(!strcmp(buf,"LUMINANCE")) format = Texture::LUMINANCE;
  104. else if(!strcmp(buf,"LUMINANCE_ALPHA")) format = Texture::LUMINANCE_ALPHA;
  105. else if(!strcmp(buf,"RGB")) format = Texture::RGB;
  106. else if(!strcmp(buf,"RGBA")) format = Texture::RGBA;
  107. else if(!strcmp(buf,"CLAMP")) flag |= Texture::CLAMP;
  108. else if(!strcmp(buf,"CLAMP_TO_EDGE")) flag |= Texture::CLAMP_TO_EDGE;
  109. else if(!strcmp(buf,"NEAREST")) filter = Texture::NEAREST;
  110. else if(!strcmp(buf,"LINEAR")) filter = Texture::LINEAR;
  111. else if(!strcmp(buf,"NEAREST_MIPMAP_NEAREST")) filter = Texture::NEAREST_MIPMAP_NEAREST;
  112. else if(!strcmp(buf,"LINEAR_MIPMAP_NEAREST")) filter = Texture::LINEAR_MIPMAP_NEAREST;
  113. else if(!strcmp(buf,"LINEAR_MIPMAP_LINEAR")) filter = Texture::LINEAR_MIPMAP_LINEAR;
  114. else if(!strcmp(buf,"ANISOTROPY_1")) flag |= Texture::ANISOTROPY_1;
  115. else if(!strcmp(buf,"ANISOTROPY_2")) flag |= Texture::ANISOTROPY_2;
  116. else if(!strcmp(buf,"ANISOTROPY_4")) flag |= Texture::ANISOTROPY_4;
  117. else if(!strcmp(buf,"ANISOTROPY_8")) flag |= Texture::ANISOTROPY_8;
  118. else if(!strcmp(buf,"ANISOTROPY_16")) flag |= Texture::ANISOTROPY_16;
  119. else fprintf(stderr,"Material::Material(): unknown texture%d flag "%s"n",i,buf);
  120. } else *d++ = *s++;
  121. }
  122. textures[i] = Engine::loadTexture(name,target,flag | (format == 0 ? Texture::RGB : format) | (filter == 0 ? Engine::texture_filter : filter));
  123. } else {
  124. textures[i] = NULL;
  125. }
  126. }
  127. delete parser;
  128. }
  129. /*
  130.  */
  131. GLuint Material::getBlendFactor(const char *factor) {
  132. if(!strcmp(factor,"ZERO")) return GL_ZERO;
  133. if(!strcmp(factor,"ONE")) return GL_ONE;
  134. if(!strcmp(factor,"SRC_COLOR")) return GL_SRC_COLOR;
  135. if(!strcmp(factor,"ONE_MINUS_SRC_COLOR")) return GL_ONE_MINUS_SRC_COLOR;
  136. if(!strcmp(factor,"SRC_ALPHA")) return GL_SRC_ALPHA;
  137. if(!strcmp(factor,"ONE_MINUS_SRC_ALPHA")) return GL_ONE_MINUS_SRC_ALPHA;
  138. if(!strcmp(factor,"ALPHA")) return GL_DST_ALPHA;
  139. if(!strcmp(factor,"ONE_MINUS_DST_ALPHA")) return GL_ONE_MINUS_DST_ALPHA;
  140. if(!strcmp(factor,"DST_COLOR")) return GL_DST_COLOR;
  141. if(!strcmp(factor,"ONE_MINUS_DST_COLOR")) return GL_ONE_MINUS_DST_COLOR;
  142. fprintf(stderr,"Material::getBlendFactor() unknown blend factor "%s"n",factor);
  143. return 0;
  144. }
  145. /*
  146.  */
  147. GLuint Material::getAlphaFunc(const char *func) {
  148. if(!strcmp(func,"NEVER")) return GL_NEVER;
  149. if(!strcmp(func,"LESS")) return GL_LESS;
  150. if(!strcmp(func,"EQUAL")) return GL_EQUAL;
  151. if(!strcmp(func,"LEQUAL")) return GL_LEQUAL;
  152. if(!strcmp(func,"GREATER")) return GL_GREATER;
  153. if(!strcmp(func,"NOTEQUAL")) return GL_NOTEQUAL;
  154. if(!strcmp(func,"GEQUAL")) return GL_GEQUAL;
  155. if(!strcmp(func,"ALWAYS")) return GL_ALWAYS;
  156. fprintf(stderr,"Material::getAlphaFunc() unknown alpha function "%s"n",func);
  157. return 0;
  158. }
  159. /*****************************************************************************/
  160. /*                                                                           */
  161. /* enable/disable/bind                                                       */
  162. /*                                                                           */
  163. /*****************************************************************************/
  164. /*
  165.  */
  166. int Material::enable() {
  167. if(alpha_test) {
  168. if(!old_material || (old_material && old_material->alpha_test == 0)) {
  169. glDisable(GL_CULL_FACE);
  170. glEnable(GL_ALPHA_TEST);
  171. }
  172. } else {
  173. if(old_material && old_material->alpha_test == 1) {
  174. glEnable(GL_CULL_FACE);
  175. glDisable(GL_ALPHA_TEST);
  176. }
  177. }
  178. if(Engine::num_visible_lights) {
  179. if(light_shader) {
  180. if(Engine::current_light && Engine::current_light->material && Engine::current_light->material->light_shader) {
  181. Engine::current_light->material->light_shader->enable();
  182. } else {
  183. light_shader->enable();
  184. }
  185. return 1;
  186. }
  187. } else {
  188. if(ambient_shader) {
  189. ambient_shader->enable();
  190. return 1;
  191. }
  192. }
  193. return 0;
  194. }
  195. /*
  196.  */
  197. void Material::disable() {
  198. if(alpha_test) {
  199. glEnable(GL_CULL_FACE);
  200. glDisable(GL_ALPHA_TEST);
  201. }
  202. if(Shader::old_shader) Shader::old_shader->disable();
  203. glColor4f(1,1,1,1);
  204. old_material = NULL;
  205. }
  206. /*
  207.  */
  208. void Material::bind() {
  209. if(old_material != this) {
  210. if(blend) glBlendFunc(sfactor,dfactor);
  211. if(alpha_test) glAlphaFunc(alpha_func,alpha_ref);
  212. for(int i = 0; i < Shader::NUM_PARAMETERS; i++) Shader::setParameter(i,parameters[i]);
  213. for(int i = 0; i < Shader::NUM_TEXTURES; i++) bindTexture(i,textures[i]);
  214. old_material = this;
  215. }
  216. if(Engine::num_visible_lights) {
  217. if(light_shader) {
  218. if(Engine::current_light && Engine::current_light->material && Engine::current_light->material->light_shader) {
  219. for(int i = 0; i < Shader::NUM_TEXTURES; i++) {
  220. if(Engine::current_light->material->textures[i]) bindTexture(i,Engine::current_light->material->textures[i]);
  221. }
  222. Engine::current_light->material->light_shader->bind();
  223. } else {
  224. light_shader->bind();
  225. }
  226. }
  227. } else {
  228. if(ambient_shader) ambient_shader->bind();
  229. }
  230. }
  231. /*
  232.  */
  233. void Material::bindTexture(int unit,Texture *texture) {
  234. if(Engine::num_visible_lights) {
  235. if(Engine::current_light && Engine::current_light->material && Engine::current_light->material->light_shader) {
  236. Engine::current_light->material->light_shader->bindTexture(unit,texture);
  237. } else if(light_shader) {
  238. light_shader->bindTexture(unit,texture);
  239. }
  240. } else {
  241. if(ambient_shader) ambient_shader->bindTexture(unit,texture);
  242. }
  243. }