Major overhaul to shader subsystem

This commit is contained in:
Josh Yelon 2006-02-27 21:52:36 +00:00
parent 43bbca86fb
commit 129cef9f62
12 changed files with 1261 additions and 1038 deletions

View File

@ -2296,7 +2296,7 @@ EnqueueIgate(ipath=IPATH, opts=OPTS, outd='libpstatclient.in', obj='libpstatclie
#
IPATH=['panda/src/gobj']
OPTS=['BUILDING_PANDA', 'NSPR']
OPTS=['BUILDING_PANDA', 'NSPR', 'NVIDIACG']
CopyAllHeaders('panda/src/gobj')
EnqueueCxx(ipath=IPATH, opts=OPTS, src='gobj_composite1.cxx', obj='gobj_composite1.obj')
EnqueueCxx(ipath=IPATH, opts=OPTS, src='gobj_composite2.cxx', obj='gobj_composite2.obj')
@ -2572,7 +2572,7 @@ CopyAllHeaders('panda/src/physics')
CopyAllHeaders('panda/src/particlesystem')
IPATH=['panda/metalibs/panda']
OPTS=['BUILDING_PANDA', 'ZLIB', 'VRPN', 'JPEG', 'PNG', 'TIFF', 'NSPR', 'FREETYPE', 'HELIX', 'FFTW', 'OPENCV',
'ADVAPI', 'WINSOCK2', 'WINUSER', 'WINMM']
'ADVAPI', 'WINSOCK2', 'WINUSER', 'WINMM', 'NVIDIACG']
INFILES=['librecorder.in', 'libpgraph.in', 'libgrutil.in', 'libchan.in', 'libpstatclient.in',
'libchar.in', 'libcollide.in', 'libdevice.in', 'libdgraph.in', 'libdisplay.in', 'libevent.in',
'libgobj.in', 'libgsgbase.in', 'liblinmath.in', 'libmathutil.in', 'libparametrics.in',

View File

@ -103,6 +103,11 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
_current_display_region = (DisplayRegion*)0L;
_current_stereo_channel = Lens::SC_mono;
_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;
_closing_gsg = false;
@ -363,6 +368,15 @@ set_scene(SceneSetup *scene_setup) {
return false;
}
_projection_mat = calc_projection_mat(_current_lens);
if (_projection_mat == 0) {
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();
}
@ -636,6 +650,206 @@ clear(DrawableRegion *clearable) {
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::fetch_specified_value
// Access: Public
// Description: The gsg contains a large number of useful matrices:
//
// * the world transform,
// * the modelview matrix,
// * the cs_transform,
// * etc, etc.
//
// A shader can request any of these values, and
// furthermore, it can request that various compositions,
// inverses, and transposes be performed. The
// ShaderMatSpec is a data structure indicating what
// datum is desired and what conversions to perform.
// This routine, fetch_specified_value, is responsible for
// doing the actual retrieval and conversions.
//
// Some values, like the following, aren't matrices:
//
// * window size
// * texture coordinates of card center
//
// This routine can fetch these values as well, by
// 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.
////////////////////////////////////////////////////////////////////
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;
}
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;
}
case ShaderContext::SMO_transpose:
stack.back().transpose_in_place();
break;
}
}
result = stack.back();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::prepare_display_region
// Access: Public, Virtual
@ -1832,3 +2046,24 @@ traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),vo
return;
}
}
////////////////////////////////////////////////////////////////////
// Function: GraphicsStateGuardian::calc_projection_mat
// Access: Public, Virtual
// Description: Given a lens, this function calculates the appropriate
// projection matrix for this gsg. The result depends
// on the peculiarities of the rendering API.
////////////////////////////////////////////////////////////////////
CPT(TransformState) GraphicsStateGuardian::
calc_projection_mat(const Lens *lens) {
if (lens == (Lens *)NULL) {
return NULL;
}
if (!lens->is_linear()) {
return NULL;
}
return TransformState::make_identity();
}

View File

@ -42,6 +42,7 @@
#include "notify.h"
#include "pvector.h"
#include "attribSlots.h"
#include "shaderContext.h"
class DrawableRegion;
class GraphicsEngine;
@ -158,8 +159,12 @@ public:
void clear(DrawableRegion *clearable);
bool fetch_specified_value(const ShaderContext::ShaderMatSpec &spec, LMatrix4f &result);
virtual void prepare_display_region(DisplayRegion *dr,
Lens::StereoChannel stereo_channel);
virtual CPT(TransformState) calc_projection_mat(const Lens *lens);
virtual bool prepare_lens();
virtual bool begin_frame();
@ -198,7 +203,7 @@ public:
INLINE const TransformState *get_cs_transform() const;
INLINE const TransformState *get_inv_cs_transform() const;
void do_issue_clip_plane();
void do_issue_color();
void do_issue_color_scale();
@ -288,7 +293,11 @@ protected:
CPT(DisplayRegion) _current_display_region;
Lens::StereoChannel _current_stereo_channel;
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;
CPT(TransformState) _cs_transform;

View File

