diff --git a/panda/src/glstuff/glCgShaderContext_src.I b/panda/src/glstuff/glCgShaderContext_src.I new file mode 100755 index 0000000000..84e78d6544 --- /dev/null +++ b/panda/src/glstuff/glCgShaderContext_src.I @@ -0,0 +1,67 @@ +// Filename: glCgShaderContext_src.h +// Created by: rdb (27Jun14) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#ifndef OPENGLES_1 + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::valid +// Access: Public +// Description: Returns true if the shader is "valid", ie, if the +// compilation was successful. The compilation could +// fail if there is a syntax error in the shader, or +// if the current video card isn't shader-capable, +// or if no shader languages are compiled into panda. +//////////////////////////////////////////////////////////////////// +INLINE bool CLP(CgShaderContext):: +valid() { + if (_shader->get_error_flag()) return false; + if (_shader->get_language() != Shader::SL_Cg) return false; + if (_cg_context) return true; + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::uses_standard_vertex_arrays +// Access: Public +// Description: Returns true if the shader may need to access +// standard vertex attributes as passed by +// glVertexPointer and the like. +//////////////////////////////////////////////////////////////////// +INLINE bool CLP(CgShaderContext):: +uses_standard_vertex_arrays() { + return _uses_standard_vertex_arrays; +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::uses_custom_vertex_arrays +// Access: Public +// Description: Always true, for now. +//////////////////////////////////////////////////////////////////// +INLINE bool CLP(CgShaderContext):: +uses_custom_vertex_arrays() { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::uses_custom_texture_bindings +// Access: Public +// Description: Always true, for now. +//////////////////////////////////////////////////////////////////// +INLINE bool CLP(CgShaderContext):: +uses_custom_texture_bindings() { + return true; +} + +#endif // OPENGLES_1 + diff --git a/panda/src/glstuff/glCgShaderContext_src.cxx b/panda/src/glstuff/glCgShaderContext_src.cxx new file mode 100755 index 0000000000..fe35672716 --- /dev/null +++ b/panda/src/glstuff/glCgShaderContext_src.cxx @@ -0,0 +1,589 @@ +// Filename: glCgShaderContext_src.cxx +// Created by: jyelon (01Sep05) +// Updated by: fperazzi, PandaSE (29Apr10) (updated CLP with note that some +// parameter types only supported under Cg) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#if defined(HAVE_CG) && !defined(OPENGLES) + +#include "Cg/cgGL.h" + +#include "pStatTimer.h" + +TypeHandle CLP(CgShaderContext)::_type_handle; + +#ifndef NDEBUG +#define cg_report_errors() { \ + CGerror err = cgGetError(); \ + if (err != CG_NO_ERROR) { \ + GLCAT.error() << __FILE__ ", line " << __LINE__ << ": " << cgGetErrorString(err) << "\n"; \ + } } +#else +#define cg_report_errors() +#endif + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::Constructor +// Access: Public +// Description: xyz +//////////////////////////////////////////////////////////////////// +CLP(CgShaderContext):: +CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext(s) { + _glgsg = glgsg; + _uses_standard_vertex_arrays = false; + _cg_context = 0; + _cg_vprofile = CG_PROFILE_UNKNOWN; + _cg_fprofile = CG_PROFILE_UNKNOWN; + _cg_gprofile = CG_PROFILE_UNKNOWN; + + nassertv(s->get_language() == Shader::SL_Cg); + + // Ask the shader to compile itself for us and + // to give us the resulting Cg program objects. + if (!s->cg_compile_for(_glgsg->_shader_caps, + _cg_context, + _cg_vprogram, + _cg_fprogram, + _cg_gprogram, + _cg_parameter_map)) { + return; + } + + // Load the program. + if (_cg_vprogram != 0) { + _cg_vprofile = cgGetProgramProfile(_cg_vprogram); + cgGLLoadProgram(_cg_vprogram); + CGerror verror = cgGetError(); + if (verror != CG_NO_ERROR) { + const char *str = cgGetErrorString(verror); + GLCAT.error() + << "Could not load Cg vertex program: " << s->get_filename(Shader::ST_vertex) + << " (" << cgGetProfileString(_cg_vprofile) << " " << str << ")\n"; + release_resources(); + } + } + + if (_cg_fprogram != 0) { + _cg_fprofile = cgGetProgramProfile(_cg_fprogram); + cgGLLoadProgram(_cg_fprogram); + CGerror ferror = cgGetError(); + if (ferror != CG_NO_ERROR) { + const char *str = cgGetErrorString(ferror); + GLCAT.error() + << "Could not load Cg fragment program: " << s->get_filename(Shader::ST_fragment) + << " (" << cgGetProfileString(_cg_fprofile) << " " << str << ")\n"; + release_resources(); + } + } + + if (_cg_gprogram != 0) { + _cg_gprofile = cgGetProgramProfile(_cg_gprogram); + cgGLLoadProgram(_cg_gprogram); + CGerror gerror = cgGetError(); + if (gerror != CG_NO_ERROR) { + const char *str = cgGetErrorString(gerror); + GLCAT.error() + << "Could not load Cg geometry program: " << s->get_filename(Shader::ST_geometry) + << " (" << cgGetProfileString(_cg_gprofile) << " " << str << ")\n"; + release_resources(); + } + } + + _glgsg->report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::Destructor +// Access: Public +// Description: xyz +//////////////////////////////////////////////////////////////////// +CLP(CgShaderContext):: +~CLP(CgShaderContext)() { + release_resources(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::release_resources +// Access: Public +// Description: Should deallocate all system resources (such as +// vertex program handles or Cg contexts). +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +release_resources() { + if (_cg_context) { + cgDestroyContext(_cg_context); + _cg_context = 0; + // Do *NOT* destroy the programs here! It causes problems. +// if (_cg_vprogram != 0) cgDestroyProgram(_cg_vprogram); +// if (_cg_fprogram != 0) cgDestroyProgram(_cg_fprogram); +// if (_cg_gprogram != 0) cgDestroyProgram(_cg_gprogram); + _cg_vprogram = 0; + _cg_fprogram = 0; + _cg_gprogram = 0; + _cg_parameter_map.clear(); + } + if (_glgsg) { + _glgsg->report_my_gl_errors(); + } else if (glGetError() != GL_NO_ERROR) { + GLCAT.error() << "GL error in ShaderContext destructor\n"; + } + + if (!_glgsg) { + return; + } + _glgsg->report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::bind +// Access: Public +// Description: This function is to be called to enable a new +// shader. It also initializes all of the shader's +// input parameters. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +bind(bool reissue_parameters) { + if (reissue_parameters) { + // Pass in k-parameters and transform-parameters + issue_parameters(Shader::SSD_general); + } + + if (_cg_context != 0) { + // Bind the shaders. + if (_cg_vprogram != 0) { + cgGLEnableProfile(_cg_vprofile); + cgGLBindProgram(_cg_vprogram); + } + if (_cg_fprogram != 0) { + cgGLEnableProfile(_cg_fprofile); + cgGLBindProgram(_cg_fprogram); + } + if (_cg_gprogram != 0) { + cgGLEnableProfile(_cg_gprofile); + cgGLBindProgram(_cg_gprogram); + } + + cg_report_errors(); + _glgsg->report_my_gl_errors(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::unbind +// Access: Public +// Description: This function disables a currently-bound shader. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +unbind() { + if (_cg_context != 0) { + if (_cg_vprogram != 0) { + cgGLUnbindProgram(_cg_vprofile); + cgGLDisableProfile(_cg_vprofile); + } + if (_cg_fprogram != 0) { + cgGLUnbindProgram(_cg_fprofile); + cgGLDisableProfile(_cg_fprofile); + } + if (_cg_gprogram != 0) { + cgGLUnbindProgram(_cg_gprofile); + cgGLDisableProfile(_cg_gprofile); + } + + cg_report_errors(); + _glgsg->report_my_gl_errors(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::issue_parameters +// Access: Public +// Description: This function gets called whenever the RenderState +// or TransformState has changed, but the Shader +// itself has not changed. It loads new values into the +// 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(CgShaderContext):: +issue_parameters(int altered) { + PStatTimer timer(_glgsg->_draw_set_state_shader_parameters_pcollector); + + if (!valid()) { + return; + } + + // Iterate through _ptr parameters + for (int i=0; i<(int)_shader->_ptr_spec.size(); i++) { + if (altered & (_shader->_ptr_spec[i]._dep[0] | _shader->_ptr_spec[i]._dep[1])) { + const Shader::ShaderPtrSpec& _ptr = _shader->_ptr_spec[i]; + Shader::ShaderPtrData* ptr_data = + const_cast< Shader::ShaderPtrData*>(_glgsg->fetch_ptr_parameter(_ptr)); + + if (ptr_data == NULL){ //the input is not contained in ShaderPtrData + release_resources(); + return; + } + //check if the data must be shipped to the GPU + /*if (!ptr_data->_updated) + continue; + ptr_data->_updated = false;*/ + + //Check if the size of the shader input and ptr_data match + int input_size = _ptr._dim[0] * _ptr._dim[1] * _ptr._dim[2]; + + // dimension is negative only if the parameter had the (deprecated)k_ prefix. + if ((input_size > ptr_data->_size) && (_ptr._dim[0] > 0)) { + GLCAT.error() << _ptr._id._name << ": incorrect number of elements, expected " + << input_size <<" got " << ptr_data->_size << "\n"; + release_resources(); + return; + } + CGparameter p = _cg_parameter_map[_ptr._id._seqno]; + + switch (ptr_data->_type) { + case Shader::SPT_float: + switch(_ptr._info._class) { + case Shader::SAC_scalar: cgSetParameter1fv(p,(float*)ptr_data->_ptr); continue; + case Shader::SAC_vector: + switch(_ptr._info._type) { + case Shader::SAT_vec1: cgSetParameter1fv(p,(float*)ptr_data->_ptr); continue; + case Shader::SAT_vec2: cgSetParameter2fv(p,(float*)ptr_data->_ptr); continue; + case Shader::SAT_vec3: cgSetParameter3fv(p,(float*)ptr_data->_ptr); continue; + case Shader::SAT_vec4: cgSetParameter4fv(p,(float*)ptr_data->_ptr); continue; + } + case Shader::SAC_matrix: cgGLSetMatrixParameterfc(p,(float*)ptr_data->_ptr); continue; + case Shader::SAC_array: { + switch(_ptr._info._subclass) { + case Shader::SAC_scalar: + cgGLSetParameterArray1f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + case Shader::SAC_vector: + switch(_ptr._dim[2]) { + case 1: cgGLSetParameterArray1f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + case 2: cgGLSetParameterArray2f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + case 3: cgGLSetParameterArray3f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + case 4: cgGLSetParameterArray4f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + } + case Shader::SAC_matrix: + cgGLSetMatrixParameterArrayfc(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; + } + } + } + case Shader::SPT_double: + switch(_ptr._info._class) { + case Shader::SAC_scalar: cgSetParameter1dv(p,(double*)ptr_data->_ptr); continue; + case Shader::SAC_vector: + switch(_ptr._info._type) { + case Shader::SAT_vec1: cgSetParameter1dv(p,(double*)ptr_data->_ptr); continue; + case Shader::SAT_vec2: cgSetParameter2dv(p,(double*)ptr_data->_ptr); continue; + case Shader::SAT_vec3: cgSetParameter3dv(p,(double*)ptr_data->_ptr); continue; + case Shader::SAT_vec4: cgSetParameter4dv(p,(double*)ptr_data->_ptr); continue; + } + case Shader::SAC_matrix: cgGLSetMatrixParameterdc(p,(double*)ptr_data->_ptr); continue; + case Shader::SAC_array: { + switch(_ptr._info._subclass) { + case Shader::SAC_scalar: + cgGLSetParameterArray1d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + case Shader::SAC_vector: + switch(_ptr._dim[2]) { + case 1: cgGLSetParameterArray1d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + case 2: cgGLSetParameterArray2d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + case 3: cgGLSetParameterArray3d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + case 4: cgGLSetParameterArray4d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + } + case Shader::SAC_matrix: + cgGLSetMatrixParameterArraydc(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; + } + } + } + default: GLCAT.error() << _ptr._id._name << ":" << "unrecognized parameter type\n"; + release_resources(); + return; + } + } + } + + //FIXME: this could be much faster if we used deferred parameter setting. + + for (int i=0; i<(int)_shader->_mat_spec.size(); i++) { + if (altered & (_shader->_mat_spec[i]._dep[0] | _shader->_mat_spec[i]._dep[1])) { + const LMatrix4 *val = _glgsg->fetch_specified_value(_shader->_mat_spec[i], altered); + if (!val) continue; +#ifndef STDFLOAT_DOUBLE + // In this case, the data is already single-precision. + const PN_float32 *data = val->get_data(); +#else + // In this case, we have to convert it. + LMatrix4f valf = LCAST(PN_float32, *val); + const PN_float32 *data = valf.get_data(); +#endif + + CGparameter p = _cg_parameter_map[_shader->_mat_spec[i]._id._seqno]; + switch (_shader->_mat_spec[i]._piece) { + case Shader::SMP_whole: GLfc(cgGLSetMatrixParameter)(p, data); continue; + case Shader::SMP_transpose: GLfr(cgGLSetMatrixParameter)(p, data); continue; + case Shader::SMP_col0: GLf(cgGLSetParameter4)(p, data[0], data[4], data[ 8], data[12]); continue; + case Shader::SMP_col1: GLf(cgGLSetParameter4)(p, data[1], data[5], data[ 9], data[13]); continue; + case Shader::SMP_col2: GLf(cgGLSetParameter4)(p, data[2], data[6], data[10], data[14]); continue; + case Shader::SMP_col3: GLf(cgGLSetParameter4)(p, data[3], data[7], data[11], data[15]); continue; + case Shader::SMP_row0: GLfv(cgGLSetParameter4)(p, data+ 0); continue; + case Shader::SMP_row1: GLfv(cgGLSetParameter4)(p, data+ 4); continue; + case Shader::SMP_row2: GLfv(cgGLSetParameter4)(p, data+ 8); continue; + case Shader::SMP_row3: GLfv(cgGLSetParameter4)(p, data+12); continue; + case Shader::SMP_row3x1: GLfv(cgGLSetParameter1)(p, data+12); continue; + case Shader::SMP_row3x2: GLfv(cgGLSetParameter2)(p, data+12); continue; + case Shader::SMP_row3x3: GLfv(cgGLSetParameter3)(p, data+12); continue; + case Shader::SMP_upper3x3: + { + LMatrix3f upper3 = val->get_upper_3(); + GLfc(cgGLSetMatrixParameter)(p, upper3.get_data()); + continue; + } + case Shader::SMP_transpose3x3: + { + LMatrix3f upper3 = val->get_upper_3(); + GLfr(cgGLSetMatrixParameter)(p, upper3.get_data()); + continue; + } + } + } + } + + _glgsg->report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::disable_shader_vertex_arrays +// Access: Public +// Description: Disable all the vertex arrays used by this shader. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +disable_shader_vertex_arrays() { + if (!valid()) { + return; + } + + for (int i=0; i<(int)_shader->_var_spec.size(); i++) { + CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; + if (p == 0) continue; + cgGLDisableClientState(p); + } + + cg_report_errors(); + _glgsg->report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::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. +//////////////////////////////////////////////////////////////////// +bool CLP(CgShaderContext):: +update_shader_vertex_arrays(ShaderContext *prev, bool force) { + if (prev) prev->disable_shader_vertex_arrays(); + if (!valid()) { + return true; + } + cg_report_errors(); + +#ifdef SUPPORT_IMMEDIATE_MODE + if (_glgsg->_use_sender) { + GLCAT.error() << "immediate mode shaders not implemented yet\n"; + } else +#endif // SUPPORT_IMMEDIATE_MODE + { + const GeomVertexArrayDataHandle *array_reader; + Geom::NumericType numeric_type; + int start, stride, num_values; + int nvarying = _shader->_var_spec.size(); + for (int i = 0; i < nvarying; ++i) { + if (_cg_parameter_map[_shader->_var_spec[i]._id._seqno] == 0) { + continue; + } + + InternalName *name = _shader->_var_spec[i]._name; + int texslot = _shader->_var_spec[i]._append_uv; + if (texslot >= 0 && texslot < _glgsg->_state_texture->get_num_on_stages()) { + TextureStage *stage = _glgsg->_state_texture->get_on_stage(texslot); + InternalName *texname = stage->get_texcoord_name(); + + if (name == InternalName::get_texcoord()) { + name = texname; + } else if (texname != InternalName::get_texcoord()) { + name = name->append(texname->get_basename()); + } + } + if (_glgsg->_data_reader->get_array_info(name, + array_reader, num_values, numeric_type, + start, stride)) { + const unsigned char *client_pointer; + if (!_glgsg->setup_array_data(client_pointer, array_reader, force)) { + return false; + } + + CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; + cgGLSetParameterPointer(p, + num_values, _glgsg->get_numeric_type(numeric_type), + stride, client_pointer + start); + cgGLEnableClientState(p); + } else { + CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; + cgGLDisableClientState(p); + } + } + } + + cg_report_errors(); + _glgsg->report_my_gl_errors(); + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::disable_shader_texture_bindings +// Access: Public +// Description: Disable all the texture bindings used by this shader. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +disable_shader_texture_bindings() { + if (!valid()) { + return; + } + +#ifndef OPENGLES_2 + for (int i=0; i<(int)_shader->_tex_spec.size(); i++) { + CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno]; + if (p == 0) continue; + int texunit = cgGetParameterResourceIndex(p); + _glgsg->_glActiveTexture(GL_TEXTURE0 + texunit); + +#ifndef OPENGLES + glBindTexture(GL_TEXTURE_1D, 0); +#endif // OPENGLES + glBindTexture(GL_TEXTURE_2D, 0); +#ifndef OPENGLES_1 + if (_glgsg->_supports_3d_texture) { + glBindTexture(GL_TEXTURE_3D, 0); + } +#endif // OPENGLES_1 +#ifndef OPENGLES + if (_glgsg->_supports_2d_texture_array) { + glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 0); + } +#endif + if (_glgsg->_supports_cube_map) { + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + } + // This is probably faster - but maybe not as safe? + // cgGLDisableTextureParameter(p); + } +#endif // OPENGLES_2 + _stage_offset = 0; + + cg_report_errors(); + _glgsg->report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLCgShaderContext::update_shader_texture_bindings +// Access: Public +// Description: Disables all texture bindings used by the previous +// shader, then enables all the texture bindings needed +// by this shader. Extracts the relevant vertex array +// data from the gsg. +// The current implementation is inefficient, because +// it may unnecessarily disable textures then immediately +// reenable them. We may optimize this someday. +//////////////////////////////////////////////////////////////////// +void CLP(CgShaderContext):: +update_shader_texture_bindings(ShaderContext *prev) { + if (prev) { + prev->disable_shader_texture_bindings(); + } + + if (!valid()) { + return; + } + + // We get the TextureAttrib directly from the _target_rs, not the + // filtered TextureAttrib in _target_texture. + const TextureAttrib *texattrib = DCAST(TextureAttrib, _glgsg->_target_rs->get_attrib_def(TextureAttrib::get_class_slot())); + nassertv(texattrib != (TextureAttrib *)NULL); + _stage_offset = texattrib->get_num_on_stages(); + + for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) { + InternalName *id = _shader->_tex_spec[i]._name; + + CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno]; + if (p == 0) { + continue; + } + int texunit = cgGetParameterResourceIndex(p); + + Texture *tex = 0; + int view = _glgsg->get_current_tex_view_offset(); + if (id != 0) { + const ShaderInput *input = _glgsg->_target_shader->get_shader_input(id); + tex = input->get_texture(); + } else { + if (_shader->_tex_spec[i]._stage >= texattrib->get_num_on_stages()) { + continue; + } + TextureStage *stage = texattrib->get_on_stage(_shader->_tex_spec[i]._stage); + tex = texattrib->get_on_texture(stage); + view += stage->get_tex_view_offset(); + } + if (_shader->_tex_spec[i]._suffix != 0) { + // The suffix feature is inefficient. It is a temporary hack. + if (tex == 0) { + continue; + } + tex = tex->load_related(_shader->_tex_spec[i]._suffix); + } + if ((tex == 0) || (tex->get_texture_type() != _shader->_tex_spec[i]._desired_type)) { + continue; + } + + _glgsg->_glActiveTexture(GL_TEXTURE0 + texunit); + + TextureContext *tc = tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg); + if (tc == (TextureContext*)NULL) { + continue; + } + + GLenum target = _glgsg->get_texture_target(tex->get_texture_type()); + if (target == GL_NONE) { + // Unsupported texture mode. + continue; + } + + if (!_glgsg->update_texture(tc, false)) { + continue; + } + } + + cg_report_errors(); + _glgsg->report_my_gl_errors(); +} + +#endif // OPENGLES_1 diff --git a/panda/src/glstuff/glCgShaderContext_src.h b/panda/src/glstuff/glCgShaderContext_src.h new file mode 100755 index 0000000000..c7437f72c3 --- /dev/null +++ b/panda/src/glstuff/glCgShaderContext_src.h @@ -0,0 +1,92 @@ +// Filename: glShaderContext_src.h +// Created by: jyelon (01Sep05) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) Carnegie Mellon University. All rights reserved. +// +// All use of this software is subject to the terms of the revised BSD +// license. You should have received a copy of this license along +// with this source code in a file named "LICENSE." +// +//////////////////////////////////////////////////////////////////// + +#if defined(HAVE_CG) && !defined(OPENGLES) + +#include "pandabase.h" +#include "string_utils.h" +#include "internalName.h" +#include "shader.h" +#include "shaderContext.h" +#include "deletedChain.h" + +#include + +class CLP(GraphicsStateGuardian); + +//////////////////////////////////////////////////////////////////// +// Class : GLShaderContext +// Description : xyz +//////////////////////////////////////////////////////////////////// +class EXPCL_GL CLP(CgShaderContext) : public ShaderContext { +public: + friend class CLP(GraphicsStateGuardian); + + CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s); + ~CLP(CgShaderContext)(); + ALLOC_DELETED_CHAIN(CLP(CgShaderContext)); + + INLINE bool valid(void); + void bind(bool reissue_parameters = true); + void unbind(); + void issue_parameters(int altered); + void disable_shader_vertex_arrays(); + bool update_shader_vertex_arrays(ShaderContext *prev, bool force); + void disable_shader_texture_bindings(); + void update_shader_texture_bindings(ShaderContext *prev); + + INLINE bool uses_standard_vertex_arrays(void); + INLINE bool uses_custom_vertex_arrays(void); + INLINE bool uses_custom_texture_bindings(void); + +private: + CGcontext _cg_context; + CGprogram _cg_vprogram; + CGprogram _cg_fprogram; + CGprogram _cg_gprogram; + CGprofile _cg_vprofile; + CGprofile _cg_fprofile; + CGprofile _cg_gprofile; + + pvector _cg_parameter_map; + + int _stage_offset; + CLP(GraphicsStateGuardian) *_glgsg; + + bool _uses_standard_vertex_arrays; + + void release_resources(); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedObject::init_type(); + register_type(_type_handle, CLASSPREFIX_QUOTED "CgShaderContext", + TypedObject::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "glCgShaderContext_src.I" + +#endif // OPENGLES_1 + diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index e5332e05e3..296519c46b 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2431,17 +2431,17 @@ end_frame(Thread *current_thread) { #ifndef OPENGLES_1 // This breaks shaders across multiple regions. if (_vertex_array_shader_context != 0) { - _vertex_array_shader_context->disable_shader_vertex_arrays(this); + _vertex_array_shader_context->disable_shader_vertex_arrays(); _vertex_array_shader = (Shader *)NULL; _vertex_array_shader_context = (CLP(ShaderContext) *)NULL; } if (_texture_binding_shader_context != 0) { - _texture_binding_shader_context->disable_shader_texture_bindings(this); + _texture_binding_shader_context->disable_shader_texture_bindings(); _texture_binding_shader = (Shader *)NULL; _texture_binding_shader_context = (CLP(ShaderContext) *)NULL; } if (_current_shader_context != 0) { - _current_shader_context->unbind(this); + _current_shader_context->unbind(); _current_shader = (Shader *)NULL; _current_shader_context = (CLP(ShaderContext) *)NULL; } @@ -2737,7 +2737,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, if (_current_shader_context == 0) { // No shader. if (_vertex_array_shader_context != 0) { - _vertex_array_shader_context->disable_shader_vertex_arrays(this); + _vertex_array_shader_context->disable_shader_vertex_arrays(); } if (!update_standard_vertex_arrays(force)) { return false; @@ -2759,11 +2759,11 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader, if (_current_shader_context->uses_custom_vertex_arrays()) { // The current shader also uses custom vertex arrays. if (!_current_shader_context-> - update_shader_vertex_arrays(_vertex_array_shader_context, this, force)) { + update_shader_vertex_arrays(_vertex_array_shader_context, force)) { return false; } } else { - _vertex_array_shader_context->disable_shader_vertex_arrays(this); + _vertex_array_shader_context->disable_shader_vertex_arrays(); } } @@ -3834,29 +3834,48 @@ release_geom(GeomContext *gc) { //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::prepare_shader // Access: Public, Virtual -// Description: yadda. +// Description: //////////////////////////////////////////////////////////////////// ShaderContext *CLP(GraphicsStateGuardian):: prepare_shader(Shader *se) { #ifndef OPENGLES_1 - CLP(ShaderContext) *result = new CLP(ShaderContext)(se, this); - if (result->valid()) return result; - delete result; + ShaderContext *result = NULL; + + switch (se->get_language()) { + case Shader::SL_GLSL: + result = new CLP(ShaderContext)(this, se); + break; + +#if defined(HAVE_CG) && !defined(OPENGLES) + case Shader::SL_Cg: + result = new CLP(CgShaderContext)(this, se); + break; #endif + + default: + GLCAT.error() + << "Tried to load shader with unsupported shader language!\n"; + return NULL; + } + + if (result->valid()) { + return result; + } + + delete result; +#endif // OPENGLES_1 + return NULL; } //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::release_shader // Access: Public, Virtual -// Description: yadda. +// Description: //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: release_shader(ShaderContext *sc) { -#ifndef OPENGLES_1 - CLP(ShaderContext) *gsc = DCAST(CLP(ShaderContext), sc); - delete gsc; -#endif + delete sc; } //////////////////////////////////////////////////////////////////// @@ -4807,7 +4826,7 @@ do_issue_transform() { #ifndef OPENGLES_1 if (_current_shader_context) { - _current_shader_context->issue_parameters(this, Shader::SSD_transform); + _current_shader_context->issue_parameters(Shader::SSD_transform); } #endif @@ -4868,7 +4887,7 @@ do_issue_shader(bool state_has_changed) { if (context == 0 || (context->valid() == false)) { if (_current_shader_context != 0) { - _current_shader_context->unbind(this); + _current_shader_context->unbind(); _current_shader = 0; _current_shader_context = 0; } @@ -4877,19 +4896,19 @@ do_issue_shader(bool state_has_changed) { // Use a completely different shader than before. // Unbind old shader, bind the new one. if (_current_shader_context != 0) { - _current_shader_context->unbind(this); + _current_shader_context->unbind(); } - context->bind(this); + context->bind(); _current_shader = shader; _current_shader_context = context; - context->issue_parameters(this, Shader::SSD_shaderinputs); + context->issue_parameters(Shader::SSD_shaderinputs); } else { #ifdef OPENGLES_2 - context->bind(this, false); + context->bind(false); #endif if (state_has_changed) { // Use the same shader as before, but with new input arguments. - context->issue_parameters(this, Shader::SSD_shaderinputs); + context->issue_parameters(Shader::SSD_shaderinputs); } } } @@ -7856,8 +7875,8 @@ set_state_and_transform(const RenderState *target, _state_mask.set_bit(color_scale_slot); #ifndef OPENGLES_1 if (_current_shader_context) { - _current_shader_context->issue_parameters(this, Shader::SSD_color); - _current_shader_context->issue_parameters(this, Shader::SSD_colorscale); + _current_shader_context->issue_parameters(Shader::SSD_color); + _current_shader_context->issue_parameters(Shader::SSD_colorscale); } #endif } @@ -8008,7 +8027,7 @@ set_state_and_transform(const RenderState *target, _state_mask.set_bit(material_slot); #ifndef OPENGLES_1 if (_current_shader_context) { - _current_shader_context->issue_parameters(this, Shader::SSD_material); + _current_shader_context->issue_parameters(Shader::SSD_material); } #endif } @@ -8037,7 +8056,7 @@ set_state_and_transform(const RenderState *target, _state_mask.set_bit(fog_slot); #ifndef OPENGLES_1 if (_current_shader_context) { - _current_shader_context->issue_parameters(this, Shader::SSD_fog); + _current_shader_context->issue_parameters(Shader::SSD_fog); } #endif } @@ -8136,16 +8155,16 @@ do_issue_texture() { if (_current_shader_context == 0 || !_current_shader_context->uses_custom_texture_bindings()) { // No shader, or a non-Cg shader. if (_texture_binding_shader_context != 0) { - _texture_binding_shader_context->disable_shader_texture_bindings(this); + _texture_binding_shader_context->disable_shader_texture_bindings(); } update_standard_texture_bindings(); } else { if (_texture_binding_shader_context == 0) { disable_standard_texture_bindings(); - _current_shader_context->update_shader_texture_bindings(NULL,this); + _current_shader_context->update_shader_texture_bindings(NULL); } else { _current_shader_context-> - update_shader_texture_bindings(_texture_binding_shader_context,this); + update_shader_texture_bindings(_texture_binding_shader_context); } } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index af12e7c1ca..264fb037e3 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -775,6 +775,7 @@ private: friend class CLP(VertexBufferContext); friend class CLP(IndexBufferContext); friend class CLP(ShaderContext); + friend class CLP(CgShaderContext); friend class CLP(GraphicsBuffer); friend class CLP(OcclusionQueryContext); }; diff --git a/panda/src/glstuff/glShaderContext_src.I b/panda/src/glstuff/glShaderContext_src.I index a6cd94cdbc..c3424b8cca 100755 --- a/panda/src/glstuff/glShaderContext_src.I +++ b/panda/src/glstuff/glShaderContext_src.I @@ -12,7 +12,6 @@ // //////////////////////////////////////////////////////////////////// -#ifndef OPENGLES_1 //////////////////////////////////////////////////////////////////// // Function: GLShaderContext::valid @@ -26,11 +25,10 @@ INLINE bool CLP(ShaderContext):: valid() { if (_shader->get_error_flag()) return false; - if (_shader->get_language() == Shader::SL_none) return false; -#if defined(HAVE_CG) && !defined(OPENGLES) - if (_cg_context) return true; -#endif - if (_shader->get_language() == Shader::SL_GLSL && _glsl_program != 0) { + if (_shader->get_language() != Shader::SL_GLSL) { + return false; + } + if (_glsl_program != 0) { return true; } return false; @@ -67,6 +65,3 @@ INLINE bool CLP(ShaderContext):: uses_custom_texture_bindings() { return true; } - -#endif // OPENGLES_1 - diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 1f79b90197..c76c44c703 100755 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -16,13 +16,8 @@ #ifndef OPENGLES_1 -#if defined(HAVE_CG) && !defined(OPENGLES) -#include "Cg/cgGL.h" -#endif #include "pStatTimer.h" -#define DEBUG_GL_SHADER 0 - TypeHandle CLP(ShaderContext)::_type_handle; #ifndef GL_GEOMETRY_SHADER_EXT @@ -35,19 +30,6 @@ TypeHandle CLP(ShaderContext)::_type_handle; #define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 #endif -#if defined(HAVE_CG) && !defined(OPENGLES) -#ifndef NDEBUG -#define cg_report_errors() { \ - CGerror err = cgGetError(); \ - if (err != CG_NO_ERROR) { \ - GLCAT.error() << __FILE__ ", line " << __LINE__ << ": " << cgGetErrorString(err) << "\n"; \ - } } -#else -#define cg_report_errors() -#endif -#endif - - //////////////////////////////////////////////////////////////////// // Function: GLShaderContext::ParseAndSetShaderUniformVars // Access: Public @@ -70,137 +52,138 @@ TypeHandle CLP(ShaderContext)::_type_handle; //////////////////////////////////////////////////////////////////// bool CLP(ShaderContext):: parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objShader) { - Shader::ShaderArgInfo p; - p._id = arg_id; + Shader::ShaderArgInfo p; + p._id = arg_id; + p._cat = GLCAT; - string basename(arg_id._name); - // Split it at the underscores. - vector_string pieces; - tokenize(basename, pieces, "_"); + string basename(arg_id._name); + // Split it at the underscores. + vector_string pieces; + tokenize(basename, pieces, "_"); - 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"); - } + 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"); + } - if ((pieces[0] == "mat") || (pieces[0] == "inv") || - (pieces[0] == "tps") || (pieces[0] == "itp")) { - if (!objShader->cp_errchk_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 { - objShader->cp_report_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"; - } + if ((pieces[0] == "mat") || (pieces[0] == "inv") || + (pieces[0] == "tps") || (pieces[0] == "itp")) { + if (!objShader->cp_errchk_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 { + objShader->cp_report_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 ((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")) { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._func = Shader::SMF_compose; - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._func = Shader::SMF_compose; + int next = 1; + pieces.push_back(""); - int next = 1; - pieces.push_back(""); + // Decide whether this is a matrix or vector. + if (pieces[0] == "trans") bind._piece = Shader::SMP_whole; + else if (pieces[0] == "tpose") bind._piece = Shader::SMP_transpose; + else if (pieces[0] == "row0") bind._piece = Shader::SMP_row0; + else if (pieces[0] == "row1") bind._piece = Shader::SMP_row1; + else if (pieces[0] == "row2") bind._piece = Shader::SMP_row2; + else if (pieces[0] == "row3") bind._piece = Shader::SMP_row3; + else if (pieces[0] == "col0") bind._piece = Shader::SMP_col0; + else if (pieces[0] == "col1") bind._piece = Shader::SMP_col1; + else if (pieces[0] == "col2") bind._piece = Shader::SMP_col2; + else if (pieces[0] == "col3") bind._piece = Shader::SMP_col3; - // Decide whether this is a matrix or vector. - if (pieces[0] == "trans") bind._piece = Shader::SMP_whole; - else if (pieces[0] == "tpose") bind._piece = Shader::SMP_transpose; - else if (pieces[0] == "row0") bind._piece = Shader::SMP_row0; - else if (pieces[0] == "row1") bind._piece = Shader::SMP_row1; - else if (pieces[0] == "row2") bind._piece = Shader::SMP_row2; - else if (pieces[0] == "row3") bind._piece = Shader::SMP_row3; - else if (pieces[0] == "col0") bind._piece = Shader::SMP_col0; - else if (pieces[0] == "col1") bind._piece = Shader::SMP_col1; - else if (pieces[0] == "col2") bind._piece = Shader::SMP_col2; - else if (pieces[0] == "col3") bind._piece = Shader::SMP_col3; - - if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, true)) { - return false; - } - if (!objShader->cp_parse_delimiter(p, pieces, next)) { - return false; - } - if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, false)) { - return false; - } - if (!objShader->cp_parse_eol(p, pieces, next)) { - return false; - } - objShader->cp_optimize_mat_spec(bind); - objShader->_mat_spec.push_back(bind); - return true; + if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, true)) { + return false; } - return false; + if (!objShader->cp_parse_delimiter(p, pieces, next)) { + return false; + } + if (!objShader->cp_parse_coord_sys(p, pieces, next, bind, false)) { + return false; + } + if (!objShader->cp_parse_eol(p, pieces, next)) { + return false; + } + objShader->cp_optimize_mat_spec(bind); + objShader->_mat_spec.push_back(bind); + return true; + } + return false; } //////////////////////////////////////////////////////////////////// @@ -209,8 +192,8 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objSha // Description: xyz //////////////////////////////////////////////////////////////////// CLP(ShaderContext):: -CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { - _last_gsg = gsg; +CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext(s) { + _glgsg = glgsg; _glsl_program = 0; _glsl_vshader = 0; _glsl_fshader = 0; @@ -220,469 +203,307 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { _glsl_cshader = 0; _uses_standard_vertex_arrays = false; -#if defined(HAVE_CG) && !defined(OPENGLES) - _cg_context = 0; - _cg_vprofile = CG_PROFILE_UNKNOWN; - _cg_fprofile = CG_PROFILE_UNKNOWN; - _cg_gprofile = CG_PROFILE_UNKNOWN; - if (s->get_language() == Shader::SL_Cg) { - // Ask the shader to compile itself for us and - // to give us the resulting Cg program objects. + nassertv(s->get_language() == Shader::SL_GLSL); - if (!s->cg_compile_for(gsg->_shader_caps, - _cg_context, - _cg_vprogram, - _cg_fprogram, - _cg_gprogram, - _cg_parameter_map)) { - return; - } - - // Load the program. - if (_cg_vprogram != 0) { - _cg_vprofile = cgGetProgramProfile(_cg_vprogram); - cgGLLoadProgram(_cg_vprogram); - CGerror verror = cgGetError(); - if (verror != CG_NO_ERROR) { - const char *str = cgGetErrorString(verror); - GLCAT.error() - << "Could not load Cg vertex program: " << s->get_filename(Shader::ST_vertex) - << " (" << cgGetProfileString(_cg_vprofile) << " " << str << ")\n"; - release_resources(gsg); - } - } - - if (_cg_fprogram != 0) { - _cg_fprofile = cgGetProgramProfile(_cg_fprogram); - cgGLLoadProgram(_cg_fprogram); - CGerror ferror = cgGetError(); - if (ferror != CG_NO_ERROR) { - const char *str = cgGetErrorString(ferror); - GLCAT.error() - << "Could not load Cg fragment program: " << s->get_filename(Shader::ST_fragment) - << " (" << cgGetProfileString(_cg_fprofile) << " " << str << ")\n"; - release_resources(gsg); - } - } - - if (_cg_gprogram != 0) { - _cg_gprofile = cgGetProgramProfile(_cg_gprogram); - cgGLLoadProgram(_cg_gprogram); - CGerror gerror = cgGetError(); - if (gerror != CG_NO_ERROR) { - const char *str = cgGetErrorString(gerror); - GLCAT.error() - << "Could not load Cg geometry program: " << s->get_filename(Shader::ST_geometry) - << " (" << cgGetProfileString(_cg_gprofile) << " " << str << ")\n"; - release_resources(gsg); - } - } - gsg->report_my_gl_errors(); + // We compile and analyze the shader here, instead of in shader.cxx, to avoid gobj getting a dependency on GL stuff. + if (!glsl_compile_shader()) { + release_resources(); + s->_error_flag = true; + return; } -#endif + _glgsg->_glUseProgram(_glsl_program); - if (s->get_language() == Shader::SL_GLSL) { - // We compile and analyze the shader here, instead of in shader.cxx, to avoid gobj getting a dependency on GL stuff. - if (_glsl_program == 0) { - gsg->report_my_gl_errors(); - if (!glsl_compile_shader(gsg)) { - release_resources(gsg); - s->_error_flag = true; - return; + // Analyze the uniforms and put them in _glsl_parameter_map + if (_glsl_parameter_map.size() == 0) { + int seqno = 0, texunitno = 0, imgunitno = 0; + string noprefix; + GLint param_count, param_maxlength, param_size; + GLenum param_type; + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, ¶m_count); + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, ¶m_maxlength); + char* param_name_cstr = (char *)alloca(param_maxlength); + + for (int i = 0; i < param_count; ++i) { + param_name_cstr[0] = 0; + _glgsg->_glGetActiveUniform(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name_cstr); + string param_name(param_name_cstr); + GLint p = _glgsg->_glGetUniformLocation(_glsl_program, param_name_cstr); + + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Active uniform " << param_name << " with size " << param_size + << " and type " << param_type << " is bound to location " << p << "\n"; } - } - gsg->_glUseProgram(_glsl_program); - // Analyze the uniforms and put them in _glsl_parameter_map - if (_glsl_parameter_map.size() == 0) { - int seqno = 0, texunitno = 0, imgunitno = 0; - string noprefix; - GLint param_count, param_maxlength, param_size; - GLenum param_type; - gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, ¶m_count); - gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, ¶m_maxlength); - char* param_name_cstr = (char *)alloca(param_maxlength); - - for (int i = 0; i < param_count; ++i) { - param_name_cstr[0] = 0; - gsg->_glGetActiveUniform(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name_cstr); - string param_name(param_name_cstr); - GLint p = gsg->_glGetUniformLocation(_glsl_program, param_name_cstr); - - if (GLCAT.is_debug()) { - GLCAT.debug() - << "Active uniform " << param_name << " with size " << param_size - << " and type " << param_type << " is bound to location " << p << "\n"; + if (p > -1) { + // Strip off [0] suffix that some drivers append to arrays. + size_t size = param_name.size(); + if (size > 3 && param_name.substr(size - 3, 3) == "[0]") { + param_name = param_name.substr(0, size - 3); } - if (p > -1) { - // Strip off [0] suffix that some drivers append to arrays. - size_t size = param_name.size(); - if (size > 3 && param_name.substr(size - 3, 3) == "[0]") { - param_name = param_name.substr(0, size - 3); + Shader::ShaderArgId arg_id; + arg_id._name = param_name; + arg_id._seqno = seqno++; + _glsl_parameter_map.push_back(p); + + // Check for inputs with p3d_ prefix. + if (param_name.substr(0, 4) == "p3d_") { + noprefix = param_name.substr(4); + + // Check for matrix inputs. + bool transpose = false; + bool inverse = false; + string matrix_name (noprefix); + + // Check for and chop off any "Transpose" or "Inverse" suffix. + if (size > 15 && matrix_name.compare(size - 9, 9, "Transpose") == 0) { + transpose = true; + matrix_name = matrix_name.substr(0, size - 9); } + size = matrix_name.size(); + if (size > 13 && matrix_name.compare(size - 7, 7, "Inverse") == 0) { + inverse = true; + matrix_name = matrix_name.substr(0, size - 7); + } + size = matrix_name.size(); - Shader::ShaderArgId arg_id; - arg_id._name = param_name; - arg_id._seqno = seqno++; - _glsl_parameter_map.push_back(p); - - // Check for inputs with p3d_ prefix. - if (param_name.substr(0, 4) == "p3d_") { - noprefix = param_name.substr(4); - - // Check for matrix inputs. - bool transpose = false; - bool inverse = false; - string matrix_name (noprefix); - - // Check for and chop off any "Transpose" or "Inverse" suffix. - if (size > 15 && matrix_name.compare(size - 9, 9, "Transpose") == 0) { - transpose = true; - matrix_name = matrix_name.substr(0, size - 9); - } - size = matrix_name.size(); - if (size > 13 && matrix_name.compare(size - 7, 7, "Inverse") == 0) { - inverse = true; - matrix_name = matrix_name.substr(0, size - 7); - } - size = matrix_name.size(); - - // Now if the suffix that is left over is "Matrix", - // we know that it is supposed to be a matrix input. - if (size > 6 && matrix_name.compare(size - 6, 6, "Matrix") == 0) { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - if (transpose) { - bind._piece = Shader::SMP_transpose; - } else { - bind._piece = Shader::SMP_whole; - } - bind._arg[0] = NULL; - bind._arg[1] = NULL; - - if (matrix_name == "ModelViewProjectionMatrix") { - bind._func = Shader::SMF_compose; - if (inverse) { - bind._part[0] = Shader::SMO_apiclip_to_view; - bind._part[1] = Shader::SMO_view_to_model; - } else { - bind._part[0] = Shader::SMO_model_to_view; - bind._part[1] = Shader::SMO_view_to_apiclip; - } - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - - } else if (matrix_name == "ModelViewMatrix") { - bind._func = Shader::SMF_compose; - if (inverse) { - bind._part[0] = Shader::SMO_apiview_to_view; - bind._part[1] = Shader::SMO_view_to_model; - } else { - bind._part[0] = Shader::SMO_model_to_view; - bind._part[1] = Shader::SMO_view_to_apiview; - } - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - - } else if (matrix_name == "ProjectionMatrix") { - bind._func = Shader::SMF_compose; - if (inverse) { - bind._part[0] = Shader::SMO_apiclip_to_view; - bind._part[1] = Shader::SMO_view_to_apiview; - } else { - bind._part[0] = Shader::SMO_apiview_to_view; - bind._part[1] = Shader::SMO_view_to_apiclip; - } - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - - } else if (matrix_name == "NormalMatrix") { - // This is really the upper 3x3 of the ModelViewMatrixInverseTranspose. - bind._func = Shader::SMF_compose; - if (inverse) { - bind._part[0] = Shader::SMO_model_to_view; - bind._part[1] = Shader::SMO_view_to_apiview; - } else { - bind._part[0] = Shader::SMO_apiview_to_view; - bind._part[1] = Shader::SMO_view_to_model; - } - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - - if (transpose) { - bind._piece = Shader::SMP_upper3x3; - } else { - bind._piece = Shader::SMP_transpose3x3; - } - - } else { - GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n"; - continue; - } - s->_mat_spec.push_back(bind); - continue; - } - if (size > 7 && noprefix.substr(0, 7) == "Texture") { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = 0; - bind._desired_type = Texture::TT_2d_texture; - bind._stage = atoi(noprefix.substr(7).c_str()); - s->_tex_spec.push_back(bind); - continue; - } - if (size > 9 && noprefix.substr(0, 9) == "Material.") { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_attr_material; - bind._arg[0] = NULL; - bind._dep[0] = Shader::SSD_general | Shader::SSD_material; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - - if (noprefix == "Material.ambient") { - bind._piece = Shader::SMP_row0; - s->_mat_spec.push_back(bind); - continue; - } else if (noprefix == "Material.diffuse") { - bind._piece = Shader::SMP_row1; - s->_mat_spec.push_back(bind); - continue; - } else if (noprefix == "Material.emission") { - bind._piece = Shader::SMP_row2; - s->_mat_spec.push_back(bind); - continue; - } else if (noprefix == "Material.specular") { - bind._piece = Shader::SMP_row3; - s->_mat_spec.push_back(bind); - continue; - } - } - if (noprefix == "ColorScale") { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._piece = Shader::SMP_row3; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_attr_colorscale; - bind._arg[0] = NULL; - bind._dep[0] = Shader::SSD_general | Shader::SSD_colorscale; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; - } - GLCAT.error() << "Unrecognized uniform name '" << param_name_cstr << "'!\n"; - continue; - - } else if (param_name.substr(0, 4) == "osg_") { - // These inputs are supported by OpenSceneGraph. We can support - // them as well, to increase compatibility. - // Other inputs we may support in the future: - // int osg_FrameNumber - + // Now if the suffix that is left over is "Matrix", + // we know that it is supposed to be a matrix input. + if (size > 6 && matrix_name.compare(size - 6, 6, "Matrix") == 0) { Shader::ShaderMatSpec bind; bind._id = arg_id; + if (transpose) { + bind._piece = Shader::SMP_transpose; + } else { + bind._piece = Shader::SMP_whole; + } bind._arg[0] = NULL; bind._arg[1] = NULL; - if (param_name == "osg_ViewMatrix") { - bind._piece = Shader::SMP_whole; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_world_to_view; - bind._part[1] = Shader::SMO_identity; + if (matrix_name == "ModelViewProjectionMatrix") { + bind._func = Shader::SMF_compose; + if (inverse) { + bind._part[0] = Shader::SMO_apiclip_to_view; + bind._part[1] = Shader::SMO_view_to_model; + } else { + bind._part[0] = Shader::SMO_model_to_view; + bind._part[1] = Shader::SMO_view_to_apiclip; + } bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; + bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - } else if (param_name == "osg_InverseViewMatrix") { - bind._piece = Shader::SMP_whole; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_view_to_world; - bind._part[1] = Shader::SMO_identity; + } else if (matrix_name == "ModelViewMatrix") { + bind._func = Shader::SMF_compose; + if (inverse) { + bind._part[0] = Shader::SMO_apiview_to_view; + bind._part[1] = Shader::SMO_view_to_model; + } else { + bind._part[0] = Shader::SMO_model_to_view; + bind._part[1] = Shader::SMO_view_to_apiview; + } bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; + bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - } else if (param_name == "osg_FrameTime") { - bind._piece = Shader::SMP_row3x1; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_frame_time; - bind._part[1] = Shader::SMO_identity; - bind._dep[0] = Shader::SSD_general; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; + } else if (matrix_name == "ProjectionMatrix") { + bind._func = Shader::SMF_compose; + if (inverse) { + bind._part[0] = Shader::SMO_apiclip_to_view; + bind._part[1] = Shader::SMO_view_to_apiview; + } else { + bind._part[0] = Shader::SMO_apiview_to_view; + bind._part[1] = Shader::SMO_view_to_apiclip; + } + bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - } else if (param_name == "osg_DeltaFrameTime") { - bind._piece = Shader::SMP_row3x1; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_frame_delta; - bind._part[1] = Shader::SMO_identity; - bind._dep[0] = Shader::SSD_general; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); + } else if (matrix_name == "NormalMatrix") { + // This is really the upper 3x3 of the ModelViewMatrixInverseTranspose. + bind._func = Shader::SMF_compose; + if (inverse) { + bind._part[0] = Shader::SMO_model_to_view; + bind._part[1] = Shader::SMO_view_to_apiview; + } else { + bind._part[0] = Shader::SMO_apiview_to_view; + bind._part[1] = Shader::SMO_view_to_model; + } + bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; + + if (transpose) { + bind._piece = Shader::SMP_upper3x3; + } else { + bind._piece = Shader::SMP_transpose3x3; + } + + } else { + GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n"; continue; } - } - - //Tries to parse shorthand notations like mspos_XXX and trans_model_to_clip_of_XXX - if (parse_and_set_short_hand_shader_vars(arg_id, s)) { + s->_mat_spec.push_back(bind); continue; } + if (size > 7 && noprefix.substr(0, 7) == "Texture") { + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = 0; + bind._desired_type = Texture::TT_2d_texture; + bind._stage = atoi(noprefix.substr(7).c_str()); + s->_tex_spec.push_back(bind); + continue; + } + if (size > 9 && noprefix.substr(0, 9) == "Material.") { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_attr_material; + bind._arg[0] = NULL; + bind._dep[0] = Shader::SSD_general | Shader::SSD_material; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; - if (param_size == 1) { - switch (param_type) { -#ifndef OPENGLES - case GL_SAMPLER_1D_SHADOW: - case GL_SAMPLER_1D: { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = InternalName::make(param_name); - bind._desired_type = Texture::TT_1d_texture; - bind._stage = texunitno++; - s->_tex_spec.push_back(bind); - continue; } - case GL_SAMPLER_2D_SHADOW: -#endif - case GL_SAMPLER_2D: { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = InternalName::make(param_name); - bind._desired_type = Texture::TT_2d_texture; - bind._stage = texunitno++; - s->_tex_spec.push_back(bind); - continue; } - case GL_SAMPLER_3D: { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = InternalName::make(param_name); - bind._desired_type = Texture::TT_3d_texture; - bind._stage = texunitno++; - s->_tex_spec.push_back(bind); - continue; } - case GL_SAMPLER_CUBE: { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = InternalName::make(param_name); - bind._desired_type = Texture::TT_cube_map; - bind._stage = texunitno++; - s->_tex_spec.push_back(bind); - continue; } -#ifndef OPENGLES - case GL_SAMPLER_2D_ARRAY: { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = InternalName::make(param_name); - bind._desired_type = Texture::TT_2d_texture_array; - bind._stage = texunitno++; - s->_tex_spec.push_back(bind); - continue; } -#endif - case GL_FLOAT_MAT2: -#ifndef OPENGLES - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: -#endif - GLCAT.warning() << "GLSL shader requested an unrecognized matrix type\n"; - continue; - case GL_FLOAT_MAT3: { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._piece = Shader::SMP_upper3x3; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_mat_constant_x; - bind._arg[0] = InternalName::make(param_name); - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; } - case GL_FLOAT_MAT4: { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._piece = Shader::SMP_whole; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_mat_constant_x; - bind._arg[0] = InternalName::make(param_name); - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; } - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - switch (param_type) { - case GL_BOOL: - case GL_FLOAT: bind._piece = Shader::SMP_row3x1; break; - case GL_BOOL_VEC2: - case GL_FLOAT_VEC2: bind._piece = Shader::SMP_row3x2; break; - case GL_BOOL_VEC3: - case GL_FLOAT_VEC3: bind._piece = Shader::SMP_row3x3; break; - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: bind._piece = Shader::SMP_row3 ; break; - } - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_vec_constant_x; - bind._arg[0] = InternalName::make(param_name); - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; } - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - GLCAT.warning() << "Panda does not support passing integers to shaders (yet)!\n"; - continue; -#ifndef OPENGLES - case GL_IMAGE_1D_EXT: - case GL_IMAGE_2D_EXT: - case GL_IMAGE_3D_EXT: - case GL_IMAGE_CUBE_EXT: - case GL_IMAGE_2D_ARRAY_EXT: - case GL_INT_IMAGE_1D_EXT: - case GL_INT_IMAGE_2D_EXT: - case GL_INT_IMAGE_3D_EXT: - case GL_INT_IMAGE_CUBE_EXT: - case GL_INT_IMAGE_2D_ARRAY_EXT: - case GL_UNSIGNED_INT_IMAGE_1D_EXT: - case GL_UNSIGNED_INT_IMAGE_2D_EXT: - case GL_UNSIGNED_INT_IMAGE_3D_EXT: - case GL_UNSIGNED_INT_IMAGE_CUBE_EXT: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT: - // This won't really change at runtime, so we might as well - // bind once and then forget about it. - gsg->_glUniform1i(p, imgunitno++); - _glsl_img_inputs.push_back(InternalName::make(param_name)); - continue; -#endif - default: - GLCAT.warning() << "Ignoring unrecognized GLSL parameter type!\n"; + if (noprefix == "Material.ambient") { + bind._piece = Shader::SMP_row0; + s->_mat_spec.push_back(bind); + continue; + } else if (noprefix == "Material.diffuse") { + bind._piece = Shader::SMP_row1; + s->_mat_spec.push_back(bind); + continue; + } else if (noprefix == "Material.emission") { + bind._piece = Shader::SMP_row2; + s->_mat_spec.push_back(bind); + continue; + } else if (noprefix == "Material.specular") { + bind._piece = Shader::SMP_row3; + s->_mat_spec.push_back(bind); + continue; } - } else { - switch (param_type) { + } + if (noprefix == "ColorScale") { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._piece = Shader::SMP_row3; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_attr_colorscale; + bind._arg[0] = NULL; + bind._dep[0] = Shader::SSD_general | Shader::SSD_colorscale; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + } + GLCAT.error() << "Unrecognized uniform name '" << param_name_cstr << "'!\n"; + continue; + + } else if (param_name.substr(0, 4) == "osg_") { + // These inputs are supported by OpenSceneGraph. We can support + // them as well, to increase compatibility. + // Other inputs we may support in the future: + // int osg_FrameNumber + + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._arg[0] = NULL; + bind._arg[1] = NULL; + + if (param_name == "osg_ViewMatrix") { + bind._piece = Shader::SMP_whole; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_world_to_view; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + + } else if (param_name == "osg_InverseViewMatrix") { + bind._piece = Shader::SMP_whole; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_view_to_world; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + + } else if (param_name == "osg_FrameTime") { + bind._piece = Shader::SMP_row3x1; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_frame_time; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + + } else if (param_name == "osg_DeltaFrameTime") { + bind._piece = Shader::SMP_row3x1; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_frame_delta; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; + } + } + + //Tries to parse shorthand notations like mspos_XXX and trans_model_to_clip_of_XXX + if (parse_and_set_short_hand_shader_vars(arg_id, s)) { + continue; + } + + if (param_size == 1) { + switch (param_type) { +#ifndef OPENGLES + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_1D: { + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = InternalName::make(param_name); + bind._desired_type = Texture::TT_1d_texture; + bind._stage = texunitno++; + s->_tex_spec.push_back(bind); + continue; } + case GL_SAMPLER_2D_SHADOW: +#endif + case GL_SAMPLER_2D: { + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = InternalName::make(param_name); + bind._desired_type = Texture::TT_2d_texture; + bind._stage = texunitno++; + s->_tex_spec.push_back(bind); + continue; } + case GL_SAMPLER_3D: { + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = InternalName::make(param_name); + bind._desired_type = Texture::TT_3d_texture; + bind._stage = texunitno++; + s->_tex_spec.push_back(bind); + continue; } + case GL_SAMPLER_CUBE: { + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = InternalName::make(param_name); + bind._desired_type = Texture::TT_cube_map; + bind._stage = texunitno++; + s->_tex_spec.push_back(bind); + continue; } +#ifndef OPENGLES + case GL_SAMPLER_2D_ARRAY: { + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = InternalName::make(param_name); + bind._desired_type = Texture::TT_2d_texture_array; + bind._stage = texunitno++; + s->_tex_spec.push_back(bind); + continue; } +#endif case GL_FLOAT_MAT2: #ifndef OPENGLES case GL_FLOAT_MAT2x3: @@ -692,8 +513,34 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { case GL_FLOAT_MAT4x2: case GL_FLOAT_MAT4x3: #endif - GLCAT.warning() << "GLSL shader requested an unrecognized matrix array type\n"; + GLCAT.warning() << "GLSL shader requested an unrecognized matrix type\n"; continue; + case GL_FLOAT_MAT3: { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._piece = Shader::SMP_upper3x3; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_mat_constant_x; + bind._arg[0] = InternalName::make(param_name); + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; } + case GL_FLOAT_MAT4: { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._piece = Shader::SMP_whole; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_mat_constant_x; + bind._arg[0] = InternalName::make(param_name); + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + s->_mat_spec.push_back(bind); + continue; } case GL_BOOL: case GL_BOOL_VEC2: case GL_BOOL_VEC3: @@ -701,127 +548,199 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { case GL_FLOAT: case GL_FLOAT_VEC2: case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: { - Shader::ShaderPtrSpec bind; + case GL_FLOAT_VEC4: { + Shader::ShaderMatSpec bind; bind._id = arg_id; switch (param_type) { - case GL_BOOL: - case GL_FLOAT: bind._dim[1] = 1; break; - case GL_BOOL_VEC2: - case GL_FLOAT_VEC2: bind._dim[1] = 2; break; - case GL_BOOL_VEC3: - case GL_FLOAT_VEC3: bind._dim[1] = 3; break; - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: bind._dim[1] = 4; break; - case GL_FLOAT_MAT3: bind._dim[1] = 9; break; - case GL_FLOAT_MAT4: bind._dim[1] = 16; break; + case GL_BOOL: + case GL_FLOAT: bind._piece = Shader::SMP_row3x1; break; + case GL_BOOL_VEC2: + case GL_FLOAT_VEC2: bind._piece = Shader::SMP_row3x2; break; + case GL_BOOL_VEC3: + case GL_FLOAT_VEC3: bind._piece = Shader::SMP_row3x3; break; + case GL_BOOL_VEC4: + case GL_FLOAT_VEC4: bind._piece = Shader::SMP_row3 ; break; } - bind._arg = InternalName::make(param_name); - bind._dim[0] = param_size; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_vec_constant_x; + bind._arg[0] = InternalName::make(param_name); bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; bind._dep[1] = Shader::SSD_NONE; - s->_ptr_spec.push_back(bind); + s->_mat_spec.push_back(bind); continue; } case GL_INT: case GL_INT_VEC2: case GL_INT_VEC3: case GL_INT_VEC4: - GLCAT.warning() << "Panda does not support passing integer arrays to shaders (yet)!\n"; + GLCAT.warning() << "Panda does not support passing integers to shaders (yet)!\n"; continue; +#ifndef OPENGLES + case GL_IMAGE_1D_EXT: + case GL_IMAGE_2D_EXT: + case GL_IMAGE_3D_EXT: + case GL_IMAGE_CUBE_EXT: + case GL_IMAGE_2D_ARRAY_EXT: + case GL_INT_IMAGE_1D_EXT: + case GL_INT_IMAGE_2D_EXT: + case GL_INT_IMAGE_3D_EXT: + case GL_INT_IMAGE_CUBE_EXT: + case GL_INT_IMAGE_2D_ARRAY_EXT: + case GL_UNSIGNED_INT_IMAGE_1D_EXT: + case GL_UNSIGNED_INT_IMAGE_2D_EXT: + case GL_UNSIGNED_INT_IMAGE_3D_EXT: + case GL_UNSIGNED_INT_IMAGE_CUBE_EXT: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT: + // This won't really change at runtime, so we might as well + // bind once and then forget about it. + _glgsg->_glUniform1i(p, imgunitno++); + _glsl_img_inputs.push_back(InternalName::make(param_name)); + continue; +#endif default: - GLCAT.warning() << "Ignoring unrecognized GLSL parameter array type!\n"; + GLCAT.warning() << "Ignoring unrecognized GLSL parameter type!\n"; + } + } else { + switch (param_type) { + case GL_FLOAT_MAT2: +#ifndef OPENGLES + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: +#endif + GLCAT.warning() << "GLSL shader requested an unrecognized matrix array type\n"; + continue; + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: { + Shader::ShaderPtrSpec bind; + bind._id = arg_id; + switch (param_type) { + case GL_BOOL: + case GL_FLOAT: bind._dim[1] = 1; break; + case GL_BOOL_VEC2: + case GL_FLOAT_VEC2: bind._dim[1] = 2; break; + case GL_BOOL_VEC3: + case GL_FLOAT_VEC3: bind._dim[1] = 3; break; + case GL_BOOL_VEC4: + case GL_FLOAT_VEC4: bind._dim[1] = 4; break; + case GL_FLOAT_MAT3: bind._dim[1] = 9; break; + case GL_FLOAT_MAT4: bind._dim[1] = 16; break; } + bind._arg = InternalName::make(param_name); + bind._dim[0] = param_size; + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._dep[1] = Shader::SSD_NONE; + s->_ptr_spec.push_back(bind); + continue; } + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + GLCAT.warning() << "Panda does not support passing integer arrays to shaders (yet)!\n"; + continue; + default: + GLCAT.warning() << "Ignoring unrecognized GLSL parameter array type!\n"; } } } - - // Now we've processed the uniforms, we'll process the attribs. - gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTES, ¶m_count); - gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, ¶m_maxlength); - param_name_cstr = (char *)alloca(param_maxlength); - - for (int i = 0; i < param_count; ++i) { - param_name_cstr[0] = 0; - gsg->_glGetActiveAttrib(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name_cstr); - string param_name(param_name_cstr); - - // Get the attrib location. - GLint p = gsg->_glGetAttribLocation(_glsl_program, param_name_cstr); - - GLCAT.debug() << - "Active attribute " << param_name << " is bound to location " << p << "\n"; - - if (p == -1) { - // A gl_ attribute such as gl_Vertex requires us to pass the - // standard vertex arrays as we would do without shader. - // This is not always the case, though -- see below. - _uses_standard_vertex_arrays = true; - continue; - } - - Shader::ShaderArgId arg_id; - arg_id._name = param_name; - arg_id._seqno = seqno++; - _glsl_parameter_map.push_back(p); - - Shader::ShaderVarSpec bind; - bind._id = arg_id; - bind._name = NULL; - bind._append_uv = -1; - - if (param_name.substr(0, 3) == "gl_") { - // Not all drivers return -1 in glGetAttribLocation - // for gl_ prefixed attributes. - _uses_standard_vertex_arrays = true; - continue; - } else if (param_name.substr(0, 4) == "p3d_") { - noprefix = param_name.substr(4); - } else { - noprefix = ""; - } - - if (noprefix.empty()) { - // Arbitrarily named attribute. - bind._name = InternalName::make(param_name); - - } else if (noprefix == "Vertex") { - bind._name = InternalName::get_vertex(); - - } else if (noprefix == "Normal") { - bind._name = InternalName::get_normal(); - - } else if (noprefix == "Color") { - bind._name = InternalName::get_color(); - - } else if (noprefix.substr(0, 7) == "Tangent") { - bind._name = InternalName::get_tangent(); - if (noprefix.size() > 7) { - bind._append_uv = atoi(noprefix.substr(7).c_str()); - } - - } else if (noprefix.substr(0, 8) == "Binormal") { - bind._name = InternalName::get_binormal(); - if (noprefix.size() > 8) { - bind._append_uv = atoi(noprefix.substr(8).c_str()); - } - - } else if (noprefix.substr(0, 13) == "MultiTexCoord") { - bind._name = InternalName::get_texcoord(); - bind._append_uv = atoi(noprefix.substr(13).c_str()); - - } else { - GLCAT.error() << "Unrecognized vertex attrib '" << param_name << "'!\n"; - continue; - } - s->_var_spec.push_back(bind); - } } - gsg->_glUseProgram(0); - } + + // Now we've processed the uniforms, we'll process the attribs. + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTES, ¶m_count); + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, ¶m_maxlength); + param_name_cstr = (char *)alloca(param_maxlength); - gsg->report_my_gl_errors(); + for (int i = 0; i < param_count; ++i) { + param_name_cstr[0] = 0; + _glgsg->_glGetActiveAttrib(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name_cstr); + string param_name(param_name_cstr); + + // Get the attrib location. + GLint p = _glgsg->_glGetAttribLocation(_glsl_program, param_name_cstr); + + GLCAT.debug() << + "Active attribute " << param_name << " is bound to location " << p << "\n"; + + if (p == -1) { + // A gl_ attribute such as gl_Vertex requires us to pass the + // standard vertex arrays as we would do without shader. + // This is not always the case, though -- see below. + _uses_standard_vertex_arrays = true; + continue; + } + + Shader::ShaderArgId arg_id; + arg_id._name = param_name; + arg_id._seqno = seqno++; + _glsl_parameter_map.push_back(p); + + Shader::ShaderVarSpec bind; + bind._id = arg_id; + bind._name = NULL; + bind._append_uv = -1; + + if (param_name.substr(0, 3) == "gl_") { + // Not all drivers return -1 in glGetAttribLocation + // for gl_ prefixed attributes. + _uses_standard_vertex_arrays = true; + continue; + } else if (param_name.substr(0, 4) == "p3d_") { + noprefix = param_name.substr(4); + } else { + noprefix = ""; + } + + if (noprefix.empty()) { + // Arbitrarily named attribute. + bind._name = InternalName::make(param_name); + + } else if (noprefix == "Vertex") { + bind._name = InternalName::get_vertex(); + + } else if (noprefix == "Normal") { + bind._name = InternalName::get_normal(); + + } else if (noprefix == "Color") { + bind._name = InternalName::get_color(); + + } else if (noprefix.substr(0, 7) == "Tangent") { + bind._name = InternalName::get_tangent(); + if (noprefix.size() > 7) { + bind._append_uv = atoi(noprefix.substr(7).c_str()); + } + + } else if (noprefix.substr(0, 8) == "Binormal") { + bind._name = InternalName::get_binormal(); + if (noprefix.size() > 8) { + bind._append_uv = atoi(noprefix.substr(8).c_str()); + } + + } else if (noprefix.substr(0, 13) == "MultiTexCoord") { + bind._name = InternalName::get_texcoord(); + bind._append_uv = atoi(noprefix.substr(13).c_str()); + + } else { + GLCAT.error() << "Unrecognized vertex attrib '" << param_name << "'!\n"; + continue; + } + s->_var_spec.push_back(bind); + } + } + _glgsg->_glUseProgram(0); + + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -831,7 +750,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) { //////////////////////////////////////////////////////////////////// CLP(ShaderContext):: ~CLP(ShaderContext)() { - release_resources(_last_gsg); + release_resources(); } //////////////////////////////////////////////////////////////////// @@ -841,78 +760,58 @@ CLP(ShaderContext):: // vertex program handles or Cg contexts). //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -release_resources(GSG *gsg) { -#if defined(HAVE_CG) && !defined(OPENGLES) - if (_cg_context) { - cgDestroyContext(_cg_context); - _cg_context = 0; - // Do *NOT* destroy the programs here! It causes problems. -// if (_cg_vprogram != 0) cgDestroyProgram(_cg_vprogram); -// if (_cg_fprogram != 0) cgDestroyProgram(_cg_fprogram); -// if (_cg_gprogram != 0) cgDestroyProgram(_cg_gprogram); - _cg_vprogram = 0; - _cg_fprogram = 0; - _cg_gprogram = 0; - _cg_parameter_map.clear(); - } - if (gsg) { - gsg->report_my_gl_errors(); - } else if (glGetError() != GL_NO_ERROR) { - GLCAT.error() << "GL error in ShaderContext destructor\n"; - } -#endif - - if (!gsg) { +release_resources() { + if (!_glgsg) { return; } if (_glsl_program != 0) { if (_glsl_vshader != 0) { - gsg->_glDetachShader(_glsl_program, _glsl_vshader); + _glgsg->_glDetachShader(_glsl_program, _glsl_vshader); } if (_glsl_fshader != 0) { - gsg->_glDetachShader(_glsl_program, _glsl_fshader); + _glgsg->_glDetachShader(_glsl_program, _glsl_fshader); } if (_glsl_gshader != 0) { - gsg->_glDetachShader(_glsl_program, _glsl_gshader); + _glgsg->_glDetachShader(_glsl_program, _glsl_gshader); } if (_glsl_tcshader != 0) { - gsg->_glDetachShader(_glsl_program, _glsl_tcshader); + _glgsg->_glDetachShader(_glsl_program, _glsl_tcshader); } if (_glsl_teshader != 0) { - gsg->_glDetachShader(_glsl_program, _glsl_teshader); + _glgsg->_glDetachShader(_glsl_program, _glsl_teshader); } if (_glsl_cshader != 0) { - gsg->_glDetachShader(_glsl_program, _glsl_cshader); + _glgsg->_glDetachShader(_glsl_program, _glsl_cshader); } - gsg->_glDeleteProgram(_glsl_program); + _glgsg->_glDeleteProgram(_glsl_program); _glsl_program = 0; } if (_glsl_vshader != 0) { - gsg->_glDeleteShader(_glsl_vshader); + _glgsg->_glDeleteShader(_glsl_vshader); _glsl_vshader = 0; } if (_glsl_fshader != 0) { - gsg->_glDeleteShader(_glsl_fshader); + _glgsg->_glDeleteShader(_glsl_fshader); _glsl_fshader = 0; } if (_glsl_gshader != 0) { - gsg->_glDeleteShader(_glsl_gshader); + _glgsg->_glDeleteShader(_glsl_gshader); _glsl_gshader = 0; } if (_glsl_tcshader != 0) { - gsg->_glDeleteShader(_glsl_tcshader); + _glgsg->_glDeleteShader(_glsl_tcshader); _glsl_tcshader = 0; } if (_glsl_teshader != 0) { - gsg->_glDeleteShader(_glsl_teshader); + _glgsg->_glDeleteShader(_glsl_teshader); _glsl_teshader = 0; } if (_glsl_cshader != 0) { - gsg->_glDeleteShader(_glsl_cshader); + _glgsg->_glDeleteShader(_glsl_cshader); _glsl_cshader = 0; } - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -923,40 +822,18 @@ release_resources(GSG *gsg) { // input parameters. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -bind(GSG *gsg, bool reissue_parameters) { - _last_gsg = gsg; - +bind(bool reissue_parameters) { // GLSL shaders need to be bound before passing parameters. - if (_shader->get_language() == Shader::SL_GLSL && !_shader->get_error_flag()) { - gsg->_glUseProgram(_glsl_program); + if (!_shader->get_error_flag()) { + _glgsg->_glUseProgram(_glsl_program); } if (reissue_parameters) { // Pass in k-parameters and transform-parameters - issue_parameters(gsg, Shader::SSD_general); + issue_parameters(Shader::SSD_general); } -#if defined(HAVE_CG) && !defined(OPENGLES) - if (_cg_context != 0) { - // Bind the shaders. - if (_cg_vprogram != 0) { - cgGLEnableProfile(_cg_vprofile); - cgGLBindProgram(_cg_vprogram); - } - if (_cg_fprogram != 0) { - cgGLEnableProfile(_cg_fprofile); - cgGLBindProgram(_cg_fprogram); - } - if (_cg_gprogram != 0) { - cgGLEnableProfile(_cg_gprofile); - cgGLBindProgram(_cg_gprogram); - } - - cg_report_errors(); - } -#endif - - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -965,32 +842,9 @@ bind(GSG *gsg, bool reissue_parameters) { // Description: This function disables a currently-bound shader. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -unbind(GSG *gsg) { - _last_gsg = gsg; - -#if defined(HAVE_CG) && !defined(OPENGLES) - if (_cg_context != 0) { - if (_cg_vprogram != 0) { - cgGLUnbindProgram(_cg_vprofile); - cgGLDisableProfile(_cg_vprofile); - } - if (_cg_fprogram != 0) { - cgGLUnbindProgram(_cg_fprofile); - cgGLDisableProfile(_cg_fprofile); - } - if (_cg_gprogram != 0) { - cgGLUnbindProgram(_cg_gprofile); - cgGLDisableProfile(_cg_gprofile); - } - - cg_report_errors(); - } -#endif - - if (_shader->get_language() == Shader::SL_GLSL) { - gsg->_glUseProgram(0); - } - gsg->report_my_gl_errors(); +unbind() { + _glgsg->_glUseProgram(0); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -1009,10 +863,8 @@ unbind(GSG *gsg) { // transforms. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -issue_parameters(GSG *gsg, int altered) { - _last_gsg = gsg; - - PStatTimer timer(gsg->_draw_set_state_shader_parameters_pcollector); +issue_parameters(int altered) { + PStatTimer timer(_glgsg->_draw_set_state_shader_parameters_pcollector); if (!valid()) { return; @@ -1021,120 +873,28 @@ issue_parameters(GSG *gsg, int altered) { // Iterate through _ptr parameters for (int i=0; i<(int)_shader->_ptr_spec.size(); i++) { if(altered & (_shader->_ptr_spec[i]._dep[0] | _shader->_ptr_spec[i]._dep[1])) { - if (_shader->get_language() == Shader::SL_GLSL) { - const Shader::ShaderPtrSpec& _ptr = _shader->_ptr_spec[i]; - Shader::ShaderPtrData* _ptr_data = - const_cast< Shader::ShaderPtrData*>(gsg->fetch_ptr_parameter(_ptr)); - if (_ptr_data == NULL) { //the input is not contained in ShaderPtrData - release_resources(gsg); - return; - } - GLint p = _glsl_parameter_map[_shader->_ptr_spec[i]._id._seqno]; - switch (_ptr._dim[1]) { - case 1: gsg->_glUniform1fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; - case 2: gsg->_glUniform2fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; - case 3: gsg->_glUniform3fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; - case 4: gsg->_glUniform4fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; - case 9: gsg->_glUniformMatrix3fv(p, _ptr._dim[0], GL_FALSE, (float*)_ptr_data->_ptr); continue; - case 16: gsg->_glUniformMatrix4fv(p, _ptr._dim[0], GL_FALSE, (float*)_ptr_data->_ptr); continue; - } + const Shader::ShaderPtrSpec& _ptr = _shader->_ptr_spec[i]; + Shader::ShaderPtrData* _ptr_data = + const_cast< Shader::ShaderPtrData*>(_glgsg->fetch_ptr_parameter(_ptr)); + if (_ptr_data == NULL) { //the input is not contained in ShaderPtrData + release_resources(); + return; } -#if defined(HAVE_CG) && !defined(OPENGLES) - else if (_shader->get_language() == Shader::SL_Cg) { - const Shader::ShaderPtrSpec& _ptr = _shader->_ptr_spec[i]; - Shader::ShaderPtrData* ptr_data = - const_cast< Shader::ShaderPtrData*>(gsg->fetch_ptr_parameter(_ptr)); - - if (ptr_data == NULL){ //the input is not contained in ShaderPtrData - release_resources(gsg); - return; - } - //check if the data must be shipped to the GPU - /*if (!ptr_data->_updated) - continue; - ptr_data->_updated = false;*/ - - //Check if the size of the shader input and ptr_data match - int input_size = _ptr._dim[0] * _ptr._dim[1] * _ptr._dim[2]; - - // dimension is negative only if the parameter had the (deprecated)k_ prefix. - if ((input_size > ptr_data->_size) && (_ptr._dim[0] > 0)) { - GLCAT.error() << _ptr._id._name << ": incorrect number of elements, expected " - << input_size <<" got " << ptr_data->_size << "\n"; - release_resources(gsg); - return; - } - CGparameter p = _cg_parameter_map[_ptr._id._seqno]; - - switch (ptr_data->_type) { - case Shader::SPT_float: - switch(_ptr._info._class) { - case Shader::SAC_scalar: cgSetParameter1fv(p,(float*)ptr_data->_ptr); continue; - case Shader::SAC_vector: - switch(_ptr._info._type) { - case Shader::SAT_vec1: cgSetParameter1fv(p,(float*)ptr_data->_ptr); continue; - case Shader::SAT_vec2: cgSetParameter2fv(p,(float*)ptr_data->_ptr); continue; - case Shader::SAT_vec3: cgSetParameter3fv(p,(float*)ptr_data->_ptr); continue; - case Shader::SAT_vec4: cgSetParameter4fv(p,(float*)ptr_data->_ptr); continue; - } - case Shader::SAC_matrix: cgGLSetMatrixParameterfc(p,(float*)ptr_data->_ptr); continue; - case Shader::SAC_array: { - switch(_ptr._info._subclass) { - case Shader::SAC_scalar: - cgGLSetParameterArray1f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - case Shader::SAC_vector: - switch(_ptr._dim[2]) { - case 1: cgGLSetParameterArray1f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - case 2: cgGLSetParameterArray2f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - case 3: cgGLSetParameterArray3f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - case 4: cgGLSetParameterArray4f(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - } - case Shader::SAC_matrix: - cgGLSetMatrixParameterArrayfc(p,0,_ptr._dim[0],(float*)ptr_data->_ptr); continue; - } - } - } - case Shader::SPT_double: - switch(_ptr._info._class) { - case Shader::SAC_scalar: cgSetParameter1dv(p,(double*)ptr_data->_ptr); continue; - case Shader::SAC_vector: - switch(_ptr._info._type) { - case Shader::SAT_vec1: cgSetParameter1dv(p,(double*)ptr_data->_ptr); continue; - case Shader::SAT_vec2: cgSetParameter2dv(p,(double*)ptr_data->_ptr); continue; - case Shader::SAT_vec3: cgSetParameter3dv(p,(double*)ptr_data->_ptr); continue; - case Shader::SAT_vec4: cgSetParameter4dv(p,(double*)ptr_data->_ptr); continue; - } - case Shader::SAC_matrix: cgGLSetMatrixParameterdc(p,(double*)ptr_data->_ptr); continue; - case Shader::SAC_array: { - switch(_ptr._info._subclass) { - case Shader::SAC_scalar: - cgGLSetParameterArray1d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - case Shader::SAC_vector: - switch(_ptr._dim[2]) { - case 1: cgGLSetParameterArray1d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - case 2: cgGLSetParameterArray2d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - case 3: cgGLSetParameterArray3d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - case 4: cgGLSetParameterArray4d(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - } - case Shader::SAC_matrix: - cgGLSetMatrixParameterArraydc(p,0,_ptr._dim[0],(double*)ptr_data->_ptr); continue; - } - } - } - default: GLCAT.error() << _ptr._id._name << ":" << "unrecognized parameter type\n"; - release_resources(gsg); - return; - } + GLint p = _glsl_parameter_map[_shader->_ptr_spec[i]._id._seqno]; + switch (_ptr._dim[1]) { + case 1: _glgsg->_glUniform1fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; + case 2: _glgsg->_glUniform2fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; + case 3: _glgsg->_glUniform3fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; + case 4: _glgsg->_glUniform4fv(p, _ptr._dim[0], (float*)_ptr_data->_ptr); continue; + case 9: _glgsg->_glUniformMatrix3fv(p, _ptr._dim[0], GL_FALSE, (float*)_ptr_data->_ptr); continue; + case 16: _glgsg->_glUniformMatrix4fv(p, _ptr._dim[0], GL_FALSE, (float*)_ptr_data->_ptr); continue; } -#endif } } - //FIXME: this could be much faster if we used deferred parameter setting. - for (int i=0; i<(int)_shader->_mat_spec.size(); i++) { if (altered & (_shader->_mat_spec[i]._dep[0] | _shader->_mat_spec[i]._dep[1])) { - const LMatrix4 *val = gsg->fetch_specified_value(_shader->_mat_spec[i], altered); + const LMatrix4 *val = _glgsg->fetch_specified_value(_shader->_mat_spec[i], altered); if (!val) continue; #ifndef STDFLOAT_DOUBLE // In this case, the data is already single-precision. @@ -1145,75 +905,38 @@ issue_parameters(GSG *gsg, int altered) { const PN_float32 *data = valf.get_data(); #endif - if (_shader->get_language() == Shader::SL_GLSL) { - GLint p = _glsl_parameter_map[_shader->_mat_spec[i]._id._seqno]; - switch (_shader->_mat_spec[i]._piece) { - case Shader::SMP_whole: gsg->_glUniformMatrix4fv(p, 1, GL_FALSE, data); continue; - case Shader::SMP_transpose: gsg->_glUniformMatrix4fv(p, 1, GL_TRUE, data); continue; - case Shader::SMP_col0: gsg->_glUniform4f(p, data[0], data[4], data[ 8], data[12]); continue; - case Shader::SMP_col1: gsg->_glUniform4f(p, data[1], data[5], data[ 9], data[13]); continue; - case Shader::SMP_col2: gsg->_glUniform4f(p, data[2], data[6], data[10], data[14]); continue; - case Shader::SMP_col3: gsg->_glUniform4f(p, data[3], data[7], data[11], data[15]); continue; - case Shader::SMP_row0: gsg->_glUniform4fv(p, 1, data+ 0); continue; - case Shader::SMP_row1: gsg->_glUniform4fv(p, 1, data+ 4); continue; - case Shader::SMP_row2: gsg->_glUniform4fv(p, 1, data+ 8); continue; - case Shader::SMP_row3: gsg->_glUniform4fv(p, 1, data+12); continue; - case Shader::SMP_row3x1: gsg->_glUniform1fv(p, 1, data+12); continue; - case Shader::SMP_row3x2: gsg->_glUniform2fv(p, 1, data+12); continue; - case Shader::SMP_row3x3: gsg->_glUniform3fv(p, 1, data+12); continue; - case Shader::SMP_upper3x3: - { - LMatrix3f upper3 = val->get_upper_3(); - gsg->_glUniformMatrix3fv(p, 1, false, upper3.get_data()); - continue; - } - case Shader::SMP_transpose3x3: - { - LMatrix3f upper3 = val->get_upper_3(); - gsg->_glUniformMatrix3fv(p, 1, true, upper3.get_data()); - continue; - } + GLint p = _glsl_parameter_map[_shader->_mat_spec[i]._id._seqno]; + switch (_shader->_mat_spec[i]._piece) { + case Shader::SMP_whole: _glgsg->_glUniformMatrix4fv(p, 1, GL_FALSE, data); continue; + case Shader::SMP_transpose: _glgsg->_glUniformMatrix4fv(p, 1, GL_TRUE, data); continue; + case Shader::SMP_col0: _glgsg->_glUniform4f(p, data[0], data[4], data[ 8], data[12]); continue; + case Shader::SMP_col1: _glgsg->_glUniform4f(p, data[1], data[5], data[ 9], data[13]); continue; + case Shader::SMP_col2: _glgsg->_glUniform4f(p, data[2], data[6], data[10], data[14]); continue; + case Shader::SMP_col3: _glgsg->_glUniform4f(p, data[3], data[7], data[11], data[15]); continue; + case Shader::SMP_row0: _glgsg->_glUniform4fv(p, 1, data+ 0); continue; + case Shader::SMP_row1: _glgsg->_glUniform4fv(p, 1, data+ 4); continue; + case Shader::SMP_row2: _glgsg->_glUniform4fv(p, 1, data+ 8); continue; + case Shader::SMP_row3: _glgsg->_glUniform4fv(p, 1, data+12); continue; + case Shader::SMP_row3x1: _glgsg->_glUniform1fv(p, 1, data+12); continue; + case Shader::SMP_row3x2: _glgsg->_glUniform2fv(p, 1, data+12); continue; + case Shader::SMP_row3x3: _glgsg->_glUniform3fv(p, 1, data+12); continue; + case Shader::SMP_upper3x3: + { + LMatrix3f upper3 = val->get_upper_3(); + _glgsg->_glUniformMatrix3fv(p, 1, false, upper3.get_data()); + continue; + } + case Shader::SMP_transpose3x3: + { + LMatrix3f upper3 = val->get_upper_3(); + _glgsg->_glUniformMatrix3fv(p, 1, true, upper3.get_data()); + continue; } } -#if defined(HAVE_CG) && !defined(OPENGLES) - else if (_shader->get_language() == Shader::SL_Cg) { - CGparameter p = _cg_parameter_map[_shader->_mat_spec[i]._id._seqno]; - switch (_shader->_mat_spec[i]._piece) { - case Shader::SMP_whole: GLfc(cgGLSetMatrixParameter)(p, data); continue; - case Shader::SMP_transpose: GLfr(cgGLSetMatrixParameter)(p, data); continue; - case Shader::SMP_col0: GLf(cgGLSetParameter4)(p, data[0], data[4], data[ 8], data[12]); continue; - case Shader::SMP_col1: GLf(cgGLSetParameter4)(p, data[1], data[5], data[ 9], data[13]); continue; - case Shader::SMP_col2: GLf(cgGLSetParameter4)(p, data[2], data[6], data[10], data[14]); continue; - case Shader::SMP_col3: GLf(cgGLSetParameter4)(p, data[3], data[7], data[11], data[15]); continue; - case Shader::SMP_row0: GLfv(cgGLSetParameter4)(p, data+ 0); continue; - case Shader::SMP_row1: GLfv(cgGLSetParameter4)(p, data+ 4); continue; - case Shader::SMP_row2: GLfv(cgGLSetParameter4)(p, data+ 8); continue; - case Shader::SMP_row3: GLfv(cgGLSetParameter4)(p, data+12); continue; - case Shader::SMP_row3x1: GLfv(cgGLSetParameter1)(p, data+12); continue; - case Shader::SMP_row3x2: GLfv(cgGLSetParameter2)(p, data+12); continue; - case Shader::SMP_row3x3: GLfv(cgGLSetParameter3)(p, data+12); continue; - case Shader::SMP_upper3x3: - { - LMatrix3f upper3 = val->get_upper_3(); - GLfc(cgGLSetMatrixParameter)(p, upper3.get_data()); - continue; - } - case Shader::SMP_transpose3x3: - { - LMatrix3f upper3 = val->get_upper_3(); - GLfr(cgGLSetMatrixParameter)(p, upper3.get_data()); - continue; - } - } - } -#endif } } -#if defined(HAVE_CG) && !defined(OPENGLES) - cg_report_errors(); -#endif - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -1222,29 +945,16 @@ issue_parameters(GSG *gsg, int altered) { // Description: Disable all the vertex arrays used by this shader. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -disable_shader_vertex_arrays(GSG *gsg) { - _last_gsg = gsg; +disable_shader_vertex_arrays() { if (!valid()) { return; } - if (_shader->get_language() == Shader::SL_GLSL) { - for (int i=0; i<(int)_shader->_var_spec.size(); i++) { - gsg->_glDisableVertexAttribArray(i); - } + for (int i=0; i<(int)_shader->_var_spec.size(); i++) { + _glgsg->_glDisableVertexAttribArray(i); } -#if defined(HAVE_CG) && !defined(OPENGLES) - else if (_shader->get_language() == Shader::SL_Cg) { - for (int i=0; i<(int)_shader->_var_spec.size(); i++) { - CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; - if (p == 0) continue; - cgGLDisableClientState(p); - } - cg_report_errors(); - } -#endif - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -1259,19 +969,14 @@ disable_shader_vertex_arrays(GSG *gsg) { // reenable them. We may optimize this someday. //////////////////////////////////////////////////////////////////// bool CLP(ShaderContext):: -update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, - bool force) { - _last_gsg = gsg; - if (prev) prev->disable_shader_vertex_arrays(gsg); +update_shader_vertex_arrays(ShaderContext *prev, bool force) { + if (prev) prev->disable_shader_vertex_arrays(); if (!valid()) { return true; } -#if defined(HAVE_CG) && !defined(OPENGLES) - cg_report_errors(); -#endif #ifdef SUPPORT_IMMEDIATE_MODE - if (gsg->_use_sender) { + if (_glgsg->_use_sender) { GLCAT.error() << "immediate mode shaders not implemented yet\n"; } else #endif // SUPPORT_IMMEDIATE_MODE @@ -1281,18 +986,10 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, int start, stride, num_values; int nvarying = _shader->_var_spec.size(); for (int i = 0; i < nvarying; ++i) { -#if defined(HAVE_CG) && !defined(OPENGLES) - if (_shader->get_language() == Shader::SL_Cg) { - if (_cg_parameter_map[_shader->_var_spec[i]._id._seqno] == 0) { - continue; - } - } -#endif - InternalName *name = _shader->_var_spec[i]._name; int texslot = _shader->_var_spec[i]._append_uv; - if (texslot >= 0 && texslot < gsg->_state_texture->get_num_on_stages()) { - TextureStage *stage = gsg->_state_texture->get_on_stage(texslot); + if (texslot >= 0 && texslot < _glgsg->_state_texture->get_num_on_stages()) { + TextureStage *stage = _glgsg->_state_texture->get_on_stage(texslot); InternalName *texname = stage->get_texcoord_name(); if (name == InternalName::get_texcoord()) { @@ -1301,43 +998,23 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, name = name->append(texname->get_basename()); } } - if (gsg->_data_reader->get_array_info(name, + if (_glgsg->_data_reader->get_array_info(name, array_reader, num_values, numeric_type, start, stride)) { const unsigned char *client_pointer; - if (!gsg->setup_array_data(client_pointer, array_reader, force)) { + if (!_glgsg->setup_array_data(client_pointer, array_reader, force)) { return false; } - if (_shader->get_language() == Shader::SL_GLSL) { - const GLint p = _glsl_parameter_map[_shader->_var_spec[i]._id._seqno]; - gsg->_glEnableVertexAttribArray(p); - gsg->_glVertexAttribPointer(p, num_values, gsg->get_numeric_type(numeric_type), - GL_TRUE, stride, client_pointer + start); - -#if defined(HAVE_CG) && !defined(OPENGLES) - } else if (_shader->get_language() == Shader::SL_Cg) { - CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; - cgGLSetParameterPointer(p, - num_values, gsg->get_numeric_type(numeric_type), - stride, client_pointer + start); - cgGLEnableClientState(p); -#endif - } + const GLint p = _glsl_parameter_map[_shader->_var_spec[i]._id._seqno]; + _glgsg->_glEnableVertexAttribArray(p); + _glgsg->_glVertexAttribPointer(p, num_values, _glgsg->get_numeric_type(numeric_type), + GL_TRUE, stride, client_pointer + start); } -#if defined(HAVE_CG) && !defined(OPENGLES) - else if (_shader->get_language() == Shader::SL_Cg) { - CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno]; - cgGLDisableClientState(p); - } -#endif } } -#if defined(HAVE_CG) && !defined(OPENGLES) - cg_report_errors(); -#endif - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); return true; } @@ -1348,45 +1025,34 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, // Description: Disable all the texture bindings used by this shader. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -disable_shader_texture_bindings(GSG *gsg) { - _last_gsg = gsg; +disable_shader_texture_bindings() { if (!valid()) { return; } #ifndef OPENGLES_2 for (int i=0; i<(int)_shader->_tex_spec.size(); i++) { - if (_shader->get_language() == Shader::SL_GLSL) { - if (_shader->_tex_spec[i]._name == 0) { - gsg->_glActiveTexture(GL_TEXTURE0 + _shader->_tex_spec[i]._stage); - } else { - gsg->_glActiveTexture(GL_TEXTURE0 + _shader->_tex_spec[i]._stage + _stage_offset); - } -#if defined(HAVE_CG) && !defined(OPENGLES) - } else if (_shader->get_language() == Shader::SL_Cg) { - CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno]; - if (p == 0) continue; - int texunit = cgGetParameterResourceIndex(p); - gsg->_glActiveTexture(GL_TEXTURE0 + texunit); -#endif + if (_shader->_tex_spec[i]._name == 0) { + _glgsg->_glActiveTexture(GL_TEXTURE0 + _shader->_tex_spec[i]._stage); } else { - return; + _glgsg->_glActiveTexture(GL_TEXTURE0 + _shader->_tex_spec[i]._stage + _stage_offset); } + #ifndef OPENGLES glBindTexture(GL_TEXTURE_1D, 0); #endif // OPENGLES glBindTexture(GL_TEXTURE_2D, 0); #ifndef OPENGLES_1 - if (gsg->_supports_3d_texture) { + if (_glgsg->_supports_3d_texture) { glBindTexture(GL_TEXTURE_3D, 0); } #endif // OPENGLES_1 #ifndef OPENGLES - if (gsg->_supports_2d_texture_array) { + if (_glgsg->_supports_2d_texture_array) { glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 0); } #endif - if (gsg->_supports_cube_map) { + if (_glgsg->_supports_cube_map) { glBindTexture(GL_TEXTURE_CUBE_MAP, 0); } // This is probably faster - but maybe not as safe? @@ -1395,27 +1061,21 @@ disable_shader_texture_bindings(GSG *gsg) { #endif // OPENGLES_2 _stage_offset = 0; -#if defined(HAVE_CG) && !defined(OPENGLES) - cg_report_errors(); -#endif - #ifndef OPENGLES // Now unbind all the image units. Not sure if we *have* to do this. - int num_image_units = min(_glsl_img_inputs.size(), (size_t)gsg->_max_image_units); + int num_image_units = min(_glsl_img_inputs.size(), (size_t)_glgsg->_max_image_units); - if (num_image_units > 0 && _shader->get_language() == Shader::SL_GLSL) { - if (gsg->_supports_multi_bind) { - gsg->_glBindImageTextures(0, num_image_units, NULL); + if (_glgsg->_supports_multi_bind) { + _glgsg->_glBindImageTextures(0, num_image_units, NULL); - } else { - for (int i = 0; i < num_image_units; ++i) { - gsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); - } + } else { + for (int i = 0; i < num_image_units; ++i) { + _glgsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); } } #endif - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -1430,11 +1090,9 @@ disable_shader_texture_bindings(GSG *gsg) { // reenable them. We may optimize this someday. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) { - _last_gsg = gsg; - +update_shader_texture_bindings(ShaderContext *prev) { if (prev) { - prev->disable_shader_texture_bindings(gsg); + prev->disable_shader_texture_bindings(); } if (!valid()) { @@ -1443,34 +1101,21 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) { // We get the TextureAttrib directly from the _target_rs, not the // filtered TextureAttrib in _target_texture. - const TextureAttrib *texattrib = DCAST(TextureAttrib, gsg->_target_rs->get_attrib_def(TextureAttrib::get_class_slot())); + const TextureAttrib *texattrib = DCAST(TextureAttrib, _glgsg->_target_rs->get_attrib_def(TextureAttrib::get_class_slot())); nassertv(texattrib != (TextureAttrib *)NULL); _stage_offset = texattrib->get_num_on_stages(); for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) { InternalName *id = _shader->_tex_spec[i]._name; - int texunit; - - if (_shader->get_language() == Shader::SL_GLSL) { - texunit = _shader->_tex_spec[i]._stage; - if (id != 0) { - texunit += _stage_offset; - } + int texunit = _shader->_tex_spec[i]._stage; + if (id != 0) { + texunit += _stage_offset; } -#if defined(HAVE_CG) && !defined(OPENGLES) - else if (_shader->get_language() == Shader::SL_Cg) { - CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno]; - if (p == 0) { - continue; - } - texunit = cgGetParameterResourceIndex(p); - } -#endif Texture *tex = 0; - int view = gsg->get_current_tex_view_offset(); + int view = _glgsg->get_current_tex_view_offset(); if (id != 0) { - const ShaderInput *input = gsg->_target_shader->get_shader_input(id); + const ShaderInput *input = _glgsg->_target_shader->get_shader_input(id); tex = input->get_texture(); } else { if (_shader->_tex_spec[i]._stage >= texattrib->get_num_on_stages()) { @@ -1491,56 +1136,50 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) { continue; } - gsg->_glActiveTexture(GL_TEXTURE0 + texunit); + _glgsg->_glActiveTexture(GL_TEXTURE0 + texunit); - TextureContext *tc = tex->prepare_now(view, gsg->_prepared_objects, gsg); + TextureContext *tc = tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg); if (tc == (TextureContext*)NULL) { continue; } - GLenum target = gsg->get_texture_target(tex->get_texture_type()); + GLenum target = _glgsg->get_texture_target(tex->get_texture_type()); if (target == GL_NONE) { // Unsupported texture mode. continue; } - if (_shader->get_language() == Shader::SL_GLSL) { - GLint p = _glsl_parameter_map[_shader->_tex_spec[i]._id._seqno]; - gsg->_glUniform1i(p, texunit); - } + GLint p = _glsl_parameter_map[_shader->_tex_spec[i]._id._seqno]; + _glgsg->_glUniform1i(p, texunit); - if (!gsg->update_texture(tc, false)) { + if (!_glgsg->update_texture(tc, false)) { continue; } } -#if defined(HAVE_CG) && !defined(OPENGLES) - cg_report_errors(); -#endif - #ifndef OPENGLES // Now bind all the 'image units'; a bit of an esoteric OpenGL feature right now. - int num_image_units = min(_glsl_img_inputs.size(), (size_t)gsg->_max_image_units); + int num_image_units = min(_glsl_img_inputs.size(), (size_t)_glgsg->_max_image_units); - if (num_image_units > 0 && _shader->get_language() == Shader::SL_GLSL) { + if (num_image_units > 0) { GLuint *multi_img = NULL; // If we support multi-bind, prepare an array. - if (gsg->_supports_multi_bind && num_image_units > 1) { + if (_glgsg->_supports_multi_bind && num_image_units > 1) { multi_img = new GLuint[num_image_units]; } for (int i = 0; i < num_image_units; ++i) { const InternalName *name = _glsl_img_inputs[i]; - Texture *tex = gsg->_target_shader->get_shader_input_texture(name); + Texture *tex = _glgsg->_target_shader->get_shader_input_texture(name); GLuint gl_tex = 0; if (tex != NULL) { - int view = gsg->get_current_tex_view_offset(); + int view = _glgsg->get_current_tex_view_offset(); - CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, gsg->_prepared_objects, gsg)); + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg)); if (gtc != (TextureContext*)NULL) { gl_tex = gtc->_index; - gsg->update_texture(gtc, true); + _glgsg->update_texture(gtc, true); } } @@ -1551,23 +1190,23 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) { } else { // We don't support multi-bind, so bind now in the same way that multi-bind would have done it. if (gl_tex == 0) { - gsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); + _glgsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); } else { //TODO: automatically convert to sized type instead of plain GL_RGBA - GLint internal_format = gsg->get_internal_image_format(tex); - gsg->_glBindImageTexture(i, gl_tex, 0, GL_TRUE, 0, GL_READ_WRITE, internal_format); + GLint internal_format = _glgsg->get_internal_image_format(tex); + _glgsg->_glBindImageTexture(i, gl_tex, 0, GL_TRUE, 0, GL_READ_WRITE, internal_format); } } } if (multi_img != NULL) { - gsg->_glBindImageTextures(0, num_image_units, multi_img); + _glgsg->_glBindImageTextures(0, num_image_units, multi_img); delete[] multi_img; } } #endif - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } //////////////////////////////////////////////////////////////////// @@ -1576,16 +1215,16 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) { // Description: This subroutine prints the infolog for a shader. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -glsl_report_shader_errors(GSG *gsg, unsigned int shader) { +glsl_report_shader_errors(unsigned int shader) { char *info_log; GLint length = 0; GLint num_chars = 0; - gsg->_glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); + _glgsg->_glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); if (length > 1) { info_log = (char *) malloc(length); - gsg->_glGetShaderInfoLog(shader, length, &num_chars, info_log); + _glgsg->_glGetShaderInfoLog(shader, length, &num_chars, info_log); if (strcmp(info_log, "Success.\n") != 0 && strcmp(info_log, "No errors.\n") != 0) { GLCAT.error(false) << info_log << "\n"; } @@ -1599,16 +1238,16 @@ glsl_report_shader_errors(GSG *gsg, unsigned int shader) { // Description: This subroutine prints the infolog for a program. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -glsl_report_program_errors(GSG *gsg, unsigned int program) { +glsl_report_program_errors(unsigned int program) { char *info_log; GLint length = 0; GLint num_chars = 0; - gsg->_glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); + _glgsg->_glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); if (length > 1) { info_log = (char *) malloc(length); - gsg->_glGetProgramInfoLog(program, length, &num_chars, info_log); + _glgsg->_glGetProgramInfoLog(program, length, &num_chars, info_log); if (strcmp(info_log, "Success.\n") != 0 && strcmp(info_log, "No errors.\n") != 0) { GLCAT.error(false) << info_log << "\n"; } @@ -1622,61 +1261,61 @@ glsl_report_program_errors(GSG *gsg, unsigned int program) { // Description: //////////////////////////////////////////////////////////////////// unsigned int CLP(ShaderContext):: -glsl_compile_entry_point(GSG *gsg, Shader::ShaderType type) { +glsl_compile_entry_point(Shader::ShaderType type) { unsigned int handle = 0; switch (type) { case Shader::ST_vertex: - handle = gsg->_glCreateShader(GL_VERTEX_SHADER); + handle = _glgsg->_glCreateShader(GL_VERTEX_SHADER); break; case Shader::ST_fragment: - handle = gsg->_glCreateShader(GL_FRAGMENT_SHADER); + handle = _glgsg->_glCreateShader(GL_FRAGMENT_SHADER); break; #ifndef OPENGLES case Shader::ST_geometry: - if (gsg->get_supports_geometry_shaders()) { - handle = gsg->_glCreateShader(GL_GEOMETRY_SHADER); + if (_glgsg->get_supports_geometry_shaders()) { + handle = _glgsg->_glCreateShader(GL_GEOMETRY_SHADER); } break; case Shader::ST_tess_control: - if (gsg->get_supports_tessellation_shaders()) { - handle = gsg->_glCreateShader(GL_TESS_CONTROL_SHADER); + if (_glgsg->get_supports_tessellation_shaders()) { + handle = _glgsg->_glCreateShader(GL_TESS_CONTROL_SHADER); } break; case Shader::ST_tess_evaluation: - if (gsg->get_supports_tessellation_shaders()) { - handle = gsg->_glCreateShader(GL_TESS_EVALUATION_SHADER); + if (_glgsg->get_supports_tessellation_shaders()) { + handle = _glgsg->_glCreateShader(GL_TESS_EVALUATION_SHADER); } break; case Shader::ST_compute: - if (gsg->get_supports_compute_shaders()) { - handle = gsg->_glCreateShader(GL_COMPUTE_SHADER); + if (_glgsg->get_supports_compute_shaders()) { + handle = _glgsg->_glCreateShader(GL_COMPUTE_SHADER); } break; #endif } if (!handle) { - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); return 0; } string text_str = _shader->get_text(type); const char* text = text_str.c_str(); - gsg->_glShaderSource(handle, 1, &text, NULL); - gsg->_glCompileShader(handle); + _glgsg->_glShaderSource(handle, 1, &text, NULL); + _glgsg->_glCompileShader(handle); GLint status; - gsg->_glGetShaderiv(handle, GL_COMPILE_STATUS, &status); + _glgsg->_glGetShaderiv(handle, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { GLCAT.error() << "An error occurred while compiling shader " << _shader->get_filename(type) << "\n"; - glsl_report_shader_errors(gsg, handle); - gsg->_glDeleteShader(handle); - gsg->report_my_gl_errors(); + glsl_report_shader_errors(handle); + _glgsg->_glDeleteShader(handle); + _glgsg->report_my_gl_errors(); return 0; } - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); return handle; } @@ -1686,92 +1325,92 @@ glsl_compile_entry_point(GSG *gsg, Shader::ShaderType type) { // Description: This subroutine compiles a GLSL shader. //////////////////////////////////////////////////////////////////// bool CLP(ShaderContext):: -glsl_compile_shader(GSG *gsg) { - _glsl_program = gsg->_glCreateProgram(); +glsl_compile_shader() { + _glsl_program = _glgsg->_glCreateProgram(); if (!_glsl_program) return false; if (!_shader->get_text(Shader::ST_vertex).empty()) { - _glsl_vshader = glsl_compile_entry_point(gsg, Shader::ST_vertex); + _glsl_vshader = glsl_compile_entry_point(Shader::ST_vertex); if (!_glsl_vshader) return false; - gsg->_glAttachShader(_glsl_program, _glsl_vshader); + _glgsg->_glAttachShader(_glsl_program, _glsl_vshader); } if (!_shader->get_text(Shader::ST_fragment).empty()) { - _glsl_fshader = glsl_compile_entry_point(gsg, Shader::ST_fragment); + _glsl_fshader = glsl_compile_entry_point(Shader::ST_fragment); if (!_glsl_fshader) return false; - gsg->_glAttachShader(_glsl_program, _glsl_fshader); + _glgsg->_glAttachShader(_glsl_program, _glsl_fshader); } if (!_shader->get_text(Shader::ST_geometry).empty()) { - _glsl_gshader = glsl_compile_entry_point(gsg, Shader::ST_geometry); + _glsl_gshader = glsl_compile_entry_point(Shader::ST_geometry); if (!_glsl_gshader) return false; - gsg->_glAttachShader(_glsl_program, _glsl_gshader); + _glgsg->_glAttachShader(_glsl_program, _glsl_gshader); #ifdef OPENGLES nassertr(false, false); // OpenGL ES has no geometry shaders. #else // Set the vertex output limit to the maximum - nassertr(gsg->_glProgramParameteri != NULL, false); + nassertr(_glgsg->_glProgramParameteri != NULL, false); GLint max_vertices; glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &max_vertices); - gsg->_glProgramParameteri(_glsl_program, GL_GEOMETRY_VERTICES_OUT_ARB, max_vertices); + _glgsg->_glProgramParameteri(_glsl_program, GL_GEOMETRY_VERTICES_OUT_ARB, max_vertices); #endif - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); } if (!_shader->get_text(Shader::ST_tess_control).empty()) { - _glsl_tcshader = glsl_compile_entry_point(gsg, Shader::ST_tess_control); + _glsl_tcshader = glsl_compile_entry_point(Shader::ST_tess_control); if (!_glsl_tcshader) return false; - gsg->_glAttachShader(_glsl_program, _glsl_tcshader); + _glgsg->_glAttachShader(_glsl_program, _glsl_tcshader); } if (!_shader->get_text(Shader::ST_tess_evaluation).empty()) { - _glsl_teshader = glsl_compile_entry_point(gsg, Shader::ST_tess_evaluation); + _glsl_teshader = glsl_compile_entry_point(Shader::ST_tess_evaluation); if (!_glsl_teshader) return false; - gsg->_glAttachShader(_glsl_program, _glsl_teshader); + _glgsg->_glAttachShader(_glsl_program, _glsl_teshader); } if (!_shader->get_text(Shader::ST_compute).empty()) { - _glsl_cshader = glsl_compile_entry_point(gsg, Shader::ST_compute); + _glsl_cshader = glsl_compile_entry_point(Shader::ST_compute); if (!_glsl_cshader) return false; - gsg->_glAttachShader(_glsl_program, _glsl_cshader); + _glgsg->_glAttachShader(_glsl_program, _glsl_cshader); } // There might be warnings. Only report them for one shader program. if (_glsl_vshader != 0) { - glsl_report_shader_errors(gsg, _glsl_vshader); + glsl_report_shader_errors(_glsl_vshader); } else if (_glsl_fshader != 0) { - glsl_report_shader_errors(gsg, _glsl_fshader); + glsl_report_shader_errors(_glsl_fshader); } else if (_glsl_gshader != 0) { - glsl_report_shader_errors(gsg, _glsl_gshader); + glsl_report_shader_errors(_glsl_gshader); } else if (_glsl_tcshader != 0) { - glsl_report_shader_errors(gsg, _glsl_tcshader); + glsl_report_shader_errors(_glsl_tcshader); } else if (_glsl_teshader != 0) { - glsl_report_shader_errors(gsg, _glsl_teshader); + glsl_report_shader_errors(_glsl_teshader); } // If we requested to retrieve the shader, we should indicate that before linking. #if !defined(NDEBUG) && !defined(OPENGLES) - if (gl_dump_compiled_shaders && gsg->_supports_get_program_binary) { - gsg->_glProgramParameteri(_glsl_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); + if (gl_dump_compiled_shaders && _glgsg->_supports_get_program_binary) { + _glgsg->_glProgramParameteri(_glsl_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); } #endif - gsg->_glLinkProgram(_glsl_program); + _glgsg->_glLinkProgram(_glsl_program); GLint status; - gsg->_glGetProgramiv(_glsl_program, GL_LINK_STATUS, &status); + _glgsg->_glGetProgramiv(_glsl_program, GL_LINK_STATUS, &status); if (status != GL_TRUE) { GLCAT.error() << "An error occurred while linking shader program!\n"; - glsl_report_program_errors(gsg, _glsl_program); + glsl_report_program_errors(_glsl_program); return false; } // Dump the binary if requested. #if !defined(NDEBUG) && !defined(OPENGLES) - if (gl_dump_compiled_shaders && gsg->_supports_get_program_binary) { + if (gl_dump_compiled_shaders && _glgsg->_supports_get_program_binary) { GLint length = 0; - gsg->_glGetProgramiv(_glsl_program, GL_PROGRAM_BINARY_LENGTH, &length); + _glgsg->_glGetProgramiv(_glsl_program, GL_PROGRAM_BINARY_LENGTH, &length); length += 2; char filename[64]; @@ -1781,7 +1420,7 @@ glsl_compile_shader(GSG *gsg) { char *binary = new char[length]; GLenum format; GLsizei num_bytes; - gsg->_glGetProgramBinary(_glsl_program, length, &num_bytes, &format, (void*)binary); + _glgsg->_glGetProgramBinary(_glsl_program, length, &num_bytes, &format, (void*)binary); pofstream s; s.open(filename, ios::out | ios::binary); @@ -1795,7 +1434,7 @@ glsl_compile_shader(GSG *gsg) { } #endif // NDEBUG - gsg->report_my_gl_errors(); + _glgsg->report_my_gl_errors(); return true; } diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index c1eaec6267..1ce7277647 100755 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -21,53 +21,34 @@ #include "shaderContext.h" #include "deletedChain.h" -#if defined(HAVE_CG) && !defined(OPENGLES) -#include -#endif - class CLP(GraphicsStateGuardian); //////////////////////////////////////////////////////////////////// // Class : GLShaderContext // Description : xyz //////////////////////////////////////////////////////////////////// -class EXPCL_GL CLP(ShaderContext): public ShaderContext { +class EXPCL_GL CLP(ShaderContext) : public ShaderContext { public: friend class CLP(GraphicsStateGuardian); - typedef CLP(GraphicsStateGuardian) GSG; - CLP(ShaderContext)(Shader *s, GSG *gsg); + CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s); ~CLP(ShaderContext)(); ALLOC_DELETED_CHAIN(CLP(ShaderContext)); INLINE bool valid(void); - void bind(GSG *gsg, bool reissue_parameters = true); - void unbind(GSG *gsg); - void issue_parameters(GSG *gsg, int altered); - void disable_shader_vertex_arrays(GSG *gsg); - bool update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, - bool force); - void disable_shader_texture_bindings(GSG *gsg); - void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg); + void bind(bool reissue_parameters = true); + void unbind(); + void issue_parameters(int altered); + void disable_shader_vertex_arrays(); + bool update_shader_vertex_arrays(ShaderContext *prev, bool force); + void disable_shader_texture_bindings(); + void update_shader_texture_bindings(ShaderContext *prev); INLINE bool uses_standard_vertex_arrays(void); INLINE bool uses_custom_vertex_arrays(void); INLINE bool uses_custom_texture_bindings(void); private: - -#if defined(HAVE_CG) && !defined(OPENGLES) - CGcontext _cg_context; - CGprogram _cg_vprogram; - CGprogram _cg_fprogram; - CGprogram _cg_gprogram; - CGprofile _cg_vprofile; - CGprofile _cg_fprofile; - CGprofile _cg_gprofile; - - pvector _cg_parameter_map; -#endif - GLuint _glsl_program; GLuint _glsl_vshader; GLuint _glsl_fshader; @@ -81,18 +62,16 @@ private: pvector _glsl_img_inputs; int _stage_offset; - // Avoid using this! It merely exists so the - // destructor has access to the extension functions. - WPT(GSG) _last_gsg; + CLP(GraphicsStateGuardian) *_glgsg; bool _uses_standard_vertex_arrays; - void glsl_report_shader_errors(GSG *gsg, unsigned int shader); - void glsl_report_program_errors(GSG *gsg, unsigned int program); - unsigned int glsl_compile_entry_point(GSG *gsg, Shader::ShaderType type); - bool glsl_compile_shader(GSG *gsg); + void glsl_report_shader_errors(unsigned int shader); + void glsl_report_program_errors(unsigned int program); + unsigned int glsl_compile_entry_point(Shader::ShaderType type); + bool glsl_compile_shader(); bool parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *s); - void release_resources(GSG *gsg); + void release_resources(); public: static TypeHandle get_class_type() { @@ -115,4 +94,3 @@ private: #include "glShaderContext_src.I" #endif // OPENGLES_1 - diff --git a/panda/src/glstuff/glstuff_src.cxx b/panda/src/glstuff/glstuff_src.cxx index 6a46538784..49d54804b8 100644 --- a/panda/src/glstuff/glstuff_src.cxx +++ b/panda/src/glstuff/glstuff_src.cxx @@ -25,8 +25,7 @@ #include "glGeomContext_src.cxx" #include "glGeomMunger_src.cxx" #include "glShaderContext_src.cxx" +#include "glCgShaderContext_src.cxx" #include "glImmediateModeSender_src.cxx" #include "glGraphicsBuffer_src.cxx" #include "glGraphicsStateGuardian_src.cxx" - - diff --git a/panda/src/glstuff/glstuff_src.h b/panda/src/glstuff/glstuff_src.h index 0c48fafdac..0892a8bba3 100644 --- a/panda/src/glstuff/glstuff_src.h +++ b/panda/src/glstuff/glstuff_src.h @@ -39,6 +39,7 @@ #include "glGeomContext_src.h" #include "glGeomMunger_src.h" #include "glShaderContext_src.h" +#include "glCgShaderContext_src.h" #include "glImmediateModeSender_src.h" #include "glGraphicsBuffer_src.h" #include "glGraphicsStateGuardian_src.h" diff --git a/panda/src/gobj/shaderContext.h b/panda/src/gobj/shaderContext.h index 18b4a3ed2a..5785b155c9 100755 --- a/panda/src/gobj/shaderContext.h +++ b/panda/src/gobj/shaderContext.h @@ -36,10 +36,23 @@ class EXPCL_PANDA_GOBJ ShaderContext: public SavedContext { public: INLINE ShaderContext(Shader *se); + INLINE virtual bool valid() { return false; } + INLINE virtual void bind(bool reissue_parameters = true) {}; + INLINE virtual void unbind() {}; + INLINE virtual void issue_parameters(int altered) {}; + INLINE virtual void disable_shader_vertex_arrays() {}; + INLINE virtual bool update_shader_vertex_arrays(ShaderContext *prev, bool force) { return false; }; + INLINE virtual void disable_shader_texture_bindings() {}; + INLINE virtual void update_shader_texture_bindings(ShaderContext *prev) {}; + + INLINE virtual bool uses_standard_vertex_arrays(void) { return true; }; + INLINE virtual bool uses_custom_vertex_arrays(void) { return false; }; + INLINE virtual bool uses_custom_texture_bindings(void) { return false; }; + PUBLISHED: INLINE Shader *get_shader() const; -public: +public: Shader *_shader; public: