|
|
@@ -55,8 +55,8 @@ TypeHandle ShaderGenerator::_type_handle;
|
|
|
* shader generator belongs.
|
|
|
*/
|
|
|
ShaderGenerator::
|
|
|
-ShaderGenerator(GraphicsStateGuardianBase *gsg, GraphicsOutputBase *host) :
|
|
|
- _gsg(gsg), _host(host) {
|
|
|
+ShaderGenerator(GraphicsStateGuardianBase *gsg) :
|
|
|
+ _gsg(gsg) {
|
|
|
|
|
|
// The ATTR# input semantics seem to map to generic vertex attributes in
|
|
|
// both arbvp1 and glslv, which behave more consistently. However, they
|
|
|
@@ -265,12 +265,7 @@ analyze_renderstate(const RenderState *rs) {
|
|
|
|
|
|
const MaterialAttrib *material;
|
|
|
rs->get_attrib_def(material);
|
|
|
-
|
|
|
- if (!material->is_off()) {
|
|
|
- _material = material->get_material();
|
|
|
- } else {
|
|
|
- _material = Material::get_default();
|
|
|
- }
|
|
|
+ _material_flags = material->get_material_flags();
|
|
|
|
|
|
// Break out the lights by type.
|
|
|
|
|
|
@@ -285,14 +280,7 @@ analyze_renderstate(const RenderState *rs) {
|
|
|
nassertv(light_obj != (PandaNode *)NULL);
|
|
|
|
|
|
if (light_obj->is_ambient_light()) {
|
|
|
- if (_material->has_ambient()) {
|
|
|
- LColor a = _material->get_ambient();
|
|
|
- if ((a[0]!=0.0)||(a[1]!=0.0)||(a[2]!=0.0)) {
|
|
|
- _have_ambient = true;
|
|
|
- }
|
|
|
- } else {
|
|
|
- _have_ambient = true;
|
|
|
- }
|
|
|
+ _have_ambient = true;
|
|
|
_lighting = true;
|
|
|
|
|
|
} else if (light_obj->is_of_type(LightLensNode::get_class_type())) {
|
|
|
@@ -357,37 +345,28 @@ analyze_renderstate(const RenderState *rs) {
|
|
|
}
|
|
|
|
|
|
// Determine whether we should normalize the normals.
|
|
|
- const RescaleNormalAttrib *rescale;
|
|
|
+ /*const RescaleNormalAttrib *rescale;
|
|
|
rs->get_attrib_def(rescale);
|
|
|
|
|
|
_normalize_normals = (rescale->get_mode() != RescaleNormalAttrib::M_none);
|
|
|
+ */
|
|
|
+ // Actually, let's always normalize the normals for now. This helps to
|
|
|
+ // reduce combinatoric explosion of shaders.
|
|
|
+ _normalize_normals = true;
|
|
|
|
|
|
// Decide which material modes need to be calculated.
|
|
|
|
|
|
if (_lighting) {
|
|
|
- if (_material->has_diffuse()) {
|
|
|
- LColor d = _material->get_diffuse();
|
|
|
- if ((d[0]!=0.0)||(d[1]!=0.0)||(d[2]!=0.0)) {
|
|
|
- _have_diffuse = true;
|
|
|
- }
|
|
|
- } else {
|
|
|
- _have_diffuse = true;
|
|
|
- }
|
|
|
+ _have_diffuse = true;
|
|
|
}
|
|
|
|
|
|
- if (_lighting && (_material->has_emission())) {
|
|
|
- LColor e = _material->get_emission();
|
|
|
- if ((e[0]!=0.0)||(e[1]!=0.0)||(e[2]!=0.0)) {
|
|
|
- _have_emission = true;
|
|
|
- }
|
|
|
+ if (_lighting && (_material_flags & Material::F_emission) != 0) {
|
|
|
+ _have_emission = true;
|
|
|
}
|
|
|
|
|
|
if (_lighting) {
|
|
|
- if (_material->has_specular()) {
|
|
|
- LColor s = _material->get_specular();
|
|
|
- if ((s[0]!=0.0)||(s[1]!=0.0)||(s[2]!=0.0)) {
|
|
|
- _have_specular = true;
|
|
|
- }
|
|
|
+ if (_material_flags & Material::F_specular) {
|
|
|
+ _have_specular = true;
|
|
|
} else if (_map_index_gloss >= 0) {
|
|
|
_have_specular = true;
|
|
|
}
|
|
|
@@ -398,14 +377,10 @@ analyze_renderstate(const RenderState *rs) {
|
|
|
// Decide whether to separate ambient and diffuse calculations.
|
|
|
|
|
|
if (_have_ambient && _have_diffuse) {
|
|
|
- if (_material->has_ambient()) {
|
|
|
- if (_material->has_diffuse()) {
|
|
|
- _separate_ambient_diffuse = _material->get_ambient() != _material->get_diffuse();
|
|
|
- } else {
|
|
|
- _separate_ambient_diffuse = true;
|
|
|
- }
|
|
|
+ if (_material_flags & Material::F_ambient) {
|
|
|
+ _separate_ambient_diffuse = true;
|
|
|
} else {
|
|
|
- if (_material->has_diffuse()) {
|
|
|
+ if (_material_flags & Material::F_diffuse) {
|
|
|
_separate_ambient_diffuse = true;
|
|
|
} else {
|
|
|
_separate_ambient_diffuse = false;
|
|
|
@@ -427,10 +402,10 @@ analyze_renderstate(const RenderState *rs) {
|
|
|
// Does the shader need material properties as input?
|
|
|
|
|
|
_need_material_props =
|
|
|
- (_have_ambient && (_material->has_ambient()))||
|
|
|
- (_have_diffuse && (_material->has_diffuse()))||
|
|
|
- (_have_emission && (_material->has_emission()))||
|
|
|
- (_have_specular && (_material->has_specular()));
|
|
|
+ (_have_ambient && (_material_flags & Material::F_ambient) != 0) ||
|
|
|
+ (_have_diffuse && (_material_flags & Material::F_diffuse) != 0) ||
|
|
|
+ (_have_emission && (_material_flags & Material::F_emission) != 0) ||
|
|
|
+ (_have_specular && (_material_flags & Material::F_specular) != 0);
|
|
|
|
|
|
// Check for clip planes.
|
|
|
|
|
|
@@ -490,7 +465,7 @@ clear_analysis() {
|
|
|
_out_aux_normal = false;
|
|
|
_out_aux_glow = false;
|
|
|
_out_aux_any = false;
|
|
|
- _material = (Material*)NULL;
|
|
|
+ _material_flags = 0;
|
|
|
_need_material_props = false;
|
|
|
_need_world_position = false;
|
|
|
_need_world_normal = false;
|
|
|
@@ -823,11 +798,10 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
text << "\t in float4 l_" << it->first->join("_") << " : " << it->second << ",\n";
|
|
|
}
|
|
|
const TexMatrixAttrib *tex_matrix = DCAST(TexMatrixAttrib, rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
|
|
|
- for (int i=0; i<_num_textures; i++) {
|
|
|
+ for (int i = 0; i < _num_textures; ++i) {
|
|
|
TextureStage *stage = texture->get_on_stage(i);
|
|
|
- Texture *tex = texture->get_on_texture(stage);
|
|
|
- nassertr(tex != NULL, NULL);
|
|
|
- text << "\t uniform sampler" << texture_type_as_string(tex->get_texture_type()) << " tex_" << i << ",\n";
|
|
|
+ Texture::TextureType type = texture->get_on_texture_type(stage);
|
|
|
+ text << "\t uniform sampler" << texture_type_as_string(type) << " tex_" << i << ",\n";
|
|
|
if (tex_matrix->has_stage(stage)) {
|
|
|
text << "\t uniform float4x4 texmat_" << i << ",\n";
|
|
|
}
|
|
|
@@ -864,7 +838,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
text << "\t uniform float4x4 attr_material,\n";
|
|
|
}
|
|
|
if (_have_specular) {
|
|
|
- if (_material->get_local()) {
|
|
|
+ if (_material_flags & Material::F_local) {
|
|
|
text << "\t uniform float4 mspos_view,\n";
|
|
|
} else {
|
|
|
text << "\t uniform float4 row1_view_to_model,\n";
|
|
|
@@ -935,11 +909,10 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
}
|
|
|
text << "\t // Fetch all textures.\n";
|
|
|
if (_map_index_height >= 0 && parallax_mapping_samples > 0) {
|
|
|
- Texture *tex = texture->get_on_texture(texture->get_on_stage(_map_index_height));
|
|
|
- nassertr(tex != NULL, NULL);
|
|
|
- text << "\t float4 tex" << _map_index_height << " = tex" << texture_type_as_string(tex->get_texture_type());
|
|
|
+ Texture::TextureType type = texture->get_on_texture_type(texture->get_on_stage(_map_index_height));
|
|
|
+ text << "\t float4 tex" << _map_index_height << " = tex" << texture_type_as_string(type);
|
|
|
text << "(tex_" << _map_index_height << ", texcoord" << _map_index_height << ".";
|
|
|
- switch (tex->get_texture_type()) {
|
|
|
+ switch (type) {
|
|
|
case Texture::TT_cube_map:
|
|
|
case Texture::TT_3d_texture:
|
|
|
case Texture::TT_2d_texture_array:
|
|
|
@@ -972,18 +945,17 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
text << " * 2.0 - 1.0)) * " << 0.5 * parallax_mapping_scale << ";\n";
|
|
|
}
|
|
|
}
|
|
|
- for (int i=0; i<_num_textures; i++) {
|
|
|
+ for (int i = 0; i < _num_textures; ++i) {
|
|
|
if (i != _map_index_height) {
|
|
|
- Texture *tex = texture->get_on_texture(texture->get_on_stage(i));
|
|
|
- nassertr(tex != NULL, NULL);
|
|
|
+ Texture::TextureType type = texture->get_on_texture_type(texture->get_on_stage(i));
|
|
|
// Parallax mapping pushes the texture coordinates of the other textures
|
|
|
// away from the camera.
|
|
|
if (_map_index_height >= 0 && parallax_mapping_samples > 0) {
|
|
|
text << "\t texcoord" << i << ".xyz -= parallax_offset;\n";
|
|
|
}
|
|
|
- text << "\t float4 tex" << i << " = tex" << texture_type_as_string(tex->get_texture_type());
|
|
|
+ text << "\t float4 tex" << i << " = tex" << texture_type_as_string(type);
|
|
|
text << "(tex_" << i << ", texcoord" << i << ".";
|
|
|
- switch(tex->get_texture_type()) {
|
|
|
+ switch (type) {
|
|
|
case Texture::TT_cube_map:
|
|
|
case Texture::TT_3d_texture:
|
|
|
case Texture::TT_2d_texture_array:
|
|
|
@@ -1040,7 +1012,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
}
|
|
|
if (_have_specular) {
|
|
|
text << "\t float4 tot_specular = float4(0,0,0,0);\n";
|
|
|
- if (_material->has_specular()) {
|
|
|
+ if (_material_flags & Material::F_specular) {
|
|
|
text << "\t float shininess = attr_material[3].w;\n";
|
|
|
} else {
|
|
|
text << "\t float shininess = 50; // no shininess specified, using default\n";
|
|
|
@@ -1072,7 +1044,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
text << "\t tot_diffuse += lcolor;\n";
|
|
|
}
|
|
|
if (_have_specular) {
|
|
|
- if (_material->get_local()) {
|
|
|
+ if (_material_flags & Material::F_local) {
|
|
|
text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
|
|
|
} else {
|
|
|
text << "\t lhalf = dlight_light" << i << "_rel_view[3].xyz;\n";
|
|
|
@@ -1102,7 +1074,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
text << "\t tot_diffuse += lcolor;\n";
|
|
|
}
|
|
|
if (_have_specular) {
|
|
|
- if (_material->get_local()) {
|
|
|
+ if (_material_flags & Material::F_local) {
|
|
|
text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
|
|
|
} else {
|
|
|
text << "\t lhalf = normalize(lvec - float3(0, 1, 0));\n";
|
|
|
@@ -1140,7 +1112,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
text << "\t tot_diffuse += lcolor;\n";
|
|
|
}
|
|
|
if (_have_specular) {
|
|
|
- if (_material->get_local()) {
|
|
|
+ if (_material_flags & Material::F_local) {
|
|
|
text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
|
|
|
} else {
|
|
|
text << "\t lhalf = normalize(lvec - float3(0,1,0));\n";
|
|
|
@@ -1198,7 +1170,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
}
|
|
|
}
|
|
|
if ((_have_ambient)&&(_separate_ambient_diffuse)) {
|
|
|
- if (_material->has_ambient()) {
|
|
|
+ if (_material_flags & Material::F_ambient) {
|
|
|
text << "\t result += tot_ambient * attr_material[0];\n";
|
|
|
} else if (_vertex_colors) {
|
|
|
text << "\t result += tot_ambient * l_color;\n";
|
|
|
@@ -1209,7 +1181,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
}
|
|
|
}
|
|
|
if (_have_diffuse) {
|
|
|
- if (_material->has_diffuse()) {
|
|
|
+ if (_material_flags & Material::F_diffuse) {
|
|
|
text << "\t result += tot_diffuse * attr_material[1];\n";
|
|
|
} else if (_vertex_colors) {
|
|
|
text << "\t result += tot_diffuse * l_color;\n";
|
|
|
@@ -1263,20 +1235,20 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
}
|
|
|
|
|
|
// Now loop through the textures to compose our magic blending formulas.
|
|
|
- for (int i=0; i<_num_textures; i++) {
|
|
|
+ for (int i = 0; i < _num_textures; ++i) {
|
|
|
TextureStage *stage = texture->get_on_stage(i);
|
|
|
switch (stage->get_mode()) {
|
|
|
case TextureStage::M_modulate: {
|
|
|
- int num_components = texture->get_on_texture(texture->get_on_stage(i))->get_num_components();
|
|
|
+ bool affects_rgb = texture->on_stage_affects_rgb(i);
|
|
|
+ bool affects_alpha = texture->on_stage_affects_alpha(i);
|
|
|
|
|
|
- if (num_components == 1) {
|
|
|
+ if (affects_rgb && affects_alpha) {
|
|
|
+ text << "\t result.rgba *= tex" << i << ".rgba;\n";
|
|
|
+ } else if (affects_alpha) {
|
|
|
text << "\t result.a *= tex" << i << ".a;\n";
|
|
|
- } else if (num_components == 3) {
|
|
|
+ } else if (affects_rgb) {
|
|
|
text << "\t result.rgb *= tex" << i << ".rgb;\n";
|
|
|
- } else {
|
|
|
- text << "\t result.rgba *= tex" << i << ".rgba;\n";
|
|
|
}
|
|
|
-
|
|
|
break; }
|
|
|
case TextureStage::M_modulate_glow:
|
|
|
case TextureStage::M_modulate_gloss:
|
|
|
@@ -1388,7 +1360,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|
|
|
|
|
if (_lighting) {
|
|
|
if (_have_specular) {
|
|
|
- if (_material->has_specular()) {
|
|
|
+ if (_material_flags & Material::F_specular) {
|
|
|
text << "\t tot_specular *= attr_material[3];\n";
|
|
|
}
|
|
|
if (_map_index_gloss >= 0 && _auto_gloss_on) {
|