diff --git a/panda/src/crgsg/config_crgsg.cxx b/panda/src/crgsg/config_crgsg.cxx index 6838b43f95..0dbdeaf713 100644 --- a/panda/src/crgsg/config_crgsg.cxx +++ b/panda/src/crgsg/config_crgsg.cxx @@ -65,6 +65,11 @@ bool cr_save_mipmaps = config_crgsg.GetBool("cr-save-mipmaps", false); // variable. bool cr_auto_normalize_lighting = config_crgsg.GetBool("auto-normalize-lighting", false); +// Configure this true to try to implement decals using a +// DepthOffsetAttrib, false to do them with the more reliable 3-pass +// rendering method instead. +bool cr_depth_offset_decals = config_crgsg.GetBool("depth-offset-decals", false); + // Configure this true to indicate the current version of GL fully // supports textures with B, G, R ordering; false if it only supports // R, G, B. false will always work, but true might be faster if the diff --git a/panda/src/crgsg/config_crgsg.h b/panda/src/crgsg/config_crgsg.h index 82f397d564..babef21bae 100644 --- a/panda/src/crgsg/config_crgsg.h +++ b/panda/src/crgsg/config_crgsg.h @@ -32,6 +32,7 @@ extern bool cr_force_mipmaps; extern bool cr_show_mipmaps; extern bool cr_save_mipmaps; extern bool cr_auto_normalize_lighting; +extern bool cr_depth_offset_decals; extern bool cr_supports_bgr; // Ways to implement decals. diff --git a/panda/src/crgsg/crGraphicsStateGuardian.I b/panda/src/crgsg/crGraphicsStateGuardian.I index 6f6452e38f..44da35f91f 100644 --- a/panda/src/crgsg/crGraphicsStateGuardian.I +++ b/panda/src/crgsg/crGraphicsStateGuardian.I @@ -20,18 +20,6 @@ #include -//////////////////////////////////////////////////////////////////// -// Function: CRGraphicsStateGuardian::LightInfo::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE CRGraphicsStateGuardian::LightInfo:: -LightInfo() { - _light = (Light *)NULL; - _enabled = false; - _next_enabled = false; -} - //////////////////////////////////////////////////////////////////// // Function: CRGraphicsStateGuardian::activate // Access: Public @@ -227,24 +215,6 @@ call_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) } } -//////////////////////////////////////////////////////////////////// -// Function: CRGraphicsStateGuardian::call_glLightModelAmbient -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void CRGraphicsStateGuardian:: -call_glLightModelAmbient( const Colorf& color ) -{ - if (_lmodel_ambient != color) { - _lmodel_ambient = color; -#ifdef GSG_VERBOSE - crgsg_cat.debug() - << "crLightModel(GL_LIGHT_MODEL_AMBIENT, " << color << ")" << endl; -#endif - chromium.LightModelfv(GL_LIGHT_MODEL_AMBIENT, color.get_data()); - } -} - //////////////////////////////////////////////////////////////////// // Function: CRGraphicsStateGuardian::call_glLightModelLocal // Access: @@ -733,32 +703,6 @@ enable_point_smooth(bool val) { } } -//////////////////////////////////////////////////////////////////// -// Function: CRGraphicsStateGuardian::enable_lighting -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void CRGraphicsStateGuardian:: -enable_lighting(bool val) { - if (_lighting_enabled != val) { - _lighting_enabled = val; - if (val) { -#ifdef GSG_VERBOSE - crgsg_cat.debug() - << "crEnable(GL_LIGHTING)" << endl; -#endif - chromium.Enable(GL_LIGHTING); - _lighting_enabled_this_frame = true; - } else { -#ifdef GSG_VERBOSE - crgsg_cat.debug() - << "crDisable(GL_LIGHTING)" << endl; -#endif - chromium.Disable(GL_LIGHTING); - } - } -} - //////////////////////////////////////////////////////////////////// // Function: CRGraphicsStateGuardian::enable_dither // Access: @@ -809,35 +753,6 @@ enable_stencil_test(bool val) { } } -//////////////////////////////////////////////////////////////////// -// Function: CRGraphicsStateGuardian::enable_light -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void CRGraphicsStateGuardian::enable_light(int light, bool val) -{ - if ( _light_info[light]._enabled != val ) - { - _light_info[light]._enabled = val; - if ( val ) - { -#ifdef GSG_VERBOSE - crgsg_cat.debug() - << "crEnable(GL_LIGHT" << light << ")" << endl; -#endif - chromium.Enable( get_light_id( light ) ); - } - else - { -#ifdef GSG_VERBOSE - crgsg_cat.debug() - << "crDisable(GL_LIGHT" << light << ")" << endl; -#endif - chromium.Disable( get_light_id( light ) ); - } - } -} - //////////////////////////////////////////////////////////////////// // Function: CRGraphicsStateGuardian::enable_texturing // Access: diff --git a/panda/src/crgsg/crGraphicsStateGuardian.cxx b/panda/src/crgsg/crGraphicsStateGuardian.cxx index b2f8d1f2b4..38bbca717d 100644 --- a/panda/src/crgsg/crGraphicsStateGuardian.cxx +++ b/panda/src/crgsg/crGraphicsStateGuardian.cxx @@ -36,7 +36,6 @@ #include "lens.h" #include "get_rel_pos.h" #include "perspectiveLens.h" -#include "ambientLight.h" #include "directionalLight.h" #include "pointLight.h" #include "spotlight.h" @@ -46,7 +45,6 @@ #include "colorMatrixTransition.h" #include "alphaTransformTransition.h" #include "colorTransition.h" -#include "lightTransition.h" #include "textureTransition.h" #include "renderModeTransition.h" #include "materialTransition.h" @@ -66,6 +64,7 @@ #include "pointShapeTransition.h" #include "polygonOffsetTransition.h" #include "textureAttrib.h" +#include "lightAttrib.h" #include "cullFaceAttrib.h" #include "transparencyAttrib.h" #include "depthTestAttrib.h" @@ -157,7 +156,6 @@ issue_transformed_color_gl(const Geom *geom, Geom::ColorIterator &citerator, //////////////////////////////////////////////////////////////////// CRGraphicsStateGuardian:: CRGraphicsStateGuardian(GraphicsWindow *win) : GraphicsStateGuardian(win) { - _light_info = (LightInfo *)NULL; _clip_plane_enabled = (bool *)NULL; _cur_clip_plane_enabled = (bool *)NULL; @@ -261,8 +259,6 @@ reset() { _line_smooth_enabled = false; _point_smooth_enabled = false; _scissor_enabled = false; - _lighting_enabled = false; - _lighting_enabled_this_frame = false; _normals_enabled = false; _texturing_enabled = false; _multisample_alpha_one_enabled = false; @@ -294,9 +290,8 @@ reset() { // Set up the light id map GLint max_lights; - chromium.GetIntegerv( GL_MAX_LIGHTS, &max_lights ); - _max_lights = max_lights; - _light_info = new LightInfo[_max_lights]; + chromium.GetIntegerv(GL_MAX_LIGHTS, &max_lights); + init_lights(max_lights); // Set up the clip plane id map GLint max_clip_planes; @@ -319,15 +314,16 @@ reset() { PT(DepthTestTransition) dta = new DepthTestTransition; PT(DepthWriteTransition) dwa = new DepthWriteTransition; PT(CullFaceTransition) cfa = new CullFaceTransition; - PT(LightTransition) la = new LightTransition; PT(TextureTransition) ta = new TextureTransition; dta->issue(this); dwa->issue(this); cfa->issue(this); - la->issue(this); ta->issue(this); + Material empty; + apply_material(&empty); + if (cr_cheap_textures) { crgsg_cat.info() << "Setting chromium.Hint() for fastest textures.\n"; @@ -531,7 +527,6 @@ render_frame() { _win->begin_frame(); report_errors(); _decal_level = 0; - _lighting_enabled_this_frame = false; #ifdef DO_PSTATS // For Pstats to track our current texture memory usage, we have to @@ -582,28 +577,6 @@ render_frame() { // Now we're done with the frame processing. Clean up. - if (_lighting_enabled_this_frame) { - - // Let's turn off all the lights we had on, and clear the light - // cache--to force the lights to be reissued next frame, in case - // their parameters or positions have changed between frames. - - for (int i = 0; i < _max_lights; i++) { - enable_light(i, false); - _light_info[i]._light = (Light *)NULL; - } - - // Also force the lighting state to unlit, so that issue_light() - // will be guaranteed to be called next frame even if we have the - // same set of light pointers we had this frame. - clear_attribute(LightTransition::get_class_type()); - - // All this work to undo the lighting state each frame doesn't seem - // ideal--there may be a better way. Maybe if the lights were just - // more aware of whether their parameters or positions have changed - // at all? - } - #ifndef NDEBUG report_errors(); #endif @@ -1020,16 +993,9 @@ draw_sprite(GeomSprite *geom, GeomContext *) { // save the modelview matrix const LMatrix4f &modelview_mat = _transform->get_mat(); - // get the camera information - - // Hmm, this doesn't work any more, since we don't store the camera - // pointer in new scene graph land. Need to find a better way to - // get the current window's aspect ratio. Here's a temporary hack - // for now. - - // float aspect_ratio = - // get_current_camera()->get_lens()->get_aspect_ratio(); - float aspect_ratio = 1.333333; + // We don't need to mess with the aspect ratio, since we are now + // using the default projection matrix, which has the right aspect + // ratio built in. // load up our own matrices chromium.MatrixMode(GL_MODELVIEW); @@ -1089,7 +1055,7 @@ draw_sprite(GeomSprite *geom, GeomContext *) { // y direction if (y_overall) - scaled_height = geom->_y_texel_ratio[0] * half_height * aspect_ratio; + scaled_height = geom->_y_texel_ratio[0] * half_height; else { nassertv(((int)geom->_y_texel_ratio.size() >= geom->get_num_prims())); y_walk = &geom->_y_texel_ratio[0]; @@ -1171,7 +1137,7 @@ draw_sprite(GeomSprite *geom, GeomContext *) { scaled_width = cur_image._x_ratio * half_width; if (y_overall == false) - scaled_height = cur_image._y_ratio * half_height * aspect_ratio; + scaled_height = cur_image._y_ratio * half_height; // if not G_OVERALL, do some trig for this z rotate if (theta_on) { @@ -2087,7 +2053,6 @@ draw_texture(TextureContext *tc, const DisplayRegion *dr) { TextureApplyTransition *taa = new TextureApplyTransition; taa->set_mode(TextureApplyProperty::M_decal); - state.set_transition(new LightTransition); state.set_transition(new ColorMaskTransition); state.set_transition(new RenderModeTransition); state.set_transition(new TexMatrixTransition); @@ -2303,7 +2268,6 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr, prepare_display_region(); NodeTransitions state(na); - state.set_transition(new LightTransition); state.set_transition(new TextureTransition); state.set_transition(new TransformTransition); //state.set_transition(new ColorBlendTransition); @@ -2522,196 +2486,6 @@ apply_fog(qpFog *fog) { report_errors(); } -//////////////////////////////////////////////////////////////////// -// Function: CRGraphicsStateGuardian::apply_light -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void CRGraphicsStateGuardian::apply_light( PointLight* light ) -{ -#if 0 - // The light position will be relative to the current matrix, so - // we have to know what the current matrix is. Find a better - // solution later. -#ifdef GSG_VERBOSE - crgsg_cat.debug() - << "crMatrixMode(GL_MODELVIEW)" << endl; - crgsg_cat.debug() - << "crPushMatrix()" << endl; - crgsg_cat.debug() - << "crLoadIdentity()" << endl; -#endif - chromium.MatrixMode(GL_MODELVIEW); - chromium.PushMatrix(); - - chromium.LoadMatrixf(LMatrix4f::convert_mat(_coordinate_system, CS_yup_right) - .get_data()); - - GLenum id = get_light_id( _cur_light_id ); - Colorf black(0, 0, 0, 1); - chromium.Lightfv(id, GL_AMBIENT, black.get_data()); - chromium.Lightfv(id, GL_DIFFUSE, light->get_color().get_data()); - chromium.Lightfv(id, GL_SPECULAR, light->get_specular().get_data()); - - // Position needs to specify x, y, z, and w - // w == 1 implies non-infinite position - LPoint3f pos = get_rel_pos( light, _current_camera ); - LPoint4f fpos( pos[0], pos[1], pos[2], 1 ); - chromium.Lightfv( id, GL_POSITION, fpos.get_data() ); - - // GL_SPOT_DIRECTION is not significant when cutoff == 180 - - // Exponent == 0 implies uniform light distribution - chromium.Lightf( id, GL_SPOT_EXPONENT, 0 ); - - // Cutoff == 180 means uniform point light source - chromium.Lightf( id, GL_SPOT_CUTOFF, 180.0 ); - - chromium.Lightf( id, GL_CONSTANT_ATTENUATION, - light->get_constant_attenuation() ); - chromium.Lightf( id, GL_LINEAR_ATTENUATION, - light->get_linear_attenuation() ); - chromium.Lightf( id, GL_QUADRATIC_ATTENUATION, - light->get_quadratic_attenuation() ); - - chromium.PopMatrix(); - -#ifdef GSG_VERBOSE - crgsg_cat.debug() - << "crPopMatrix()" << endl; -#endif - report_errors(); -#endif -} - -//////////////////////////////////////////////////////////////////// -// Function: CRGraphicsStateGuardian::apply_light -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void CRGraphicsStateGuardian::apply_light( DirectionalLight* light ) -{ -#if 0 - // The light position will be relative to the current matrix, so - // we have to know what the current matrix is. Find a better - // solution later. -#ifdef GSG_VERBOSE - crgsg_cat.debug() - << "crMatrixMode(GL_MODELVIEW)" << endl; - crgsg_cat.debug() - << "crPushMatrix()" << endl; - crgsg_cat.debug() - << "crLoadIdentity()" << endl; -#endif - chromium.MatrixMode(GL_MODELVIEW); - chromium.PushMatrix(); - chromium.LoadMatrixf(LMatrix4f::convert_mat(_coordinate_system, CS_yup_right) - .get_data()); - - GLenum id = get_light_id( _cur_light_id ); - Colorf black(0, 0, 0, 1); - chromium.Lightfv(id, GL_AMBIENT, black.get_data()); - chromium.Lightfv(id, GL_DIFFUSE, light->get_color().get_data()); - chromium.Lightfv(id, GL_SPECULAR, light->get_specular().get_data()); - - // Position needs to specify x, y, z, and w - // w == 0 implies light is at infinity - LPoint3f dir = get_rel_forward( light, _current_camera, - _coordinate_system ); - LPoint4f pos( -dir[0], -dir[1], -dir[2], 0 ); - chromium.Lightfv( id, GL_POSITION, pos.get_data() ); - - // GL_SPOT_DIRECTION is not significant when cutoff == 180 - // In this case, position x, y, z specifies direction - - // Exponent == 0 implies uniform light distribution - chromium.Lightf( id, GL_SPOT_EXPONENT, 0 ); - - // Cutoff == 180 means uniform point light source - chromium.Lightf( id, GL_SPOT_CUTOFF, 180.0 ); - - // Default attenuation values (only spotlight can modify these) - chromium.Lightf( id, GL_CONSTANT_ATTENUATION, 1 ); - chromium.Lightf( id, GL_LINEAR_ATTENUATION, 0 ); - chromium.Lightf( id, GL_QUADRATIC_ATTENUATION, 0 ); - - chromium.PopMatrix(); -#ifdef GSG_VERBOSE - crgsg_cat.debug() - << "crPopMatrix()" << endl; -#endif - report_errors(); -#endif -} - -//////////////////////////////////////////////////////////////////// -// Function: CRGraphicsStateGuardian::apply_light -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void CRGraphicsStateGuardian::apply_light( Spotlight* light ) -{ -#if 0 - // The light position will be relative to the current matrix, so - // we have to know what the current matrix is. Find a better - // solution later. -#ifdef GSG_VERBOSE - crgsg_cat.debug() - << "crMatrixMode(GL_MODELVIEW)" << endl; - crgsg_cat.debug() - << "crPushMatrix()" << endl; - crgsg_cat.debug() - << "crLoadIdentity()" << endl; -#endif - chromium.MatrixMode(GL_MODELVIEW); - chromium.PushMatrix(); - chromium.LoadMatrixf(LMatrix4f::convert_mat(_coordinate_system, CS_yup_right) - .get_data()); - - GLenum id = get_light_id( _cur_light_id ); - Colorf black(0, 0, 0, 1); - chromium.Lightfv(id, GL_AMBIENT, black.get_data()); - chromium.Lightfv(id, GL_DIFFUSE, light->get_color().get_data()); - chromium.Lightfv(id, GL_SPECULAR, light->get_specular().get_data()); - - // Position needs to specify x, y, z, and w - // w == 1 implies non-infinite position - LPoint3f pos = get_rel_pos( light, _current_camera ); - LPoint4f fpos( pos[0], pos[1], pos[2], 1 ); - chromium.Lightfv( id, GL_POSITION, fpos.get_data() ); - - chromium.Lightfv( id, GL_SPOT_DIRECTION, - get_rel_forward( light, _current_camera, - _coordinate_system ).get_data() ); - chromium.Lightf( id, GL_SPOT_EXPONENT, light->get_exponent() ); - chromium.Lightf( id, GL_SPOT_CUTOFF, - light->get_cutoff_angle() ); - chromium.Lightf( id, GL_CONSTANT_ATTENUATION, - light->get_constant_attenuation() ); - chromium.Lightf( id, GL_LINEAR_ATTENUATION, - light->get_linear_attenuation() ); - chromium.Lightf( id, GL_QUADRATIC_ATTENUATION, - light->get_quadratic_attenuation() ); - - chromium.PopMatrix(); -#ifdef GSG_VERBOSE - crgsg_cat.debug() - << "crPopMatrix()" << endl; -#endif - report_errors(); -#endif -} - -//////////////////////////////////////////////////////////////////// -// Function: CRGraphicsStateGuardian::apply_light -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void CRGraphicsStateGuardian::apply_light( AmbientLight* ) -{ - // Ambient lights are handled as a special case in issue_light(). -} - //////////////////////////////////////////////////////////////////// // Function: CRGraphicsStateGuardian::issue_transform // Access: Public, Virtual @@ -2726,36 +2500,6 @@ issue_transform(const TransformTransition *attrib) { #endif chromium.MatrixMode(GL_MODELVIEW); chromium.LoadMatrixf(attrib->get_matrix().get_data()); - -#ifndef NDEBUG - if (cr_show_transforms) { - bool lighting_was_enabled = _lighting_enabled; - bool texturing_was_enabled = _texturing_enabled; - enable_lighting(false); - enable_texturing(false); - - chromium.Begin(GL_LINES); - - // X axis in red - chromium.Color3f(1.0f, 0.0f, 0.0f); - chromium.Vertex3f(0.0f, 0.0f, 0.0f); - chromium.Vertex3f(1.0f, 0.0f, 0.0f); - - // Y axis in green - chromium.Color3f(0.0f, 1.0f, 0.0f); - chromium.Vertex3f(0.0f, 0.0f, 0.0f); - chromium.Vertex3f(0.0f, 1.0f, 0.0f); - - // Z axis in blue - chromium.Color3f(0.0f, 0.0f, 1.0f); - chromium.Vertex3f(0.0f, 0.0f, 0.0f); - chromium.Vertex3f(0.0f, 0.0f, 1.0f); - - chromium.End(); - enable_lighting(lighting_was_enabled); - enable_texturing(texturing_was_enabled); - } -#endif report_errors(); } @@ -2984,106 +2728,6 @@ issue_render_mode(const RenderModeTransition *attrib) { report_errors(); } -//////////////////////////////////////////////////////////////////// -// Function: CRGraphicsStateGuardian::issue_light -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void CRGraphicsStateGuardian::issue_light(const LightTransition *attrib ) -{ - nassertv(attrib->get_default_dir() != TD_on); - // activate(); - - // Initialize the current ambient light total and newly enabled - // light list - Colorf cur_ambient_light(0.0f, 0.0f, 0.0f, 1.0f); - int i; - for (i = 0; i < _max_lights; i++) { - _light_info[i]._next_enabled = false; - } - - int num_enabled = 0; - LightTransition::const_iterator li; - for (li = attrib->begin(); li != attrib->end(); ++li) { - Light *light = (*li).first; - nassertv(light != (Light *)NULL); - TransitionDirection dir = (*li).second; - - if (dir == TD_on) { - num_enabled++; - enable_lighting(true); - - if (light->get_light_type() == AmbientLight::get_class_type()) { - // Ambient lights don't require specific light ids; simply add - // in the ambient contribution to the current total - cur_ambient_light += light->get_color(); - - } else { - // Check to see if this light has already been bound to an id - _cur_light_id = -1; - for (i = 0; i < _max_lights; i++) { - if (_light_info[i]._light == light) { - // Light has already been bound to an id, we only need - // to enable the light, not apply it - _cur_light_id = -2; - enable_light(i, true); - _light_info[i]._next_enabled = true; - break; - } - } - - // See if there are any unbound light ids - if (_cur_light_id == -1) { - for (i = 0; i < _max_lights; i++) { - if (_light_info[i]._light == (Light *)NULL) { - _light_info[i]._light = light; - _cur_light_id = i; - break; - } - } - } - - // If there were no unbound light ids, see if we can replace - // a currently unused but previously bound id - if (_cur_light_id == -1) { - for (i = 0; i < _max_lights; i++) { - if (attrib->is_off(_light_info[i]._light)) { - _light_info[i]._light = light; - _cur_light_id = i; - break; - } - } - } - - if (_cur_light_id >= 0) { - enable_light(_cur_light_id, true); - _light_info[i]._next_enabled = true; - - // We need to do something different for each type of light - light->apply(this); - } else if (_cur_light_id == -1) { - crgsg_cat.error() - << "issue_light() - failed to bind light to id" << endl; - } - } - } - } - - // Disable all unused lights - for (i = 0; i < _max_lights; i++) { - if (!_light_info[i]._next_enabled) - enable_light(i, false); - } - - // If no lights were enabled, disable lighting - if (num_enabled == 0) { - enable_lighting(false); - } else { - call_glLightModelAmbient(cur_ambient_light); - } - report_errors(); -} - //////////////////////////////////////////////////////////////////// // Function: CRGraphicsStateGuardian::issue_color_blend // Access: Public, Virtual @@ -3508,6 +3152,10 @@ issue_material(const MaterialAttrib *attrib) { const Material *material = attrib->get_material(); if (material != (const Material *)NULL) { apply_material(material); + } else { + // Apply a default material when materials are turned off. + Material empty; + apply_material(&empty); } report_errors(); } @@ -3718,9 +3366,9 @@ issue_depth_offset(const DepthOffsetAttrib *attrib) { int offset = attrib->get_offset(); if (offset != 0) { - GLfloat newfactor = 1.0f; - GLfloat newunits = (GLfloat)offset; - chromium.PolygonOffset(newfactor, newunits); + // The relationship between these two parameters is a little + // unclear and poorly explained in the GL man pages. + chromium.PolygonOffset((GLfloat) -offset, (GLfloat) -offset); enable_polygon_offset(true); } else { @@ -3730,6 +3378,130 @@ issue_depth_offset(const DepthOffsetAttrib *attrib) { report_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: CRGraphicsStateGuardian::bind_light +// Access: Public, Virtual +// Description: Called the first time a particular light has been +// bound to a given id within a frame, this should set +// up the associated hardware light with the light's +// properties. +//////////////////////////////////////////////////////////////////// +void CRGraphicsStateGuardian:: +bind_light(PointLight *light, int light_id) { + GLenum id = get_light_id(light_id); + static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f); + chromium.Lightfv(id, GL_AMBIENT, black.get_data()); + chromium.Lightfv(id, GL_DIFFUSE, light->get_color().get_data()); + chromium.Lightfv(id, GL_SPECULAR, light->get_specular_color().get_data()); + + // Position needs to specify x, y, z, and w + // w == 1 implies non-infinite position + qpNodePath light_np(light); + const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root()); + LPoint3f pos = light->get_point() * light_mat; + + LPoint4f fpos(pos[0], pos[1], pos[2], 1.0f); + chromium.Lightfv(id, GL_POSITION, fpos.get_data()); + + // GL_SPOT_DIRECTION is not significant when cutoff == 180 + + // Exponent == 0 implies uniform light distribution + chromium.Lightf(id, GL_SPOT_EXPONENT, 0.0f); + + // Cutoff == 180 means uniform point light source + chromium.Lightf(id, GL_SPOT_CUTOFF, 180.0f); + + const LVecBase3f &att = light->get_attenuation(); + chromium.Lightf(id, GL_CONSTANT_ATTENUATION, att[0]); + chromium.Lightf(id, GL_LINEAR_ATTENUATION, att[1]); + chromium.Lightf(id, GL_QUADRATIC_ATTENUATION, att[2]); + + report_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: CRGraphicsStateGuardian::bind_light +// Access: Public, Virtual +// Description: Called the first time a particular light has been +// bound to a given id within a frame, this should set +// up the associated hardware light with the light's +// properties. +//////////////////////////////////////////////////////////////////// +void CRGraphicsStateGuardian:: +bind_light(DirectionalLight *light, int light_id) { + GLenum id = get_light_id( light_id ); + static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f); + chromium.Lightfv(id, GL_AMBIENT, black.get_data()); + chromium.Lightfv(id, GL_DIFFUSE, light->get_color().get_data()); + chromium.Lightfv(id, GL_SPECULAR, light->get_specular_color().get_data()); + + // Position needs to specify x, y, z, and w. + // w == 0 implies light is at infinity + qpNodePath light_np(light); + const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root()); + LVector3f dir = light->get_direction() * light_mat; + LPoint4f fdir(-dir[0], -dir[1], -dir[2], 0); + chromium.Lightfv(id, GL_POSITION, fdir.get_data()); + + // GL_SPOT_DIRECTION is not significant when cutoff == 180 + // In this case, position x, y, z specifies direction + + // Exponent == 0 implies uniform light distribution + chromium.Lightf(id, GL_SPOT_EXPONENT, 0.0f); + + // Cutoff == 180 means uniform point light source + chromium.Lightf(id, GL_SPOT_CUTOFF, 180.0f); + + // Default attenuation values (only spotlight and point light can + // modify these) + chromium.Lightf(id, GL_CONSTANT_ATTENUATION, 1.0f); + chromium.Lightf(id, GL_LINEAR_ATTENUATION, 0.0f); + chromium.Lightf(id, GL_QUADRATIC_ATTENUATION, 0.0f); + + report_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: CRGraphicsStateGuardian::bind_light +// Access: Public, Virtual +// Description: Called the first time a particular light has been +// bound to a given id within a frame, this should set +// up the associated hardware light with the light's +// properties. +//////////////////////////////////////////////////////////////////// +void CRGraphicsStateGuardian:: +bind_light(Spotlight *light, int light_id) { + Lens *lens = light->get_lens(); + nassertv(lens != (Lens *)NULL); + + GLenum id = get_light_id(light_id); + static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f); + chromium.Lightfv(id, GL_AMBIENT, black.get_data()); + chromium.Lightfv(id, GL_DIFFUSE, light->get_color().get_data()); + chromium.Lightfv(id, GL_SPECULAR, light->get_specular_color().get_data()); + + // Position needs to specify x, y, z, and w + // w == 1 implies non-infinite position + qpNodePath light_np(light); + const LMatrix4f &light_mat = light_np.get_mat(_scene_setup->get_scene_root()); + LPoint3f pos = lens->get_nodal_point() * light_mat; + LVector3f dir = lens->get_view_vector() * light_mat; + + LPoint4f fpos(pos[0], pos[1], pos[2], 1.0f); + chromium.Lightfv(id, GL_POSITION, fpos.get_data()); + chromium.Lightfv(id, GL_SPOT_DIRECTION, dir.get_data()); + + chromium.Lightf(id, GL_SPOT_EXPONENT, light->get_exponent()); + chromium.Lightf(id, GL_SPOT_CUTOFF, lens->get_hfov()); + + const LVecBase3f &att = light->get_attenuation(); + chromium.Lightf(id, GL_CONSTANT_ATTENUATION, att[0]); + chromium.Lightf(id, GL_LINEAR_ATTENUATION, att[1]); + chromium.Lightf(id, GL_QUADRATIC_ATTENUATION, att[2]); + + report_errors(); +} + //////////////////////////////////////////////////////////////////// // Function: CRGraphicsStateGuardian::wants_normals // Access: Public, Virtual @@ -3895,6 +3667,19 @@ end_decal(GeomNode *base_geom) { report_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: CRGraphicsStateGuardian::depth_offset_decals +// Access: Public, Virtual +// Description: Returns true if this GSG can implement decals using a +// DepthOffsetAttrib, or false if that is unreliable +// and the three-step rendering process should be used +// instead. +//////////////////////////////////////////////////////////////////// +bool CRGraphicsStateGuardian:: +depth_offset_decals() { + return cr_depth_offset_decals; +} + //////////////////////////////////////////////////////////////////// // Function: CRGraphicsStateGuardian::get_internal_coordinate_system // Access: Public, Virtual @@ -4754,6 +4539,93 @@ issue_transformed_color(const Colorf &color) const { chromium.Color4fv(transformed.get_data()); } +//////////////////////////////////////////////////////////////////// +// Function: CRGraphicsStateGuardian::enable_lighting +// Access: Protected, Virtual +// Description: Intended to be overridden by a derived class to +// enable or disable the use of lighting overall. This +// is called by issue_light() according to whether any +// lights are in use or not. +//////////////////////////////////////////////////////////////////// +void CRGraphicsStateGuardian:: +enable_lighting(bool enable) { + if (enable) { + chromium.Enable(GL_LIGHTING); + } else { + chromium.Disable(GL_LIGHTING); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CRGraphicsStateGuardian::set_ambient_light +// Access: Protected, Virtual +// Description: Intended to be overridden by a derived class to +// indicate the color of the ambient light that should +// be in effect. This is called by issue_light() after +// all other lights have been enabled or disabled. +//////////////////////////////////////////////////////////////////// +void CRGraphicsStateGuardian:: +set_ambient_light(const Colorf &color) { + chromium.LightModelfv(GL_LIGHT_MODEL_AMBIENT, color.get_data()); +} + +//////////////////////////////////////////////////////////////////// +// Function: CRGraphicsStateGuardian::enable_light +// Access: Protected, Virtual +// Description: Intended to be overridden by a derived class to +// enable the indicated light id. A specific Light will +// already have been bound to this id via bind_light(). +//////////////////////////////////////////////////////////////////// +void CRGraphicsStateGuardian:: +enable_light(int light_id, bool enable) { + if (enable) { + chromium.Enable(get_light_id(light_id)); + } else { + chromium.Disable(get_light_id(light_id)); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CRGraphicsStateGuardian::begin_bind_lights +// Access: Protected, Virtual +// Description: Called immediately before bind_light() is called, +// this is intended to provide the derived class a hook +// in which to set up some state (like transform) that +// might apply to several lights. +// +// The sequence is: begin_bind_lights() will be called, +// then one or more bind_light() calls, then +// end_bind_lights(). +//////////////////////////////////////////////////////////////////// +void CRGraphicsStateGuardian:: +begin_bind_lights() { + // We need to temporarily load a new matrix so we can define the + // light in a known coordinate system. We pick the transform of the + // root. (Alternatively, we could leave the current transform where + // it is and compute the light position relative to that transform + // instead of relative to the root, by composing with the matrix + // computed by _transform->invert_compose(render_transform). But I + // think loading a completely new matrix is simpler.) + chromium.MatrixMode(GL_MODELVIEW); + chromium.PushMatrix(); + chromium.LoadMatrixf(_scene_setup->get_render_transform()->get_mat().get_data()); +} + +//////////////////////////////////////////////////////////////////// +// Function: CRGraphicsStateGuardian::end_bind_lights +// Access: Protected, Virtual +// Description: Called after before bind_light() has been called one +// or more times (but before any geometry is issued or +// additional state is changed), this is intended to +// clean up any temporary changes to the state that may +// have been made by begin_bind_lights(). +//////////////////////////////////////////////////////////////////// +void CRGraphicsStateGuardian:: +end_bind_lights() { + chromium.MatrixMode(GL_MODELVIEW); + chromium.PopMatrix(); +} + //////////////////////////////////////////////////////////////////// // Function: CRGraphicsStateGuardian::free_pointers // Access: Protected @@ -4762,10 +4634,6 @@ issue_transformed_color(const Colorf &color) const { //////////////////////////////////////////////////////////////////// void CRGraphicsStateGuardian:: free_pointers() { - if (_light_info != (LightInfo *)NULL) { - delete[] _light_info; - _light_info = (LightInfo *)NULL; - } if (_clip_plane_enabled != (bool *)NULL) { delete[] _clip_plane_enabled; _clip_plane_enabled = (bool *)NULL; @@ -5044,10 +4912,6 @@ dump_state(void) dump << "\t\t" << "GL_LINE_SMOOTH " << _line_smooth_enabled << " " << (bool)chromium.IsEnabled(GL_LINE_SMOOTH) << "\n"; dump << "\t\t" << "GL_POINT_SMOOTH " << _point_smooth_enabled << " " << (bool)chromium.IsEnabled(GL_POINT_SMOOTH) << "\n"; dump << "\t\t" << "GL_LIGHTING " << _lighting_enabled << " " << (bool)chromium.IsEnabled(GL_LIGHTING) << "\n"; - for(i = 0; i < _max_lights; i++) - { - dump << "\t\t\t\t" << "GL_LIGHT" << i << " " << _light_info[i]._enabled << " " << (bool)chromium.IsEnabled(GL_LIGHT0+i) << "\n"; - } dump << "\t\t" << "GL_SCISSOR_TEST " << _scissor_enabled << " " << (bool)chromium.IsEnabled(GL_SCISSOR_TEST) << "\n"; dump << "\t\t" << "GL_TEXTURE_2D " << _texturing_enabled << " " << (bool)chromium.IsEnabled(GL_TEXTURE_2D) << "\n"; dump << "\t\t" << "GL_DITHER " << _dither_enabled << " " << (bool)chromium.IsEnabled(GL_DITHER) << "\n"; diff --git a/panda/src/crgsg/crGraphicsStateGuardian.h b/panda/src/crgsg/crGraphicsStateGuardian.h index 3b564da6e1..60fbe73a82 100644 --- a/panda/src/crgsg/crGraphicsStateGuardian.h +++ b/panda/src/crgsg/crGraphicsStateGuardian.h @@ -33,7 +33,6 @@ #include "depthTestProperty.h" #include "stencilProperty.h" #include "fog.h" -#include "pt_Light.h" #include "depthTestAttrib.h" #include "textureApplyAttrib.h" #include "pointerToArray.h" @@ -141,18 +140,12 @@ public: virtual void apply_fog(Fog *fog); void apply_fog(qpFog *fog); - virtual void apply_light(PointLight* light); - virtual void apply_light(DirectionalLight* light); - virtual void apply_light(Spotlight* light); - virtual void apply_light(AmbientLight* light); - virtual void issue_transform(const TransformTransition *attrib); virtual void issue_color_transform(const ColorMatrixTransition *attrib); virtual void issue_alpha_transform(const AlphaTransformTransition *attrib); virtual void issue_tex_matrix(const TexMatrixTransition *attrib); virtual void issue_color(const ColorTransition *attrib); virtual void issue_texture(const TextureTransition *attrib); - virtual void issue_light(const LightTransition *attrib); virtual void issue_material(const MaterialTransition *attrib); virtual void issue_render_mode(const RenderModeTransition *attrib); virtual void issue_color_blend(const ColorBlendTransition *attrib); @@ -171,11 +164,8 @@ public: virtual void issue_polygon_offset(const PolygonOffsetTransition *attrib); virtual void issue_transform(const TransformState *transform); - // virtual void issue_color_scale(const ColorScaleAttrib *attrib); - // virtual void issue_color(const ColorAttrib *attrib); virtual void issue_tex_matrix(const TexMatrixAttrib *attrib); virtual void issue_texture(const TextureAttrib *attrib); - // virtual void issue_light(const LightAttrib *attrib); virtual void issue_material(const MaterialAttrib *attrib); virtual void issue_render_mode(const RenderModeAttrib *attrib); virtual void issue_texture_apply(const TextureApplyAttrib *attrib); @@ -191,12 +181,18 @@ public: // virtual void issue_stencil(const StencilAttrib *attrib); // virtual void issue_clip_plane(const ClipPlaneAttrib *attrib); + virtual void bind_light(PointLight *light, int light_id); + virtual void bind_light(DirectionalLight *light, int light_id); + virtual void bind_light(Spotlight *light, int light_id); + virtual bool wants_normals(void) const; virtual bool wants_texcoords(void) const; virtual void begin_decal(GeomNode *base_geom, AllTransitionsWrapper &attrib); virtual void end_decal(GeomNode *base_geom); + virtual bool depth_offset_decals(); + virtual CoordinateSystem get_internal_coordinate_system() const; virtual float compute_distance_to(const LPoint3f &point) const; @@ -214,6 +210,12 @@ public: void issue_transformed_color(const Colorf &color) const; protected: + virtual void enable_lighting(bool enable); + virtual void set_ambient_light(const Colorf &color); + virtual void enable_light(int light_id, bool enable); + virtual void begin_bind_lights(); + virtual void end_bind_lights(); + void free_pointers(); virtual PT(SavedFrameBuffer) save_frame_buffer(const RenderBuffer &buffer, CPT(DisplayRegion) dr); @@ -234,7 +236,6 @@ protected: INLINE void call_glCullFace(GLenum mode); INLINE void call_glScissor(GLint x, GLint y, GLsizei width, GLsizei height); INLINE void call_glViewport(GLint x, GLint y, GLsizei width, GLsizei height); - INLINE void call_glLightModelAmbient(const Colorf& color); INLINE void call_glLightModelLocal(GLboolean local); INLINE void call_glLightModelTwoSide(GLboolean twoside); INLINE void call_glStencilFunc(GLenum func,GLint refval,GLuint mask); @@ -256,8 +257,6 @@ protected: INLINE void enable_multisample(bool val); INLINE void enable_line_smooth(bool val); INLINE void enable_point_smooth(bool val); - INLINE void enable_lighting(bool val); - INLINE void enable_light(int light, bool val); INLINE void enable_texturing(bool val); INLINE void enable_scissor(bool val); INLINE void enable_dither(bool val); @@ -321,7 +320,6 @@ protected: GLsizei _viewport_height; GLboolean _lmodel_local; GLboolean _lmodel_twoside; - Colorf _lmodel_ambient; Colorf _material_ambient; Colorf _material_diffuse; Colorf _material_specular; @@ -350,8 +348,6 @@ protected: bool _line_smooth_enabled; bool _point_smooth_enabled; bool _scissor_enabled; - bool _lighting_enabled; - bool _lighting_enabled_this_frame; bool _texturing_enabled; bool _dither_enabled; bool _stencil_test_enabled; @@ -365,16 +361,6 @@ protected: bool _polygon_offset_enabled; int _decal_level; - class LightInfo { - public: - INLINE LightInfo(); - PT_Light _light; - bool _enabled; - bool _next_enabled; - }; - - int _max_lights; - LightInfo *_light_info; // LightInfo[_max_lights] int _cur_light_id; LMatrix4f _current_projection_mat;