@ -2058,22 +2058,22 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
data = total->get_mat().get_data();
switch (stb.trans_piece) {
/*
case SHADER_data_matrix: cgD3D9SetMatrixParameterfc(stb.parameter, data); break;
case SHADER_data_transpose: cgD3D9SetMatrixParameterfr(stb.parameter, data); break;
case SHADER_data_row0: cgD3D9SetParameter4fv(stb.parameter, data+ 0); break;
case SHADER_data_row1: cgD3D9SetParameter4fv(stb.parameter, data+ 4); break;
case SHADER_data_row2: cgD3D9SetParameter4fv(stb.parameter, data+ 8); break;
case SHADER_data_row3: cgD3D9SetParameter4fv(stb.parameter, data+12); break;
case SHADER_data_col0: cgD3D9SetParameter4f(stb.parameter, data[0], data[4], data[ 8], data[12]); break;
case SHADER_data_col1: cgD3D9SetParameter4f(stb.parameter, data[1], data[5], data[ 9], data[13]); break;
case SHADER_data_col2: cgD3D9SetParameter4f(stb.parameter, data[2], data[6], data[10], data[14]); break;
case SHADER_data_col3: cgD3D9SetParameter4f(stb.parameter, data[3], data[7], data[11], data[15]); break;
case SMP_whole: cgD3D9SetMatrixParameterfc(stb.parameter, data); break;
case SMP_transpose: cgD3D9SetMatrixParameterfr(stb.parameter, data); break;
case SMP_row0: cgD3D9SetParameter4fv(stb.parameter, data+ 0); break;
case SMP_row1: cgD3D9SetParameter4fv(stb.parameter, data+ 4); break;
case SMP_row2: cgD3D9SetParameter4fv(stb.parameter, data+ 8); break;
case SMP_row3: cgD3D9SetParameter4fv(stb.parameter, data+12); break;
case SMP_col0: cgD3D9SetParameter4f(stb.parameter, data[0], data[4], data[ 8], data[12]); break;
case SMP_col1: cgD3D9SetParameter4f(stb.parameter, data[1], data[5], data[ 9], data[13]); break;
case SMP_col2: cgD3D9SetParameter4f(stb.parameter, data[2], data[6], data[10], data[14]); break;
case SMP_col3: cgD3D9SetParameter4f(stb.parameter, data[3], data[7], data[11], data[15]); break;
*/
float vector [4];
float matrix [16];
case SHADER_data_matrix:
case SMP_whole:
if (_cg_shader) {
cgD3D9SetUniform (stb.parameter, data);
}
@ -2081,7 +2081,7 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
set_dx_shader_parameter_float (stb.dx_parameter, data, gsg -> _d3d_device);
}
break;
case SHADER_data_transpose:
case SMP_transpose:
matrix [0] = data[0];
matrix [1] = data[4];
matrix [2] = data[8];
@ -2105,7 +2105,7 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
set_dx_shader_parameter_float (stb.dx_parameter, matrix, gsg -> _d3d_device);
}
break;
case SHADER_data_row0:
case SMP_row0:
if (_cg_shader) {
cgD3D9SetUniform (stb.parameter, data);
}
@ -2113,7 +2113,7 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
set_dx_shader_parameter_float (stb.dx_parameter, data, gsg -> _d3d_device);
}
break;
case SHADER_data_row1:
case SMP_row1:
if (_cg_shader) {
cgD3D9SetUniform (stb.parameter, data + 4);
}
@ -2121,7 +2121,7 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
set_dx_shader_parameter_float (stb.dx_parameter, data + 4, gsg -> _d3d_device);
}
break;
case SHADER_data_row2:
case SMP_row2:
if (_cg_shader) {
cgD3D9SetUniform (stb.parameter, data + 8);
}
@ -2129,7 +2129,7 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
set_dx_shader_parameter_float (stb.dx_parameter, data + 8, gsg -> _d3d_device);
}
break;
case SHADER_data_row3:
case SMP_row3:
if (_cg_shader) {
cgD3D9SetUniform (stb.parameter, data + 12);
}
@ -2137,7 +2137,7 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
set_dx_shader_parameter_float (stb.dx_parameter, data + 12, gsg -> _d3d_device);
}
break;
case SHADER_data_col0:
case SMP_col0:
vector [0] = data[0];
vector [1] = data[4];
vector [2] = data[8];
@ -2149,7 +2149,7 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
set_dx_shader_parameter_float (stb.dx_parameter, vector, gsg -> _d3d_device);
}
break;
case SHADER_data_col1:
case SMP_col1:
vector [0] = data[1];
vector [1] = data[5];
vector [2] = data[9];
@ -2161,7 +2161,7 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
set_dx_shader_parameter_float (stb.dx_parameter, vector, gsg -> _d3d_device);
}
break;
case SHADER_data_col2:
case SMP_col2:
vector [0] = data[2];
vector [1] = data[6];
vector [2] = data[10];
@ -2173,7 +2173,7 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg)
set_dx_shader_parameter_float (stb.dx_parameter, vector, gsg -> _d3d_device);
}
break;
case SHADER_data_col3:
case SMP_col3:
vector [0] = data[3];
vector [1] = data[7];
vector [2] = data[11];
@ -2499,21 +2499,21 @@ compile_cg_parameter(CGparameter p, DX_PARAMETER *dx_parameter)
bind.parameter = p;
bind.dx_parameter = dx_parameter;
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[0]=="trans") bind.trans_piece = SMP_whole;
else if (pieces[0]=="tpose") bind.trans_piece = SMP_transpose;
else if (pieces[0]=="row0") bind.trans_piece = SMP_row0;
else if (pieces[0]=="row1") bind.trans_piece = SMP_row1;
else if (pieces[0]=="row2") bind.trans_piece = SMP_row2;
else if (pieces[0]=="row3") bind.trans_piece = SMP_row3;
else if (pieces[0]=="col0") bind.trans_piece = SMP_col0;
else if (pieces[0]=="col1") bind.trans_piece = SMP_col1;
else if (pieces[0]=="col2") bind.trans_piece = SMP_col2;
else if (pieces[0]=="col3") bind.trans_piece = SMP_col3;
bind.src_name = InternalName::make(pieces[1]);
bind.rel_name = InternalName::make(pieces[3]);
if ((bind.trans_piece == SHADER_data_matrix)||(bind.trans_piece == SHADER_data_transpose)) {
if ((bind.trans_piece == SMP_whole)||(bind.trans_piece == SMP_transpose)) {
if (!errchk_cg_parameter_type(p, CG_FLOAT4x4)) return false;
} else {
if (!errchk_cg_parameter_type(p, CG_FLOAT4)) return false;
@ -2541,18 +2541,18 @@ compile_cg_parameter(CGparameter p, DX_PARAMETER *dx_parameter)
bind.parameter = p;
bind.dx_parameter = dx_parameter;
if (pieces[0]=="wstrans") { bind.rel_name = InternalName::get_world(); bind.trans_piece = SHADER_data_matrix; }
else if (pieces[0]=="vstrans") { bind.rel_name = InternalName::get_view(); bind.trans_piece = SHADER_data_matrix; }
else if (pieces[0]=="cstrans") { bind.rel_name = InternalName::get_camera(); bind.trans_piece = SHADER_data_matrix; }
else if (pieces[0]=="mstrans") { bind.rel_name = InternalName::get_model(); bind.trans_piece = SHADER_data_matrix; }
else if (pieces[0]=="wspos") { bind.rel_name = InternalName::get_world(); bind.trans_piece = SHADER_data_row3; }
else if (pieces[0]=="vspos") { bind.rel_name = InternalName::get_view(); bind.trans_piece = SHADER_data_row3; }
else if (pieces[0]=="cspos") { bind.rel_name = InternalName::get_camera(); bind.trans_piece = SHADER_data_row3; }
else if (pieces[0]=="mspos") { bind.rel_name = InternalName::get_model(); bind.trans_piece = SHADER_data_row3; }
if (pieces[0]=="wstrans") { bind.rel_name = InternalName::get_world(); bind.trans_piece = SMP_whole; }
else if (pieces[0]=="vstrans") { bind.rel_name = InternalName::get_view(); bind.trans_piece = SMP_whole; }
else if (pieces[0]=="cstrans") { bind.rel_name = InternalName::get_camera(); bind.trans_piece = SMP_whole; }
else if (pieces[0]=="mstrans") { bind.rel_name = InternalName::get_model(); bind.trans_piece = SMP_whole; }
else if (pieces[0]=="wspos") { bind.rel_name = InternalName::get_world(); bind.trans_piece = SMP_row3; }
else if (pieces[0]=="vspos") { bind.rel_name = InternalName::get_view(); bind.trans_piece = SMP_row3; }
else if (pieces[0]=="cspos") { bind.rel_name = InternalName::get_camera(); bind.trans_piece = SMP_row3; }
else if (pieces[0]=="mspos") { bind.rel_name = InternalName::get_model(); bind.trans_piece = SMP_row3; }
bind.src_name = InternalName::make(pieces[1]);
if ((bind.trans_piece == SHADER_data_matrix)||(bind.trans_piece == SHADER_data_transpose)) {
if ((bind.trans_piece == SMP_whole)||(bind.trans_piece == SMP_transpose)) {
if (!errchk_cg_parameter_type(p, CG_FLOAT4x4)) return false;
} else {
if (!errchk_cg_parameter_type(p, CG_FLOAT4)) return false;

View File

@ -845,8 +845,6 @@ reset() {
<< "max clip planes = " << _max_clip_planes << "\n";
}
_projection_mat = LMatrix4f::ident_mat();
if (_supports_multitexture) {
GLint max_texture_stages;
GLP(GetIntegerv)(GL_MAX_TEXTURE_UNITS, &max_texture_stages);
@ -986,6 +984,48 @@ prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel) {
do_point_size();
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::calc_projection_mat
// Access: Public, Virtual
// Description: Given a lens, calculates the appropriate projection
// matrix for use with this gsg. Note that the
// projection matrix depends a lot upon the coordinate
// system of the rendering API.
//
// The return value is a TransformState if the lens is
// acceptable, NULL if it is not.
////////////////////////////////////////////////////////////////////
CPT(TransformState) CLP(GraphicsStateGuardian)::
calc_projection_mat(const Lens *lens) {
if (lens == (Lens *)NULL) {
return NULL;
}
if (!lens->is_linear()) {
return NULL;
}
// The projection matrix must always be right-handed Y-up, even if
// our coordinate system of choice is otherwise, because certain GL
// calls (specifically glTexGen(GL_SPHERE_MAP)) assume this kind of
// a coordinate system. Sigh. In order to implement a Z-up (or
// other arbitrary) coordinate system, we'll use a Y-up projection
// matrix, and store the conversion to our coordinate system of
// choice in the modelview matrix.
LMatrix4f &result =
LMatrix4f::convert_mat(CS_yup_right, _current_lens->get_coordinate_system()) *
lens->get_projection_mat(_current_stereo_channel);
if (_scene_setup->get_inverted()) {
// If the scene is supposed to be inverted, then invert the
// projection matrix.
result *= LMatrix4f::scale_mat(1.0f, -1.0f, 1.0f);
}
return TransformState::make_mat(result);
}
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::prepare_lens
// Access: Public, Virtual
@ -1000,40 +1040,12 @@ prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel) {
////////////////////////////////////////////////////////////////////
bool CLP(GraphicsStateGuardian)::
prepare_lens() {
if (_current_lens == (Lens *)NULL) {
return false;
}
if (!_current_lens->is_linear()) {
return false;
}
const LMatrix4f &lens_mat = _current_lens->get_projection_mat(_current_stereo_channel);
// The projection matrix must always be right-handed Y-up, even if
// our coordinate system of choice is otherwise, because certain GL
// calls (specifically glTexGen(GL_SPHERE_MAP)) assume this kind of
// a coordinate system. Sigh. In order to implement a Z-up (or
// other arbitrary) coordinate system, we'll use a Y-up projection
// matrix, and store the conversion to our coordinate system of
// choice in the modelview matrix.
_projection_mat =
LMatrix4f::convert_mat(CS_yup_right, _current_lens->get_coordinate_system()) *
lens_mat;
if (_scene_setup->get_inverted()) {
// If the scene is supposed to be inverted, then invert the
// projection matrix.
static LMatrix4f invert_mat = LMatrix4f::scale_mat(1.0f, -1.0f, 1.0f);
_projection_mat *= invert_mat;
}
if (GLCAT.is_spam()) {
GLCAT.spam()
<< "glMatrixMode(GL_PROJECTION): " << _projection_mat << endl;
<< "glMatrixMode(GL_PROJECTION): " << _projection_mat->get_mat() << endl;
}
GLP(MatrixMode)(GL_PROJECTION);
GLP(LoadMatrixf)(_projection_mat.get_data());
GLP(LoadMatrixf)(_projection_mat->get_mat().get_data());
report_my_gl_errors();
do_point_size();
@ -2745,7 +2757,7 @@ do_issue_transform() {
}
if (_current_shader_context)
_current_shader_context->issue_transform(this);
_current_shader_context->issue_parameters(this, false);
report_my_gl_errors();
}
@ -2818,7 +2830,7 @@ do_issue_shader() {
}
} else {
// Use the same shader as before, but with new input arguments.
context->issue_parameters(this);
context->issue_parameters(this, true);
}
report_my_gl_errors();
@ -5965,7 +5977,7 @@ do_point_size() {
// scaling factor based on the current viewport and projection
// matrix.
LVector3f height(0.0f, _point_size, 1.0f);
height = height * _projection_mat;
height = height * _projection_mat->get_mat();
float s = height[1] * _viewport_height / _point_size;
if (_current_lens->is_orthographic()) {

View File

@ -85,6 +85,7 @@ public:
virtual void do_clear(const RenderBuffer &buffer);
virtual void prepare_display_region(DisplayRegion *dr, Lens::StereoChannel stereo_channel);
virtual CPT(TransformState) calc_projection_mat(const Lens *lens);
virtual bool prepare_lens();
virtual bool begin_frame();
@ -305,7 +306,6 @@ protected:
bool _dithering_enabled;
LMatrix4f _projection_mat;
int _viewport_width;
int _viewport_height;
bool _auto_antialias_mode;

File diff suppressed because it is too large Load Diff

View File

@ -42,102 +42,26 @@ public:
INLINE bool valid(void);
void bind(GSG *gsg);
void unbind();
void issue_parameters(GSG *gsg);
void issue_transform(GSG *gsg);
void issue_parameters(GSG *gsg, bool all);
void disable_shader_vertex_arrays(GSG *gsg);
void update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg);
void disable_shader_texture_bindings(GSG *gsg);
void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg);
bool _state;
private:
#ifdef HAVE_CGGL
enum ShaderAutoValue {
// This first batch of constants cleverly lines up
// with the Cg constant values. Don't insert anything.
SIC_mat_modelview,
SIC_inv_modelview,
SIC_tps_modelview,
SIC_itp_modelview,
SIC_mat_projection,
SIC_inv_projection,
SIC_tps_projection,
SIC_itp_projection,
SIC_mat_texture,
SIC_inv_texture,
SIC_tps_texture,
SIC_itp_texture,
SIC_mat_modelproj,
SIC_inv_modelproj,
SIC_tps_modelproj,
SIC_itp_modelproj,
// From this point forward, it's okay to insert stuff.
SIC_sys_windowsize,
SIC_sys_pixelsize,
SIC_sys_cardcenter,
};
struct ShaderAutoBind {
CGparameter parameter;
int value;
};
struct ShaderArgBind {
CGparameter parameter;
PT(InternalName) name;
};
struct ShaderTexBind {
CGparameter parameter;
PT(InternalName) name;
int stage;
int desiredtype;
PT(InternalName) suffix;
};
struct ShaderTransBind {
CGparameter parameter;
PT(InternalName) src_name;
PT(InternalName) rel_name;
int trans_piece;
};
struct ShaderVarying {
CGparameter parameter;
PT(InternalName) name;
int append_uv;
};
CGcontext _cg_context;
CGprofile _cg_profile[2];
CGprogram _cg_program[2];
string _cg_errors;
// These arrays contain lists of "bindings." They
// tell us how to fill the shader's input parameters.
vector <ShaderAutoBind> _cg_auto_trans;
vector <ShaderAutoBind> _cg_auto_param;
vector <ShaderArgBind> _cg_fbind;
vector <ShaderArgBind> _cg_npbind;
vector <ShaderTexBind> _cg_texbind;
vector <ShaderTransBind> _cg_transform_bind;
vector <ShaderTransBind> _cg_parameter_bind;
vector <ShaderVarying> _cg_varying;
bool try_cg_compile(ShaderExpansion *s, GSG *gsg);
void bind_cg_transform(const ShaderTransBind &stb,
CLP(GraphicsStateGuardian) *gsg);
void suggest_cg_profile(const string &vpro, const string &fpro);
CGprofile parse_cg_profile(const string &id, bool vertex);
void issue_cg_auto_bind(const ShaderAutoBind &bind, GSG *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_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);
public:

View File

@ -442,3 +442,35 @@ operator << (ostream &out, const Lens &lens) {
lens.output(out);
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,6 +155,9 @@ 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

@ -18,3 +18,634 @@
TypeHandle ShaderContext::_type_handle;
#ifdef HAVE_CG
#include "Cg/cg.h"
////////////////////////////////////////////////////////////////////
// Function: Shader::report_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 ShaderContext::
report_cg_compile_errors(const string &file, CGcontext ctx,
NotifyCategory *cat)
{
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 != "") {
cat->error() << file << " " << errlines[i] << "\n";
}
}
} else {
cat->error() << file << ": " << cgGetErrorString(err) << "\n";
}
}
}
////////////////////////////////////////////////////////////////////
// Function: Shader::report_cg_parameter_error
// Access: Public
// Description: Generate an error message including a description
// of the specified Cg parameter.
////////////////////////////////////////////////////////////////////
void ShaderContext::
report_cg_parameter_error(CGparameter p, const string &msg)
{
string vstr;
CGenum v = cgGetParameterVariability(p);
if (v == CG_UNIFORM) vstr = "uniform ";
if (v == CG_VARYING) vstr = "varying ";
if (v == CG_CONSTANT) vstr = "const ";
string dstr;
CGenum d = cgGetParameterDirection(p);
if (d == CG_IN) dstr = "in ";
if (d == CG_OUT) dstr = "out ";
if (d == CG_INOUT) dstr = "inout ";
const char *ts = cgGetTypeString(cgGetParameterType(p));
string err;
string fn = _shader_expansion->get_name();
_cg_report_cat->error() << fn << ": " << msg << " (" <<
vstr << dstr << ts << " " << cgGetParameterName(p) << ")\n";
}
////////////////////////////////////////////////////////////////////
// Function: Shader::errchk_cg_parameter_words
// Access: Public, Static
// Description: Make sure the provided Cg parameter contains
// the specified number of words. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
errchk_cg_parameter_words(CGparameter p, int len)
{
vector_string words;
tokenize(cgGetParameterName(p), words, "_");
if (words.size() != len) {
report_cg_parameter_error(p, "parameter name has wrong number of words");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::errchk_cg_parameter_in
// Access: Public, Static
// Description: Make sure the provided Cg parameter has the
// CG_IN direction. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
errchk_cg_parameter_in(CGparameter p)
{
if (cgGetParameterDirection(p) != CG_IN) {
report_cg_parameter_error(p, "parameter should be declared 'in'");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::errchk_cg_parameter_varying
// Access: Public, Static
// Description: Make sure the provided Cg parameter has the
// correct variance. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
errchk_cg_parameter_varying(CGparameter p)
{
if (cgGetParameterVariability(p) != CG_VARYING) {
report_cg_parameter_error(p, "parameter should be declared 'varying'");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::errchk_cg_parameter_uniform
// Access: Public, Static
// Description: Make sure the provided Cg parameter has the
// correct variance. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
errchk_cg_parameter_uniform(CGparameter p)
{
if (cgGetParameterVariability(p) != CG_UNIFORM) {
report_cg_parameter_error(p, "parameter should be declared 'uniform'");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::errchk_cg_parameter_float
// Access: Public, Static
// Description: Make sure the provided Cg parameter has
// a floating point type. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
errchk_cg_parameter_float(CGparameter p, int lo, int hi)
{
CGtype t = cgGetParameterType(p);
int nfloat = 0;
switch (t) {
case CG_FLOAT1: nfloat = 1; break;
case CG_FLOAT2: nfloat = 2; break;
case CG_FLOAT3: nfloat = 3; break;
case CG_FLOAT4: nfloat = 4; break;
case CG_FLOAT4x4: nfloat = 16; break;
}
if ((nfloat < lo)||(nfloat > hi)) {
report_cg_parameter_error(p, "wrong float-type for parameter");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Shader::errchk_cg_parameter_sampler
// Access: Public, Static
// Description: Make sure the provided Cg parameter has
// a texture type. If not, print
// error message and return false.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
errchk_cg_parameter_sampler(CGparameter p)
{
CGtype t = cgGetParameterType(p);
if ((t!=CG_SAMPLER1D)&&
(t!=CG_SAMPLER2D)&&
(t!=CG_SAMPLER3D)&&
(t!=CG_SAMPLERCUBE)) {
report_cg_parameter_error(p, "parameter should have a 'sampler' type");
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::parse_cg_trans_clause
// Access: Public
// Description: Parses a single clause of a "trans" parameter.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
parse_cg_trans_clause(CGparameter p, ShaderMatSpec &spec, const vector_string &pieces,
int &next, ShaderMatOp ofop, ShaderMatOp op) {
if (pieces[next+1]=="of") {
if (pieces[next+2]=="") {
report_cg_parameter_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]));
}
next += 3;
return true;
} else {
if (op != SMO_noop) {
spec._opcodes.push_back(op);
}
next += 1;
return true;
}
}
////////////////////////////////////////////////////////////////////
// Function: GLShaderContext::compile_cg_parameter
// Access: Public
// Description: Analyzes a Cg parameter and decides how to
// bind the parameter to some part of panda's
// internal state. Updates one of the cg bind
// arrays to cause the binding to occur.
//
// If there is an error, this routine will append
// an error message onto the error messages.
////////////////////////////////////////////////////////////////////
bool ShaderContext::
compile_cg_parameter(CGparameter p, NotifyCategory *cat)
{
_cg_report_cat = cat;
string pname = cgGetParameterName(p);
if (pname.size() == 0) return true;
if (pname[0] == '$') return true;
vector_string pieces;
tokenize(pname, pieces, "_");
if (pieces.size() < 2) {
report_cg_parameter_error(p, "invalid parameter name");
return false;
}
// Implement vtx parameters - the varying kind.
if (pieces[0] == "vtx") {
if ((!errchk_cg_parameter_in(p)) ||
(!errchk_cg_parameter_varying(p)) ||
(!errchk_cg_parameter_float(p, 1, 4))) {
return false;
}
ShaderVarSpec bind;
bind._parameter = (void*)p;
if (pieces.size() == 2) {
if (pieces[1]=="position") {
bind._name = InternalName::get_vertex();
bind._append_uv = -1;
_var_spec.push_back(bind);
return true;
}
if (pieces[1].substr(0,8)=="texcoord") {
bind._name = InternalName::get_texcoord();
bind._append_uv = atoi(pieces[1].c_str()+8);
_var_spec.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);
_var_spec.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);
_var_spec.push_back(bind);
return true;
}
}
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]);
_var_spec.push_back(bind);
return true;
}
// Implement some macros. Macros work by altering the
// contents of the 'pieces' array, and then falling through.
if (pieces[0] == "mstrans") {
pieces[0] = "trans";
pieces.push_back("to");
pieces.push_back("model");
}
if (pieces[0] == "wstrans") {
pieces[0] = "trans";
pieces.push_back("to");
pieces.push_back("world");
}
if (pieces[0] == "vstrans") {
pieces[0] = "trans";
pieces.push_back("to");
pieces.push_back("view");
}
if (pieces[0] == "cstrans") {
pieces[0] = "trans";
pieces.push_back("to");
pieces.push_back("clip");
}
if (pieces[0] == "mspos") {
pieces[0] = "row3";
pieces.push_back("to");
pieces.push_back("model");
}
if (pieces[0] == "wspos") {
pieces[0] = "row3";
pieces.push_back("to");
pieces.push_back("world");
}
if (pieces[0] == "vspos") {
pieces[0] = "row3";
pieces.push_back("to");
pieces.push_back("view");
}
if (pieces[0] == "cspos") {
pieces[0] = "row3";
pieces.push_back("to");
pieces.push_back("clip");
}
// Implement the modelview macros.
if ((pieces[0] == "mat")||(pieces[0] == "inv")||
(pieces[0] == "tps")||(pieces[0] == "itp")) {
if (!errchk_cg_parameter_words(p, 2)) {
return false;
}
string trans = pieces[0];
string matrix = pieces[1];
pieces.clear();
if (matrix == "modelview") {
tokenize("trans_model_to_apiview", pieces, "_");
} else if (matrix == "projection") {
tokenize("trans_apiview_to_apiclip", pieces, "_");
} else if (matrix == "modelproj") {
tokenize("trans_model_to_apiclip", pieces, "_");
} else {
report_cg_parameter_error(p,"unrecognized matrix name");
return false;
}
if (trans=="mat") {
pieces[0] = "trans";
} else if (trans=="inv") {
string t = pieces[1];
pieces[1] = pieces[3];
pieces[3] = t;
} else if (trans=="tps") {
pieces[0] = "tpose";
} else if (trans=="itp") {
string t = pieces[1];
pieces[1] = pieces[3];
pieces[3] = t;
pieces[0] = "tpose";
}
}
// Implement the transform-matrix generator.
if ((pieces[0]=="trans")||
(pieces[0]=="tpose")||
(pieces[0]=="row0")||
(pieces[0]=="row1")||
(pieces[0]=="row2")||
(pieces[0]=="row3")||
(pieces[0]=="col0")||
(pieces[0]=="col1")||
(pieces[0]=="col2")||
(pieces[0]=="col3")) {
if ((!errchk_cg_parameter_in(p)) ||
(!errchk_cg_parameter_uniform(p)))
return false;
ShaderMatSpec bind;
bind._parameter = (void*)p;
bind._trans_dependent = false;
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]=="row0") bind._piece = SMP_row0;
else if (pieces[0]=="row1") bind._piece = SMP_row1;
else if (pieces[0]=="row2") bind._piece = SMP_row2;
else if (pieces[0]=="row3") bind._piece = SMP_row3;
else if (pieces[0]=="col0") bind._piece = SMP_col0;
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 (!errchk_cg_parameter_float(p, 16, 16)) return false;
} else {
if (!errchk_cg_parameter_float(p, 4, 4)) return false;
}
// Parse the first half of the clause.
bool ok = true;
if ((pieces[next]=="")||(pieces[next]=="of")||(pieces[next]=="to")){
report_cg_parameter_error(p, "argument missing");
return false;
} else if (pieces[next] == "world") {
bind._opcodes.push_back(SMO_world_to_view);
next += 1;
} else if (pieces[next] == "model") {
ok &= parse_cg_trans_clause(p, bind, pieces, next, SMO_view_x_to_view, SMO_model_to_view);
} else if (pieces[next] == "clip") {
ok &= parse_cg_trans_clause(p, bind, pieces, next, SMO_clip_x_to_view, SMO_clip_to_view);
} else if (pieces[next] == "view") {
ok &= parse_cg_trans_clause(p, bind, pieces, next, SMO_view_x_to_view, SMO_identity);
} else if (pieces[next] == "apiview") {
ok &= parse_cg_trans_clause(p, bind, pieces, next, SMO_apiview_x_to_view, SMO_apiview_to_view);
} else if (pieces[next] == "apiclip") {
ok &= parse_cg_trans_clause(p, bind, 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]));
next += 1;
}
// Check for errors in the first clause.
if (!ok) {
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") {
report_cg_parameter_error(p, "keyword 'to' expected");
return false;
} else {
next += 1;
}
// Parse the second half of the clause.
if ((pieces[next]=="")||(pieces[next]=="of")||(pieces[next]=="to")){
report_cg_parameter_error(p, "argument missing");
return false;
} else if (pieces[next] == "world") {
bind._opcodes.push_back(SMO_view_to_world_C);
next += 1;
} else if (pieces[next] == "model") {
ok &= parse_cg_trans_clause(p, bind, pieces, next, SMO_view_to_view_x_C, SMO_view_to_model_C);
} else if (pieces[next] == "clip") {
ok &= parse_cg_trans_clause(p, bind, pieces, next, SMO_view_to_clip_x_C, SMO_view_to_clip_C);
} else if (pieces[next] == "view") {
ok &= parse_cg_trans_clause(p, bind, pieces, next, SMO_view_to_view_x_C, SMO_noop);
} else if (pieces[next] == "apiview") {
ok &= parse_cg_trans_clause(p, bind, pieces, next, SMO_view_to_apiview_x_C, SMO_view_to_apiview_C);
} else if (pieces[next] == "apiclip") {
ok &= parse_cg_trans_clause(p, bind, pieces, next, SMO_view_to_apiclip_x_C, SMO_view_to_apiclip_C);
} else {
bind._opcodes.push_back(SMO_view_to_view_x_C);
bind._args.push_back(InternalName::make(pieces[next]));
next += 1;
}
// Check for errors in the second clause.
if (!ok) {
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] != "") {
report_cg_parameter_error(p, "end of line expected");
return false;
}
_mat_spec.push_back(bind);
return true;
}
// Keywords to access unusual parameters.
if (pieces[0] == "sys") {
if ((!errchk_cg_parameter_words(p,2)) ||
(!errchk_cg_parameter_in(p)) ||
(!errchk_cg_parameter_uniform(p))) {
return false;
}
ShaderMatSpec bind;
bind._parameter = (void*)p;
bind._trans_dependent = false;
bind._piece = SMP_row3;
if (pieces[1] == "pixelsize") {
if (!errchk_cg_parameter_float(p, 2, 2)) {
return false;
}
bind._opcodes.push_back(SMO_pixel_size);
} else if (pieces[1] == "windowsize") {
if (!errchk_cg_parameter_float(p, 2, 2)) {
return false;
}
bind._opcodes.push_back(SMO_window_size);
} else if (pieces[1] == "cardcenter") {
if (!errchk_cg_parameter_float(p, 2, 2)) {
return false;
}
bind._opcodes.push_back(SMO_card_center);
} else {
report_cg_parameter_error(p,"unknown system parameter");
return false;
}
_mat_spec.push_back(bind);
return true;
}
// Keywords to access textures.
if (pieces[0] == "tex") {
if ((!errchk_cg_parameter_in(p)) ||
(!errchk_cg_parameter_uniform(p)) ||
(!errchk_cg_parameter_sampler(p)))
return false;
if ((pieces.size() != 2)&&(pieces.size() != 3)) {
report_cg_parameter_error(p, "Invalid parameter name");
return false;
}
ShaderTexSpec bind;
bind._parameter = (void*)p;
bind._name = 0;
bind._stage = atoi(pieces[1].c_str());
switch (cgGetParameterType(p)) {
case CG_SAMPLER1D: bind._desired_type = Texture::TT_1d_texture; break;
case CG_SAMPLER2D: bind._desired_type = Texture::TT_2d_texture; break;
case CG_SAMPLER3D: bind._desired_type = Texture::TT_3d_texture; break;
case CG_SAMPLERCUBE: bind._desired_type = Texture::TT_cube_map; break;
default:
report_cg_parameter_error(p, "Invalid type for a tex-parameter");
return false;
}
if (pieces.size()==3) {
bind._suffix = InternalName::make(((string)"-") + pieces[2]);
}
_tex_spec.push_back(bind);
return true;
}
// Keywords to access constants.
if (pieces[0] == "k") {
if ((!errchk_cg_parameter_words(p,2)) ||
(!errchk_cg_parameter_in(p)) ||
(!errchk_cg_parameter_uniform(p)))
return false;
switch (cgGetParameterType(p)) {
case CG_FLOAT4: {
ShaderMatSpec bind;
bind._parameter = (void*)p;
bind._trans_dependent = false;
bind._piece = SMP_row3;
bind._opcodes.push_back(SMO_vec_constant_x);
bind._args.push_back(InternalName::make(pieces[1]));
_mat_spec.push_back(bind);
break;
}
case CG_FLOAT4x4: {
ShaderMatSpec bind;
bind._parameter = (void*)p;
bind._trans_dependent = false;
bind._piece = SMP_whole;
bind._opcodes.push_back(SMO_mat_constant_x);
bind._args.push_back(InternalName::make(pieces[1]));
_mat_spec.push_back(bind);
break;
}
case CG_SAMPLER1D: {
ShaderTexSpec bind;
bind._parameter = (void*)p;
bind._name = InternalName::make(pieces[1]);
bind._desired_type=Texture::TT_1d_texture;
_tex_spec.push_back(bind);
break;
}
case CG_SAMPLER2D: {
ShaderTexSpec bind;
bind._parameter = (void*)p;
bind._name = InternalName::make(pieces[1]);
bind._desired_type=Texture::TT_2d_texture;
_tex_spec.push_back(bind);
break;
}
case CG_SAMPLER3D: {
ShaderTexSpec bind;
bind._parameter = (void*)p;
bind._name = InternalName::make(pieces[1]);
bind._desired_type=Texture::TT_3d_texture;
_tex_spec.push_back(bind);
break;
}
case CG_SAMPLERCUBE: {
ShaderTexSpec bind;
bind._parameter = (void*)p;
bind._name = InternalName::make(pieces[1]);
bind._desired_type = Texture::TT_cube_map;
_tex_spec.push_back(bind);
break;
}
default:
report_cg_parameter_error(p, "Invalid type for a k-parameter");
return false;
}
return true;
}
if (pieces[0] == "l") {
// IMPLEMENT THE ERROR CHECKING
return true; // Cg handles this automatically.
}
if (pieces[0] == "o") {
// IMPLEMENT THE ERROR CHECKING
return true; // Cg handles this automatically.
}
report_cg_parameter_error(p, "unrecognized parameter name");
return false;
}
#endif // HAVE_CG

