Improve shadow system, add point light shadows, GLSL shadow inputs
This commit is contained in:
parent
571fd7d72e
commit
25451feb87
|
|
@ -445,6 +445,12 @@ ConfigVariableDouble pixel_zoom
|
|||
("pixel-zoom", 1.0,
|
||||
PRC_DESC("The default pixel_zoom factor for new windows."));
|
||||
|
||||
ConfigVariableInt shadow_depth_bits
|
||||
("shadow-depth-bits", 24,
|
||||
PRC_DESC("The minimum number of depth buffer bits requested when rendering "
|
||||
"shadow maps. Set this to 32 for more depth resolution in shadow "
|
||||
"maps."));
|
||||
|
||||
ConfigVariableColor background_color
|
||||
("background-color", "0.41 0.41 0.41 0.0",
|
||||
PRC_DESC("Specifies the rgb(a) value of the default background color for a "
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableInt stencil_bits;
|
|||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt accum_bits;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt multisamples;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt back_buffers;
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableInt shadow_depth_bits;
|
||||
|
||||
extern EXPCL_PANDA_DISPLAY ConfigVariableDouble pixel_zoom;
|
||||
|
||||
|
|
|
|||
|
|
@ -1480,7 +1480,8 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
|
|||
|
||||
// Keep track of the cameras we have already used in this thread to
|
||||
// render DisplayRegions.
|
||||
typedef pmap<NodePath, DisplayRegion *> AlreadyCulled;
|
||||
typedef pair<NodePath, int> CullKey;
|
||||
typedef pmap<CullKey, DisplayRegion *> AlreadyCulled;
|
||||
AlreadyCulled already_culled;
|
||||
|
||||
size_t wlist_size = wlist.size();
|
||||
|
|
@ -1495,7 +1496,9 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
|
|||
DisplayRegionPipelineReader *dr_reader =
|
||||
new DisplayRegionPipelineReader(dr, current_thread);
|
||||
NodePath camera = dr_reader->get_camera();
|
||||
AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(camera, (DisplayRegion *)NULL)).first;
|
||||
int lens_index = dr_reader->get_lens_index();
|
||||
|
||||
AlreadyCulled::iterator aci = already_culled.insert(AlreadyCulled::value_type(CullKey(camera, lens_index), (DisplayRegion *)NULL)).first;
|
||||
if ((*aci).second == NULL) {
|
||||
// We have not used this camera already in this thread.
|
||||
// Perform the cull operation.
|
||||
|
|
|
|||
|
|
@ -967,9 +967,15 @@ fetch_specified_value(Shader::ShaderMatSpec &spec, int altered) {
|
|||
spec._value.set_row(3, v);
|
||||
return &spec._value;
|
||||
case Shader::SMF_transform_plight:
|
||||
spec._value = spec._cache[0];
|
||||
spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2)));
|
||||
return &spec._value;
|
||||
{
|
||||
// Careful not to touch the w component, which contains the near value.
|
||||
spec._value = spec._cache[0];
|
||||
LPoint3 point = spec._cache[1].xform_point(spec._cache[0].get_row3(2));
|
||||
spec._value(2, 0) = point[0];
|
||||
spec._value(2, 1) = point[1];
|
||||
spec._value(2, 2) = point[2];
|
||||
return &spec._value;
|
||||
}
|
||||
case Shader::SMF_transform_slight:
|
||||
spec._value = spec._cache[0];
|
||||
spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2)));
|
||||
|
|
@ -1152,7 +1158,9 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
get_scene()->get_world_transform()->get_mat();
|
||||
LVecBase3 p = (t.xform_point(lt->get_point()));
|
||||
LVecBase3 a = lt->get_attenuation();
|
||||
t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],0,a[0],a[1],a[2],0);
|
||||
PN_stdfloat near = lt->get_lens(0)->get_near();
|
||||
PN_stdfloat far = lt->get_lens(0)->get_far();
|
||||
t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],near,a[0],a[1],a[2],far);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_slight_x: {
|
||||
|
|
@ -1405,8 +1413,19 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
calc_projection_mat(lens)->get_mat();
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_mat_constant_x_attrib: {
|
||||
if (_target_shader->has_shader_input(name)) {
|
||||
// There is an input specifying precisely this whole thing, with
|
||||
// dot and all. Support this, even if only for backward compatibility.
|
||||
return &_target_shader->get_shader_input_matrix(name, t);
|
||||
}
|
||||
|
||||
const NodePath &np = _target_shader->get_shader_input_nodepath(name->get_parent());
|
||||
nassertr(!np.is_empty(), &LMatrix4::ident_mat());
|
||||
|
||||
return fetch_specified_member(np, name->get_basename(), t);
|
||||
}
|
||||
case Shader::SMO_vec_constant_x_attrib: {
|
||||
// This system is not ideal. It will be improved in the future.
|
||||
if (_target_shader->has_shader_input(name)) {
|
||||
// There is an input specifying precisely this whole thing, with
|
||||
// dot and all. Support this, even if only for backward compatibility.
|
||||
|
|
@ -1421,205 +1440,33 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
const NodePath &np = _target_shader->get_shader_input_nodepath(name->get_parent());
|
||||
nassertr(!np.is_empty(), &LMatrix4::ident_mat());
|
||||
|
||||
CPT_InternalName attrib = name->get_basename();
|
||||
return fetch_specified_member(np, name->get_basename(), t);
|
||||
}
|
||||
case Shader::SMO_light_source_i_attrib: {
|
||||
const LightAttrib *target_light;
|
||||
_target_rs->get_attrib_def(target_light);
|
||||
|
||||
static const CPT_InternalName IN_ambient("ambient");
|
||||
static const CPT_InternalName IN_diffuse("diffuse");
|
||||
static const CPT_InternalName IN_specular("specular");
|
||||
static const CPT_InternalName IN_position("position");
|
||||
static const CPT_InternalName IN_halfVector("halfVector");
|
||||
static const CPT_InternalName IN_spotDirection("spotDirection");
|
||||
static const CPT_InternalName IN_spotCutoff("spotCutoff");
|
||||
static const CPT_InternalName IN_spotCosCutoff("spotCosCutoff");
|
||||
static const CPT_InternalName IN_spotExponent("spotExponent");
|
||||
static const CPT_InternalName IN_constantAttenuation("constantAttenuation");
|
||||
static const CPT_InternalName IN_linearAttenuation("linearAttenuation");
|
||||
static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation");
|
||||
// We want to ignore ambient lights. To that effect, iterate through
|
||||
// the list of lights. In the future, we will improve this system, by
|
||||
// also filtering down to the number of lights specified by the shader.
|
||||
int i = 0;
|
||||
|
||||
if (attrib == IN_ambient) {
|
||||
Light *light = np.node()->as_light();
|
||||
nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
|
||||
if (np.node()->is_of_type(AmbientLight::get_class_type())) {
|
||||
LColor c = light->get_color();
|
||||
c.componentwise_mult(_light_color_scale);
|
||||
t.set_row(3, c);
|
||||
} else {
|
||||
// Non-ambient lights don't currently have an ambient color in Panda3D.
|
||||
t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
int num_on_lights = target_light->get_num_on_lights();
|
||||
for (int li = 0; li < num_on_lights; li++) {
|
||||
NodePath light = target_light->get_on_light(li);
|
||||
nassertr(!light.is_empty(), &LMatrix4::ident_mat());
|
||||
Light *light_obj = light.node()->as_light();
|
||||
nassertr(light_obj != (Light *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
if (light_obj->get_type() != AmbientLight::get_class_type()) {
|
||||
if (i++ == index) {
|
||||
return fetch_specified_member(light, name, t);
|
||||
}
|
||||
}
|
||||
return &t;
|
||||
|
||||
} else if (attrib == IN_diffuse) {
|
||||
Light *light = np.node()->as_light();
|
||||
nassertr(light != (Light *)NULL, &LMatrix4::ones_mat());
|
||||
if (np.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 {
|
||||
LColor c = light->get_color();
|
||||
c.componentwise_mult(_light_color_scale);
|
||||
t.set_row(3, c);
|
||||
}
|
||||
return &t;
|
||||
|
||||
} else if (attrib == IN_specular) {
|
||||
Light *light = np.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())) {
|
||||
// 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())) {
|
||||
DirectionalLight *light;
|
||||
DCAST_INTO_R(light, np.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());
|
||||
dir *= get_scene()->get_cs_world_transform()->get_mat();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],0);
|
||||
return &t;
|
||||
} else {
|
||||
LightLensNode *light;
|
||||
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
|
||||
Lens *lens = light->get_lens();
|
||||
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
CPT(TransformState) transform =
|
||||
get_scene()->get_cs_world_transform()->compose(
|
||||
np.get_transform(_scene_setup->get_scene_root().get_parent()));
|
||||
|
||||
const LMatrix4 &light_mat = transform->get_mat();
|
||||
LPoint3 pos = lens->get_nodal_point() * light_mat;
|
||||
t = LMatrix4::translate_mat(pos);
|
||||
return &t;
|
||||
}
|
||||
|
||||
} else if (attrib == IN_halfVector) {
|
||||
if (np.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())) {
|
||||
DirectionalLight *light;
|
||||
DCAST_INTO_R(light, np.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());
|
||||
dir *= get_scene()->get_cs_world_transform()->get_mat();
|
||||
dir.normalize();
|
||||
dir += LVector3(0, 0, 1);
|
||||
dir.normalize();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],1);
|
||||
return &t;
|
||||
} else {
|
||||
LightLensNode *light;
|
||||
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
|
||||
Lens *lens = light->get_lens();
|
||||
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
CPT(TransformState) transform =
|
||||
get_scene()->get_cs_world_transform()->compose(
|
||||
np.get_transform(_scene_setup->get_scene_root().get_parent()));
|
||||
|
||||
const LMatrix4 &light_mat = transform->get_mat();
|
||||
LPoint3 pos = lens->get_nodal_point() * light_mat;
|
||||
pos.normalize();
|
||||
pos += LVector3(0, 0, 1);
|
||||
pos.normalize();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,pos[0],pos[1],pos[2],1);
|
||||
return &t;
|
||||
}
|
||||
|
||||
} else if (attrib == IN_spotDirection) {
|
||||
if (np.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());
|
||||
Lens *lens = light->get_lens();
|
||||
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
CPT(TransformState) transform =
|
||||
get_scene()->get_cs_world_transform()->compose(
|
||||
np.get_transform(_scene_setup->get_scene_root().get_parent()));
|
||||
|
||||
const LMatrix4 &light_mat = transform->get_mat();
|
||||
LVector3 dir = lens->get_view_vector() * light_mat;
|
||||
t.set_row(3, dir);
|
||||
return &t;
|
||||
}
|
||||
|
||||
} else if (attrib == IN_spotCutoff) {
|
||||
if (np.node()->is_of_type(Spotlight::get_class_type())) {
|
||||
LightLensNode *light;
|
||||
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
|
||||
Lens *lens = light->get_lens();
|
||||
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
float cutoff = lens->get_hfov() * 0.5f;
|
||||
t.set_row(3, LVecBase4(cutoff));
|
||||
return &t;
|
||||
} else {
|
||||
// Other lights have no cut-off.
|
||||
t.set_row(3, LVecBase4(180));
|
||||
return &t;
|
||||
}
|
||||
|
||||
} else if (attrib == IN_spotCosCutoff) {
|
||||
if (np.node()->is_of_type(Spotlight::get_class_type())) {
|
||||
LightLensNode *light;
|
||||
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
|
||||
Lens *lens = light->get_lens();
|
||||
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
float cutoff = lens->get_hfov() * 0.5f;
|
||||
t.set_row(3, LVecBase4(ccos(deg_2_rad(cutoff))));
|
||||
return &t;
|
||||
} else {
|
||||
// Other lights have no cut-off.
|
||||
t.set_row(3, LVecBase4(-1));
|
||||
return &t;
|
||||
}
|
||||
} else if (attrib == IN_spotExponent) {
|
||||
Light *light = np.node()->as_light();
|
||||
nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
t.set_row(3, LVecBase4(light->get_exponent()));
|
||||
return &t;
|
||||
|
||||
} else if (attrib == IN_constantAttenuation) {
|
||||
Light *light = np.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();
|
||||
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();
|
||||
nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
t.set_row(3, LVecBase4(light->get_attenuation()[2]));
|
||||
return &t;
|
||||
|
||||
} else {
|
||||
display_cat.error()
|
||||
<< "Shader input requests invalid attribute " << *name
|
||||
<< " from node " << np << "\n";
|
||||
return &LMatrix4::ident_mat();
|
||||
}
|
||||
|
||||
// TODO: dummy light
|
||||
nassertr(false, &LMatrix4::ident_mat());
|
||||
}
|
||||
default:
|
||||
nassertr(false /*should never get here*/, &LMatrix4::ident_mat());
|
||||
|
|
@ -1627,6 +1474,346 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::fetch_specified_member
|
||||
// Access: Public
|
||||
// Description: Given a NodePath passed into a shader input that is
|
||||
// a structure, fetches the value for the given member.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const LMatrix4 *GraphicsStateGuardian::
|
||||
fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) {
|
||||
// This system is not ideal. It will be improved in the future.
|
||||
static const CPT_InternalName IN_ambient("ambient");
|
||||
static const CPT_InternalName IN_diffuse("diffuse");
|
||||
static const CPT_InternalName IN_specular("specular");
|
||||
static const CPT_InternalName IN_position("position");
|
||||
static const CPT_InternalName IN_halfVector("halfVector");
|
||||
static const CPT_InternalName IN_spotDirection("spotDirection");
|
||||
static const CPT_InternalName IN_spotCutoff("spotCutoff");
|
||||
static const CPT_InternalName IN_spotCosCutoff("spotCosCutoff");
|
||||
static const CPT_InternalName IN_spotExponent("spotExponent");
|
||||
static const CPT_InternalName IN_attenuation("attenuation");
|
||||
static const CPT_InternalName IN_constantAttenuation("constantAttenuation");
|
||||
static const CPT_InternalName IN_linearAttenuation("linearAttenuation");
|
||||
static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation");
|
||||
static const CPT_InternalName IN_shadowMatrix("shadowMatrix");
|
||||
|
||||
if (attrib == IN_ambient) {
|
||||
Light *light = np.node()->as_light();
|
||||
nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
|
||||
if (np.node()->is_of_type(AmbientLight::get_class_type())) {
|
||||
LColor c = light->get_color();
|
||||
c.componentwise_mult(_light_color_scale);
|
||||
t.set_row(3, c);
|
||||
} else {
|
||||
// Non-ambient lights don't currently have an ambient color in Panda3D.
|
||||
t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
}
|
||||
return &t;
|
||||
|
||||
} else if (attrib == IN_diffuse) {
|
||||
Light *light = np.node()->as_light();
|
||||
nassertr(light != (Light *)NULL, &LMatrix4::ones_mat());
|
||||
if (np.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 {
|
||||
LColor c = light->get_color();
|
||||
c.componentwise_mult(_light_color_scale);
|
||||
t.set_row(3, c);
|
||||
}
|
||||
return &t;
|
||||
|
||||
} else if (attrib == IN_specular) {
|
||||
Light *light = np.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())) {
|
||||
// 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())) {
|
||||
DirectionalLight *light;
|
||||
DCAST_INTO_R(light, np.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());
|
||||
dir *= get_scene()->get_cs_world_transform()->get_mat();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],0);
|
||||
return &t;
|
||||
} else {
|
||||
LightLensNode *light;
|
||||
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
|
||||
Lens *lens = light->get_lens();
|
||||
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
CPT(TransformState) transform =
|
||||
get_scene()->get_cs_world_transform()->compose(
|
||||
np.get_transform(_scene_setup->get_scene_root().get_parent()));
|
||||
|
||||
const LMatrix4 &light_mat = transform->get_mat();
|
||||
LPoint3 pos = lens->get_nodal_point() * light_mat;
|
||||
t = LMatrix4::translate_mat(pos);
|
||||
return &t;
|
||||
}
|
||||
|
||||
} else if (attrib == IN_halfVector) {
|
||||
if (np.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())) {
|
||||
DirectionalLight *light;
|
||||
DCAST_INTO_R(light, np.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());
|
||||
dir *= get_scene()->get_cs_world_transform()->get_mat();
|
||||
dir.normalize();
|
||||
dir += LVector3(0, 0, 1);
|
||||
dir.normalize();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],1);
|
||||
return &t;
|
||||
} else {
|
||||
LightLensNode *light;
|
||||
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
|
||||
Lens *lens = light->get_lens();
|
||||
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
CPT(TransformState) transform =
|
||||
get_scene()->get_cs_world_transform()->compose(
|
||||
np.get_transform(_scene_setup->get_scene_root().get_parent()));
|
||||
|
||||
const LMatrix4 &light_mat = transform->get_mat();
|
||||
LPoint3 pos = lens->get_nodal_point() * light_mat;
|
||||
pos.normalize();
|
||||
pos += LVector3(0, 0, 1);
|
||||
pos.normalize();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,pos[0],pos[1],pos[2],1);
|
||||
return &t;
|
||||
}
|
||||
|
||||
} else if (attrib == IN_spotDirection) {
|
||||
if (np.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());
|
||||
Lens *lens = light->get_lens();
|
||||
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
CPT(TransformState) transform =
|
||||
get_scene()->get_cs_world_transform()->compose(
|
||||
np.get_transform(_scene_setup->get_scene_root().get_parent()));
|
||||
|
||||
const LMatrix4 &light_mat = transform->get_mat();
|
||||
LVector3 dir = lens->get_view_vector() * light_mat;
|
||||
t.set_row(3, dir);
|
||||
return &t;
|
||||
}
|
||||
|
||||
} else if (attrib == IN_spotCutoff) {
|
||||
if (np.node()->is_of_type(Spotlight::get_class_type())) {
|
||||
LightLensNode *light;
|
||||
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
|
||||
Lens *lens = light->get_lens();
|
||||
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
float cutoff = lens->get_hfov() * 0.5f;
|
||||
t.set_row(3, LVecBase4(cutoff));
|
||||
return &t;
|
||||
} else {
|
||||
// Other lights have no cut-off.
|
||||
t.set_row(3, LVecBase4(180));
|
||||
return &t;
|
||||
}
|
||||
|
||||
} else if (attrib == IN_spotCosCutoff) {
|
||||
if (np.node()->is_of_type(Spotlight::get_class_type())) {
|
||||
LightLensNode *light;
|
||||
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
|
||||
Lens *lens = light->get_lens();
|
||||
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
|
||||
|
||||
float cutoff = lens->get_hfov() * 0.5f;
|
||||
t.set_row(3, LVecBase4(ccos(deg_2_rad(cutoff))));
|
||||
return &t;
|
||||
} else {
|
||||
// Other lights have no cut-off.
|
||||
t.set_row(3, LVecBase4(-1));
|
||||
return &t;
|
||||
}
|
||||
} else if (attrib == IN_spotExponent) {
|
||||
Light *light = np.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());
|
||||
|
||||
t.set_row(3, LVecBase4(light->get_attenuation(), 0));
|
||||
return &t;
|
||||
|
||||
} else if (attrib == IN_constantAttenuation) {
|
||||
Light *light = np.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();
|
||||
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();
|
||||
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);
|
||||
|
||||
t = get_external_transform()->get_mat() *
|
||||
get_scene()->get_camera_transform()->get_mat() *
|
||||
np.get_net_transform()->get_inverse()->get_mat() *
|
||||
LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system()) *
|
||||
lens->get_projection_mat() * biasmat;
|
||||
return &t;
|
||||
|
||||
} else {
|
||||
display_cat.error()
|
||||
<< "Shader input requests invalid attribute " << *attrib
|
||||
<< " from node " << np << "\n";
|
||||
return &LMatrix4::ident_mat();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::fetch_specified_texture
|
||||
// Access: Public
|
||||
// Description: Like fetch_specified_value, but for texture inputs.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(Texture) GraphicsStateGuardian::
|
||||
fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
|
||||
int &view) {
|
||||
switch (spec._part) {
|
||||
case Shader::STO_named_input:
|
||||
// Named texture input.
|
||||
if (!_target_shader->has_shader_input(spec._name)) {
|
||||
// Is this a member of something, like a node?
|
||||
const InternalName *parent = spec._name->get_parent();
|
||||
if (parent != InternalName::get_root() &&
|
||||
_target_shader->has_shader_input(parent)) {
|
||||
|
||||
// Yes, grab the node.
|
||||
const string &basename = spec._name->get_basename();
|
||||
NodePath np = _target_shader->get_shader_input_nodepath(parent);
|
||||
|
||||
if (basename == "shadowMap") {
|
||||
PT(Texture) tex = get_shadow_map(np);
|
||||
if (tex != (Texture *)NULL) {
|
||||
sampler = tex->get_default_sampler();
|
||||
}
|
||||
return tex;
|
||||
|
||||
} else {
|
||||
if (spec._stage == 0) {
|
||||
display_cat.error()
|
||||
<< "Shader input " << *parent
|
||||
<< " has no member named " << basename << ".\n";
|
||||
spec._stage = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// This used to be legal for some reason, so don't trigger the assert.
|
||||
// Prevent flood, though, so abuse the _stage flag to indicate whether
|
||||
// we've already errored about this.
|
||||
if (spec._stage == 0) {
|
||||
display_cat.error()
|
||||
<< "Shader input " << *spec._name << " is not present.\n";
|
||||
spec._stage = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Just a regular texture input.
|
||||
return _target_shader->get_shader_input_texture(spec._name, &sampler);
|
||||
}
|
||||
break;
|
||||
|
||||
case Shader::STO_stage_i:
|
||||
{
|
||||
// We get the TextureAttrib directly from the _target_rs, not the
|
||||
// filtered TextureAttrib in _target_texture.
|
||||
const TextureAttrib *texattrib;
|
||||
_target_rs->get_attrib_def(texattrib);
|
||||
|
||||
if (spec._stage < texattrib->get_num_on_stages()) {
|
||||
TextureStage *stage = texattrib->get_on_stage(spec._stage);
|
||||
sampler = texattrib->get_on_sampler(stage);
|
||||
view += stage->get_tex_view_offset();
|
||||
return texattrib->get_on_texture(stage);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Shader::STO_light_i_shadow_map:
|
||||
{
|
||||
const LightAttrib *target_light;
|
||||
_target_rs->get_attrib_def(target_light);
|
||||
|
||||
// We want to ignore ambient lights. To that effect, iterate through
|
||||
// the list of lights. In the future, we will improve this system, by
|
||||
// also filtering down to the number of lights specified by the shader.
|
||||
int i = 0;
|
||||
|
||||
int num_on_lights = target_light->get_num_on_lights();
|
||||
for (int li = 0; li < num_on_lights; li++) {
|
||||
NodePath light = target_light->get_on_light(li);
|
||||
nassertr(!light.is_empty(), NULL);
|
||||
Light *light_obj = light.node()->as_light();
|
||||
nassertr(light_obj != (Light *)NULL, NULL);
|
||||
|
||||
if (light_obj->get_type() != AmbientLight::get_class_type()) {
|
||||
if (i++ == spec._stage) {
|
||||
PT(Texture) tex = get_shadow_map(light);
|
||||
if (tex != (Texture *)NULL) {
|
||||
sampler = tex->get_default_sampler();
|
||||
}
|
||||
return tex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nassertr(false, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::fetch_ptr_parameter
|
||||
// Access: Public
|
||||
|
|
@ -2579,8 +2766,8 @@ do_issue_light() {
|
|||
int num_enabled = 0;
|
||||
int num_on_lights = 0;
|
||||
|
||||
const LightAttrib *target_light = (const LightAttrib *)
|
||||
_target_rs->get_attrib_def(LightAttrib::get_class_slot());
|
||||
const LightAttrib *target_light;
|
||||
_target_rs->get_attrib_def(target_light);
|
||||
|
||||
if (display_cat.is_spam()) {
|
||||
display_cat.spam()
|
||||
|
|
@ -3161,6 +3348,42 @@ async_reload_texture(TextureContext *tc) {
|
|||
_loader->load_async(request);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_shadow_map
|
||||
// Access: Protected
|
||||
// Description: Returns a shadow map for the given light source.
|
||||
// If none exists, it is created, using the given host
|
||||
// window to create the buffer, or the current window
|
||||
// if that is set to NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(Texture) GraphicsStateGuardian::
|
||||
get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host) {
|
||||
nassertr(light_np.node()->is_of_type(DirectionalLight::get_class_type()) ||
|
||||
light_np.node()->is_of_type(PointLight::get_class_type()) ||
|
||||
light_np.node()->is_of_type(Spotlight::get_class_type()), NULL);
|
||||
|
||||
PT(LightLensNode) light = DCAST(LightLensNode, light_np.node());
|
||||
if (light == NULL || !light->_shadow_caster) {
|
||||
//TODO: return dummy shadow map (all white).
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// See if we already have a buffer. If not, create one.
|
||||
if (light->_sbuffers.count(this) == 0) {
|
||||
if (host == (GraphicsOutputBase *)NULL) {
|
||||
host = _current_display_region->get_window();
|
||||
}
|
||||
nassertr(host != NULL, NULL);
|
||||
|
||||
// Nope, the light doesn't have a buffer for our GSG. Make one.
|
||||
return make_shadow_buffer(light_np, host);
|
||||
|
||||
} else {
|
||||
// There's already a buffer - use that.
|
||||
return light->_sbuffers[this]->get_texture();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::make_shadow_buffer
|
||||
// Access: Protected
|
||||
|
|
@ -3186,13 +3409,17 @@ make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) {
|
|||
|
||||
nassertr(light->_sbuffers.count(this) == 0, NULL);
|
||||
|
||||
display_cat.debug() << "Constructing shadow buffer for light '" << light->get_name()
|
||||
<< "', size=" << light->_sb_xsize << "x" << light->_sb_ysize
|
||||
<< ", sort=" << light->_sb_sort << "\n";
|
||||
if (display_cat.is_debug()) {
|
||||
display_cat.debug()
|
||||
<< "Constructing shadow buffer for light '" << light->get_name()
|
||||
<< "', size=" << light->_sb_xsize << "x" << light->_sb_ysize
|
||||
<< ", sort=" << light->_sb_sort << "\n";
|
||||
}
|
||||
|
||||
// Setup some flags and properties
|
||||
// Determine the properties for creating the depth buffer.
|
||||
FrameBufferProperties fbp;
|
||||
fbp.set_depth_bits(1); // We only need depth
|
||||
fbp.set_depth_bits(shadow_depth_bits);
|
||||
|
||||
WindowProperties props = WindowProperties::size(light->_sb_xsize, light->_sb_ysize);
|
||||
int flags = GraphicsPipe::BF_refuse_window;
|
||||
if (is_point) {
|
||||
|
|
@ -3228,12 +3455,12 @@ make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) {
|
|||
tex->set_border_color(LVecBase4(1, 1, 1, 1));
|
||||
}
|
||||
|
||||
if (get_supports_shadow_filter()) {
|
||||
// Note: cube map shadow filtering doesn't seem to work in Cg.
|
||||
if (get_supports_shadow_filter() && !is_point) {
|
||||
// If we have the ARB_shadow extension, enable shadow filtering.
|
||||
tex->set_minfilter(SamplerState::FT_shadow);
|
||||
tex->set_magfilter(SamplerState::FT_shadow);
|
||||
} else {
|
||||
// We only accept linear - this tells the GPU to use hardware PCF.
|
||||
tex->set_minfilter(SamplerState::FT_linear);
|
||||
tex->set_magfilter(SamplerState::FT_linear);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,6 +263,9 @@ public:
|
|||
const LMatrix4 *fetch_specified_value(Shader::ShaderMatSpec &spec, int altered);
|
||||
const LMatrix4 *fetch_specified_part(Shader::ShaderMatInput input, InternalName *name,
|
||||
LMatrix4 &t, int index);
|
||||
const LMatrix4 *fetch_specified_member(const NodePath &np, CPT_InternalName member, LMatrix4 &t);
|
||||
PT(Texture) fetch_specified_texture(Shader::ShaderTexSpec &spec,
|
||||
SamplerState &sampler, int &view);
|
||||
const Shader::ShaderPtrData *fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec);
|
||||
|
||||
virtual void prepare_display_region(DisplayRegionPipelineReader *dr);
|
||||
|
|
@ -348,7 +351,8 @@ public:
|
|||
|
||||
static void create_gamma_table (PN_stdfloat gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table);
|
||||
|
||||
virtual PT(Texture) make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host);
|
||||
PT(Texture) get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host=NULL);
|
||||
PT(Texture) make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host);
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
static void init_frame_pstats();
|
||||
|
|
|
|||
|
|
@ -1090,26 +1090,16 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||
continue;
|
||||
}
|
||||
int texunit = cgGetParameterResourceIndex(p);
|
||||
|
||||
Texture *tex = NULL;
|
||||
int view = _glgsg->get_current_tex_view_offset();
|
||||
SamplerState sampler;
|
||||
|
||||
if (id != NULL) {
|
||||
tex = _glgsg->_target_shader->get_shader_input_texture(id, &sampler);
|
||||
|
||||
} else {
|
||||
if (spec._stage >= texattrib->get_num_on_stages()) {
|
||||
// Apply a white texture in order to make it easier to use a shader
|
||||
// that takes a texture on a model that doesn't have a texture applied.
|
||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + texunit);
|
||||
_glgsg->apply_white_texture();
|
||||
continue;
|
||||
}
|
||||
TextureStage *stage = texattrib->get_on_stage(spec._stage);
|
||||
tex = texattrib->get_on_texture(stage);
|
||||
sampler = texattrib->get_on_sampler(stage);
|
||||
view += stage->get_tex_view_offset();
|
||||
PT(Texture) tex = _glgsg->fetch_specified_texture(spec, sampler, view);
|
||||
if (tex.is_null()) {
|
||||
// Apply a white texture in order to make it easier to use a shader
|
||||
// that takes a texture on a model that doesn't have a texture applied.
|
||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + i);
|
||||
_glgsg->apply_white_texture();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spec._suffix != 0) {
|
||||
|
|
|
|||
|
|
@ -6841,7 +6841,7 @@ bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
|
|||
call_glLightfv(id, GL_POSITION, fpos);
|
||||
call_glLightfv(id, GL_SPOT_DIRECTION, dir);
|
||||
|
||||
glLightf(id, GL_SPOT_EXPONENT, light_obj->get_exponent());
|
||||
glLightf(id, GL_SPOT_EXPONENT, max(min(light_obj->get_exponent(), (PN_stdfloat)128), (PN_stdfloat)0));
|
||||
glLightf(id, GL_SPOT_CUTOFF, lens->get_hfov() * 0.5f);
|
||||
|
||||
const LVecBase3 &att = light_obj->get_attenuation();
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "fogAttrib.h"
|
||||
#include "lightAttrib.h"
|
||||
#include "clipPlaneAttrib.h"
|
||||
#include "ambientLight.h"
|
||||
|
||||
TypeHandle CLP(ShaderContext)::_type_handle;
|
||||
|
||||
|
|
@ -799,8 +800,29 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
|
|||
for (bind._index = 0; bind._index < param_size; ++bind._index) {
|
||||
_shader->_mat_spec.push_back(bind);
|
||||
}
|
||||
_shader->_mat_deps |= bind._dep[0];
|
||||
return;
|
||||
|
||||
} else if (matrix_name.size() > 15 &&
|
||||
matrix_name.substr(0, 12) == "LightSource[" &&
|
||||
sscanf(matrix_name.c_str(), "LightSource[%d].%s", &bind._index, name_buffer) == 2) {
|
||||
// A matrix member of a p3d_LightSource struct.
|
||||
if (strncmp(name_buffer, "shadowMatrix", 127) == 0) {
|
||||
if (inverse) {
|
||||
// Tack inverse back onto the end.
|
||||
strcpy(name_buffer + strlen(name_buffer), "Inverse");
|
||||
}
|
||||
|
||||
bind._func = Shader::SMF_first;
|
||||
bind._part[0] = Shader::SMO_light_source_i_attrib;
|
||||
bind._arg[0] = InternalName::make(name_buffer);
|
||||
bind._part[1] = Shader::SMO_identity;
|
||||
|
||||
} else {
|
||||
GLCAT.error() << "p3d_LightSource struct does not provide a matrix named " << matrix_name << "!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n";
|
||||
return;
|
||||
|
|
@ -813,6 +835,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
|
|||
if (size > 7 && noprefix.substr(0, 7) == "Texture") {
|
||||
Shader::ShaderTexSpec bind;
|
||||
bind._id = arg_id;
|
||||
bind._part = Shader::STO_stage_i;
|
||||
bind._name = 0;
|
||||
|
||||
string tail;
|
||||
|
|
@ -991,6 +1014,78 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
|
|||
_shader->_mat_deps |= bind._dep[0];
|
||||
return;
|
||||
}
|
||||
if (size > 15 && noprefix.substr(0, 12) == "LightSource[") {
|
||||
int index;
|
||||
if (sscanf(noprefix.c_str(), "LightSource[%d].%s", &index, name_buffer) == 2) {
|
||||
// A member of a p3d_LightSource struct.
|
||||
string member_name(name_buffer);
|
||||
if (member_name == "shadowMap") {
|
||||
switch (param_type) {
|
||||
#ifndef OPENGLES
|
||||
case GL_SAMPLER_CUBE_SHADOW:
|
||||
#endif // !OPENGLES
|
||||
case GL_SAMPLER_2D:
|
||||
case GL_SAMPLER_2D_SHADOW:
|
||||
case GL_SAMPLER_CUBE:
|
||||
{
|
||||
Shader::ShaderTexSpec bind;
|
||||
bind._id = arg_id;
|
||||
bind._part = Shader::STO_light_i_shadow_map;
|
||||
bind._name = 0;
|
||||
bind._desired_type = Texture::TT_2d_texture;
|
||||
bind._stage = index;
|
||||
if (get_sampler_texture_type(bind._desired_type, param_type)) {
|
||||
_glgsg->_glUniform1i(p, _shader->_tex_spec.size());
|
||||
_shader->_tex_spec.push_back(bind);
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
GLCAT.error()
|
||||
<< "Invalid type for p3d_LightSource[].shadowMap input!\n";
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// A non-sampler attribute of a numbered light source.
|
||||
Shader::ShaderMatSpec bind;
|
||||
bind._id = arg_id;
|
||||
bind._func = Shader::SMF_first;
|
||||
bind._index = index;
|
||||
bind._part[0] = Shader::SMO_light_source_i_attrib;
|
||||
bind._arg[0] = InternalName::make(member_name);
|
||||
bind._dep[0] = Shader::SSD_general | Shader::SSD_light | Shader::SSD_frame | Shader::SSD_transform;
|
||||
bind._part[1] = Shader::SMO_identity;
|
||||
bind._arg[1] = NULL;
|
||||
bind._dep[1] = Shader::SSD_NONE;
|
||||
|
||||
switch (param_type) {
|
||||
case GL_FLOAT:
|
||||
bind._piece = Shader::SMP_row3x1;
|
||||
break;
|
||||
|
||||
case GL_FLOAT_VEC2:
|
||||
bind._piece = Shader::SMP_row3x2;
|
||||
break;
|
||||
|
||||
case GL_FLOAT_VEC3:
|
||||
bind._piece = Shader::SMP_row3x3;
|
||||
break;
|
||||
|
||||
case GL_FLOAT_VEC4:
|
||||
bind._piece = Shader::SMP_row3;
|
||||
break;
|
||||
|
||||
default:
|
||||
GLCAT.error()
|
||||
<< "p3d_LightSource[]." << member_name << " should be float or vec\n";
|
||||
return;
|
||||
}
|
||||
_shader->_mat_spec.push_back(bind);
|
||||
_shader->_mat_deps |= bind._dep[0] | bind._dep[1];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (noprefix == "TransformTable") {
|
||||
if (param_type != GL_FLOAT_MAT4) {
|
||||
GLCAT.error()
|
||||
|
|
@ -1119,6 +1214,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
|
|||
case GL_SAMPLER_CUBE: {
|
||||
Shader::ShaderTexSpec bind;
|
||||
bind._id = arg_id;
|
||||
bind._part = Shader::STO_named_input;
|
||||
bind._name = InternalName::make(param_name);
|
||||
bind._desired_type = Texture::TT_2d_texture;
|
||||
bind._stage = 0;
|
||||
|
|
@ -1159,9 +1255,19 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
|
|||
bind._id = arg_id;
|
||||
bind._piece = Shader::SMP_whole;
|
||||
bind._func = Shader::SMF_first;
|
||||
bind._part[0] = Shader::SMO_mat_constant_x;
|
||||
bind._arg[0] = InternalName::make(param_name);
|
||||
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame;
|
||||
PT(InternalName) iname = InternalName::make(param_name);
|
||||
if (iname->get_parent() != InternalName::get_root()) {
|
||||
// It might be something like an attribute of a shader
|
||||
// input, like a light parameter. It might also just be
|
||||
// a custom struct parameter. We can't know yet, sadly.
|
||||
bind._part[0] = Shader::SMO_mat_constant_x_attrib;
|
||||
bind._arg[0] = InternalName::make(param_name);
|
||||
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame | Shader::SSD_transform;
|
||||
} else {
|
||||
bind._part[0] = Shader::SMO_mat_constant_x;
|
||||
bind._arg[0] = InternalName::make(param_name);
|
||||
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame;
|
||||
}
|
||||
bind._part[1] = Shader::SMO_identity;
|
||||
bind._arg[1] = NULL;
|
||||
bind._dep[1] = Shader::SSD_NONE;
|
||||
|
|
@ -2260,46 +2366,19 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||
}
|
||||
#endif
|
||||
|
||||
// We get the TextureAttrib directly from the _target_rs, not the
|
||||
// filtered TextureAttrib in _target_texture.
|
||||
const TextureAttrib *texattrib;
|
||||
_glgsg->_target_rs->get_attrib_def(texattrib);
|
||||
//const TextureAttrib *texattrib;
|
||||
//_state_rs->get_attrib_def(TextureAttrib::get_class_slot());
|
||||
|
||||
for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) {
|
||||
Shader::ShaderTexSpec &spec = _shader->_tex_spec[i];
|
||||
const InternalName *id = spec._name;
|
||||
|
||||
Texture *tex = NULL;
|
||||
int view = _glgsg->get_current_tex_view_offset();
|
||||
SamplerState sampler;
|
||||
|
||||
if (id != NULL) {
|
||||
// Named texture input.
|
||||
if (!_glgsg->_target_shader->has_shader_input(id)) {
|
||||
// This used to be legal for some reason, so don't trigger the assert.
|
||||
GLCAT.error()
|
||||
<< "Shader input " << *id << " is not present.\n";
|
||||
continue;
|
||||
}
|
||||
tex = _glgsg->_target_shader->get_shader_input_texture(id, &sampler);
|
||||
|
||||
} else {
|
||||
if (spec._stage >= texattrib->get_num_on_stages()) {
|
||||
// Apply a white texture in order to make it easier to use a shader
|
||||
// that takes a texture on a model that doesn't have a texture applied.
|
||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + i);
|
||||
_glgsg->apply_white_texture();
|
||||
continue;
|
||||
}
|
||||
TextureStage *stage = texattrib->get_on_stage(spec._stage);
|
||||
tex = texattrib->get_on_texture(stage);
|
||||
sampler = texattrib->get_on_sampler(stage);
|
||||
view += stage->get_tex_view_offset();
|
||||
}
|
||||
|
||||
if (tex == NULL) {
|
||||
PT(Texture) tex = _glgsg->fetch_specified_texture(spec, sampler, view);
|
||||
if (tex.is_null()) {
|
||||
// Apply a white texture in order to make it easier to use a shader
|
||||
// that takes a texture on a model that doesn't have a texture applied.
|
||||
_glgsg->_glActiveTexture(GL_TEXTURE0 + i);
|
||||
_glgsg->apply_white_texture();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -478,6 +478,9 @@ cp_dependency(ShaderMatInput inp) {
|
|||
if ((inp == SMO_light_ambient) ||
|
||||
(inp == SMO_light_source_i_attrib)) {
|
||||
dep |= SSD_light;
|
||||
if (inp == SMO_light_source_i_attrib) {
|
||||
dep |= SSD_transform;
|
||||
}
|
||||
}
|
||||
if ((inp == SMO_light_product_i_ambient) ||
|
||||
(inp == SMO_light_product_i_diffuse) ||
|
||||
|
|
@ -976,6 +979,17 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
|
|||
bind._arg[0] = NULL;
|
||||
bind._part[1] = SMO_identity;
|
||||
bind._arg[1] = NULL;
|
||||
} else if (pieces[1] == "ambient") {
|
||||
if (!cp_errchk_parameter_float(p,3,4)) {
|
||||
return false;
|
||||
}
|
||||
bind._id = p._id;
|
||||
bind._piece = SMP_row3;
|
||||
bind._func = SMF_first;
|
||||
bind._part[0] = SMO_light_ambient;
|
||||
bind._arg[0] = NULL;
|
||||
bind._part[1] = SMO_identity;
|
||||
bind._arg[1] = NULL;
|
||||
} else {
|
||||
cp_report_error(p,"Unknown attr parameter.");
|
||||
return false;
|
||||
|
|
@ -1218,6 +1232,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
|
|||
bind._id = p._id;
|
||||
bind._name = 0;
|
||||
bind._stage = atoi(pieces[1].c_str());
|
||||
bind._part = STO_stage_i;
|
||||
switch (p._type) {
|
||||
case SAT_sampler1d: bind._desired_type = Texture::TT_1d_texture; break;
|
||||
case SAT_sampler2d: bind._desired_type = Texture::TT_2d_texture; break;
|
||||
|
|
@ -1239,6 +1254,31 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (pieces[0] == "shadow") {
|
||||
if ((!cp_errchk_parameter_in(p)) ||
|
||||
(!cp_errchk_parameter_uniform(p)) ||
|
||||
(!cp_errchk_parameter_sampler(p)))
|
||||
return false;
|
||||
if (pieces.size() != 2) {
|
||||
cp_report_error(p, "Invalid parameter name");
|
||||
return false;
|
||||
}
|
||||
ShaderTexSpec bind;
|
||||
bind._id = p._id;
|
||||
bind._name = InternalName::make(pieces[1])->append("shadowMap");
|
||||
bind._stage = -1;
|
||||
bind._part = STO_named_input;
|
||||
switch (p._type) {
|
||||
case SAT_sampler2d: bind._desired_type = Texture::TT_2d_texture; break;
|
||||
case SAT_sampler_cube: bind._desired_type = Texture::TT_cube_map; break;
|
||||
default:
|
||||
cp_report_error(p, "Invalid type for a shadow-parameter");
|
||||
return false;
|
||||
}
|
||||
_tex_spec.push_back(bind);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Keywords to fetch texture parameter data.
|
||||
|
||||
if (pieces[0] == "texpad") {
|
||||
|
|
@ -1347,6 +1387,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
|
|||
ShaderTexSpec bind;
|
||||
bind._id = p._id;
|
||||
bind._name = kinputname;
|
||||
bind._part = STO_named_input;
|
||||
bind._desired_type = Texture::TT_1d_texture;
|
||||
_tex_spec.push_back(bind);
|
||||
return true;
|
||||
|
|
@ -1355,6 +1396,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
|
|||
ShaderTexSpec bind;
|
||||
bind._id = p._id;
|
||||
bind._name = kinputname;
|
||||
bind._part = STO_named_input;
|
||||
bind._desired_type = Texture::TT_2d_texture;
|
||||
_tex_spec.push_back(bind);
|
||||
return true;
|
||||
|
|
@ -1363,6 +1405,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
|
|||
ShaderTexSpec bind;
|
||||
bind._id = p._id;
|
||||
bind._name = kinputname;
|
||||
bind._part = STO_named_input;
|
||||
bind._desired_type = Texture::TT_3d_texture;
|
||||
_tex_spec.push_back(bind);
|
||||
return true;
|
||||
|
|
@ -1371,6 +1414,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
|
|||
ShaderTexSpec bind;
|
||||
bind._id = p._id;
|
||||
bind._name = kinputname;
|
||||
bind._part = STO_named_input;
|
||||
bind._desired_type = Texture::TT_2d_texture_array;
|
||||
_tex_spec.push_back(bind);
|
||||
return true;
|
||||
|
|
@ -1379,6 +1423,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
|
|||
ShaderTexSpec bind;
|
||||
bind._id = p._id;
|
||||
bind._name = kinputname;
|
||||
bind._part = STO_named_input;
|
||||
bind._desired_type = Texture::TT_cube_map;
|
||||
_tex_spec.push_back(bind);
|
||||
return true;
|
||||
|
|
@ -1387,6 +1432,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
|
|||
ShaderTexSpec bind;
|
||||
bind._id = p._id;
|
||||
bind._name = kinputname;
|
||||
bind._part = STO_named_input;
|
||||
bind._desired_type = Texture::TT_buffer_texture;
|
||||
_tex_spec.push_back(bind);
|
||||
return true;
|
||||
|
|
@ -1395,6 +1441,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
|
|||
ShaderTexSpec bind;
|
||||
bind._id = p._id;
|
||||
bind._name = kinputname;
|
||||
bind._part = STO_named_input;
|
||||
bind._desired_type = Texture::TT_cube_map_array;
|
||||
_tex_spec.push_back(bind);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -197,6 +197,16 @@ public:
|
|||
SMO_INVALID
|
||||
};
|
||||
|
||||
enum ShaderTexInput {
|
||||
STO_INVALID,
|
||||
|
||||
STO_named_input,
|
||||
STO_named_stage,
|
||||
|
||||
STO_stage_i,
|
||||
STO_light_i_shadow_map,
|
||||
};
|
||||
|
||||
enum ShaderArgClass {
|
||||
SAC_scalar,
|
||||
SAC_vector,
|
||||
|
|
@ -380,6 +390,7 @@ public:
|
|||
struct ShaderTexSpec {
|
||||
ShaderArgId _id;
|
||||
PT(InternalName) _name;
|
||||
ShaderTexInput _part;
|
||||
int _stage;
|
||||
int _desired_type;
|
||||
PT(InternalName) _suffix;
|
||||
|
|
|
|||
|
|
@ -227,10 +227,6 @@ public:
|
|||
virtual void bind_light(Spotlight *light_obj, const NodePath &light,
|
||||
int light_id) { }
|
||||
|
||||
// This function creates a shadow mapping buffer. This is not put in ShaderGenerator
|
||||
// because that would cause circular dependencies.
|
||||
virtual PT(Texture) make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host)=0;
|
||||
|
||||
PUBLISHED:
|
||||
static GraphicsStateGuardianBase *get_default_gsg();
|
||||
static void set_default_gsg(GraphicsStateGuardianBase *default_gsg);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,13 @@ void LightLensNode::
|
|||
clear_shadow_buffers() {
|
||||
ShadowBuffers::iterator it;
|
||||
for(it = _sbuffers.begin(); it != _sbuffers.end(); ++it) {
|
||||
PT(Texture) tex = (*it).second->get_texture();
|
||||
if (tex) {
|
||||
// Clear it to all ones, so that any shaders that might still
|
||||
// be using it will see the shadows being disabled.
|
||||
tex->set_clear_color(LColor(1));
|
||||
tex->clear_image();
|
||||
}
|
||||
(*it).first->remove_window((*it).second);
|
||||
}
|
||||
_sbuffers.clear();
|
||||
|
|
|
|||
|
|
@ -204,21 +204,25 @@ analyze_renderstate(const RenderState *rs) {
|
|||
|
||||
// verify_enforce_attrib_lock();
|
||||
_state = rs;
|
||||
const AuxBitplaneAttrib *aux_bitplane = DCAST(AuxBitplaneAttrib, rs->get_attrib_def(AuxBitplaneAttrib::get_class_slot()));
|
||||
const AuxBitplaneAttrib *aux_bitplane;
|
||||
rs->get_attrib_def(aux_bitplane);
|
||||
int outputs = aux_bitplane->get_outputs();
|
||||
|
||||
// Decide whether or not we need alpha testing or alpha blending.
|
||||
|
||||
const AlphaTestAttrib *alpha_test = DCAST(AlphaTestAttrib, rs->get_attrib_def(AlphaTestAttrib::get_class_slot()));
|
||||
const AlphaTestAttrib *alpha_test;
|
||||
rs->get_attrib_def(alpha_test);
|
||||
if ((alpha_test->get_mode() != RenderAttrib::M_none)&&
|
||||
(alpha_test->get_mode() != RenderAttrib::M_always)) {
|
||||
_have_alpha_test = true;
|
||||
}
|
||||
const ColorBlendAttrib *color_blend = DCAST(ColorBlendAttrib, rs->get_attrib_def(ColorBlendAttrib::get_class_slot()));
|
||||
const ColorBlendAttrib *color_blend;
|
||||
rs->get_attrib_def(color_blend);
|
||||
if (color_blend->get_mode() != ColorBlendAttrib::M_none) {
|
||||
_have_alpha_blend = true;
|
||||
}
|
||||
const TransparencyAttrib *transparency = DCAST(TransparencyAttrib, rs->get_attrib_def(TransparencyAttrib::get_class_slot()));
|
||||
const TransparencyAttrib *transparency;
|
||||
rs->get_attrib_def(transparency);
|
||||
if ((transparency->get_mode() == TransparencyAttrib::M_alpha)||
|
||||
(transparency->get_mode() == TransparencyAttrib::M_dual)) {
|
||||
_have_alpha_blend = true;
|
||||
|
|
@ -257,57 +261,71 @@ analyze_renderstate(const RenderState *rs) {
|
|||
|
||||
// Count number of textures.
|
||||
|
||||
const TextureAttrib *texture = DCAST(TextureAttrib, rs->get_attrib_def(TextureAttrib::get_class_slot()));
|
||||
const TextureAttrib *texture;
|
||||
rs->get_attrib_def(texture);
|
||||
_num_textures = texture->get_num_on_stages();
|
||||
|
||||
// Determine whether or not vertex colors or flat colors are present.
|
||||
|
||||
const ColorAttrib *color = DCAST(ColorAttrib, rs->get_attrib_def(ColorAttrib::get_class_slot()));
|
||||
const ColorAttrib *color;
|
||||
rs->get_attrib_def(color);
|
||||
if (color->get_color_type() == ColorAttrib::T_vertex) {
|
||||
_vertex_colors = true;
|
||||
} else if (color->get_color_type() == ColorAttrib::T_flat) {
|
||||
_flat_colors = true;
|
||||
}
|
||||
|
||||
// Find the material.
|
||||
|
||||
const MaterialAttrib *material;
|
||||
rs->get_attrib_def(material);
|
||||
|
||||
if (!material->is_off()) {
|
||||
_material = material->get_material();
|
||||
} else {
|
||||
_material = Material::get_default();
|
||||
}
|
||||
|
||||
// Break out the lights by type.
|
||||
|
||||
_shadows = false;
|
||||
const LightAttrib *la = DCAST(LightAttrib, rs->get_attrib_def(LightAttrib::get_class_slot()));
|
||||
for (int i=0; i<la->get_num_on_lights(); i++) {
|
||||
const LightAttrib *la;
|
||||
rs->get_attrib_def(la);
|
||||
|
||||
for (int i = 0; i < la->get_num_on_lights(); ++i) {
|
||||
NodePath light = la->get_on_light(i);
|
||||
nassertv(!light.is_empty());
|
||||
PandaNode *light_obj = light.node();
|
||||
nassertv(light_obj != (PandaNode *)NULL);
|
||||
|
||||
if (light_obj->get_type() == AmbientLight::get_class_type()) {
|
||||
_alights_np.push_back(light);
|
||||
_alights.push_back((AmbientLight*)light_obj);
|
||||
}
|
||||
else if (light_obj->get_type() == DirectionalLight::get_class_type()) {
|
||||
_dlights_np.push_back(light);
|
||||
_dlights.push_back((DirectionalLight*)light_obj);
|
||||
if (DCAST(LightLensNode, light_obj)->is_shadow_caster()) {
|
||||
_shadows = true;
|
||||
}
|
||||
}
|
||||
else if (light_obj->get_type() == PointLight::get_class_type()) {
|
||||
_plights_np.push_back(light);
|
||||
_plights.push_back((PointLight*)light_obj);
|
||||
}
|
||||
else if (light_obj->get_type() == Spotlight::get_class_type()) {
|
||||
_slights_np.push_back(light);
|
||||
_slights.push_back((Spotlight*)light_obj);
|
||||
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;
|
||||
}
|
||||
_lighting = true;
|
||||
|
||||
} else if (light_obj->is_of_type(LightLensNode::get_class_type())) {
|
||||
_lights_np.push_back(light);
|
||||
_lights.push_back((LightLensNode *)light_obj);
|
||||
if (DCAST(LightLensNode, light_obj)->is_shadow_caster()) {
|
||||
_shadows = true;
|
||||
}
|
||||
_lighting = true;
|
||||
_need_eye_normal = true;
|
||||
}
|
||||
}
|
||||
|
||||
// See if there is a normal map, height map, gloss map, or glow map.
|
||||
// Also check if anything has TexGen.
|
||||
|
||||
const TexGenAttrib *tex_gen = DCAST(TexGenAttrib, rs->get_attrib_def(TexGenAttrib::get_class_slot()));
|
||||
for (int i=0; i<_num_textures; i++) {
|
||||
const TexGenAttrib *tex_gen;
|
||||
rs->get_attrib_def(tex_gen);
|
||||
for (int i = 0; i < _num_textures; ++i) {
|
||||
TextureStage *stage = texture->get_on_stage(i);
|
||||
TextureStage::Mode mode = stage->get_mode();
|
||||
if ((mode == TextureStage::M_normal)||
|
||||
|
|
@ -352,43 +370,15 @@ analyze_renderstate(const RenderState *rs) {
|
|||
}
|
||||
}
|
||||
|
||||
// Determine whether lighting is needed.
|
||||
|
||||
if (la->get_num_on_lights() > 0) {
|
||||
_lighting = true;
|
||||
_need_eye_normal = true;
|
||||
}
|
||||
|
||||
// Determine whether we should normalize the normals.
|
||||
const RescaleNormalAttrib *rescale;
|
||||
rs->get_attrib_def(rescale);
|
||||
|
||||
_normalize_normals = (rescale->get_mode() != RescaleNormalAttrib::M_none);
|
||||
|
||||
// Find the material.
|
||||
|
||||
const MaterialAttrib *material = DCAST(MaterialAttrib, rs->get_attrib_def(MaterialAttrib::get_class_slot()));
|
||||
|
||||
if (!material->is_off()) {
|
||||
_material = material->get_material();
|
||||
} else {
|
||||
_material = Material::get_default();
|
||||
}
|
||||
|
||||
// Decide which material modes need to be calculated.
|
||||
|
||||
if (_lighting && (_alights.size() > 0)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (_lighting && (_dlights.size() + _plights.size() + _slights.size())) {
|
||||
if (_lighting) {
|
||||
if (_material->has_diffuse()) {
|
||||
LColor d = _material->get_diffuse();
|
||||
if ((d[0]!=0.0)||(d[1]!=0.0)||(d[2]!=0.0)) {
|
||||
|
|
@ -406,7 +396,7 @@ analyze_renderstate(const RenderState *rs) {
|
|||
}
|
||||
}
|
||||
|
||||
if (_lighting && (_dlights.size() + _plights.size() + _slights.size())) {
|
||||
if (_lighting) {
|
||||
if (_material->has_specular()) {
|
||||
LColor s = _material->get_specular();
|
||||
if ((s[0]!=0.0)||(s[1]!=0.0)||(s[2]!=0.0)) {
|
||||
|
|
@ -416,12 +406,7 @@ analyze_renderstate(const RenderState *rs) {
|
|||
_have_specular = true;
|
||||
}
|
||||
|
||||
if (_plights.size() + _slights.size() > 0) {
|
||||
_need_eye_position = true;
|
||||
|
||||
} else if (_have_specular && _material->get_local()) {
|
||||
_need_eye_position = true;
|
||||
}
|
||||
_need_eye_position = true;
|
||||
}
|
||||
|
||||
// Decide whether to separate ambient and diffuse calculations.
|
||||
|
|
@ -442,8 +427,8 @@ analyze_renderstate(const RenderState *rs) {
|
|||
}
|
||||
}
|
||||
|
||||
const LightRampAttrib *light_ramp = DCAST(LightRampAttrib, rs->get_attrib_def(LightRampAttrib::get_class_slot()));
|
||||
if (_lighting &&
|
||||
const LightRampAttrib *light_ramp;
|
||||
if (_lighting && rs->get_attrib(light_ramp) &&
|
||||
(light_ramp->get_mode() != LightRampAttrib::LRT_identity)) {
|
||||
_separate_ambient_diffuse = true;
|
||||
}
|
||||
|
|
@ -463,13 +448,15 @@ analyze_renderstate(const RenderState *rs) {
|
|||
|
||||
// Check for clip planes.
|
||||
|
||||
const ClipPlaneAttrib *clip_plane = DCAST(ClipPlaneAttrib, rs->get_attrib_def(ClipPlaneAttrib::get_class_slot()));
|
||||
const ClipPlaneAttrib *clip_plane;
|
||||
rs->get_attrib_def(clip_plane);
|
||||
_num_clip_planes = clip_plane->get_num_on_planes();
|
||||
if (_num_clip_planes > 0) {
|
||||
_need_world_position = true;
|
||||
}
|
||||
|
||||
const ShaderAttrib *shader_attrib = DCAST(ShaderAttrib, rs->get_attrib_def(ShaderAttrib::get_class_slot()));
|
||||
const ShaderAttrib *shader_attrib;
|
||||
rs->get_attrib_def(shader_attrib);
|
||||
if (shader_attrib->auto_shader()) {
|
||||
_auto_normal_on = shader_attrib->auto_normal_on();
|
||||
_auto_glow_on = shader_attrib->auto_glow_on();
|
||||
|
|
@ -479,8 +466,8 @@ analyze_renderstate(const RenderState *rs) {
|
|||
}
|
||||
|
||||
// Check for fog.
|
||||
const FogAttrib *fog = DCAST(FogAttrib, rs->get_attrib_def(FogAttrib::get_class_slot()));
|
||||
if (!fog->is_off()) {
|
||||
const FogAttrib *fog;
|
||||
if (rs->get_attrib(fog) && !fog->is_off()) {
|
||||
_fog = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -533,14 +520,8 @@ clear_analysis() {
|
|||
_auto_ramp_on = false;
|
||||
_auto_shadow_on = false;
|
||||
|
||||
_alights.clear();
|
||||
_dlights.clear();
|
||||
_plights.clear();
|
||||
_slights.clear();
|
||||
_alights_np.clear();
|
||||
_dlights_np.clear();
|
||||
_plights_np.clear();
|
||||
_slights_np.clear();
|
||||
_lights.clear();
|
||||
_lights_np.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -553,75 +534,14 @@ clear_analysis() {
|
|||
CPT(RenderAttrib) ShaderGenerator::
|
||||
create_shader_attrib(const string &txt) {
|
||||
PT(Shader) shader = Shader::make(txt, Shader::SL_Cg);
|
||||
CPT(RenderAttrib) shattr = ShaderAttrib::make();
|
||||
shattr = DCAST(ShaderAttrib, shattr)->set_shader(shader);
|
||||
if (_lighting) {
|
||||
for (int i=0; i < (int)_alights.size(); i++) {
|
||||
shattr = DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("alight", i), _alights_np[i]);
|
||||
}
|
||||
for (int i=0; i < (int)_dlights.size(); i++) {
|
||||
shattr = DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("dlight", i), _dlights_np[i]);
|
||||
if (_shadows && _dlights[i]->_shadow_caster) {
|
||||
PT(Texture) tex = update_shadow_buffer(_dlights_np[i]);
|
||||
if (tex == NULL) {
|
||||
pgraphnodes_cat.error() << "Failed to create shadow buffer for DirectionalLight '" << _dlights[i]->get_name() << "'!\n";
|
||||
}
|
||||
shattr = DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("dlighttex", i), tex);
|
||||
} else {
|
||||
_dlights[i]->clear_shadow_buffers();
|
||||
}
|
||||
}
|
||||
for (int i=0; i < (int)_plights.size(); i++) {
|
||||
shattr = DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("plight", i), _plights_np[i]);
|
||||
}
|
||||
for (int i=0; i < (int)_slights.size(); i++) {
|
||||
shattr = DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("slight", i), _slights_np[i]);
|
||||
if (_shadows && _slights[i]->_shadow_caster) {
|
||||
PT(Texture) tex = update_shadow_buffer(_slights_np[i]);
|
||||
if (tex == NULL) {
|
||||
pgraphnodes_cat.error() << "Failed to create shadow buffer for Spotlight '" << _slights[i]->get_name() << "'!\n";
|
||||
}
|
||||
shattr = DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("slighttex", i), tex);
|
||||
} else {
|
||||
_slights[i]->clear_shadow_buffers();
|
||||
}
|
||||
}
|
||||
CPT(RenderAttrib) shattr = ShaderAttrib::make(shader);
|
||||
|
||||
for (size_t i = 0; i < _lights.size(); ++i) {
|
||||
shattr = DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("light", i), _lights_np[i]);
|
||||
}
|
||||
return shattr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderGenerator::update_shadow_buffer
|
||||
// Access: Protected, Virtual
|
||||
// Description: Updates the depth buffer of the specified light,
|
||||
// if it is configured to cast shadows.
|
||||
// Only call this function for DirectionalLights
|
||||
// and Spotlights. Returns the depth texture.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(Texture) ShaderGenerator::
|
||||
update_shadow_buffer(NodePath light_np) {
|
||||
// Make sure everything is valid.
|
||||
nassertr(light_np.node()->is_of_type(DirectionalLight::get_class_type()) ||
|
||||
light_np.node()->is_of_type(Spotlight::get_class_type()), NULL);
|
||||
PT(LightLensNode) light = DCAST(LightLensNode, light_np.node());
|
||||
if (light == NULL || !light->_shadow_caster) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// See if we already have a buffer. If not, create one.
|
||||
Texture *tex;
|
||||
if (light->_sbuffers.count(_gsg) == 0) {
|
||||
// Nope, the light doesn't have a buffer for our GSG. Make one.
|
||||
tex = _gsg->make_shadow_buffer(light_np, _host);
|
||||
} else {
|
||||
// There's already a buffer - use that.
|
||||
tex = light->_sbuffers[_gsg]->get_texture();
|
||||
}
|
||||
nassertr(tex != NULL, NULL);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShaderGenerator::synthesize_shader
|
||||
// Access: Published, Virtual
|
||||
|
|
@ -674,8 +594,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|||
string tangent_input;
|
||||
string binormal_input;
|
||||
pmap<const InternalName *, const char *> texcoord_fregs;
|
||||
pvector<const char *> dlightcoord_fregs;
|
||||
pvector<const char *> slightcoord_fregs;
|
||||
pvector<const char *> lightcoord_fregs;
|
||||
const char *world_position_freg = 0;
|
||||
const char *world_normal_freg = 0;
|
||||
const char *eye_position_freg = 0;
|
||||
|
|
@ -790,25 +709,18 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|||
text << "\t uniform float4 mspos_view,\n";
|
||||
text << "\t out float3 l_eyevec,\n";
|
||||
}
|
||||
if (_lighting) {
|
||||
if (_shadows && _auto_shadow_on) {
|
||||
for (int i=0; i < (int)_dlights.size(); i++) {
|
||||
if (_dlights[i]->_shadow_caster) {
|
||||
dlightcoord_fregs.push_back(alloc_freg());
|
||||
text << "\t uniform float4x4 trans_model_to_clip_of_dlight" << i << ",\n";
|
||||
text << "\t out float4 l_dlightcoord" << i << " : " << dlightcoord_fregs[i] << ",\n";
|
||||
if (_lighting && _shadows && _auto_shadow_on) {
|
||||
for (size_t i = 0; i < _lights.size(); ++i) {
|
||||
if (_lights[i]->_shadow_caster) {
|
||||
lightcoord_fregs.push_back(alloc_freg());
|
||||
if (_lights[i]->is_of_type(PointLight::get_class_type())) {
|
||||
text << "\t uniform float4x4 trans_model_to_light" << i << ",\n";
|
||||
} else {
|
||||
dlightcoord_fregs.push_back(NULL);
|
||||
}
|
||||
}
|
||||
for (int i=0; i < (int)_slights.size(); i++) {
|
||||
if (_slights[i]->_shadow_caster) {
|
||||
slightcoord_fregs.push_back(alloc_freg());
|
||||
text << "\t uniform float4x4 trans_model_to_clip_of_slight" << i << ",\n";
|
||||
text << "\t out float4 l_slightcoord" << i << " : " << slightcoord_fregs[i] << ",\n";
|
||||
} else {
|
||||
slightcoord_fregs.push_back(NULL);
|
||||
text << "\t uniform float4x4 trans_model_to_clip_of_light" << i << ",\n";
|
||||
}
|
||||
text << "\t out float4 l_lightcoord" << i << " : " << lightcoord_fregs[i] << ",\n";
|
||||
} else {
|
||||
lightcoord_fregs.push_back(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -904,14 +816,13 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|||
}
|
||||
if (_shadows && _auto_shadow_on) {
|
||||
text << "\t float4x4 biasmat = {0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f};\n";
|
||||
for (int i=0; i < (int)_dlights.size(); i++) {
|
||||
if (_dlights[i]->_shadow_caster) {
|
||||
text << "\t l_dlightcoord" << i << " = mul(biasmat, mul(trans_model_to_clip_of_dlight" << i << ", vtx_position));\n";
|
||||
}
|
||||
}
|
||||
for (int i=0; i < (int)_slights.size(); i++) {
|
||||
if (_slights[i]->_shadow_caster) {
|
||||
text << "\t l_slightcoord" << i << " = mul(biasmat, mul(trans_model_to_clip_of_slight" << i << ", vtx_position));\n";
|
||||
for (size_t i = 0; i < _lights.size(); ++i) {
|
||||
if (_lights[i]->_shadow_caster) {
|
||||
if (_lights[i]->is_of_type(PointLight::get_class_type())) {
|
||||
text << "\t l_lightcoord" << i << " = mul(trans_model_to_light" << i << ", vtx_position);\n";
|
||||
} else {
|
||||
text << "\t l_lightcoord" << i << " = mul(biasmat, mul(trans_model_to_clip_of_light" << i << ", vtx_position));\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -962,33 +873,27 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|||
text << "\t in float3 l_binormal : " << binormal_freg << ",\n";
|
||||
}
|
||||
if (_lighting) {
|
||||
for (int i=0; i < (int)_alights.size(); i++) {
|
||||
text << "\t uniform float4 alight_alight" << i << ",\n";
|
||||
}
|
||||
for (int i=0; i < (int)_dlights.size(); i++) {
|
||||
text << "\t uniform float4x4 dlight_dlight" << i << "_rel_view,\n";
|
||||
if (_shadows && _dlights[i]->_shadow_caster && _auto_shadow_on) {
|
||||
if (_use_shadow_filter) {
|
||||
text << "\t uniform sampler2DShadow k_dlighttex" << i << ",\n";
|
||||
} else {
|
||||
text << "\t uniform sampler2D k_dlighttex" << i << ",\n";
|
||||
}
|
||||
text << "\t in float4 l_dlightcoord" << i << " : " << dlightcoord_fregs[i] << ",\n";
|
||||
for (size_t i = 0; i < _lights.size(); ++i) {
|
||||
if (_lights[i]->is_of_type(DirectionalLight::get_class_type())) {
|
||||
text << "\t uniform float4x4 dlight_light" << i << "_rel_view,\n";
|
||||
|
||||
} else if (_lights[i]->is_of_type(PointLight::get_class_type())) {
|
||||
text << "\t uniform float4x4 plight_light" << i << "_rel_view,\n";
|
||||
|
||||
} else if (_lights[i]->is_of_type(Spotlight::get_class_type())) {
|
||||
text << "\t uniform float4x4 slight_light" << i << "_rel_view,\n";
|
||||
text << "\t uniform float4 satten_light" << i << ",\n";
|
||||
}
|
||||
}
|
||||
for (int i=0; i < (int)_plights.size(); i++) {
|
||||
text << "\t uniform float4x4 plight_plight" << i << "_rel_view,\n";
|
||||
}
|
||||
for (int i=0; i < (int)_slights.size(); i++) {
|
||||
text << "\t uniform float4x4 slight_slight" << i << "_rel_view,\n";
|
||||
text << "\t uniform float4 satten_slight" << i << ",\n";
|
||||
if (_shadows && _slights[i]->_shadow_caster && _auto_shadow_on) {
|
||||
if (_use_shadow_filter) {
|
||||
text << "\t uniform sampler2DShadow k_slighttex" << i << ",\n";
|
||||
|
||||
if (_shadows && _lights[i]->_shadow_caster && _auto_shadow_on) {
|
||||
if (_lights[i]->is_of_type(PointLight::get_class_type())) {
|
||||
text << "\t uniform samplerCUBE shadow_light" << i << ",\n";
|
||||
} else if (_use_shadow_filter) {
|
||||
text << "\t uniform sampler2DShadow shadow_light" << i << ",\n";
|
||||
} else {
|
||||
text << "\t uniform sampler2D k_slighttex" << i << ",\n";
|
||||
text << "\t uniform sampler2D shadow_light" << i << ",\n";
|
||||
}
|
||||
text << "\t in float4 l_slightcoord" << i << " : " << slightcoord_fregs[i] << ",\n";
|
||||
text << "\t in float4 l_lightcoord" << i << " : " << lightcoord_fregs[i] << ",\n";
|
||||
}
|
||||
}
|
||||
if (_need_material_props) {
|
||||
|
|
@ -1017,6 +922,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|||
for (int i=0; i<_num_clip_planes; ++i) {
|
||||
text << "\t uniform float4 clipplane_" << i << ",\n";
|
||||
}
|
||||
text << "\t uniform float4 attr_ambient,\n";
|
||||
text << "\t uniform float4 attr_colorscale\n";
|
||||
text << ") {\n";
|
||||
// Clipping first!
|
||||
|
|
@ -1149,7 +1055,8 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|||
if (_lighting) {
|
||||
text << "\t // Begin view-space light calculations\n";
|
||||
text << "\t float ldist,lattenv,langle;\n";
|
||||
text << "\t float4 lcolor,lspec,lvec,lpoint,latten,ldir,leye,lhalf;\n";
|
||||
text << "\t float4 lcolor,lspec,lpoint,latten,ldir,leye;\n";
|
||||
text << "\t float3 lvec,lhalf;\n";
|
||||
if (_shadows && _auto_shadow_on) {
|
||||
text << "\t float lshad;\n";
|
||||
}
|
||||
|
|
@ -1173,26 +1080,24 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|||
text << "\t float shininess = 50; // no shininess specified, using default\n";
|
||||
}
|
||||
}
|
||||
for (int i=0; i < (int)_alights.size(); i++) {
|
||||
text << "\t // Ambient Light " << i << "\n";
|
||||
text << "\t lcolor = alight_alight" << i << ";\n";
|
||||
if (_separate_ambient_diffuse && _have_ambient) {
|
||||
text << "\t tot_ambient += lcolor;\n";
|
||||
} else if(_have_diffuse) {
|
||||
text << "\t tot_diffuse += lcolor;\n";
|
||||
}
|
||||
if (_separate_ambient_diffuse && _have_ambient) {
|
||||
text << "\t tot_ambient += attr_ambient;\n";
|
||||
} else if(_have_diffuse) {
|
||||
text << "\t tot_diffuse += attr_ambient;\n";
|
||||
}
|
||||
for (int i=0; i < (int)_dlights.size(); i++) {
|
||||
}
|
||||
for (size_t i = 0; i < _lights.size(); ++i) {
|
||||
if (_lights[i]->is_of_type(DirectionalLight::get_class_type())) {
|
||||
text << "\t // Directional Light " << i << "\n";
|
||||
text << "\t lcolor = dlight_dlight" << i << "_rel_view[0];\n";
|
||||
text << "\t lspec = dlight_dlight" << i << "_rel_view[1];\n";
|
||||
text << "\t lvec = dlight_dlight" << i << "_rel_view[2];\n";
|
||||
text << "\t lcolor = dlight_light" << i << "_rel_view[0];\n";
|
||||
text << "\t lspec = dlight_light" << i << "_rel_view[1];\n";
|
||||
text << "\t lvec = dlight_light" << i << "_rel_view[2].xyz;\n";
|
||||
text << "\t lcolor *= saturate(dot(l_eye_normal.xyz, lvec.xyz));\n";
|
||||
if (_shadows && _dlights[i]->_shadow_caster && _auto_shadow_on) {
|
||||
if (_shadows && _lights[i]->_shadow_caster && _auto_shadow_on) {
|
||||
if (_use_shadow_filter) {
|
||||
text << "\t lshad = shadow2DProj(k_dlighttex" << i << ", l_dlightcoord" << i << ").r;\n";
|
||||
text << "\t lshad = shadow2DProj(shadow_light" << i << ", l_lightcoord" << i << ").r;\n";
|
||||
} else {
|
||||
text << "\t lshad = tex2Dproj(k_dlighttex" << i << ", l_dlightcoord" << i << ").r > l_dlightcoord" << i << ".z / l_dlightcoord" << i << ".w;\n";
|
||||
text << "\t lshad = tex2Dproj(shadow_light" << i << ", l_lightcoord" << i << ").r > l_lightcoord" << i << ".z / l_lightcoord" << i << ".w;\n";
|
||||
}
|
||||
text << "\t lcolor *= lshad;\n";
|
||||
text << "\t lspec *= lshad;\n";
|
||||
|
|
@ -1202,59 +1107,64 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|||
}
|
||||
if (_have_specular) {
|
||||
if (_material->get_local()) {
|
||||
text << "\t lhalf = normalize(lvec - normalize(l_eye_position));\n";
|
||||
text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
|
||||
} else {
|
||||
text << "\t lhalf = dlight_dlight" << i << "_rel_view[3];\n";
|
||||
text << "\t lhalf = dlight_light" << i << "_rel_view[3].xyz;\n";
|
||||
}
|
||||
text << "\t lspec *= pow(saturate(dot(l_eye_normal.xyz, lhalf.xyz)), shininess);\n";
|
||||
text << "\t lspec *= pow(saturate(dot(l_eye_normal.xyz, lhalf)), shininess);\n";
|
||||
text << "\t tot_specular += lspec;\n";
|
||||
}
|
||||
}
|
||||
for (int i=0; i < (int)_plights.size(); i++) {
|
||||
} else if (_lights[i]->is_of_type(PointLight::get_class_type())) {
|
||||
text << "\t // Point Light " << i << "\n";
|
||||
text << "\t lcolor = plight_plight" << i << "_rel_view[0];\n";
|
||||
text << "\t lspec = plight_plight" << i << "_rel_view[1];\n";
|
||||
text << "\t lpoint = plight_plight" << i << "_rel_view[2];\n";
|
||||
text << "\t latten = plight_plight" << i << "_rel_view[3];\n";
|
||||
text << "\t lvec = lpoint - l_eye_position;\n";
|
||||
text << "\t ldist = length(float3(lvec));\n";
|
||||
text << "\t lcolor = plight_light" << i << "_rel_view[0];\n";
|
||||
text << "\t lspec = plight_light" << i << "_rel_view[1];\n";
|
||||
text << "\t lpoint = plight_light" << i << "_rel_view[2];\n";
|
||||
text << "\t latten = plight_light" << i << "_rel_view[3];\n";
|
||||
text << "\t lvec = lpoint.xyz - l_eye_position.xyz;\n";
|
||||
text << "\t ldist = length(lvec);\n";
|
||||
text << "\t lvec /= ldist;\n";
|
||||
text << "\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
|
||||
text << "\t lcolor *= lattenv * saturate(dot(l_eye_normal.xyz, lvec.xyz));\n";
|
||||
text << "\t lcolor *= lattenv * saturate(dot(l_eye_normal.xyz, lvec));\n";
|
||||
if (_shadows && _lights[i]->_shadow_caster && _auto_shadow_on) {
|
||||
text << "\t ldist = max(abs(l_lightcoord" << i << ".x), max(abs(l_lightcoord" << i << ".y), abs(l_lightcoord" << i << ".z)));\n";
|
||||
text << "\t ldist = ((latten.w+lpoint.w)/(latten.w-lpoint.w))+((-2*latten.w*lpoint.w)/(ldist * (latten.w-lpoint.w)));\n";
|
||||
text << "\t lshad = texCUBE(shadow_light" << i << ", l_lightcoord" << i << ".xyz).r >= ldist * 0.5 + 0.5;\n";
|
||||
text << "\t lcolor *= lshad;\n";
|
||||
text << "\t lspec *= lshad;\n";
|
||||
}
|
||||
if (_have_diffuse) {
|
||||
text << "\t tot_diffuse += lcolor;\n";
|
||||
}
|
||||
if (_have_specular) {
|
||||
if (_material->get_local()) {
|
||||
text << "\t lhalf = normalize(lvec - normalize(l_eye_position));\n";
|
||||
text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
|
||||
} else {
|
||||
text << "\t lhalf = normalize(lvec - float4(0, 1, 0, 0));\n";
|
||||
text << "\t lhalf = normalize(lvec - float3(0, 1, 0));\n";
|
||||
}
|
||||
text << "\t lspec *= lattenv;\n";
|
||||
text << "\t lspec *= pow(saturate(dot(l_eye_normal.xyz, lhalf.xyz)), shininess);\n";
|
||||
text << "\t lspec *= pow(saturate(dot(l_eye_normal.xyz, lhalf)), shininess);\n";
|
||||
text << "\t tot_specular += lspec;\n";
|
||||
}
|
||||
}
|
||||
for (int i=0; i < (int)_slights.size(); i++) {
|
||||
} else if (_lights[i]->is_of_type(Spotlight::get_class_type())) {
|
||||
text << "\t // Spot Light " << i << "\n";
|
||||
text << "\t lcolor = slight_slight" << i << "_rel_view[0];\n";
|
||||
text << "\t lspec = slight_slight" << i << "_rel_view[1];\n";
|
||||
text << "\t lpoint = slight_slight" << i << "_rel_view[2];\n";
|
||||
text << "\t ldir = slight_slight" << i << "_rel_view[3];\n";
|
||||
text << "\t latten = satten_slight" << i << ";\n";
|
||||
text << "\t lvec = lpoint - l_eye_position;\n";
|
||||
text << "\t ldist = length(float3(lvec));\n";
|
||||
text << "\t lcolor = slight_light" << i << "_rel_view[0];\n";
|
||||
text << "\t lspec = slight_light" << i << "_rel_view[1];\n";
|
||||
text << "\t lpoint = slight_light" << i << "_rel_view[2];\n";
|
||||
text << "\t ldir = slight_light" << i << "_rel_view[3];\n";
|
||||
text << "\t latten = satten_light" << i << ";\n";
|
||||
text << "\t lvec = lpoint.xyz - l_eye_position.xyz;\n";
|
||||
text << "\t ldist = length(lvec);\n";
|
||||
text << "\t lvec /= ldist;\n";
|
||||
text << "\t langle = saturate(dot(ldir.xyz, lvec.xyz));\n";
|
||||
text << "\t langle = saturate(dot(ldir.xyz, lvec));\n";
|
||||
text << "\t lattenv = 1/(latten.x + latten.y*ldist + latten.z*ldist*ldist);\n";
|
||||
text << "\t lattenv *= pow(langle, latten.w);\n";
|
||||
text << "\t if (langle < ldir.w) lattenv = 0;\n";
|
||||
text << "\t lcolor *= lattenv * saturate(dot(l_eye_normal.xyz, lvec.xyz));\n";
|
||||
if (_shadows && _slights[i]->_shadow_caster && _auto_shadow_on) {
|
||||
text << "\t lcolor *= lattenv * saturate(dot(l_eye_normal.xyz, lvec));\n";
|
||||
if (_shadows && _lights[i]->_shadow_caster && _auto_shadow_on) {
|
||||
if (_use_shadow_filter) {
|
||||
text << "\t lshad = shadow2DProj(k_slighttex" << i << ", l_slightcoord" << i << ").r;\n";
|
||||
text << "\t lshad = shadow2DProj(shadow_light" << i << ", l_lightcoord" << i << ").r;\n";
|
||||
} else {
|
||||
text << "\t lshad = tex2Dproj(k_slighttex" << i << ", l_slightcoord" << i << ").r > l_slightcoord" << i << ".z / l_slightcoord" << i << ".w;\n";
|
||||
text << "\t lshad = tex2Dproj(shadow_light" << i << ", l_lightcoord" << i << ").r > l_lightcoord" << i << ".z / l_lightcoord" << i << ".w;\n";
|
||||
}
|
||||
text << "\t lcolor *= lshad;\n";
|
||||
text << "\t lspec *= lshad;\n";
|
||||
|
|
@ -1265,15 +1175,17 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
|
|||
}
|
||||
if (_have_specular) {
|
||||
if (_material->get_local()) {
|
||||
text << "\t lhalf = normalize(lvec - normalize(l_eye_position));\n";
|
||||
text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
|
||||
} else {
|
||||
text << "\t lhalf = normalize(lvec - float4(0,1,0,0));\n";
|
||||
text << "\t lhalf = normalize(lvec - float3(0,1,0));\n";
|
||||
}
|
||||
text << "\t lspec *= lattenv;\n";
|
||||
text << "\t lspec *= pow(saturate(dot(l_eye_normal.xyz, lhalf.xyz)), shininess);\n";
|
||||
text << "\t lspec *= pow(saturate(dot(l_eye_normal.xyz, lhalf)), shininess);\n";
|
||||
text << "\t tot_specular += lspec;\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_lighting) {
|
||||
const LightRampAttrib *light_ramp = DCAST(LightRampAttrib, rs->get_attrib_def(LightRampAttrib::get_class_slot()));
|
||||
if (_auto_ramp_on && _have_diffuse) {
|
||||
switch (light_ramp->get_mode()) {
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ PUBLISHED:
|
|||
|
||||
protected:
|
||||
CPT(RenderAttrib) create_shader_attrib(const string &txt);
|
||||
PT(Texture) update_shadow_buffer(NodePath light_np);
|
||||
static const string combine_mode_as_string(CPT(TextureStage) stage,
|
||||
TextureStage::CombineMode c_mode, bool alpha, short texindex);
|
||||
static const string combine_source_as_string(CPT(TextureStage) stage,
|
||||
|
|
@ -101,14 +100,8 @@ protected:
|
|||
Material *_material;
|
||||
int _num_textures;
|
||||
|
||||
pvector <AmbientLight *> _alights;
|
||||
pvector <DirectionalLight *> _dlights;
|
||||
pvector <PointLight *> _plights;
|
||||
pvector <Spotlight *> _slights;
|
||||
pvector <NodePath> _alights_np;
|
||||
pvector <NodePath> _dlights_np;
|
||||
pvector <NodePath> _plights_np;
|
||||
pvector <NodePath> _slights_np;
|
||||
pvector<LightLensNode *> _lights;
|
||||
pvector<NodePath> _lights_np;
|
||||
|
||||
bool _vertex_colors;
|
||||
bool _flat_colors;
|
||||
|
|
|
|||
Loading…
Reference in New Issue