From 7db45cb647a160dc0acd14f291124d6bd1f71dea Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 27 Nov 2016 14:25:00 +0100 Subject: [PATCH] Make fetching of p3d_LightSource[n] input clearly defined for non-existent lights Refer to OpenGL 2.1 spec page 61 Closes: #129 --- panda/src/display/graphicsStateGuardian.cxx | 125 ++++++++++++++------ 1 file changed, 92 insertions(+), 33 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index ad532c5643..67fbdb2f6c 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -1363,8 +1363,18 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, } } - // TODO: dummy light - nassertr(false, &LMatrix4::ident_mat()); + // Apply the default OpenGL lights otherwise. + // Special exception for light 0, which defaults to white. + if (index == 0) { + string basename = name->get_basename(); + if (basename == "color" || basename == "diffuse") { + t.set_row(3, _light_color_scale); + return &t; + } else if (basename == "specular") { + return &LMatrix4::ones_mat(); + } + } + return fetch_specified_member(NodePath(), name, t); } default: nassertr(false /*should never get here*/, &LMatrix4::ident_mat()); @@ -1395,8 +1405,16 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation"); static const CPT_InternalName IN_shadowMatrix("shadowMatrix"); + PandaNode *node = NULL; + if (!np.is_empty()) { + node = np.node(); + } + if (attrib == IN_color) { - Light *light = np.node()->as_light(); + if (node == (PandaNode *)NULL) { + return &LMatrix4::ident_mat(); + } + Light *light = node->as_light(); nassertr(light != (Light *)NULL, &LMatrix4::ident_mat()); LColor c = light->get_color(); c.componentwise_mult(_light_color_scale); @@ -1404,9 +1422,12 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) return &t; } else if (attrib == IN_ambient) { - Light *light = np.node()->as_light(); + if (node == (PandaNode *)NULL) { + return &LMatrix4::ident_mat(); + } + Light *light = node->as_light(); nassertr(light != (Light *)NULL, &LMatrix4::ident_mat()); - if (np.node()->is_of_type(AmbientLight::get_class_type())) { + if (node->is_of_type(AmbientLight::get_class_type())) { LColor c = light->get_color(); c.componentwise_mult(_light_color_scale); t.set_row(3, c); @@ -1417,9 +1438,12 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) return &t; } else if (attrib == IN_diffuse) { - Light *light = np.node()->as_light(); + if (node == (PandaNode *)NULL) { + return &LMatrix4::ident_mat(); + } + Light *light = node->as_light(); nassertr(light != (Light *)NULL, &LMatrix4::ones_mat()); - if (np.node()->is_of_type(AmbientLight::get_class_type())) { + if (node->is_of_type(AmbientLight::get_class_type())) { // Ambient light has no diffuse color. t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f)); } else { @@ -1430,19 +1454,25 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) return &t; } else if (attrib == IN_specular) { - Light *light = np.node()->as_light(); + if (node == (PandaNode *)NULL) { + return &LMatrix4::ident_mat(); + } + Light *light = node->as_light(); nassertr(light != (Light *)NULL, &LMatrix4::ones_mat()); t.set_row(3, light->get_specular_color()); return &t; } else if (attrib == IN_position) { - if (np.node()->is_of_type(AmbientLight::get_class_type())) { + if (np.is_empty()) { + t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0); + return &t; + } else if (node->is_of_type(AmbientLight::get_class_type())) { // Ambient light has no position. t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); return &t; - } else if (np.node()->is_of_type(DirectionalLight::get_class_type())) { + } else if (node->is_of_type(DirectionalLight::get_class_type())) { DirectionalLight *light; - DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat()); + DCAST_INTO_R(light, node, &LMatrix4::ident_mat()); CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent()); LVector3 dir = -(light->get_direction() * transform->get_mat()); @@ -1451,7 +1481,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) return &t; } else { LightLensNode *light; - DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat()); + DCAST_INTO_R(light, node, &LMatrix4::ident_mat()); Lens *lens = light->get_lens(); nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat()); @@ -1466,13 +1496,16 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) } } else if (attrib == IN_halfVector) { - if (np.node()->is_of_type(AmbientLight::get_class_type())) { + if (np.is_empty()) { + t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0); + return &t; + } else if (node->is_of_type(AmbientLight::get_class_type())) { // Ambient light has no half-vector. t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); return &t; - } else if (np.node()->is_of_type(DirectionalLight::get_class_type())) { + } else if (node->is_of_type(DirectionalLight::get_class_type())) { DirectionalLight *light; - DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat()); + DCAST_INTO_R(light, node, &LMatrix4::ident_mat()); CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent()); LVector3 dir = -(light->get_direction() * transform->get_mat()); @@ -1484,7 +1517,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) return &t; } else { LightLensNode *light; - DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat()); + DCAST_INTO_R(light, node, &LMatrix4::ident_mat()); Lens *lens = light->get_lens(); nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat()); @@ -1502,13 +1535,16 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) } } else if (attrib == IN_spotDirection) { - if (np.node()->is_of_type(AmbientLight::get_class_type())) { + if (node == (PandaNode *)NULL) { + t.set_row(3, LVector3(0.0f, 0.0f, -1.0f)); + return &t; + } else if (node->is_of_type(AmbientLight::get_class_type())) { // Ambient light has no spot direction. t.set_row(3, LVector3(0.0f, 0.0f, 0.0f)); return &t; } else { LightLensNode *light; - DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat()); + DCAST_INTO_R(light, node, &LMatrix4::ident_mat()); Lens *lens = light->get_lens(); nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat()); @@ -1523,9 +1559,10 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) } } else if (attrib == IN_spotCutoff) { - if (np.node()->is_of_type(Spotlight::get_class_type())) { + if (node != (PandaNode *)NULL && + node->is_of_type(Spotlight::get_class_type())) { LightLensNode *light; - DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat()); + DCAST_INTO_R(light, node, &LMatrix4::ident_mat()); Lens *lens = light->get_lens(); nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat()); @@ -1539,9 +1576,10 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) } } else if (attrib == IN_spotCosCutoff) { - if (np.node()->is_of_type(Spotlight::get_class_type())) { + if (node != (PandaNode *)NULL && + node->is_of_type(Spotlight::get_class_type())) { LightLensNode *light; - DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat()); + DCAST_INTO_R(light, node, &LMatrix4::ident_mat()); Lens *lens = light->get_lens(); nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat()); @@ -1553,51 +1591,72 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) t.set_row(3, LVecBase4(-1)); return &t; } + } else if (attrib == IN_spotExponent) { - Light *light = np.node()->as_light(); + if (node == (PandaNode *)NULL) { + return &LMatrix4::zeros_mat(); + } + Light *light = node->as_light(); nassertr(light != (Light *)NULL, &LMatrix4::ident_mat()); t.set_row(3, LVecBase4(light->get_exponent())); return &t; } else if (attrib == IN_attenuation) { - Light *light = np.node()->as_light(); - nassertr(light != (Light *)NULL, &LMatrix4::ones_mat()); + if (node != (PandaNode *)NULL) { + Light *light = node->as_light(); + nassertr(light != (Light *)NULL, &LMatrix4::ones_mat()); - t.set_row(3, LVecBase4(light->get_attenuation(), 0)); + t.set_row(3, LVecBase4(light->get_attenuation(), 0)); + } else { + t.set_row(3, LVecBase4(1, 0, 0, 0)); + } return &t; } else if (attrib == IN_constantAttenuation) { - Light *light = np.node()->as_light(); + if (node == (PandaNode *)NULL) { + return &LMatrix4::ones_mat(); + } + Light *light = node->as_light(); nassertr(light != (Light *)NULL, &LMatrix4::ones_mat()); t.set_row(3, LVecBase4(light->get_attenuation()[0])); return &t; } else if (attrib == IN_linearAttenuation) { - Light *light = np.node()->as_light(); + if (node == (PandaNode *)NULL) { + return &LMatrix4::zeros_mat(); + } + Light *light = node->as_light(); nassertr(light != (Light *)NULL, &LMatrix4::ident_mat()); t.set_row(3, LVecBase4(light->get_attenuation()[1])); return &t; } else if (attrib == IN_quadraticAttenuation) { - Light *light = np.node()->as_light(); + if (node == (PandaNode *)NULL) { + return &LMatrix4::zeros_mat(); + } + Light *light = node->as_light(); nassertr(light != (Light *)NULL, &LMatrix4::ident_mat()); t.set_row(3, LVecBase4(light->get_attenuation()[2])); return &t; } else if (attrib == IN_shadowMatrix) { - LensNode *lnode; - DCAST_INTO_R(lnode, np.node(), &LMatrix4::ident_mat()); - Lens *lens = lnode->get_lens(); - static const LMatrix4 biasmat(0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f); + if (node == (PandaNode *)NULL) { + return &biasmat; + } + + LensNode *lnode; + DCAST_INTO_R(lnode, node, &LMatrix4::ident_mat()); + Lens *lens = lnode->get_lens(); + t = get_external_transform()->get_mat() * get_scene()->get_camera_transform()->get_mat() * np.get_net_transform()->get_inverse()->get_mat() *