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);
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);
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;
470 case TextureStage::M_emission:
471 info._flags = ShaderKey::TF_map_emission;
480 info._type = Texture::TT_1d_texture;
481 info._mode = TextureStage::M_modulate;
483 key._textures.push_back(info);
489 if (tex_matrix->has_stage(stage)) {
491 if (!transform->is_identity()) {
494 if (transform->has_components() && !transform->has_nonzero_shear() &&
495 transform->get_pos() == LPoint3::zero() &&
496 transform->get_hpr() == LVecBase3::zero()) {
497 info._flags |= ShaderKey::TF_has_texscale;
499 info._flags |= ShaderKey::TF_has_texmat;
504 if (tex_gen->has_stage(stage)) {
505 info._texcoord_name =
nullptr;
506 info._gen_mode = tex_gen->get_mode(stage);
509 info._gen_mode = TexGenAttrib::M_off;
514 info._flags |= ShaderKey::TF_saved_result;
519 info._flags |= ShaderKey::TF_uses_color;
522 key._textures.push_back(info);
523 key._texture_flags |= info._flags;
527 if ((key._texture_flags & ShaderKey::TF_uses_last_saved_result) == 0 &&
528 (key._texture_flags & ShaderKey::TF_saved_result) != 0) {
531 for (it = key._textures.begin(); it != key._textures.end(); ++it) {
532 (*it)._flags &= ~ShaderKey::TF_saved_result;
534 key._texture_flags &= ~ShaderKey::TF_saved_result;
539 if (key._material_flags & Material::F_ambient) {
540 key._have_separate_ambient =
true;
542 if (key._material_flags & Material::F_diffuse) {
543 key._have_separate_ambient =
true;
545 key._have_separate_ambient =
false;
550 if (shader_attrib->auto_ramp_on()) {
552 if (rs->get_attrib(light_ramp)) {
553 key._light_ramp = light_ramp;
555 key._have_separate_ambient =
true;
562 rs->get_attrib_def(clip_plane);
567 if (rs->get_attrib(fog) && !fog->
is_off()) {
568 key._fog_mode = (int)fog->
get_fog()->get_mode() + 1;
582 void ShaderGenerator::
583 rehash_generated_shaders() {
589 for (
size_t si = 0; si < size; ++si) {
592 if (state->_generated_shader !=
nullptr) {
594 analyze_renderstate(key, state);
596 GeneratedShaders::const_iterator si;
597 si = _generated_shaders.find(key);
598 if (si != _generated_shaders.end()) {
599 if (si->second != state->_generated_shader) {
600 state->_generated_shader = si->second;
601 state->_munged_states.
clear();
605 state->_generated_shader.clear();
606 state->_munged_states.
clear();
614 if (!uniquify_states) {
615 GraphicsStateGuardianBase::mark_rehash_generated_shaders();
625 void ShaderGenerator::
626 clear_generated_shaders() {
630 for (
size_t si = 0; si < size; ++si) {
632 state->_generated_shader.clear();
635 _generated_shaders.clear();
639 if (!uniquify_states) {
640 GraphicsStateGuardianBase::mark_rehash_generated_shaders();
679 key._anim_spec = anim;
680 analyze_renderstate(key, rs);
682 GeneratedShaders::const_iterator si;
683 si = _generated_shaders.find(key);
684 if (si != _generated_shaders.end()) {
692 reset_register_allocator();
694 if (pgraphnodes_cat.is_debug()) {
695 pgraphnodes_cat.debug()
696 <<
"Generating shader for render state " << rs <<
":\n";
697 rs->write(pgraphnodes_cat.debug(
false), 2);
702 const char *tangent_freg =
nullptr;
703 const char *binormal_freg =
nullptr;
704 string tangent_input;
705 string binormal_input;
708 const char *world_position_freg =
nullptr;
709 const char *world_normal_freg =
nullptr;
710 const char *eye_position_freg =
nullptr;
711 const char *eye_normal_freg =
nullptr;
712 const char *hpos_freg =
nullptr;
714 const char *position_vreg;
715 const char *transform_weight_vreg =
nullptr;
716 const char *normal_vreg;
717 const char *color_vreg =
nullptr;
718 const char *transform_index_vreg =
nullptr;
720 if (_use_generic_attr) {
721 position_vreg =
"ATTR0";
722 transform_weight_vreg =
"ATTR1";
723 normal_vreg =
"ATTR2";
724 transform_index_vreg =
"ATTR7";
726 position_vreg =
"POSITION";
727 normal_vreg =
"NORMAL";
730 if (key._color_type == ColorAttrib::T_vertex) {
732 color_vreg = _use_generic_attr ?
"ATTR3" :
"COLOR0";
739 std::ostringstream text;
743 text <<
"/* Generated shader for render state:\n";
747 int map_index_glow = -1;
748 int map_index_gloss = -1;
749 int map_index_emission = -1;
752 bool need_world_position = (key._num_clip_planes > 0);
753 bool need_world_normal =
false;
754 bool need_eye_position = key._lighting;
755 bool need_eye_normal = !key._lights.empty() || ((key._outputs & AuxBitplaneAttrib::ABO_aux_normal) != 0);
756 bool need_tangents = ((key._texture_flags & ShaderKey::TF_map_normal) != 0);
760 bool pack_eye_normal = need_eye_normal && need_tangents && need_eye_position;
762 bool have_specular =
false;
764 if (key._material_flags & Material::F_specular) {
765 have_specular =
true;
766 }
else if ((key._texture_flags & ShaderKey::TF_map_gloss) != 0) {
767 have_specular =
true;
771 bool need_color =
false;
772 if (key._color_type != ColorAttrib::T_off) {
774 if (((key._material_flags & Material::F_ambient) == 0 && key._have_separate_ambient) ||
775 (key._material_flags & Material::F_diffuse) == 0 ||
776 key._calc_primary_alpha) {
784 text <<
"void vshader(\n";
785 for (
size_t i = 0; i < key._textures.size(); ++i) {
786 const ShaderKey::TextureInfo &tex = key._textures[i];
788 switch (tex._gen_mode) {
789 case TexGenAttrib::M_world_position:
790 need_world_position =
true;
792 case TexGenAttrib::M_world_normal:
793 need_world_normal =
true;
795 case TexGenAttrib::M_eye_position:
796 need_eye_position =
true;
798 case TexGenAttrib::M_eye_normal:
799 need_eye_normal =
true;
805 if (tex._texcoord_name !=
nullptr) {
806 if (texcoord_fregs.count(tex._texcoord_name) == 0) {
807 const char *freg = alloc_freg();
808 texcoord_fregs[tex._texcoord_name] = freg;
810 string tcname = tex._texcoord_name->join(
"_");
811 text <<
"\t in float4 vtx_" << tcname <<
" : " << alloc_vreg() <<
",\n";
812 text <<
"\t out float4 l_" << tcname <<
" : " << freg <<
",\n";
816 if (tangent_input.empty() &&
817 (tex._flags & (ShaderKey::TF_map_normal | ShaderKey::TF_map_height)) != 0) {
818 PT(
InternalName) tangent_name = InternalName::get_tangent();
819 PT(
InternalName) binormal_name = InternalName::get_binormal();
821 if (tex._texcoord_name !=
nullptr &&
822 tex._texcoord_name != InternalName::get_texcoord()) {
823 tangent_name = tangent_name->append(tex._texcoord_name->get_basename());
824 binormal_name = binormal_name->append(tex._texcoord_name->get_basename());
827 tangent_input = tangent_name->join(
"_");
828 binormal_input = binormal_name->join(
"_");
830 text <<
"\t in float4 vtx_" << tangent_input <<
" : " << alloc_vreg() <<
",\n";
831 text <<
"\t in float4 vtx_" << binormal_input <<
" : " << alloc_vreg() <<
",\n";
834 if (tex._flags & ShaderKey::TF_map_glow) {
837 if (tex._flags & ShaderKey::TF_map_gloss) {
840 if (tex._flags & ShaderKey::TF_map_emission) {
841 map_index_emission = i;
845 tangent_freg = alloc_freg();
846 binormal_freg = alloc_freg();
847 text <<
"\t out float4 l_tangent : " << tangent_freg <<
",\n";
848 text <<
"\t out float4 l_binormal : " << binormal_freg <<
",\n";
850 if (need_color && key._color_type == ColorAttrib::T_vertex) {
851 text <<
"\t in float4 vtx_color : " << color_vreg <<
",\n";
852 text <<
"\t out float4 l_color : COLOR0,\n";
854 if (need_world_position || need_world_normal) {
855 text <<
"\t uniform float4x4 trans_model_to_world,\n";
857 if (need_world_position) {
858 world_position_freg = alloc_freg();
859 text <<
"\t out float4 l_world_position : " << world_position_freg <<
",\n";
861 if (need_world_normal) {
862 world_normal_freg = alloc_freg();
863 text <<
"\t out float4 l_world_normal : " << world_normal_freg <<
",\n";
865 if (need_eye_position) {
866 text <<
"\t uniform float4x4 trans_model_to_view,\n";
867 eye_position_freg = alloc_freg();
868 text <<
"\t out float4 l_eye_position : " << eye_position_freg <<
",\n";
869 }
else if (need_tangents) {
870 text <<
"\t uniform float4x4 trans_model_to_view,\n";
872 if (need_eye_normal) {
873 text <<
"\t uniform float4x4 tpose_view_to_model,\n";
874 if (!pack_eye_normal) {
875 eye_normal_freg = alloc_freg();
876 text <<
"\t out float3 l_eye_normal : " << eye_normal_freg <<
",\n";
879 if ((key._texture_flags & ShaderKey::TF_map_height) != 0 || need_world_normal || need_eye_normal) {
880 text <<
"\t in float3 vtx_normal : " << normal_vreg <<
",\n";
882 if (key._texture_flags & ShaderKey::TF_map_height) {
883 text <<
"\t uniform float4 mspos_view,\n";
884 text <<
"\t out float3 l_eyevec,\n";
886 if (key._fog_mode != 0) {
887 hpos_freg = alloc_freg();
888 text <<
"\t out float4 l_hpos : " << hpos_freg <<
",\n";
890 for (
size_t i = 0; i < key._lights.size(); ++i) {
891 const ShaderKey::LightInfo &light = key._lights[i];
892 if (light._flags & ShaderKey::LF_has_shadows) {
893 if (_ftregs_used >= 8) {
896 lightcoord_fregs.push_back(
nullptr);
898 lightcoord_fregs.push_back(alloc_freg());
899 text <<
"\t uniform float4x4 mat_shadow_" << i <<
",\n";
900 text <<
"\t out float4 l_lightcoord" << i <<
" : " << lightcoord_fregs[i] <<
",\n";
903 lightcoord_fregs.push_back(
nullptr);
906 if (key._anim_spec.get_animation_type() == GeomEnums::AT_hardware &&
907 key._anim_spec.get_num_transforms() > 0) {
909 if (key._anim_spec.get_indexed_transforms()) {
910 num_transforms = 120;
912 num_transforms = key._anim_spec.get_num_transforms();
914 if (transform_weight_vreg ==
nullptr) {
915 transform_weight_vreg = alloc_vreg();
917 if (transform_index_vreg ==
nullptr) {
918 transform_index_vreg = alloc_vreg();
920 text <<
"\t uniform float4x4 tbl_transforms[" << num_transforms <<
"],\n";
921 text <<
"\t in float4 vtx_transform_weight : " << transform_weight_vreg <<
",\n";
922 if (key._anim_spec.get_indexed_transforms()) {
923 text <<
"\t in uint4 vtx_transform_index : " << transform_index_vreg <<
",\n";
926 text <<
"\t in float4 vtx_position : " << position_vreg <<
",\n";
927 text <<
"\t out float4 l_position : POSITION,\n";
928 text <<
"\t uniform float4x4 mat_modelproj\n";
931 if (key._anim_spec.get_animation_type() == GeomEnums::AT_hardware &&
932 key._anim_spec.get_num_transforms() > 0) {
934 if (!key._anim_spec.get_indexed_transforms()) {
935 text <<
"\t const uint4 vtx_transform_index = uint4(0, 1, 2, 3);\n";
938 text <<
"\t float4x4 matrix = tbl_transforms[vtx_transform_index.x] * vtx_transform_weight.x";
939 if (key._anim_spec.get_num_transforms() > 1) {
940 text <<
"\n\t + tbl_transforms[vtx_transform_index.y] * vtx_transform_weight.y";
942 if (key._anim_spec.get_num_transforms() > 2) {
943 text <<
"\n\t + tbl_transforms[vtx_transform_index.z] * vtx_transform_weight.z";
945 if (key._anim_spec.get_num_transforms() > 3) {
946 text <<
"\n\t + tbl_transforms[vtx_transform_index.w] * vtx_transform_weight.w";
950 text <<
"\t vtx_position = mul(matrix, vtx_position);\n";
951 if (need_world_normal || need_eye_normal) {
952 text <<
"\t vtx_normal = mul((float3x3)matrix, vtx_normal);\n";
956 text <<
"\t l_position = mul(mat_modelproj, vtx_position);\n";
957 if (key._fog_mode != 0) {
958 text <<
"\t l_hpos = l_position;\n";
960 if (need_world_position) {
961 text <<
"\t l_world_position = mul(trans_model_to_world, vtx_position);\n";
963 if (need_world_normal) {
964 text <<
"\t l_world_normal = mul(trans_model_to_world, float4(vtx_normal, 0));\n";
966 if (need_eye_position) {
967 text <<
"\t l_eye_position = mul(trans_model_to_view, vtx_position);\n";
970 for (it = texcoord_fregs.begin(); it != texcoord_fregs.end(); ++it) {
972 string tcname = it->first->join(
"_");
973 text <<
"\t l_" << tcname <<
" = vtx_" << tcname <<
";\n";
975 if (need_color && key._color_type == ColorAttrib::T_vertex) {
976 text <<
"\t l_color = vtx_color;\n";
979 text <<
"\t l_tangent.xyz = normalize(mul((float3x3)trans_model_to_view, vtx_" << tangent_input <<
".xyz));\n";
980 text <<
"\t l_tangent.w = 0;\n";
981 text <<
"\t l_binormal.xyz = normalize(mul((float3x3)trans_model_to_view, -vtx_" << binormal_input <<
".xyz));\n";
982 text <<
"\t l_binormal.w = 0;\n";
984 for (
size_t i = 0; i < key._lights.size(); ++i) {
985 if (key._lights[i]._flags & ShaderKey::LF_has_shadows) {
986 if (lightcoord_fregs[i] !=
nullptr) {
987 text <<
"\t l_lightcoord" << i <<
" = mul(mat_shadow_" << i <<
", l_eye_position);\n";
991 if (key._texture_flags & ShaderKey::TF_map_height) {
992 text <<
"\t float3 eyedir = mspos_view.xyz - vtx_position.xyz;\n";
993 text <<
"\t l_eyevec.x = dot(vtx_" << tangent_input <<
".xyz, eyedir);\n";
994 text <<
"\t l_eyevec.y = dot(vtx_" << binormal_input <<
".xyz, eyedir);\n";
995 text <<
"\t l_eyevec.z = dot(vtx_normal, eyedir);\n";
996 text <<
"\t l_eyevec = normalize(l_eyevec);\n";
998 if (need_eye_normal) {
999 if (pack_eye_normal) {
1001 text <<
"\t float3 eye_normal = normalize(mul((float3x3)tpose_view_to_model, vtx_normal));\n";
1002 text <<
"\t l_tangent.w = eye_normal.x;\n";
1003 text <<
"\t l_binormal.w = eye_normal.y;\n";
1004 text <<
"\t l_eye_position.w = eye_normal.z;\n";
1006 text <<
"\t l_eye_normal = normalize(mul((float3x3)tpose_view_to_model, vtx_normal));\n";
1013 text <<
"void fshader(\n";
1014 if (key._fog_mode != 0) {
1015 text <<
"\t in float4 l_hpos : " << hpos_freg <<
",\n";
1016 text <<
"\t in uniform float4 attr_fog,\n";
1017 text <<
"\t in uniform float4 attr_fogcolor,\n";
1019 if (need_world_position) {
1020 text <<
"\t in float4 l_world_position : " << world_position_freg <<
",\n";
1022 if (need_world_normal) {
1023 text <<
"\t in float4 l_world_normal : " << world_normal_freg <<
",\n";
1025 if (need_eye_position) {
1026 text <<
"\t in float4 l_eye_position : " << eye_position_freg <<
",\n";
1028 if (need_eye_normal && !pack_eye_normal) {
1029 text <<
"\t in float3 l_eye_normal : " << eye_normal_freg <<
",\n";
1031 for (it = texcoord_fregs.begin(); it != texcoord_fregs.end(); ++it) {
1032 text <<
"\t in float4 l_" << it->first->join(
"_") <<
" : " << it->second <<
",\n";
1034 for (
size_t i = 0; i < key._textures.size(); ++i) {
1035 const ShaderKey::TextureInfo &tex = key._textures[i];
1036 if (tex._mode == TextureStage::M_modulate && tex._flags == 0) {
1041 text <<
"\t uniform sampler" << texture_type_as_string(tex._type) <<
" tex_" << i <<
",\n";
1043 if (tex._flags & ShaderKey::TF_has_texscale) {
1044 text <<
"\t uniform float3 texscale_" << i <<
",\n";
1045 }
else if (tex._flags & ShaderKey::TF_has_texmat) {
1046 text <<
"\t uniform float4x4 texmat_" << i <<
",\n";
1049 if (tex._flags & ShaderKey::TF_uses_color) {
1050 text <<
"\t uniform float4 texcolor_" << i <<
",\n";
1053 if (need_tangents) {
1054 text <<
"\t in float4 l_tangent : " << tangent_freg <<
",\n";
1055 text <<
"\t in float4 l_binormal : " << binormal_freg <<
",\n";
1057 for (
size_t i = 0; i < key._lights.size(); ++i) {
1058 text <<
"\t uniform float4x4 attr_light" << i <<
",\n";
1060 const ShaderKey::LightInfo &light = key._lights[i];
1061 if (light._flags & ShaderKey::LF_has_shadows) {
1062 if (light._type.is_derived_from(PointLight::get_class_type())) {
1063 text <<
"\t uniform samplerCUBE shadow_" << i <<
",\n";
1064 }
else if (_use_shadow_filter) {
1065 text <<
"\t uniform sampler2DShadow shadow_" << i <<
",\n";
1067 text <<
"\t uniform sampler2D shadow_" << i <<
",\n";
1069 if (lightcoord_fregs[i] !=
nullptr) {
1070 text <<
"\t in float4 l_lightcoord" << i <<
" : " << lightcoord_fregs[i] <<
",\n";
1072 text <<
"\t uniform float4x4 mat_shadow_" << i <<
",\n";
1075 if (light._flags & ShaderKey::LF_has_specular_color) {
1076 text <<
"\t uniform float4 attr_lspec" << i <<
",\n";
1081 if (key._material_flags & (Material::F_ambient | Material::F_diffuse | Material::F_emission | Material::F_specular)) {
1082 text <<
"\t uniform float4x4 attr_material,\n";
1084 if (key._texture_flags & ShaderKey::TF_map_height) {
1085 text <<
"\t float3 l_eyevec,\n";
1087 if (key._outputs & (AuxBitplaneAttrib::ABO_aux_normal | AuxBitplaneAttrib::ABO_aux_glow)) {
1088 text <<
"\t out float4 o_aux : COLOR1,\n";
1090 text <<
"\t out float4 o_color : COLOR0,\n";
1093 if (key._color_type == ColorAttrib::T_vertex) {
1094 text <<
"\t in float4 l_color : COLOR0,\n";
1095 }
else if (key._color_type == ColorAttrib::T_flat) {
1096 text <<
"\t uniform float4 attr_color,\n";
1100 for (
int i = 0; i < key._num_clip_planes; ++i) {
1101 text <<
"\t uniform float4 clipplane_" << i <<
",\n";
1104 if (key._lighting) {
1105 text <<
"\t uniform float4 attr_ambient,\n";
1107 text <<
"\t uniform float4 attr_colorscale\n";
1111 for (
int i = 0; i < key._num_clip_planes; ++i) {
1112 text <<
"\t if (l_world_position.x * clipplane_" << i <<
".x + l_world_position.y ";
1113 text <<
"* clipplane_" << i <<
".y + l_world_position.z * clipplane_" << i <<
".z + clipplane_" << i <<
".w <= 0) {\n";
1114 text <<
"\t discard;\n";
1119 if (need_eye_normal && pack_eye_normal) {
1120 text <<
"\t float3 l_eye_normal = float3(l_tangent.w, l_binormal.w, l_eye_position.w);\n";
1123 text <<
"\t float4 result;\n";
1124 if (key._outputs & (AuxBitplaneAttrib::ABO_aux_normal | AuxBitplaneAttrib::ABO_aux_glow)) {
1125 text <<
"\t o_aux = float4(0, 0, 0, 0);\n";
1129 for (
size_t i = 0; i < key._textures.size(); ++i) {
1130 const ShaderKey::TextureInfo &tex = key._textures[i];
1131 if (tex._mode == TextureStage::M_modulate && tex._flags == 0) {
1135 switch (tex._gen_mode) {
1136 case TexGenAttrib::M_off:
1138 text <<
"\t float4 texcoord" << i <<
" = l_" << tex._texcoord_name->join(
"_") <<
";\n";
1140 case TexGenAttrib::M_world_position:
1141 text <<
"\t float4 texcoord" << i <<
" = l_world_position;\n";
1143 case TexGenAttrib::M_world_normal:
1144 text <<
"\t float4 texcoord" << i <<
" = l_world_normal;\n";
1146 case TexGenAttrib::M_eye_position:
1147 text <<
"\t float4 texcoord" << i <<
" = float4(l_eye_position.xyz, 1.0f);\n";
1149 case TexGenAttrib::M_eye_normal:
1150 text <<
"\t float4 texcoord" << i <<
" = float4(l_eye_normal, 1.0f);\n";
1153 text <<
"\t float4 texcoord" << i <<
" = float4(0, 0, 0, 0);\n";
1154 pgraphnodes_cat.error()
1155 <<
"Unsupported TexGenAttrib mode: " << tex._gen_mode <<
"\n";
1157 if (tex._flags & ShaderKey::TF_has_texscale) {
1158 text <<
"\t texcoord" << i <<
".xyz *= texscale_" << i <<
";\n";
1159 }
else if (tex._flags & ShaderKey::TF_has_texmat) {
1160 text <<
"\t texcoord" << i <<
" = mul(texmat_" << i <<
", texcoord" << i <<
");\n";
1161 text <<
"\t texcoord" << i <<
".xyz /= texcoord" << i <<
".w;\n";
1164 text <<
"\t // Fetch all textures.\n";
1165 for (
size_t i = 0; i < key._textures.size(); ++i) {
1166 const ShaderKey::TextureInfo &tex = key._textures[i];
1167 if ((tex._flags & ShaderKey::TF_map_height) == 0) {
1171 text <<
"\t float4 tex" << i <<
" = tex" << texture_type_as_string(tex._type);
1172 text <<
"(tex_" << i <<
", texcoord" << i <<
".";
1173 switch (tex._type) {
1174 case Texture::TT_cube_map:
1175 case Texture::TT_3d_texture:
1176 case Texture::TT_2d_texture_array:
1179 case Texture::TT_2d_texture:
1182 case Texture::TT_1d_texture:
1188 text <<
");\n\t float3 parallax_offset = l_eyevec.xyz * (tex" << i;
1189 if (tex._mode == TextureStage::M_normal_height ||
1190 (tex._flags & ShaderKey::TF_has_alpha) != 0) {
1195 text <<
" * 2.0 - 1.0) * " << parallax_mapping_scale <<
";\n";
1197 for (
int j = 0; j < parallax_mapping_samples - 1; ++j) {
1198 text <<
"\t parallax_offset = l_eyevec.xyz * (parallax_offset + (tex" << i;
1199 if (tex._mode == TextureStage::M_normal_height ||
1200 (tex._flags & ShaderKey::TF_has_alpha) != 0) {
1205 text <<
" * 2.0 - 1.0)) * " << 0.5 * parallax_mapping_scale <<
";\n";
1208 for (
size_t i = 0; i < key._textures.size(); ++i) {
1209 ShaderKey::TextureInfo &tex = key._textures[i];
1210 if (tex._mode == TextureStage::M_modulate && tex._flags == 0) {
1214 if ((tex._flags & ShaderKey::TF_map_height) == 0) {
1217 if (key._texture_flags & ShaderKey::TF_map_height) {
1218 text <<
"\t texcoord" << i <<
".xyz -= parallax_offset;\n";
1220 text <<
"\t float4 tex" << i <<
" = tex" << texture_type_as_string(tex._type);
1221 text <<
"(tex_" << i <<
", texcoord" << i <<
".";
1222 switch (tex._type) {
1223 case Texture::TT_cube_map:
1224 case Texture::TT_3d_texture:
1225 case Texture::TT_2d_texture_array:
1228 case Texture::TT_2d_texture:
1231 case Texture::TT_1d_texture:
1240 if (need_eye_normal) {
1241 text <<
"\t // Correct the surface normal for interpolation effects\n";
1242 text <<
"\t l_eye_normal = normalize(l_eye_normal);\n";
1244 if (need_tangents) {
1245 text <<
"\t // Translate tangent-space normal in map to view-space.\n";
1248 bool is_first =
true;
1249 for (
size_t i = 0; i < key._textures.size(); ++i) {
1250 const ShaderKey::TextureInfo &tex = key._textures[i];
1251 if (tex._flags & ShaderKey::TF_map_normal) {
1253 if (tex._flags & ShaderKey::TF_has_texscale) {
1254 text <<
"\t float3 tsnormal = normalize(((tex" << i <<
".xyz * 2) - 1) * texscale_" << i <<
");\n";
1255 }
else if (tex._flags & ShaderKey::TF_has_texmat) {
1256 text <<
"\t float3 tsnormal = normalize(mul(texmat_" << i <<
", float4((tex" << i <<
".xyz * 2) - 1, 0)).xyz);\n";
1258 text <<
"\t float3 tsnormal = normalize((tex" << i <<
".xyz * 2) - 1);\n";
1263 text <<
"\t tsnormal.z += 1;\n";
1264 text <<
"\t float3 tmp" << i <<
" = tex" << i <<
".xyz * float3(-2, -2, 2) + float3(1, 1, -1);\n";
1265 if (tex._flags & ShaderKey::TF_has_texscale) {
1266 text <<
"\t tmp" << i <<
" *= texscale_" << i <<
";\n";
1267 }
else if (tex._flags & ShaderKey::TF_has_texmat) {
1268 text <<
"\t tmp" << i <<
" = mul(texmat_" << i <<
", float4(tmp" << i <<
", 0)).xyz;\n";
1270 text <<
"\t tsnormal = normalize(tsnormal * dot(tsnormal, tmp" << i <<
") - tmp" << i <<
" * tsnormal.z);\n";
1273 text <<
"\t l_eye_normal *= tsnormal.z;\n";
1274 text <<
"\t l_eye_normal += normalize(l_tangent.xyz) * tsnormal.x;\n";
1275 text <<
"\t l_eye_normal += normalize(l_binormal.xyz) * tsnormal.y;\n";
1276 text <<
"\t l_eye_normal = normalize(l_eye_normal);\n";
1278 if (key._outputs & AuxBitplaneAttrib::ABO_aux_normal) {
1279 text <<
"\t // Output the camera-space surface normal\n";
1280 text <<
"\t o_aux.rgb = (l_eye_normal*0.5) + float3(0.5,0.5,0.5);\n";
1282 if (key._lighting) {
1283 text <<
"\t // Begin view-space light calculations\n";
1284 text <<
"\t float ldist,lattenv,langle,lshad;\n";
1285 text <<
"\t float4 lcolor,lspec,lpoint,latten,ldir,leye;\n";
1286 text <<
"\t float3 lvec,lhalf;\n";
1287 if (key._have_separate_ambient) {
1288 text <<
"\t float4 tot_ambient = float4(0,0,0,0);\n";
1290 text <<
"\t float4 tot_diffuse = float4(0,0,0,0);\n";
1291 if (have_specular) {
1292 text <<
"\t float4 tot_specular = float4(0,0,0,0);\n";
1293 if (key._material_flags & Material::F_specular) {
1294 text <<
"\t float shininess = attr_material[3].w;\n";
1296 text <<
"\t float shininess = 50; // no shininess specified, using default\n";
1299 if (key._have_separate_ambient) {
1300 text <<
"\t tot_ambient += attr_ambient;\n";
1302 text <<
"\t tot_diffuse += attr_ambient;\n";
1305 for (
size_t i = 0; i < key._lights.size(); ++i) {
1306 const ShaderKey::LightInfo &light = key._lights[i];
1308 if (light._flags & ShaderKey::LF_has_shadows) {
1309 if (lightcoord_fregs[i] ==
nullptr) {
1312 text <<
"\t float4 l_lightcoord" << i <<
" = mul(mat_shadow_" << i <<
", float4(l_eye_position.xyz, 1.0f));\n";
1316 if (light._type.is_derived_from(DirectionalLight::get_class_type())) {
1317 text <<
"\t // Directional Light " << i <<
"\n";
1318 text <<
"\t lcolor = attr_light" << i <<
"[0];\n";
1319 if (light._flags & ShaderKey::LF_has_specular_color) {
1320 text <<
"\t lspec = attr_lspec" << i <<
";\n";
1322 text <<
"\t lspec = lcolor;\n";
1324 text <<
"\t lvec = attr_light" << i <<
"[3].xyz;\n";
1325 text <<
"\t lcolor *= saturate(dot(l_eye_normal, lvec.xyz));\n";
1326 if (light._flags & ShaderKey::LF_has_shadows) {
1327 if (_use_shadow_filter) {
1328 text <<
"\t lshad = shadow2DProj(shadow_" << i <<
", l_lightcoord" << i <<
").r;\n";
1330 text <<
"\t lshad = tex2Dproj(shadow_" << i <<
", l_lightcoord" << i <<
").r > l_lightcoord" << i <<
".z / l_lightcoord" << i <<
".w;\n";
1332 text <<
"\t lcolor *= lshad;\n";
1333 text <<
"\t lspec *= lshad;\n";
1335 text <<
"\t tot_diffuse += lcolor;\n";
1336 if (have_specular) {
1337 if (key._material_flags & Material::F_local) {
1338 text <<
"\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
1340 text <<
"\t lhalf = normalize(lvec - float3(0, 1, 0));\n";
1342 text <<
"\t lspec *= pow(saturate(dot(l_eye_normal, lhalf)), shininess);\n";
1343 text <<
"\t tot_specular += lspec;\n";
1345 }
else if (light._type.is_derived_from(PointLight::get_class_type())) {
1346 text <<
"\t // Point Light " << i <<
"\n";
1347 text <<
"\t lcolor = attr_light" << i <<
"[0];\n";
1348 if (light._flags & ShaderKey::LF_has_specular_color) {
1349 text <<
"\t lspec = attr_lspec" << i <<
";\n";
1351 text <<
"\t lspec = lcolor;\n";
1353 text <<
"\t latten = attr_light" << i <<
"[1];\n";
1354 text <<
"\t lpoint = attr_light" << i <<
"[3];\n";
1355 text <<
"\t lvec = lpoint.xyz - l_eye_position.xyz;\n";
1356 text <<
"\t ldist = length(lvec);\n";
1357 text <<
"\t lvec /= ldist;\n";
1358 if (light._type.is_derived_from(SphereLight::get_class_type())) {
1359 text <<
"\t ldist = max(ldist, attr_light" << i <<
"[2].w);\n";
1361 text <<
"\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
1362 text <<
"\t lcolor *= lattenv * saturate(dot(l_eye_normal, lvec));\n";
1363 if (light._flags & ShaderKey::LF_has_shadows) {
1364 text <<
"\t ldist = max(abs(l_lightcoord" << i <<
".x), max(abs(l_lightcoord" << i <<
".y), abs(l_lightcoord" << i <<
".z)));\n";
1365 text <<
"\t ldist = ((latten.w+lpoint.w)/(latten.w-lpoint.w))+((-2*latten.w*lpoint.w)/(ldist * (latten.w-lpoint.w)));\n";
1366 text <<
"\t lshad = texCUBE(shadow_" << i <<
", l_lightcoord" << i <<
".xyz).r >= ldist * 0.5 + 0.5;\n";
1367 text <<
"\t lcolor *= lshad;\n";
1368 text <<
"\t lspec *= lshad;\n";
1370 text <<
"\t tot_diffuse += lcolor;\n";
1371 if (have_specular) {
1372 if (key._material_flags & Material::F_local) {
1373 text <<
"\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
1375 text <<
"\t lhalf = normalize(lvec - float3(0, 1, 0));\n";
1377 text <<
"\t lspec *= lattenv;\n";
1378 text <<
"\t lspec *= pow(saturate(dot(l_eye_normal, lhalf)), shininess);\n";
1379 text <<
"\t tot_specular += lspec;\n";
1381 }
else if (light._type.is_derived_from(Spotlight::get_class_type())) {
1382 text <<
"\t // Spot Light " << i <<
"\n";
1383 text <<
"\t lcolor = attr_light" << i <<
"[0];\n";
1384 if (light._flags & ShaderKey::LF_has_specular_color) {
1385 text <<
"\t lspec = attr_lspec" << i <<
";\n";
1387 text <<
"\t lspec = lcolor;\n";
1389 text <<
"\t latten = attr_light" << i <<
"[1];\n";
1390 text <<
"\t ldir = attr_light" << i <<
"[2];\n";
1391 text <<
"\t lpoint = attr_light" << i <<
"[3];\n";
1392 text <<
"\t lvec = lpoint.xyz - l_eye_position.xyz;\n";
1393 text <<
"\t ldist = length(lvec);\n";
1394 text <<
"\t lvec /= ldist;\n";
1395 text <<
"\t langle = saturate(dot(ldir.xyz, lvec));\n";
1396 text <<
"\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
1397 text <<
"\t lattenv *= pow(langle, latten.w);\n";
1398 text <<
"\t if (langle < ldir.w) lattenv = 0;\n";
1399 text <<
"\t lcolor *= lattenv * saturate(dot(l_eye_normal, lvec));\n";
1400 if (light._flags & ShaderKey::LF_has_shadows) {
1401 if (_use_shadow_filter) {
1402 text <<
"\t lshad = shadow2DProj(shadow_" << i <<
", l_lightcoord" << i <<
").r;\n";
1404 text <<
"\t lshad = tex2Dproj(shadow_" << i <<
", l_lightcoord" << i <<
").r > l_lightcoord" << i <<
".z / l_lightcoord" << i <<
".w;\n";
1406 text <<
"\t lcolor *= lshad;\n";
1407 text <<
"\t lspec *= lshad;\n";
1410 text <<
"\t tot_diffuse += lcolor;\n";
1411 if (have_specular) {
1412 if (key._material_flags & Material::F_local) {
1413 text <<
"\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
1415 text <<
"\t lhalf = normalize(lvec - float3(0,1,0));\n";
1417 text <<
"\t lspec *= lattenv;\n";
1418 text <<
"\t lspec *= pow(saturate(dot(l_eye_normal, lhalf)), shininess);\n";
1419 text <<
"\t tot_specular += lspec;\n";
1423 if (key._lighting) {
1424 if (key._light_ramp !=
nullptr) {
1425 switch (key._light_ramp->get_mode()) {
1426 case LightRampAttrib::LRT_single_threshold:
1428 PN_stdfloat t = key._light_ramp->get_threshold(0);
1429 PN_stdfloat l0 = key._light_ramp->get_level(0);
1430 text <<
"\t // Single-threshold light ramp\n";
1431 text <<
"\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
1432 text <<
"\t float lr_scale = (lr_in < " << t <<
") ? 0.0 : (" << l0 <<
"/lr_in);\n";
1433 text <<
"\t tot_diffuse = tot_diffuse * lr_scale;\n";
1436 case LightRampAttrib::LRT_double_threshold:
1438 PN_stdfloat t0 = key._light_ramp->get_threshold(0);
1439 PN_stdfloat t1 = key._light_ramp->get_threshold(1);
1440 PN_stdfloat l0 = key._light_ramp->get_level(0);
1441 PN_stdfloat l1 = key._light_ramp->get_level(1);
1442 text <<
"\t // Double-threshold light ramp\n";
1443 text <<
"\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
1444 text <<
"\t float lr_out = 0.0;\n";
1445 text <<
"\t if (lr_in > " << t0 <<
") lr_out=" << l0 <<
";\n";
1446 text <<
"\t if (lr_in > " << t1 <<
") lr_out=" << l1 <<
";\n";
1447 text <<
"\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n";
1454 text <<
"\t // Begin view-space light summation\n";
1455 if (key._material_flags & Material::F_emission) {
1456 text <<
"\t result = attr_material[2];\n";
1457 }
else if (key._texture_flags & (ShaderKey::TF_map_glow | ShaderKey::TF_map_emission)) {
1458 text <<
"\t result = float4(1,1,1,0);\n";
1460 text <<
"\t result = float4(0,0,0,0);\n";
1462 if (key._texture_flags & ShaderKey::TF_map_emission) {
1463 text <<
"\t result.rgb *= tex" << map_index_emission <<
".rgb;\n";
1465 if (key._texture_flags & ShaderKey::TF_map_glow) {
1466 text <<
"\t result *= saturate(2 * (tex" << map_index_glow <<
".a - 0.5));\n";
1468 if (key._have_separate_ambient) {
1469 if (key._material_flags & Material::F_ambient) {
1470 text <<
"\t result += tot_ambient * attr_material[0];\n";
1471 }
else if (key._color_type == ColorAttrib::T_vertex) {
1472 text <<
"\t result += tot_ambient * l_color;\n";
1473 }
else if (key._color_type == ColorAttrib::T_flat) {
1474 text <<
"\t result += tot_ambient * attr_color;\n";
1476 text <<
"\t result += tot_ambient;\n";
1479 if (key._material_flags & Material::F_diffuse) {
1480 text <<
"\t result += tot_diffuse * attr_material[1];\n";
1481 }
else if (key._color_type == ColorAttrib::T_vertex) {
1482 text <<
"\t result += tot_diffuse * l_color;\n";
1483 }
else if (key._color_type == ColorAttrib::T_flat) {
1484 text <<
"\t result += tot_diffuse * attr_color;\n";
1486 text <<
"\t result += tot_diffuse;\n";
1488 if (key._light_ramp ==
nullptr ||
1489 key._light_ramp->get_mode() == LightRampAttrib::LRT_default) {
1490 text <<
"\t result = saturate(result);\n";
1492 text <<
"\t // End view-space light calculations\n";
1496 if (key._calc_primary_alpha) {
1497 if (key._material_flags & Material::F_diffuse) {
1498 text <<
"\t result.a = attr_material[1].w;\n";
1499 }
else if (key._color_type == ColorAttrib::T_vertex) {
1500 text <<
"\t result.a = l_color.a;\n";
1501 }
else if (key._color_type == ColorAttrib::T_flat) {
1502 text <<
"\t result.a = attr_color.a;\n";
1504 text <<
"\t result.a = 1;\n";
1508 if (key._color_type == ColorAttrib::T_vertex) {
1509 text <<
"\t result = l_color;\n";
1510 }
else if (key._color_type == ColorAttrib::T_flat) {
1511 text <<
"\t result = attr_color;\n";
1513 text <<
"\t result = float4(1, 1, 1, 1);\n";
1518 text <<
"\t result *= attr_colorscale;\n";
1521 if (key._texture_flags & ShaderKey::TF_uses_primary_color) {
1522 text <<
"\t float4 primary_color = result;\n";
1524 if (key._texture_flags & ShaderKey::TF_uses_last_saved_result) {
1525 text <<
"\t float4 last_saved_result = result;\n";
1529 for (
size_t i = 0; i < key._textures.size(); ++i) {
1530 const ShaderKey::TextureInfo &tex = key._textures[i];
1531 TextureStage::CombineMode combine_rgb, combine_alpha;
1533 switch (tex._mode) {
1534 case TextureStage::M_modulate:
1535 if ((tex._flags & ShaderKey::TF_has_rgb) != 0 &&
1536 (tex._flags & ShaderKey::TF_has_alpha) != 0) {
1537 text <<
"\t result.rgba *= tex" << i <<
".rgba;\n";
1538 }
else if (tex._flags & ShaderKey::TF_has_alpha) {
1539 text <<
"\t result.a *= tex" << i <<
".a;\n";
1540 }
else if (tex._flags & ShaderKey::TF_has_rgb) {
1541 text <<
"\t result.rgb *= tex" << i <<
".rgb;\n";
1544 case TextureStage::M_modulate_glow:
1545 case TextureStage::M_modulate_gloss:
1551 text <<
"\t result.rgb *= tex" << i <<
";\n";
1553 case TextureStage::M_decal:
1554 text <<
"\t result.rgb = lerp(result, tex" << i <<
", tex" << i <<
".a).rgb;\n";
1556 case TextureStage::M_blend:
1557 text <<
"\t result.rgb = lerp(result.rgb, texcolor_" << i <<
".rgb, tex" << i <<
".rgb);\n";
1558 if (key._calc_primary_alpha) {
1559 text <<
"\t result.a *= tex" << i <<
".a;\n";
1562 case TextureStage::M_replace:
1563 text <<
"\t result = tex" << i <<
";\n";
1565 case TextureStage::M_add:
1566 text <<
"\t result.rgb += tex" << i <<
".rgb;\n";
1567 if (key._calc_primary_alpha) {
1568 text <<
"\t result.a *= tex" << i <<
".a;\n";
1571 case TextureStage::M_combine:
1572 combine_rgb = (TextureStage::CombineMode)((tex._flags & ShaderKey::TF_COMBINE_RGB_MODE_MASK) >> ShaderKey::TF_COMBINE_RGB_MODE_SHIFT);
1573 combine_alpha = (TextureStage::CombineMode)((tex._flags & ShaderKey::TF_COMBINE_ALPHA_MODE_MASK) >> ShaderKey::TF_COMBINE_ALPHA_MODE_SHIFT);
1574 if (combine_rgb == TextureStage::CM_dot3_rgba) {
1575 text <<
"\t result = ";
1576 text << combine_mode_as_string(tex, combine_rgb,
false, i);
1579 text <<
"\t result.rgb = ";
1580 text << combine_mode_as_string(tex, combine_rgb,
false, i);
1581 text <<
";\n\t result.a = ";
1582 text << combine_mode_as_string(tex, combine_alpha,
true, i);
1585 if (tex._flags & ShaderKey::TF_rgb_scale_2) {
1586 text <<
"\t result.rgb *= 2;\n";
1588 if (tex._flags & ShaderKey::TF_rgb_scale_4) {
1589 text <<
"\t result.rgb *= 4;\n";
1591 if (tex._flags & ShaderKey::TF_alpha_scale_2) {
1592 text <<
"\t result.a *= 2;\n";
1594 if (tex._flags & ShaderKey::TF_alpha_scale_4) {
1595 text <<
"\t result.a *= 4;\n";
1598 case TextureStage::M_blend_color_scale:
1599 text <<
"\t result.rgb = lerp(result.rgb, texcolor_" << i <<
".rgb * attr_colorscale.rgb, tex" << i <<
".rgb);\n";
1600 if (key._calc_primary_alpha) {
1601 text <<
"\t result.a *= texcolor_" << i <<
".a * attr_colorscale.a;\n";
1607 if (tex._flags & ShaderKey::TF_saved_result) {
1608 text <<
"\t last_saved_result = result;\n";
1612 if (key._alpha_test_mode != RenderAttrib::M_none) {
1613 text <<
"\t // Shader includes alpha test:\n";
1614 double ref = key._alpha_test_ref;
1615 switch (key._alpha_test_mode) {
1616 case RenderAttrib::M_never:
1617 text <<
"\t discard;\n";
1619 case RenderAttrib::M_less:
1620 text <<
"\t if (result.a >= " <<
ref <<
") discard;\n";
1622 case RenderAttrib::M_equal:
1623 text <<
"\t if (result.a != " <<
ref <<
") discard;\n";
1625 case RenderAttrib::M_less_equal:
1626 text <<
"\t if (result.a > " <<
ref <<
") discard;\n";
1628 case RenderAttrib::M_greater:
1629 text <<
"\t if (result.a <= " <<
ref <<
") discard;\n";
1631 case RenderAttrib::M_not_equal:
1632 text <<
"\t if (result.a == " <<
ref <<
") discard;\n";
1634 case RenderAttrib::M_greater_equal:
1635 text <<
"\t if (result.a < " <<
ref <<
") discard;\n";
1637 case RenderAttrib::M_none:
1638 case RenderAttrib::M_always:
1643 if (key._outputs & AuxBitplaneAttrib::ABO_glow) {
1644 if (key._texture_flags & ShaderKey::TF_map_glow) {
1645 text <<
"\t result.a = tex" << map_index_glow <<
".a;\n";
1647 text <<
"\t result.a = 0.5;\n";
1650 if (key._outputs & AuxBitplaneAttrib::ABO_aux_glow) {
1651 if (key._texture_flags & ShaderKey::TF_map_glow) {
1652 text <<
"\t o_aux.a = tex" << map_index_glow <<
".a;\n";
1654 text <<
"\t o_aux.a = 0.5;\n";
1658 if (have_specular) {
1659 if (key._material_flags & Material::F_specular) {
1660 text <<
"\t tot_specular *= attr_material[3];\n";
1662 if (key._texture_flags & ShaderKey::TF_map_gloss) {
1663 text <<
"\t tot_specular *= tex" << map_index_gloss <<
".a;\n";
1665 text <<
"\t result.rgb = result.rgb + tot_specular.rgb;\n";
1667 if (key._light_ramp !=
nullptr) {
1668 switch (key._light_ramp->get_mode()) {
1669 case LightRampAttrib::LRT_hdr0:
1670 text <<
"\t result.rgb = (result*result*result + result*result + result) / (result*result*result + result*result + result + 1);\n";
1672 case LightRampAttrib::LRT_hdr1:
1673 text <<
"\t result.rgb = (result*result + result) / (result*result + result + 1);\n";
1675 case LightRampAttrib::LRT_hdr2:
1676 text <<
"\t result.rgb = result / (result + 1);\n";
1683 if (key._fog_mode != 0) {
1684 Fog::Mode fog_mode = (Fog::Mode)(key._fog_mode - 1);
1687 text <<
"\t result.rgb = lerp(attr_fogcolor.rgb, result.rgb, saturate((attr_fog.z - l_hpos.z) * attr_fog.w));\n";
1689 case Fog::M_exponential:
1690 text <<
"\t result.rgb = lerp(attr_fogcolor.rgb, result.rgb, saturate(exp2(attr_fog.x * l_hpos.z * -1.442695f)));\n";
1692 case Fog::M_exponential_squared:
1693 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";
1700 text <<
"\t o_color = result * 1.000001;\n";
1701 if (key._alpha_test_mode != RenderAttrib::M_none) {
1702 text <<
"\t // Shader subsumes normal alpha test.\n";
1704 if (key._disable_alpha_write) {
1705 text <<
"\t // Shader disables alpha write.\n";
1709 if (pgraphnodes_cat.is_spam()) {
1710 pgraphnodes_cat.spam() <<
"Generated shader:\n"
1711 << text.str() <<
"\n";
1715 PT(
Shader) shader = Shader::make(text.str(), Shader::SL_Cg);
1716 nassertr(shader !=
nullptr,
nullptr);
1719 if (key._alpha_test_mode != RenderAttrib::M_none) {
1720 shattr = DCAST(
ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_subsume_alpha_test,
true);
1722 if (key._disable_alpha_write) {
1723 shattr = DCAST(
ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_disable_alpha_write,
true);
1726 reset_register_allocator();
1729 _generated_shaders[key] = attr;
1736 string ShaderGenerator::
1737 combine_mode_as_string(
const ShaderKey::TextureInfo &info, TextureStage::CombineMode c_mode,
bool alpha,
short texindex) {
1738 std::ostringstream text;
1740 case TextureStage::CM_modulate:
1741 text << combine_source_as_string(info, 0, alpha, texindex);
1743 text << combine_source_as_string(info, 1, alpha, texindex);
1745 case TextureStage::CM_add:
1746 text << combine_source_as_string(info, 0, alpha, texindex);
1748 text << combine_source_as_string(info, 1, alpha, texindex);
1750 case TextureStage::CM_add_signed:
1751 text << combine_source_as_string(info, 0, alpha, texindex);
1753 text << combine_source_as_string(info, 1, alpha, texindex);
1757 text <<
" - float3(0.5, 0.5, 0.5)";
1760 case TextureStage::CM_interpolate:
1762 text << combine_source_as_string(info, 1, alpha, texindex);
1764 text << combine_source_as_string(info, 0, alpha, texindex);
1766 text << combine_source_as_string(info, 2, alpha, texindex);
1769 case TextureStage::CM_subtract:
1770 text << combine_source_as_string(info, 0, alpha, texindex);
1772 text << combine_source_as_string(info, 1, alpha, texindex);
1774 case TextureStage::CM_dot3_rgb:
1775 case TextureStage::CM_dot3_rgba:
1777 text << combine_source_as_string(info, 0, alpha, texindex);
1778 text <<
" - float3(0.5), ";
1779 text << combine_source_as_string(info, 1, alpha, texindex);
1780 text <<
" - float3(0.5))";
1782 case TextureStage::CM_replace:
1784 text << combine_source_as_string(info, 0, alpha, texindex);
1793 string ShaderGenerator::
1794 combine_source_as_string(
const ShaderKey::TextureInfo &info,
short num,
bool alpha,
short texindex) {
1795 TextureStage::CombineSource c_src;
1796 TextureStage::CombineOperand c_op;
1798 c_src = UNPACK_COMBINE_SRC(info._combine_rgb, num);
1799 c_op = UNPACK_COMBINE_OP(info._combine_rgb, num);
1801 c_src = UNPACK_COMBINE_SRC(info._combine_alpha, num);
1802 c_op = UNPACK_COMBINE_OP(info._combine_alpha, num);
1804 std::ostringstream csource;
1805 if (c_op == TextureStage::CO_one_minus_src_color ||
1806 c_op == TextureStage::CO_one_minus_src_alpha) {
1807 csource <<
"saturate(1.0f - ";
1810 case TextureStage::CS_undefined:
1811 case TextureStage::CS_texture:
1812 csource <<
"tex" << texindex;
1814 case TextureStage::CS_constant:
1815 csource <<
"texcolor_" << texindex;
1817 case TextureStage::CS_primary_color:
1818 csource <<
"primary_color";
1820 case TextureStage::CS_previous:
1821 csource <<
"result";
1823 case TextureStage::CS_constant_color_scale:
1824 csource <<
"attr_colorscale";
1826 case TextureStage::CS_last_saved_result:
1827 csource <<
"last_saved_result";
1830 if (c_op == TextureStage::CO_one_minus_src_color ||
1831 c_op == TextureStage::CO_one_minus_src_alpha) {
1834 if (c_op == TextureStage::CO_src_color || c_op == TextureStage::CO_one_minus_src_color) {
1840 return "float3(" + csource.str() +
")";
1843 return csource.str();
1849 const char *ShaderGenerator::
1850 texture_type_as_string(Texture::TextureType ttype) {
1852 case Texture::TT_1d_texture:
1855 case Texture::TT_2d_texture:
1858 case Texture::TT_3d_texture:
1861 case Texture::TT_cube_map:
1864 case Texture::TT_2d_texture_array:
1868 pgraphnodes_cat.error() <<
"Unsupported texture type!\n";
1876 ShaderGenerator::ShaderKey::
1882 _have_separate_ambient(false),
1885 _calc_primary_alpha(false),
1886 _disable_alpha_write(false),
1888 _alpha_test_ref(0.0),
1889 _num_clip_planes(0),
1890 _light_ramp(nullptr) {
1897 bool ShaderGenerator::ShaderKey::
1898 operator < (
const ShaderKey &other)
const {
1899 if (_anim_spec != other._anim_spec) {
1900 return _anim_spec < other._anim_spec;
1902 if (_color_type != other._color_type) {
1903 return _color_type < other._color_type;
1905 if (_material_flags != other._material_flags) {
1906 return _material_flags < other._material_flags;
1908 if (_texture_flags != other._texture_flags) {
1909 return _texture_flags < other._texture_flags;
1911 if (_textures.size() != other._textures.size()) {
1912 return _textures.size() < other._textures.size();
1914 for (
size_t i = 0; i < _textures.size(); ++i) {
1915 const ShaderKey::TextureInfo &tex = _textures[i];
1916 const ShaderKey::TextureInfo &other_tex = other._textures[i];
1917 if (tex._texcoord_name != other_tex._texcoord_name) {
1918 return tex._texcoord_name < other_tex._texcoord_name;
1920 if (tex._type != other_tex._type) {
1921 return tex._type < other_tex._type;
1923 if (tex._mode != other_tex._mode) {
1924 return tex._mode < other_tex._mode;
1926 if (tex._gen_mode != other_tex._gen_mode) {
1927 return tex._gen_mode < other_tex._gen_mode;
1929 if (tex._flags != other_tex._flags) {
1930 return tex._flags < other_tex._flags;
1932 if (tex._combine_rgb != other_tex._combine_rgb) {
1933 return tex._combine_rgb < other_tex._combine_rgb;
1935 if (tex._combine_alpha != other_tex._combine_alpha) {
1936 return tex._combine_alpha < other_tex._combine_alpha;
1939 if (_lights.size() != other._lights.size()) {
1940 return _lights.size() < other._lights.size();
1942 for (
size_t i = 0; i < _lights.size(); ++i) {
1943 const ShaderKey::LightInfo &light = _lights[i];
1944 const ShaderKey::LightInfo &other_light = other._lights[i];
1945 if (light._type != other_light._type) {
1946 return light._type < other_light._type;
1948 if (light._flags != other_light._flags) {
1949 return light._flags < other_light._flags;
1952 if (_lighting != other._lighting) {
1953 return _lighting < other._lighting;
1955 if (_have_separate_ambient != other._have_separate_ambient) {
1956 return _have_separate_ambient < other._have_separate_ambient;
1958 if (_fog_mode != other._fog_mode) {
1959 return _fog_mode < other._fog_mode;
1961 if (_outputs != other._outputs) {
1962 return _outputs < other._outputs;
1964 if (_calc_primary_alpha != other._calc_primary_alpha) {
1965 return _calc_primary_alpha < other._calc_primary_alpha;
1967 if (_disable_alpha_write != other._disable_alpha_write) {
1968 return _disable_alpha_write < other._disable_alpha_write;
1970 if (_alpha_test_mode != other._alpha_test_mode) {
1971 return _alpha_test_mode < other._alpha_test_mode;
1973 if (_alpha_test_ref != other._alpha_test_ref) {
1974 return _alpha_test_ref < other._alpha_test_ref;
1976 if (_num_clip_planes != other._num_clip_planes) {
1977 return _num_clip_planes < other._num_clip_planes;
1979 return _light_ramp < other._light_ramp;
1985 bool ShaderGenerator::ShaderKey::
1986 operator == (
const ShaderKey &other)
const {
1987 if (_anim_spec != other._anim_spec) {
1990 if (_color_type != other._color_type) {
1993 if (_material_flags != other._material_flags) {
1996 if (_texture_flags != other._texture_flags) {
1999 if (_textures.size() != other._textures.size()) {
2002 for (
size_t i = 0; i < _textures.size(); ++i) {
2003 const ShaderKey::TextureInfo &tex = _textures[i];
2004 const ShaderKey::TextureInfo &other_tex = other._textures[i];
2005 if (tex._texcoord_name != other_tex._texcoord_name ||
2006 tex._type != other_tex._type ||
2007 tex._mode != other_tex._mode ||
2008 tex._gen_mode != other_tex._gen_mode ||
2009 tex._flags != other_tex._flags ||
2010 tex._combine_rgb != other_tex._combine_rgb ||
2011 tex._combine_alpha != other_tex._combine_alpha) {
2015 if (_lights.size() != other._lights.size()) {
2018 for (
size_t i = 0; i < _lights.size(); ++i) {
2019 const ShaderKey::LightInfo &light = _lights[i];
2020 const ShaderKey::LightInfo &other_light = other._lights[i];
2021 if (light._type != other_light._type ||
2022 light._flags != other_light._flags) {
2026 return _lighting == other._lighting
2027 && _have_separate_ambient == other._have_separate_ambient
2028 && _fog_mode == other._fog_mode
2029 && _outputs == other._outputs
2030 && _calc_primary_alpha == other._calc_primary_alpha
2031 && _disable_alpha_write == other._disable_alpha_write
2032 && _alpha_test_mode == other._alpha_test_mode
2033 && _alpha_test_ref == other._alpha_test_ref
2034 && _num_clip_planes == other._num_clip_planes
2035 && _light_ramp == other._light_ramp;
2046 ~ShaderGenerator() {
2049 void ShaderGenerator::
2050 rehash_generated_shaders() {
2053 void ShaderGenerator::
2054 clear_generated_shaders() {