00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "shaderGenerator.h"
00020 #include "renderState.h"
00021 #include "shaderAttrib.h"
00022 #include "auxBitplaneAttrib.h"
00023 #include "alphaTestAttrib.h"
00024 #include "colorBlendAttrib.h"
00025 #include "transparencyAttrib.h"
00026 #include "textureAttrib.h"
00027 #include "colorAttrib.h"
00028 #include "lightAttrib.h"
00029 #include "materialAttrib.h"
00030 #include "lightRampAttrib.h"
00031 #include "texMatrixAttrib.h"
00032 #include "texGenAttrib.h"
00033 #include "colorScaleAttrib.h"
00034 #include "fogAttrib.h"
00035 #include "texture.h"
00036 #include "ambientLight.h"
00037 #include "directionalLight.h"
00038 #include "pointLight.h"
00039 #include "spotlight.h"
00040 #include "lightLensNode.h"
00041 #include "lvector4.h"
00042
00043 TypeHandle ShaderGenerator::_type_handle;
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 ShaderGenerator::
00054 ShaderGenerator(PT(GraphicsStateGuardianBase) gsg, PT(GraphicsOutputBase) host) :
00055 _gsg (gsg), _host (host) {
00056 }
00057
00058
00059
00060
00061
00062
00063 ShaderGenerator::
00064 ~ShaderGenerator() {
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074 void ShaderGenerator::
00075 reset_register_allocator() {
00076 _vtregs_used = 0;
00077 _vcregs_used = 0;
00078 _ftregs_used = 0;
00079 _fcregs_used = 0;
00080 }
00081
00082
00083
00084
00085
00086
00087 INLINE char *ShaderGenerator::
00088 alloc_vreg() {
00089 switch (_vtregs_used) {
00090 case 0: _vtregs_used += 1; return (char*)"TEXCOORD0";
00091 case 1: _vtregs_used += 1; return (char*)"TEXCOORD1";
00092 case 2: _vtregs_used += 1; return (char*)"TEXCOORD2";
00093 case 3: _vtregs_used += 1; return (char*)"TEXCOORD3";
00094 case 4: _vtregs_used += 1; return (char*)"TEXCOORD4";
00095 case 5: _vtregs_used += 1; return (char*)"TEXCOORD5";
00096 case 6: _vtregs_used += 1; return (char*)"TEXCOORD6";
00097 case 7: _vtregs_used += 1; return (char*)"TEXCOORD7";
00098 case 8: _vtregs_used += 1; return (char*)"TEXCOORD8";
00099 case 9: _vtregs_used += 1; return (char*)"TEXCOORD9";
00100 case 10: _vtregs_used += 1; return (char*)"TEXCOORD10";
00101 case 11: _vtregs_used += 1; return (char*)"TEXCOORD11";
00102 case 12: _vtregs_used += 1; return (char*)"TEXCOORD12";
00103 case 13: _vtregs_used += 1; return (char*)"TEXCOORD13";
00104 case 14: _vtregs_used += 1; return (char*)"TEXCOORD14";
00105 case 15: _vtregs_used += 1; return (char*)"TEXCOORD15";
00106 }
00107 switch (_vcregs_used) {
00108 case 0: _vcregs_used += 1; return (char*)"COLOR0";
00109 case 1: _vcregs_used += 1; return (char*)"COLOR1";
00110 case 2: _vcregs_used += 1; return (char*)"COLOR2";
00111 case 3: _vcregs_used += 1; return (char*)"COLOR3";
00112 case 4: _vcregs_used += 1; return (char*)"COLOR4";
00113 case 5: _vcregs_used += 1; return (char*)"COLOR5";
00114 case 6: _vcregs_used += 1; return (char*)"COLOR6";
00115 case 7: _vcregs_used += 1; return (char*)"COLOR7";
00116 case 8: _vcregs_used += 1; return (char*)"COLOR8";
00117 case 9: _vcregs_used += 1; return (char*)"COLOR9";
00118 case 10: _vcregs_used += 1; return (char*)"COLOR10";
00119 case 11: _vcregs_used += 1; return (char*)"COLOR11";
00120 case 12: _vcregs_used += 1; return (char*)"COLOR12";
00121 case 13: _vcregs_used += 1; return (char*)"COLOR13";
00122 case 14: _vcregs_used += 1; return (char*)"COLOR14";
00123 case 15: _vcregs_used += 1; return (char*)"COLOR15";
00124 }
00125 return (char*)"UNKNOWN";
00126 }
00127
00128
00129
00130
00131
00132
00133 INLINE char *ShaderGenerator::
00134 alloc_freg() {
00135 switch (_ftregs_used) {
00136 case 0: _ftregs_used += 1; return (char*)"TEXCOORD0";
00137 case 1: _ftregs_used += 1; return (char*)"TEXCOORD1";
00138 case 2: _ftregs_used += 1; return (char*)"TEXCOORD2";
00139 case 3: _ftregs_used += 1; return (char*)"TEXCOORD3";
00140 case 4: _ftregs_used += 1; return (char*)"TEXCOORD4";
00141 case 5: _ftregs_used += 1; return (char*)"TEXCOORD5";
00142 case 6: _ftregs_used += 1; return (char*)"TEXCOORD6";
00143 case 7: _ftregs_used += 1; return (char*)"TEXCOORD7";
00144 case 8: _ftregs_used += 1; return (char*)"TEXCOORD8";
00145 case 9: _ftregs_used += 1; return (char*)"TEXCOORD9";
00146 case 10: _ftregs_used += 1; return (char*)"TEXCOORD10";
00147 case 11: _ftregs_used += 1; return (char*)"TEXCOORD11";
00148 case 12: _ftregs_used += 1; return (char*)"TEXCOORD12";
00149 case 13: _ftregs_used += 1; return (char*)"TEXCOORD13";
00150 case 14: _ftregs_used += 1; return (char*)"TEXCOORD14";
00151 case 15: _ftregs_used += 1; return (char*)"TEXCOORD15";
00152 }
00153 switch (_fcregs_used) {
00154 case 0: _fcregs_used += 1; return (char*)"COLOR0";
00155 case 1: _fcregs_used += 1; return (char*)"COLOR1";
00156 case 2: _fcregs_used += 1; return (char*)"COLOR2";
00157 case 3: _fcregs_used += 1; return (char*)"COLOR3";
00158 case 4: _fcregs_used += 1; return (char*)"COLOR4";
00159 case 5: _fcregs_used += 1; return (char*)"COLOR5";
00160 case 6: _fcregs_used += 1; return (char*)"COLOR6";
00161 case 7: _fcregs_used += 1; return (char*)"COLOR7";
00162 case 8: _fcregs_used += 1; return (char*)"COLOR8";
00163 case 9: _fcregs_used += 1; return (char*)"COLOR9";
00164 case 10: _fcregs_used += 1; return (char*)"COLOR10";
00165 case 11: _fcregs_used += 1; return (char*)"COLOR11";
00166 case 12: _fcregs_used += 1; return (char*)"COLOR12";
00167 case 13: _fcregs_used += 1; return (char*)"COLOR13";
00168 case 14: _fcregs_used += 1; return (char*)"COLOR14";
00169 case 15: _fcregs_used += 1; return (char*)"COLOR15";
00170 }
00171 return (char*)"UNKNOWN";
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181 void ShaderGenerator::
00182 analyze_renderstate(const RenderState *rs) {
00183 clear_analysis();
00184
00185
00186 _state = rs;
00187 const AuxBitplaneAttrib *aux_bitplane = DCAST(AuxBitplaneAttrib, rs->get_attrib_def(AuxBitplaneAttrib::get_class_slot()));
00188 int outputs = aux_bitplane->get_outputs();
00189
00190
00191
00192 const AlphaTestAttrib *alpha_test = DCAST(AlphaTestAttrib, rs->get_attrib_def(AlphaTestAttrib::get_class_slot()));
00193 if ((alpha_test->get_mode() != RenderAttrib::M_none)&&
00194 (alpha_test->get_mode() != RenderAttrib::M_always)) {
00195 _have_alpha_test = true;
00196 }
00197 const ColorBlendAttrib *color_blend = DCAST(ColorBlendAttrib, rs->get_attrib_def(ColorBlendAttrib::get_class_slot()));
00198 if (color_blend->get_mode() != ColorBlendAttrib::M_none) {
00199 _have_alpha_blend = true;
00200 }
00201 const TransparencyAttrib *transparency = DCAST(TransparencyAttrib, rs->get_attrib_def(TransparencyAttrib::get_class_slot()));
00202 if ((transparency->get_mode() == TransparencyAttrib::M_alpha)||
00203 (transparency->get_mode() == TransparencyAttrib::M_dual)) {
00204 _have_alpha_blend = true;
00205 }
00206
00207
00208
00209 if (outputs & AuxBitplaneAttrib::ABO_glow) {
00210 if (_have_alpha_blend) {
00211 _calc_primary_alpha = true;
00212 _out_primary_glow = false;
00213 _disable_alpha_write = true;
00214 } else if (_have_alpha_test) {
00215 _calc_primary_alpha = true;
00216 _out_primary_glow = true;
00217 _subsume_alpha_test = true;
00218 } else {
00219 _calc_primary_alpha = false;
00220 _out_primary_glow = true;
00221 }
00222 } else {
00223 if (_have_alpha_blend || _have_alpha_test) {
00224 _calc_primary_alpha = true;
00225 }
00226 }
00227
00228
00229
00230 _out_aux_normal = (outputs & AuxBitplaneAttrib::ABO_aux_normal) ? true:false;
00231 _out_aux_glow = (outputs & AuxBitplaneAttrib::ABO_aux_glow) ? true:false;
00232 _out_aux_any = (_out_aux_normal || _out_aux_glow);
00233
00234 if (_out_aux_normal) {
00235 _need_eye_normal = true;
00236 }
00237
00238
00239
00240 const TextureAttrib *texture = DCAST(TextureAttrib, rs->get_attrib_def(TextureAttrib::get_class_slot()));
00241 _num_textures = texture->get_num_on_stages();
00242
00243
00244
00245 const ColorAttrib *color = DCAST(ColorAttrib, rs->get_attrib_def(ColorAttrib::get_class_slot()));
00246 if (color->get_color_type() == ColorAttrib::T_vertex) {
00247 _vertex_colors = true;
00248 } else if (color->get_color_type() == ColorAttrib::T_flat) {
00249 _flat_colors = true;
00250 }
00251
00252
00253
00254 _shadows = false;
00255 const LightAttrib *la = DCAST(LightAttrib, rs->get_attrib_def(LightAttrib::get_class_slot()));
00256 for (int i=0; i<la->get_num_on_lights(); i++) {
00257 NodePath light = la->get_on_light(i);
00258 nassertv(!light.is_empty());
00259 PandaNode *light_obj = light.node();
00260 nassertv(light_obj != (PandaNode *)NULL);
00261
00262 if (light_obj->get_type() == AmbientLight::get_class_type()) {
00263 _alights_np.push_back(light);
00264 _alights.push_back((AmbientLight*)light_obj);
00265 }
00266 else if (light_obj->get_type() == DirectionalLight::get_class_type()) {
00267 _dlights_np.push_back(light);
00268 _dlights.push_back((DirectionalLight*)light_obj);
00269 if (DCAST(LightLensNode, light_obj)->is_shadow_caster()) {
00270 _shadows = true;
00271 }
00272 }
00273 else if (light_obj->get_type() == PointLight::get_class_type()) {
00274 _plights_np.push_back(light);
00275 _plights.push_back((PointLight*)light_obj);
00276 }
00277 else if (light_obj->get_type() == Spotlight::get_class_type()) {
00278 _slights_np.push_back(light);
00279 _slights.push_back((Spotlight*)light_obj);
00280 if (DCAST(LightLensNode, light_obj)->is_shadow_caster()) {
00281 _shadows = true;
00282 }
00283 }
00284 }
00285
00286
00287
00288
00289 const TexGenAttrib *tex_gen = DCAST(TexGenAttrib, rs->get_attrib_def(TexGenAttrib::get_class_slot()));
00290 for (int i=0; i<_num_textures; i++) {
00291 TextureStage *stage = texture->get_on_stage(i);
00292 TextureStage::Mode mode = stage->get_mode();
00293 if ((mode == TextureStage::M_normal)||
00294 (mode == TextureStage::M_normal_height)||
00295 (mode == TextureStage::M_normal_gloss)) {
00296 _map_index_normal = i;
00297 }
00298 if ((mode == TextureStage::M_height)||(mode == TextureStage::M_normal_height)) {
00299 _map_index_height = i;
00300 }
00301 if ((mode == TextureStage::M_glow)||(mode == TextureStage::M_modulate_glow)) {
00302 _map_index_glow = i;
00303 }
00304 if ((mode == TextureStage::M_gloss)||
00305 (mode == TextureStage::M_modulate_gloss)||
00306 (mode == TextureStage::M_normal_gloss)) {
00307 _map_index_gloss = i;
00308 }
00309 if (mode == TextureStage::M_height) {
00310 _map_height_in_alpha = false;
00311 }
00312 if (mode == TextureStage::M_normal_height) {
00313 _map_height_in_alpha = true;
00314 }
00315 if (tex_gen->has_stage(stage)) {
00316 switch (tex_gen->get_mode(stage)) {
00317 case TexGenAttrib::M_world_position:
00318 _need_world_position = true;
00319 break;
00320 case TexGenAttrib::M_world_normal:
00321 _need_world_normal = true;
00322 break;
00323 case TexGenAttrib::M_eye_position:
00324 _need_eye_position = true;
00325 break;
00326 case TexGenAttrib::M_eye_normal:
00327 _need_eye_normal = true;
00328 break;
00329 default:
00330 break;
00331 }
00332 }
00333 }
00334
00335
00336
00337 if (la->get_num_on_lights() > 0) {
00338 _lighting = true;
00339 _need_eye_position = true;
00340 _need_eye_normal = true;
00341 }
00342
00343
00344
00345 const MaterialAttrib *material = DCAST(MaterialAttrib, rs->get_attrib_def(MaterialAttrib::get_class_slot()));
00346
00347 if (!material->is_off()) {
00348 _material = material->get_material();
00349 } else {
00350 _material = Material::get_default();
00351 }
00352
00353
00354
00355 if (_lighting && (_alights.size() > 0)) {
00356 if (_material->has_ambient()) {
00357 LColor a = _material->get_ambient();
00358 if ((a[0]!=0.0)||(a[1]!=0.0)||(a[2]!=0.0)) {
00359 _have_ambient = true;
00360 }
00361 } else {
00362 _have_ambient = true;
00363 }
00364 }
00365
00366 if (_lighting && (_dlights.size() + _plights.size() + _slights.size())) {
00367 if (_material->has_diffuse()) {
00368 LColor d = _material->get_diffuse();
00369 if ((d[0]!=0.0)||(d[1]!=0.0)||(d[2]!=0.0)) {
00370 _have_diffuse = true;
00371 }
00372 } else {
00373 _have_diffuse = true;
00374 }
00375 }
00376
00377 if (_lighting && (_material->has_emission())) {
00378 LColor e = _material->get_emission();
00379 if ((e[0]!=0.0)||(e[1]!=0.0)||(e[2]!=0.0)) {
00380 _have_emission = true;
00381 }
00382 }
00383
00384 if (_lighting && (_dlights.size() + _plights.size() + _slights.size())) {
00385 if (_material->has_specular()) {
00386 LColor s = _material->get_specular();
00387 if ((s[0]!=0.0)||(s[1]!=0.0)||(s[2]!=0.0)) {
00388 _have_specular = true;
00389 }
00390 } else if (_map_index_gloss >= 0) {
00391 _have_specular = true;
00392 }
00393 }
00394
00395
00396
00397 if (_have_ambient && _have_diffuse) {
00398 if (_material->has_ambient()) {
00399 if (_material->has_diffuse()) {
00400 _separate_ambient_diffuse = _material->get_ambient() != _material->get_diffuse();
00401 } else {
00402 _separate_ambient_diffuse = true;
00403 }
00404 } else {
00405 if (_material->has_diffuse()) {
00406 _separate_ambient_diffuse = true;
00407 } else {
00408 _separate_ambient_diffuse = false;
00409 }
00410 }
00411 }
00412
00413 const LightRampAttrib *light_ramp = DCAST(LightRampAttrib, rs->get_attrib_def(LightRampAttrib::get_class_slot()));
00414 if (_lighting &&
00415 (light_ramp->get_mode() != LightRampAttrib::LRT_identity)) {
00416 _separate_ambient_diffuse = true;
00417 }
00418
00419
00420
00421
00422 _use_shadow_filter = _gsg->get_supports_shadow_filter();
00423
00424
00425
00426 _need_material_props =
00427 (_have_ambient && (_material->has_ambient()))||
00428 (_have_diffuse && (_material->has_diffuse()))||
00429 (_have_emission && (_material->has_emission()))||
00430 (_have_specular && (_material->has_specular()));
00431
00432
00433
00434 const ClipPlaneAttrib *clip_plane = DCAST(ClipPlaneAttrib, rs->get_attrib_def(ClipPlaneAttrib::get_class_slot()));
00435 _num_clip_planes = clip_plane->get_num_on_planes();
00436 if (_num_clip_planes > 0) {
00437 _need_world_position = true;
00438 }
00439
00440 const ShaderAttrib *shader_attrib = DCAST(ShaderAttrib, rs->get_attrib_def(ShaderAttrib::get_class_slot()));
00441 if (shader_attrib->auto_shader()) {
00442 _auto_normal_on = shader_attrib->auto_normal_on();
00443 _auto_glow_on = shader_attrib->auto_glow_on();
00444 _auto_gloss_on = shader_attrib->auto_gloss_on();
00445 _auto_ramp_on = shader_attrib->auto_ramp_on();
00446 _auto_shadow_on = shader_attrib->auto_shadow_on();
00447 }
00448
00449
00450 const FogAttrib *fog = DCAST(FogAttrib, rs->get_attrib_def(FogAttrib::get_class_slot()));
00451 if (!fog->is_off()) {
00452 _fog = true;
00453 }
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463 void ShaderGenerator::
00464 clear_analysis() {
00465 _vertex_colors = false;
00466 _flat_colors = false;
00467 _lighting = false;
00468 _shadows = false;
00469 _fog = false;
00470 _have_ambient = false;
00471 _have_diffuse = false;
00472 _have_emission = false;
00473 _have_specular = false;
00474 _separate_ambient_diffuse = false;
00475 _map_index_normal = -1;
00476 _map_index_glow = -1;
00477 _map_index_gloss = -1;
00478 _map_index_height = -1;
00479 _map_height_in_alpha = false;
00480 _calc_primary_alpha = false;
00481 _have_alpha_test = false;
00482 _have_alpha_blend = false;
00483 _subsume_alpha_test = false;
00484 _disable_alpha_write = false;
00485 _num_clip_planes = 0;
00486 _use_shadow_filter = false;
00487 _out_primary_glow = false;
00488 _out_aux_normal = false;
00489 _out_aux_glow = false;
00490 _out_aux_any = false;
00491 _material = (Material*)NULL;
00492 _need_material_props = false;
00493 _need_world_position = false;
00494 _need_world_normal = false;
00495 _need_eye_position = false;
00496 _need_eye_normal = false;
00497 _auto_normal_on = false;
00498 _auto_glow_on = false;
00499 _auto_gloss_on = false;
00500 _auto_ramp_on = false;
00501 _auto_shadow_on = false;
00502
00503 _alights.clear();
00504 _dlights.clear();
00505 _plights.clear();
00506 _slights.clear();
00507 _alights_np.clear();
00508 _dlights_np.clear();
00509 _plights_np.clear();
00510 _slights_np.clear();
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520 CPT(RenderAttrib) ShaderGenerator::
00521 create_shader_attrib(const string &txt) {
00522 PT(Shader) shader = Shader::make(txt);
00523 CPT(RenderAttrib) shattr = ShaderAttrib::make();
00524 shattr=DCAST(ShaderAttrib, shattr)->set_shader(shader);
00525 if (_lighting) {
00526 for (int i=0; i<(int)_alights.size(); i++) {
00527 shattr=DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("alight", i), _alights_np[i]);
00528 }
00529 for (int i=0; i<(int)_dlights.size(); i++) {
00530 shattr=DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("dlight", i), _dlights_np[i]);
00531 if (_shadows && _dlights[i]->_shadow_caster) {
00532 PT(Texture) tex = update_shadow_buffer(_dlights_np[i]);
00533 if (tex == NULL) {
00534 pgraph_cat.error() << "Failed to create shadow buffer for DirectionalLight '" << _dlights[i]->get_name() << "'!\n";
00535 }
00536 shattr=DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("dlighttex", i), tex);
00537 } else {
00538 _dlights[i]->clear_shadow_buffers();
00539 }
00540 }
00541 for (int i=0; i<(int)_plights.size(); i++) {
00542 shattr=DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("plight", i), _plights_np[i]);
00543 }
00544 for (int i=0; i<(int)_slights.size(); i++) {
00545 shattr=DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("slight", i), _slights_np[i]);
00546 if (_shadows && _slights[i]->_shadow_caster) {
00547 PT(Texture) tex = update_shadow_buffer(_slights_np[i]);
00548 if (tex == NULL) {
00549 pgraph_cat.error() << "Failed to create shadow buffer for Spotlight '" << _slights[i]->get_name() << "'!\n";
00550 }
00551 shattr=DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("slighttex", i), tex);
00552 } else {
00553 _slights[i]->clear_shadow_buffers();
00554 }
00555 }
00556 }
00557 return shattr;
00558 }
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 PT(Texture) ShaderGenerator::
00569 update_shadow_buffer(NodePath light_np) {
00570
00571 nassertr(light_np.node()->is_of_type(DirectionalLight::get_class_type()) ||
00572 light_np.node()->is_of_type(Spotlight::get_class_type()), NULL);
00573 PT(LightLensNode) light = DCAST(LightLensNode, light_np.node());
00574 if (light == NULL || !light->_shadow_caster) {
00575 return NULL;
00576 }
00577
00578
00579 PT(Texture) tex;
00580 if (light->_sbuffers.count(_gsg) == 0) {
00581
00582 tex = _gsg->make_shadow_buffer(light_np, _host);
00583 } else {
00584
00585 tex = light->_sbuffers[_gsg]->get_texture();
00586 }
00587 nassertr(tex != NULL, NULL);
00588
00589 return tex;
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 CPT(RenderAttrib) ShaderGenerator::
00626 synthesize_shader(const RenderState *rs) {
00627 analyze_renderstate(rs);
00628 reset_register_allocator();
00629
00630 if (pgraph_cat.is_debug()) {
00631 pgraph_cat.debug()
00632 << "Generating shader for render state " << *rs << "\n";
00633 }
00634
00635
00636
00637 char *normal_vreg = 0;
00638 char *ntangent_vreg = 0;
00639 char *ntangent_freg = 0;
00640 char *nbinormal_vreg = 0;
00641 char *nbinormal_freg = 0;
00642 char *htangent_vreg = 0;
00643 char *hbinormal_vreg = 0;
00644 pvector<char *> texcoord_vreg;
00645 pvector<char *> texcoord_freg;
00646 pvector<char *> dlightcoord_freg;
00647 pvector<char *> slightcoord_freg;
00648 char *world_position_freg = 0;
00649 char *world_normal_freg = 0;
00650 char *eye_position_freg = 0;
00651 char *eye_normal_freg = 0;
00652 char *hpos_freg = 0;
00653
00654 if (_vertex_colors) {
00655 _vcregs_used = 1;
00656 _fcregs_used = 1;
00657 }
00658
00659
00660
00661 ostringstream text;
00662
00663 text << "//Cg\n";
00664
00665 text << "/* Generated shader for render state " << rs << ":\n";
00666 rs->write(text, 2);
00667 text << "*/\n";
00668
00669 text << "void vshader(\n";
00670 const TextureAttrib *texture = DCAST(TextureAttrib, rs->get_attrib_def(TextureAttrib::get_class_slot()));
00671 const TexGenAttrib *tex_gen = DCAST(TexGenAttrib, rs->get_attrib_def(TexGenAttrib::get_class_slot()));
00672 for (int i=0; i<_num_textures; i++) {
00673 texcoord_vreg.push_back(alloc_vreg());
00674 texcoord_freg.push_back(alloc_freg());
00675 text << "\t in float4 vtx_texcoord" << i << " : " << texcoord_vreg[i] << ",\n";
00676 text << "\t out float4 l_texcoord" << i << " : " << texcoord_freg[i] << ",\n";
00677 }
00678 if (_vertex_colors) {
00679 text << "\t in float4 vtx_color : COLOR,\n";
00680 text << "\t out float4 l_color : COLOR,\n";
00681 }
00682 if (_need_world_position || _need_world_normal) {
00683 text << "\t uniform float4x4 trans_model_to_world,\n";
00684 }
00685 if (_need_world_position) {
00686 world_position_freg = alloc_freg();
00687 text << "\t out float4 l_world_position : " << world_position_freg << ",\n";
00688 }
00689 if (_need_world_normal) {
00690 world_normal_freg = alloc_freg();
00691 text << "\t out float4 l_world_normal : " << world_normal_freg << ",\n";
00692 }
00693 if (_need_eye_position) {
00694 text << "\t uniform float4x4 trans_model_to_view,\n";
00695 eye_position_freg = alloc_freg();
00696 text << "\t out float4 l_eye_position : " << eye_position_freg << ",\n";
00697 }
00698 if (_need_eye_normal) {
00699 eye_normal_freg = alloc_freg();
00700 text << "\t uniform float4x4 tpose_view_to_model,\n";
00701 text << "\t out float4 l_eye_normal : " << eye_normal_freg << ",\n";
00702 }
00703 if (_map_index_height >= 0 || _need_world_normal || _need_eye_normal) {
00704 normal_vreg = alloc_vreg();
00705 text << "\t in float4 vtx_normal : " << normal_vreg << ",\n";
00706 }
00707 if (_map_index_height >= 0) {
00708 htangent_vreg = alloc_vreg();
00709 hbinormal_vreg = alloc_vreg();
00710 if (_map_index_normal == _map_index_height) {
00711 ntangent_vreg = htangent_vreg;
00712 nbinormal_vreg = hbinormal_vreg;
00713 }
00714 text << "\t in float4 vtx_tangent" << _map_index_height << " : " << htangent_vreg << ",\n";
00715 text << "\t in float4 vtx_binormal" << _map_index_height << " : " << hbinormal_vreg << ",\n";
00716 text << "\t uniform float4 mspos_view,\n";
00717 text << "\t out float3 l_eyevec,\n";
00718 }
00719 if (_lighting) {
00720 if (_map_index_normal >= 0 && _auto_normal_on) {
00721
00722 if (_map_index_normal != _map_index_height) {
00723 ntangent_vreg = alloc_vreg();
00724 nbinormal_vreg = alloc_vreg();
00725 text << "\t in float4 vtx_tangent" << _map_index_normal << " : " << ntangent_vreg << ",\n";
00726 text << "\t in float4 vtx_binormal" << _map_index_normal << " : " << nbinormal_vreg << ",\n";
00727 }
00728 ntangent_freg = alloc_freg();
00729 nbinormal_freg = alloc_freg();
00730 text << "\t out float4 l_tangent : " << ntangent_freg << ",\n";
00731 text << "\t out float4 l_binormal : " << nbinormal_freg << ",\n";
00732 }
00733 if (_shadows && _auto_shadow_on) {
00734 for (int i=0; i<(int)_dlights.size(); i++) {
00735 if (_dlights[i]->_shadow_caster) {
00736 dlightcoord_freg.push_back(alloc_freg());
00737 text << "\t uniform float4x4 trans_model_to_clip_of_dlight" << i << ",\n";
00738 text << "\t out float4 l_dlightcoord" << i << " : " << dlightcoord_freg[i] << ",\n";
00739 } else {
00740 dlightcoord_freg.push_back(NULL);
00741 }
00742 }
00743 for (int i=0; i<(int)_slights.size(); i++) {
00744 if (_slights[i]->_shadow_caster) {
00745 slightcoord_freg.push_back(alloc_freg());
00746 text << "\t uniform float4x4 trans_model_to_clip_of_slight" << i << ",\n";
00747 text << "\t out float4 l_slightcoord" << i << " : " << slightcoord_freg[i] << ",\n";
00748 } else {
00749 slightcoord_freg.push_back(NULL);
00750 }
00751 }
00752 }
00753 }
00754 if (_fog) {
00755 hpos_freg = alloc_freg();
00756 text << "\t out float4 l_hpos : " << hpos_freg << ",\n";
00757 }
00758 text << "\t float4 vtx_position : POSITION,\n";
00759 text << "\t out float4 l_position : POSITION,\n";
00760 text << "\t uniform float4x4 mat_modelproj\n";
00761 text << ") {\n";
00762
00763 text << "\t l_position = mul(mat_modelproj, vtx_position);\n";
00764 if (_fog) {
00765 text << "\t l_hpos = l_position;\n";
00766 }
00767 if (_need_world_position) {
00768 text << "\t l_world_position = mul(trans_model_to_world, vtx_position);\n";
00769 }
00770 if (_need_world_normal) {
00771 text << "\t l_world_normal = mul(trans_model_to_world, vtx_normal);\n";
00772 }
00773 if (_need_eye_position) {
00774 text << "\t l_eye_position = mul(trans_model_to_view, vtx_position);\n";
00775 }
00776 if (_need_eye_normal) {
00777 text << "\t l_eye_normal.xyz = mul((float3x3)tpose_view_to_model, vtx_normal.xyz);\n";
00778 text << "\t l_eye_normal.w = 0;\n";
00779 }
00780 for (int i=0; i<_num_textures; i++) {
00781 if (!tex_gen->has_stage(texture->get_on_stage(i))) {
00782 text << "\t l_texcoord" << i << " = vtx_texcoord" << i << ";\n";
00783 }
00784 }
00785 if (_vertex_colors) {
00786 text << "\t l_color = vtx_color;\n";
00787 }
00788 if (_lighting && (_map_index_normal >= 0 && _auto_normal_on)) {
00789 text << "\t l_tangent.xyz = mul((float3x3)tpose_view_to_model, vtx_tangent" << _map_index_normal << ".xyz);\n";
00790 text << "\t l_tangent.w = 0;\n";
00791 text << "\t l_binormal.xyz = mul((float3x3)tpose_view_to_model, -vtx_binormal" << _map_index_normal << ".xyz);\n";
00792 text << "\t l_binormal.w = 0;\n";
00793 }
00794 if (_shadows && _auto_shadow_on) {
00795 text << "\t float4x4 biasmat = {0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f};\n";
00796 for (int i=0; i<(int)_dlights.size(); i++) {
00797 if (_dlights[i]->_shadow_caster) {
00798 text << "\t l_dlightcoord" << i << " = mul(biasmat, mul(trans_model_to_clip_of_dlight" << i << ", vtx_position));\n";
00799 }
00800 }
00801 for (int i=0; i<(int)_slights.size(); i++) {
00802 if (_slights[i]->_shadow_caster) {
00803 text << "\t l_slightcoord" << i << " = mul(biasmat, mul(trans_model_to_clip_of_slight" << i << ", vtx_position));\n";
00804 }
00805 }
00806 }
00807 if (_map_index_height >= 0) {
00808 text << "\t float3 eyedir = mspos_view.xyz - vtx_position.xyz;\n";
00809 text << "\t l_eyevec.x = dot(vtx_tangent" << _map_index_height << ".xyz, eyedir);\n";
00810 text << "\t l_eyevec.y = dot(vtx_binormal" << _map_index_height << ".xyz, eyedir);\n";
00811 text << "\t l_eyevec.z = dot(vtx_normal.xyz, eyedir);\n";
00812 text << "\t l_eyevec = normalize(l_eyevec);\n";
00813 }
00814 text << "}\n\n";
00815
00816
00817
00818 text << "void fshader(\n";
00819 if (_fog) {
00820 text << "\t in float4 l_hpos : " << hpos_freg << ",\n";
00821 text << "\t in uniform float4 attr_fog,\n";
00822 text << "\t in uniform float4 attr_fogcolor,\n";
00823 }
00824 if (_need_world_position) {
00825 text << "\t in float4 l_world_position : " << world_position_freg << ",\n";
00826 }
00827 if (_need_world_normal) {
00828 text << "\t in float4 l_world_normal : " << world_normal_freg << ",\n";
00829 }
00830 if (_need_eye_position) {
00831 text << "\t in float4 l_eye_position : " << eye_position_freg << ",\n";
00832 }
00833 if (_need_eye_normal) {
00834 text << "\t in float4 l_eye_normal : " << eye_normal_freg << ",\n";
00835 }
00836 const TexMatrixAttrib *tex_matrix = DCAST(TexMatrixAttrib, rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
00837 for (int i=0; i<_num_textures; i++) {
00838 TextureStage *stage = texture->get_on_stage(i);
00839 Texture *tex = texture->get_on_texture(stage);
00840 nassertr(tex != NULL, NULL);
00841 text << "\t uniform sampler" << texture_type_as_string(tex->get_texture_type()) << " tex_" << i << ",\n";
00842 if (!tex_gen->has_stage(stage)) {
00843 text << "\t in float4 l_texcoord" << i << " : " << texcoord_freg[i] << ",\n";
00844 }
00845 if (tex_matrix->has_stage(stage)) {
00846 text << "\t uniform float4x4 texmat_" << i << ",\n";
00847 }
00848 }
00849 if (_lighting && (_map_index_normal >= 0 && _auto_normal_on)) {
00850 text << "\t in float3 l_tangent : " << ntangent_freg << ",\n";
00851 text << "\t in float3 l_binormal : " << nbinormal_freg << ",\n";
00852 }
00853 if (_lighting) {
00854 for (int i=0; i<(int)_alights.size(); i++) {
00855 text << "\t uniform float4 alight_alight" << i << ",\n";
00856 }
00857 for (int i=0; i<(int)_dlights.size(); i++) {
00858 text << "\t uniform float4x4 dlight_dlight" << i << "_rel_view,\n";
00859 if (_shadows && _dlights[i]->_shadow_caster && _auto_shadow_on) {
00860 if (_use_shadow_filter) {
00861 text << "\t uniform sampler2DShadow k_dlighttex" << i << ",\n";
00862 } else {
00863 text << "\t uniform sampler2D k_dlighttex" << i << ",\n";
00864 }
00865 text << "\t in float4 l_dlightcoord" << i << " : " << dlightcoord_freg[i] << ",\n";
00866 }
00867 }
00868 for (int i=0; i<(int)_plights.size(); i++) {
00869 text << "\t uniform float4x4 plight_plight" << i << "_rel_view,\n";
00870 }
00871 for (int i=0; i<(int)_slights.size(); i++) {
00872 text << "\t uniform float4x4 slight_slight" << i << "_rel_view,\n";
00873 text << "\t uniform float4 satten_slight" << i << ",\n";
00874 if (_shadows && _slights[i]->_shadow_caster && _auto_shadow_on) {
00875 if (_use_shadow_filter) {
00876 text << "\t uniform sampler2DShadow k_slighttex" << i << ",\n";
00877 } else {
00878 text << "\t uniform sampler2D k_slighttex" << i << ",\n";
00879 }
00880 text << "\t in float4 l_slightcoord" << i << " : " << slightcoord_freg[i] << ",\n";
00881 }
00882 }
00883 if (_need_material_props) {
00884 text << "\t uniform float4x4 attr_material,\n";
00885 }
00886 if (_have_specular) {
00887 if (_material->get_local()) {
00888 text << "\t uniform float4 mspos_view,\n";
00889 } else {
00890 text << "\t uniform float4 row1_view_to_model,\n";
00891 }
00892 }
00893 }
00894 if (_map_index_height >= 0) {
00895 text << "\t float3 l_eyevec,\n";
00896 }
00897 if (_out_aux_any) {
00898 text << "\t out float4 o_aux : COLOR1,\n";
00899 }
00900 text << "\t out float4 o_color : COLOR0,\n";
00901 if (_vertex_colors) {
00902 text << "\t in float4 l_color : COLOR,\n";
00903 } else {
00904 text << "\t uniform float4 attr_color,\n";
00905 }
00906 for (int i=0; i<_num_clip_planes; ++i) {
00907 text << "\t uniform float4 clipplane_" << i << ",\n";
00908 }
00909 text << "\t uniform float4 attr_colorscale\n";
00910 text << ") {\n";
00911
00912 for (int i=0; i<_num_clip_planes; ++i) {
00913 text << "\t if (l_world_position.x * clipplane_" << i << ".x + l_world_position.y ";
00914 text << "* clipplane_" << i << ".y + l_world_position.z * clipplane_" << i << ".z + clipplane_" << i << ".w <= 0) {\n";
00915 text << "\t discard;\n";
00916 text << "\t }\n";
00917 }
00918 text << "\t float4 result;\n";
00919 if (_out_aux_any) {
00920 text << "\t o_aux = float4(0,0,0,0);\n";
00921 }
00922
00923 for (int i=0; i<_num_textures; i++) {
00924 TextureStage *stage = texture->get_on_stage(i);
00925 if (tex_gen != NULL && tex_gen->has_stage(stage)) {
00926 switch (tex_gen->get_mode(stage)) {
00927 case TexGenAttrib::M_world_position:
00928 text << "\t float4 l_texcoord" << i << " = l_world_position;\n";
00929 break;
00930 case TexGenAttrib::M_world_normal:
00931 text << "\t float4 l_texcoord" << i << " = l_world_normal;\n";
00932 break;
00933 case TexGenAttrib::M_eye_position:
00934 text << "\t float4 l_texcoord" << i << " = l_eye_position;\n";
00935 break;
00936 case TexGenAttrib::M_eye_normal:
00937 text << "\t float4 l_texcoord" << i << " = l_eye_normal;\n";
00938 text << "\t l_texcoord" << i << ".w = 1.0f;\n";
00939 break;
00940 default:
00941 pgraph_cat.error() << "Unsupported TexGenAttrib mode\n";
00942 text << "\t float4 l_texcoord" << i << " = float4(0, 0, 0, 0);\n";
00943 }
00944 }
00945 if (tex_matrix != NULL && tex_matrix->has_stage(stage)) {
00946 text << "\t l_texcoord" << i << " = mul(texmat_" << i << ", l_texcoord" << i << ");\n";
00947 text << "\t l_texcoord" << i << ".xyz /= l_texcoord" << i << ".w;\n";
00948 }
00949 }
00950 text << "\t // Fetch all textures.\n";
00951 if (_map_index_height >= 0 && parallax_mapping_samples > 0) {
00952 Texture *tex = texture->get_on_texture(texture->get_on_stage(_map_index_height));
00953 nassertr(tex != NULL, NULL);
00954 text << "\t float4 tex" << _map_index_height << " = tex" << texture_type_as_string(tex->get_texture_type());
00955 text << "(tex_" << _map_index_height << ", l_texcoord" << _map_index_height << ".";
00956 switch (tex->get_texture_type()) {
00957 case Texture::TT_cube_map:
00958 case Texture::TT_3d_texture:
00959 text << "xyz";
00960 break;
00961 case Texture::TT_2d_texture:
00962 text << "xy";
00963 break;
00964 case Texture::TT_1d_texture:
00965 text << "x";
00966 break;
00967 default:
00968 break;
00969 }
00970 text << ");\n\t float3 parallax_offset = l_eyevec.xyz * (tex" << _map_index_height;
00971 if (_map_height_in_alpha) {
00972 text << ".aaa";
00973 } else {
00974 text << ".rgb";
00975 }
00976 text << " * 2.0 - 1.0) * " << parallax_mapping_scale << ";\n";
00977
00978 for (int i=0; i<parallax_mapping_samples-1; i++) {
00979 text << "\t parallax_offset = l_eyevec.xyz * (parallax_offset + (tex" << _map_index_height;
00980 if (_map_height_in_alpha) {
00981 text << ".aaa";
00982 } else {
00983 text << ".rgb";
00984 }
00985 text << " * 2.0 - 1.0)) * " << 0.5 * parallax_mapping_scale << ";\n";
00986 }
00987 }
00988 for (int i=0; i<_num_textures; i++) {
00989 if (i != _map_index_height) {
00990 Texture *tex = texture->get_on_texture(texture->get_on_stage(i));
00991 nassertr(tex != NULL, NULL);
00992
00993 if (_map_index_height >= 0 && parallax_mapping_samples > 0) {
00994 text << "\t l_texcoord" << i << ".xyz -= parallax_offset;\n";
00995 }
00996 text << "\t float4 tex" << i << " = tex" << texture_type_as_string(tex->get_texture_type());
00997 text << "(tex_" << i << ", l_texcoord" << i << ".";
00998 switch(tex->get_texture_type()) {
00999 case Texture::TT_cube_map:
01000 case Texture::TT_3d_texture:
01001 text << "xyz";
01002 break;
01003 case Texture::TT_2d_texture:
01004 text << "xy";
01005 break;
01006 case Texture::TT_1d_texture:
01007 text << "x";
01008 break;
01009 default:
01010 break;
01011 }
01012 text << ");\n";
01013 }
01014 }
01015 if (_lighting) {
01016 if (_map_index_normal >= 0 && _auto_normal_on) {
01017 text << "\t // Translate tangent-space normal in map to view-space.\n";
01018 text << "\t float3 tsnormal = ((float3)tex" << _map_index_normal << " * 2) - 1;\n";
01019 text << "\t l_eye_normal.xyz *= tsnormal.z;\n";
01020 text << "\t l_eye_normal.xyz += l_tangent * tsnormal.x;\n";
01021 text << "\t l_eye_normal.xyz += l_binormal * tsnormal.y;\n";
01022 }
01023 }
01024 if (_need_eye_normal) {
01025 text << "\t // Correct the surface normal for interpolation effects\n";
01026 text << "\t l_eye_normal.xyz = normalize(l_eye_normal.xyz);\n";
01027 }
01028 if (_out_aux_normal) {
01029 text << "\t // Output the camera-space surface normal\n";
01030 text << "\t o_aux.rgb = (l_eye_normal.xyz*0.5) + float3(0.5,0.5,0.5);\n";
01031 }
01032 if (_lighting) {
01033 text << "\t // Begin view-space light calculations\n";
01034 text << "\t float ldist,lattenv,langle;\n";
01035 text << "\t float4 lcolor,lspec,lvec,lpoint,latten,ldir,leye,lhalf;\n";
01036 if (_shadows && _auto_shadow_on) {
01037 text << "\t float lshad;\n";
01038 }
01039 if (_separate_ambient_diffuse) {
01040 if (_have_ambient) {
01041 text << "\t float4 tot_ambient = float4(0,0,0,0);\n";
01042 }
01043 if (_have_diffuse) {
01044 text << "\t float4 tot_diffuse = float4(0,0,0,0);\n";
01045 }
01046 } else {
01047 if (_have_ambient || _have_diffuse) {
01048 text << "\t float4 tot_diffuse = float4(0,0,0,0);\n";
01049 }
01050 }
01051 if (_have_specular) {
01052 text << "\t float4 tot_specular = float4(0,0,0,0);\n";
01053 if (_material->has_specular()) {
01054 text << "\t float shininess = attr_material[3].w;\n";
01055 } else {
01056 text << "\t float shininess = 50; // no shininess specified, using default\n";
01057 }
01058 }
01059 for (int i=0; i<(int)_alights.size(); i++) {
01060 text << "\t // Ambient Light " << i << "\n";
01061 text << "\t lcolor = alight_alight" << i << ";\n";
01062 if (_separate_ambient_diffuse && _have_ambient) {
01063 text << "\t tot_ambient += lcolor;\n";
01064 } else if(_have_diffuse) {
01065 text << "\t tot_diffuse += lcolor;\n";
01066 }
01067 }
01068 for (int i=0; i<(int)_dlights.size(); i++) {
01069 text << "\t // Directional Light " << i << "\n";
01070 text << "\t lcolor = dlight_dlight" << i << "_rel_view[0];\n";
01071 text << "\t lspec = dlight_dlight" << i << "_rel_view[1];\n";
01072 text << "\t lvec = dlight_dlight" << i << "_rel_view[2];\n";
01073 text << "\t lcolor *= saturate(dot(l_eye_normal.xyz, lvec.xyz));\n";
01074 if (_shadows && _dlights[i]->_shadow_caster && _auto_shadow_on) {
01075 if (_use_shadow_filter) {
01076 text << "\t lshad = shadow2DProj(k_dlighttex" << i << ", l_dlightcoord" << i << ").r;\n";
01077 } else {
01078 text << "\t lshad = tex2Dproj(k_dlighttex" << i << ", l_dlightcoord" << i << ").r > l_dlightcoord" << i << ".z / l_dlightcoord" << i << ".w;\n";
01079 }
01080 text << "\t lcolor *= lshad;\n";
01081 text << "\t lspec *= lshad;\n";
01082 }
01083 if (_have_diffuse) {
01084 text << "\t tot_diffuse += lcolor;\n";
01085 }
01086 if (_have_specular) {
01087 if (_material->get_local()) {
01088 text << "\t lhalf = normalize(lvec - normalize(l_eye_position));\n";
01089 } else {
01090 text << "\t lhalf = dlight_dlight" << i << "_rel_view[3];\n";
01091 }
01092 text << "\t lspec *= pow(saturate(dot(l_eye_normal.xyz, lhalf.xyz)), shininess);\n";
01093 text << "\t tot_specular += lspec;\n";
01094 }
01095 }
01096 for (int i=0; i<(int)_plights.size(); i++) {
01097 text << "\t // Point Light " << i << "\n";
01098 text << "\t lcolor = plight_plight" << i << "_rel_view[0];\n";
01099 text << "\t lspec = plight_plight" << i << "_rel_view[1];\n";
01100 text << "\t lpoint = plight_plight" << i << "_rel_view[2];\n";
01101 text << "\t latten = plight_plight" << i << "_rel_view[3];\n";
01102 text << "\t lvec = lpoint - l_eye_position;\n";
01103 text << "\t ldist = length(float3(lvec));\n";
01104 text << "\t lvec /= ldist;\n";
01105 text << "\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
01106 text << "\t lcolor *= lattenv * saturate(dot(l_eye_normal.xyz, lvec.xyz));\n";
01107 if (_have_diffuse) {
01108 text << "\t tot_diffuse += lcolor;\n";
01109 }
01110 if (_have_specular) {
01111 if (_material->get_local()) {
01112 text << "\t lhalf = normalize(lvec - normalize(l_eye_position));\n";
01113 } else {
01114 text << "\t lhalf = normalize(lvec - float4(0,1,0,0));\n";
01115 }
01116 text << "\t lspec *= lattenv;\n";
01117 text << "\t lspec *= pow(saturate(dot(l_eye_normal.xyz, lhalf.xyz)), shininess);\n";
01118 text << "\t tot_specular += lspec;\n";
01119 }
01120 }
01121 for (int i=0; i<(int)_slights.size(); i++) {
01122 text << "\t // Spot Light " << i << "\n";
01123 text << "\t lcolor = slight_slight" << i << "_rel_view[0];\n";
01124 text << "\t lspec = slight_slight" << i << "_rel_view[1];\n";
01125 text << "\t lpoint = slight_slight" << i << "_rel_view[2];\n";
01126 text << "\t ldir = slight_slight" << i << "_rel_view[3];\n";
01127 text << "\t latten = satten_slight" << i << ";\n";
01128 text << "\t lvec = lpoint - l_eye_position;\n";
01129 text << "\t ldist = length(float3(lvec));\n";
01130 text << "\t lvec /= ldist;\n";
01131 text << "\t langle = saturate(dot(ldir.xyz, lvec.xyz));\n";
01132 text << "\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
01133 text << "\t lattenv *= pow(langle, latten.w);\n";
01134 text << "\t if (langle < ldir.w) lattenv = 0;\n";
01135 text << "\t lcolor *= lattenv * saturate(dot(l_eye_normal.xyz, lvec.xyz));\n";
01136 if (_shadows && _slights[i]->_shadow_caster && _auto_shadow_on) {
01137 if (_use_shadow_filter) {
01138 text << "\t lshad = shadow2DProj(k_slighttex" << i << ", l_slightcoord" << i << ").r;\n";
01139 } else {
01140 text << "\t lshad = tex2Dproj(k_slighttex" << i << ", l_slightcoord" << i << ").r > l_slightcoord" << i << ".z / l_slightcoord" << i << ".w;\n";
01141 }
01142 text << "\t lcolor *= lshad;\n";
01143 text << "\t lspec *= lshad;\n";
01144 }
01145
01146 if (_have_diffuse) {
01147 text << "\t tot_diffuse += lcolor;\n";
01148 }
01149 if (_have_specular) {
01150 if (_material->get_local()) {
01151 text << "\t lhalf = normalize(lvec - normalize(l_eye_position));\n";
01152 } else {
01153 text << "\t lhalf = normalize(lvec - float4(0,1,0,0));\n";
01154 }
01155 text << "\t lspec *= lattenv;\n";
01156 text << "\t lspec *= pow(saturate(dot(l_eye_normal.xyz, lhalf.xyz)), shininess);\n";
01157 text << "\t tot_specular += lspec;\n";
01158 }
01159 }
01160 const LightRampAttrib *light_ramp = DCAST(LightRampAttrib, rs->get_attrib_def(LightRampAttrib::get_class_slot()));
01161 if(_auto_ramp_on) {
01162 switch (light_ramp->get_mode()) {
01163 case LightRampAttrib::LRT_single_threshold:
01164 {
01165 PN_stdfloat t = light_ramp->get_threshold(0);
01166 PN_stdfloat l0 = light_ramp->get_level(0);
01167 text << "\t // Single-threshold light ramp\n";
01168 text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
01169 text << "\t float lr_scale = (lr_in < " << t << ") ? 0.0 : (" << l0 << "/lr_in);\n";
01170 text << "\t tot_diffuse = tot_diffuse * lr_scale;\n";
01171 break;
01172 }
01173 case LightRampAttrib::LRT_double_threshold:
01174 {
01175 PN_stdfloat t0 = light_ramp->get_threshold(0);
01176 PN_stdfloat t1 = light_ramp->get_threshold(1);
01177 PN_stdfloat l0 = light_ramp->get_level(0);
01178 PN_stdfloat l1 = light_ramp->get_level(1);
01179 PN_stdfloat l2 = light_ramp->get_level(2);
01180 text << "\t // Double-threshold light ramp\n";
01181 text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
01182 text << "\t float lr_out = " << l0 << "\n";
01183 text << "\t if (lr_in > " << t0 << ") lr_out=" << l1 << ";\n";
01184 text << "\t if (lr_in > " << t1 << ") lr_out=" << l2 << ";\n";
01185 text << "\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n";
01186 break;
01187 }
01188 default:
01189 break;
01190 }
01191 }
01192 text << "\t // Begin view-space light summation\n";
01193 if (_have_emission) {
01194 if (_map_index_glow >= 0 && _auto_glow_on) {
01195 text << "\t result = attr_material[2] * saturate(2 * (tex" << _map_index_glow << ".a - 0.5));\n";
01196 } else {
01197 text << "\t result = attr_material[2];\n";
01198 }
01199 } else {
01200 if (_map_index_glow >= 0 && _auto_glow_on) {
01201 text << "\t result = saturate(2 * (tex" << _map_index_glow << ".a - 0.5));\n";
01202 } else {
01203 text << "\t result = float4(0,0,0,0);\n";
01204 }
01205 }
01206 if ((_have_ambient)&&(_separate_ambient_diffuse)) {
01207 if (_material->has_ambient()) {
01208 text << "\t result += tot_ambient * attr_material[0];\n";
01209 } else if (_vertex_colors) {
01210 text << "\t result += tot_ambient * l_color;\n";
01211 } else if (_flat_colors) {
01212 text << "\t result += tot_ambient * attr_color;\n";
01213 } else {
01214 text << "\t result += tot_ambient;\n";
01215 }
01216 }
01217 if (_have_diffuse) {
01218 if (_material->has_diffuse()) {
01219 text << "\t result += tot_diffuse * attr_material[1];\n";
01220 } else if (_vertex_colors) {
01221 text << "\t result += tot_diffuse * l_color;\n";
01222 } else if (_flat_colors) {
01223 text << "\t result += tot_diffuse * attr_color;\n";
01224 } else {
01225 text << "\t result += tot_diffuse;\n";
01226 }
01227 }
01228 if (light_ramp->get_mode() == LightRampAttrib::LRT_default) {
01229 text << "\t result = saturate(result);\n";
01230 }
01231 text << "\t // End view-space light calculations\n";
01232
01233
01234
01235 if (_calc_primary_alpha) {
01236 if (_vertex_colors) {
01237 text << "\t result.a = l_color.a;\n";
01238 } else if (_flat_colors) {
01239 text << "\t result.a = attr_color.a;\n";
01240 } else {
01241 text << "\t result.a = 1;\n";
01242 }
01243 }
01244 } else {
01245 if (_vertex_colors) {
01246 text << "\t result = l_color;\n";
01247 } else if (_flat_colors) {
01248 text << "\t result = attr_color;\n";
01249 } else {
01250 text << "\t result = float4(1,1,1,1);\n";
01251 }
01252 }
01253
01254
01255 bool have_saved_result = false;
01256 bool have_primary_color = false;
01257 for (int i=0; i<_num_textures; i++) {
01258 TextureStage *stage = texture->get_on_stage(i);
01259 if (stage->get_mode() != TextureStage::M_combine) continue;
01260 if (stage->uses_primary_color() && !have_primary_color) {
01261 text << "\t float4 primary_color = result;\n";
01262 have_primary_color = true;
01263 }
01264 if (stage->uses_last_saved_result() && !have_saved_result) {
01265 text << "\t float4 last_saved_result = result;\n";
01266 have_saved_result = true;
01267 }
01268 }
01269
01270
01271 for (int i=0; i<_num_textures; i++) {
01272 TextureStage *stage = texture->get_on_stage(i);
01273 switch (stage->get_mode()) {
01274 case TextureStage::M_modulate: {
01275 int num_components = texture->get_on_texture(texture->get_on_stage(i))->get_num_components();
01276
01277 if (num_components == 1) {
01278 text << "\t result.a *= tex" << i << ".a;\n";
01279 } else if (num_components == 3) {
01280 text << "\t result.rgb *= tex" << i << ".rgb;\n";
01281 } else {
01282 text << "\t result.rgba *= tex" << i << ".rgba;\n";
01283 }
01284
01285 break; }
01286 case TextureStage::M_modulate_glow:
01287 case TextureStage::M_modulate_gloss:
01288
01289
01290
01291
01292
01293
01294
01295 text << "\t result.rgb *= tex" << i << ";\n";
01296 break;
01297 case TextureStage::M_decal:
01298 text << "\t result.rgb = lerp(result, tex" << i << ", tex" << i << ".a).rgb;\n";
01299 break;
01300 case TextureStage::M_blend: {
01301 LVecBase4 c = stage->get_color();
01302 text << "\t result.rgb = lerp(result, tex" << i << " * float4("
01303 << c[0] << ", " << c[1] << ", " << c[2] << ", " << c[3] << "), tex" << i << ".r).rgb;\n";
01304 break; }
01305 case TextureStage::M_replace:
01306 text << "\t result = tex" << i << ";\n";
01307 break;
01308 case TextureStage::M_add:
01309 text << "\t result.rgb += tex" << i << ".rgb;\n";
01310 if (_calc_primary_alpha) {
01311 text << "\t result.a *= tex" << i << ".a;\n";
01312 }
01313 break;
01314 case TextureStage::M_combine:
01315 text << "\t result.rgb = ";
01316 if (stage->get_combine_rgb_mode() != TextureStage::CM_undefined) {
01317 text << combine_mode_as_string(stage, stage->get_combine_rgb_mode(), false, i);
01318 } else {
01319 text << "tex" << i << ".rgb";
01320 }
01321 if (stage->get_rgb_scale() != 1) {
01322 text << " * " << stage->get_rgb_scale();
01323 }
01324 text << ";\n\t result.a = ";
01325 if (stage->get_combine_alpha_mode() != TextureStage::CM_undefined) {
01326 text << combine_mode_as_string(stage, stage->get_combine_alpha_mode(), true, i);
01327 } else {
01328 text << "tex" << i << ".a";
01329 }
01330 if (stage->get_alpha_scale() != 1) {
01331 text << " * " << stage->get_alpha_scale();
01332 }
01333 text << ";\n";
01334 break;
01335 case TextureStage::M_blend_color_scale:
01336 text << "\t result.rgb = lerp(result, tex" << i << " * attr_colorscale, tex" << i << ".r).rgb;\n";
01337 break;
01338 default:
01339 break;
01340 }
01341 if (stage->get_saved_result() && have_saved_result) {
01342 text << "\t last_saved_result = result;\n";
01343 }
01344 }
01345
01346 text << "\t result *= attr_colorscale;\n";
01347
01348 if (_subsume_alpha_test) {
01349 const AlphaTestAttrib *alpha_test = DCAST(AlphaTestAttrib, rs->get_attrib_def(AlphaTestAttrib::get_class_slot()));
01350 text << "\t // Shader includes alpha test:\n";
01351 double ref = alpha_test->get_reference_alpha();
01352 switch (alpha_test->get_mode()) {
01353 case RenderAttrib::M_never:
01354 text << "\t discard;\n";
01355 break;
01356 case RenderAttrib::M_less:
01357 text << "\t if (result.a >= " << ref << ") discard;\n";
01358 break;
01359 case RenderAttrib::M_equal:
01360 text << "\t if (result.a != " << ref << ") discard;\n";
01361 break;
01362 case RenderAttrib::M_less_equal:
01363 text << "\t if (result.a > " << ref << ") discard;\n";
01364 break;
01365 case RenderAttrib::M_greater:
01366 text << "\t if (result.a <= " << ref << ") discard;\n";
01367 break;
01368 case RenderAttrib::M_not_equal:
01369 text << "\t if (result.a == " << ref << ") discard;\n";
01370 break;
01371 case RenderAttrib::M_greater_equal:
01372 text << "\t if (result.a < " << ref << ") discard;\n";
01373 break;
01374 case RenderAttrib::M_none:
01375 case RenderAttrib::M_always:
01376 default:
01377 break;
01378 }
01379 }
01380
01381 if (_out_primary_glow) {
01382 if (_map_index_glow >= 0 && _auto_glow_on) {
01383 text << "\t result.a = tex" << _map_index_glow << ".a;\n";
01384 } else {
01385 text << "\t result.a = 0.5;\n";
01386 }
01387 }
01388 if (_out_aux_glow) {
01389 if (_map_index_glow >= 0 && _auto_glow_on) {
01390 text << "\t o_aux.a = tex" << _map_index_glow << ".a;\n";
01391 } else {
01392 text << "\t o_aux.a = 0.5;\n";
01393 }
01394 }
01395
01396 if (_lighting) {
01397 if (_have_specular) {
01398 if (_material->has_specular()) {
01399 text << "\t tot_specular *= attr_material[3];\n";
01400 }
01401 if (_map_index_gloss >= 0 && _auto_gloss_on) {
01402 text << "\t tot_specular *= tex" << _map_index_gloss << ".a;\n";
01403 }
01404 text << "\t result.rgb = result.rgb + tot_specular.rgb;\n";
01405 }
01406 }
01407 if(_auto_ramp_on) {
01408 const LightRampAttrib *light_ramp = DCAST(LightRampAttrib, rs->get_attrib_def(LightRampAttrib::get_class_slot()));
01409 switch (light_ramp->get_mode()) {
01410 case LightRampAttrib::LRT_hdr0:
01411 text << "\t result.rgb = (result*result*result + result*result + result) / (result*result*result + result*result + result + 1);\n";
01412 break;
01413 case LightRampAttrib::LRT_hdr1:
01414 text << "\t result.rgb = (result*result + result) / (result*result + result + 1);\n";
01415 break;
01416 case LightRampAttrib::LRT_hdr2:
01417 text << "\t result.rgb = result / (result + 1);\n";
01418 break;
01419 default: break;
01420 }
01421 }
01422
01423
01424 if (_fog) {
01425 const FogAttrib *fog_attr = DCAST(FogAttrib, rs->get_attrib_def(FogAttrib::get_class_slot()));
01426 Fog *fog = fog_attr->get_fog();
01427
01428 switch (fog->get_mode()) {
01429 case Fog::M_linear:
01430 text << "\t result.rgb = lerp(attr_fogcolor.rgb, result.rgb, saturate((attr_fog.z - l_hpos.z) * attr_fog.w));\n";
01431 break;
01432 case Fog::M_exponential:
01433 text << "\t result.rgb = lerp(attr_fogcolor.rgb, result.rgb, saturate(exp2(attr_fog.x * l_hpos.z * -1.442695f)));\n";
01434 break;
01435 case Fog::M_exponential_squared:
01436 text << "\t result.rgb = lerp(attr_fogcolor.rgb, result.rgb, saturate(exp2(attr_fog.x * attr_fog.x * l_hpos.z * l_hpos.z * -1.442695f)));\n";
01437 break;
01438 }
01439 }
01440
01441
01442
01443 text << "\t o_color = result * 1.000001;\n";
01444 if (_subsume_alpha_test) {
01445 text << "\t // Shader subsumes normal alpha test.\n";
01446 }
01447 if (_disable_alpha_write) {
01448 text << "\t // Shader disables alpha write.\n";
01449 }
01450 text << "}\n";
01451
01452
01453 CPT(RenderAttrib) shattr = create_shader_attrib(text.str());
01454 if (_subsume_alpha_test) {
01455 shattr=DCAST(ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_subsume_alpha_test, true);
01456 }
01457 if (_disable_alpha_write) {
01458 shattr=DCAST(ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_disable_alpha_write, true);
01459 }
01460 clear_analysis();
01461 reset_register_allocator();
01462 return shattr;
01463 }
01464
01465
01466
01467
01468
01469
01470 const string ShaderGenerator::
01471 combine_mode_as_string(CPT(TextureStage) stage, TextureStage::CombineMode c_mode, bool alpha, short texindex) {
01472 ostringstream text;
01473 switch (c_mode) {
01474 case TextureStage::CM_modulate:
01475 text << combine_source_as_string(stage, 0, alpha, alpha, texindex);
01476 text << " * ";
01477 text << combine_source_as_string(stage, 1, alpha, alpha, texindex);
01478 break;
01479 case TextureStage::CM_add:
01480 text << combine_source_as_string(stage, 0, alpha, alpha, texindex);
01481 text << " + ";
01482 text << combine_source_as_string(stage, 1, alpha, alpha, texindex);
01483 break;
01484 case TextureStage::CM_add_signed:
01485 pgraph_cat.error() << "TextureStage::CombineMode ADD_SIGNED not yet supported in per-pixel mode.\n";
01486 break;
01487 case TextureStage::CM_interpolate:
01488 text << "lerp(";
01489 text << combine_source_as_string(stage, 1, alpha, alpha, texindex);
01490 text << ", ";
01491 text << combine_source_as_string(stage, 0, alpha, alpha, texindex);
01492 text << ", ";
01493 text << combine_source_as_string(stage, 2, alpha, true, texindex);
01494 text << ")";
01495 break;
01496 case TextureStage::CM_subtract:
01497 text << combine_source_as_string(stage, 0, alpha, alpha, texindex);
01498 text << " + ";
01499 text << combine_source_as_string(stage, 1, alpha, alpha, texindex);
01500 break;
01501 case TextureStage::CM_dot3_rgb:
01502 pgraph_cat.error() << "TextureStage::CombineMode DOT3_RGB not yet supported in per-pixel mode.\n";
01503 break;
01504 case TextureStage::CM_dot3_rgba:
01505 pgraph_cat.error() << "TextureStage::CombineMode DOT3_RGBA not yet supported in per-pixel mode.\n";
01506 break;
01507 case TextureStage::CM_replace:
01508 default:
01509 text << combine_source_as_string(stage, 0, alpha, alpha, texindex);
01510 break;
01511 }
01512 return text.str();
01513 }
01514
01515
01516
01517
01518
01519
01520 const string ShaderGenerator::
01521 combine_source_as_string(CPT(TextureStage) stage, short num, bool alpha, bool single_value, short texindex) {
01522 TextureStage::CombineSource c_src = TextureStage::CS_undefined;
01523 TextureStage::CombineOperand c_op = TextureStage::CO_undefined;
01524 if (alpha) {
01525 switch (num) {
01526 case 0:
01527 c_src = stage->get_combine_alpha_source0();
01528 c_op = stage->get_combine_alpha_operand0();
01529 break;
01530 case 1:
01531 c_src = stage->get_combine_alpha_source1();
01532 c_op = stage->get_combine_alpha_operand1();
01533 break;
01534 case 2:
01535 c_src = stage->get_combine_alpha_source2();
01536 c_op = stage->get_combine_alpha_operand2();
01537 break;
01538 }
01539 } else {
01540 switch (num) {
01541 case 0:
01542 c_src = stage->get_combine_rgb_source0();
01543 c_op = stage->get_combine_rgb_operand0();
01544 break;
01545 case 1:
01546 c_src = stage->get_combine_rgb_source1();
01547 c_op = stage->get_combine_rgb_operand1();
01548 break;
01549 case 2:
01550 c_src = stage->get_combine_rgb_source2();
01551 c_op = stage->get_combine_rgb_operand2();
01552 break;
01553 }
01554 }
01555 ostringstream csource;
01556 if (c_op == TextureStage::CO_one_minus_src_color ||
01557 c_op == TextureStage::CO_one_minus_src_alpha) {
01558 csource << "1.0f - ";
01559 }
01560 switch (c_src) {
01561 case TextureStage::CS_texture:
01562 csource << "tex" << texindex;
01563 break;
01564 case TextureStage::CS_constant: {
01565 LVecBase4 c = stage->get_color();
01566 csource << "float4(" << c[0] << ", " << c[1] << ", " << c[2] << ", " << c[3] << ")";
01567 break; }
01568 case TextureStage::CS_primary_color:
01569 csource << "primary_color";
01570 break;
01571 case TextureStage::CS_previous:
01572 csource << "result";
01573 break;
01574 case TextureStage::CS_constant_color_scale:
01575 csource << "attr_colorscale";
01576 break;
01577 case TextureStage::CS_last_saved_result:
01578 csource << "last_saved_result";
01579 break;
01580 case TextureStage::CS_undefined:
01581 break;
01582 }
01583 if (c_op == TextureStage::CO_src_color || c_op == TextureStage::CO_one_minus_src_color) {
01584 if (single_value) {
01585
01586 csource << ".r";
01587 } else {
01588 csource << ".rgb";
01589 }
01590 } else {
01591 csource << ".a";
01592 if (!single_value) {
01593
01594 return "float3(" + csource.str() + ")";
01595 }
01596 }
01597 return csource.str();
01598 }
01599
01600
01601
01602
01603
01604
01605
01606 const string ShaderGenerator::
01607 texture_type_as_string(Texture::TextureType ttype) {
01608 switch (ttype) {
01609 case Texture::TT_1d_texture:
01610 return "1D";
01611 break;
01612 case Texture::TT_2d_texture:
01613 return "2D";
01614 break;
01615 case Texture::TT_3d_texture:
01616 return "3D";
01617 break;
01618 case Texture::TT_cube_map:
01619 return "CUBE";
01620 break;
01621 default:
01622 pgraph_cat.error() << "Unsupported texture type!\n";
01623 return "2D";
01624 }
01625 }
01626