More code for shader matrix computation

This commit is contained in:
Josh Yelon 2006-03-02 22:08:48 +00:00
parent 7a4897708e
commit 5fa80f8c40
8 changed files with 375 additions and 320 deletions

View File

@ -105,8 +105,6 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
_current_lens = (Lens *)NULL;
_projection_mat = TransformState::make_identity();
_projection_mat_inv = TransformState::make_identity();
_clip_to_view = TransformState::make_identity();
_view_to_clip = TransformState::make_identity();
_needs_reset = true;
_is_valid = false;
@ -373,10 +371,6 @@ set_scene(SceneSetup *scene_setup) {
return false;
}
_projection_mat_inv = _projection_mat->get_inverse();
_view_to_clip = TransformState::make_mat(_current_lens->
get_projection_mat(_coordinate_system, _current_stereo_channel));
_clip_to_view = TransformState::make_mat(_current_lens->
get_projection_mat_inv(_coordinate_system, _current_stereo_channel));
return prepare_lens();
}
@ -677,177 +671,205 @@ clear(DrawableRegion *clearable) {
// shoehorning them into a matrix. In this way, we avoid
// the need for a separate routine to fetch these values.
//
// This routine is actually a simple pcode-interpreter,
// and the ShaderMatSpec is actually a small pcode-array.
// This makes it possible to express requests for a
// large variety of values, and a large variety of
// possible conversions.
// If "altered" is false, that means you promise that
// this ShaderMatSpec has been evaluated before, and that
// since the last time this ShaderMatSpec was evaluated,
// that no part of the render state has changed except
// the external and internal transforms.
//
////////////////////////////////////////////////////////////////////
bool GraphicsStateGuardian::
fetch_specified_value(const ShaderContext::ShaderMatSpec &spec, LMatrix4f &result) {
pvector<LMatrix4f> stack;
int pc = 0;
int ac = 0;
while (pc < (int)spec._opcodes.size()) {
int opcode = spec._opcodes[pc++];
switch(opcode) {
case ShaderContext::SMO_identity: {
stack.push_back(LMatrix4f::ident_mat());
break;
const LMatrix4f *GraphicsStateGuardian::
fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered) {
static LMatrix4f acc;
const LMatrix4f *val1;
const LMatrix4f *val2;
static LMatrix4f t1;
static LMatrix4f t2;
switch(spec._func) {
case ShaderContext::SMF_compose:
val1 = fetch_specified_part(spec._part[0], spec._arg[0], t1);
val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2);
acc.multiply(*val1, *val2);
return &acc;
case ShaderContext::SMF_compose_cache_first:
if (altered) {
spec._cache = *fetch_specified_part(spec._part[0], spec._arg[0], t1);
}
case ShaderContext::SMO_modelview: {
stack.push_back(_internal_transform->get_mat());
break;
}
case ShaderContext::SMO_projection: {
stack.push_back(_projection_mat->get_mat());
break;
}
case ShaderContext::SMO_modelproj: {
stack.push_back(_internal_transform->get_mat() * _projection_mat->get_mat());
break;
}
case ShaderContext::SMO_window_size: {
stack.push_back(LMatrix4f::translate_mat(_current_display_region->get_pixel_width(),
_current_display_region->get_pixel_height(),
0.0));
break;
}
case ShaderContext::SMO_pixel_size: {
stack.push_back(LMatrix4f::translate_mat(_current_display_region->get_pixel_width(),
_current_display_region->get_pixel_height(),
0.0));
break;
}
case ShaderContext::SMO_card_center: {
int px = _current_display_region->get_pixel_width();
int py = _current_display_region->get_pixel_height();
stack.push_back(LMatrix4f::translate_mat((px*0.5) / Texture::up_to_power_2(px),
(py*0.5) / Texture::up_to_power_2(py),
0.0));
break;
}
case ShaderContext::SMO_mat_constant_x: {
const ShaderInput *input = _target._shader->get_shader_input(spec._args[ac++]);
if (input->get_nodepath().is_empty()) {
return false;
}
stack.push_back(input->get_nodepath().node()->get_transform()->get_mat());
break;
}
case ShaderContext::SMO_vec_constant_x: {
const ShaderInput *input = _target._shader->get_shader_input(spec._args[ac++]);
const float *data = input->get_vector().get_data();
stack.push_back(LMatrix4f(data[0],data[1],data[2],data[3],
data[0],data[1],data[2],data[3],
data[0],data[1],data[2],data[3],
data[0],data[1],data[2],data[3]));
break;
}
case ShaderContext::SMO_world_to_view: {
stack.push_back(get_scene()->get_world_transform()->get_mat());
break;
}
case ShaderContext::SMO_view_to_world_C: {
stack.back() *= get_scene()->get_camera_transform()->get_mat();
break;
}
case ShaderContext::SMO_model_to_view: {
stack.push_back(_external_transform->get_mat());
break;
}
case ShaderContext::SMO_view_to_model_C: {
stack.back() *= invert(_external_transform->get_mat());
break;
}
case ShaderContext::SMO_apiview_to_view: {
stack.push_back(_inv_cs_transform->get_mat());
break;
}
case ShaderContext::SMO_view_to_apiview_C: {
stack.back() *= _cs_transform->get_mat();
break;
}
case ShaderContext::SMO_clip_to_view: {
stack.push_back(_clip_to_view->get_mat());
break;
}
case ShaderContext::SMO_view_to_clip_C: {
stack.back() *= _view_to_clip->get_mat();
break;
}
case ShaderContext::SMO_apiclip_to_view: {
stack.push_back(_projection_mat_inv->get_mat() * _inv_cs_transform->get_mat());
break;
}
case ShaderContext::SMO_view_to_apiclip_C: {
stack.back() *= _cs_transform->get_mat() * _projection_mat->get_mat();
break;
}
case ShaderContext::SMO_view_x_to_view: {
const ShaderInput *input = _target._shader->get_shader_input(spec._args[ac++]);
nassertr(!input->get_nodepath().is_empty(), false);
stack.push_back(input->get_nodepath().get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat());
break;
}
case ShaderContext::SMO_view_to_view_x_C: {
const ShaderInput *input = _target._shader->get_shader_input(spec._args[ac++]);
nassertr(!input->get_nodepath().is_empty(), false);
stack.back()*= (get_scene()->get_camera_transform()->get_mat() *
invert(input->get_nodepath().get_net_transform()->get_mat()));
break;
}
case ShaderContext::SMO_apiview_x_to_view: {
const ShaderInput *input = _target._shader->get_shader_input(spec._args[ac++]);
nassertr(!input->get_nodepath().is_empty(), false);
stack.push_back(LMatrix4f::convert_mat(_internal_coordinate_system, _coordinate_system) *
input->get_nodepath().get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat());
break;
}
case ShaderContext::SMO_view_to_apiview_x_C: {
const ShaderInput *input = _target._shader->get_shader_input(spec._args[ac++]);
nassertr(!input->get_nodepath().is_empty(), false);
stack.back()*= (get_scene()->get_camera_transform()->get_mat() *
invert(input->get_nodepath().get_net_transform()->get_mat()) *
LMatrix4f::convert_mat(_coordinate_system, _internal_coordinate_system));
break;
}
case ShaderContext::SMO_clip_x_to_view: {
const ShaderInput *input = _target._shader->get_shader_input(spec._args[ac++]);
nassertr(!input->get_nodepath().is_empty(), false);
Lens *lens = DCAST(LensNode, input->get_nodepath().node())->get_lens();
stack.push_back(lens->get_projection_mat_inv(_coordinate_system, _current_stereo_channel) *
input->get_nodepath().get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat());
break;
}
case ShaderContext::SMO_view_to_clip_x_C: {
const ShaderInput *input = _target._shader->get_shader_input(spec._args[ac++]);
nassertr(!input->get_nodepath().is_empty(), false);
Lens *lens = DCAST(LensNode, input->get_nodepath().node())->get_lens();
stack.back()*= (get_scene()->get_camera_transform()->get_mat() *
invert(input->get_nodepath().get_net_transform()->get_mat()) *
lens->get_projection_mat(_coordinate_system, _current_stereo_channel));
break;
}
case ShaderContext::SMO_apiclip_x_to_view: {
// NOT IMPLEMENTED
break;
}
case ShaderContext::SMO_view_to_apiclip_x_C: {
// NOT IMPLEMENTED
break;
val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2);
acc.multiply(spec._cache, *val2);
return &acc;
case ShaderContext::SMF_compose_cache_second:
if (altered) {
spec._cache = *fetch_specified_part(spec._part[1], spec._arg[1], t2);
}
val1 = fetch_specified_part(spec._part[0], spec._arg[0], t1);
acc.multiply(*val1, spec._cache);
return &acc;
case ShaderContext::SMF_first:
return fetch_specified_part(spec._part[0], spec._arg[0], t1);
default:
// should never get here
return &LMatrix4f::ident_mat();
}
}
case ShaderContext::SMO_transpose:
stack.back().transpose_in_place();
break;
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::fetch_specified_part
// Access: Public
// Description: See fetch_specified_value
////////////////////////////////////////////////////////////////////
const LMatrix4f *GraphicsStateGuardian::
fetch_specified_part(ShaderContext::ShaderMatInput part, InternalName *name, LMatrix4f &t) {
switch(part) {
case ShaderContext::SMO_identity: {
return &LMatrix4f::ident_mat();
}
case ShaderContext::SMO_window_size: {
t = LMatrix4f::translate_mat(_current_display_region->get_pixel_width(),
_current_display_region->get_pixel_height(),
0.0);
return &t;
}
case ShaderContext::SMO_pixel_size: {
t = LMatrix4f::translate_mat(_current_display_region->get_pixel_width(),
_current_display_region->get_pixel_height(),
0.0);
return &t;
}
case ShaderContext::SMO_card_center: {
int px = _current_display_region->get_pixel_width();
int py = _current_display_region->get_pixel_height();
t = LMatrix4f::translate_mat((px*0.5) / Texture::up_to_power_2(px),
(py*0.5) / Texture::up_to_power_2(py),
0.0);
return &t;
}
case ShaderContext::SMO_mat_constant_x: {
const ShaderInput *input = _target._shader->get_shader_input(name);
if (input->get_nodepath().is_empty()) {
return &LMatrix4f::ident_mat();
}
return &(input->get_nodepath().node()->get_transform()->get_mat());
}
case ShaderContext::SMO_vec_constant_x: {
const ShaderInput *input = _target._shader->get_shader_input(name);
const float *data = input->get_vector().get_data();
t = LMatrix4f(data[0],data[1],data[2],data[3],
data[0],data[1],data[2],data[3],
data[0],data[1],data[2],data[3],
data[0],data[1],data[2],data[3]);
return &t;
}
case ShaderContext::SMO_world_to_view: {
return &(get_scene()->get_world_transform()->get_mat());
break;
}
case ShaderContext::SMO_view_to_world: {
return &(get_scene()->get_camera_transform()->get_mat());
}
case ShaderContext::SMO_model_to_view: {
return &(_external_transform->get_mat());
}
case ShaderContext::SMO_view_to_model: {
// DANGER: SLOW AND NOT CACHEABLE!
t.invert_from(_external_transform->get_mat());
return &t;
}
case ShaderContext::SMO_apiview_to_view: {
return &(_inv_cs_transform->get_mat());
}
case ShaderContext::SMO_view_to_apiview: {
return &(_cs_transform->get_mat());
}
case ShaderContext::SMO_clip_to_view: {
if (_current_lens->get_coordinate_system() == _coordinate_system) {
return &(_current_lens->get_projection_mat_inv(_current_stereo_channel));
} else {
t = _current_lens->get_projection_mat_inv(_current_stereo_channel) *
LMatrix4f::convert_mat(_current_lens->get_coordinate_system(), _coordinate_system);
return &t;
}
}
result = stack.back();
return true;
case ShaderContext::SMO_view_to_clip: {
if (_current_lens->get_coordinate_system() == _coordinate_system) {
return &(_current_lens->get_projection_mat(_current_stereo_channel));
} else {
t = LMatrix4f::convert_mat(_coordinate_system, _current_lens->get_coordinate_system()) *
_current_lens->get_projection_mat(_current_stereo_channel);
return &t;
}
}
case ShaderContext::SMO_apiclip_to_view: {
t = _projection_mat_inv->get_mat() * _inv_cs_transform->get_mat();
return &t;
}
case ShaderContext::SMO_view_to_apiclip: {
t = _cs_transform->get_mat() * _projection_mat->get_mat();
return &t;
}
case ShaderContext::SMO_view_x_to_view: {
const ShaderInput *input = _target._shader->get_shader_input(name);
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
t = input->get_nodepath().get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat();
return &t;
}
case ShaderContext::SMO_view_to_view_x: {
const ShaderInput *input = _target._shader->get_shader_input(name);
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
t = get_scene()->get_camera_transform()->get_mat() *
invert(input->get_nodepath().get_net_transform()->get_mat());
return &t;
}
case ShaderContext::SMO_apiview_x_to_view: {
const ShaderInput *input = _target._shader->get_shader_input(name);
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
t = LMatrix4f::convert_mat(_internal_coordinate_system, _coordinate_system) *
input->get_nodepath().get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat();
return &t;
}
case ShaderContext::SMO_view_to_apiview_x: {
const ShaderInput *input = _target._shader->get_shader_input(name);
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
t = (get_scene()->get_camera_transform()->get_mat() *
invert(input->get_nodepath().get_net_transform()->get_mat()) *
LMatrix4f::convert_mat(_coordinate_system, _internal_coordinate_system));
return &t;
}
case ShaderContext::SMO_clip_x_to_view: {
const ShaderInput *input = _target._shader->get_shader_input(name);
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
Lens *lens = DCAST(LensNode, input->get_nodepath().node())->get_lens();
t = lens->get_projection_mat_inv(_current_stereo_channel) *
LMatrix4f::convert_mat(lens->get_coordinate_system(), _coordinate_system) *
input->get_nodepath().get_net_transform()->get_mat() *
get_scene()->get_world_transform()->get_mat();
return &t;
}
case ShaderContext::SMO_view_to_clip_x: {
const ShaderInput *input = _target._shader->get_shader_input(name);
nassertr(!input->get_nodepath().is_empty(), &LMatrix4f::ident_mat());
Lens *lens = DCAST(LensNode, input->get_nodepath().node())->get_lens();
t = get_scene()->get_camera_transform()->get_mat() *
invert(input->get_nodepath().get_net_transform()->get_mat()) *
LMatrix4f::convert_mat(_coordinate_system, lens->get_coordinate_system()) *
lens->get_projection_mat(_current_stereo_channel);
return &t;
}
case ShaderContext::SMO_apiclip_x_to_view: {
// NOT IMPLEMENTED
return &LMatrix4f::ident_mat();
}
case ShaderContext::SMO_view_to_apiclip_x: {
// NOT IMPLEMENTED
return &LMatrix4f::ident_mat();
}
default:
// should never get here
return &LMatrix4f::ident_mat();
}
}
////////////////////////////////////////////////////////////////////

View File

@ -159,7 +159,8 @@ public:
void clear(DrawableRegion *clearable);
bool fetch_specified_value(const ShaderContext::ShaderMatSpec &spec, LMatrix4f &result);
const LMatrix4f *fetch_specified_value(ShaderContext::ShaderMatSpec &spec, bool altered);
const LMatrix4f *fetch_specified_part(ShaderContext::ShaderMatInput input, InternalName *name, LMatrix4f &t);
virtual void prepare_display_region(DisplayRegion *dr,
Lens::StereoChannel stereo_channel);
@ -295,8 +296,6 @@ protected:
CPT(Lens) _current_lens;
CPT(TransformState) _projection_mat;
CPT(TransformState) _projection_mat_inv;
CPT(TransformState) _view_to_clip;
CPT(TransformState) _clip_to_view;
CoordinateSystem _coordinate_system;
CoordinateSystem _internal_coordinate_system;

View File

@ -2763,8 +2763,9 @@ do_issue_transform() {
do_auto_rescale_normal();
}
if (_current_shader_context)
if (_current_shader_context) {
_current_shader_context->issue_parameters(this, false);
}
report_my_gl_errors();
}

View File

@ -442,13 +442,17 @@ unbind()
// Description: This function gets called whenever the RenderState
// or TransformState has changed, but the ShaderExpansion
// itself has not changed. It loads new values into the
// shader's parameters. The flag "all" is false if the
// only thing that has changed is the modelview matrix.
// In this case, only the transform-dependent parameters
// are reloaded.
// shader's parameters.
//
// If "altered" is false, that means you promise that
// the parameters for this shader context have already
// been issued once, and that since the last time the
// parameters were issued, no part of the render
// state has changed except the external and internal
// transforms.
////////////////////////////////////////////////////////////////////
void CLP(ShaderContext)::
issue_parameters(GSG *gsg, bool all)
issue_parameters(GSG *gsg, bool altered)
{
#ifdef HAVE_CGGL
if (_cg_context == 0) {
@ -456,11 +460,11 @@ issue_parameters(GSG *gsg, bool all)
}
for (int i=0; i<(int)_mat_spec.size(); i++) {
if (all || _mat_spec[i]._trans_dependent) {
LMatrix4f result;
if (altered || _mat_spec[i]._trans_dependent) {
CGparameter p = (CGparameter)(_mat_spec[i]._parameter);
if (gsg->fetch_specified_value(_mat_spec[i], result)) {
const float *data = result.get_data();
const LMatrix4f *val = gsg->fetch_specified_value(_mat_spec[i], altered);
if (val) {
const float *data = val->get_data();
switch (_mat_spec[i]._piece) {
case SMP_whole: cgGLSetMatrixParameterfc(p, data); break;
case SMP_transpose: cgGLSetMatrixParameterfr(p, data); break;

View File

@ -443,34 +443,3 @@ operator << (ostream &out, const Lens &lens) {
return out;
}
////////////////////////////////////////////////////////////////////
// Function: Lens::get_projection_mat
// Access: Published
// Description: Returns the complete transformation matrix from a 3-d
// point in space to a point on the film, if such a
// matrix exists, or the identity matrix if the lens is
// nonlinear, in the specified coordinate system.
////////////////////////////////////////////////////////////////////
const LMatrix4f Lens::
get_projection_mat(CoordinateSystem cs, StereoChannel channel) const {
return
LMatrix4f::convert_mat(cs, _cs) *
get_projection_mat(channel) *
LMatrix4f::convert_mat(CS_yup_right, cs);
}
////////////////////////////////////////////////////////////////////
// Function: Lens::get_projection_mat_inv
// Access: Published
// Description: Returns the matrix that transforms from a 2-d point
// on the film to a 3-d vector in space, if such a
// matrix exists, in the specified coordinate system.
////////////////////////////////////////////////////////////////////
const LMatrix4f Lens::
get_projection_mat_inv(CoordinateSystem cs, StereoChannel channel) const {
return
LMatrix4f::convert_mat(cs, CS_yup_right) *
get_projection_mat_inv(channel) *
LMatrix4f::convert_mat(_cs, cs);
}

View File

@ -155,9 +155,6 @@ PUBLISHED:
const LMatrix4f &get_projection_mat(StereoChannel channel = SC_mono) const;
const LMatrix4f &get_projection_mat_inv(StereoChannel channel = SC_mono) const;
INLINE const LMatrix4f get_projection_mat(CoordinateSystem cs, StereoChannel channel) const;
INLINE const LMatrix4f get_projection_mat_inv(CoordinateSystem cs, StereoChannel channel) const;
const LMatrix4f &get_film_mat() const;
const LMatrix4f &get_film_mat_inv() const;

View File

@ -171,35 +171,88 @@ cp_errchk_parameter_sampler(ShaderArgInfo &p)
}
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::cp_parse_trans_clause
// Function: ShaderContext::cp_parse_trans_clause
// Access: Public
// Description: Parses a single clause of a "trans" parameter.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
cp_parse_trans_clause(ShaderArgInfo &p, ShaderMatSpec &spec, const vector_string &pieces,
int &next, ShaderMatOp ofop, ShaderMatOp op) {
cp_parse_trans_clause(ShaderArgInfo &p, ShaderMatSpec &spec,
int part, const vector_string &pieces,
int &next, ShaderMatInput ofop, ShaderMatInput op) {
if (pieces[next+1]=="of") {
if (pieces[next+2]=="") {
cp_report_error(p, "'of' should be followed by a name");
return false;
}
if (ofop != SMO_noop) {
spec._opcodes.push_back(ofop);
spec._args.push_back(InternalName::make(pieces[next+2]));
}
spec._part[part] = ofop;
spec._arg[part] = InternalName::make(pieces[next+2]);
next += 3;
return true;
} else {
if (op != SMO_noop) {
spec._opcodes.push_back(op);
}
spec._part[part] = op;
spec._arg[part] = NULL;
next += 1;
return true;
}
}
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::compile_parameter
// Function: ShaderContext::cp_optimize_mat_spec
// Access: Public
// Description: Analyzes a ShaderMatSpec and decides what it should
// use its cache for. It can cache the results of any
// one opcode, or, it can cache the entire result. This
// routine needs to be smart enough to know which
// data items can be correctly cached, and which cannot.
////////////////////////////////////////////////////////////////////
void ShaderContext::
cp_optimize_mat_spec(ShaderMatSpec &spec) {
// If we're composing with identity, simplify.
if (spec._func == SMF_compose) {
if (spec._part[1] == SMO_identity) {
spec._func = SMF_first;
}
}
if (spec._func == SMF_compose) {
if (spec._part[0] == SMO_identity) {
spec._func = SMF_first;
spec._part[0] = spec._part[1];
spec._arg[0] = spec._arg[1];
}
}
// See if either half can be cached.
bool can_cache_part0 = true;
bool can_cache_part1 = true;
if ((spec._part[0] == SMO_model_to_view)||
(spec._part[0] == SMO_view_to_model)) {
can_cache_part0 = false;
}
if ((spec._part[1] == SMO_model_to_view)||
(spec._part[1] == SMO_view_to_model)) {
can_cache_part1 = false;
}
// See if we can use a compose-with-cache variant.
if (spec._func == SMF_compose) {
if (can_cache_part0) {
spec._func = SMF_compose_cache_first;
} else if (can_cache_part1) {
spec._func = SMF_compose_cache_second;
}
}
// Determine transform-dependence.
if (can_cache_part0 && can_cache_part1) {
spec._trans_dependent = false;
} else {
spec._trans_dependent = true;
}
}
////////////////////////////////////////////////////////////////////
// Function: ShaderContext::compile_parameter
// Access: Public
// Description: Analyzes a parameter and decides how to
// bind the parameter to some part of panda's
@ -377,14 +430,14 @@ compile_parameter(void *reference,
ShaderMatSpec bind;
bind._parameter = reference;
bind._trans_dependent = false;
bind._func = SMF_compose;
int next = 1;
pieces.push_back("");
// Decide whether this is a matrix or vector.
if (pieces[0]=="trans") bind._piece = SMP_whole;
else if (pieces[0]=="tpose") bind._piece = SMP_whole;
else if (pieces[0]=="tpose") bind._piece = SMP_transpose;
else if (pieces[0]=="row0") bind._piece = SMP_row0;
else if (pieces[0]=="row1") bind._piece = SMP_row1;
else if (pieces[0]=="row2") bind._piece = SMP_row2;
@ -393,7 +446,7 @@ compile_parameter(void *reference,
else if (pieces[0]=="col1") bind._piece = SMP_col1;
else if (pieces[0]=="col2") bind._piece = SMP_col2;
else if (pieces[0]=="col3") bind._piece = SMP_col3;
if (bind._piece == SMP_whole) {
if ((bind._piece == SMP_whole)||(bind._piece == SMP_transpose)) {
if (!cp_errchk_parameter_float(p, 16, 16)) return false;
} else {
if (!cp_errchk_parameter_float(p, 4, 4)) return false;
@ -405,21 +458,22 @@ compile_parameter(void *reference,
cp_report_error(p, "argument missing");
return false;
} else if (pieces[next] == "world") {
bind._opcodes.push_back(SMO_world_to_view);
bind._part[0] = SMO_world_to_view;
bind._arg[0] = NULL;
next += 1;
} else if (pieces[next] == "model") {
ok &= cp_parse_trans_clause(p, bind, pieces, next, SMO_view_x_to_view, SMO_model_to_view);
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_view_x_to_view, SMO_model_to_view);
} else if (pieces[next] == "clip") {
ok &= cp_parse_trans_clause(p, bind, pieces, next, SMO_clip_x_to_view, SMO_clip_to_view);
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_clip_x_to_view, SMO_clip_to_view);
} else if (pieces[next] == "view") {
ok &= cp_parse_trans_clause(p, bind, pieces, next, SMO_view_x_to_view, SMO_identity);
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_view_x_to_view, SMO_identity);
} else if (pieces[next] == "apiview") {
ok &= cp_parse_trans_clause(p, bind, pieces, next, SMO_apiview_x_to_view, SMO_apiview_to_view);
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_apiview_x_to_view, SMO_apiview_to_view);
} else if (pieces[next] == "apiclip") {
ok &= cp_parse_trans_clause(p, bind, pieces, next, SMO_apiclip_x_to_view, SMO_apiclip_to_view);
ok &= cp_parse_trans_clause(p, bind, 0, pieces, next, SMO_apiclip_x_to_view, SMO_apiclip_to_view);
} else {
bind._opcodes.push_back(SMO_view_x_to_view);
bind._args.push_back(InternalName::make(pieces[next]));
bind._part[0] = SMO_view_x_to_view;
bind._arg[0] = InternalName::make(pieces[next]);
next += 1;
}
@ -428,11 +482,6 @@ compile_parameter(void *reference,
return false;
}
// Check for transform-dependence.
if (bind._opcodes.back() == SMO_model_to_view) {
bind._trans_dependent = true;
}
// Check for syntactic well-formed-ness.
if (pieces[next] != "to") {
cp_report_error(p, "keyword 'to' expected");
@ -446,21 +495,22 @@ compile_parameter(void *reference,
cp_report_error(p, "argument missing");
return false;
} else if (pieces[next] == "world") {
bind._opcodes.push_back(SMO_view_to_world_C);
bind._part[1] = SMO_view_to_world;
bind._arg[1] = NULL;
next += 1;
} else if (pieces[next] == "model") {
ok &= cp_parse_trans_clause(p, bind, pieces, next, SMO_view_to_view_x_C, SMO_view_to_model_C);
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_view_x, SMO_view_to_model);
} else if (pieces[next] == "clip") {
ok &= cp_parse_trans_clause(p, bind, pieces, next, SMO_view_to_clip_x_C, SMO_view_to_clip_C);
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_clip_x, SMO_view_to_clip);
} else if (pieces[next] == "view") {
ok &= cp_parse_trans_clause(p, bind, pieces, next, SMO_view_to_view_x_C, SMO_noop);
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_view_x, SMO_identity);
} else if (pieces[next] == "apiview") {
ok &= cp_parse_trans_clause(p, bind, pieces, next, SMO_view_to_apiview_x_C, SMO_view_to_apiview_C);
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_apiview_x, SMO_view_to_apiview);
} else if (pieces[next] == "apiclip") {
ok &= cp_parse_trans_clause(p, bind, pieces, next, SMO_view_to_apiclip_x_C, SMO_view_to_apiclip_C);
ok &= cp_parse_trans_clause(p, bind, 1, pieces, next, SMO_view_to_apiclip_x, SMO_view_to_apiclip);
} else {
bind._opcodes.push_back(SMO_view_to_view_x_C);
bind._args.push_back(InternalName::make(pieces[next]));
bind._part[1] = SMO_view_to_view_x;
bind._arg[1] = InternalName::make(pieces[next]);
next += 1;
}
@ -469,17 +519,13 @@ compile_parameter(void *reference,
return false;
}
// Check for transform-dependence.
if (bind._opcodes.back() == SMO_view_to_model_C) {
bind._trans_dependent = true;
}
// Check for syntactic well-formed-ness.
if (pieces[next] != "") {
cp_report_error(p, "end of line expected");
return false;
}
cp_optimize_mat_spec(bind);
_mat_spec.push_back(bind);
return true;
}
@ -494,27 +540,34 @@ compile_parameter(void *reference,
}
ShaderMatSpec bind;
bind._parameter = reference;
bind._trans_dependent = false;
bind._piece = SMP_row3;
bind._func = SMF_first;
bind._part[1] = SMO_identity;
bind._arg[1] = NULL;
if (pieces[1] == "pixelsize") {
if (!cp_errchk_parameter_float(p, 2, 2)) {
return false;
}
bind._opcodes.push_back(SMO_pixel_size);
bind._part[0] = SMO_pixel_size;
bind._arg[0] = NULL;
} else if (pieces[1] == "windowsize") {
if (!cp_errchk_parameter_float(p, 2, 2)) {
return false;
}
bind._opcodes.push_back(SMO_window_size);
bind._part[0] = SMO_window_size;
bind._arg[0] = NULL;
} else if (pieces[1] == "cardcenter") {
if (!cp_errchk_parameter_float(p, 2, 2)) {
return false;
}
bind._opcodes.push_back(SMO_card_center);
bind._part[0] = SMO_card_center;
bind._arg[0] = NULL;
} else {
cp_report_error(p,"unknown system parameter");
return false;
}
cp_optimize_mat_spec(bind);
_mat_spec.push_back(bind);
return true;
}
@ -561,20 +614,26 @@ compile_parameter(void *reference,
case SAT_float4: {
ShaderMatSpec bind;
bind._parameter = reference;
bind._trans_dependent = false;
bind._piece = SMP_row3;
bind._opcodes.push_back(SMO_vec_constant_x);
bind._args.push_back(InternalName::make(pieces[1]));
bind._func = SMF_first;
bind._part[0] = SMO_vec_constant_x;
bind._arg[0] = InternalName::make(pieces[1]);
bind._part[1] = SMO_identity;
bind._arg[1] = NULL;
cp_optimize_mat_spec(bind);
_mat_spec.push_back(bind);
break;
}
case SAT_float4x4: {
ShaderMatSpec bind;
bind._parameter = reference;
bind._trans_dependent = false;
bind._piece = SMP_whole;
bind._opcodes.push_back(SMO_mat_constant_x);
bind._args.push_back(InternalName::make(pieces[1]));
bind._func = SMF_first;
bind._part[0] = SMO_vec_constant_x;
bind._arg[0] = InternalName::make(pieces[1]);
bind._part[1] = SMO_identity;
bind._arg[1] = NULL;
cp_optimize_mat_spec(bind);
_mat_spec.push_back(bind);
break;
}

View File

@ -49,6 +49,44 @@ public:
SHADER_type_both=2,
};
enum ShaderMatInput {
SMO_identity,
SMO_window_size,
SMO_pixel_size,
SMO_card_center,
SMO_mat_constant_x,
SMO_vec_constant_x,
SMO_world_to_view,
SMO_view_to_world,
SMO_model_to_view,
SMO_view_to_model,
SMO_apiview_to_view,
SMO_view_to_apiview,
SMO_clip_to_view,
SMO_view_to_clip,
SMO_apiclip_to_view,
SMO_view_to_apiclip,
SMO_view_x_to_view,
SMO_view_to_view_x,
SMO_apiview_x_to_view,
SMO_view_to_apiview_x,
SMO_clip_x_to_view,
SMO_view_to_clip_x,
SMO_apiclip_x_to_view,
SMO_view_to_apiclip_x,
};
enum ShaderArgType {
SAT_float1,
SAT_float2,
@ -69,51 +107,6 @@ public:
SAD_unknown,
};
enum ShaderMatOp {
SMO_identity,
SMO_modelview,
SMO_projection,
SMO_modelproj,
SMO_window_size,
SMO_pixel_size,
SMO_card_center,
SMO_mat_constant_x,
SMO_vec_constant_x,
SMO_world_to_view,
SMO_view_to_world_C,
SMO_model_to_view,
SMO_view_to_model_C,
SMO_apiview_to_view,
SMO_view_to_apiview_C,
SMO_clip_to_view,
SMO_view_to_clip_C,
SMO_apiclip_to_view,
SMO_view_to_apiclip_C,
SMO_view_x_to_view,
SMO_view_to_view_x_C,
SMO_apiview_x_to_view,
SMO_view_to_apiview_x_C,
SMO_clip_x_to_view,
SMO_view_to_clip_x_C,
SMO_apiclip_x_to_view,
SMO_view_to_apiclip_x_C,
SMO_transpose,
SMO_noop,
};
enum ShaderMatPiece {
SMP_whole,
SMP_transpose,
@ -127,12 +120,21 @@ public:
SMP_col3,
};
enum ShaderMatFunc {
SMF_compose,
SMF_compose_cache_first,
SMF_compose_cache_second,
SMF_first,
};
struct ShaderMatSpec {
pvector<ShaderMatOp> _opcodes;
pvector<PT(InternalName)> _args;
ShaderMatPiece _piece;
bool _trans_dependent;
void *_parameter;
ShaderMatFunc _func;
ShaderMatInput _part[2];
PT(InternalName) _arg[2];
LMatrix4f _cache;
ShaderMatPiece _piece;
bool _trans_dependent;
void *_parameter;
};
struct ShaderTexSpec {
@ -174,10 +176,12 @@ private:
bool cp_errchk_parameter_sampler(ShaderArgInfo &arg);
bool cp_parse_trans_clause(ShaderArgInfo &arg,
ShaderMatSpec &spec,
int part,
const vector_string &pieces,
int &next,
ShaderMatOp ofop,
ShaderMatOp op);
ShaderMatInput ofop,
ShaderMatInput op);
void cp_optimize_mat_spec(ShaderMatSpec &spec);
protected:
bool compile_parameter(void *reference,