shadows: provide dummy shadow maps for nonexistent/noncasting lights
This commit is contained in:
parent
65a705217e
commit
7755a2e1c7
|
|
@ -1798,6 +1798,13 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There is no such light assigned. Bind a dummy shadow map.
|
||||
PT(Texture) tex = get_dummy_shadow_map((Texture::TextureType)spec._desired_type);
|
||||
if (tex != nullptr) {
|
||||
sampler = tex->get_default_sampler();
|
||||
}
|
||||
return tex;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -3152,9 +3159,14 @@ get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host) {
|
|||
node->is_of_type(Spotlight::get_class_type()), NULL);
|
||||
|
||||
LightLensNode *light = (LightLensNode *)node;
|
||||
if (light == NULL || !light->_shadow_caster) {
|
||||
// TODO: return dummy shadow map (all white).
|
||||
return NULL;
|
||||
if (light == nullptr || !light->_shadow_caster) {
|
||||
// This light does not have a shadow caster. Return a dummy shadow map
|
||||
// that is filled with a depth value of 1.
|
||||
if (node->is_of_type(PointLight::get_class_type())) {
|
||||
return get_dummy_shadow_map(Texture::TT_cube_map);
|
||||
} else {
|
||||
return get_dummy_shadow_map(Texture::TT_2d_texture);
|
||||
}
|
||||
}
|
||||
|
||||
// See if we already have a buffer. If not, create one.
|
||||
|
|
@ -3173,6 +3185,42 @@ get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a dummy shadow map that can be used for a light of the given type
|
||||
* that does not cast shadows.
|
||||
*/
|
||||
PT(Texture) GraphicsStateGuardian::
|
||||
get_dummy_shadow_map(Texture::TextureType texture_type) const {
|
||||
if (texture_type != Texture::TT_cube_map) {
|
||||
static PT(Texture) dummy_2d;
|
||||
if (dummy_2d == nullptr) {
|
||||
dummy_2d = new Texture("dummy-shadow-2d");
|
||||
dummy_2d->setup_2d_texture(1, 1, Texture::T_unsigned_byte, Texture::F_depth_component);
|
||||
dummy_2d->set_clear_color(1);
|
||||
if (get_supports_shadow_filter()) {
|
||||
// If we have the ARB_shadow extension, enable shadow filtering.
|
||||
dummy_2d->set_minfilter(SamplerState::FT_shadow);
|
||||
dummy_2d->set_magfilter(SamplerState::FT_shadow);
|
||||
} else {
|
||||
dummy_2d->set_minfilter(SamplerState::FT_linear);
|
||||
dummy_2d->set_magfilter(SamplerState::FT_linear);
|
||||
}
|
||||
}
|
||||
return dummy_2d;
|
||||
} else {
|
||||
static PT(Texture) dummy_cube;
|
||||
if (dummy_cube == nullptr) {
|
||||
dummy_cube = new Texture("dummy-shadow-cube");
|
||||
dummy_cube->setup_cube_map(1, Texture::T_unsigned_byte, Texture::F_depth_component);
|
||||
dummy_cube->set_clear_color(1);
|
||||
// Note: cube map shadow filtering doesn't seem to work in Cg.
|
||||
dummy_cube->set_minfilter(SamplerState::FT_linear);
|
||||
dummy_cube->set_magfilter(SamplerState::FT_linear);
|
||||
}
|
||||
return dummy_cube;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a depth buffer for shadow mapping. This is a convenience function
|
||||
* for the ShaderGenerator; putting this directly in the ShaderGenerator would
|
||||
|
|
|
|||
|
|
@ -424,6 +424,7 @@ public:
|
|||
static void create_gamma_table (PN_stdfloat gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table);
|
||||
|
||||
PT(Texture) get_shadow_map(const NodePath &light_np, GraphicsOutputBase *host=NULL);
|
||||
PT(Texture) get_dummy_shadow_map(Texture::TextureType texture_type) const;
|
||||
PT(Texture) make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host);
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
|
|
|
|||
|
|
@ -1078,8 +1078,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||
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->set_active_texture_stage(i);
|
||||
_glgsg->apply_white_texture();
|
||||
_glgsg->apply_white_texture(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10906,25 +10906,20 @@ update_standard_texture_bindings() {
|
|||
|
||||
/**
|
||||
* Applies a white dummy texture. This is useful to bind to a texture slot
|
||||
* when a texture is missing.
|
||||
* when a texture is missing. Also binds the default sampler to the unit.
|
||||
*/
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
apply_white_texture() {
|
||||
if (_white_texture != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, _white_texture);
|
||||
return;
|
||||
apply_white_texture(GLuint unit) {
|
||||
set_active_texture_stage(unit);
|
||||
glBindTexture(GL_TEXTURE_2D, get_white_texture());
|
||||
|
||||
// Also apply the default sampler, if there's a chance we'd applied anything
|
||||
// else.
|
||||
#ifndef OPENGLES_1
|
||||
if (_supports_sampler_objects) {
|
||||
_glBindSampler(unit, 0);
|
||||
}
|
||||
|
||||
glGenTextures(1, &_white_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, _white_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
unsigned char data[] = {0xff, 0xff, 0xff, 0xff};
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -10934,7 +10929,16 @@ apply_white_texture() {
|
|||
GLuint CLP(GraphicsStateGuardian)::
|
||||
get_white_texture() {
|
||||
if (_white_texture == 0) {
|
||||
apply_white_texture();
|
||||
glGenTextures(1, &_white_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, _white_texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
unsigned char data[] = {0xff, 0xff, 0xff, 0xff};
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
return _white_texture;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -567,7 +567,7 @@ protected:
|
|||
void update_shader_vertex_format(const GeomVertexFormat *format);
|
||||
#endif
|
||||
|
||||
void apply_white_texture();
|
||||
void apply_white_texture(GLuint unit);
|
||||
GLuint get_white_texture();
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
|
|||
|
|
@ -2617,8 +2617,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||
textures[i] = _glgsg->get_white_texture();
|
||||
samplers[i] = 0;
|
||||
} else {
|
||||
_glgsg->set_active_texture_stage(i);
|
||||
_glgsg->apply_white_texture();
|
||||
_glgsg->apply_white_texture(i);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue