00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "projtexShadower.h"
00019 #include "config_shader.h"
00020
00021 #include <light.h>
00022 #include <spotlight.h>
00023 #include <renderBuffer.h>
00024 #include <transformTransition.h>
00025 #include <lightTransition.h>
00026 #include <textureTransition.h>
00027 #include <colorBlendTransition.h>
00028 #include <colorTransition.h>
00029 #include <depthTestTransition.h>
00030 #include <depthWriteTransition.h>
00031 #include <polygonOffsetTransition.h>
00032 #include <get_rel_pos.h>
00033 #include <dftraverser.h>
00034 #include <displayRegion.h>
00035 #include <graphicsWindow.h>
00036 #include <directRenderTraverser.h>
00037
00038
00039
00040
00041 TypeHandle ProjtexShadower::_type_handle;
00042
00043
00044
00045
00046
00047
00048 ProjtexShadower::ProjtexShadower(int size) : CasterShader()
00049 {
00050 set_size(size);
00051
00052 Texture* texture = new Texture;
00053 texture->set_minfilter(Texture::FT_linear);
00054 texture->set_magfilter(Texture::FT_linear);
00055 texture->set_wrapu(Texture::WM_clamp);
00056 texture->set_wrapv(Texture::WM_clamp);
00057 texture->_pbuffer->set_xsize(_size);
00058 texture->_pbuffer->set_ysize(_size);
00059
00060 _projtex_shader = new ProjtexShader(texture, ColorBlendProperty::M_multiply);
00061 }
00062
00063
00064
00065
00066
00067
00068 void ProjtexShadower::
00069 set_priority(int priority)
00070 {
00071 Shader::set_priority(priority);
00072 _projtex_shader->set_priority(priority);
00073 }
00074
00075
00076
00077
00078
00079
00080 void ProjtexShadower::
00081 set_multipass(bool on)
00082 {
00083 Shader::set_multipass(on);
00084 _projtex_shader->set_multipass(on);
00085 }
00086
00087
00088
00089
00090
00091
00092 void ProjtexShadower::
00093 pre_apply(Node *node, const AllAttributesWrapper &init_state,
00094 const AllTransitionsWrapper &net_trans, GraphicsStateGuardian *gsg)
00095 {
00096 DirectRenderTraverser drt(gsg, RenderRelation::get_class_type());
00097
00098 int num_lights = 1;
00099
00100 if (get_num_casters() == 0) {
00101 shader_cat.error()
00102 << "ProjtexShadower::config() - no casters in caster list" << endl;
00103 return;
00104 }
00105 if (get_num_frusta() == 0) {
00106 shader_cat.error()
00107 << "ProjtexShadower::config() - no lights in frusta list" << endl;
00108 return;
00109 } else if (get_num_frusta() > 1) {
00110 shader_cat.warning()
00111 << "ProjtexShadower::config() - frusta list has more than one "
00112 << "frustum - ignore all but the first one for now..." << endl;
00113 num_lights = 1;
00114 }
00115 if (_frusta[0]->get_type() != Spotlight::get_class_type()) {
00116 shader_cat.error()
00117 << "ProjtexShadower::config() - only works for Spotlights" << endl;
00118 return;
00119 }
00120 Spotlight* light = (Spotlight *)_frusta[0];
00121
00122
00123 Colorf clear_color = gsg->get_color_clear_value();
00124
00125
00126 _projtex_shader->remove_frustum(light);
00127 _projtex_shader->add_frustum(light);
00128
00129
00130 Colorf diffuse = light->get_color();
00131 Colorf shadow_color;
00132 for (int i = 0; i < 4; i++)
00133 shadow_color[i] = 1.0 / ((diffuse[i] + 1) * num_lights);
00134
00135 nassertv(node != (Node *)NULL && gsg != (GraphicsStateGuardian *)NULL);
00136
00137
00138
00139
00140
00141
00142 PT(DisplayRegion) disp_region =
00143 gsg->get_window()->make_scratch_display_region(_size, _size);
00144 DisplayRegionStack old_dr = gsg->push_display_region(disp_region);
00145
00146
00147 FrameBufferStack old_fb = gsg->push_frame_buffer
00148 (gsg->get_render_buffer(RenderBuffer::T_back | RenderBuffer::T_depth),
00149 disp_region);
00150
00151 gsg->set_color_clear_value(Colorf(1., 1., 1., 1.));
00152 gsg->clear(gsg->get_render_buffer(RenderBuffer::T_back |
00153 RenderBuffer::T_depth), disp_region);
00154
00155
00156 AllTransitionsWrapper trans(net_trans);
00157
00158
00159 trans.set_transition(new LightTransition(LightTransition::all_off()));
00160
00161
00162 TextureTransition *t = new TextureTransition(TextureTransition::off());
00163 t->set_priority(100);
00164 trans.set_transition(t);
00165 trans.set_transition(new ColorBlendTransition(ColorBlendProperty::M_none));
00166
00167
00168
00169
00170 AllAttributesWrapper state(init_state);
00171 state.clear_attribute(TransformTransition::get_class_type());
00172
00173
00174
00175 gsg->render_subgraph(&drt, node, light, state, trans);
00176
00177
00178
00179
00180
00181
00182 DepthTestTransition *dta =
00183 new DepthTestTransition(DepthTestProperty::M_less);
00184 trans.set_transition(dta);
00185
00186 DepthWriteTransition *dwa = new DepthWriteTransition;
00187 trans.set_transition(dwa);
00188
00189 ColorTransition *ca = new ColorTransition(shadow_color);
00190 trans.set_transition(ca);
00191
00192
00193
00194
00195
00196 PT_Node caster_group = new Node;
00197 NamedNodeVector::iterator ci;
00198 for (ci = _casters.begin(); ci != _casters.end(); ++ci) {
00199 Node *caster = (*ci);
00200
00201 LMatrix4f mat;
00202 get_rel_mat(caster, node, mat);
00203
00204 RenderRelation *arc = new RenderRelation(caster_group, caster);
00205 arc->set_transition(new TransformTransition(mat));
00206 }
00207
00208
00209
00210 PT(RenderRelation) caster_arc = new RenderRelation(node, caster_group);
00211
00212
00213 gsg->render_subgraph(&drt, caster_group, light, state, trans);
00214
00215
00216
00217
00218 remove_arc(caster_arc);
00219
00220
00221
00222
00223 _projtex_shader->get_texture()->copy(gsg, disp_region, gsg->get_render_buffer(RenderBuffer::T_back));
00224
00225
00226
00227 gsg->set_color_clear_value(clear_color);
00228 gsg->pop_frame_buffer(old_fb);
00229 gsg->pop_display_region(old_dr);
00230 }
00231
00232
00233
00234
00235
00236
00237 void ProjtexShadower::
00238 apply(Node *node, const AllAttributesWrapper &init_state,
00239 const AllTransitionsWrapper &net_trans, GraphicsStateGuardian *gsg) {
00240
00241 Shader::apply(node, init_state, net_trans, gsg);
00242
00243
00244 _projtex_shader->apply(node, init_state, net_trans, gsg);
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258