Added support for shadow maps + shaders

This commit is contained in:
Josh Yelon 2005-11-01 04:30:22 +00:00
parent 5da0172878
commit 0400248b37
10 changed files with 165 additions and 19 deletions

View File

@ -64,7 +64,7 @@ class ShowBase(DirectObject.DirectObject):
self.sfxActive = self.config.GetBool('audio-sfx-active', 1)
self.musicActive = self.config.GetBool('audio-music-active', 1)
self.wantFog = self.config.GetBool('want-fog', 1)
self.wantRender2dp = self.config.GetBool('want-render2dp', 0)
self.wantRender2dp = self.config.GetBool('want-render2dp', 1)
self.screenshotExtension = self.config.GetString('screenshot-extension', 'jpg')
self.musicManager = None
@ -117,12 +117,14 @@ class ShowBase(DirectObject.DirectObject):
self.drive = None
self.trackball = None
self.cam = None
self.camList = []
self.camNode = None
self.camLens = None
self.cam2d = None
self.cam2dp = None
self.camera = None
self.camera2d = None
self.camera2dp = None
self.camList = []
self.camNode = None
self.camLens = None
self.camFrustumVis = None
# This is used for syncing multiple PCs in a distributed cluster
@ -458,6 +460,10 @@ class ShowBase(DirectObject.DirectObject):
# preserve it for reopening the window.
if cam == self.cam:
self.cam = None
if cam == self.cam2d:
self.cam2d = None
if cam == self.cam2dp:
self.cam2dp = None
cam.removeNode()
# Now we can actually close the window.
@ -813,6 +819,9 @@ class ShowBase(DirectObject.DirectObject):
camera2d = self.camera2d.attachNewNode(cam2dNode)
dr.setCamera(camera2d)
if self.cam2d == None:
self.cam2d = camera2d
return camera2d
def makeCamera2dp(self, win, sort = 20,
@ -847,6 +856,9 @@ class ShowBase(DirectObject.DirectObject):
camera2dp = self.camera2dp.attachNewNode(cam2dNode)
dr.setCamera(camera2dp)
if self.cam2dp == None:
self.cam2dp = camera2dp
return camera2dp

View File

@ -520,7 +520,7 @@ create_texture_card_vdata(int x, int y)
float xhi = (x * 1.0f) / xru;
float yhi = (y * 1.0f) / yru;
CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3n3cpt2();
CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3n3t2();
PT(GeomVertexData) vdata = new GeomVertexData
("card", format, Geom::UH_static);

View File

@ -470,6 +470,28 @@ get_supports_render_texture() const {
return _supports_render_texture;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supports_depth_texture
// Access: Published
// Description: Returns true if this particular GSG supports
// textures whose format is F_depth_component.
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsStateGuardian::
get_supports_depth_texture() const {
return _supports_depth_texture;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_supports_shadow_filter
// Access: Published
// Description: Returns true if this particular GSG supports
// the filter mode FT_shadow for depth textures.
////////////////////////////////////////////////////////////////////
INLINE bool GraphicsStateGuardian::
get_supports_shadow_filter() const {
return _supports_shadow_filter;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_color_scale_via_lighting
// Access: Published

View File

@ -145,7 +145,8 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
_supports_multisample = false;
_supports_generate_mipmap = false;
_supports_render_texture = false;
_supports_depth_texture = false;
_supports_shadow_filter = false;
_supported_geom_rendering = 0;
// If this is true, then we can apply a color and/or color scale by

View File

@ -109,6 +109,8 @@ PUBLISHED:
virtual bool get_supports_multisample() const;
INLINE bool get_supports_generate_mipmap() const;
INLINE bool get_supports_render_texture() const;
INLINE bool get_supports_depth_texture() const;
INLINE bool get_supports_shadow_filter() const;
virtual int get_supported_geom_rendering() const;
@ -355,6 +357,8 @@ protected:
bool _supports_multisample;
bool _supports_generate_mipmap;
bool _supports_render_texture;
bool _supports_depth_texture;
bool _supports_shadow_filter;
int _supported_geom_rendering;
bool _color_scale_via_lighting;

View File

@ -518,6 +518,16 @@ reset() {
_glClientActiveTexture = null_glActiveTexture;
}
if (has_extension("GL_ARB_depth_texture")) {
_supports_depth_texture = true;
}
if (_supports_depth_texture &&
has_extension("GL_ARB_shadow") &&
has_extension("GL_ARB_fragment_program_shadow")) {
_supports_shadow_filter = true;
}
_supports_texture_combine =
has_extension("GL_ARB_texture_env_combine") || is_at_least_version(1, 3);
_supports_texture_saved_result =
@ -2041,7 +2051,7 @@ release_geom(GeomContext *gc) {
////////////////////////////////////////////////////////////////////
ShaderContext *CLP(GraphicsStateGuardian)::
prepare_shader(ShaderExpansion *se) {
CLP(ShaderContext) *result = new CLP(ShaderContext)(se);
CLP(ShaderContext) *result = new CLP(ShaderContext)(se, this);
if (result->valid()) return result;
delete result;
return NULL;
@ -3901,6 +3911,8 @@ get_texture_filter_type(Texture::FilterType ft, bool ignore_mipmaps) {
case Texture::FT_nearest_mipmap_linear:
case Texture::FT_linear_mipmap_linear:
return GL_LINEAR;
case Texture::FT_shadow:
return GL_LINEAR;
case Texture::FT_invalid:
break;
}
@ -3919,6 +3931,8 @@ get_texture_filter_type(Texture::FilterType ft, bool ignore_mipmaps) {
return GL_NEAREST_MIPMAP_LINEAR;
case Texture::FT_linear_mipmap_linear:
return GL_LINEAR_MIPMAP_LINEAR;
case Texture::FT_shadow:
return GL_LINEAR;
case Texture::FT_invalid:
break;
}
@ -5044,7 +5058,7 @@ update_standard_texture_bindings()
GLP(MatrixMode)(GL_TEXTURE);
if (_target._tex_matrix->has_stage(stage)) {
GLP(LoadMatrixf)(_state._tex_matrix->get_mat(stage).get_data());
GLP(LoadMatrixf)(_target._tex_matrix->get_mat(stage).get_data());
} else {
GLP(LoadIdentity)();
}
@ -5444,6 +5458,19 @@ specify_texture(Texture *tex) {
GLP(TexParameteri)(target, GL_TEXTURE_MAG_FILTER,
get_texture_filter_type(magfilter, true));
if (_supports_shadow_filter) {
if (tex->get_format() == Texture::F_depth_component) {
if ((tex->get_magfilter() == Texture::FT_shadow) ||
(tex->get_minfilter() == Texture::FT_shadow)) {
GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GEQUAL);
} else {
GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
GLP(TexParameteri)(target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
}
}
}
report_my_gl_errors();
}

View File

@ -24,7 +24,7 @@ TypeHandle CLP(ShaderContext)::_type_handle;
// Description: xyz
////////////////////////////////////////////////////////////////////
CLP(ShaderContext)::
CLP(ShaderContext)(ShaderExpansion *s) : ShaderContext(s) {
CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg) : ShaderContext(s) {
string header;
s->parse_init();
s->parse_line(header, true, true);
@ -73,7 +73,7 @@ CLP(ShaderContext)(ShaderExpansion *s) : ShaderContext(s) {
}
// Compile the program.
try_cg_compile(s);
try_cg_compile(s, gsg);
cerr << _cg_errors;
return;
}
@ -155,7 +155,7 @@ parse_cg_profile(const string &id, bool vertex)
////////////////////////////////////////////////////////////////////
#ifdef HAVE_CGGL
bool CLP(ShaderContext)::
try_cg_compile(ShaderExpansion *s)
try_cg_compile(ShaderExpansion *s, GSG *gsg)
{
_cg_errors = "";
@ -176,6 +176,78 @@ try_cg_compile(ShaderExpansion *s)
return false;
}
// The following code is present to work around a bug in the Cg compiler.
// It does not generate correct code for shadow map lookups when using arbfp1.
// This is a particularly onerous limitation, given that arbfp1 is the only
// Cg target that works on radeons. I suspect this is an intentional
// omission on nvidia's part. The following code fetches the output listing,
// detects the error, repairs the code, and resumbits the repaired code to Cg.
if ((_cg_profile[1] == CG_PROFILE_ARBFP1) && (gsg->_supports_shadow_filter)) {
bool shadowunit[32];
bool anyshadow = false;
memset(shadowunit, 0, sizeof(shadowunit));
vector_string lines;
tokenize(cgGetProgramString(_cg_program[1], CG_COMPILED_PROGRAM), lines, "\n");
// figure out which texture units contain shadow maps.
for (int lineno=0; lineno<(int)lines.size(); lineno++) {
if (lines[lineno].compare(0,21,"#var sampler2DSHADOW ")) {
continue;
}
vector_string fields;
tokenize(lines[lineno], fields, ":");
if (fields.size()!=5) {
continue;
}
vector_string words;
tokenize(trim(fields[2]), words, " ");
if (words.size()!=2) {
continue;
}
int unit = atoi(words[1].c_str());
if ((unit < 0)||(unit >= 32)) {
continue;
}
anyshadow = true;
shadowunit[unit] = true;
}
// modify all TEX statements that use the relevant texture units.
if (anyshadow) {
for (int lineno=0; lineno<(int)lines.size(); lineno++) {
if (lines[lineno].compare(0,4,"TEX ")) {
continue;
}
vector_string fields;
tokenize(lines[lineno], fields, ",");
if ((fields.size()!=4)||(trim(fields[3]) != "2D;")) {
continue;
}
vector_string texunitf;
tokenize(trim(fields[2]), texunitf, "[]");
if ((texunitf.size()!=3)||(texunitf[0] != "texture")||(texunitf[2]!="")) {
continue;
}
int unit = atoi(texunitf[1].c_str());
if ((unit < 0) || (unit >= 32) || (shadowunit[unit]==false)) {
continue;
}
lines[lineno] = fields[0]+","+fields[1]+","+fields[2]+", SHADOW2D;";
}
string result = "!!ARBfp1.0\nOPTION ARB_fragment_program_shadow;\n";
for (int lineno=1; lineno<(int)lines.size(); lineno++) {
result += (lines[lineno] + "\n");
}
cgDestroyProgram(_cg_program[1]);
_cg_program[1] =
cgCreateProgram(_cg_context, CG_OBJECT, result.c_str(),
_cg_profile[1], "fshader", (const char**)NULL);
print_cg_compile_errors(s->get_name(), _cg_context);
if (_cg_program[SHADER_type_frag]==0) {
release_resources();
return false;
}
}
}
bool success = true;
CGparameter parameter;
for (int progindex=0; progindex<2; progindex++) {

View File

@ -34,10 +34,11 @@ class CLP(GraphicsStateGuardian);
class EXPCL_GL CLP(ShaderContext): public ShaderContext {
public:
CLP(ShaderContext)(ShaderExpansion *s);
~CLP(ShaderContext)();
typedef CLP(GraphicsStateGuardian) GSG;
CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg);
~CLP(ShaderContext)();
INLINE bool valid(void);
void bind(GSG *gsg);
void unbind();
@ -116,7 +117,7 @@ private:
vector <ShaderTransBind> _cg_parameter_bind;
vector <ShaderVarying> _cg_varying;
bool try_cg_compile(ShaderExpansion *s);
bool try_cg_compile(ShaderExpansion *s, GSG *gsg);
void bind_cg_transform(const ShaderTransBind &stb,
CLP(GraphicsStateGuardian) *gsg);
void suggest_cg_profile(const string &vpro, const string &fpro);

View File

@ -1367,7 +1367,8 @@ string_filter_type(const string &string) {
return FT_linear_mipmap_linear;
} else if (cmp_nocase_uh(string, "mipmap") == 0) {
return FT_linear_mipmap_linear;
} else if (cmp_nocase_uh(string, "shadow") == 0) {
return FT_shadow;
} else {
return FT_invalid;
}
@ -1923,6 +1924,9 @@ operator << (ostream &out, Texture::FilterType ft) {
case Texture::FT_linear_mipmap_linear:
return out << "linear_mipmap_linear";
case Texture::FT_shadow:
return out << "shadow";
case Texture::FT_invalid:
return out << "invalid";
}

View File

@ -127,6 +127,9 @@ PUBLISHED:
// two mipmap levels, and linearly blend the results.
FT_linear_mipmap_linear,
// The OpenGL ARB_shadow extension can be thought of as a kind of filtering.
FT_shadow,
// Returned by string_filter_type() for an invalid match.
FT_invalid
};