View File

@ -23,6 +23,13 @@
#include "internalName.h"
#include "savedContext.h"
#include "shaderExpansion.h"
#ifdef HAVE_CG
// Instead of including the whole header file, just include these stubs.
typedef struct _CGcontext *CGcontext;
typedef struct _CGprogram *CGprogram;
typedef struct _CGparameter *CGparameter;
#endif
////////////////////////////////////////////////////////////////////
// Class : ShaderContext
@ -41,28 +48,117 @@ public:
INLINE ShaderContext(ShaderExpansion *se);
ShaderExpansion *_shader_expansion;
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_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,
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,
SMP_row0,
SMP_row1,
SMP_row2,
SMP_row3,
SMP_col0,
SMP_col1,
SMP_col2,
SMP_col3,
};
struct ShaderMatSpec {
pvector<ShaderMatOp> _opcodes;
pvector<PT(InternalName)> _args;
ShaderMatPiece _piece;
bool _trans_dependent;
void *_parameter;
};
struct ShaderTexSpec {
PT(InternalName) _name;
int _stage;
int _desired_type;
PT(InternalName) _suffix;
void *_parameter;
};
struct ShaderVarSpec {
PT(InternalName) _name;
int _append_uv;
void *_parameter;
};
protected:
pvector <ShaderMatSpec> _mat_spec;
pvector <ShaderTexSpec> _tex_spec;
pvector <ShaderVarSpec> _var_spec;
#ifdef HAVE_CG
private:
// These functions are only called by 'compile_cg_parameter'
NotifyCategory *_cg_report_cat;
void report_cg_parameter_error(CGparameter p, const string &msg);
bool errchk_cg_parameter_words(CGparameter p, int len);
bool errchk_cg_parameter_in(CGparameter p);
bool errchk_cg_parameter_varying(CGparameter p);
bool errchk_cg_parameter_uniform(CGparameter p);
bool errchk_cg_parameter_float(CGparameter p, int lo, int hi);
bool errchk_cg_parameter_sampler(CGparameter p);
bool parse_cg_trans_clause(CGparameter p,
ShaderMatSpec &spec,
const vector_string &pieces,
int &next,
ShaderMatOp ofop,
ShaderMatOp op);
protected:
void report_cg_compile_errors(const string &file, CGcontext ctx,
NotifyCategory *cat);
bool compile_cg_parameter(CGparameter p, NotifyCategory *cat);
#endif
public:
static TypeHandle get_class_type() {