optimize light state a bit

This commit is contained in:
David Rose 2008-11-12 22:20:21 +00:00
parent c69c8680e8
commit 7b7b973a7a
6 changed files with 104 additions and 58 deletions

View File

@ -798,6 +798,8 @@ begin_scene() {
void DXGraphicsStateGuardian8::
end_scene() {
GraphicsStateGuardian::end_scene();
_dlights.clear();
HRESULT hr = _d3d_device->EndScene();
if (FAILED(hr)) {
@ -2528,35 +2530,41 @@ bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian8::
bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
// Get the light in "world coordinates" (actually, view
// coordinates). This means the light in the coordinate space of
// the camera, converted to DX's coordinate system.
CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path());
const LMatrix4f &light_mat = transform->get_mat();
LMatrix4f rel_mat = light_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
LVector3f dir = light_obj->get_direction() * rel_mat;
static PStatCollector _draw_set_state_light_bind_directional_pcollector("Draw:Set State:Light:Bind:Directional");
PStatTimer timer(_draw_set_state_light_bind_directional_pcollector);
D3DCOLORVALUE black;
black.r = black.g = black.b = black.a = 0.0f;
pair<DirectionalLights::iterator, bool> lookup = _dlights.insert(DirectionalLights::value_type(light, D3DLIGHT8()));
D3DLIGHT8 &fdata = (*lookup.first).second;
if (lookup.second) {
// Get the light in "world coordinates" (actually, view
// coordinates). This means the light in the coordinate space of
// the camera, converted to DX's coordinate system.
CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path());
const LMatrix4f &light_mat = transform->get_mat();
LMatrix4f rel_mat = light_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
LVector3f dir = light_obj->get_direction() * rel_mat;
D3DCOLORVALUE black;
black.r = black.g = black.b = black.a = 0.0f;
ZeroMemory(&fdata, sizeof(D3DLIGHT8));
fdata.Type = D3DLIGHT_DIRECTIONAL;
fdata.Diffuse = get_light_color(light_obj);
fdata.Ambient = black ;
fdata.Specular = *(D3DCOLORVALUE *)(light_obj->get_specular_color().get_data());
fdata.Direction = *(D3DVECTOR *)dir.get_data();
fdata.Range = __D3DLIGHT_RANGE_MAX;
fdata.Falloff = 1.0f;
fdata.Attenuation0 = 1.0f; // constant
fdata.Attenuation1 = 0.0f; // linear
fdata.Attenuation2 = 0.0f; // quadratic
}
D3DLIGHT8 alight;
ZeroMemory(&alight, sizeof(D3DLIGHT8));
alight.Type = D3DLIGHT_DIRECTIONAL;
alight.Diffuse = get_light_color(light_obj);
alight.Ambient = black ;
alight.Specular = *(D3DCOLORVALUE *)(light_obj->get_specular_color().get_data());
alight.Direction = *(D3DVECTOR *)dir.get_data();
alight.Range = __D3DLIGHT_RANGE_MAX;
alight.Falloff = 1.0f;
alight.Attenuation0 = 1.0f; // constant
alight.Attenuation1 = 0.0f; // linear
alight.Attenuation2 = 0.0f; // quadratic
HRESULT hr = _d3d_device->SetLight(light_id, &alight);
HRESULT hr = _d3d_device->SetLight(light_id, &fdata);
if (FAILED(hr)) {
wdxdisplay8_cat.warning()
<< "Could not set light properties for " << light

View File

@ -252,6 +252,12 @@ protected:
const DXIndexBufferContext8 *_active_ibuffer;
int _num_active_texture_stages;
// Cache the data necessary to bind each particular light each
// frame, so if we bind a given light multiple times, we only have
// to compute its data once.
typedef pmap<NodePath, D3DLIGHT8> DirectionalLights;
DirectionalLights _dlights;
bool _overlay_windows_supported;
bool _tex_stats_retrieval_impossible;

View File

@ -1146,6 +1146,8 @@ end_scene() {
_current_shader_context = (CLP(ShaderContext) *)NULL;
}
_dlights.clear();
/*
HRESULT hr = _d3d_device->EndScene();
@ -3382,35 +3384,41 @@ bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
////////////////////////////////////////////////////////////////////
void DXGraphicsStateGuardian9::
bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
// Get the light in "world coordinates" (actually, view
// coordinates). This means the light in the coordinate space of
// the camera, converted to DX's coordinate system.
CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path());
const LMatrix4f &light_mat = transform->get_mat();
LMatrix4f rel_mat = light_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
LVector3f dir = light_obj->get_direction() * rel_mat;
static PStatCollector _draw_set_state_light_bind_directional_pcollector("Draw:Set State:Light:Bind:Directional");
PStatTimer timer(_draw_set_state_light_bind_directional_pcollector);
D3DCOLORVALUE black;
black.r = black.g = black.b = black.a = 0.0f;
pair<DirectionalLights::iterator, bool> lookup = _dlights.insert(DirectionalLights::value_type(light, D3DLIGHT9()));
D3DLIGHT9 &fdata = (*lookup.first).second;
if (lookup.second) {
// Get the light in "world coordinates" (actually, view
// coordinates). This means the light in the coordinate space of
// the camera, converted to DX's coordinate system.
CPT(TransformState) transform = light.get_transform(_scene_setup->get_camera_path());
const LMatrix4f &light_mat = transform->get_mat();
LMatrix4f rel_mat = light_mat * LMatrix4f::convert_mat(CS_yup_left, CS_default);
LVector3f dir = light_obj->get_direction() * rel_mat;
D3DCOLORVALUE black;
black.r = black.g = black.b = black.a = 0.0f;
ZeroMemory(&fdata, sizeof(D3DLIGHT9));
fdata.Type = D3DLIGHT_DIRECTIONAL;
fdata.Diffuse = get_light_color(light_obj);
fdata.Ambient = black ;
fdata.Specular = *(D3DCOLORVALUE *)(light_obj->get_specular_color().get_data());
fdata.Direction = *(D3DVECTOR *)dir.get_data();
fdata.Range = __D3DLIGHT_RANGE_MAX;
fdata.Falloff = 1.0f;
fdata.Attenuation0 = 1.0f; // constant
fdata.Attenuation1 = 0.0f; // linear
fdata.Attenuation2 = 0.0f; // quadratic
}
D3DLIGHT9 alight;
ZeroMemory(&alight, sizeof(D3DLIGHT9));
alight.Type = D3DLIGHT_DIRECTIONAL;
alight.Diffuse = get_light_color(light_obj);
alight.Ambient = black ;
alight.Specular = *(D3DCOLORVALUE *)(light_obj->get_specular_color().get_data());
alight.Direction = *(D3DVECTOR *)dir.get_data();
alight.Range = __D3DLIGHT_RANGE_MAX;
alight.Falloff = 1.0f;
alight.Attenuation0 = 1.0f; // constant
alight.Attenuation1 = 0.0f; // linear
alight.Attenuation2 = 0.0f; // quadratic
HRESULT hr = _d3d_device->SetLight(light_id, &alight);
HRESULT hr = _d3d_device->SetLight(light_id, &fdata);
if (FAILED(hr)) {
wdxdisplay9_cat.warning()
<< "Could not set light properties for " << light

View File

@ -316,6 +316,12 @@ protected:
DWORD _last_fvf;
// Cache the data necessary to bind each particular light each
// frame, so if we bind a given light multiple times, we only have
// to compute its data once.
typedef pmap<NodePath, D3DLIGHT9> DirectionalLights;
DirectionalLights _dlights;
#define MAXIMUM_TEXTURES 16

View File

@ -1631,6 +1631,8 @@ end_scene() {
_current_shader = (Shader *)NULL;
_current_shader_context = (CLP(ShaderContext) *)NULL;
}
_dlights.clear();
report_my_gl_errors();
}
@ -4176,6 +4178,15 @@ bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
static PStatCollector _draw_set_state_light_bind_directional_pcollector("Draw:Set State:Light:Bind:Directional");
PStatTimer timer(_draw_set_state_light_bind_directional_pcollector);
pair<DirectionalLights::iterator, bool> lookup = _dlights.insert(DirectionalLights::value_type(light, DirectionalLightFrameData()));
DirectionalLightFrameData &fdata = (*lookup.first).second;
if (lookup.second) {
// The light was not computed yet this frame. Compute it now.
CPT(TransformState) transform = light.get_transform(_scene_setup->get_scene_root().get_parent());
LVector3f dir = light_obj->get_direction() * transform->get_mat();
fdata._neg_dir.set(-dir[0], -dir[1], -dir[2], 0);
}
float light_color[4];
GLenum id = get_light_id( light_id );
static const Colorf black(0.0f, 0.0f, 0.0f, 1.0f);
@ -4185,10 +4196,7 @@ bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
// Position needs to specify x, y, z, and w.
// w == 0 implies light is at infinity
CPT(TransformState) transform = light.get_transform(_scene_setup->get_scene_root().get_parent());
LVector3f dir = light_obj->get_direction() * transform->get_mat();
LPoint4f fdir(-dir[0], -dir[1], -dir[2], 0);
GLP(Lightfv)(id, GL_POSITION, fdir.get_data());
GLP(Lightfv)(id, GL_POSITION, fdata._neg_dir.get_data());
// GL_SPOT_DIRECTION is not significant when cutoff == 180
// In this case, position x, y, z specifies direction

View File

@ -395,6 +395,16 @@ protected:
bool _use_sender;
#endif // SUPPORT_IMMEDIATE_MODE
// Cache the data necessary to bind each particular light each
// frame, so if we bind a given light multiple times, we only have
// to compute its data once.
class DirectionalLightFrameData {
public:
LVector4f _neg_dir;
};
typedef pmap<NodePath, DirectionalLightFrameData> DirectionalLights;
DirectionalLights _dlights;
int _pass_number;
bool _auto_rescale_normal;
GLuint _geom_display_list;