56 #define UNPACK_COMBINE_SRC(from, n) (TextureStage::CombineSource)((from >> ((uint16_t)n * 5u)) & 7u) 57 #define UNPACK_COMBINE_OP(from, n) (TextureStage::CombineOperand)(((from >> (((uint16_t)n * 5u) + 3u)) & 3u) + 1u) 59 static inline uint16_t
60 pack_combine(TextureStage::CombineSource src0, TextureStage::CombineOperand op0,
61 TextureStage::CombineSource src1, TextureStage::CombineOperand op1,
62 TextureStage::CombineSource src2, TextureStage::CombineOperand op2) {
63 if (op0 == TextureStage::CO_undefined) op0 = TextureStage::CO_src_alpha;
64 if (op1 == TextureStage::CO_undefined) op1 = TextureStage::CO_src_alpha;
65 if (op2 == TextureStage::CO_undefined) op2 = TextureStage::CO_src_alpha;
67 return ((uint16_t)src0) | ((((uint16_t)op0 - 1u) & 3u) << 3u) |
68 ((uint16_t)src1 << 5u) | ((((uint16_t)op1 - 1u) & 3u) << 8u) |
69 ((uint16_t)src2 << 10u) | ((((uint16_t)op2 - 1u) & 3u) << 13u);
72 static PStatCollector lookup_collector(
"*:Munge:ShaderGen:Lookup");
73 static PStatCollector synthesize_collector(
"*:Munge:ShaderGen:Synthesize");
86 _use_generic_attr = !gsg->get_supports_hlsl();
88 _use_generic_attr =
true;
93 _use_shadow_filter = gsg->get_supports_shadow_filter();
107 void ShaderGenerator::
108 reset_register_allocator() {
118 const char *ShaderGenerator::
120 if (_use_generic_attr) {
122 switch (_vtregs_used) {
123 case 0: _vtregs_used += 1;
return "ATTR8";
124 case 1: _vtregs_used += 1;
return "ATTR9";
125 case 2: _vtregs_used += 1;
return "ATTR10";
126 case 3: _vtregs_used += 1;
return "ATTR11";
127 case 4: _vtregs_used += 1;
return "ATTR12";
128 case 5: _vtregs_used += 1;
return "ATTR13";
129 case 6: _vtregs_used += 1;
return "ATTR14";
130 case 7: _vtregs_used += 1;
return "ATTR15";
132 switch (_vcregs_used) {
133 case 0: _vcregs_used += 1;
return "ATTR3";
134 case 1: _vcregs_used += 1;
return "ATTR4";
135 case 2: _vcregs_used += 1;
return "ATTR5";
136 case 3: _vcregs_used += 1;
return "ATTR6";
137 case 4: _vcregs_used += 1;
return "ATTR7";
138 case 5: _vcregs_used += 1;
return "ATTR1";
142 switch (_vtregs_used) {
143 case 0: _vtregs_used += 1;
return "TEXCOORD0";
144 case 1: _vtregs_used += 1;
return "TEXCOORD1";
145 case 2: _vtregs_used += 1;
return "TEXCOORD2";
146 case 3: _vtregs_used += 1;
return "TEXCOORD3";
147 case 4: _vtregs_used += 1;
return "TEXCOORD4";
148 case 5: _vtregs_used += 1;
return "TEXCOORD5";
149 case 6: _vtregs_used += 1;
return "TEXCOORD6";
150 case 7: _vtregs_used += 1;
return "TEXCOORD7";
152 switch (_vcregs_used) {
153 case 0: _vcregs_used += 1;
return "COLOR0";
154 case 1: _vcregs_used += 1;
return "COLOR1";
159 switch (_vtregs_used) {
160 case 8: _vtregs_used += 1;
return "TEXCOORD8";
161 case 9: _vtregs_used += 1;
return "TEXCOORD9";
162 case 10: _vtregs_used += 1;
return "TEXCOORD10";
163 case 11: _vtregs_used += 1;
return "TEXCOORD11";
164 case 12: _vtregs_used += 1;
return "TEXCOORD12";
165 case 13: _vtregs_used += 1;
return "TEXCOORD13";
166 case 14: _vtregs_used += 1;
return "TEXCOORD14";
167 case 15: _vtregs_used += 1;
return "TEXCOORD15";
175 const char *ShaderGenerator::
177 switch (_ftregs_used) {
178 case 0: _ftregs_used += 1;
return "TEXCOORD0";
179 case 1: _ftregs_used += 1;
return "TEXCOORD1";
180 case 2: _ftregs_used += 1;
return "TEXCOORD2";
181 case 3: _ftregs_used += 1;
return "TEXCOORD3";
182 case 4: _ftregs_used += 1;
return "TEXCOORD4";
183 case 5: _ftregs_used += 1;
return "TEXCOORD5";
184 case 6: _ftregs_used += 1;
return "TEXCOORD6";
185 case 7: _ftregs_used += 1;
return "TEXCOORD7";
189 switch (_ftregs_used) {
190 case 8: _ftregs_used += 1;
return "TEXCOORD8";
191 case 9: _ftregs_used += 1;
return "TEXCOORD9";
192 case 10: _ftregs_used += 1;
return "TEXCOORD10";
193 case 11: _ftregs_used += 1;
return "TEXCOORD11";
194 case 12: _ftregs_used += 1;
return "TEXCOORD12";
195 case 13: _ftregs_used += 1;
return "TEXCOORD13";
196 case 14: _ftregs_used += 1;
return "TEXCOORD14";
197 case 15: _ftregs_used += 1;
return "TEXCOORD15";
206 void ShaderGenerator::
207 analyze_renderstate(ShaderKey &key,
const RenderState *rs) {
209 rs->get_attrib_def(shader_attrib);
214 rs->get_attrib_def(aux_bitplane);
215 key._outputs = aux_bitplane->get_outputs();
218 bool have_alpha_test =
false;
219 bool have_alpha_blend =
false;
221 rs->get_attrib_def(alpha_test);
222 if (alpha_test->
get_mode() != RenderAttrib::M_none &&
223 alpha_test->
get_mode() != RenderAttrib::M_always) {
224 have_alpha_test =
true;
227 rs->get_attrib_def(color_blend);
228 if (color_blend->
get_mode() != ColorBlendAttrib::M_none) {
229 have_alpha_blend =
true;
232 rs->get_attrib_def(transparency);
233 if (transparency->
get_mode() == TransparencyAttrib::M_alpha ||
234 transparency->
get_mode() == TransparencyAttrib::M_premultiplied_alpha ||
235 transparency->
get_mode() == TransparencyAttrib::M_dual) {
236 have_alpha_blend =
true;
240 if (key._outputs & AuxBitplaneAttrib::ABO_glow) {
241 if (have_alpha_blend) {
243 key._disable_alpha_write =
true;
244 }
else if (have_alpha_test) {
246 key._alpha_test_mode = alpha_test->
get_mode();
251 if (have_alpha_blend || have_alpha_test) {
252 key._calc_primary_alpha =
true;
257 rs->get_attrib_def(color);
262 rs->get_attrib_def(material);
264 if (mat !=
nullptr) {
267 mat->mark_used_by_auto_shader();
268 key._material_flags = mat->get_flags();
270 if ((key._material_flags & Material::F_base_color) != 0) {
271 key._material_flags |= (Material::F_diffuse | Material::F_specular | Material::F_ambient);
272 key._material_flags &= ~
Material::F_base_color;
278 rs->get_attrib_def(la);
279 bool have_ambient =
false;
285 nassertv(node !=
nullptr);
287 if (node->is_ambient_light()) {
289 key._lighting =
true;
291 ShaderKey::LightInfo info;
292 info._type = node->get_type();
295 if (node->is_of_type(LightLensNode::get_class_type())) {
297 if (shader_attrib->auto_shadow_on()) {
299 info._flags |= ShaderKey::LF_has_shadows;
307 info._flags |= ShaderKey::LF_has_specular_color;
311 key._lights.push_back(info);
312 key._lighting =
true;
320 rs->get_attrib_def(texture);
322 rs->get_attrib_def(tex_gen);
324 rs->get_attrib_def(tex_matrix);
327 for (
size_t i = 0; i < num_textures; ++i) {
330 nassertd(tex !=
nullptr) continue;
335 stage->mark_used_by_auto_shader();
337 ShaderKey::TextureInfo info;
338 info._type = tex->get_texture_type();
339 info._mode = stage->get_mode();
341 info._combine_rgb = 0u;
342 info._combine_alpha = 0u;
346 switch (info._mode) {
347 case TextureStage::M_modulate:
350 if (format != Texture::F_alpha) {
351 info._flags |= ShaderKey::TF_has_rgb;
354 info._flags |= ShaderKey::TF_has_alpha;
359 case TextureStage::M_modulate_glow:
360 if (shader_attrib->auto_glow_on()) {
361 info._flags = ShaderKey::TF_map_glow;
363 info._mode = TextureStage::M_modulate;
364 info._flags = ShaderKey::TF_has_rgb;
368 case TextureStage::M_modulate_gloss:
369 if (shader_attrib->auto_gloss_on()) {
370 info._flags = ShaderKey::TF_map_gloss;
372 info._mode = TextureStage::M_modulate;
373 info._flags = ShaderKey::TF_has_rgb;
377 case TextureStage::M_normal_height:
378 if (parallax_mapping_samples == 0) {
379 info._mode = TextureStage::M_normal;
380 }
else if (!shader_attrib->auto_normal_on() ||
381 (key._lights.empty() && (key._outputs & AuxBitplaneAttrib::ABO_aux_normal) == 0)) {
382 info._mode = TextureStage::M_height;
383 info._flags = ShaderKey::TF_has_alpha;
385 info._flags = ShaderKey::TF_map_normal | ShaderKey::TF_map_height;
389 case TextureStage::M_normal_gloss:
390 if (!shader_attrib->auto_gloss_on() || key._lights.empty()) {
391 info._mode = TextureStage::M_normal;
392 }
else if (!shader_attrib->auto_normal_on()) {
393 info._mode = TextureStage::M_gloss;
395 info._flags = ShaderKey::TF_map_normal | ShaderKey::TF_map_gloss;
399 case TextureStage::M_combine:
405 info._flags |= ShaderKey::TF_rgb_scale_2;
408 info._flags |= ShaderKey::TF_rgb_scale_4;
411 info._flags |= ShaderKey::TF_alpha_scale_2;
414 info._flags |= ShaderKey::TF_alpha_scale_4;
417 info._combine_rgb = pack_combine(
421 info._combine_alpha = pack_combine(
427 info._flags |= ShaderKey::TF_uses_primary_color;
430 info._flags |= ShaderKey::TF_uses_last_saved_result;
440 switch (info._mode) {
441 case TextureStage::M_normal:
442 if (!shader_attrib->auto_normal_on() ||
443 (key._lights.empty() && (key._outputs & AuxBitplaneAttrib::ABO_aux_normal) == 0)) {
446 info._flags = ShaderKey::TF_map_normal;
449 case TextureStage::M_glow:
450 if (shader_attrib->auto_glow_on()) {
451 info._flags = ShaderKey::TF_map_glow;
456 case TextureStage::M_gloss:
457 if (!key._lights.empty() && shader_attrib->auto_gloss_on()) {
458 info._flags = ShaderKey::TF_map_gloss;
463 case TextureStage::M_height:
464 if (parallax_mapping_samples > 0) {
465 info._flags = ShaderKey::TF_map_height;
477 info._type = Texture::TT_1d_texture;
478 info._mode = TextureStage::M_modulate;
480 key._textures.push_back(info);
486 if (tex_matrix->has_stage(stage)) {
488 if (!transform->is_identity()) {
491 if (transform->has_components() && !transform->has_nonzero_shear() &&
492 transform->get_pos() == LPoint3::zero() &&
493 transform->get_hpr() == LVecBase3::zero()) {
494 info._flags |= ShaderKey::TF_has_texscale;
496 info._flags |= ShaderKey::TF_has_texmat;
501 if (tex_gen->has_stage(stage)) {
502 info._texcoord_name =
nullptr;
503 info._gen_mode = tex_gen->get_mode(stage);
506 info._gen_mode = TexGenAttrib::M_off;
511 info._flags |= ShaderKey::TF_saved_result;
516 info._flags |= ShaderKey::TF_uses_color;
519 key._textures.push_back(info);
520 key._texture_flags |= info._flags;
524 if ((key._texture_flags & ShaderKey::TF_uses_last_saved_result) == 0 &&
525 (key._texture_flags & ShaderKey::TF_saved_result) != 0) {
528 for (it = key._textures.begin(); it != key._textures.end(); ++it) {
529 (*it)._flags &= ~ShaderKey::TF_saved_result;
531 key._texture_flags &= ~ShaderKey::TF_saved_result;
536 if (key._material_flags & Material::F_ambient) {
537 key._have_separate_ambient =
true;
539 if (key._material_flags & Material::F_diffuse) {
540 key._have_separate_ambient =
true;
542 key._have_separate_ambient =
false;
547 if (shader_attrib->auto_ramp_on()) {
549 if (rs->get_attrib(light_ramp)) {
550 key._light_ramp = light_ramp;
552 key._have_separate_ambient =
true;
559 rs->get_attrib_def(clip_plane);
564 if (rs->get_attrib(fog) && !fog->
is_off()) {
565 key._fog_mode = (int)fog->
get_fog()->get_mode() + 1;
579 void ShaderGenerator::
580 rehash_generated_shaders() {
586 for (
size_t si = 0; si < size; ++si) {
589 if (state->_generated_shader !=
nullptr) {
591 analyze_renderstate(key, state);
593 GeneratedShaders::const_iterator si;
594 si = _generated_shaders.find(key);
595 if (si != _generated_shaders.end()) {
596 if (si->second != state->_generated_shader) {
597 state->_generated_shader = si->second;
598 state->_munged_states.
clear();
602 state->_generated_shader.clear();
603 state->_munged_states.
clear();
611 if (!uniquify_states) {
612 GraphicsStateGuardianBase::mark_rehash_generated_shaders();
622 void ShaderGenerator::
623 clear_generated_shaders() {
627 for (
size_t si = 0; si < size; ++si) {
629 state->_generated_shader.clear();
632 _generated_shaders.clear();
636 if (!uniquify_states) {
637 GraphicsStateGuardianBase::mark_rehash_generated_shaders();
676 key._anim_spec = anim;
677 analyze_renderstate(key, rs);
679 GeneratedShaders::const_iterator si;
680 si = _generated_shaders.find(key);
681 if (si != _generated_shaders.end()) {
689 reset_register_allocator();
691 if (pgraphnodes_cat.is_debug()) {
692 pgraphnodes_cat.debug()
693 <<
"Generating shader for render state " << rs <<
":\n";
694 rs->write(pgraphnodes_cat.debug(
false), 2);
699 const char *tangent_freg =
nullptr;
700 const char *binormal_freg =
nullptr;
701 string tangent_input;
702 string binormal_input;
705 const char *world_position_freg =
nullptr;
706 const char *world_normal_freg =
nullptr;
707 const char *eye_position_freg =
nullptr;
708 const char *eye_normal_freg =
nullptr;
709 const char *hpos_freg =
nullptr;
711 const char *position_vreg;
712 const char *transform_weight_vreg =
nullptr;
713 const char *normal_vreg;
714 const char *color_vreg =
nullptr;
715 const char *transform_index_vreg =
nullptr;
717 if (_use_generic_attr) {
718 position_vreg =
"ATTR0";
719 transform_weight_vreg =
"ATTR1";
720 normal_vreg =
"ATTR2";
721 transform_index_vreg =
"ATTR7";
723 position_vreg =
"POSITION";
724 normal_vreg =
"NORMAL";
727 if (key._color_type == ColorAttrib::T_vertex) {
729 color_vreg = _use_generic_attr ?
"ATTR3" :
"COLOR0";
736 std::ostringstream text;
740 text <<
"/* Generated shader for render state:\n";
744 int map_index_glow = -1;
745 int map_index_gloss = -1;
748 bool need_world_position = (key._num_clip_planes > 0);
749 bool need_world_normal =
false;
750 bool need_eye_position = key._lighting;
751 bool need_eye_normal = !key._lights.empty() || ((key._outputs & AuxBitplaneAttrib::ABO_aux_normal) != 0);
752 bool need_tangents = ((key._texture_flags & ShaderKey::TF_map_normal) != 0);
756 bool pack_eye_normal = need_eye_normal && need_tangents && need_eye_position;
758 bool have_specular =
false;
760 if (key._material_flags & Material::F_specular) {
761 have_specular =
true;
762 }
else if ((key._texture_flags & ShaderKey::TF_map_gloss) != 0) {
763 have_specular =
true;
767 bool need_color =
false;
768 if (key._color_type != ColorAttrib::T_off) {
770 if (((key._material_flags & Material::F_ambient) == 0 && key._have_separate_ambient) ||
771 (key._material_flags & Material::F_diffuse) == 0 ||
772 key._calc_primary_alpha) {
780 text <<
"void vshader(\n";
781 for (
size_t i = 0; i < key._textures.size(); ++i) {
782 const ShaderKey::TextureInfo &tex = key._textures[i];
784 switch (tex._gen_mode) {
785 case TexGenAttrib::M_world_position:
786 need_world_position =
true;
788 case TexGenAttrib::M_world_normal:
789 need_world_normal =
true;
791 case TexGenAttrib::M_eye_position:
792 need_eye_position =
true;
794 case TexGenAttrib::M_eye_normal:
795 need_eye_normal =
true;
801 if (tex._texcoord_name !=
nullptr) {
802 if (texcoord_fregs.count(tex._texcoord_name) == 0) {
803 const char *freg = alloc_freg();
804 texcoord_fregs[tex._texcoord_name] = freg;
806 string tcname = tex._texcoord_name->join(
"_");
807 text <<
"\t in float4 vtx_" << tcname <<
" : " << alloc_vreg() <<
",\n";
808 text <<
"\t out float4 l_" << tcname <<
" : " << freg <<
",\n";
812 if (tangent_input.empty() &&
813 (tex._flags & (ShaderKey::TF_map_normal | ShaderKey::TF_map_height)) != 0) {
814 PT(
InternalName) tangent_name = InternalName::get_tangent();
815 PT(
InternalName) binormal_name = InternalName::get_binormal();
817 if (tex._texcoord_name !=
nullptr &&
818 tex._texcoord_name != InternalName::get_texcoord()) {
819 tangent_name = tangent_name->append(tex._texcoord_name->get_basename());
820 binormal_name = binormal_name->append(tex._texcoord_name->get_basename());
823 tangent_input = tangent_name->join(
"_");
824 binormal_input = binormal_name->join(
"_");
826 text <<
"\t in float4 vtx_" << tangent_input <<
" : " << alloc_vreg() <<
",\n";
827 text <<
"\t in float4 vtx_" << binormal_input <<
" : " << alloc_vreg() <<
",\n";
830 if (tex._flags & ShaderKey::TF_map_glow) {
833 if (tex._flags & ShaderKey::TF_map_gloss) {
838 tangent_freg = alloc_freg();
839 binormal_freg = alloc_freg();
840 text <<
"\t out float4 l_tangent : " << tangent_freg <<
",\n";
841 text <<
"\t out float4 l_binormal : " << binormal_freg <<
",\n";
843 if (need_color && key._color_type == ColorAttrib::T_vertex) {
844 text <<
"\t in float4 vtx_color : " << color_vreg <<
",\n";
845 text <<
"\t out float4 l_color : COLOR0,\n";
847 if (need_world_position || need_world_normal) {
848 text <<
"\t uniform float4x4 trans_model_to_world,\n";
850 if (need_world_position) {
851 world_position_freg = alloc_freg();
852 text <<
"\t out float4 l_world_position : " << world_position_freg <<
",\n";
854 if (need_world_normal) {
855 world_normal_freg = alloc_freg();
856 text <<
"\t out float4 l_world_normal : " << world_normal_freg <<
",\n";
858 if (need_eye_position) {
859 text <<
"\t uniform float4x4 trans_model_to_view,\n";
860 eye_position_freg = alloc_freg();
861 text <<
"\t out float4 l_eye_position : " << eye_position_freg <<
",\n";
862 }
else if (need_tangents) {
863 text <<
"\t uniform float4x4 trans_model_to_view,\n";
865 if (need_eye_normal) {
866 text <<
"\t uniform float4x4 tpose_view_to_model,\n";
867 if (!pack_eye_normal) {
868 eye_normal_freg = alloc_freg();
869 text <<
"\t out float3 l_eye_normal : " << eye_normal_freg <<
",\n";
872 if ((key._texture_flags & ShaderKey::TF_map_height) != 0 || need_world_normal || need_eye_normal) {
873 text <<
"\t in float3 vtx_normal : " << normal_vreg <<
",\n";
875 if (key._texture_flags & ShaderKey::TF_map_height) {
876 text <<
"\t uniform float4 mspos_view,\n";
877 text <<
"\t out float3 l_eyevec,\n";
879 if (key._fog_mode != 0) {
880 hpos_freg = alloc_freg();
881 text <<
"\t out float4 l_hpos : " << hpos_freg <<
",\n";
883 for (
size_t i = 0; i < key._lights.size(); ++i) {
884 const ShaderKey::LightInfo &light = key._lights[i];
885 if (light._flags & ShaderKey::LF_has_shadows) {
886 if (_ftregs_used >= 8) {
889 lightcoord_fregs.push_back(
nullptr);
891 lightcoord_fregs.push_back(alloc_freg());
892 text <<
"\t uniform float4x4 mat_shadow_" << i <<
",\n";
893 text <<
"\t out float4 l_lightcoord" << i <<
" : " << lightcoord_fregs[i] <<
",\n";
896 lightcoord_fregs.push_back(
nullptr);
899 if (key._anim_spec.get_animation_type() == GeomEnums::AT_hardware &&
900 key._anim_spec.get_num_transforms() > 0) {
902 if (key._anim_spec.get_indexed_transforms()) {
903 num_transforms = 120;
905 num_transforms = key._anim_spec.get_num_transforms();
907 if (transform_weight_vreg ==
nullptr) {
908 transform_weight_vreg = alloc_vreg();
910 if (transform_index_vreg ==
nullptr) {
911 transform_index_vreg = alloc_vreg();
913 text <<
"\t uniform float4x4 tbl_transforms[" << num_transforms <<
"],\n";
914 text <<
"\t in float4 vtx_transform_weight : " << transform_weight_vreg <<
",\n";
915 if (key._anim_spec.get_indexed_transforms()) {
916 text <<
"\t in uint4 vtx_transform_index : " << transform_index_vreg <<
",\n";
919 text <<
"\t in float4 vtx_position : " << position_vreg <<
",\n";
920 text <<
"\t out float4 l_position : POSITION,\n";
921 text <<
"\t uniform float4x4 mat_modelproj\n";
924 if (key._anim_spec.get_animation_type() == GeomEnums::AT_hardware &&
925 key._anim_spec.get_num_transforms() > 0) {
927 if (!key._anim_spec.get_indexed_transforms()) {
928 text <<
"\t const uint4 vtx_transform_index = uint4(0, 1, 2, 3);\n";
931 text <<
"\t float4x4 matrix = tbl_transforms[vtx_transform_index.x] * vtx_transform_weight.x";
932 if (key._anim_spec.get_num_transforms() > 1) {
933 text <<
"\n\t + tbl_transforms[vtx_transform_index.y] * vtx_transform_weight.y";
935 if (key._anim_spec.get_num_transforms() > 2) {
936 text <<
"\n\t + tbl_transforms[vtx_transform_index.z] * vtx_transform_weight.z";
938 if (key._anim_spec.get_num_transforms() > 3) {
939 text <<
"\n\t + tbl_transforms[vtx_transform_index.w] * vtx_transform_weight.w";
943 text <<
"\t vtx_position = mul(matrix, vtx_position);\n";
944 if (need_world_normal || need_eye_normal) {
945 text <<
"\t vtx_normal = mul((float3x3)matrix, vtx_normal);\n";
949 text <<
"\t l_position = mul(mat_modelproj, vtx_position);\n";
950 if (key._fog_mode != 0) {
951 text <<
"\t l_hpos = l_position;\n";
953 if (need_world_position) {
954 text <<
"\t l_world_position = mul(trans_model_to_world, vtx_position);\n";
956 if (need_world_normal) {
957 text <<
"\t l_world_normal = mul(trans_model_to_world, float4(vtx_normal, 0));\n";
959 if (need_eye_position) {
960 text <<
"\t l_eye_position = mul(trans_model_to_view, vtx_position);\n";
963 for (it = texcoord_fregs.begin(); it != texcoord_fregs.end(); ++it) {
965 string tcname = it->first->join(
"_");
966 text <<
"\t l_" << tcname <<
" = vtx_" << tcname <<
";\n";
968 if (need_color && key._color_type == ColorAttrib::T_vertex) {
969 text <<
"\t l_color = vtx_color;\n";
972 text <<
"\t l_tangent.xyz = normalize(mul((float3x3)trans_model_to_view, vtx_" << tangent_input <<
".xyz));\n";
973 text <<
"\t l_tangent.w = 0;\n";
974 text <<
"\t l_binormal.xyz = normalize(mul((float3x3)trans_model_to_view, -vtx_" << binormal_input <<
".xyz));\n";
975 text <<
"\t l_binormal.w = 0;\n";
977 for (
size_t i = 0; i < key._lights.size(); ++i) {
978 if (key._lights[i]._flags & ShaderKey::LF_has_shadows) {
979 if (lightcoord_fregs[i] !=
nullptr) {
980 text <<
"\t l_lightcoord" << i <<
" = mul(mat_shadow_" << i <<
", l_eye_position);\n";
984 if (key._texture_flags & ShaderKey::TF_map_height) {
985 text <<
"\t float3 eyedir = mspos_view.xyz - vtx_position.xyz;\n";
986 text <<
"\t l_eyevec.x = dot(vtx_" << tangent_input <<
".xyz, eyedir);\n";
987 text <<
"\t l_eyevec.y = dot(vtx_" << binormal_input <<
".xyz, eyedir);\n";
988 text <<
"\t l_eyevec.z = dot(vtx_normal, eyedir);\n";
989 text <<
"\t l_eyevec = normalize(l_eyevec);\n";
991 if (need_eye_normal) {
992 if (pack_eye_normal) {
994 text <<
"\t float3 eye_normal = normalize(mul((float3x3)tpose_view_to_model, vtx_normal));\n";
995 text <<
"\t l_tangent.w = eye_normal.x;\n";
996 text <<
"\t l_binormal.w = eye_normal.y;\n";
997 text <<
"\t l_eye_position.w = eye_normal.z;\n";
999 text <<
"\t l_eye_normal = normalize(mul((float3x3)tpose_view_to_model, vtx_normal));\n";
1006 text <<
"void fshader(\n";
1007 if (key._fog_mode != 0) {
1008 text <<
"\t in float4 l_hpos : " << hpos_freg <<
",\n";
1009 text <<
"\t in uniform float4 attr_fog,\n";
1010 text <<
"\t in uniform float4 attr_fogcolor,\n";
1012 if (need_world_position) {
1013 text <<
"\t in float4 l_world_position : " << world_position_freg <<
",\n";
1015 if (need_world_normal) {
1016 text <<
"\t in float4 l_world_normal : " << world_normal_freg <<
",\n";
1018 if (need_eye_position) {
1019 text <<
"\t in float4 l_eye_position : " << eye_position_freg <<
",\n";
1021 if (need_eye_normal && !pack_eye_normal) {
1022 text <<
"\t in float3 l_eye_normal : " << eye_normal_freg <<
",\n";
1024 for (it = texcoord_fregs.begin(); it != texcoord_fregs.end(); ++it) {
1025 text <<
"\t in float4 l_" << it->first->join(
"_") <<
" : " << it->second <<
",\n";
1027 for (
size_t i = 0; i < key._textures.size(); ++i) {
1028 const ShaderKey::TextureInfo &tex = key._textures[i];
1029 if (tex._mode == TextureStage::M_modulate && tex._flags == 0) {
1034 text <<
"\t uniform sampler" << texture_type_as_string(tex._type) <<
" tex_" << i <<
",\n";
1036 if (tex._flags & ShaderKey::TF_has_texscale) {
1037 text <<
"\t uniform float3 texscale_" << i <<
",\n";
1038 }
else if (tex._flags & ShaderKey::TF_has_texmat) {
1039 text <<
"\t uniform float4x4 texmat_" << i <<
",\n";
1042 if (tex._flags & ShaderKey::TF_uses_color) {
1043 text <<
"\t uniform float4 texcolor_" << i <<
",\n";
1046 if (need_tangents) {
1047 text <<
"\t in float4 l_tangent : " << tangent_freg <<
",\n";
1048 text <<
"\t in float4 l_binormal : " << binormal_freg <<
",\n";
1050 for (
size_t i = 0; i < key._lights.size(); ++i) {
1051 text <<
"\t uniform float4x4 attr_light" << i <<
",\n";
1053 const ShaderKey::LightInfo &light = key._lights[i];
1054 if (light._flags & ShaderKey::LF_has_shadows) {
1055 if (light._type.is_derived_from(PointLight::get_class_type())) {
1056 text <<
"\t uniform samplerCUBE shadow_" << i <<
",\n";
1057 }
else if (_use_shadow_filter) {
1058 text <<
"\t uniform sampler2DShadow shadow_" << i <<
",\n";
1060 text <<
"\t uniform sampler2D shadow_" << i <<
",\n";
1062 if (lightcoord_fregs[i] !=
nullptr) {
1063 text <<
"\t in float4 l_lightcoord" << i <<
" : " << lightcoord_fregs[i] <<
",\n";
1065 text <<
"\t uniform float4x4 mat_shadow_" << i <<
",\n";
1068 if (light._flags & ShaderKey::LF_has_specular_color) {
1069 text <<
"\t uniform float4 attr_lspec" << i <<
",\n";
1074 if (key._material_flags & (Material::F_ambient | Material::F_diffuse | Material::F_emission | Material::F_specular)) {
1075 text <<
"\t uniform float4x4 attr_material,\n";
1077 if (key._texture_flags & ShaderKey::TF_map_height) {
1078 text <<
"\t float3 l_eyevec,\n";
1080 if (key._outputs & (AuxBitplaneAttrib::ABO_aux_normal | AuxBitplaneAttrib::ABO_aux_glow)) {
1081 text <<
"\t out float4 o_aux : COLOR1,\n";
1083 text <<
"\t out float4 o_color : COLOR0,\n";
1086 if (key._color_type == ColorAttrib::T_vertex) {
1087 text <<
"\t in float4 l_color : COLOR0,\n";
1088 }
else if (key._color_type == ColorAttrib::T_flat) {
1089 text <<
"\t uniform float4 attr_color,\n";
1093 for (
int i = 0; i < key._num_clip_planes; ++i) {
1094 text <<
"\t uniform float4 clipplane_" << i <<
",\n";
1097 text <<
"\t uniform float4 attr_ambient,\n";
1098 text <<
"\t uniform float4 attr_colorscale\n";
1102 for (
int i = 0; i < key._num_clip_planes; ++i) {
1103 text <<
"\t if (l_world_position.x * clipplane_" << i <<
".x + l_world_position.y ";
1104 text <<
"* clipplane_" << i <<
".y + l_world_position.z * clipplane_" << i <<
".z + clipplane_" << i <<
".w <= 0) {\n";
1105 text <<
"\t discard;\n";
1110 if (need_eye_normal && pack_eye_normal) {
1111 text <<
"\t float3 l_eye_normal = float3(l_tangent.w, l_binormal.w, l_eye_position.w);\n";
1114 text <<
"\t float4 result;\n";
1115 if (key._outputs & (AuxBitplaneAttrib::ABO_aux_normal | AuxBitplaneAttrib::ABO_aux_glow)) {
1116 text <<
"\t o_aux = float4(0, 0, 0, 0);\n";
1120 for (
size_t i = 0; i < key._textures.size(); ++i) {
1121 const ShaderKey::TextureInfo &tex = key._textures[i];
1122 if (tex._mode == TextureStage::M_modulate && tex._flags == 0) {
1126 switch (tex._gen_mode) {
1127 case TexGenAttrib::M_off:
1129 text <<
"\t float4 texcoord" << i <<
" = l_" << tex._texcoord_name->join(
"_") <<
";\n";
1131 case TexGenAttrib::M_world_position:
1132 text <<
"\t float4 texcoord" << i <<
" = l_world_position;\n";
1134 case TexGenAttrib::M_world_normal:
1135 text <<
"\t float4 texcoord" << i <<
" = l_world_normal;\n";
1137 case TexGenAttrib::M_eye_position:
1138 text <<
"\t float4 texcoord" << i <<
" = float4(l_eye_position.xyz, 1.0f);\n";
1140 case TexGenAttrib::M_eye_normal:
1141 text <<
"\t float4 texcoord" << i <<
" = float4(l_eye_normal, 1.0f);\n";
1144 text <<
"\t float4 texcoord" << i <<
" = float4(0, 0, 0, 0);\n";
1145 pgraphnodes_cat.error()
1146 <<
"Unsupported TexGenAttrib mode: " << tex._gen_mode <<
"\n";
1148 if (tex._flags & ShaderKey::TF_has_texscale) {
1149 text <<
"\t texcoord" << i <<
".xyz *= texscale_" << i <<
";\n";
1150 }
else if (tex._flags & ShaderKey::TF_has_texmat) {
1151 text <<
"\t texcoord" << i <<
" = mul(texmat_" << i <<
", texcoord" << i <<
");\n";
1152 text <<
"\t texcoord" << i <<
".xyz /= texcoord" << i <<
".w;\n";
1155 text <<
"\t // Fetch all textures.\n";
1156 for (
size_t i = 0; i < key._textures.size(); ++i) {
1157 const ShaderKey::TextureInfo &tex = key._textures[i];
1158 if ((tex._flags & ShaderKey::TF_map_height) == 0) {
1162 text <<
"\t float4 tex" << i <<
" = tex" << texture_type_as_string(tex._type);
1163 text <<
"(tex_" << i <<
", texcoord" << i <<
".";
1164 switch (tex._type) {
1165 case Texture::TT_cube_map:
1166 case Texture::TT_3d_texture:
1167 case Texture::TT_2d_texture_array:
1170 case Texture::TT_2d_texture:
1173 case Texture::TT_1d_texture:
1179 text <<
");\n\t float3 parallax_offset = l_eyevec.xyz * (tex" << i;
1180 if (tex._mode == TextureStage::M_normal_height ||
1181 (tex._flags & ShaderKey::TF_has_alpha) != 0) {
1186 text <<
" * 2.0 - 1.0) * " << parallax_mapping_scale <<
";\n";
1188 for (
int j = 0; j < parallax_mapping_samples - 1; ++j) {
1189 text <<
"\t parallax_offset = l_eyevec.xyz * (parallax_offset + (tex" << i;
1190 if (tex._mode == TextureStage::M_normal_height ||
1191 (tex._flags & ShaderKey::TF_has_alpha) != 0) {
1196 text <<
" * 2.0 - 1.0)) * " << 0.5 * parallax_mapping_scale <<
";\n";
1199 for (
size_t i = 0; i < key._textures.size(); ++i) {
1200 ShaderKey::TextureInfo &tex = key._textures[i];
1201 if (tex._mode == TextureStage::M_modulate && tex._flags == 0) {
1205 if ((tex._flags & ShaderKey::TF_map_height) == 0) {
1208 if (key._texture_flags & ShaderKey::TF_map_height) {
1209 text <<
"\t texcoord" << i <<
".xyz -= parallax_offset;\n";
1211 text <<
"\t float4 tex" << i <<
" = tex" << texture_type_as_string(tex._type);
1212 text <<
"(tex_" << i <<
", texcoord" << i <<
".";
1213 switch (tex._type) {
1214 case Texture::TT_cube_map:
1215 case Texture::TT_3d_texture:
1216 case Texture::TT_2d_texture_array:
1219 case Texture::TT_2d_texture:
1222 case Texture::TT_1d_texture:
1231 if (need_eye_normal) {
1232 text <<
"\t // Correct the surface normal for interpolation effects\n";
1233 text <<
"\t l_eye_normal = normalize(l_eye_normal);\n";
1235 if (need_tangents) {
1236 text <<
"\t // Translate tangent-space normal in map to view-space.\n";
1239 bool is_first =
true;
1240 for (
size_t i = 0; i < key._textures.size(); ++i) {
1241 const ShaderKey::TextureInfo &tex = key._textures[i];
1242 if (tex._flags & ShaderKey::TF_map_normal) {
1244 text <<
"\t float3 tsnormal = normalize((tex" << i <<
".xyz * 2) - 1);\n";
1248 text <<
"\t tsnormal.z += 1;\n";
1249 text <<
"\t float3 tmp" << i <<
" = tex" << i <<
".xyz * float3(-2, -2, 2) + float3(1, 1, -1);\n";
1250 text <<
"\t tsnormal = normalize(tsnormal * dot(tsnormal, tmp" << i <<
") - tmp" << i <<
" * tsnormal.z);\n";
1253 text <<
"\t l_eye_normal *= tsnormal.z;\n";
1254 text <<
"\t l_eye_normal += normalize(l_tangent.xyz) * tsnormal.x;\n";
1255 text <<
"\t l_eye_normal += normalize(l_binormal.xyz) * tsnormal.y;\n";
1256 text <<
"\t l_eye_normal = normalize(l_eye_normal);\n";
1258 if (key._outputs & AuxBitplaneAttrib::ABO_aux_normal) {
1259 text <<
"\t // Output the camera-space surface normal\n";
1260 text <<
"\t o_aux.rgb = (l_eye_normal*0.5) + float3(0.5,0.5,0.5);\n";
1262 if (key._lighting) {
1263 text <<
"\t // Begin view-space light calculations\n";
1264 text <<
"\t float ldist,lattenv,langle,lshad;\n";
1265 text <<
"\t float4 lcolor,lspec,lpoint,latten,ldir,leye;\n";
1266 text <<
"\t float3 lvec,lhalf;\n";
1267 if (key._have_separate_ambient) {
1268 text <<
"\t float4 tot_ambient = float4(0,0,0,0);\n";
1270 text <<
"\t float4 tot_diffuse = float4(0,0,0,0);\n";
1271 if (have_specular) {
1272 text <<
"\t float4 tot_specular = float4(0,0,0,0);\n";
1273 if (key._material_flags & Material::F_specular) {
1274 text <<
"\t float shininess = attr_material[3].w;\n";
1276 text <<
"\t float shininess = 50; // no shininess specified, using default\n";
1279 if (key._have_separate_ambient) {
1280 text <<
"\t tot_ambient += attr_ambient;\n";
1282 text <<
"\t tot_diffuse += attr_ambient;\n";
1285 for (
size_t i = 0; i < key._lights.size(); ++i) {
1286 const ShaderKey::LightInfo &light = key._lights[i];
1288 if (light._flags & ShaderKey::LF_has_shadows) {
1289 if (lightcoord_fregs[i] ==
nullptr) {
1292 text <<
"\t float4 l_lightcoord" << i <<
" = mul(mat_shadow_" << i <<
", float4(l_eye_position.xyz, 1.0f));\n";
1296 if (light._type.is_derived_from(DirectionalLight::get_class_type())) {
1297 text <<
"\t // Directional Light " << i <<
"\n";
1298 text <<
"\t lcolor = attr_light" << i <<
"[0];\n";
1299 if (light._flags & ShaderKey::LF_has_specular_color) {
1300 text <<
"\t lspec = attr_lspec" << i <<
";\n";
1302 text <<
"\t lspec = lcolor;\n";
1304 text <<
"\t lvec = attr_light" << i <<
"[3].xyz;\n";
1305 text <<
"\t lcolor *= saturate(dot(l_eye_normal, lvec.xyz));\n";
1306 if (light._flags & ShaderKey::LF_has_shadows) {
1307 if (_use_shadow_filter) {
1308 text <<
"\t lshad = shadow2DProj(shadow_" << i <<
", l_lightcoord" << i <<
").r;\n";
1310 text <<
"\t lshad = tex2Dproj(shadow_" << i <<
", l_lightcoord" << i <<
").r > l_lightcoord" << i <<
".z / l_lightcoord" << i <<
".w;\n";
1312 text <<
"\t lcolor *= lshad;\n";
1313 text <<
"\t lspec *= lshad;\n";
1315 text <<
"\t tot_diffuse += lcolor;\n";
1316 if (have_specular) {
1317 if (key._material_flags & Material::F_local) {
1318 text <<
"\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
1320 text <<
"\t lhalf = normalize(lvec - float3(0, 1, 0));\n";
1322 text <<
"\t lspec *= pow(saturate(dot(l_eye_normal, lhalf)), shininess);\n";
1323 text <<
"\t tot_specular += lspec;\n";
1325 }
else if (light._type.is_derived_from(PointLight::get_class_type())) {
1326 text <<
"\t // Point Light " << i <<
"\n";
1327 text <<
"\t lcolor = attr_light" << i <<
"[0];\n";
1328 if (light._flags & ShaderKey::LF_has_specular_color) {
1329 text <<
"\t lspec = attr_lspec" << i <<
";\n";
1331 text <<
"\t lspec = lcolor;\n";
1333 text <<
"\t latten = attr_light" << i <<
"[1];\n";
1334 text <<
"\t lpoint = attr_light" << i <<
"[3];\n";
1335 text <<
"\t lvec = lpoint.xyz - l_eye_position.xyz;\n";
1336 text <<
"\t ldist = length(lvec);\n";
1337 text <<
"\t lvec /= ldist;\n";
1338 if (light._type.is_derived_from(SphereLight::get_class_type())) {
1339 text <<
"\t ldist = max(ldist, attr_light" << i <<
"[2].w);\n";
1341 text <<
"\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
1342 text <<
"\t lcolor *= lattenv * saturate(dot(l_eye_normal, lvec));\n";
1343 if (light._flags & ShaderKey::LF_has_shadows) {
1344 text <<
"\t ldist = max(abs(l_lightcoord" << i <<
".x), max(abs(l_lightcoord" << i <<
".y), abs(l_lightcoord" << i <<
".z)));\n";
1345 text <<
"\t ldist = ((latten.w+lpoint.w)/(latten.w-lpoint.w))+((-2*latten.w*lpoint.w)/(ldist * (latten.w-lpoint.w)));\n";
1346 text <<
"\t lshad = texCUBE(shadow_" << i <<
", l_lightcoord" << i <<
".xyz).r >= ldist * 0.5 + 0.5;\n";
1347 text <<
"\t lcolor *= lshad;\n";
1348 text <<
"\t lspec *= lshad;\n";
1350 text <<
"\t tot_diffuse += lcolor;\n";
1351 if (have_specular) {
1352 if (key._material_flags & Material::F_local) {
1353 text <<
"\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
1355 text <<
"\t lhalf = normalize(lvec - float3(0, 1, 0));\n";
1357 text <<
"\t lspec *= lattenv;\n";
1358 text <<
"\t lspec *= pow(saturate(dot(l_eye_normal, lhalf)), shininess);\n";
1359 text <<
"\t tot_specular += lspec;\n";
1361 }
else if (light._type.is_derived_from(Spotlight::get_class_type())) {
1362 text <<
"\t // Spot Light " << i <<
"\n";
1363 text <<
"\t lcolor = attr_light" << i <<
"[0];\n";
1364 if (light._flags & ShaderKey::LF_has_specular_color) {
1365 text <<
"\t lspec = attr_lspec" << i <<
";\n";
1367 text <<
"\t lspec = lcolor;\n";
1369 text <<
"\t latten = attr_light" << i <<
"[1];\n";
1370 text <<
"\t ldir = attr_light" << i <<
"[2];\n";
1371 text <<
"\t lpoint = attr_light" << i <<
"[3];\n";
1372 text <<
"\t lvec = lpoint.xyz - l_eye_position.xyz;\n";
1373 text <<
"\t ldist = length(lvec);\n";
1374 text <<
"\t lvec /= ldist;\n";
1375 text <<
"\t langle = saturate(dot(ldir.xyz, lvec));\n";
1376 text <<
"\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
1377 text <<
"\t lattenv *= pow(langle, latten.w);\n";
1378 text <<
"\t if (langle < ldir.w) lattenv = 0;\n";
1379 text <<
"\t lcolor *= lattenv * saturate(dot(l_eye_normal, lvec));\n";
1380 if (light._flags & ShaderKey::LF_has_shadows) {
1381 if (_use_shadow_filter) {
1382 text <<
"\t lshad = shadow2DProj(shadow_" << i <<
", l_lightcoord" << i <<
").r;\n";
1384 text <<
"\t lshad = tex2Dproj(shadow_" << i <<
", l_lightcoord" << i <<
").r > l_lightcoord" << i <<
".z / l_lightcoord" << i <<
".w;\n";
1386 text <<
"\t lcolor *= lshad;\n";
1387 text <<
"\t lspec *= lshad;\n";
1390 text <<
"\t tot_diffuse += lcolor;\n";
1391 if (have_specular) {
1392 if (key._material_flags & Material::F_local) {
1393 text <<
"\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
1395 text <<
"\t lhalf = normalize(lvec - float3(0,1,0));\n";
1397 text <<
"\t lspec *= lattenv;\n";
1398 text <<
"\t lspec *= pow(saturate(dot(l_eye_normal, lhalf)), shininess);\n";
1399 text <<
"\t tot_specular += lspec;\n";
1403 if (key._lighting) {
1404 if (key._light_ramp !=
nullptr) {
1405 switch (key._light_ramp->get_mode()) {
1406 case LightRampAttrib::LRT_single_threshold:
1408 PN_stdfloat t = key._light_ramp->get_threshold(0);
1409 PN_stdfloat l0 = key._light_ramp->get_level(0);
1410 text <<
"\t // Single-threshold light ramp\n";
1411 text <<
"\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
1412 text <<
"\t float lr_scale = (lr_in < " << t <<
") ? 0.0 : (" << l0 <<
"/lr_in);\n";
1413 text <<
"\t tot_diffuse = tot_diffuse * lr_scale;\n";
1416 case LightRampAttrib::LRT_double_threshold:
1418 PN_stdfloat t0 = key._light_ramp->get_threshold(0);
1419 PN_stdfloat t1 = key._light_ramp->get_threshold(1);
1420 PN_stdfloat l0 = key._light_ramp->get_level(0);
1421 PN_stdfloat l1 = key._light_ramp->get_level(1);
1422 text <<
"\t // Double-threshold light ramp\n";
1423 text <<
"\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
1424 text <<
"\t float lr_out = 0.0;\n";
1425 text <<
"\t if (lr_in > " << t0 <<
") lr_out=" << l0 <<
";\n";
1426 text <<
"\t if (lr_in > " << t1 <<
") lr_out=" << l1 <<
";\n";
1427 text <<
"\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n";
1434 text <<
"\t // Begin view-space light summation\n";
1435 if (key._material_flags & Material::F_emission) {
1436 if (key._texture_flags & ShaderKey::TF_map_glow) {
1437 text <<
"\t result = attr_material[2] * saturate(2 * (tex" << map_index_glow <<
".a - 0.5));\n";
1439 text <<
"\t result = attr_material[2];\n";
1442 if (key._texture_flags & ShaderKey::TF_map_glow) {
1443 text <<
"\t result = saturate(2 * (tex" << map_index_glow <<
".a - 0.5));\n";
1445 text <<
"\t result = float4(0,0,0,0);\n";
1448 if (key._have_separate_ambient) {
1449 if (key._material_flags & Material::F_ambient) {
1450 text <<
"\t result += tot_ambient * attr_material[0];\n";
1451 }
else if (key._color_type == ColorAttrib::T_vertex) {
1452 text <<
"\t result += tot_ambient * l_color;\n";
1453 }
else if (key._color_type == ColorAttrib::T_flat) {
1454 text <<
"\t result += tot_ambient * attr_color;\n";
1456 text <<
"\t result += tot_ambient;\n";
1459 if (key._material_flags & Material::F_diffuse) {
1460 text <<
"\t result += tot_diffuse * attr_material[1];\n";
1461 }
else if (key._color_type == ColorAttrib::T_vertex) {
1462 text <<
"\t result += tot_diffuse * l_color;\n";
1463 }
else if (key._color_type == ColorAttrib::T_flat) {
1464 text <<
"\t result += tot_diffuse * attr_color;\n";
1466 text <<
"\t result += tot_diffuse;\n";
1468 if (key._light_ramp ==
nullptr ||
1469 key._light_ramp->get_mode() == LightRampAttrib::LRT_default) {
1470 text <<
"\t result = saturate(result);\n";
1472 text <<
"\t // End view-space light calculations\n";
1476 if (key._calc_primary_alpha) {
1477 if (key._color_type == ColorAttrib::T_vertex) {
1478 text <<
"\t result.a = l_color.a;\n";
1479 }
else if (key._color_type == ColorAttrib::T_flat) {
1480 text <<
"\t result.a = attr_color.a;\n";
1482 text <<
"\t result.a = 1;\n";
1486 if (key._color_type == ColorAttrib::T_vertex) {
1487 text <<
"\t result = l_color;\n";
1488 }
else if (key._color_type == ColorAttrib::T_flat) {
1489 text <<
"\t result = attr_color;\n";
1491 text <<
"\t result = float4(1, 1, 1, 1);\n";
1496 text <<
"\t result *= attr_colorscale;\n";
1499 if (key._texture_flags & ShaderKey::TF_uses_primary_color) {
1500 text <<
"\t float4 primary_color = result;\n";
1502 if (key._texture_flags & ShaderKey::TF_uses_last_saved_result) {
1503 text <<
"\t float4 last_saved_result = result;\n";
1507 for (
size_t i = 0; i < key._textures.size(); ++i) {
1508 const ShaderKey::TextureInfo &tex = key._textures[i];
1509 TextureStage::CombineMode combine_rgb, combine_alpha;
1511 switch (tex._mode) {
1512 case TextureStage::M_modulate:
1513 if ((tex._flags & ShaderKey::TF_has_rgb) != 0 &&
1514 (tex._flags & ShaderKey::TF_has_alpha) != 0) {
1515 text <<
"\t result.rgba *= tex" << i <<
".rgba;\n";
1516 }
else if (tex._flags & ShaderKey::TF_has_alpha) {
1517 text <<
"\t result.a *= tex" << i <<
".a;\n";
1518 }
else if (tex._flags & ShaderKey::TF_has_rgb) {
1519 text <<
"\t result.rgb *= tex" << i <<
".rgb;\n";
1522 case TextureStage::M_modulate_glow:
1523 case TextureStage::M_modulate_gloss:
1529 text <<
"\t result.rgb *= tex" << i <<
";\n";
1531 case TextureStage::M_decal:
1532 text <<
"\t result.rgb = lerp(result, tex" << i <<
", tex" << i <<
".a).rgb;\n";
1534 case TextureStage::M_blend:
1535 text <<
"\t result.rgb = lerp(result.rgb, texcolor_" << i <<
".rgb, tex" << i <<
".rgb);\n";
1536 if (key._calc_primary_alpha) {
1537 text <<
"\t result.a *= tex" << i <<
".a;\n";
1540 case TextureStage::M_replace:
1541 text <<
"\t result = tex" << i <<
";\n";
1543 case TextureStage::M_add:
1544 text <<
"\t result.rgb += tex" << i <<
".rgb;\n";
1545 if (key._calc_primary_alpha) {
1546 text <<
"\t result.a *= tex" << i <<
".a;\n";
1549 case TextureStage::M_combine:
1550 combine_rgb = (TextureStage::CombineMode)((tex._flags & ShaderKey::TF_COMBINE_RGB_MODE_MASK) >> ShaderKey::TF_COMBINE_RGB_MODE_SHIFT);
1551 combine_alpha = (TextureStage::CombineMode)((tex._flags & ShaderKey::TF_COMBINE_ALPHA_MODE_MASK) >> ShaderKey::TF_COMBINE_ALPHA_MODE_SHIFT);
1552 if (combine_rgb == TextureStage::CM_dot3_rgba) {
1553 text <<
"\t result = ";
1554 text << combine_mode_as_string(tex, combine_rgb,
false, i);
1557 text <<
"\t result.rgb = ";
1558 text << combine_mode_as_string(tex, combine_rgb,
false, i);
1559 text <<
";\n\t result.a = ";
1560 text << combine_mode_as_string(tex, combine_alpha,
true, i);
1563 if (tex._flags & ShaderKey::TF_rgb_scale_2) {
1564 text <<
"\t result.rgb *= 2;\n";
1566 if (tex._flags & ShaderKey::TF_rgb_scale_4) {
1567 text <<
"\t result.rgb *= 4;\n";
1569 if (tex._flags & ShaderKey::TF_alpha_scale_2) {
1570 text <<
"\t result.a *= 2;\n";
1572 if (tex._flags & ShaderKey::TF_alpha_scale_4) {
1573 text <<
"\t result.a *= 4;\n";
1576 case TextureStage::M_blend_color_scale:
1577 text <<
"\t result.rgb = lerp(result.rgb, texcolor_" << i <<
".rgb * attr_colorscale.rgb, tex" << i <<
".rgb);\n";
1578 if (key._calc_primary_alpha) {
1579 text <<
"\t result.a *= texcolor_" << i <<
".a * attr_colorscale.a;\n";
1585 if (tex._flags & ShaderKey::TF_saved_result) {
1586 text <<
"\t last_saved_result = result;\n";
1590 if (key._alpha_test_mode != RenderAttrib::M_none) {
1591 text <<
"\t // Shader includes alpha test:\n";
1592 double ref = key._alpha_test_ref;
1593 switch (key._alpha_test_mode) {
1594 case RenderAttrib::M_never:
1595 text <<
"\t discard;\n";
1597 case RenderAttrib::M_less:
1598 text <<
"\t if (result.a >= " <<
ref <<
") discard;\n";
1600 case RenderAttrib::M_equal:
1601 text <<
"\t if (result.a != " <<
ref <<
") discard;\n";
1603 case RenderAttrib::M_less_equal:
1604 text <<
"\t if (result.a > " <<
ref <<
") discard;\n";
1606 case RenderAttrib::M_greater:
1607 text <<
"\t if (result.a <= " <<
ref <<
") discard;\n";
1609 case RenderAttrib::M_not_equal:
1610 text <<
"\t if (result.a == " <<
ref <<
") discard;\n";
1612 case RenderAttrib::M_greater_equal:
1613 text <<
"\t if (result.a < " <<
ref <<
") discard;\n";
1615 case RenderAttrib::M_none:
1616 case RenderAttrib::M_always:
1621 if (key._outputs & AuxBitplaneAttrib::ABO_glow) {
1622 if (key._texture_flags & ShaderKey::TF_map_glow) {
1623 text <<
"\t result.a = tex" << map_index_glow <<
".a;\n";
1625 text <<
"\t result.a = 0.5;\n";
1628 if (key._outputs & AuxBitplaneAttrib::ABO_aux_glow) {
1629 if (key._texture_flags & ShaderKey::TF_map_glow) {
1630 text <<
"\t o_aux.a = tex" << map_index_glow <<
".a;\n";
1632 text <<
"\t o_aux.a = 0.5;\n";
1636 if (have_specular) {
1637 if (key._material_flags & Material::F_specular) {
1638 text <<
"\t tot_specular *= attr_material[3];\n";
1640 if (key._texture_flags & ShaderKey::TF_map_gloss) {
1641 text <<
"\t tot_specular *= tex" << map_index_gloss <<
".a;\n";
1643 text <<
"\t result.rgb = result.rgb + tot_specular.rgb;\n";
1645 if (key._light_ramp !=
nullptr) {
1646 switch (key._light_ramp->get_mode()) {
1647 case LightRampAttrib::LRT_hdr0:
1648 text <<
"\t result.rgb = (result*result*result + result*result + result) / (result*result*result + result*result + result + 1);\n";
1650 case LightRampAttrib::LRT_hdr1:
1651 text <<
"\t result.rgb = (result*result + result) / (result*result + result + 1);\n";
1653 case LightRampAttrib::LRT_hdr2:
1654 text <<
"\t result.rgb = result / (result + 1);\n";
1661 if (key._fog_mode != 0) {
1662 Fog::Mode fog_mode = (Fog::Mode)(key._fog_mode - 1);
1665 text <<
"\t result.rgb = lerp(attr_fogcolor.rgb, result.rgb, saturate((attr_fog.z - l_hpos.z) * attr_fog.w));\n";
1667 case Fog::M_exponential:
1668 text <<
"\t result.rgb = lerp(attr_fogcolor.rgb, result.rgb, saturate(exp2(attr_fog.x * l_hpos.z * -1.442695f)));\n";
1670 case Fog::M_exponential_squared:
1671 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";
1678 text <<
"\t o_color = result * 1.000001;\n";
1679 if (key._alpha_test_mode != RenderAttrib::M_none) {
1680 text <<
"\t // Shader subsumes normal alpha test.\n";
1682 if (key._disable_alpha_write) {
1683 text <<
"\t // Shader disables alpha write.\n";
1687 if (pgraphnodes_cat.is_spam()) {
1688 pgraphnodes_cat.spam() <<
"Generated shader:\n" 1689 << text.str() <<
"\n";
1693 PT(
Shader) shader = Shader::make(text.str(), Shader::SL_Cg);
1694 nassertr(shader !=
nullptr,
nullptr);
1697 if (key._alpha_test_mode != RenderAttrib::M_none) {
1698 shattr = DCAST(
ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_subsume_alpha_test,
true);
1700 if (key._disable_alpha_write) {
1701 shattr = DCAST(
ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_disable_alpha_write,
true);
1704 reset_register_allocator();
1707 _generated_shaders[key] = attr;
1714 string ShaderGenerator::
1715 combine_mode_as_string(
const ShaderKey::TextureInfo &info, TextureStage::CombineMode c_mode,
bool alpha,
short texindex) {
1716 std::ostringstream text;
1718 case TextureStage::CM_modulate:
1719 text << combine_source_as_string(info, 0, alpha, texindex);
1721 text << combine_source_as_string(info, 1, alpha, texindex);
1723 case TextureStage::CM_add:
1724 text << combine_source_as_string(info, 0, alpha, texindex);
1726 text << combine_source_as_string(info, 1, alpha, texindex);
1728 case TextureStage::CM_add_signed:
1729 text << combine_source_as_string(info, 0, alpha, texindex);
1731 text << combine_source_as_string(info, 1, alpha, texindex);
1735 text <<
" - float3(0.5, 0.5, 0.5)";
1738 case TextureStage::CM_interpolate:
1740 text << combine_source_as_string(info, 1, alpha, texindex);
1742 text << combine_source_as_string(info, 0, alpha, texindex);
1744 text << combine_source_as_string(info, 2, alpha, texindex);
1747 case TextureStage::CM_subtract:
1748 text << combine_source_as_string(info, 0, alpha, texindex);
1750 text << combine_source_as_string(info, 1, alpha, texindex);
1752 case TextureStage::CM_dot3_rgb:
1753 case TextureStage::CM_dot3_rgba:
1755 text << combine_source_as_string(info, 0, alpha, texindex);
1756 text <<
" - float3(0.5), ";
1757 text << combine_source_as_string(info, 1, alpha, texindex);
1758 text <<
" - float3(0.5))";
1760 case TextureStage::CM_replace:
1762 text << combine_source_as_string(info, 0, alpha, texindex);
1771 string ShaderGenerator::
1772 combine_source_as_string(
const ShaderKey::TextureInfo &info,
short num,
bool alpha,
short texindex) {
1773 TextureStage::CombineSource c_src;
1774 TextureStage::CombineOperand c_op;
1776 c_src = UNPACK_COMBINE_SRC(info._combine_rgb, num);
1777 c_op = UNPACK_COMBINE_OP(info._combine_rgb, num);
1779 c_src = UNPACK_COMBINE_SRC(info._combine_alpha, num);
1780 c_op = UNPACK_COMBINE_OP(info._combine_alpha, num);
1782 std::ostringstream csource;
1783 if (c_op == TextureStage::CO_one_minus_src_color ||
1784 c_op == TextureStage::CO_one_minus_src_alpha) {
1785 csource <<
"saturate(1.0f - ";
1788 case TextureStage::CS_undefined:
1789 case TextureStage::CS_texture:
1790 csource <<
"tex" << texindex;
1792 case TextureStage::CS_constant:
1793 csource <<
"texcolor_" << texindex;
1795 case TextureStage::CS_primary_color:
1796 csource <<
"primary_color";
1798 case TextureStage::CS_previous:
1799 csource <<
"result";
1801 case TextureStage::CS_constant_color_scale:
1802 csource <<
"attr_colorscale";
1804 case TextureStage::CS_last_saved_result:
1805 csource <<
"last_saved_result";
1808 if (c_op == TextureStage::CO_one_minus_src_color ||
1809 c_op == TextureStage::CO_one_minus_src_alpha) {
1812 if (c_op == TextureStage::CO_src_color || c_op == TextureStage::CO_one_minus_src_color) {
1818 return "float3(" + csource.str() +
")";
1821 return csource.str();
1827 const char *ShaderGenerator::
1828 texture_type_as_string(Texture::TextureType ttype) {
1830 case Texture::TT_1d_texture:
1833 case Texture::TT_2d_texture:
1836 case Texture::TT_3d_texture:
1839 case Texture::TT_cube_map:
1842 case Texture::TT_2d_texture_array:
1846 pgraphnodes_cat.error() <<
"Unsupported texture type!\n";
1854 ShaderGenerator::ShaderKey::
1860 _have_separate_ambient(false),
1863 _calc_primary_alpha(false),
1864 _disable_alpha_write(false),
1866 _alpha_test_ref(0.0),
1867 _num_clip_planes(0),
1868 _light_ramp(nullptr) {
1875 bool ShaderGenerator::ShaderKey::
1876 operator < (
const ShaderKey &other)
const {
1877 if (_anim_spec != other._anim_spec) {
1878 return _anim_spec < other._anim_spec;
1880 if (_color_type != other._color_type) {
1881 return _color_type < other._color_type;
1883 if (_material_flags != other._material_flags) {
1884 return _material_flags < other._material_flags;
1886 if (_texture_flags != other._texture_flags) {
1887 return _texture_flags < other._texture_flags;
1889 if (_textures.size() != other._textures.size()) {
1890 return _textures.size() < other._textures.size();
1892 for (
size_t i = 0; i < _textures.size(); ++i) {
1893 const ShaderKey::TextureInfo &tex = _textures[i];
1894 const ShaderKey::TextureInfo &other_tex = other._textures[i];
1895 if (tex._texcoord_name != other_tex._texcoord_name) {
1896 return tex._texcoord_name < other_tex._texcoord_name;
1898 if (tex._type != other_tex._type) {
1899 return tex._type < other_tex._type;
1901 if (tex._mode != other_tex._mode) {
1902 return tex._mode < other_tex._mode;
1904 if (tex._gen_mode != other_tex._gen_mode) {
1905 return tex._gen_mode < other_tex._gen_mode;
1907 if (tex._flags != other_tex._flags) {
1908 return tex._flags < other_tex._flags;
1910 if (tex._combine_rgb != other_tex._combine_rgb) {
1911 return tex._combine_rgb < other_tex._combine_rgb;
1913 if (tex._combine_alpha != other_tex._combine_alpha) {
1914 return tex._combine_alpha < other_tex._combine_alpha;
1917 if (_lights.size() != other._lights.size()) {
1918 return _lights.size() < other._lights.size();
1920 for (
size_t i = 0; i < _lights.size(); ++i) {
1921 const ShaderKey::LightInfo &light = _lights[i];
1922 const ShaderKey::LightInfo &other_light = other._lights[i];
1923 if (light._type != other_light._type) {
1924 return light._type < other_light._type;
1926 if (light._flags != other_light._flags) {
1927 return light._flags < other_light._flags;
1930 if (_lighting != other._lighting) {
1931 return _lighting < other._lighting;
1933 if (_have_separate_ambient != other._have_separate_ambient) {
1934 return _have_separate_ambient < other._have_separate_ambient;
1936 if (_fog_mode != other._fog_mode) {
1937 return _fog_mode < other._fog_mode;
1939 if (_outputs != other._outputs) {
1940 return _outputs < other._outputs;
1942 if (_calc_primary_alpha != other._calc_primary_alpha) {
1943 return _calc_primary_alpha < other._calc_primary_alpha;
1945 if (_disable_alpha_write != other._disable_alpha_write) {
1946 return _disable_alpha_write < other._disable_alpha_write;
1948 if (_alpha_test_mode != other._alpha_test_mode) {
1949 return _alpha_test_mode < other._alpha_test_mode;
1951 if (_alpha_test_ref != other._alpha_test_ref) {
1952 return _alpha_test_ref < other._alpha_test_ref;
1954 if (_num_clip_planes != other._num_clip_planes) {
1955 return _num_clip_planes < other._num_clip_planes;
1957 return _light_ramp < other._light_ramp;
1963 bool ShaderGenerator::ShaderKey::
1964 operator == (
const ShaderKey &other)
const {
1965 if (_anim_spec != other._anim_spec) {
1968 if (_color_type != other._color_type) {
1971 if (_material_flags != other._material_flags) {
1974 if (_texture_flags != other._texture_flags) {
1977 if (_textures.size() != other._textures.size()) {
1980 for (
size_t i = 0; i < _textures.size(); ++i) {
1981 const ShaderKey::TextureInfo &tex = _textures[i];
1982 const ShaderKey::TextureInfo &other_tex = other._textures[i];
1983 if (tex._texcoord_name != other_tex._texcoord_name ||
1984 tex._type != other_tex._type ||
1985 tex._mode != other_tex._mode ||
1986 tex._gen_mode != other_tex._gen_mode ||
1987 tex._flags != other_tex._flags ||
1988 tex._combine_rgb != other_tex._combine_rgb ||
1989 tex._combine_alpha != other_tex._combine_alpha) {
1993 if (_lights.size() != other._lights.size()) {
1996 for (
size_t i = 0; i < _lights.size(); ++i) {
1997 const ShaderKey::LightInfo &light = _lights[i];
1998 const ShaderKey::LightInfo &other_light = other._lights[i];
1999 if (light._type != other_light._type ||
2000 light._flags != other_light._flags) {
2004 return _lighting == other._lighting
2005 && _have_separate_ambient == other._have_separate_ambient
2006 && _fog_mode == other._fog_mode
2007 && _outputs == other._outputs
2008 && _calc_primary_alpha == other._calc_primary_alpha
2009 && _disable_alpha_write == other._disable_alpha_write
2010 && _alpha_test_mode == other._alpha_test_mode
2011 && _alpha_test_ref == other._alpha_test_ref
2012 && _num_clip_planes == other._num_clip_planes
2013 && _light_ramp == other._light_ramp;
CombineSource get_combine_alpha_source2() const
Get source2 of combine_alpha_mode.
is_shadow_caster
Returns whether this light is configured to cast shadows or not.
A basic node of the scene graph or data graph.
This is our own Panda specialization on the default STL map.
bool auto_shader() const
If true, then this ShaderAttrib does not contain an explicit shader - instead, it requests the automa...
get_mode
Returns the transparency mode.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
CombineOperand get_combine_alpha_operand0() const
Get operand0 of combine_alpha_mode.
bool has_specular_color() const
Returns true if this light defines a specular color, false if the specular color is derived automatic...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_reference_alpha
Returns the alpha reference value.
bool is_empty() const
Returns true if the NodePath contains no nodes.
Indicates which, if any, material should be applied to geometry.
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded.
get_num_on_stages
Returns the number of stages that are turned on by the attribute.
get_on_stage
Returns the nth stage turned on by the attribute, sorted in render order.
This controls the enabling of transparency.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_fog
If the FogAttrib is not an 'off' FogAttrib, returns the fog that is associated.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
This functions similarly to a LightAttrib.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A Light Ramp is any unary operator that takes a rendered pixel as input, and adjusts the brightness o...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void clear()
Completely empties the table.
CombineOperand get_combine_rgb_operand1() const
Get operand1 of combine_rgb_mode.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CombineSource get_combine_rgb_source1() const
Get source1 of combine_rgb_mode.
get_rgb_scale
See set_rgb_scale().
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is our own Panda specialization on the default STL vector.
Applies a Fog to the geometry at and below this node.
Modern frame buffers can have 'aux' bitplanes, which are additional bitplanes above and beyond the st...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
size_t get_num_entries() const
Returns the number of active entries in the table.
A lightweight class that represents a single element that may be timed and/or counted via stats.
get_mode
Returns the blending mode for the RGB channels.
get_format
Returns the format of the texture, which represents both the semantic meaning of the texels and,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool uses_last_saved_result() const
Returns true if the TextureStage makes use of the CS_primary_color combine source.
CombineSource get_combine_alpha_source0() const
Get source0 of combine_alpha_mode.
bool uses_primary_color() const
Returns true if the TextureStage makes use of the CS_primary_color combine source.
void mark_used_by_auto_shader() const
Marks this light as having been used by the auto shader.
CombineSource get_combine_rgb_source2() const
Get source2 of combine_rgb_mode.
get_on_light
Returns the nth light turned on by the attribute, sorted in render order.
static bool has_alpha(Format format)
Returns true if the indicated format includes alpha, false otherwise.
get_num_on_planes
Returns the number of planes that are enabled by the attribute.
CombineOperand get_combine_rgb_operand0() const
Get operand0 of combine_rgb_mode.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const Key & get_key(size_t n) const
Returns the key in the nth entry of the table.
get_num_on_lights
Returns the number of lights that are turned on by the attribute.
get_saved_result
Returns the current setting of the saved_result flag.
CombineMode get_combine_alpha_mode() const
Get combine_alpha_mode.
get_alpha_scale
See set_alpha_scale().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Enables or disables writing of pixel to framebuffer based on its alpha value relative to a reference ...
CombineOperand get_combine_alpha_operand1() const
Get operand1 of combine_alpha_mode.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Defines the way an object appears in the presence of lighting.
Similar to MutexHolder, but for a light reentrant mutex.
Encodes a string name in a hash table, mapping it to a pointer.
void ref() const
Explicitly increments the reference count.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Applies a transform matrix to UV's before they are rendered.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_material
If the MaterialAttrib is not an 'off' MaterialAttrib, returns the material that is associated.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This specifies how colors are blended into the frame buffer, for special effects.
CombineMode get_combine_rgb_mode() const
Get the combine_rgb_mode.
PandaNode * node() const
Returns the referenced node of the path.
CombineSource get_combine_rgb_source0() const
Get source0 of combine_rgb_mode.
A derivative of Light and of Camera.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Indicates what color should be applied to renderable geometry.
CombineOperand get_combine_rgb_operand2() const
Get operand2 of combine_rgb_mode.
CombineSource get_combine_alpha_source1() const
Get source1 of combine_alpha_mode.
CombineOperand get_combine_alpha_operand2() const
Get operand2 of combine_alpha_mode.
bool uses_color() const
Returns true if the TextureStage makes use of whatever color is specified in set_color(),...
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool is_off() const
Returns true if the FogAttrib is an 'off' FogAttrib, indicating that it should disable fog.
get_mode
Returns the alpha write mode.
Defines the properties of a named stage of the multitexture pipeline.
Computes texture coordinates for geometry automatically based on vertex position and/or normal.
get_color_type
Returns the type of color specified by this ColorAttrib.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_texcoord_name
See set_texcoord_name.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Indicates which set of lights should be considered "on" to illuminate geometry at this level and belo...
get_on_texture
Returns the texture associated with the indicated stage, or NULL if no texture is associated.