mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
Added support for shadow maps + shaders
This commit is contained in:
parent
5da0172878
commit
0400248b37
@ -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
|
||||
|
||||
|
||||
|
@ -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);
|
||||
@ -528,7 +528,7 @@ create_texture_card_vdata(int x, int y)
|
||||
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
||||
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
|
||||
GeomVertexWriter normal(vdata, InternalName::get_normal());
|
||||
|
||||
|
||||
vertex.add_data3f(Vertexf::rfu(-1.0f, 0.0f, 1.0f));
|
||||
vertex.add_data3f(Vertexf::rfu(-1.0f, 0.0f, -1.0f));
|
||||
vertex.add_data3f(Vertexf::rfu( 1.0f, 0.0f, 1.0f));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -109,11 +109,13 @@ 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;
|
||||
|
||||
INLINE bool get_color_scale_via_lighting() const;
|
||||
|
||||
|
||||
void set_coordinate_system(CoordinateSystem cs);
|
||||
INLINE CoordinateSystem get_coordinate_system() const;
|
||||
virtual CoordinateSystem get_internal_coordinate_system() const;
|
||||
@ -355,9 +357,11 @@ 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;
|
||||
|
||||
|
||||
public:
|
||||
// Statistics
|
||||
static PStatCollector _total_texusage_pcollector;
|
||||
|
@ -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;
|
||||
@ -2452,7 +2462,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
|
||||
} else {
|
||||
nassertv(tex->get_texture_type() == Texture::TT_2d_texture);
|
||||
}
|
||||
|
||||
|
||||
// Match framebuffer format if necessary.
|
||||
if (tex->get_match_framebuffer_format()) {
|
||||
const FrameBufferProperties &properties = get_properties();
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user