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;
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 if (tex._flags & ShaderKey::TF_has_texscale) {
1245 text <<
"\t float3 tsnormal = normalize(((tex" << i <<
".xyz * 2) - 1) * texscale_" << i <<
");\n";
1246 }
else if (tex._flags & ShaderKey::TF_has_texmat) {
1247 text <<
"\t float3 tsnormal = normalize(mul(texmat_" << i <<
", float4((tex" << i <<
".xyz * 2) - 1, 0)).xyz);\n";
1249 text <<
"\t float3 tsnormal = normalize((tex" << i <<
".xyz * 2) - 1);\n";
1254 text <<
"\t tsnormal.z += 1;\n";
1255 text <<
"\t float3 tmp" << i <<
" = tex" << i <<
".xyz * float3(-2, -2, 2) + float3(1, 1, -1);\n";
1256 if (tex._flags & ShaderKey::TF_has_texscale) {
1257 text <<
"\t tmp" << i <<
" *= texscale_" << i <<
";\n";
1258 }
else if (tex._flags & ShaderKey::TF_has_texmat) {
1259 text <<
"\t tmp" << i <<
" = mul(texmat_" << i <<
", float4(tmp" << i <<
", 0)).xyz;\n";
1261 text <<
"\t tsnormal = normalize(tsnormal * dot(tsnormal, tmp" << i <<
") - tmp" << i <<
" * tsnormal.z);\n";
1264 text <<
"\t l_eye_normal *= tsnormal.z;\n";
1265 text <<
"\t l_eye_normal += normalize(l_tangent.xyz) * tsnormal.x;\n";
1266 text <<
"\t l_eye_normal += normalize(l_binormal.xyz) * tsnormal.y;\n";
1267 text <<
"\t l_eye_normal = normalize(l_eye_normal);\n";
1269 if (key._outputs & AuxBitplaneAttrib::ABO_aux_normal) {
1270 text <<
"\t // Output the camera-space surface normal\n";
1271 text <<
"\t o_aux.rgb = (l_eye_normal*0.5) + float3(0.5,0.5,0.5);\n";
1273 if (key._lighting) {
1274 text <<
"\t // Begin view-space light calculations\n";
1275 text <<
"\t float ldist,lattenv,langle,lshad;\n";
1276 text <<
"\t float4 lcolor,lspec,lpoint,latten,ldir,leye;\n";
1277 text <<
"\t float3 lvec,lhalf;\n";
1278 if (key._have_separate_ambient) {
1279 text <<
"\t float4 tot_ambient = float4(0,0,0,0);\n";
1281 text <<
"\t float4 tot_diffuse = float4(0,0,0,0);\n";
1282 if (have_specular) {
1283 text <<
"\t float4 tot_specular = float4(0,0,0,0);\n";
1284 if (key._material_flags & Material::F_specular) {
1285 text <<
"\t float shininess = attr_material[3].w;\n";
1287 text <<
"\t float shininess = 50; // no shininess specified, using default\n";
1290 if (key._have_separate_ambient) {
1291 text <<
"\t tot_ambient += attr_ambient;\n";
1293 text <<
"\t tot_diffuse += attr_ambient;\n";
1296 for (
size_t i = 0; i < key._lights.size(); ++i) {
1297 const ShaderKey::LightInfo &light = key._lights[i];
1299 if (light._flags & ShaderKey::LF_has_shadows) {
1300 if (lightcoord_fregs[i] ==
nullptr) {
1303 text <<
"\t float4 l_lightcoord" << i <<
" = mul(mat_shadow_" << i <<
", float4(l_eye_position.xyz, 1.0f));\n";
1307 if (light._type.is_derived_from(DirectionalLight::get_class_type())) {
1308 text <<
"\t // Directional Light " << i <<
"\n";
1309 text <<
"\t lcolor = attr_light" << i <<
"[0];\n";
1310 if (light._flags & ShaderKey::LF_has_specular_color) {
1311 text <<
"\t lspec = attr_lspec" << i <<
";\n";
1313 text <<
"\t lspec = lcolor;\n";
1315 text <<
"\t lvec = attr_light" << i <<
"[3].xyz;\n";
1316 text <<
"\t lcolor *= saturate(dot(l_eye_normal, lvec.xyz));\n";
1317 if (light._flags & ShaderKey::LF_has_shadows) {
1318 if (_use_shadow_filter) {
1319 text <<
"\t lshad = shadow2DProj(shadow_" << i <<
", l_lightcoord" << i <<
").r;\n";
1321 text <<
"\t lshad = tex2Dproj(shadow_" << i <<
", l_lightcoord" << i <<
").r > l_lightcoord" << i <<
".z / l_lightcoord" << i <<
".w;\n";
1323 text <<
"\t lcolor *= lshad;\n";
1324 text <<
"\t lspec *= lshad;\n";
1326 text <<
"\t tot_diffuse += lcolor;\n";
1327 if (have_specular) {
1328 if (key._material_flags & Material::F_local) {
1329 text <<
"\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
1331 text <<
"\t lhalf = normalize(lvec - float3(0, 1, 0));\n";
1333 text <<
"\t lspec *= pow(saturate(dot(l_eye_normal, lhalf)), shininess);\n";
1334 text <<
"\t tot_specular += lspec;\n";
1336 }
else if (light._type.is_derived_from(PointLight::get_class_type())) {
1337 text <<
"\t // Point Light " << i <<
"\n";
1338 text <<
"\t lcolor = attr_light" << i <<
"[0];\n";
1339 if (light._flags & ShaderKey::LF_has_specular_color) {
1340 text <<
"\t lspec = attr_lspec" << i <<
";\n";
1342 text <<
"\t lspec = lcolor;\n";
1344 text <<
"\t latten = attr_light" << i <<
"[1];\n";
1345 text <<
"\t lpoint = attr_light" << i <<
"[3];\n";
1346 text <<
"\t lvec = lpoint.xyz - l_eye_position.xyz;\n";
1347 text <<
"\t ldist = length(lvec);\n";
1348 text <<
"\t lvec /= ldist;\n";
1349 if (light._type.is_derived_from(SphereLight::get_class_type())) {
1350 text <<
"\t ldist = max(ldist, attr_light" << i <<
"[2].w);\n";
1352 text <<
"\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
1353 text <<
"\t lcolor *= lattenv * saturate(dot(l_eye_normal, lvec));\n";
1354 if (light._flags & ShaderKey::LF_has_shadows) {
1355 text <<
"\t ldist = max(abs(l_lightcoord" << i <<
".x), max(abs(l_lightcoord" << i <<
".y), abs(l_lightcoord" << i <<
".z)));\n";
1356 text <<
"\t ldist = ((latten.w+lpoint.w)/(latten.w-lpoint.w))+((-2*latten.w*lpoint.w)/(ldist * (latten.w-lpoint.w)));\n";
1357 text <<
"\t lshad = texCUBE(shadow_" << i <<
", l_lightcoord" << i <<
".xyz).r >= ldist * 0.5 + 0.5;\n";
1358 text <<
"\t lcolor *= lshad;\n";
1359 text <<
"\t lspec *= lshad;\n";
1361 text <<
"\t tot_diffuse += lcolor;\n";
1362 if (have_specular) {
1363 if (key._material_flags & Material::F_local) {
1364 text <<
"\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
1366 text <<
"\t lhalf = normalize(lvec - float3(0, 1, 0));\n";
1368 text <<
"\t lspec *= lattenv;\n";
1369 text <<
"\t lspec *= pow(saturate(dot(l_eye_normal, lhalf)), shininess);\n";
1370 text <<
"\t tot_specular += lspec;\n";
1372 }
else if (light._type.is_derived_from(Spotlight::get_class_type())) {
1373 text <<
"\t // Spot Light " << i <<
"\n";
1374 text <<
"\t lcolor = attr_light" << i <<
"[0];\n";
1375 if (light._flags & ShaderKey::LF_has_specular_color) {
1376 text <<
"\t lspec = attr_lspec" << i <<
";\n";
1378 text <<
"\t lspec = lcolor;\n";
1380 text <<
"\t latten = attr_light" << i <<
"[1];\n";
1381 text <<
"\t ldir = attr_light" << i <<
"[2];\n";
1382 text <<
"\t lpoint = attr_light" << i <<
"[3];\n";
1383 text <<
"\t lvec = lpoint.xyz - l_eye_position.xyz;\n";
1384 text <<
"\t ldist = length(lvec);\n";
1385 text <<
"\t lvec /= ldist;\n";
1386 text <<
"\t langle = saturate(dot(ldir.xyz, lvec));\n";
1387 text <<
"\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
1388 text <<
"\t lattenv *= pow(langle, latten.w);\n";
1389 text <<
"\t if (langle < ldir.w) lattenv = 0;\n";
1390 text <<
"\t lcolor *= lattenv * saturate(dot(l_eye_normal, lvec));\n";
1391 if (light._flags & ShaderKey::LF_has_shadows) {
1392 if (_use_shadow_filter) {
1393 text <<
"\t lshad = shadow2DProj(shadow_" << i <<
", l_lightcoord" << i <<
").r;\n";
1395 text <<
"\t lshad = tex2Dproj(shadow_" << i <<
", l_lightcoord" << i <<
").r > l_lightcoord" << i <<
".z / l_lightcoord" << i <<
".w;\n";
1397 text <<
"\t lcolor *= lshad;\n";
1398 text <<
"\t lspec *= lshad;\n";
1401 text <<
"\t tot_diffuse += lcolor;\n";
1402 if (have_specular) {
1403 if (key._material_flags & Material::F_local) {
1404 text <<
"\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
1406 text <<
"\t lhalf = normalize(lvec - float3(0,1,0));\n";
1408 text <<
"\t lspec *= lattenv;\n";
1409 text <<
"\t lspec *= pow(saturate(dot(l_eye_normal, lhalf)), shininess);\n";
1410 text <<
"\t tot_specular += lspec;\n";
1414 if (key._lighting) {
1415 if (key._light_ramp !=
nullptr) {
1416 switch (key._light_ramp->get_mode()) {
1417 case LightRampAttrib::LRT_single_threshold:
1419 PN_stdfloat t = key._light_ramp->get_threshold(0);
1420 PN_stdfloat l0 = key._light_ramp->get_level(0);
1421 text <<
"\t // Single-threshold light ramp\n";
1422 text <<
"\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
1423 text <<
"\t float lr_scale = (lr_in < " << t <<
") ? 0.0 : (" << l0 <<
"/lr_in);\n";
1424 text <<
"\t tot_diffuse = tot_diffuse * lr_scale;\n";
1427 case LightRampAttrib::LRT_double_threshold:
1429 PN_stdfloat t0 = key._light_ramp->get_threshold(0);
1430 PN_stdfloat t1 = key._light_ramp->get_threshold(1);
1431 PN_stdfloat l0 = key._light_ramp->get_level(0);
1432 PN_stdfloat l1 = key._light_ramp->get_level(1);
1433 text <<
"\t // Double-threshold light ramp\n";
1434 text <<
"\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
1435 text <<
"\t float lr_out = 0.0;\n";
1436 text <<
"\t if (lr_in > " << t0 <<
") lr_out=" << l0 <<
";\n";
1437 text <<
"\t if (lr_in > " << t1 <<
") lr_out=" << l1 <<
";\n";
1438 text <<
"\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n";
1445 text <<
"\t // Begin view-space light summation\n";
1446 if (key._material_flags & Material::F_emission) {
1447 if (key._texture_flags & ShaderKey::TF_map_glow) {
1448 text <<
"\t result = attr_material[2] * saturate(2 * (tex" << map_index_glow <<
".a - 0.5));\n";
1450 text <<
"\t result = attr_material[2];\n";
1453 if (key._texture_flags & ShaderKey::TF_map_glow) {
1454 text <<
"\t result = saturate(2 * (tex" << map_index_glow <<
".a - 0.5));\n";
1456 text <<
"\t result = float4(0,0,0,0);\n";
1459 if (key._have_separate_ambient) {
1460 if (key._material_flags & Material::F_ambient) {
1461 text <<
"\t result += tot_ambient * attr_material[0];\n";
1462 }
else if (key._color_type == ColorAttrib::T_vertex) {
1463 text <<
"\t result += tot_ambient * l_color;\n";
1464 }
else if (key._color_type == ColorAttrib::T_flat) {
1465 text <<
"\t result += tot_ambient * attr_color;\n";
1467 text <<
"\t result += tot_ambient;\n";
1470 if (key._material_flags & Material::F_diffuse) {
1471 text <<
"\t result += tot_diffuse * attr_material[1];\n";
1472 }
else if (key._color_type == ColorAttrib::T_vertex) {
1473 text <<
"\t result += tot_diffuse * l_color;\n";
1474 }
else if (key._color_type == ColorAttrib::T_flat) {
1475 text <<
"\t result += tot_diffuse * attr_color;\n";
1477 text <<
"\t result += tot_diffuse;\n";
1479 if (key._light_ramp ==
nullptr ||
1480 key._light_ramp->get_mode() == LightRampAttrib::LRT_default) {
1481 text <<
"\t result = saturate(result);\n";
1483 text <<
"\t // End view-space light calculations\n";
1487 if (key._calc_primary_alpha) {
1488 if (key._material_flags & Material::F_diffuse) {
1489 text <<
"\t result.a = attr_material[1].w;\n";
1490 }
else if (key._color_type == ColorAttrib::T_vertex) {
1491 text <<
"\t result.a = l_color.a;\n";
1492 }
else if (key._color_type == ColorAttrib::T_flat) {
1493 text <<
"\t result.a = attr_color.a;\n";
1495 text <<
"\t result.a = 1;\n";
1499 if (key._color_type == ColorAttrib::T_vertex) {
1500 text <<
"\t result = l_color;\n";
1501 }
else if (key._color_type == ColorAttrib::T_flat) {
1502 text <<
"\t result = attr_color;\n";
1504 text <<
"\t result = float4(1, 1, 1, 1);\n";
1509 text <<
"\t result *= attr_colorscale;\n";
1512 if (key._texture_flags & ShaderKey::TF_uses_primary_color) {
1513 text <<
"\t float4 primary_color = result;\n";
1515 if (key._texture_flags & ShaderKey::TF_uses_last_saved_result) {
1516 text <<
"\t float4 last_saved_result = result;\n";
1520 for (
size_t i = 0; i < key._textures.size(); ++i) {
1521 const ShaderKey::TextureInfo &tex = key._textures[i];
1522 TextureStage::CombineMode combine_rgb, combine_alpha;
1524 switch (tex._mode) {
1525 case TextureStage::M_modulate:
1526 if ((tex._flags & ShaderKey::TF_has_rgb) != 0 &&
1527 (tex._flags & ShaderKey::TF_has_alpha) != 0) {
1528 text <<
"\t result.rgba *= tex" << i <<
".rgba;\n";
1529 }
else if (tex._flags & ShaderKey::TF_has_alpha) {
1530 text <<
"\t result.a *= tex" << i <<
".a;\n";
1531 }
else if (tex._flags & ShaderKey::TF_has_rgb) {
1532 text <<
"\t result.rgb *= tex" << i <<
".rgb;\n";
1535 case TextureStage::M_modulate_glow:
1536 case TextureStage::M_modulate_gloss:
1542 text <<
"\t result.rgb *= tex" << i <<
";\n";
1544 case TextureStage::M_decal:
1545 text <<
"\t result.rgb = lerp(result, tex" << i <<
", tex" << i <<
".a).rgb;\n";
1547 case TextureStage::M_blend:
1548 text <<
"\t result.rgb = lerp(result.rgb, texcolor_" << i <<
".rgb, tex" << i <<
".rgb);\n";
1549 if (key._calc_primary_alpha) {
1550 text <<
"\t result.a *= tex" << i <<
".a;\n";
1553 case TextureStage::M_replace:
1554 text <<
"\t result = tex" << i <<
";\n";
1556 case TextureStage::M_add:
1557 text <<
"\t result.rgb += tex" << i <<
".rgb;\n";
1558 if (key._calc_primary_alpha) {
1559 text <<
"\t result.a *= tex" << i <<
".a;\n";
1562 case TextureStage::M_combine:
1563 combine_rgb = (TextureStage::CombineMode)((tex._flags & ShaderKey::TF_COMBINE_RGB_MODE_MASK) >> ShaderKey::TF_COMBINE_RGB_MODE_SHIFT);
1564 combine_alpha = (TextureStage::CombineMode)((tex._flags & ShaderKey::TF_COMBINE_ALPHA_MODE_MASK) >> ShaderKey::TF_COMBINE_ALPHA_MODE_SHIFT);
1565 if (combine_rgb == TextureStage::CM_dot3_rgba) {
1566 text <<
"\t result = ";
1567 text << combine_mode_as_string(tex, combine_rgb,
false, i);
1570 text <<
"\t result.rgb = ";
1571 text << combine_mode_as_string(tex, combine_rgb,
false, i);
1572 text <<
";\n\t result.a = ";
1573 text << combine_mode_as_string(tex, combine_alpha,
true, i);
1576 if (tex._flags & ShaderKey::TF_rgb_scale_2) {
1577 text <<
"\t result.rgb *= 2;\n";
1579 if (tex._flags & ShaderKey::TF_rgb_scale_4) {
1580 text <<
"\t result.rgb *= 4;\n";
1582 if (tex._flags & ShaderKey::TF_alpha_scale_2) {
1583 text <<
"\t result.a *= 2;\n";
1585 if (tex._flags & ShaderKey::TF_alpha_scale_4) {
1586 text <<
"\t result.a *= 4;\n";
1589 case TextureStage::M_blend_color_scale:
1590 text <<
"\t result.rgb = lerp(result.rgb, texcolor_" << i <<
".rgb * attr_colorscale.rgb, tex" << i <<
".rgb);\n";
1591 if (key._calc_primary_alpha) {
1592 text <<
"\t result.a *= texcolor_" << i <<
".a * attr_colorscale.a;\n";
1598 if (tex._flags & ShaderKey::TF_saved_result) {
1599 text <<
"\t last_saved_result = result;\n";
1603 if (key._alpha_test_mode != RenderAttrib::M_none) {
1604 text <<
"\t // Shader includes alpha test:\n";
1605 double ref = key._alpha_test_ref;
1606 switch (key._alpha_test_mode) {
1607 case RenderAttrib::M_never:
1608 text <<
"\t discard;\n";
1610 case RenderAttrib::M_less:
1611 text <<
"\t if (result.a >= " <<
ref <<
") discard;\n";
1613 case RenderAttrib::M_equal:
1614 text <<
"\t if (result.a != " <<
ref <<
") discard;\n";
1616 case RenderAttrib::M_less_equal:
1617 text <<
"\t if (result.a > " <<
ref <<
") discard;\n";
1619 case RenderAttrib::M_greater:
1620 text <<
"\t if (result.a <= " <<
ref <<
") discard;\n";
1622 case RenderAttrib::M_not_equal:
1623 text <<
"\t if (result.a == " <<
ref <<
") discard;\n";
1625 case RenderAttrib::M_greater_equal:
1626 text <<
"\t if (result.a < " <<
ref <<
") discard;\n";
1628 case RenderAttrib::M_none:
1629 case RenderAttrib::M_always:
1634 if (key._outputs & AuxBitplaneAttrib::ABO_glow) {
1635 if (key._texture_flags & ShaderKey::TF_map_glow) {
1636 text <<
"\t result.a = tex" << map_index_glow <<
".a;\n";
1638 text <<
"\t result.a = 0.5;\n";
1641 if (key._outputs & AuxBitplaneAttrib::ABO_aux_glow) {
1642 if (key._texture_flags & ShaderKey::TF_map_glow) {
1643 text <<
"\t o_aux.a = tex" << map_index_glow <<
".a;\n";
1645 text <<
"\t o_aux.a = 0.5;\n";
1649 if (have_specular) {
1650 if (key._material_flags & Material::F_specular) {
1651 text <<
"\t tot_specular *= attr_material[3];\n";
1653 if (key._texture_flags & ShaderKey::TF_map_gloss) {
1654 text <<
"\t tot_specular *= tex" << map_index_gloss <<
".a;\n";
1656 text <<
"\t result.rgb = result.rgb + tot_specular.rgb;\n";
1658 if (key._light_ramp !=
nullptr) {
1659 switch (key._light_ramp->get_mode()) {
1660 case LightRampAttrib::LRT_hdr0:
1661 text <<
"\t result.rgb = (result*result*result + result*result + result) / (result*result*result + result*result + result + 1);\n";
1663 case LightRampAttrib::LRT_hdr1:
1664 text <<
"\t result.rgb = (result*result + result) / (result*result + result + 1);\n";
1666 case LightRampAttrib::LRT_hdr2:
1667 text <<
"\t result.rgb = result / (result + 1);\n";
1674 if (key._fog_mode != 0) {
1675 Fog::Mode fog_mode = (Fog::Mode)(key._fog_mode - 1);
1678 text <<
"\t result.rgb = lerp(attr_fogcolor.rgb, result.rgb, saturate((attr_fog.z - l_hpos.z) * attr_fog.w));\n";
1680 case Fog::M_exponential:
1681 text <<
"\t result.rgb = lerp(attr_fogcolor.rgb, result.rgb, saturate(exp2(attr_fog.x * l_hpos.z * -1.442695f)));\n";
1683 case Fog::M_exponential_squared:
1684 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";
1691 text <<
"\t o_color = result * 1.000001;\n";
1692 if (key._alpha_test_mode != RenderAttrib::M_none) {
1693 text <<
"\t // Shader subsumes normal alpha test.\n";
1695 if (key._disable_alpha_write) {
1696 text <<
"\t // Shader disables alpha write.\n";
1700 if (pgraphnodes_cat.is_spam()) {
1701 pgraphnodes_cat.spam() <<
"Generated shader:\n"
1702 << text.str() <<
"\n";
1706 PT(
Shader) shader = Shader::make(text.str(), Shader::SL_Cg);
1707 nassertr(shader !=
nullptr,
nullptr);
1710 if (key._alpha_test_mode != RenderAttrib::M_none) {
1711 shattr = DCAST(
ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_subsume_alpha_test,
true);
1713 if (key._disable_alpha_write) {
1714 shattr = DCAST(
ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_disable_alpha_write,
true);
1717 reset_register_allocator();
1720 _generated_shaders[key] = attr;
1727 string ShaderGenerator::
1728 combine_mode_as_string(
const ShaderKey::TextureInfo &info, TextureStage::CombineMode c_mode,
bool alpha,
short texindex) {
1729 std::ostringstream text;
1731 case TextureStage::CM_modulate:
1732 text << combine_source_as_string(info, 0, alpha, texindex);
1734 text << combine_source_as_string(info, 1, alpha, texindex);
1736 case TextureStage::CM_add:
1737 text << combine_source_as_string(info, 0, alpha, texindex);
1739 text << combine_source_as_string(info, 1, alpha, texindex);
1741 case TextureStage::CM_add_signed:
1742 text << combine_source_as_string(info, 0, alpha, texindex);
1744 text << combine_source_as_string(info, 1, alpha, texindex);
1748 text <<
" - float3(0.5, 0.5, 0.5)";
1751 case TextureStage::CM_interpolate:
1753 text << combine_source_as_string(info, 1, alpha, texindex);
1755 text << combine_source_as_string(info, 0, alpha, texindex);
1757 text << combine_source_as_string(info, 2, alpha, texindex);
1760 case TextureStage::CM_subtract:
1761 text << combine_source_as_string(info, 0, alpha, texindex);
1763 text << combine_source_as_string(info, 1, alpha, texindex);
1765 case TextureStage::CM_dot3_rgb:
1766 case TextureStage::CM_dot3_rgba:
1768 text << combine_source_as_string(info, 0, alpha, texindex);
1769 text <<
" - float3(0.5), ";
1770 text << combine_source_as_string(info, 1, alpha, texindex);
1771 text <<
" - float3(0.5))";
1773 case TextureStage::CM_replace:
1775 text << combine_source_as_string(info, 0, alpha, texindex);
1784 string ShaderGenerator::
1785 combine_source_as_string(
const ShaderKey::TextureInfo &info,
short num,
bool alpha,
short texindex) {
1786 TextureStage::CombineSource c_src;
1787 TextureStage::CombineOperand c_op;
1789 c_src = UNPACK_COMBINE_SRC(info._combine_rgb, num);
1790 c_op = UNPACK_COMBINE_OP(info._combine_rgb, num);
1792 c_src = UNPACK_COMBINE_SRC(info._combine_alpha, num);
1793 c_op = UNPACK_COMBINE_OP(info._combine_alpha, num);
1795 std::ostringstream csource;
1796 if (c_op == TextureStage::CO_one_minus_src_color ||
1797 c_op == TextureStage::CO_one_minus_src_alpha) {
1798 csource <<
"saturate(1.0f - ";
1801 case TextureStage::CS_undefined:
1802 case TextureStage::CS_texture:
1803 csource <<
"tex" << texindex;
1805 case TextureStage::CS_constant:
1806 csource <<
"texcolor_" << texindex;
1808 case TextureStage::CS_primary_color:
1809 csource <<
"primary_color";
1811 case TextureStage::CS_previous:
1812 csource <<
"result";
1814 case TextureStage::CS_constant_color_scale:
1815 csource <<
"attr_colorscale";
1817 case TextureStage::CS_last_saved_result:
1818 csource <<
"last_saved_result";
1821 if (c_op == TextureStage::CO_one_minus_src_color ||
1822 c_op == TextureStage::CO_one_minus_src_alpha) {
1825 if (c_op == TextureStage::CO_src_color || c_op == TextureStage::CO_one_minus_src_color) {
1831 return "float3(" + csource.str() +
")";
1834 return csource.str();
1840 const char *ShaderGenerator::
1841 texture_type_as_string(Texture::TextureType ttype) {
1843 case Texture::TT_1d_texture:
1846 case Texture::TT_2d_texture:
1849 case Texture::TT_3d_texture:
1852 case Texture::TT_cube_map:
1855 case Texture::TT_2d_texture_array:
1859 pgraphnodes_cat.error() <<
"Unsupported texture type!\n";
1867 ShaderGenerator::ShaderKey::
1873 _have_separate_ambient(false),
1876 _calc_primary_alpha(false),
1877 _disable_alpha_write(false),
1879 _alpha_test_ref(0.0),
1880 _num_clip_planes(0),
1881 _light_ramp(nullptr) {
1888 bool ShaderGenerator::ShaderKey::
1889 operator < (
const ShaderKey &other)
const {
1890 if (_anim_spec != other._anim_spec) {
1891 return _anim_spec < other._anim_spec;
1893 if (_color_type != other._color_type) {
1894 return _color_type < other._color_type;
1896 if (_material_flags != other._material_flags) {
1897 return _material_flags < other._material_flags;
1899 if (_texture_flags != other._texture_flags) {
1900 return _texture_flags < other._texture_flags;
1902 if (_textures.size() != other._textures.size()) {
1903 return _textures.size() < other._textures.size();
1905 for (
size_t i = 0; i < _textures.size(); ++i) {
1906 const ShaderKey::TextureInfo &tex = _textures[i];
1907 const ShaderKey::TextureInfo &other_tex = other._textures[i];
1908 if (tex._texcoord_name != other_tex._texcoord_name) {
1909 return tex._texcoord_name < other_tex._texcoord_name;
1911 if (tex._type != other_tex._type) {
1912 return tex._type < other_tex._type;
1914 if (tex._mode != other_tex._mode) {
1915 return tex._mode < other_tex._mode;
1917 if (tex._gen_mode != other_tex._gen_mode) {
1918 return tex._gen_mode < other_tex._gen_mode;
1920 if (tex._flags != other_tex._flags) {
1921 return tex._flags < other_tex._flags;
1923 if (tex._combine_rgb != other_tex._combine_rgb) {
1924 return tex._combine_rgb < other_tex._combine_rgb;
1926 if (tex._combine_alpha != other_tex._combine_alpha) {
1927 return tex._combine_alpha < other_tex._combine_alpha;
1930 if (_lights.size() != other._lights.size()) {
1931 return _lights.size() < other._lights.size();
1933 for (
size_t i = 0; i < _lights.size(); ++i) {
1934 const ShaderKey::LightInfo &light = _lights[i];
1935 const ShaderKey::LightInfo &other_light = other._lights[i];
1936 if (light._type != other_light._type) {
1937 return light._type < other_light._type;
1939 if (light._flags != other_light._flags) {
1940 return light._flags < other_light._flags;
1943 if (_lighting != other._lighting) {
1944 return _lighting < other._lighting;
1946 if (_have_separate_ambient != other._have_separate_ambient) {
1947 return _have_separate_ambient < other._have_separate_ambient;
1949 if (_fog_mode != other._fog_mode) {
1950 return _fog_mode < other._fog_mode;
1952 if (_outputs != other._outputs) {
1953 return _outputs < other._outputs;
1955 if (_calc_primary_alpha != other._calc_primary_alpha) {
1956 return _calc_primary_alpha < other._calc_primary_alpha;
1958 if (_disable_alpha_write != other._disable_alpha_write) {
1959 return _disable_alpha_write < other._disable_alpha_write;
1961 if (_alpha_test_mode != other._alpha_test_mode) {
1962 return _alpha_test_mode < other._alpha_test_mode;
1964 if (_alpha_test_ref != other._alpha_test_ref) {
1965 return _alpha_test_ref < other._alpha_test_ref;
1967 if (_num_clip_planes != other._num_clip_planes) {
1968 return _num_clip_planes < other._num_clip_planes;
1970 return _light_ramp < other._light_ramp;
1976 bool ShaderGenerator::ShaderKey::
1977 operator == (
const ShaderKey &other)
const {
1978 if (_anim_spec != other._anim_spec) {
1981 if (_color_type != other._color_type) {
1984 if (_material_flags != other._material_flags) {
1987 if (_texture_flags != other._texture_flags) {
1990 if (_textures.size() != other._textures.size()) {
1993 for (
size_t i = 0; i < _textures.size(); ++i) {
1994 const ShaderKey::TextureInfo &tex = _textures[i];
1995 const ShaderKey::TextureInfo &other_tex = other._textures[i];
1996 if (tex._texcoord_name != other_tex._texcoord_name ||
1997 tex._type != other_tex._type ||
1998 tex._mode != other_tex._mode ||
1999 tex._gen_mode != other_tex._gen_mode ||
2000 tex._flags != other_tex._flags ||
2001 tex._combine_rgb != other_tex._combine_rgb ||
2002 tex._combine_alpha != other_tex._combine_alpha) {
2006 if (_lights.size() != other._lights.size()) {
2009 for (
size_t i = 0; i < _lights.size(); ++i) {
2010 const ShaderKey::LightInfo &light = _lights[i];
2011 const ShaderKey::LightInfo &other_light = other._lights[i];
2012 if (light._type != other_light._type ||
2013 light._flags != other_light._flags) {
2017 return _lighting == other._lighting
2018 && _have_separate_ambient == other._have_separate_ambient
2019 && _fog_mode == other._fog_mode
2020 && _outputs == other._outputs
2021 && _calc_primary_alpha == other._calc_primary_alpha
2022 && _disable_alpha_write == other._disable_alpha_write
2023 && _alpha_test_mode == other._alpha_test_mode
2024 && _alpha_test_ref == other._alpha_test_ref
2025 && _num_clip_planes == other._num_clip_planes
2026 && _light_ramp == other._light_ramp;