mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
first pass at primitive bumpmapping support
This commit is contained in:
parent
9b228c1321
commit
166e7414a6
@ -27,6 +27,7 @@
|
||||
#include "colorScaleAttrib.h"
|
||||
#include "lightAttrib.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "texGenAttrib.h"
|
||||
#include "renderState.h"
|
||||
#include "depthWriteAttrib.h"
|
||||
#include "colorWriteAttrib.h"
|
||||
|
@ -848,10 +848,10 @@ set_lighting(bool enable) {
|
||||
if (!_got_lights) {
|
||||
setup_lights();
|
||||
}
|
||||
render.node()->set_attrib(LightAttrib::make(LightAttrib::O_add,
|
||||
_alight, _dlight));
|
||||
render.set_light(_alight);
|
||||
render.set_light(_dlight);
|
||||
} else {
|
||||
render.node()->clear_attrib(LightAttrib::get_class_type());
|
||||
render.clear_light();
|
||||
}
|
||||
|
||||
_lighting_enabled = enable;
|
||||
@ -963,11 +963,12 @@ setup_lights() {
|
||||
NodePath camera_group = get_camera_group();
|
||||
NodePath light_group = camera_group.attach_new_node("lights");
|
||||
|
||||
_alight = new AmbientLight("ambient");
|
||||
_alight->set_color(Colorf(0.2f, 0.2f, 0.2f, 1.0f));
|
||||
_dlight = new DirectionalLight("directional");
|
||||
light_group.attach_new_node(_alight);
|
||||
light_group.attach_new_node(_dlight);
|
||||
AmbientLight *alight = new AmbientLight("ambient");
|
||||
alight->set_color(Colorf(0.2f, 0.2f, 0.2f, 1.0f));
|
||||
DirectionalLight *dlight = new DirectionalLight("directional");
|
||||
|
||||
_alight = light_group.attach_new_node(alight);
|
||||
_dlight = light_group.attach_new_node(dlight);
|
||||
|
||||
_got_lights = true;
|
||||
}
|
||||
|
@ -144,8 +144,8 @@ private:
|
||||
NodePath _mouse;
|
||||
PT(Trackball) _trackball;
|
||||
|
||||
AmbientLight *_alight;
|
||||
DirectionalLight *_dlight;
|
||||
NodePath _alight;
|
||||
NodePath _dlight;
|
||||
|
||||
bool _got_keyboard;
|
||||
bool _got_trackball;
|
||||
|
@ -132,6 +132,11 @@ PUBLISHED:
|
||||
|
||||
// The union of the above shade model types.
|
||||
GR_shade_model_bits = 0x6000,
|
||||
|
||||
// If there is a TexGenAttrib in effect with M_light_vector
|
||||
// enabled, meaning we need to generate the tangent space light
|
||||
// vector as the texture coordinates.
|
||||
GR_texcoord_light_vector = 0x8000,
|
||||
};
|
||||
|
||||
// The shade model specifies whether the per-vertex colors and
|
||||
|
@ -92,12 +92,17 @@ void Texture::
|
||||
setup_texture(Texture::TextureType texture_type, int x_size, int y_size,
|
||||
int z_size, Texture::ComponentType component_type,
|
||||
Texture::Format format) {
|
||||
#ifndef NDEBUG
|
||||
if (texture_type == TT_cube_map) {
|
||||
// Cube maps must always consist of six square images.
|
||||
nassertv(x_size == y_size && z_size == 6);
|
||||
|
||||
// In principle the wrap mode shouldn't mean anything to a cube
|
||||
// map, but some drivers seem to misbehave if it's other than
|
||||
// WM_clamp.
|
||||
_wrap_u = WM_clamp;
|
||||
_wrap_v = WM_clamp;
|
||||
_wrap_w = WM_clamp;
|
||||
}
|
||||
#endif
|
||||
|
||||
_texture_type = texture_type;
|
||||
_x_size = x_size;
|
||||
@ -110,6 +115,109 @@ setup_texture(Texture::TextureType texture_type, int x_size, int y_size,
|
||||
_loaded_from_disk = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::generate_normalization_cube_map
|
||||
// Access: Published
|
||||
// Description: Generates a special cube map image in the texture
|
||||
// that can be used to apply bump mapping effects: for
|
||||
// each texel in the cube map that is indexed by the 3-d
|
||||
// texture coordinates (x, y, z), the resulting value is
|
||||
// the normalized vector (x, y, z) (compressed from
|
||||
// -1..1 into 0..1).
|
||||
//
|
||||
// This also implicitly sets keep_ram_image to true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Texture::
|
||||
generate_normalization_cube_map(int size) {
|
||||
setup_cube_map(size, T_unsigned_byte, F_rgb);
|
||||
PTA_uchar image = modify_ram_image();
|
||||
|
||||
float half_size = (float)size * 0.5f;
|
||||
float center = half_size - 0.5f;
|
||||
|
||||
LMatrix4f scale
|
||||
(127.5f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 127.5f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 127.5f, 0.0f,
|
||||
127.5f, 127.5f, 127.5f, 1.0f);
|
||||
|
||||
unsigned char *p = image;
|
||||
int xi, yi;
|
||||
|
||||
// Page 0: positive X.
|
||||
for (yi = 0; yi < size; ++yi) {
|
||||
for (xi = 0; xi < size; ++xi) {
|
||||
LVector3f vec(half_size, center - yi, center - xi);
|
||||
vec.normalize();
|
||||
vec = scale.xform_point(vec);
|
||||
|
||||
*p++ = (unsigned char)vec[0];
|
||||
*p++ = (unsigned char)vec[1];
|
||||
*p++ = (unsigned char)vec[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Page 1: negative X.
|
||||
for (yi = 0; yi < size; ++yi) {
|
||||
for (xi = 0; xi < size; ++xi) {
|
||||
LVector3f vec(-half_size, center - yi, xi - center);
|
||||
vec.normalize();
|
||||
vec = scale.xform_point(vec);
|
||||
*p++ = (unsigned char)vec[0];
|
||||
*p++ = (unsigned char)vec[1];
|
||||
*p++ = (unsigned char)vec[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Page 2: positive Y.
|
||||
for (yi = 0; yi < size; ++yi) {
|
||||
for (xi = 0; xi < size; ++xi) {
|
||||
LVector3f vec(xi - center, half_size, yi - center);
|
||||
vec.normalize();
|
||||
vec = scale.xform_point(vec);
|
||||
*p++ = (unsigned char)vec[0];
|
||||
*p++ = (unsigned char)vec[1];
|
||||
*p++ = (unsigned char)vec[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Page 3: negative Y.
|
||||
for (yi = 0; yi < size; ++yi) {
|
||||
for (xi = 0; xi < size; ++xi) {
|
||||
LVector3f vec(xi - center, -half_size, center - yi);
|
||||
vec.normalize();
|
||||
vec = scale.xform_point(vec);
|
||||
*p++ = (unsigned char)vec[0];
|
||||
*p++ = (unsigned char)vec[1];
|
||||
*p++ = (unsigned char)vec[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Page 4: positive Z.
|
||||
for (yi = 0; yi < size; ++yi) {
|
||||
for (xi = 0; xi < size; ++xi) {
|
||||
LVector3f vec(xi - center, center - yi, half_size);
|
||||
vec.normalize();
|
||||
vec = scale.xform_point(vec);
|
||||
*p++ = (unsigned char)vec[0];
|
||||
*p++ = (unsigned char)vec[1];
|
||||
*p++ = (unsigned char)vec[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Page 5: negative Z.
|
||||
for (yi = 0; yi < size; ++yi) {
|
||||
for (xi = 0; xi < size; ++xi) {
|
||||
LVector3f vec(center - xi, center - yi, -half_size);
|
||||
vec.normalize();
|
||||
vec = scale.xform_point(vec);
|
||||
*p++ = (unsigned char)vec[0];
|
||||
*p++ = (unsigned char)vec[1];
|
||||
*p++ = (unsigned char)vec[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Texture::read
|
||||
// Access: Published
|
||||
|
@ -150,6 +150,8 @@ PUBLISHED:
|
||||
INLINE void setup_cube_map(int size,
|
||||
ComponentType component_type, Format format);
|
||||
|
||||
void generate_normalization_cube_map(int size);
|
||||
|
||||
bool read(const Filename &fullpath, int z = 0,
|
||||
int primary_file_num_channels = 0);
|
||||
bool read(const Filename &fullpath, const Filename &alpha_fullpath,
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "bamWriter.h"
|
||||
#include "datagram.h"
|
||||
#include "datagramIterator.h"
|
||||
#include "config_pgraph.h"
|
||||
|
||||
CPT(RenderAttrib) ClipPlaneAttrib::_empty_attrib;
|
||||
CPT(RenderAttrib) ClipPlaneAttrib::_all_off_attrib;
|
||||
@ -39,6 +40,9 @@ TypeHandle ClipPlaneAttrib::_type_handle;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) ClipPlaneAttrib::
|
||||
make(ClipPlaneAttrib::Operation op, PlaneNode *plane) {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated ClipPlaneAttrib interface.\n";
|
||||
|
||||
CPT(RenderAttrib) attrib;
|
||||
|
||||
switch (op) {
|
||||
@ -73,6 +77,9 @@ make(ClipPlaneAttrib::Operation op, PlaneNode *plane) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) ClipPlaneAttrib::
|
||||
make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2) {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated ClipPlaneAttrib interface.\n";
|
||||
|
||||
CPT(RenderAttrib) attrib;
|
||||
|
||||
switch (op) {
|
||||
@ -111,6 +118,9 @@ make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2) {
|
||||
CPT(RenderAttrib) ClipPlaneAttrib::
|
||||
make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2,
|
||||
PlaneNode *plane3) {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated ClipPlaneAttrib interface.\n";
|
||||
|
||||
CPT(RenderAttrib) attrib;
|
||||
|
||||
switch (op) {
|
||||
@ -152,6 +162,9 @@ make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2,
|
||||
CPT(RenderAttrib) ClipPlaneAttrib::
|
||||
make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2,
|
||||
PlaneNode *plane3, PlaneNode *plane4) {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated ClipPlaneAttrib interface.\n";
|
||||
|
||||
CPT(RenderAttrib) attrib;
|
||||
|
||||
switch (op) {
|
||||
@ -202,6 +215,9 @@ make(ClipPlaneAttrib::Operation op, PlaneNode *plane1, PlaneNode *plane2,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ClipPlaneAttrib::Operation ClipPlaneAttrib::
|
||||
get_operation() const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated ClipPlaneAttrib interface.\n";
|
||||
|
||||
if (has_all_off()) {
|
||||
return O_set;
|
||||
|
||||
@ -225,6 +241,9 @@ get_operation() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int ClipPlaneAttrib::
|
||||
get_num_planes() const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated ClipPlaneAttrib interface.\n";
|
||||
|
||||
if (get_num_off_planes() == 0) {
|
||||
return get_num_on_planes();
|
||||
} else {
|
||||
@ -244,6 +263,9 @@ get_num_planes() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PlaneNode *ClipPlaneAttrib::
|
||||
get_plane(int n) const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated ClipPlaneAttrib interface.\n";
|
||||
|
||||
if (get_num_off_planes() == 0) {
|
||||
return DCAST(PlaneNode, get_on_plane(n).node());
|
||||
} else {
|
||||
@ -264,6 +286,9 @@ get_plane(int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ClipPlaneAttrib::
|
||||
has_plane(PlaneNode *plane) const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated ClipPlaneAttrib interface.\n";
|
||||
|
||||
if (get_num_off_planes() == 0) {
|
||||
return has_on_plane(NodePath(plane));
|
||||
} else {
|
||||
@ -282,6 +307,9 @@ has_plane(PlaneNode *plane) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) ClipPlaneAttrib::
|
||||
add_plane(PlaneNode *plane) const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated ClipPlaneAttrib interface.\n";
|
||||
|
||||
if (get_num_off_planes() == 0) {
|
||||
return add_on_plane(NodePath(plane));
|
||||
} else {
|
||||
@ -301,6 +329,9 @@ add_plane(PlaneNode *plane) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) ClipPlaneAttrib::
|
||||
remove_plane(PlaneNode *plane) const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated ClipPlaneAttrib interface.\n";
|
||||
|
||||
if (get_num_off_planes() == 0) {
|
||||
return remove_on_plane(NodePath(plane));
|
||||
} else {
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "cullableObject.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "texGenAttrib.h"
|
||||
#include "renderState.h"
|
||||
#include "clockObject.h"
|
||||
#include "cullTraverser.h"
|
||||
@ -28,8 +29,10 @@
|
||||
#include "geomVertexWriter.h"
|
||||
#include "geomVertexReader.h"
|
||||
#include "geomTriangles.h"
|
||||
#include "light.h"
|
||||
|
||||
PStatCollector CullableObject::_munge_points_pcollector("*:Munge:Points");
|
||||
PStatCollector CullableObject::_munge_light_vector_pcollector("*:Munge:Light Vector");
|
||||
|
||||
CullableObject *CullableObject::_deleted_chain = (CullableObject *)NULL;
|
||||
int CullableObject::_num_ever_allocated = 0;
|
||||
@ -75,6 +78,9 @@ munge_geom(GraphicsStateGuardianBase *gsg,
|
||||
}
|
||||
munge_points_to_quads(traverser);
|
||||
}
|
||||
if (unsupported_bits & Geom::GR_texcoord_light_vector) {
|
||||
munge_texcoord_light_vector(traverser);
|
||||
}
|
||||
|
||||
// Now invoke the munger to ensure the resulting geometry is in
|
||||
// a GSG-friendly form.
|
||||
@ -370,7 +376,7 @@ munge_points_to_quads(const CullTraverser *traverser) {
|
||||
LPoint2f c1(-scale_x, scale_y);
|
||||
|
||||
if (has_rotate) {
|
||||
// If we have a rotate factor, apply it to those two corners.
|
||||
// If we have a rotate factor, apply it to those two corners.
|
||||
rotate.set_row(*vi);
|
||||
float r = rotate.get_data1f();
|
||||
LMatrix3f mat = LMatrix3f::rotate_mat(r);
|
||||
@ -439,3 +445,91 @@ munge_points_to_quads(const CullTraverser *traverser) {
|
||||
_geom = new_geom.p();
|
||||
_munged_data = new_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullableObject::munge_texcoord_light_vector
|
||||
// Access: Private
|
||||
// Description: Generates the vector from each vertex to the
|
||||
// indicated light as a 3-d texture coordinate.
|
||||
//
|
||||
// This may replace _geom, _munged_data, and _state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullableObject::
|
||||
munge_texcoord_light_vector(const CullTraverser *traverser) {
|
||||
PStatTimer timer(_munge_light_vector_pcollector);
|
||||
|
||||
if (_modelview_transform->is_singular()) {
|
||||
// If we're under a singular transform, never mind.
|
||||
return;
|
||||
}
|
||||
|
||||
CPT(TransformState) net_transform =
|
||||
traverser->get_camera_transform()->compose(_modelview_transform);
|
||||
|
||||
if (!_munged_data->has_column(InternalName::get_vertex()) ||
|
||||
!_munged_data->has_column(InternalName::get_normal())) {
|
||||
// No vertex or normal; can't compute light vector.
|
||||
return;
|
||||
}
|
||||
|
||||
CPT(TexGenAttrib) tex_gen = _state->get_tex_gen();
|
||||
nassertv(tex_gen != (TexGenAttrib *)NULL);
|
||||
|
||||
const TexGenAttrib::LightVectors &light_vectors = tex_gen->get_light_vectors();
|
||||
TexGenAttrib::LightVectors::const_iterator lvi;
|
||||
for (lvi = light_vectors.begin();
|
||||
lvi != light_vectors.end();
|
||||
++lvi) {
|
||||
TextureStage *stage = (*lvi).first;
|
||||
const NodePath &light = (*lvi).second;
|
||||
nassertv(!light.is_empty());
|
||||
Light *light_obj = light.node()->as_light();
|
||||
nassertv(light_obj != (Light *)NULL);
|
||||
|
||||
// Determine the names of the tangent and binormal columns
|
||||
// associated with the stage's texcoord name.
|
||||
CPT(InternalName) texcoord_name = stage->get_texcoord_name();
|
||||
string basename;
|
||||
if (texcoord_name != InternalName::get_texcoord()) {
|
||||
basename = texcoord_name->get_basename();
|
||||
}
|
||||
|
||||
CPT(InternalName) tangent_name = InternalName::get_tangent_name(basename);
|
||||
CPT(InternalName) binormal_name = InternalName::get_binormal_name(basename);
|
||||
|
||||
if (_munged_data->has_column(tangent_name) &&
|
||||
_munged_data->has_column(binormal_name)) {
|
||||
// Create a new column for the new texcoords.
|
||||
PT(GeomVertexData) new_data = _munged_data->replace_column
|
||||
(texcoord_name, 3, Geom::NT_float32, Geom::C_texcoord);
|
||||
_munged_data = new_data;
|
||||
|
||||
// Remove this TexGen stage from the state, since we're handling
|
||||
// it now.
|
||||
_state = _state->add_attrib(tex_gen->remove_stage(stage));
|
||||
|
||||
// Get the transform from the light to the object.
|
||||
CPT(TransformState) light_transform =
|
||||
net_transform->invert_compose(light.get_net_transform());
|
||||
const LMatrix4f &light_mat = light_transform->get_mat();
|
||||
|
||||
GeomVertexWriter texcoord(new_data, texcoord_name);
|
||||
GeomVertexReader vertex(new_data, InternalName::get_vertex());
|
||||
GeomVertexReader tangent(new_data, tangent_name);
|
||||
GeomVertexReader binormal(new_data, binormal_name);
|
||||
GeomVertexReader normal(new_data, InternalName::get_normal());
|
||||
|
||||
while (!vertex.is_at_end()) {
|
||||
LPoint3f p = vertex.get_data3f();
|
||||
LVector3f t = tangent.get_data3f();
|
||||
LVector3f b = binormal.get_data3f();
|
||||
LVector3f n = normal.get_data3f();
|
||||
|
||||
LVector3f lv;
|
||||
if (light_obj->get_vector_to_light(lv, p, light_mat)) {
|
||||
texcoord.add_data3f(lv.dot(t), lv.dot(b), lv.dot(n));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ public:
|
||||
|
||||
private:
|
||||
void munge_points_to_quads(const CullTraverser *traverser);
|
||||
void munge_texcoord_light_vector(const CullTraverser *traverser);
|
||||
|
||||
private:
|
||||
// This class is used internally by munge_points_to_quads().
|
||||
@ -105,6 +106,7 @@ private:
|
||||
static int _num_ever_allocated;
|
||||
|
||||
static PStatCollector _munge_points_pcollector;
|
||||
static PStatCollector _munge_light_vector_pcollector;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
@ -133,6 +133,32 @@ write(ostream &out, int indent_level) const {
|
||||
<< "direction " << get_direction() << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DirectionalLight::get_vector_to_light
|
||||
// Access: Public, Virtual
|
||||
// Description: Computes the vector from a particular vertex to this
|
||||
// light. The exact vector depends on the type of light
|
||||
// (e.g. point lights return a different result than
|
||||
// directional lights).
|
||||
//
|
||||
// The input parameters are the vertex position in
|
||||
// question, expressed in object space, and the matrix
|
||||
// which converts from light space to object space. The
|
||||
// result is expressed in object space.
|
||||
//
|
||||
// The return value is true if the result is successful,
|
||||
// or false if it cannot be computed (e.g. for an
|
||||
// ambient light).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DirectionalLight::
|
||||
get_vector_to_light(LVector3f &result, const LPoint3f &,
|
||||
const LMatrix4f &to_object_space) {
|
||||
CDReader cdata(_cycler);
|
||||
result = cdata->_direction * to_object_space;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DirectionalLight::bind
|
||||
// Access: Public, Virtual
|
||||
|
@ -40,6 +40,10 @@ public:
|
||||
virtual void xform(const LMatrix4f &mat);
|
||||
virtual void write(ostream &out, int indent_level) const;
|
||||
|
||||
virtual bool get_vector_to_light(LVector3f &result,
|
||||
const LPoint3f &from_object_point,
|
||||
const LMatrix4f &to_object_space);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE const Colorf &get_specular_color() const;
|
||||
INLINE void set_specular_color(const Colorf &color);
|
||||
|
@ -67,6 +67,28 @@ Light::
|
||||
~Light() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Light::get_vector_to_light
|
||||
// Access: Public, Virtual
|
||||
// Description: Computes the vector from a particular vertex to this
|
||||
// light. The exact vector depends on the type of light
|
||||
// (e.g. point lights return a different result than
|
||||
// directional lights).
|
||||
//
|
||||
// The input parameters are the vertex position in
|
||||
// question, expressed in object space, and the matrix
|
||||
// which converts from light space to object space. The
|
||||
// result is expressed in object space.
|
||||
//
|
||||
// The return value is true if the result is successful,
|
||||
// or false if it cannot be computed (e.g. for an
|
||||
// ambient light).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Light::
|
||||
get_vector_to_light(LVector3f &, const LPoint3f &, const LMatrix4f &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Light::get_viz
|
||||
// Access: Public
|
||||
|
@ -62,6 +62,10 @@ public:
|
||||
virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light,
|
||||
int light_id)=0;
|
||||
|
||||
virtual bool get_vector_to_light(LVector3f &result,
|
||||
const LPoint3f &from_object_point,
|
||||
const LMatrix4f &to_object_space);
|
||||
|
||||
GeomNode *get_viz();
|
||||
|
||||
protected:
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "bamWriter.h"
|
||||
#include "datagram.h"
|
||||
#include "datagramIterator.h"
|
||||
#include "config_pgraph.h"
|
||||
|
||||
CPT(RenderAttrib) LightAttrib::_empty_attrib;
|
||||
CPT(RenderAttrib) LightAttrib::_all_off_attrib;
|
||||
@ -40,6 +41,9 @@ TypeHandle LightAttrib::_type_handle;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightAttrib::
|
||||
make(LightAttrib::Operation op, Light *light) {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated LightAttrib interface.\n";
|
||||
|
||||
CPT(RenderAttrib) attrib;
|
||||
|
||||
switch (op) {
|
||||
@ -74,6 +78,9 @@ make(LightAttrib::Operation op, Light *light) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightAttrib::
|
||||
make(LightAttrib::Operation op, Light *light1, Light *light2) {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated LightAttrib interface.\n";
|
||||
|
||||
CPT(RenderAttrib) attrib;
|
||||
|
||||
switch (op) {
|
||||
@ -112,6 +119,9 @@ make(LightAttrib::Operation op, Light *light1, Light *light2) {
|
||||
CPT(RenderAttrib) LightAttrib::
|
||||
make(LightAttrib::Operation op, Light *light1, Light *light2,
|
||||
Light *light3) {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated LightAttrib interface.\n";
|
||||
|
||||
CPT(RenderAttrib) attrib;
|
||||
|
||||
switch (op) {
|
||||
@ -153,6 +163,9 @@ make(LightAttrib::Operation op, Light *light1, Light *light2,
|
||||
CPT(RenderAttrib) LightAttrib::
|
||||
make(LightAttrib::Operation op, Light *light1, Light *light2,
|
||||
Light *light3, Light *light4) {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated LightAttrib interface.\n";
|
||||
|
||||
CPT(RenderAttrib) attrib;
|
||||
|
||||
switch (op) {
|
||||
@ -203,6 +216,9 @@ make(LightAttrib::Operation op, Light *light1, Light *light2,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LightAttrib::Operation LightAttrib::
|
||||
get_operation() const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated LightAttrib interface.\n";
|
||||
|
||||
if (has_all_off()) {
|
||||
return O_set;
|
||||
|
||||
@ -226,6 +242,9 @@ get_operation() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int LightAttrib::
|
||||
get_num_lights() const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated LightAttrib interface.\n";
|
||||
|
||||
if (get_num_off_lights() == 0) {
|
||||
return get_num_on_lights();
|
||||
} else {
|
||||
@ -245,6 +264,9 @@ get_num_lights() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Light *LightAttrib::
|
||||
get_light(int n) const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated LightAttrib interface.\n";
|
||||
|
||||
if (get_num_off_lights() == 0) {
|
||||
return get_on_light(n).node()->as_light();
|
||||
} else {
|
||||
@ -265,6 +287,9 @@ get_light(int n) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool LightAttrib::
|
||||
has_light(Light *light) const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated LightAttrib interface.\n";
|
||||
|
||||
if (get_num_off_lights() == 0) {
|
||||
return has_on_light(NodePath(light->as_node()));
|
||||
} else {
|
||||
@ -283,6 +308,9 @@ has_light(Light *light) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightAttrib::
|
||||
add_light(Light *light) const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated LightAttrib interface.\n";
|
||||
|
||||
if (get_num_off_lights() == 0) {
|
||||
return add_on_light(NodePath(light->as_node()));
|
||||
} else {
|
||||
@ -302,6 +330,9 @@ add_light(Light *light) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) LightAttrib::
|
||||
remove_light(Light *light) const {
|
||||
pgraph_cat.warning()
|
||||
<< "Using deprecated LightAttrib interface.\n";
|
||||
|
||||
if (get_num_off_lights() == 0) {
|
||||
return remove_on_light(NodePath(light->as_node()));
|
||||
} else {
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "cullBinAttrib.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "texMatrixAttrib.h"
|
||||
#include "texGenAttrib.h"
|
||||
#include "materialAttrib.h"
|
||||
#include "lightAttrib.h"
|
||||
#include "clipPlaneAttrib.h"
|
||||
@ -3226,7 +3227,7 @@ get_tex_transform(const NodePath &other, TextureStage *stage) const {
|
||||
// the indicated texture stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
set_tex_gen(TextureStage *stage, TexGenAttrib::Mode mode, int priority) {
|
||||
set_tex_gen(TextureStage *stage, RenderAttrib::TexGenMode mode, int priority) {
|
||||
nassertv_always(!is_empty());
|
||||
|
||||
const RenderAttrib *attrib =
|
||||
@ -3246,6 +3247,36 @@ set_tex_gen(TextureStage *stage, TexGenAttrib::Mode mode, int priority) {
|
||||
node()->set_attrib(tga->add_stage(stage, mode), priority);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::set_tex_gen
|
||||
// Access: Published
|
||||
// Description: Enables automatic texture coordinate generation for
|
||||
// the indicated texture stage. This version of this
|
||||
// method is useful when setting M_light_vector, which
|
||||
// requires a specific light.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
set_tex_gen(TextureStage *stage, RenderAttrib::TexGenMode mode,
|
||||
const NodePath &light, int priority) {
|
||||
nassertv_always(!is_empty());
|
||||
|
||||
const RenderAttrib *attrib =
|
||||
node()->get_attrib(TexGenAttrib::get_class_type());
|
||||
|
||||
CPT(TexGenAttrib) tga;
|
||||
|
||||
if (attrib != (const RenderAttrib *)NULL) {
|
||||
priority = max(priority,
|
||||
node()->get_state()->get_override(TextureAttrib::get_class_type()));
|
||||
tga = DCAST(TexGenAttrib, attrib);
|
||||
|
||||
} else {
|
||||
tga = DCAST(TexGenAttrib, TexGenAttrib::make());
|
||||
}
|
||||
|
||||
node()->set_attrib(tga->add_stage(stage, mode, light), priority);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::clear_tex_gen
|
||||
// Access: Published
|
||||
@ -3311,7 +3342,7 @@ has_tex_gen(TextureStage *stage) const {
|
||||
// the given stage, or M_off if there is no explicit
|
||||
// mode set for the given stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TexGenAttrib::Mode NodePath::
|
||||
RenderAttrib::TexGenMode NodePath::
|
||||
get_tex_gen(TextureStage *stage) const {
|
||||
nassertr_always(!is_empty(), TexGenAttrib::M_off);
|
||||
|
||||
@ -3325,6 +3356,28 @@ get_tex_gen(TextureStage *stage) const {
|
||||
return TexGenAttrib::M_off;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::get_tex_gen_light
|
||||
// Access: Published
|
||||
// Description: Returns the particular Light set for the indicated
|
||||
// texgen mode's texture stage, or empty NodePath if no
|
||||
// light is set. This is only meaningful if the texgen
|
||||
// mode (returned by get_tex_gen()) is M_light_vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NodePath NodePath::
|
||||
get_tex_gen_light(TextureStage *stage) const {
|
||||
nassertr_always(!is_empty(), NodePath::fail());
|
||||
|
||||
const RenderAttrib *attrib =
|
||||
node()->get_attrib(TexGenAttrib::get_class_type());
|
||||
if (attrib != (const RenderAttrib *)NULL) {
|
||||
const TexGenAttrib *tga = DCAST(TexGenAttrib, attrib);
|
||||
return tga->get_light(stage);
|
||||
}
|
||||
|
||||
return NodePath();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::set_tex_projector
|
||||
// Access: Published
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "pandaNode.h"
|
||||
#include "renderState.h"
|
||||
#include "transformState.h"
|
||||
#include "texGenAttrib.h"
|
||||
#include "renderModeAttrib.h"
|
||||
#include "transparencyAttrib.h"
|
||||
#include "nodePathComponent.h"
|
||||
@ -581,11 +580,13 @@ PUBLISHED:
|
||||
INLINE float get_tex_rotate(const NodePath &other, TextureStage *stage) const;
|
||||
INLINE LVecBase2f get_tex_scale(const NodePath &other, TextureStage *stage) const;
|
||||
|
||||
void set_tex_gen(TextureStage *stage, TexGenAttrib::Mode mode, int priority = 0);
|
||||
void set_tex_gen(TextureStage *stage, RenderAttrib::TexGenMode mode, int priority = 0);
|
||||
void set_tex_gen(TextureStage *stage, RenderAttrib::TexGenMode mode, const NodePath &light, int priority = 0);
|
||||
void clear_tex_gen();
|
||||
void clear_tex_gen(TextureStage *stage);
|
||||
bool has_tex_gen(TextureStage *stage) const;
|
||||
TexGenAttrib::Mode get_tex_gen(TextureStage *stage) const;
|
||||
RenderAttrib::TexGenMode get_tex_gen(TextureStage *stage) const;
|
||||
NodePath get_tex_gen_light(TextureStage *stage) const;
|
||||
|
||||
void set_tex_projector(TextureStage *stage, const NodePath &from, const NodePath &to);
|
||||
void clear_tex_projector(TextureStage *stage);
|
||||
|
@ -132,6 +132,33 @@ write(ostream &out, int indent_level) const {
|
||||
<< "attenuation " << get_attenuation() << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointLight::get_vector_to_light
|
||||
// Access: Public, Virtual
|
||||
// Description: Computes the vector from a particular vertex to this
|
||||
// light. The exact vector depends on the type of light
|
||||
// (e.g. point lights return a different result than
|
||||
// directional lights).
|
||||
//
|
||||
// The input parameters are the vertex position in
|
||||
// question, expressed in object space, and the matrix
|
||||
// which converts from light space to object space. The
|
||||
// result is expressed in object space.
|
||||
//
|
||||
// The return value is true if the result is successful,
|
||||
// or false if it cannot be computed (e.g. for an
|
||||
// ambient light).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PointLight::
|
||||
get_vector_to_light(LVector3f &result, const LPoint3f &from_object_point,
|
||||
const LMatrix4f &to_object_space) {
|
||||
CDReader cdata(_cycler);
|
||||
LPoint3f point = cdata->_point * to_object_space;
|
||||
|
||||
result = point - from_object_point;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PointLight::bind
|
||||
// Access: Public, Virtual
|
||||
|
@ -40,6 +40,10 @@ public:
|
||||
virtual void xform(const LMatrix4f &mat);
|
||||
virtual void write(ostream &out, int indent_level) const;
|
||||
|
||||
virtual bool get_vector_to_light(LVector3f &result,
|
||||
const LPoint3f &from_object_point,
|
||||
const LMatrix4f &to_object_space);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE const Colorf &get_specular_color() const;
|
||||
INLINE void set_specular_color(const Colorf &color);
|
||||
|
@ -92,6 +92,74 @@ PUBLISHED:
|
||||
M_always // Always draw.
|
||||
};
|
||||
|
||||
// This is the enumerated type for TexGenAttrib. It is inherited
|
||||
// into TexGenAttrib. It is defined up at this level only to avoid
|
||||
// circular dependencies in the header files.
|
||||
enum TexGenMode {
|
||||
M_off,
|
||||
|
||||
// In the types below, "eye" means the coordinate space of the
|
||||
// observing camera, "object" means the local coordinate space of
|
||||
// the object, and "world" means world coordinates, e.g. the
|
||||
// coordinate space of the root of the graph.
|
||||
|
||||
// Sphere maps are classic static reflection maps. They are
|
||||
// supported on just about any hardware, and require a precomputed
|
||||
// 180-degree fisheye image. Sphere maps only make sense in eye
|
||||
// coordinate space.
|
||||
M_eye_sphere_map,
|
||||
|
||||
// Cube maps are a modern improvement on the sphere map; they
|
||||
// don't suffer from any polar singularities, but they require six
|
||||
// texture images. They can also be generated dynamically for
|
||||
// real-time reflections (see GraphicsOutput::make_cube_map()).
|
||||
// Typically, a statically-generated cube map will be in eye
|
||||
// space, while a dynamically-generated map will be in world space
|
||||
// or object space (depending on where the camera rig that
|
||||
// generates the map is parented).
|
||||
|
||||
// Cube mapping is not supported on all hardware.
|
||||
M_world_cube_map,
|
||||
M_eye_cube_map,
|
||||
|
||||
// Normal maps are most useful for applying diffuse lighting
|
||||
// effects via a pregenerated cube map.
|
||||
M_world_normal,
|
||||
M_eye_normal,
|
||||
|
||||
// Position maps convert XYZ coordinates directly to texture
|
||||
// coordinates. This is particularly useful for implementing
|
||||
// projective texturing (see NodePath::project_texture()).
|
||||
M_world_position,
|
||||
M_object_position,
|
||||
M_eye_position,
|
||||
|
||||
// With M_point_sprite, texture coordinates will be generated for
|
||||
// large points in the range (0,0) - (1,1) from upper-left to
|
||||
// lower-right across the point's face. Without this, each point
|
||||
// will have just a single uniform texture coordinate value across
|
||||
// its face.
|
||||
|
||||
// Unfortunately, the generated texture coordinates are inverted
|
||||
// (upside-down) from Panda's usual convention, but this is what
|
||||
// the graphics card manufacturers decided to use. You could use
|
||||
// a texture matrix to re-invert the texture, but that will
|
||||
// probably force software rendering. You'll have to paint your
|
||||
// textures upside-down if you want true hardware sprites.
|
||||
M_point_sprite,
|
||||
|
||||
// M_light_vector generates special 3-d texture coordinates that
|
||||
// represent the vector to a particular Light in the scene graph,
|
||||
// expressed in each vertex's tangent space. This is used to
|
||||
// implement bumpmapping.
|
||||
|
||||
// This requires a Light to be specified to the TexGenAttrib. It
|
||||
// also requires each vertex to define a normal, as well as a
|
||||
// tangent and binormal for the particular named texture
|
||||
// coordinate set.
|
||||
M_light_vector,
|
||||
};
|
||||
|
||||
protected:
|
||||
static CPT(RenderAttrib) return_new(RenderAttrib *attrib);
|
||||
virtual int compare_to_impl(const RenderAttrib *other) const;
|
||||
|
@ -336,29 +336,6 @@ get_render_mode() const {
|
||||
return _render_mode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderState::get_geom_rendering
|
||||
// Access: Published
|
||||
// Description: Returns the union of the Geom::GeomRendering bits
|
||||
// that will be required once this RenderState is
|
||||
// applied to a geom which includes the indicated
|
||||
// geom_rendering bits.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int RenderState::
|
||||
get_geom_rendering(int geom_rendering) const {
|
||||
if (get_render_mode() != (const RenderModeAttrib *)NULL) {
|
||||
geom_rendering = _render_mode->get_geom_rendering(geom_rendering);
|
||||
}
|
||||
if (get_tex_gen() != (const TexGenAttrib *)NULL) {
|
||||
geom_rendering = _tex_gen->get_geom_rendering(geom_rendering);
|
||||
}
|
||||
if (get_tex_matrix() != (const TexMatrixAttrib *)NULL) {
|
||||
geom_rendering = _tex_matrix->get_geom_rendering(geom_rendering);
|
||||
}
|
||||
|
||||
return geom_rendering;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderState::set_destructing
|
||||
// Access: Private
|
||||
|
@ -930,6 +930,29 @@ validate_states() {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderState::get_geom_rendering
|
||||
// Access: Published
|
||||
// Description: Returns the union of the Geom::GeomRendering bits
|
||||
// that will be required once this RenderState is
|
||||
// applied to a geom which includes the indicated
|
||||
// geom_rendering bits.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int RenderState::
|
||||
get_geom_rendering(int geom_rendering) const {
|
||||
if (get_render_mode() != (const RenderModeAttrib *)NULL) {
|
||||
geom_rendering = _render_mode->get_geom_rendering(geom_rendering);
|
||||
}
|
||||
if (get_tex_gen() != (const TexGenAttrib *)NULL) {
|
||||
geom_rendering = _tex_gen->get_geom_rendering(geom_rendering);
|
||||
}
|
||||
if (get_tex_matrix() != (const TexMatrixAttrib *)NULL) {
|
||||
geom_rendering = _tex_matrix->get_geom_rendering(geom_rendering);
|
||||
}
|
||||
|
||||
return geom_rendering;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RenderState::issue_delta_modify
|
||||
// Access: Public
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "updateSeq.h"
|
||||
#include "pStatCollector.h"
|
||||
#include "renderModeAttrib.h"
|
||||
#include "texGenAttrib.h"
|
||||
#include "texMatrixAttrib.h"
|
||||
#include "geomMunger.h"
|
||||
#include "weakPointerTo.h"
|
||||
@ -40,6 +39,7 @@ class TransparencyAttrib;
|
||||
class ColorAttrib;
|
||||
class ColorScaleAttrib;
|
||||
class TextureAttrib;
|
||||
class TexGenAttrib;
|
||||
class FactoryParams;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -134,7 +134,7 @@ PUBLISHED:
|
||||
INLINE const TexMatrixAttrib *get_tex_matrix() const;
|
||||
INLINE const RenderModeAttrib *get_render_mode() const;
|
||||
|
||||
INLINE int get_geom_rendering(int geom_rendering) const;
|
||||
int get_geom_rendering(int geom_rendering) const;
|
||||
|
||||
public:
|
||||
CPT(RenderState) issue_delta_modify(const RenderState *other,
|
||||
|
@ -141,6 +141,29 @@ write(ostream &out, int indent_level) const {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Spotlight::get_vector_to_light
|
||||
// Access: Public, Virtual
|
||||
// Description: Computes the vector from a particular vertex to this
|
||||
// light. The exact vector depends on the type of light
|
||||
// (e.g. point lights return a different result than
|
||||
// directional lights).
|
||||
//
|
||||
// The input parameters are the vertex position in
|
||||
// question, expressed in object space, and the matrix
|
||||
// which converts from light space to object space. The
|
||||
// result is expressed in object space.
|
||||
//
|
||||
// The return value is true if the result is successful,
|
||||
// or false if it cannot be computed (e.g. for an
|
||||
// ambient light).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Spotlight::
|
||||
get_vector_to_light(LVector3f &result, const LPoint3f &from_object_point,
|
||||
const LMatrix4f &to_object_space) {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Spotlight::make_spot
|
||||
// Access: Published, Static
|
||||
|
@ -51,6 +51,10 @@ public:
|
||||
virtual void xform(const LMatrix4f &mat);
|
||||
virtual void write(ostream &out, int indent_level) const;
|
||||
|
||||
virtual bool get_vector_to_light(LVector3f &result,
|
||||
const LPoint3f &from_object_point,
|
||||
const LMatrix4f &to_object_space);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE float get_exponent() const;
|
||||
INLINE void set_exponent(float exponent);
|
||||
|
@ -25,7 +25,10 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TexGenAttrib::
|
||||
TexGenAttrib() :
|
||||
_num_point_sprites(0)
|
||||
_num_point_sprites(0),
|
||||
_num_light_vectors(0),
|
||||
_point_geom_rendering(0),
|
||||
_geom_rendering(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -39,7 +42,10 @@ INLINE TexGenAttrib::
|
||||
TexGenAttrib(const TexGenAttrib ©) :
|
||||
_stages(copy._stages),
|
||||
_no_texcoords(copy._no_texcoords),
|
||||
_num_point_sprites(copy._num_point_sprites)
|
||||
_num_point_sprites(copy._num_point_sprites),
|
||||
_num_light_vectors(copy._num_light_vectors),
|
||||
_point_geom_rendering(copy._point_geom_rendering),
|
||||
_geom_rendering(copy._geom_rendering)
|
||||
{
|
||||
}
|
||||
|
||||
@ -54,12 +60,10 @@ TexGenAttrib(const TexGenAttrib ©) :
|
||||
INLINE int TexGenAttrib::
|
||||
get_geom_rendering(int geom_rendering) const {
|
||||
if ((geom_rendering & Geom::GR_point) != 0) {
|
||||
if (_num_point_sprites > 0) {
|
||||
geom_rendering |= Geom::GR_point_sprite;
|
||||
}
|
||||
geom_rendering |= _point_geom_rendering;
|
||||
}
|
||||
|
||||
return geom_rendering;
|
||||
return geom_rendering | _geom_rendering;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -75,3 +79,40 @@ INLINE const Geom::NoTexCoordStages &TexGenAttrib::
|
||||
get_no_texcoords() const {
|
||||
return _no_texcoords;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TexGenAttrib::get_light_vectors
|
||||
// Access: Public
|
||||
// Description: Returns the set of TextureStages that have
|
||||
// M_light_vector in effect, as well as the associated
|
||||
// Lights.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const TexGenAttrib::LightVectors &TexGenAttrib::
|
||||
get_light_vectors() const {
|
||||
return _light_vectors;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TexGenAttrib::ModeDef::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TexGenAttrib::ModeDef::
|
||||
ModeDef() :
|
||||
_mode(M_off)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TexGenAttrib::ModeDef::compare_to
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int TexGenAttrib::ModeDef::
|
||||
compare_to(const TexGenAttrib::ModeDef &other) const {
|
||||
if (_mode != other._mode) {
|
||||
return (int)_mode < (int)other._mode ? -1 : 1;
|
||||
}
|
||||
return _light.compare_to(other._light);
|
||||
}
|
||||
|
||||
|
@ -61,8 +61,8 @@ make() {
|
||||
// indicated stage.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) TexGenAttrib::
|
||||
make(TextureStage *stage, TexGenAttrib::Mode mode) {
|
||||
return DCAST(TexGenAttrib, make())->add_stage(stage, mode);
|
||||
make(TextureStage *stage, TexGenAttrib::Mode mode, const NodePath &light) {
|
||||
return DCAST(TexGenAttrib, make())->add_stage(stage, mode, light);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -74,14 +74,44 @@ make(TextureStage *stage, TexGenAttrib::Mode mode) {
|
||||
// replaced.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) TexGenAttrib::
|
||||
add_stage(TextureStage *stage, TexGenAttrib::Mode mode) const {
|
||||
TexGenAttrib *attrib = new TexGenAttrib(*this);
|
||||
attrib->_stages[stage] = mode;
|
||||
if (mode != M_off) {
|
||||
add_stage(TextureStage *stage, TexGenAttrib::Mode mode, const NodePath &light) const {
|
||||
CPT(RenderAttrib) removed = remove_stage(stage);
|
||||
TexGenAttrib *attrib = new TexGenAttrib(*DCAST(TexGenAttrib, removed));
|
||||
|
||||
ModeDef &mode_def = attrib->_stages[stage];
|
||||
mode_def._mode = mode;
|
||||
mode_def._light = light;
|
||||
switch (mode) {
|
||||
case M_point_sprite:
|
||||
attrib->_no_texcoords.insert(stage);
|
||||
if (mode == M_point_sprite) {
|
||||
attrib->_num_point_sprites++;
|
||||
attrib->_point_geom_rendering |= Geom::GR_point_sprite;
|
||||
attrib->_num_point_sprites++;
|
||||
break;
|
||||
|
||||
case M_light_vector:
|
||||
{
|
||||
Light *light_obj = NULL;
|
||||
if (!light.is_empty()) {
|
||||
light_obj = light.node()->as_light();
|
||||
}
|
||||
if (light_obj == (Light *)NULL) {
|
||||
ostringstream strm;
|
||||
strm << "Not a light: " << light;
|
||||
nassert_raise(strm.str());
|
||||
|
||||
} else {
|
||||
attrib->_light_vectors[stage] = light;
|
||||
attrib->_geom_rendering |= Geom::GR_texcoord_light_vector;
|
||||
attrib->_num_light_vectors++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case M_off:
|
||||
break;
|
||||
|
||||
default:
|
||||
attrib->_no_texcoords.insert(stage);
|
||||
}
|
||||
return return_new(attrib);
|
||||
}
|
||||
@ -100,12 +130,21 @@ remove_stage(TextureStage *stage) const {
|
||||
return this;
|
||||
}
|
||||
|
||||
Mode mode = (*si).second;
|
||||
Mode mode = (*si).second._mode;
|
||||
TexGenAttrib *attrib = new TexGenAttrib(*this);
|
||||
attrib->_stages.erase(stage);
|
||||
attrib->_no_texcoords.erase(stage);
|
||||
if (mode == M_point_sprite) {
|
||||
attrib->_num_point_sprites--;
|
||||
if (attrib->_num_point_sprites == 0) {
|
||||
attrib->_point_geom_rendering &= ~Geom::GR_point_sprite;
|
||||
}
|
||||
} else if (mode == M_light_vector) {
|
||||
attrib->_light_vectors.erase(stage);
|
||||
attrib->_num_light_vectors--;
|
||||
if (attrib->_num_light_vectors == 0) {
|
||||
attrib->_geom_rendering &= ~Geom::GR_texcoord_light_vector;
|
||||
}
|
||||
}
|
||||
return return_new(attrib);
|
||||
}
|
||||
@ -145,11 +184,28 @@ TexGenAttrib::Mode TexGenAttrib::
|
||||
get_mode(TextureStage *stage) const {
|
||||
Stages::const_iterator mi = _stages.find(stage);
|
||||
if (mi != _stages.end()) {
|
||||
return (*mi).second;
|
||||
return (*mi).second._mode;
|
||||
}
|
||||
return M_off;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TexGenAttrib::get_light
|
||||
// Access: Published
|
||||
// Description: Returns the Light associated with the named texture
|
||||
// stage, or the empty NodePath if no light is
|
||||
// associated with the indicated stage. This is only
|
||||
// meaningful if the mode is M_light_vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NodePath TexGenAttrib::
|
||||
get_light(TextureStage *stage) const {
|
||||
Stages::const_iterator mi = _stages.find(stage);
|
||||
if (mi != _stages.end()) {
|
||||
return (*mi).second._light;
|
||||
}
|
||||
return NodePath();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TexGenAttrib::issue
|
||||
// Access: Public, Virtual
|
||||
@ -176,9 +232,9 @@ output(ostream &out) const {
|
||||
Stages::const_iterator mi;
|
||||
for (mi = _stages.begin(); mi != _stages.end(); ++mi) {
|
||||
TextureStage *stage = (*mi).first;
|
||||
Mode mode = (*mi).second;
|
||||
const ModeDef &mode_def = (*mi).second;
|
||||
out << " " << stage->get_name() << "(";
|
||||
switch (mode) {
|
||||
switch (mode_def._mode) {
|
||||
case M_off:
|
||||
out << "off";
|
||||
break;
|
||||
@ -214,6 +270,10 @@ output(ostream &out) const {
|
||||
case M_point_sprite:
|
||||
out << "point_sprite";
|
||||
break;
|
||||
|
||||
case M_light_vector:
|
||||
out << "light_vector: " << mode_def._light;
|
||||
break;
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
@ -253,8 +313,9 @@ compare_to_impl(const RenderAttrib *other) const {
|
||||
|
||||
} else {
|
||||
// This stage is in both; compare the stages.
|
||||
if ((*ai).second != (*bi).second) {
|
||||
return (int)(*ai).second < (int)(*bi).second ? -1 : 1;
|
||||
int compare = (*ai).second.compare_to((*bi).second);
|
||||
if (compare != 0) {
|
||||
return compare;
|
||||
}
|
||||
++ai;
|
||||
++bi;
|
||||
@ -338,8 +399,29 @@ compose_impl(const RenderAttrib *other) const {
|
||||
// Now copy from _stages to _no_texcoords.
|
||||
Stages::const_iterator ri;
|
||||
for (ri = attrib->_stages.begin(); ri != attrib->_stages.end(); ++ri) {
|
||||
if ((*ri).second != M_off) {
|
||||
attrib->_no_texcoords.insert((*ri).first);
|
||||
TextureStage *stage = (*ri).first;
|
||||
const ModeDef &mode_def = (*ri).second;
|
||||
Mode mode = mode_def._mode;
|
||||
const NodePath &light = mode_def._light;
|
||||
|
||||
switch (mode) {
|
||||
case M_point_sprite:
|
||||
attrib->_no_texcoords.insert(stage);
|
||||
attrib->_point_geom_rendering |= Geom::GR_point_sprite;
|
||||
attrib->_num_point_sprites++;
|
||||
break;
|
||||
|
||||
case M_light_vector:
|
||||
attrib->_light_vectors[stage] = light;
|
||||
attrib->_geom_rendering |= Geom::GR_texcoord_light_vector;
|
||||
attrib->_num_light_vectors++;
|
||||
break;
|
||||
|
||||
case M_off:
|
||||
break;
|
||||
|
||||
default:
|
||||
attrib->_no_texcoords.insert(stage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,7 +453,7 @@ invert_compose_impl(const RenderAttrib *other) const {
|
||||
while (ai != _stages.end() && bi != ta->_stages.end()) {
|
||||
if ((*ai).first < (*bi).first) {
|
||||
// This stage is in a but not in b. Turn a off.
|
||||
attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, M_off));
|
||||
attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, ModeDef()));
|
||||
++ai;
|
||||
|
||||
} else if ((*bi).first < (*ai).first) {
|
||||
@ -389,7 +471,7 @@ invert_compose_impl(const RenderAttrib *other) const {
|
||||
|
||||
while (ai != _stages.end()) {
|
||||
// This stage is in a but not in b.
|
||||
attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, M_off));
|
||||
attrib->_stages.insert(attrib->_stages.end(), Stages::value_type((*ai).first, ModeDef()));
|
||||
++ai;
|
||||
}
|
||||
|
||||
@ -402,8 +484,29 @@ invert_compose_impl(const RenderAttrib *other) const {
|
||||
// Now copy from _stages to _no_texcoords.
|
||||
Stages::const_iterator ri;
|
||||
for (ri = attrib->_stages.begin(); ri != attrib->_stages.end(); ++ri) {
|
||||
if ((*ri).second != M_off) {
|
||||
attrib->_no_texcoords.insert((*ri).first);
|
||||
TextureStage *stage = (*ri).first;
|
||||
const ModeDef &mode_def = (*ri).second;
|
||||
Mode mode = mode_def._mode;
|
||||
const NodePath &light = mode_def._light;
|
||||
|
||||
switch (mode) {
|
||||
case M_point_sprite:
|
||||
attrib->_no_texcoords.insert(stage);
|
||||
attrib->_point_geom_rendering |= Geom::GR_point_sprite;
|
||||
attrib->_num_point_sprites++;
|
||||
break;
|
||||
|
||||
case M_light_vector:
|
||||
attrib->_light_vectors[stage] = light;
|
||||
attrib->_geom_rendering |= Geom::GR_texcoord_light_vector;
|
||||
attrib->_num_light_vectors++;
|
||||
break;
|
||||
|
||||
case M_off:
|
||||
break;
|
||||
|
||||
default:
|
||||
attrib->_no_texcoords.insert(stage);
|
||||
}
|
||||
}
|
||||
|
||||
@ -452,7 +555,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
Stages::const_iterator si;
|
||||
for (si = _stages.begin(); si != _stages.end(); ++si) {
|
||||
TextureStage *stage = (*si).first;
|
||||
Mode mode = (*si).second;
|
||||
Mode mode = (*si).second._mode;
|
||||
|
||||
manager->write_pointer(dg, stage);
|
||||
dg.add_uint8((unsigned int)mode);
|
||||
@ -475,7 +578,7 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
Mode mode = (*mi);
|
||||
|
||||
TextureStage *stage = DCAST(TextureStage, p_list[pi++]);
|
||||
_stages[stage] = mode;
|
||||
_stages[stage]._mode = mode;
|
||||
|
||||
if (mode != M_off) {
|
||||
_no_texcoords.insert(stage);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "textureStage.h"
|
||||
#include "texture.h"
|
||||
#include "pointerTo.h"
|
||||
#include "nodePath.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : TexGenAttrib
|
||||
@ -38,59 +39,11 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA TexGenAttrib : public RenderAttrib {
|
||||
PUBLISHED:
|
||||
enum Mode {
|
||||
M_off,
|
||||
|
||||
// In the types below, "eye" means the coordinate space of the
|
||||
// observing camera, "object" means the local coordinate space of
|
||||
// the object, and "world" means world coordinates, e.g. the
|
||||
// coordinate space of the root of the graph.
|
||||
|
||||
// Sphere maps are classic static reflection maps. They are
|
||||
// supported on just about any hardware, and require a precomputed
|
||||
// 180-degree fisheye image. Sphere maps only make sense in eye
|
||||
// coordinate space.
|
||||
M_eye_sphere_map,
|
||||
|
||||
// Cube maps are a modern improvement on the sphere map; they
|
||||
// don't suffer from any polar singularities, but they require six
|
||||
// texture images. They can also be generated dynamically for
|
||||
// real-time reflections (see GraphicsOutput::make_cube_map()).
|
||||
// Typically, a statically-generated cube map will be in eye
|
||||
// space, while a dynamically-generated map will be in world space
|
||||
// or object space (depending on where the camera rig that
|
||||
// generates the map is parented).
|
||||
|
||||
// Cube mapping is not supported on all hardware.
|
||||
M_world_cube_map,
|
||||
M_eye_cube_map,
|
||||
|
||||
// Normal maps are most useful for applying diffuse lighting
|
||||
// effects via a pregenerated cube map.
|
||||
M_world_normal,
|
||||
M_eye_normal,
|
||||
|
||||
// Position maps convert XYZ coordinates directly to texture
|
||||
// coordinates. This is particularly useful for implementing
|
||||
// projective texturing (see NodePath::project_texture()).
|
||||
M_world_position,
|
||||
M_object_position,
|
||||
M_eye_position,
|
||||
|
||||
// With M_point_sprite, texture coordinates will be generated for
|
||||
// large points in the range (0,0) - (1,1) from upper-left to
|
||||
// lower-right across the point's face. Without this, each point
|
||||
// will have just a single uniform texture coordinate value across
|
||||
// its face.
|
||||
|
||||
// Unfortunately, the generated texture coordinates are inverted
|
||||
// (upside-down) from Panda's usual convention, but this is what
|
||||
// the graphics card manufacturers decided to use. You could use
|
||||
// a texture matrix to re-invert the texture, but that will
|
||||
// probably force software rendering. You'll have to paint your
|
||||
// textures upside-down if you want true hardware sprites.
|
||||
M_point_sprite,
|
||||
};
|
||||
// We inherit the definition of our Mode enumerated type from
|
||||
// RenderAttrib. Normally, Mode would be defined here, but we
|
||||
// define it in the base class instead as a hack to avoid a problem
|
||||
// with circular includes.
|
||||
typedef RenderAttrib::TexGenMode Mode;
|
||||
|
||||
protected:
|
||||
INLINE TexGenAttrib();
|
||||
@ -101,20 +54,24 @@ public:
|
||||
|
||||
PUBLISHED:
|
||||
static CPT(RenderAttrib) make();
|
||||
static CPT(RenderAttrib) make(TextureStage *stage, Mode mode);
|
||||
static CPT(RenderAttrib) make(TextureStage *stage, Mode mode, const NodePath &light = NodePath());
|
||||
|
||||
CPT(RenderAttrib) add_stage(TextureStage *stage, Mode mode) const;
|
||||
CPT(RenderAttrib) add_stage(TextureStage *stage, Mode mode, const NodePath &light = NodePath()) const;
|
||||
CPT(RenderAttrib) remove_stage(TextureStage *stage) const;
|
||||
|
||||
bool is_empty() const;
|
||||
bool has_stage(TextureStage *stage) const;
|
||||
Mode get_mode(TextureStage *stage) const;
|
||||
NodePath get_light(TextureStage *stage) const;
|
||||
|
||||
INLINE int get_geom_rendering(int geom_rendering) const;
|
||||
|
||||
public:
|
||||
INLINE const Geom::NoTexCoordStages &get_no_texcoords() const;
|
||||
|
||||
typedef pmap<TextureStage *, NodePath> LightVectors;
|
||||
INLINE const LightVectors &get_light_vectors() const;
|
||||
|
||||
virtual void issue(GraphicsStateGuardianBase *gsg) const;
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
@ -125,21 +82,40 @@ protected:
|
||||
virtual RenderAttrib *make_default_impl() const;
|
||||
|
||||
private:
|
||||
typedef pmap<PT(TextureStage), Mode> Stages;
|
||||
class ModeDef {
|
||||
public:
|
||||
INLINE ModeDef();
|
||||
INLINE int compare_to(const ModeDef &other) const;
|
||||
Mode _mode;
|
||||
NodePath _light;
|
||||
};
|
||||
typedef pmap<PT(TextureStage), ModeDef> Stages;
|
||||
Stages _stages;
|
||||
|
||||
// This is a set of TextureStage pointers for which texture
|
||||
// coordinates will not be needed from the Geom. It's redundant;
|
||||
// it's almost the same set that is listed in _stages, above. It's
|
||||
// just here as an optimization to pass to
|
||||
// Geom::setup_multitexcoord_iterator() during rendering.
|
||||
// just here as an optimization during rendering.
|
||||
Geom::NoTexCoordStages _no_texcoords;
|
||||
|
||||
// This is another optimization during rendering; it lists the
|
||||
// texture stages (if any) that use M_light_vector, and their
|
||||
// associated lights.
|
||||
LightVectors _light_vectors;
|
||||
|
||||
// This element is only used during reading from a bam file. It has
|
||||
// no meaningful value any other time.
|
||||
pvector<Mode> _read_modes;
|
||||
|
||||
int _num_point_sprites;
|
||||
int _num_light_vectors;
|
||||
|
||||
// _point_geom_rendering is the GeomRendering bits that are added by
|
||||
// the TexGenAttrib if there are any points in the Geom.
|
||||
// _geom_rendering is the GeomRendering bits that are added
|
||||
// regardless of the kind of Geom it is.
|
||||
int _point_geom_rendering;
|
||||
int _geom_rendering;
|
||||
|
||||
static CPT(RenderAttrib) _empty_attrib;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user