Shader vertex arrays implemented

This commit is contained in:
Josh Yelon 2005-09-14 03:45:32 +00:00
parent 09878b64b0
commit 83b88c1ac3
10 changed files with 593 additions and 257 deletions

View File

@ -707,6 +707,20 @@ set_transform(const TransformState *transform) {
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_transform
// Access: Public
// Description: Fetches the external net transform. This
// transform is generally only set when geometry is
// about to be rendered. Therefore, this "get" function
// is typically only meaningful during the geometry
// rendering process.
////////////////////////////////////////////////////////////////////
INLINE CPT(TransformState) GraphicsStateGuardian::
get_transform() {
return _external_transform;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::get_current_display_region
// Access: Public

View File

@ -209,7 +209,8 @@ public:
INLINE void modify_state(const RenderState *state);
INLINE void set_state(const RenderState *state);
INLINE void set_transform(const TransformState *transform);
INLINE CPT(TransformState) get_transform();
RenderBuffer get_render_buffer(int buffer_type);
INLINE const DisplayRegion *get_current_display_region() const;

View File

@ -771,8 +771,10 @@ reset() {
_texgen_forced_normal = false;
_shader_mode = (ShaderMode *)NULL;
_shader_context = (CLP(ShaderContext) *)NULL;
_current_shader_mode = (ShaderMode *)NULL;
_current_shader_context = (CLP(ShaderContext) *)NULL;
_vertex_array_shader_mode = (ShaderMode *)NULL;
_vertex_array_shader_context = (CLP(ShaderContext) *)NULL;
// Count the max number of lights
GLint max_lights;
@ -1297,8 +1299,53 @@ begin_draw_primitives(const Geom *geom, const GeomMunger *munger,
#endif
}
// Enable the appropriate vertex arrays, and disable any
// extra vertex arrays used by the previous rendering mode.
#ifdef SUPPORT_IMMEDIATE_MODE
_use_sender = !vertex_arrays;
#endif
if (_vertex_array_shader_context==0) {
if (_current_shader_context==0) {
update_standard_vertex_arrays();
} else {
disable_standard_vertex_arrays();
_current_shader_context->update_shader_vertex_arrays(NULL,this);
}
} else {
if (_current_shader_context==0) {
_vertex_array_shader_context->disable_shader_vertex_arrays(this);
update_standard_vertex_arrays();
} else {
_current_shader_context->
update_shader_vertex_arrays(_vertex_array_shader_context,this);
}
}
_vertex_array_shader_mode = _current_shader_mode;
_vertex_array_shader_context = _current_shader_context;
report_my_gl_errors();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::update_standard_vertex_arrays
// Access: Protected
// Description: Disables any unneeded vertex arrays that
// were previously enabled, and enables any vertex
// arrays that are needed that were not previously
// enabled (or, sets up an immediate-mode sender).
// Called only from begin_draw_primitives.
// Used only when the standard (non-shader) pipeline
// is about to be used - glShaderContexts are responsible
// for setting up their own vertex arrays.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
update_standard_vertex_arrays()
{
const GeomVertexAnimationSpec &animation =
_vertex_data->get_format()->get_animation();
bool hardware_animation = (animation.get_animation_type() == Geom::AT_hardware);
#ifdef SUPPORT_IMMEDIATE_MODE
if (_use_sender) {
// We must use immediate mode to render primitives.
_sender.clear();
@ -1500,9 +1547,46 @@ begin_draw_primitives(const Geom *geom, const GeomMunger *munger,
GLP(EnableClientState)(GL_VERTEX_ARRAY);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::disable_standard_vertex_arrays
// Access: Protected
// Description: Used to disable all the standard vertex arrays that
// are currently enabled. glShaderContexts are
// responsible for setting up their own vertex arrays,
// but before they can do so, the standard vertex
// arrays need to be disabled to get them "out of the
// way." Called only from begin_draw_primitives.
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
disable_standard_vertex_arrays()
{
#ifdef SUPPORT_IMMEDIATE_MODE
if (_use_sender) return;
#endif
GLP(DisableClientState)(GL_NORMAL_ARRAY);
GLP(DisableClientState)(GL_COLOR_ARRAY);
GLP(Color4f)(1.0f, 1.0f, 1.0f, 1.0f);
report_my_gl_errors();
for (int stage_index=0; stage_index < _last_max_stage_index; stage_index++) {
_glClientActiveTexture(GL_TEXTURE0 + stage_index);
GLP(DisableClientState)(GL_TEXTURE_COORD_ARRAY);
}
_last_max_stage_index = 0;
report_my_gl_errors();
if (_supports_vertex_blend) {
GLP(DisableClientState)(GL_WEIGHT_ARRAY_ARB);
if (_supports_matrix_palette) {
GLP(DisableClientState)(GL_MATRIX_INDEX_ARRAY_ARB);
}
}
GLP(DisableClientState)(GL_VERTEX_ARRAY);
report_my_gl_errors();
return true;
}
////////////////////////////////////////////////////////////////////
@ -1554,6 +1638,9 @@ draw_triangles(const GeomTriangles *primitive) {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
draw_tristrips(const GeomTristrips *primitive) {
report_my_gl_errors();
#ifndef NDEBUG
if (GLCAT.is_spam()) {
GLCAT.spam() << "draw_tristrips: " << *primitive << "\n";
@ -2558,6 +2645,9 @@ issue_transform(const TransformState *transform) {
do_auto_rescale_normal();
}
if (_current_shader_context)
_current_shader_context->issue_transform(_current_shader_mode, this);
report_my_gl_errors();
}
@ -2590,10 +2680,10 @@ void CLP(GraphicsStateGuardian)::
issue_shader(const ShaderAttrib *attrib) {
ShaderMode *mode = attrib->get_shader_mode();
if (mode == 0) {
if (_shader_context != 0) {
_shader_context->unbind();
_shader_context = 0;
_shader_mode = 0;
if (_current_shader_context != 0) {
_current_shader_context->unbind();
_current_shader_mode = 0;
_current_shader_context = 0;
}
return;
}
@ -2601,23 +2691,35 @@ issue_shader(const ShaderAttrib *attrib) {
Shader *shader = mode->get_shader();
CLP(ShaderContext) *context = (CLP(ShaderContext) *)(shader->prepare_now(get_prepared_objects(), this));
if (context != _shader_context) {
if (context == 0) {
if (_current_shader_context != 0) {
_current_shader_context->unbind();
_current_shader_mode = 0;
_current_shader_context = 0;
}
return;
}
if (context != _current_shader_context) {
// Use a completely different shader than before.
// Unbind old shader, bind the new one.
if (_shader_context != 0) {
_shader_context->unbind();
_shader_context = 0;
if (_current_shader_context != 0) {
_current_shader_context->unbind();
_current_shader_context = 0;
}
if (context != 0) {
context->bind(mode, this);
_shader_context = context;
_current_shader_mode = mode;
_current_shader_context = context;
}
_shader_mode = mode;
} else {
// Use the same shader as before, but with new input arguments.
context->rebind(_shader_mode, mode);
_shader_mode = mode;
_current_shader_mode = mode;
_current_shader_context = context;
context->issue_parameters(mode, this);
}
report_my_gl_errors();
}
////////////////////////////////////////////////////////////////////

View File

@ -73,6 +73,7 @@ class EXPCL_GL CLP(GraphicsStateGuardian) : public GraphicsStateGuardian {
public:
CLP(GraphicsStateGuardian)(const FrameBufferProperties &properties);
virtual ~CLP(GraphicsStateGuardian)();
friend class CLP(ShaderContext);
virtual void reset();
@ -248,6 +249,9 @@ protected:
static GLenum get_blend_func(ColorBlendAttrib::Operand operand);
static GLenum get_usage(Geom::UsageHint usage_hint);
void disable_standard_vertex_arrays();
void update_standard_vertex_arrays();
static CPT(RenderState) get_untextured_state();
static CPT(RenderState) get_smooth_state();
static CPT(RenderState) get_flat_state();
@ -296,8 +300,6 @@ protected:
bool _polygon_offset_enabled;
bool _flat_shade_model;
int _decal_level;
PT(ShaderMode) _shader_mode;
CLP(ShaderContext) *_shader_context;
bool _dithering_enabled;
bool _texgen_forced_normal;
@ -310,7 +312,12 @@ protected:
float _point_size;
bool _point_perspective;
bool _vertex_blending_enabled;
PT(ShaderMode) _current_shader_mode;
CLP(ShaderContext) *_current_shader_context;
PT(ShaderMode) _vertex_array_shader_mode;
CLP(ShaderContext) *_vertex_array_shader_context;
CPT(DisplayRegion) _actual_display_region;
#ifdef SUPPORT_IMMEDIATE_MODE

View File

@ -31,14 +31,13 @@ CLP(ShaderContext)(Shader *s) : ShaderContext(s) {
#ifdef HAVE_CGGL
_cg_context = (CGcontext)0;
_cg_profile[VERT_SHADER] = (CGprofile)0;
_cg_profile[FRAG_SHADER] = (CGprofile)0;
_cg_program[VERT_SHADER] = (CGprogram)0;
_cg_program[FRAG_SHADER] = (CGprogram)0;
_cg_profile[SHADER_type_vert] = (CGprofile)0;
_cg_profile[SHADER_type_frag] = (CGprofile)0;
_cg_program[SHADER_type_vert] = (CGprogram)0;
_cg_program[SHADER_type_frag] = (CGprogram)0;
if (header == "Cg") {
if (header == "//Cg") {
CGerror err;
_cg_context = cgCreateContext();
if (_cg_context == 0) {
release_resources();
@ -46,46 +45,28 @@ CLP(ShaderContext)(Shader *s) : ShaderContext(s) {
return;
}
_cg_profile[VERT_SHADER] = cgGLGetLatestProfile(CG_GL_VERTEX);
_cg_profile[FRAG_SHADER] = cgGLGetLatestProfile(CG_GL_FRAGMENT);
if ((_cg_profile[VERT_SHADER] == CG_PROFILE_UNKNOWN)||
(_cg_profile[FRAG_SHADER] == CG_PROFILE_UNKNOWN)) {
_cg_profile[SHADER_type_vert] = cgGLGetLatestProfile(CG_GL_VERTEX);
_cg_profile[SHADER_type_frag] = cgGLGetLatestProfile(CG_GL_FRAGMENT);
if ((_cg_profile[SHADER_type_vert] == CG_PROFILE_UNKNOWN)||
(_cg_profile[SHADER_type_frag] == CG_PROFILE_UNKNOWN)) {
release_resources();
cerr << "Cg not supported by this video card II\n";
return;
}
cgGetError();
string commentary, stext[2];
s->parse_upto(commentary, "---*---", false);
_cg_linebase[0] = s->parse_lineno();
s->parse_upto(stext[0], "---*---", false);
_cg_linebase[1] = s->parse_lineno();
s->parse_upto(stext[1], "---*---", false);
for (int progindex=0; progindex<2; progindex++) {
_cg_program[progindex] =
cgCreateProgram(_cg_context, CG_SOURCE, stext[progindex].c_str(),
_cg_profile[progindex], "main", (const char**)NULL);
err = cgGetError();
if (err != CG_NO_ERROR) {
if (err == CG_COMPILER_ERROR) {
string listing = cgGetLastListing(_cg_context);
vector_string errlines;
tokenize(listing, errlines, "\n");
for (int i=0; i<(int)errlines.size(); i++) {
string line = trim(errlines[i]);
if (line != "") {
cerr << s->_file << " " << (_cg_linebase[progindex]-1) << "+" << errlines[i] << "\n";
}
}
} else {
cerr << s->_file << ": " << cgGetErrorString(err) << "\n";
}
}
}
_cg_program[0] =
cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
_cg_profile[0], "vshader", (const char**)NULL);
print_cg_compile_errors(s->_file, _cg_context);
if ((_cg_program[VERT_SHADER]==0)||(_cg_program[FRAG_SHADER]==0)) {
cgGetError();
_cg_program[1] =
cgCreateProgram(_cg_context, CG_SOURCE, s->_text.c_str(),
_cg_profile[1], "fshader", (const char**)NULL);
print_cg_compile_errors(s->_file, _cg_context);
if ((_cg_program[SHADER_type_vert]==0)||(_cg_program[SHADER_type_frag]==0)) {
release_resources();
return;
}
@ -104,8 +85,8 @@ CLP(ShaderContext)(Shader *s) : ShaderContext(s) {
return;
}
cgGLLoadProgram(_cg_program[VERT_SHADER]);
cgGLLoadProgram(_cg_program[FRAG_SHADER]);
cgGLLoadProgram(_cg_program[SHADER_type_vert]);
cgGLLoadProgram(_cg_program[SHADER_type_frag]);
cerr << s->_file << ": compiled ok.\n";
return;
@ -137,10 +118,10 @@ release_resources() {
if (_cg_context) {
cgDestroyContext(_cg_context);
_cg_context = (CGcontext)0;
_cg_profile[VERT_SHADER] = (CGprofile)0;
_cg_profile[FRAG_SHADER] = (CGprofile)0;
_cg_program[VERT_SHADER] = (CGprogram)0;
_cg_program[FRAG_SHADER] = (CGprogram)0;
_cg_profile[SHADER_type_vert] = (CGprofile)0;
_cg_profile[SHADER_type_frag] = (CGprofile)0;
_cg_program[SHADER_type_vert] = (CGprogram)0;
_cg_program[SHADER_type_frag] = (CGprogram)0;
}
#endif
}
@ -148,38 +129,24 @@ release_resources() {
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::bind
// Access: Public
// Description: xyz
// Description: This function is to be called to enable a new
// shader. It also initializes all of the shader's
// input parameters.
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
bind(ShaderMode *m, GraphicsStateGuardianBase *gsg) {
bind(ShaderMode *m, GSG *gsg) {
#ifdef HAVE_CGGL
if (_cg_context != 0) {
LVector4d tvec;
// Assign the uniform Auto-Matrices
for (int i=0; i<(int)_cg_autobind.size(); i++) {
cgGLSetStateMatrixParameter(_cg_autobind[i].parameter,
_cg_autobind[i].matrix,
_cg_autobind[i].orientation);
}
// Pass in k-parameters and transform-parameters
issue_parameters(m, gsg);
issue_transform(m, gsg);
// Bind the shaders.
cgGLEnableProfile(_cg_profile[VERT_SHADER]);
cgGLBindProgram(_cg_program[VERT_SHADER]);
cgGLEnableProfile(_cg_profile[FRAG_SHADER]);
cgGLBindProgram(_cg_program[FRAG_SHADER]);
// Pass in uniform sampler2d parameters.
for (int i=0; i<(int)_cg_tbind2d.size(); i++) {
int index = _cg_tbind2d[i].argindex;
if (index >= (int)m->_args.size()) continue;
if (m->_args[index]._type != ShaderModeArg::SAT_TEXTURE) continue;
Texture *tex = m->_args[index]._tvalue;
TextureContext *tc = tex->prepare_now(gsg->get_prepared_objects(),gsg);
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
cgGLSetTextureParameter(_cg_tbind2d[i].parameter, gtc->_index);
cgGLEnableTextureParameter(_cg_tbind2d[i].parameter);
}
cgGLEnableProfile(_cg_profile[SHADER_type_vert]);
cgGLBindProgram(_cg_program[SHADER_type_vert]);
cgGLEnableProfile(_cg_profile[SHADER_type_frag]);
cgGLBindProgram(_cg_program[SHADER_type_frag]);
}
#endif
}
@ -187,32 +154,222 @@ bind(ShaderMode *m, GraphicsStateGuardianBase *gsg) {
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::unbind
// Access: Public
// Description: xyz
// Description: This function disables a currently-bound shader.
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
unbind() {
unbind()
{
#ifdef HAVE_CGGL
if (_cg_context != 0) {
// Disable texture parameters.
for (int i=0; i<(int)_cg_tbind2d.size(); i++)
cgGLDisableTextureParameter(_cg_tbind2d[i].parameter);
cgGLDisableProfile(_cg_profile[VERT_SHADER]);
cgGLDisableProfile(_cg_profile[FRAG_SHADER]);
cgGLDisableProfile(_cg_profile[SHADER_type_vert]);
cgGLDisableProfile(_cg_profile[SHADER_type_frag]);
}
#endif
}
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::rebind
// Function: GLShaderContext::issue_parameters
// Access: Public
// Description: xyz
// Description: This function is to be called whenever
// the ShaderMode has changed, but the Shader
// itself has not changed. It loads the new
// input parameters into the already-bound shader.
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
rebind(ShaderMode *oldmode, ShaderMode *newmode) {
issue_parameters(ShaderMode *m, GSG *gsg)
{
#ifdef HAVE_CGGL
if (_cg_context != 0) {
// Pass in k-float parameters.
for (int i=0; i<(int)_cg_fbind.size(); i++) {
int index = _cg_fbind[i].argindex;
if (index >= (int)m->_args.size()) continue;
if (m->_args[index]._type != ShaderModeArg::SAT_FLOAT) continue;
cgGLSetParameter4dv(_cg_fbind[i].parameter, m->_args[index]._fvalue.get_data());
}
// Pass in k-float4x4 parameters.
for (int i=0; i<(int)_cg_npbind.size(); i++) {
int index = _cg_npbind[i].argindex;
if (index >= (int)m->_args.size()) continue;
if (m->_args[index]._type != ShaderModeArg::SAT_NODEPATH) continue;
const float *dat = m->_args[index]._nvalue.node()->get_transform()->get_mat().get_data();
cgGLSetMatrixParameterfc(_cg_npbind[i].parameter, dat);
}
// Pass in trans,tpose,row,col,xvec,yvec,zvec,pos parameters
for (int i=0; i<(int)_cg_parameter_bind.size(); i++)
bind_cg_transform(_cg_parameter_bind[i], m, gsg);
// Pass in trans,tpose,row,col,xvec,yvec,zvec,pos parameters
for (int i=0; i<(int)_cg_transform_bind.size(); i++)
bind_cg_transform(_cg_transform_bind[i], m, gsg);
}
#endif
}
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::issue_transform
// Access: Public
// Description: This function is to be called whenever
// the external_transform has changed, but the
// Shader itself has not changed. It loads the
// new transform into the already-bound shader.
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
issue_transform(ShaderMode *m, GSG *gsg)
{
#ifdef HAVE_CGGL
if (_cg_context != 0) {
// Pass in modelview, projection, etc.
for (int i=0; i<(int)_cg_autobind.size(); i++)
cgGLSetStateMatrixParameter(_cg_autobind[i].parameter,
_cg_autobind[i].matrix,
_cg_autobind[i].orient);
// Pass in trans,tpose,row,col,xvec,yvec,zvec,pos parameters
for (int i=0; i<(int)_cg_transform_bind.size(); i++)
bind_cg_transform(_cg_transform_bind[i], m, gsg);
}
#endif
}
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::disable_shader_vertex_arrays
// Access: Public
// Description: Disable all the vertex arrays used by this shader.
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
disable_shader_vertex_arrays(GSG *gsg)
{
#ifdef HAVE_CGGL
if (_cg_context)
for (int i=0; i<(int)_cg_varying.size(); i++)
cgGLDisableClientState(_cg_varying[i].parameter);
#endif
}
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::update_shader_vertex_arrays
// Access: Public
// Description: Disables all vertex arrays used by the previous
// shader, then enables all the vertex arrays needed
// by this shader. Extracts the relevant vertex array
// data from the gsg.
// The current implementation is inefficient, because
// it may unnecessarily disable arrays then immediately
// reenable them. We may optimize this someday.
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg)
{
if (prev) prev->disable_shader_vertex_arrays(gsg);
#ifdef HAVE_CGGL
if (_cg_context) {
#ifdef SUPPORT_IMMEDIATE_MODE
if (_use_sender) {
cerr << "immediate mode shaders not implemented yet\n";
} else
#endif // SUPPORT_IMMEDIATE_MODE
{
const GeomVertexArrayData *array_data;
Geom::NumericType numeric_type;
int start, stride, num_values;
int nvarying = _cg_varying.size();
for (int i=0; i<nvarying; i++) {
InternalName *name = _cg_varying[i].name;
int texslot = _cg_varying[i].append_uv;
if (texslot >= 0) {
const Geom::ActiveTextureStages &active_stages =
gsg->_current_texture->get_on_stages();
if (texslot < (int)active_stages.size()) {
TextureStage *stage = active_stages[texslot];
const InternalName *slotname = stage->get_texcoord_name();
name = name->append(slotname->get_name());
}
}
if (gsg->_vertex_data->get_array_info(name,
array_data, num_values, numeric_type,
start, stride)) {
const unsigned char *client_pointer = gsg->setup_array_data(array_data);
cgGLSetParameterPointer(_cg_varying[i].parameter,
num_values, gsg->get_numeric_type(numeric_type),
stride, client_pointer + start);
cgGLEnableClientState(_cg_varying[i].parameter);
} else {
cgGLDisableClientState(_cg_varying[i].parameter);
}
}
}
}
#endif // HAVE_CGGL
}
#ifdef HAVE_CGGL
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::bind_cg_transform
// Access: Public
// Description: Should deallocate all system resources (such as
// vertex program handles or Cg contexts).
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
bind_cg_transform(const ShaderTransBind &stb, ShaderMode *m, GSG *gsg)
{
CPT(TransformState) src;
CPT(TransformState) rel;
if (stb.src_argindex < 0) {
if (stb.src_argindex == SHADER_arg_camera)
src = TransformState::make_identity();
else if (stb.src_argindex == SHADER_arg_model)
src = gsg->get_transform();
else
src = gsg->get_scene()->get_world_transform();
} else {
if ((int)m->_args.size() > stb.src_argindex) {
ShaderModeArg *arg = &(m->_args[stb.src_argindex]);
if (arg->_type == ShaderModeArg::SAT_NODEPATH)
src = gsg->get_scene()->get_world_transform()->compose(arg->_nvalue.get_net_transform());
}
}
if (stb.rel_argindex < 0) {
if (stb.rel_argindex == SHADER_arg_camera)
rel = TransformState::make_identity();
else if (stb.rel_argindex == SHADER_arg_model)
rel = gsg->get_transform();
else
rel = gsg->get_scene()->get_world_transform();
} else {
if ((int)m->_args.size() > stb.rel_argindex) {
ShaderModeArg *arg = &(m->_args[stb.rel_argindex]);
if (arg->_type == ShaderModeArg::SAT_NODEPATH)
rel = gsg->get_scene()->get_world_transform()->compose(arg->_nvalue.get_net_transform());
}
}
CPT(TransformState) total = rel->invert_compose(src);
const float *data = total->get_mat().get_data();
// cerr << "Input for " << cgGetParameterName(stb.parameter) << " is\n" <<
// data[ 0] << " " << data[ 1] << " " << data[ 2] << " " << data[ 3] << "\n" <<
// data[ 4] << " " << data[ 5] << " " << data[ 6] << " " << data[ 7] << "\n" <<
// data[ 8] << " " << data[ 9] << " " << data[10] << " " << data[11] << "\n" <<
// data[12] << " " << data[13] << " " << data[14] << " " << data[15] << "\n";
switch (stb.trans_piece) {
case SHADER_data_matrix: cgGLSetMatrixParameterfc(stb.parameter, data); break;
case SHADER_data_transpose: cgGLSetMatrixParameterfr(stb.parameter, data); break;
case SHADER_data_row0: cgGLSetParameter4fv(stb.parameter, data+ 0); break;
case SHADER_data_row1: cgGLSetParameter4fv(stb.parameter, data+ 4); break;
case SHADER_data_row2: cgGLSetParameter4fv(stb.parameter, data+ 8); break;
case SHADER_data_row3: cgGLSetParameter4fv(stb.parameter, data+12); break;
case SHADER_data_col0: cgGLSetParameter4f(stb.parameter, data[0], data[4], data[ 8], data[12]); break;
case SHADER_data_col1: cgGLSetParameter4f(stb.parameter, data[1], data[5], data[ 9], data[13]); break;
case SHADER_data_col2: cgGLSetParameter4f(stb.parameter, data[2], data[6], data[10], data[14]); break;
case SHADER_data_col3: cgGLSetParameter4f(stb.parameter, data[3], data[7], data[11], data[15]); break;
}
}
////////////////////////////////////////////////////////////////////
// Function: Shader::errchk_cg_parameter_words
// Access: Public, Static
@ -291,28 +448,6 @@ errchk_cg_parameter_prog(CGparameter p, CGprogram prog, const string &msg)
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::errchk_cg_parameter_semantic
// Access: Public, Static
// Description: Make sure the provided Cg parameter has the
// correct semantic string. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool CLP(ShaderContext)::
errchk_cg_parameter_semantic(CGparameter p, const string &semantic)
{
if (semantic != cgGetParameterSemantic(p)) {
if (semantic == "") {
errchk_cg_output(p, "parameter should have no semantic string");
} else {
string msg = "parameter should have the semantic string ";
errchk_cg_output(p, msg + semantic);
}
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::errchk_cg_parameter_type
// Access: Public, Static
@ -368,7 +503,7 @@ errchk_cg_parameter_sampler(CGparameter p)
}
////////////////////////////////////////////////////////////////////
// Function: Shader::errchk_cg_parameter_direction
// Function: Shader::errchk_cg_output
// Access: Public, Static
// Description: Print an error message including a description
// of the specified Cg parameter.
@ -389,18 +524,42 @@ errchk_cg_output(CGparameter p, const string &msg)
if (d == CG_INOUT) dstr = "inout ";
const char *ts = cgGetTypeString(cgGetParameterType(p));
const char *ss = cgGetParameterSemantic(p);
string err;
string fn = _shader->_file;
if (ss) {
err = fn + ": " + msg + " (" + vstr + dstr + ts + " " + cgGetParameterName(p) + ":" + ss + ")\n";
} else {
err = fn + ": " + msg + " (" + vstr + dstr + ts + " " + cgGetParameterName(p) + ")\n";
}
err = fn + ": " + msg + " (" + vstr + dstr + ts + " " + cgGetParameterName(p) + ")\n";
cerr << err << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: Shader::print_cg_compile_errors
// Access: Public, Static
// Description: Used only after a Cg compile command, to print
// out any error messages that may have occurred
// during the Cg shader compilation. The 'file'
// is the name of the file containing the Cg code.
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
print_cg_compile_errors(const string &file, CGcontext ctx)
{
CGerror err = cgGetError();
if (err != CG_NO_ERROR) {
if (err == CG_COMPILER_ERROR) {
string listing = cgGetLastListing(ctx);
vector_string errlines;
tokenize(listing, errlines, "\n");
for (int i=0; i<(int)errlines.size(); i++) {
string line = trim(errlines[i]);
if (line != "") {
cerr << file << " " << errlines[i] << "\n";
}
}
} else {
cerr << file << ": " << cgGetErrorString(err) << "\n";
}
}
}
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::compile_cg_parameter
// Access: Public
@ -417,38 +576,52 @@ compile_cg_parameter(CGparameter p)
if (pname[0] == '$') return true;
vector_string pieces;
tokenize(pname, pieces, "_");
if (pieces.size() < 2) {
errchk_cg_output(p,"invalid parameter name");
return false;
}
if (pieces[0] == "vtx") {
if ((!errchk_cg_parameter_words(p,2)) ||
(!errchk_cg_parameter_direction(p, CG_IN)) ||
if ((!errchk_cg_parameter_direction(p, CG_IN)) ||
(!errchk_cg_parameter_variance(p, CG_VARYING)) ||
(!errchk_cg_parameter_prog(p, _cg_program[VERT_SHADER], "vertex")))
(!errchk_cg_parameter_float(p)) ||
(!errchk_cg_parameter_prog(p, _cg_program[SHADER_type_vert], "vertex")))
return false;
if (pieces[1] == "position") {
if (!errchk_cg_parameter_semantic(p,"POSITION")) return false;
if (!errchk_cg_parameter_float(p)) return false;
return true; // Cg handles this automatically.
ShaderVarying bind;
bind.parameter = p;
if (pieces.size() == 2) {
if (pieces[1]=="position") {
bind.name = InternalName::get_vertex();
bind.append_uv = -1;
_cg_varying.push_back(bind);
return true;
}
if (pieces[1].substr(0,8)=="texcoord") {
bind.name = InternalName::get_root();
bind.append_uv = atoi(pieces[1].c_str()+8);
_cg_varying.push_back(bind);
return true;
}
if (pieces[1].substr(0,7)=="tangent") {
bind.name = InternalName::get_tangent();
bind.append_uv = atoi(pieces[1].c_str()+7);
_cg_varying.push_back(bind);
return true;
}
if (pieces[1].substr(0,8)=="binormal") {
bind.name = InternalName::get_binormal();
bind.append_uv = atoi(pieces[1].c_str()+8);
_cg_varying.push_back(bind);
return true;
}
}
if (pieces[1] == "normal") {
if (!errchk_cg_parameter_semantic(p,"NORMAL")) return false;
if (!errchk_cg_parameter_float(p)) return false;
return true; // Cg handles this automatically.
}
if (pieces[1] == "color") {
if (!errchk_cg_parameter_semantic(p,"COLOR")) return false;
if (!errchk_cg_parameter_float(p)) return false;
return true; // Cg handles this automatically.
}
if (pieces[1].substr(0,8) == "texcoord") {
string ss = upcase(pieces[1]);
if (!errchk_cg_parameter_semantic(p,ss)) return false;
if (!errchk_cg_parameter_float(p)) return false;
return true; // Cg handles this automatically.
}
// Handle an arbitrary column taken from the vertex array.
// IMPLEMENT ME.
errchk_cg_output(p, "Arbitrary vertex fields not implemented yet");
return false;
bind.name = InternalName::get_root();
bind.append_uv = -1;
for (int i=1; i<(int)(pieces.size()-0); i++)
bind.name = bind.name->append(pieces[i]);
_cg_varying.push_back(bind);
return true;
}
if ((pieces[0] == "trans")||
@ -460,57 +633,48 @@ compile_cg_parameter(CGparameter p)
(pieces[0] == "col0")||
(pieces[0] == "col1")||
(pieces[0] == "col2")||
(pieces[0] == "col3")||
(pieces[0] == "xvec")||
(pieces[0] == "yvec")||
(pieces[0] == "zvec")||
(pieces[0] == "pos")) {
(pieces[0] == "col3")) {
if ((!errchk_cg_parameter_words(p,4)) ||
(!errchk_cg_parameter_direction(p, CG_IN)) ||
(!errchk_cg_parameter_variance(p, CG_UNIFORM)) ||
(!errchk_cg_parameter_semantic(p, "")))
(!errchk_cg_parameter_variance(p, CG_UNIFORM)))
return false;
if (pieces[2] != "rel") {
if ((pieces[2] != "rel")&&(pieces[2] != "to")) {
errchk_cg_output(p, "syntax error");
return false;
}
ShaderTransBind bind;
bind.parameter = p;
if (pieces[0]=="trans") bind.trans_piece = TRANS_NORMAL;
else if (pieces[0]=="tpose") bind.trans_piece = TRANS_TPOSE;
else if (pieces[0]=="row0") bind.trans_piece = TRANS_ROW0;
else if (pieces[0]=="row1") bind.trans_piece = TRANS_ROW1;
else if (pieces[0]=="row2") bind.trans_piece = TRANS_ROW2;
else if (pieces[0]=="row3") bind.trans_piece = TRANS_ROW3;
else if (pieces[0]=="col0") bind.trans_piece = TRANS_COL0;
else if (pieces[0]=="col1") bind.trans_piece = TRANS_COL1;
else if (pieces[0]=="col2") bind.trans_piece = TRANS_COL2;
else if (pieces[0]=="col3") bind.trans_piece = TRANS_COL3;
else if (pieces[0]=="xvec") bind.trans_piece = TRANS_ROW0;
else if (pieces[0]=="yvec") bind.trans_piece = TRANS_ROW1;
else if (pieces[0]=="zvec") bind.trans_piece = TRANS_ROW2;
else if (pieces[0]=="pos") bind.trans_piece = TRANS_ROW3;
if (pieces[0]=="trans") bind.trans_piece = SHADER_data_matrix;
else if (pieces[0]=="tpose") bind.trans_piece = SHADER_data_transpose;
else if (pieces[0]=="row0") bind.trans_piece = SHADER_data_row0;
else if (pieces[0]=="row1") bind.trans_piece = SHADER_data_row1;
else if (pieces[0]=="row2") bind.trans_piece = SHADER_data_row2;
else if (pieces[0]=="row3") bind.trans_piece = SHADER_data_row3;
else if (pieces[0]=="col0") bind.trans_piece = SHADER_data_col0;
else if (pieces[0]=="col1") bind.trans_piece = SHADER_data_col1;
else if (pieces[0]=="col2") bind.trans_piece = SHADER_data_col2;
else if (pieces[0]=="col3") bind.trans_piece = SHADER_data_col3;
if (pieces[1] == "world") bind.src_argindex = ARGINDEX_WORLD;
else if (pieces[1] == "camera") bind.src_argindex = ARGINDEX_CAMERA;
else if (pieces[1] == "model") bind.src_argindex = ARGINDEX_MODEL;
if (pieces[1] == "world") bind.src_argindex = SHADER_arg_world;
else if (pieces[1] == "camera") bind.src_argindex = SHADER_arg_camera;
else if (pieces[1] == "model") bind.src_argindex = SHADER_arg_model;
else bind.src_argindex = _shader->arg_index(pieces[1]);
if (pieces[3] == "world") bind.rel_argindex = ARGINDEX_WORLD;
else if (pieces[3] == "camera") bind.rel_argindex = ARGINDEX_CAMERA;
else if (pieces[3] == "model") bind.rel_argindex = ARGINDEX_MODEL;
if (pieces[3] == "world") bind.rel_argindex = SHADER_arg_world;
else if (pieces[3] == "camera") bind.rel_argindex = SHADER_arg_camera;
else if (pieces[3] == "model") bind.rel_argindex = SHADER_arg_model;
else bind.rel_argindex = _shader->arg_index(pieces[3]);
if ((bind.trans_piece == TRANS_NORMAL)||(bind.trans_piece == TRANS_TPOSE)) {
if ((bind.trans_piece == SHADER_data_matrix)||(bind.trans_piece == SHADER_data_transpose)) {
if (!errchk_cg_parameter_type(p, CG_FLOAT4x4)) return false;
} else {
if (!errchk_cg_parameter_type(p, CG_FLOAT4)) return false;
}
_cg_trans_bind.push_back(bind);
if ((bind.src_argindex == ARGINDEX_MODEL) ||
(bind.rel_argindex == ARGINDEX_MODEL)) {
_cg_trans_rebind.push_back(bind);
_cg_parameter_bind.push_back(bind);
if ((bind.src_argindex == SHADER_arg_model) ||
(bind.rel_argindex == SHADER_arg_model)) {
_cg_transform_bind.push_back(bind);
}
return true;
}
@ -523,34 +687,32 @@ compile_cg_parameter(CGparameter p)
(pieces[0]=="wspos")) {
if ((!errchk_cg_parameter_words(p,2)) ||
(!errchk_cg_parameter_direction(p, CG_IN)) ||
(!errchk_cg_parameter_variance(p, CG_UNIFORM)) ||
(!errchk_cg_parameter_semantic(p, "")))
(!errchk_cg_parameter_variance(p, CG_UNIFORM)))
return false;
ShaderTransBind bind;
bind.parameter = p;
if (pieces[0]=="wstrans") { bind.rel_argindex = ARGINDEX_WORLD; bind.trans_piece = TRANS_NORMAL; }
else if (pieces[0]=="cstrans") { bind.rel_argindex = ARGINDEX_CAMERA; bind.trans_piece = TRANS_NORMAL; }
else if (pieces[0]=="mstrans") { bind.rel_argindex = ARGINDEX_MODEL; bind.trans_piece = TRANS_NORMAL; }
else if (pieces[0]=="wspos") { bind.rel_argindex = ARGINDEX_WORLD; bind.trans_piece = TRANS_ROW3; }
else if (pieces[0]=="cspos") { bind.rel_argindex = ARGINDEX_CAMERA; bind.trans_piece = TRANS_ROW3; }
else if (pieces[0]=="mspos") { bind.rel_argindex = ARGINDEX_MODEL; bind.trans_piece = TRANS_ROW3; }
if (pieces[0]=="wstrans") { bind.rel_argindex = SHADER_arg_world; bind.trans_piece = SHADER_data_matrix; }
else if (pieces[0]=="cstrans") { bind.rel_argindex = SHADER_arg_camera; bind.trans_piece = SHADER_data_matrix; }
else if (pieces[0]=="mstrans") { bind.rel_argindex = SHADER_arg_model; bind.trans_piece = SHADER_data_matrix; }
else if (pieces[0]=="wspos") { bind.rel_argindex = SHADER_arg_world; bind.trans_piece = SHADER_data_row3; }
else if (pieces[0]=="cspos") { bind.rel_argindex = SHADER_arg_camera; bind.trans_piece = SHADER_data_row3; }
else if (pieces[0]=="mspos") { bind.rel_argindex = SHADER_arg_model; bind.trans_piece = SHADER_data_row3; }
if (pieces[1] == "world") bind.src_argindex = ARGINDEX_WORLD;
else if (pieces[1] == "camera") bind.src_argindex = ARGINDEX_CAMERA;
else if (pieces[1] == "model") bind.src_argindex = ARGINDEX_MODEL;
if (pieces[1] == "world") bind.src_argindex = SHADER_arg_world;
else if (pieces[1] == "camera") bind.src_argindex = SHADER_arg_camera;
else if (pieces[1] == "model") bind.src_argindex = SHADER_arg_model;
else bind.src_argindex = _shader->arg_index(pieces[1]);
if ((bind.trans_piece == TRANS_NORMAL)||(bind.trans_piece == TRANS_TPOSE)) {
if ((bind.trans_piece == SHADER_data_matrix)||(bind.trans_piece == SHADER_data_transpose)) {
if (!errchk_cg_parameter_type(p, CG_FLOAT4x4)) return false;
} else {
if (!errchk_cg_parameter_type(p, CG_FLOAT4)) return false;
}
_cg_trans_bind.push_back(bind);
if ((bind.src_argindex == ARGINDEX_MODEL) ||
(bind.rel_argindex == ARGINDEX_MODEL)) {
_cg_trans_rebind.push_back(bind);
}
_cg_parameter_bind.push_back(bind);
if ((bind.src_argindex == SHADER_arg_model) ||
(bind.rel_argindex == SHADER_arg_model))
_cg_transform_bind.push_back(bind);
return true;
}
@ -573,10 +735,10 @@ compile_cg_parameter(CGparameter p)
errchk_cg_output(p, "unrecognized matrix name");
return false;
}
if (pieces[0]=="mat") bind.orientation = CG_GL_MATRIX_IDENTITY;
else if (pieces[0]=="inv") bind.orientation = CG_GL_MATRIX_INVERSE;
else if (pieces[0]=="tps") bind.orientation = CG_GL_MATRIX_TRANSPOSE;
else if (pieces[0]=="itp") bind.orientation = CG_GL_MATRIX_INVERSE_TRANSPOSE;
if (pieces[0]=="mat") bind.orient = CG_GL_MATRIX_IDENTITY;
else if (pieces[0]=="inv") bind.orient = CG_GL_MATRIX_INVERSE;
else if (pieces[0]=="tps") bind.orient = CG_GL_MATRIX_TRANSPOSE;
else if (pieces[0]=="itp") bind.orient = CG_GL_MATRIX_INVERSE_TRANSPOSE;
_cg_autobind.push_back(bind);
return true;
}
@ -587,10 +749,7 @@ compile_cg_parameter(CGparameter p)
(!errchk_cg_parameter_variance(p, CG_UNIFORM)) ||
(!errchk_cg_parameter_sampler(p)))
return false;
if (cgGetParameterSemantic(p)[0]!=0) {
string texunit = "TEX"+upcase(pieces[1]);
if (!errchk_cg_parameter_semantic(p, texunit)) return false;
}
// IMPLEMENT ME
return true; // Cg handles this automatically.
}
@ -603,10 +762,7 @@ compile_cg_parameter(CGparameter p)
bind.parameter = p;
bind.argindex = _shader->arg_index(pieces[1]);
switch (cgGetParameterType(p)) {
case CG_FLOAT1: _cg_vbind1.push_back(bind); break;
case CG_FLOAT2: _cg_vbind2.push_back(bind); break;
case CG_FLOAT3: _cg_vbind3.push_back(bind); break;
case CG_FLOAT4: _cg_vbind4.push_back(bind); break;
case CG_FLOAT4: _cg_fbind.push_back(bind); break;
case CG_SAMPLER2D: _cg_tbind2d.push_back(bind); break;
case CG_SAMPLER3D: _cg_tbind3d.push_back(bind); break;
case CG_FLOAT4x4: _cg_npbind.push_back(bind); break;
@ -631,3 +787,4 @@ compile_cg_parameter(CGparameter p)
return false;
}
#endif

View File

@ -23,6 +23,8 @@
#endif
#include "string_utils.h"
class CLP(GraphicsStateGuardian);
////////////////////////////////////////////////////////////////////
// Class : GLShaderContext
// Description : xyz
@ -32,36 +34,23 @@ class EXPCL_GL CLP(ShaderContext): public ShaderContext {
public:
CLP(ShaderContext)(Shader *s);
~CLP(ShaderContext)();
typedef CLP(GraphicsStateGuardian) GSG;
INLINE bool valid(void);
void bind(ShaderMode *mode, GraphicsStateGuardianBase *gsg);
void bind(ShaderMode *mode, GSG *gsg);
void unbind();
void rebind(ShaderMode *oldmode, ShaderMode *newmode);
void issue_parameters(ShaderMode *mode, GSG *gsg);
void issue_transform(ShaderMode *mode, GSG *gsg);
void disable_shader_vertex_arrays(GSG *gsg);
void update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg);
private:
#ifdef HAVE_CGGL
enum {
ARGINDEX_WORLD =-1,
ARGINDEX_CAMERA=-2,
ARGINDEX_MODEL =-3
};
enum {
TRANS_NORMAL,
TRANS_TPOSE,
TRANS_ROW0,
TRANS_ROW1,
TRANS_ROW2,
TRANS_ROW3,
TRANS_COL0,
TRANS_COL1,
TRANS_COL2,
TRANS_COL3,
};
struct ShaderAutoBind {
CGparameter parameter;
CGGLenum matrix;
CGGLenum orientation;
CGGLenum orient;
};
struct ShaderArgBind {
CGparameter parameter;
@ -73,34 +62,39 @@ private:
int rel_argindex;
int trans_piece;
};
struct ShaderVarying {
CGparameter parameter;
PT(InternalName) name;
int append_uv;
};
CGcontext _cg_context;
CGprofile _cg_profile[2];
CGprogram _cg_program[2];
int _cg_linebase[2];
// These arrays contain lists of "bindings." They
// tell us how to fill the shader's input parameters.
vector <ShaderAutoBind> _cg_autobind;
vector <ShaderArgBind> _cg_tbind2d;
vector <ShaderArgBind> _cg_tbind3d;
vector <ShaderArgBind> _cg_vbind1;
vector <ShaderArgBind> _cg_vbind2;
vector <ShaderArgBind> _cg_vbind3;
vector <ShaderArgBind> _cg_vbind4;
vector <ShaderArgBind> _cg_fbind;
vector <ShaderArgBind> _cg_npbind;
vector <ShaderTransBind> _cg_trans_bind;
vector <ShaderTransBind> _cg_trans_rebind;
vector <ShaderTransBind> _cg_transform_bind;
vector <ShaderTransBind> _cg_parameter_bind;
vector <ShaderVarying> _cg_varying;
void bind_cg_transform(const ShaderTransBind &stb, ShaderMode *m,
CLP(GraphicsStateGuardian) *gsg);
bool compile_cg_parameter(CGparameter p);
bool errchk_cg_parameter_words(CGparameter p, int len);
bool errchk_cg_parameter_direction(CGparameter p, CGenum dir);
bool errchk_cg_parameter_variance(CGparameter p, CGenum var);
bool errchk_cg_parameter_prog(CGparameter p, CGprogram prog, const string &msg);
bool errchk_cg_parameter_semantic(CGparameter p, const string &semantic);
bool errchk_cg_parameter_type(CGparameter p, CGtype dt);
bool errchk_cg_parameter_float(CGparameter p);
bool errchk_cg_parameter_sampler(CGparameter p);
void errchk_cg_output(CGparameter p, const string &msg);
void print_cg_compile_errors(const string &file, CGcontext ctx);
#endif
void release_resources(void);

View File

@ -41,13 +41,34 @@ public:
INLINE ShaderContext(Shader *shader);
Shader *_shader;
enum {
VERT_SHADER=0,
FRAG_SHADER=1,
BOTH_SHADER=2,
};
public:
// The following declarations represent useful routines
// and constants that can be used by shader implementations.
enum {
SHADER_type_vert=0,
SHADER_type_frag=1,
SHADER_type_both=2,
};
enum {
SHADER_arg_world = -1,
SHADER_arg_camera = -2,
SHADER_arg_model = -3,
};
enum {
SHADER_data_matrix,
SHADER_data_transpose,
SHADER_data_row0,
SHADER_data_row1,
SHADER_data_row2,
SHADER_data_row3,
SHADER_data_col0,
SHADER_data_col1,
SHADER_data_col2,
SHADER_data_col3,
};
public:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -355,6 +355,25 @@ get_clip_plane() const {
return _clip_plane;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_shader
// Access: Published
// Description: This function is provided as an optimization, to
// speed up the render-time checking for the existance
// of a ShaderAttrib on this state. It returns a
// pointer to the ShaderAttrib, if there is one, or
// NULL if there is not.
////////////////////////////////////////////////////////////////////
INLINE const ShaderAttrib *RenderState::
get_shader() const {
if ((_flags & F_checked_shader) == 0) {
// We pretend this function is const, even though it transparently
// modifies the internal shader cache.
((RenderState *)this)->determine_shader();
}
return _shader;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::set_destructing
// Access: Private

View File

@ -27,6 +27,7 @@
#include "colorScaleAttrib.h"
#include "textureAttrib.h"
#include "texGenAttrib.h"
#include "shaderAttrib.h"
#include "pStatTimer.h"
#include "config_pgraph.h"
#include "bamReader.h"
@ -1663,6 +1664,21 @@ determine_clip_plane() {
_flags |= F_checked_clip_plane;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::determine_shader
// Access: Private
// Description: This is the private implementation of get_shader().
////////////////////////////////////////////////////////////////////
void RenderState::
determine_shader() {
const RenderAttrib *attrib = get_attrib(ShaderAttrib::get_class_type());
_shader = (const ShaderAttrib *)NULL;
if (attrib != (const RenderAttrib *)NULL) {
_shader = DCAST(ShaderAttrib, attrib);
}
_flags |= F_checked_shader;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::update_pstats
// Access: Private

View File

@ -41,6 +41,7 @@ class ColorScaleAttrib;
class TextureAttrib;
class TexGenAttrib;
class ClipPlaneAttrib;
class ShaderAttrib;
class FactoryParams;
////////////////////////////////////////////////////////////////////
@ -135,7 +136,8 @@ PUBLISHED:
INLINE const TexMatrixAttrib *get_tex_matrix() const;
INLINE const RenderModeAttrib *get_render_mode() const;
INLINE const ClipPlaneAttrib *get_clip_plane() const;
INLINE const ShaderAttrib *get_shader() const;
int get_geom_rendering(int geom_rendering) const;
public:
@ -180,6 +182,7 @@ private:
void determine_tex_matrix();
void determine_render_mode();
void determine_clip_plane();
void determine_shader();
INLINE void set_destructing();
INLINE bool is_destructing() const;
@ -278,7 +281,8 @@ private:
const TexMatrixAttrib *_tex_matrix;
const RenderModeAttrib *_render_mode;
const ClipPlaneAttrib *_clip_plane;
const ShaderAttrib *_shader;
enum Flags {
F_checked_bin_index = 0x0001,
F_checked_fog = 0x0002,
@ -291,6 +295,7 @@ private:
F_checked_tex_matrix = 0x0100,
F_checked_render_mode = 0x0200,
F_checked_clip_plane = 0x0400,
F_checked_shader = 0x0800,
F_is_destructing = 0x8000,
};
unsigned short _flags;