mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
This is another big commit - chief new features are:
* Working OpenGL ES 2.x support. Yay! * The shader code now supports separate vertex/fragment/geometry shaders. * The GLSL code supports passing vertex attrib arrays.
This commit is contained in:
parent
44bcbe3de6
commit
66349ecaba
@ -107,6 +107,23 @@ static void APIENTRY
|
||||
null_glBlendColor(GLclampf, GLclampf, GLclampf, GLclampf) {
|
||||
}
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
// We have a default shader that will be applied when there
|
||||
// isn't any shader applied (e.g. if it failed to compile).
|
||||
// We need this because OpenGL ES 2.x does not have
|
||||
// a fixed-function pipeline.
|
||||
// This default shader just outputs a red color, telling
|
||||
// the user that something went wrong.
|
||||
CPT(Shader::ShaderFile) default_shader_name = new Shader::ShaderFile("default-shader");
|
||||
CPT(Shader::ShaderFile) default_shader_body = new Shader::ShaderFile("\
|
||||
uniform mediump mat4 p3d_ModelViewProjectionMatrix;\
|
||||
attribute highp vec4 p3d_Vertex;\
|
||||
void main(void) {\
|
||||
gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;\
}\n",
|
||||
"void main(void) {\
|
||||
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\
|
||||
}\n");
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: uchar_bgr_to_rgb
|
||||
@ -817,12 +834,12 @@ reset() {
|
||||
if (basic_shaders_only) {
|
||||
_shader_caps._active_vprofile = (int)CG_PROFILE_ARBVP1;
|
||||
_shader_caps._active_fprofile = (int)CG_PROFILE_ARBFP1;
|
||||
_shader_caps._active_gprofile = (int)0; // CG2 CHANGE: No geometry shader if only using basic
|
||||
_shader_caps._active_gprofile = (int)0; // No geometry shader if only using basic
|
||||
} else {
|
||||
_shader_caps._active_vprofile = (int)cgGLGetLatestProfile(CG_GL_VERTEX);
|
||||
_shader_caps._active_fprofile = (int)cgGLGetLatestProfile(CG_GL_FRAGMENT);
|
||||
#ifdef CG_CL_GEOMETRY
|
||||
_shader_caps._active_gprofile = (int)cgGLGetLatestProfile(CG_GL_GEOMETRY); // CG2 CHANGE
|
||||
_shader_caps._active_gprofile = (int)cgGLGetLatestProfile(CG_GL_GEOMETRY);
|
||||
#else
|
||||
_shader_caps._active_gprofile = (int)0;
|
||||
#endif
|
||||
@ -830,7 +847,7 @@ reset() {
|
||||
_shader_caps._ultimate_vprofile = (int)CG_PROFILE_VP40;
|
||||
_shader_caps._ultimate_fprofile = (int)CG_PROFILE_FP40;
|
||||
#ifdef CG_PROFILE_GPU_CP
|
||||
_shader_caps._ultimate_gprofile = (int)CG_PROFILE_GPU_GP; // CG2 CHANGE
|
||||
_shader_caps._ultimate_gprofile = (int)CG_PROFILE_GPU_GP;
|
||||
#else
|
||||
_shader_caps._ultimate_gprofile = (int)0;
|
||||
#endif
|
||||
@ -862,10 +879,12 @@ reset() {
|
||||
#endif
|
||||
_shader_caps._supports_glsl = _supports_glsl;
|
||||
|
||||
#ifndef OPENGLES_1
|
||||
#ifndef OPENGLES
|
||||
if (_supports_glsl) {
|
||||
_glAttachShader = (PFNGLATTACHSHADERPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "AttachShader");
|
||||
_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "BindAttribLocation");
|
||||
_glCompileShader = (PFNGLCOMPILESHADERPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "CompileShader");
|
||||
_glCreateProgram = (PFNGLCREATEPROGRAMPROC)
|
||||
@ -878,8 +897,16 @@ reset() {
|
||||
get_extension_func(GLPREFIX_QUOTED, "DeleteShader");
|
||||
_glDetachShader = (PFNGLDETACHSHADERPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "DetachShader");
|
||||
_glDisableVertexAttribArray (PFNGLDISABLEVERTEXATTRIBARRAYPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "DisableVertexAttribArray");
|
||||
_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "EnableVertexAttribArray");
|
||||
_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "GetActiveAttrib");
|
||||
_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "GetActiveUniform");
|
||||
_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "GetAttribLocation");
|
||||
_glGetProgramiv = (PFNGLGETPROGRAMIVPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "GetProgramiv");
|
||||
_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)
|
||||
@ -912,9 +939,50 @@ reset() {
|
||||
get_extension_func(GLPREFIX_QUOTED, "UniformMatrix4fv");
|
||||
_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "ValidateProgram");
|
||||
_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "VertexAttribPointer");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
_glAttachShader = glAttachShader;
|
||||
_glBindAttribLocation = glBindAttribLocation;
|
||||
_glCompileShader = glCompileShader;
|
||||
_glCreateProgram = glCreateProgram;
|
||||
_glCreateShader = glCreateShader;
|
||||
_glDeleteProgram = glDeleteProgram;
|
||||
_glDeleteShader = glDeleteShader;
|
||||
_glDetachShader = glDetachShader;
|
||||
_glDisableVertexAttribArray = glDisableVertexAttribArray;
|
||||
_glEnableVertexAttribArray = glEnableVertexAttribArray;
|
||||
_glGetActiveAttrib = glGetActiveAttrib;
|
||||
_glGetActiveUniform = glGetActiveUniform;
|
||||
_glGetAttribLocation = glGetAttribLocation;
|
||||
_glGetProgramiv = glGetProgramiv;
|
||||
_glGetProgramInfoLog = glGetProgramInfoLog;
|
||||
_glGetShaderiv = glGetShaderiv;
|
||||
_glGetShaderInfoLog = glGetShaderInfoLog;
|
||||
_glGetUniformLocation = glGetUniformLocation;
|
||||
_glLinkProgram = glLinkProgram;
|
||||
_glShaderSource = glShaderSource;
|
||||
_glUseProgram = glUseProgram;
|
||||
_glUniform4f = glUniform4f;
|
||||
_glUniform1i = glUniform1i;
|
||||
_glUniform1fv = glUniform1fv;
|
||||
_glUniform2fv = glUniform2fv;
|
||||
_glUniform3fv = glUniform3fv;
|
||||
_glUniform4fv = glUniform4fv;
|
||||
_glUniformMatrix4fv = glUniformMatrix4fv;
|
||||
_glValidateProgram = glValidateProgram;
|
||||
_glVertexAttribPointer = glVertexAttribPointer;
|
||||
|
||||
// We need to have a default shader to apply in case
|
||||
// something didn't happen to have a shader applied, or
|
||||
// if it failed to compile. This default shader just outputs
|
||||
// a red color, indicating that something went wrong.
|
||||
_default_shader = new Shader(default_shader_name, default_shader_body, Shader::SL_GLSL);
|
||||
#endif
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
// In OpenGL ES 2.x, FBO's are supported in the core.
|
||||
_supports_framebuffer_object = true;
|
||||
@ -1123,6 +1191,10 @@ reset() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
// In OpenGL ES 2.x, this is supported in the core.
|
||||
_glBlendEquation = glBlendEquation;
|
||||
#else
|
||||
_glBlendEquation = NULL;
|
||||
bool supports_blend_equation = false;
|
||||
if (is_at_least_gl_version(1, 2)) {
|
||||
@ -1145,7 +1217,12 @@ reset() {
|
||||
if (_glBlendEquation == NULL) {
|
||||
_glBlendEquation = null_glBlendEquation;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
// In OpenGL ES 2.x, this is supported in the core.
|
||||
_glBlendColor = glBlendColor;
|
||||
#else
|
||||
_glBlendColor = NULL;
|
||||
bool supports_blend_color = false;
|
||||
if (is_at_least_gl_version(1, 2)) {
|
||||
@ -1164,6 +1241,7 @@ reset() {
|
||||
if (_glBlendColor == NULL) {
|
||||
_glBlendColor = null_glBlendColor;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPENGLES
|
||||
_edge_clamp = GL_CLAMP_TO_EDGE;
|
||||
@ -4051,15 +4129,29 @@ do_issue_shade_model() {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
do_issue_shader() {
|
||||
do_issue_shader(bool state_has_changed) {
|
||||
#ifndef OPENGLES_1
|
||||
CLP(ShaderContext) *context = 0;
|
||||
Shader *shader = (Shader *)(_target_shader->get_shader());
|
||||
|
||||
#ifdef OPENGLES_2
|
||||
// If we don't have a shader, apply the default shader.
|
||||
if (!shader) {
|
||||
shader = _default_shader;
|
||||
}
|
||||
#endif
|
||||
if (shader) {
|
||||
context = (CLP(ShaderContext) *)(shader->prepare_now(get_prepared_objects(), this));
|
||||
}
|
||||
#ifdef OPENGLES_2
|
||||
// If it failed, try applying the default shader.
|
||||
if (shader != _default_shader && (context == 0 || !context->valid())) {
|
||||
shader = _default_shader;
|
||||
context = (CLP(ShaderContext) *)(shader->prepare_now(get_prepared_objects(), this));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (context == 0 || (context -> valid ( ) == false)) {
|
||||
if (context == 0 || (context->valid() == false)) {
|
||||
if (_current_shader_context != 0) {
|
||||
_current_shader_context->unbind(this);
|
||||
_current_shader = 0;
|
||||
@ -4076,8 +4168,13 @@ do_issue_shader() {
|
||||
_current_shader = shader;
|
||||
_current_shader_context = context;
|
||||
} else {
|
||||
// Use the same shader as before, but with new input arguments.
|
||||
context->issue_parameters(this, Shader::SSD_shaderinputs);
|
||||
#ifdef OPENGLES_2
|
||||
context->bind(this, false);
|
||||
#endif
|
||||
if (state_has_changed) {
|
||||
// Use the same shader as before, but with new input arguments.
|
||||
context->issue_parameters(this, Shader::SSD_shaderinputs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6826,6 +6923,11 @@ set_state_and_transform(const RenderState *target,
|
||||
_state_shader = _target_shader;
|
||||
_state_mask.clear_bit(TextureAttrib::get_class_slot());
|
||||
}
|
||||
#ifdef OPENGLES_2
|
||||
else { // In the case of OpenGL ES 2.x, we need to glUseShader before we draw anything.
|
||||
do_issue_shader(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
int texture_slot = TextureAttrib::get_class_slot();
|
||||
if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) ||
|
||||
|
@ -116,13 +116,18 @@ typedef void (APIENTRYP PFNGLWEIGHTPOINTEROESPROC) (GLint size, GLenum type, GLs
|
||||
#ifndef OPENGLES_1
|
||||
// GLSL shader functions
|
||||
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
|
||||
typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||
typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
|
||||
typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
|
||||
typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
|
||||
typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
|
||||
typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||
@ -139,6 +144,7 @@ typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, con
|
||||
typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
|
||||
typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
|
||||
#endif
|
||||
#endif // __EDG__
|
||||
|
||||
@ -274,7 +280,7 @@ protected:
|
||||
void do_issue_fog();
|
||||
void do_issue_depth_offset();
|
||||
void do_issue_shade_model();
|
||||
void do_issue_shader();
|
||||
void do_issue_shader(bool state_has_changed = false);
|
||||
void do_issue_material();
|
||||
void do_issue_texture();
|
||||
void do_issue_blending();
|
||||
@ -441,6 +447,9 @@ protected:
|
||||
PT(Shader) _texture_binding_shader;
|
||||
CLP(ShaderContext) *_texture_binding_shader_context;
|
||||
#endif
|
||||
#ifdef OPENGLES_2
|
||||
PT(Shader) _default_shader;
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_IMMEDIATE_MODE
|
||||
CLP(ImmediateModeSender) _sender;
|
||||
@ -581,13 +590,18 @@ public:
|
||||
#ifndef OPENGLES_1
|
||||
// GLSL functions
|
||||
PFNGLATTACHSHADERPROC _glAttachShader;
|
||||
PFNGLBINDATTRIBLOCATIONPROC _glBindAttribLocation;
|
||||
PFNGLCOMPILESHADERPROC _glCompileShader;
|
||||
PFNGLCREATEPROGRAMPROC _glCreateProgram;
|
||||
PFNGLCREATESHADERPROC _glCreateShader;
|
||||
PFNGLDELETEPROGRAMPROC _glDeleteProgram;
|
||||
PFNGLDELETESHADERPROC _glDeleteShader;
|
||||
PFNGLDETACHSHADERPROC _glDetachShader;
|
||||
PFNGLDISABLEVERTEXATTRIBARRAYPROC _glDisableVertexAttribArray;
|
||||
PFNGLENABLEVERTEXATTRIBARRAYPROC _glEnableVertexAttribArray;
|
||||
PFNGLGETACTIVEATTRIBPROC _glGetActiveAttrib;
|
||||
PFNGLGETACTIVEUNIFORMPROC _glGetActiveUniform;
|
||||
PFNGLGETATTRIBLOCATIONPROC _glGetAttribLocation;
|
||||
PFNGLGETPROGRAMIVPROC _glGetProgramiv;
|
||||
PFNGLGETPROGRAMINFOLOGPROC _glGetProgramInfoLog;
|
||||
PFNGLGETSHADERIVPROC _glGetShaderiv;
|
||||
@ -604,6 +618,7 @@ public:
|
||||
PFNGLUNIFORM4FVPROC _glUniform4fv;
|
||||
PFNGLUNIFORMMATRIX4FVPROC _glUniformMatrix4fv;
|
||||
PFNGLVALIDATEPROGRAMPROC _glValidateProgram;
|
||||
PFNGLVERTEXATTRIBPOINTERPROC _glVertexAttribPointer;
|
||||
#endif
|
||||
|
||||
GLenum _edge_clamp;
|
||||
|
@ -73,9 +73,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
|
||||
cgGetProfileString(cgGetProgramProfile(_cg_fprogram)) << " " << str << ")\n";
|
||||
release_resources(gsg);
|
||||
}
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
GLCAT.error() << "GL error in ShaderContext constructor\n";
|
||||
}
|
||||
gsg->report_my_gl_errors();
|
||||
if (_cg_gprogram != 0) {
|
||||
cgGLLoadProgram(_cg_gprogram);
|
||||
if (GLCAT.is_debug()) {
|
||||
@ -90,9 +88,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
|
||||
cgGetProfileString(cgGetProgramProfile(_cg_gprogram)) << " " << str << ")\n";
|
||||
release_resources(gsg);
|
||||
}
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
GLCAT.error() << "GL error in ShaderContext constructor\n";
|
||||
}
|
||||
gsg->report_my_gl_errors();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -109,14 +105,13 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
|
||||
// Analyze the uniforms and put them in _glsl_parameter_map
|
||||
if (s->_glsl_parameter_map.size() == 0) {
|
||||
int seqno = 0, texunitno = 0;
|
||||
int num_uniforms, uniform_maxlength;
|
||||
gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, &num_uniforms);
|
||||
gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_maxlength);
|
||||
for (int i = 0; i < num_uniforms; ++i) {
|
||||
int param_size;
|
||||
GLenum param_type;
|
||||
char* param_name = new char[uniform_maxlength];
|
||||
gsg->_glGetActiveUniform(_glsl_program, i, uniform_maxlength, NULL, ¶m_size, ¶m_type, param_name);
|
||||
int 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 = new char[param_maxlength];
|
||||
for (int i = 0; i < param_count; ++i) {
|
||||
gsg->_glGetActiveUniform(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name);
|
||||
GLint p = gsg->_glGetUniformLocation(_glsl_program, param_name);
|
||||
if (p > -1) {
|
||||
Shader::ShaderArgId arg_id;
|
||||
@ -124,6 +119,18 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
|
||||
arg_id._seqno = seqno++;
|
||||
s->_glsl_parameter_map.push_back(p);
|
||||
PT(InternalName) inputname = InternalName::make(param_name);
|
||||
if (inputname->get_name() == "p3d_ModelViewProjectionMatrix") {
|
||||
Shader::ShaderMatSpec bind;
|
||||
bind._id = arg_id;
|
||||
bind._piece = Shader::SMP_whole;
|
||||
bind._func = Shader::SMF_compose;
|
||||
bind._part[0] = Shader::SMO_model_to_view;
|
||||
bind._arg[0] = NULL;
|
||||
bind._part[1] = Shader::SMO_view_to_apiclip;
|
||||
bind._arg[1] = NULL;
|
||||
s->_mat_spec.push_back(bind);
|
||||
continue;
|
||||
}
|
||||
if (inputname->get_name().substr(0, 11) == "p3d_Texture") {
|
||||
Shader::ShaderTexSpec bind;
|
||||
bind._id = arg_id;
|
||||
@ -230,10 +237,58 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
|
||||
GLCAT.warning() << "Ignoring unrecognized GLSL parameter type!\n";
|
||||
}
|
||||
}
|
||||
delete param_name;
|
||||
}
|
||||
delete[] param_name;
|
||||
|
||||
int attrib_idx = 0;
|
||||
// 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 = new char[param_maxlength];
|
||||
for (int i = 0; i < param_count; ++i) {
|
||||
gsg->_glGetActiveAttrib(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name);
|
||||
Shader::ShaderVarSpec bind;
|
||||
Shader::ShaderArgId arg_id;
|
||||
arg_id._name = param_name;
|
||||
arg_id._seqno = -1;
|
||||
PT(InternalName) inputname = InternalName::make(param_name);
|
||||
bind._append_uv = -1;
|
||||
if (inputname->get_name() == "p3d_Vertex") {
|
||||
bind._name = InternalName::get_vertex();
|
||||
s->_var_spec.push_back(bind);
|
||||
gsg->_glBindAttribLocation(_glsl_program, i, param_name);
|
||||
continue;
|
||||
}
|
||||
if (inputname->get_name() == "p3d_Normal") {
|
||||
bind._name = InternalName::get_normal();
|
||||
s->_var_spec.push_back(bind);
|
||||
gsg->_glBindAttribLocation(_glsl_program, i, param_name);
|
||||
continue;
|
||||
}
|
||||
if (inputname->get_name() == "p3d_Color") {
|
||||
bind._name = InternalName::get_color();
|
||||
s->_var_spec.push_back(bind);
|
||||
gsg->_glBindAttribLocation(_glsl_program, i, param_name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
delete[] param_name;
|
||||
}
|
||||
|
||||
// Finally, re-link the program, or otherwise the glBindAttribLocation
|
||||
// calls won't have any effect.
|
||||
gsg->_glLinkProgram(_glsl_program);
|
||||
|
||||
int status;
|
||||
gsg->_glGetProgramiv(_glsl_program, GL_LINK_STATUS, &status);
|
||||
if (status != GL_TRUE) {
|
||||
GLCAT.error() << "An error occurred while relinking shader program!\n";
|
||||
glsl_report_program_errors(gsg, _glsl_program);
|
||||
s->_error_flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
gsg->report_my_gl_errors();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -263,7 +318,9 @@ release_resources(const GSG *gsg) {
|
||||
_cg_gprogram = 0;
|
||||
_cg_parameter_map.clear();
|
||||
}
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
if (gsg) {
|
||||
gsg->report_my_gl_errors();
|
||||
} if (glGetError() != GL_NO_ERROR) {
|
||||
GLCAT.error() << "GL error in ShaderContext destructor\n";
|
||||
}
|
||||
#endif
|
||||
@ -300,10 +357,18 @@ release_resources(const GSG *gsg) {
|
||||
// input parameters.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(ShaderContext)::
|
||||
bind(GSG *gsg) {
|
||||
bind(GSG *gsg, bool reissue_parameters) {
|
||||
_last_gsg = gsg;
|
||||
// Pass in k-parameters and transform-parameters
|
||||
issue_parameters(gsg, Shader::SSD_general);
|
||||
|
||||
// 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 (reissue_parameters) {
|
||||
// Pass in k-parameters and transform-parameters
|
||||
issue_parameters(gsg, Shader::SSD_general);
|
||||
}
|
||||
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context != 0) {
|
||||
@ -320,13 +385,8 @@ bind(GSG *gsg) {
|
||||
cg_report_errors();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_shader->get_language() == Shader::SL_GLSL && !_shader->get_error_flag()) {
|
||||
gsg->_glUseProgram(_glsl_program);
|
||||
}
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
GLCAT.error() << "GL error in ShaderContext::bind\n";
|
||||
}
|
||||
|
||||
gsg->report_my_gl_errors();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -353,9 +413,7 @@ unbind(GSG *gsg) {
|
||||
if (_shader->get_language() == Shader::SL_GLSL) {
|
||||
gsg->_glUseProgram(0);
|
||||
}
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
GLCAT.error() << "GL error in ShaderContext::unbind\n";
|
||||
}
|
||||
gsg->report_my_gl_errors();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -432,9 +490,7 @@ issue_parameters(GSG *gsg, int altered) {
|
||||
cg_report_errors();
|
||||
#endif
|
||||
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
GLCAT.error() << "GL error in ShaderContext::issue_parameters\n";
|
||||
}
|
||||
gsg->report_my_gl_errors();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -445,22 +501,27 @@ issue_parameters(GSG *gsg, int altered) {
|
||||
void CLP(ShaderContext)::
|
||||
disable_shader_vertex_arrays(GSG *gsg) {
|
||||
_last_gsg = gsg;
|
||||
|
||||
#ifdef HAVE_CG
|
||||
if (_cg_context == 0) {
|
||||
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);
|
||||
if (_shader->get_language() == Shader::SL_GLSL) {
|
||||
for (int i=0; i<(int)_shader->_var_spec.size(); i++) {
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
cg_report_errors();
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
GLCAT.error() << "GL error in ShaderContext::disable_shader_vertex_arrays\n";
|
||||
#ifdef HAVE_CG
|
||||
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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -479,11 +540,12 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg,
|
||||
bool force) {
|
||||
_last_gsg = gsg;
|
||||
if (prev) prev->disable_shader_vertex_arrays(gsg);
|
||||
#ifdef HAVE_CG
|
||||
if (!valid()) {
|
||||
return true;
|
||||
}
|
||||
#ifdef HAVE_CG
|
||||
cg_report_errors();
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_IMMEDIATE_MODE
|
||||
if (gsg->_use_sender) {
|
||||
@ -496,8 +558,14 @@ 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++) {
|
||||
CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno];
|
||||
if (p == 0) continue;
|
||||
#ifdef HAVE_CG
|
||||
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()) {
|
||||
@ -516,21 +584,39 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg,
|
||||
if (!gsg->setup_array_data(client_pointer, array_reader, force)) {
|
||||
return false;
|
||||
}
|
||||
cgGLSetParameterPointer(p,
|
||||
num_values, gsg->get_numeric_type(numeric_type),
|
||||
stride, client_pointer + start);
|
||||
cgGLEnableClientState(p);
|
||||
} else {
|
||||
if (_shader->get_language() == Shader::SL_GLSL) {
|
||||
#ifndef OPENGLES_2
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
#endif
|
||||
glEnableVertexAttribArray(i);
|
||||
glVertexAttribPointer(i, num_values, gsg->get_numeric_type(numeric_type),
|
||||
GL_FALSE, stride, client_pointer + start);
|
||||
#ifndef OPENGLES_2
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
#endif
|
||||
#ifdef HAVE_CG
|
||||
} 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
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_CG
|
||||
else if (_shader->get_language() == Shader::SL_Cg) {
|
||||
cgGLDisableClientState(p);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_CG
|
||||
cg_report_errors();
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
GLCAT.error() << "GL error in ShaderContext::update_shader_vertex_arrays\n";
|
||||
}
|
||||
#endif // HAVE_CG
|
||||
#endif
|
||||
gsg->report_my_gl_errors();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -586,9 +672,7 @@ disable_shader_texture_bindings(GSG *gsg) {
|
||||
cg_report_errors();
|
||||
#endif
|
||||
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
GLCAT.error() << "GL error in ShaderContext::disable_shader_texture_bindings\n";
|
||||
}
|
||||
gsg->report_my_gl_errors();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -694,9 +778,7 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) {
|
||||
cg_report_errors();
|
||||
#endif
|
||||
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
GLCAT.error() << "GL error in ShaderContext::update_shader_texture_bindings\n";
|
||||
}
|
||||
gsg->report_my_gl_errors();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -725,14 +807,16 @@ glsl_report_shader_errors(GSG *gsg, unsigned int shader) {
|
||||
int length = 0;
|
||||
int num_chars = 0;
|
||||
|
||||
gsg->_glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
|
||||
gsg->_glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
|
||||
|
||||
if (length > 0) {
|
||||
info_log = (char *) malloc(length);
|
||||
gsg->_glGetShaderInfoLog(shader, length, &num_chars, info_log);
|
||||
GLCAT.error(false) << info_log;
|
||||
free(info_log);
|
||||
if (strcmp(info_log, "Success.\n") != 0) {
|
||||
GLCAT.error(false) << info_log;
|
||||
}
|
||||
}
|
||||
delete[] info_log;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -746,14 +830,16 @@ glsl_report_program_errors(GSG *gsg, unsigned int program) {
|
||||
int length = 0;
|
||||
int num_chars = 0;
|
||||
|
||||
gsg->_glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
|
||||
gsg->_glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
|
||||
|
||||
if (length > 0) {
|
||||
info_log = (char *) malloc(length);
|
||||
gsg->_glGetProgramInfoLog(program, length, &num_chars, info_log);
|
||||
GLCAT.error(false) << info_log;
|
||||
free(info_log);
|
||||
if (strcmp(info_log, "Success.\n") != 0) {
|
||||
GLCAT.error(false) << info_log;
|
||||
}
|
||||
}
|
||||
delete[] info_log;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -762,16 +848,16 @@ glsl_report_program_errors(GSG *gsg, unsigned int program) {
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
unsigned int CLP(ShaderContext)::
|
||||
glsl_compile_entry_point(GSG *gsg, const char *entry, Shader::ShaderType type) {
|
||||
glsl_compile_entry_point(GSG *gsg, Shader::ShaderType type) {
|
||||
unsigned int handle;
|
||||
switch (type) {
|
||||
case Shader::ST_VERTEX:
|
||||
case Shader::ST_vertex:
|
||||
handle = gsg->_glCreateShader(GL_VERTEX_SHADER);
|
||||
break;
|
||||
case Shader::ST_FRAGMENT:
|
||||
case Shader::ST_fragment:
|
||||
handle = gsg->_glCreateShader(GL_FRAGMENT_SHADER);
|
||||
break;
|
||||
case Shader::ST_GEOMETRY:
|
||||
case Shader::ST_geometry:
|
||||
handle = gsg->_glCreateShader(GL_GEOMETRY_SHADER);
|
||||
break;
|
||||
default:
|
||||
@ -780,16 +866,13 @@ glsl_compile_entry_point(GSG *gsg, const char *entry, Shader::ShaderType type) {
|
||||
if (!handle) {
|
||||
return 0;
|
||||
}
|
||||
// We define our own main() in which we call the right function.
|
||||
ostringstream str;
|
||||
str << "void main() { " << entry << "(); };";
|
||||
const char* sources[2] = {_shader->_text.c_str(), str.str().c_str()};
|
||||
gsg->_glShaderSource(handle, 2, sources, NULL);
|
||||
const char* text = _shader->get_text(type).c_str();
|
||||
gsg->_glShaderSource(handle, 1, &text, NULL);
|
||||
gsg->_glCompileShader(handle);
|
||||
int status;
|
||||
gsg->_glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
|
||||
if (status != GL_TRUE) {
|
||||
GLCAT.error() << "An error occurred while compiling " << entry << "!\n";
|
||||
GLCAT.error() << "An error occurred while compiling shader!\n";
|
||||
glsl_report_shader_errors(gsg, handle);
|
||||
gsg->_glDeleteShader(handle);
|
||||
return 0;
|
||||
@ -810,38 +893,24 @@ glsl_compile_shader(GSG *gsg) {
|
||||
_glsl_program = gsg->_glCreateProgram();
|
||||
if (!_glsl_program) return false;
|
||||
|
||||
if (_shader->_text.find("vshader") != -1) {
|
||||
_glsl_vshader = glsl_compile_entry_point(gsg, "vshader", Shader::ST_VERTEX);
|
||||
if (!_shader->get_text(Shader::ST_vertex).empty()) {
|
||||
_glsl_vshader = glsl_compile_entry_point(gsg, Shader::ST_vertex);
|
||||
if (!_glsl_vshader) return false;
|
||||
gsg->_glAttachShader(_glsl_program, _glsl_vshader);
|
||||
} else {
|
||||
GLCAT.warning() << "Could not locate function 'vshader' in shader text!\n";
|
||||
}
|
||||
|
||||
if (_shader->_text.find("fshader") != -1) {
|
||||
_glsl_fshader = glsl_compile_entry_point(gsg, "fshader", Shader::ST_FRAGMENT);
|
||||
if (!_shader->get_text(Shader::ST_fragment).empty()) {
|
||||
_glsl_fshader = glsl_compile_entry_point(gsg, Shader::ST_fragment);
|
||||
if (!_glsl_fshader) return false;
|
||||
gsg->_glAttachShader(_glsl_program, _glsl_fshader);
|
||||
} else {
|
||||
GLCAT.warning() << "Could not locate function 'fshader' in shader text!\n";
|
||||
}
|
||||
|
||||
if (_shader->_text.find("gshader") != -1) {
|
||||
_glsl_gshader = glsl_compile_entry_point(gsg, "gshader", Shader::ST_GEOMETRY);
|
||||
if (!_shader->get_text(Shader::ST_geometry).empty()) {
|
||||
_glsl_gshader = glsl_compile_entry_point(gsg, Shader::ST_geometry);
|
||||
if (!_glsl_gshader) return false;
|
||||
gsg->_glAttachShader(_glsl_program, _glsl_gshader);
|
||||
}
|
||||
|
||||
gsg->_glLinkProgram(_glsl_program);
|
||||
|
||||
int status;
|
||||
gsg->_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);
|
||||
return false;
|
||||
}
|
||||
|
||||
// There might be warnings. Only report them for one shader program.
|
||||
if (_glsl_vshader != 0) {
|
||||
glsl_report_shader_errors(gsg, _glsl_vshader);
|
||||
@ -851,10 +920,17 @@ glsl_compile_shader(GSG *gsg) {
|
||||
glsl_report_shader_errors(gsg, _glsl_gshader);
|
||||
}
|
||||
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
GLCAT.error() << "Failed to compile shader\n";
|
||||
gsg->_glLinkProgram(_glsl_program);
|
||||
|
||||
int status;
|
||||
gsg->_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);
|
||||
return false;
|
||||
}
|
||||
|
||||
gsg->report_my_gl_errors();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -27,9 +27,9 @@ class CLP(GraphicsStateGuardian);
|
||||
// Class : GLShaderContext
|
||||
// Description : xyz
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
class EXPCL_GL CLP(ShaderContext): public ShaderContext {
|
||||
public:
|
||||
friend class CLP(GraphicsStateGuardian);
|
||||
typedef CLP(GraphicsStateGuardian) GSG;
|
||||
|
||||
CLP(ShaderContext)(Shader *s, GSG *gsg);
|
||||
@ -37,7 +37,7 @@ public:
|
||||
ALLOC_DELETED_CHAIN(CLP(ShaderContext));
|
||||
|
||||
INLINE bool valid(void);
|
||||
void bind(GSG *gsg);
|
||||
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);
|
||||
@ -76,7 +76,7 @@ private:
|
||||
|
||||
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, const char *entry, Shader::ShaderType type);
|
||||
unsigned int glsl_compile_entry_point(GSG *gsg, Shader::ShaderType type);
|
||||
bool glsl_compile_shader(GSG *gsg);
|
||||
|
||||
void release_resources(const GSG *gsg);
|
||||
|
@ -13,33 +13,68 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::get_filename
|
||||
// Access: Public
|
||||
// Description: Return the Shader's filename.
|
||||
// Function: Shader::get_filename
|
||||
// Access: Public
|
||||
// Description: Return the Shader's filename for the given shader
|
||||
// type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const Filename &Shader::
|
||||
get_filename() const {
|
||||
return _filename;
|
||||
INLINE const Filename Shader::
|
||||
get_filename(const ShaderType &type) const {
|
||||
if (_filename->_separate) {
|
||||
nassertr(type != ST_none || !_filename->_shared.empty(), "");
|
||||
switch (type) {
|
||||
case ST_vertex:
|
||||
return _filename->_vertex;
|
||||
break;
|
||||
case ST_fragment:
|
||||
return _filename->_fragment;
|
||||
break;
|
||||
case ST_geometry:
|
||||
return _filename->_geometry;
|
||||
break;
|
||||
default:
|
||||
return _filename->_shared;
|
||||
}
|
||||
} else {
|
||||
return _filename->_shared;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::get_text
|
||||
// Access: Public
|
||||
// Description: Return the Shader's text.
|
||||
// Function: Shader::get_text
|
||||
// Access: Public
|
||||
// Description: Return the Shader's text for the given shader type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &Shader::
|
||||
get_text() const {
|
||||
return _text;
|
||||
INLINE const string Shader::
|
||||
get_text(const ShaderType &type) const {
|
||||
if (_text->_separate) {
|
||||
nassertr(type != ST_none || !_text->_shared.empty(), "");
|
||||
switch (type) {
|
||||
case ST_vertex:
|
||||
return _text->_vertex;
|
||||
break;
|
||||
case ST_fragment:
|
||||
return _text->_fragment;
|
||||
break;
|
||||
case ST_geometry:
|
||||
return _text->_geometry;
|
||||
break;
|
||||
default:
|
||||
return _text->_shared;
|
||||
}
|
||||
} else {
|
||||
return _text->_shared;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::get_error_flag
|
||||
// Access: Public
|
||||
// Function: Shader::get_error_flag
|
||||
// Access: Public
|
||||
// Description: Returns true if the shader contains a compile-time
|
||||
// error. This doesn't tell you whether or not the
|
||||
// shader is supported on the current video card.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Shader::
|
||||
INLINE const bool Shader::
|
||||
get_error_flag() const {
|
||||
return _error_flag;
|
||||
}
|
||||
|
@ -24,8 +24,8 @@
|
||||
#endif
|
||||
|
||||
TypeHandle Shader::_type_handle;
|
||||
Shader::LoadTable Shader::_load_table;
|
||||
Shader::MakeTable Shader::_make_table;
|
||||
Shader::ShaderTable Shader::_load_table;
|
||||
Shader::ShaderTable Shader::_make_table;
|
||||
Shader::ShaderCaps Shader::_default_caps;
|
||||
int Shader::_shaders_generated;
|
||||
ShaderUtilization Shader::_shader_utilization = SUT_UNSPECIFIED;
|
||||
@ -37,8 +37,7 @@ ShaderUtilization Shader::_shader_utilization = SUT_UNSPECIFIED;
|
||||
// of the specified parameter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Shader::
|
||||
cp_report_error(ShaderArgInfo &p, const string &msg)
|
||||
{
|
||||
cp_report_error(ShaderArgInfo &p, const string &msg) {
|
||||
string vstr;
|
||||
if (p._varying) vstr = "varying ";
|
||||
else vstr = "uniform ";
|
||||
@ -62,7 +61,7 @@ cp_report_error(ShaderArgInfo &p, const string &msg)
|
||||
case SAT_unknown: tstr = "unknown "; break;
|
||||
}
|
||||
|
||||
Filename fn = get_filename();
|
||||
Filename fn = get_filename(p._id._type);
|
||||
p._cat->error() << fn << ": " << msg << " (" <<
|
||||
vstr << dstr << tstr << p._id._name << ")\n";
|
||||
}
|
||||
@ -1107,12 +1106,10 @@ cg_release_resources() {
|
||||
cgDestroyProgram(_cg_fprogram);
|
||||
_cg_fprogram = 0;
|
||||
}
|
||||
// BEGIN CG2 CHANGE
|
||||
if (_cg_gprogram != 0) {
|
||||
cgDestroyProgram(_cg_gprogram);
|
||||
_cg_gprogram = 0;
|
||||
}
|
||||
// END CG2 CHANGE
|
||||
if (_cg_context != 0) {
|
||||
cgDestroyContext(_cg_context);
|
||||
_cg_context = 0;
|
||||
@ -1129,40 +1126,50 @@ cg_compile_entry_point(const char *entry, const ShaderCaps &caps, ShaderType typ
|
||||
CGprogram prog;
|
||||
CGerror err;
|
||||
const char *compiler_args[100];
|
||||
const string text;
|
||||
if (!_text->_separate) {
|
||||
text = _text->_shared;
|
||||
}
|
||||
int nargs = 0;
|
||||
|
||||
int active, ultimate;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ST_VERTEX:
|
||||
switch(type) {
|
||||
case ST_vertex:
|
||||
active = caps._active_vprofile;
|
||||
ultimate = caps._ultimate_vprofile;
|
||||
if (_text->_separate) {
|
||||
text = _text._vertex;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_FRAGMENT:
|
||||
case ST_fragment:
|
||||
active = caps._active_fprofile;
|
||||
ultimate = caps._ultimate_fprofile;
|
||||
if (_text->_separate) {
|
||||
text = _text._fragment;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_GEOMETRY:
|
||||
case ST_geometry:
|
||||
active = caps._active_gprofile;
|
||||
ultimate = caps._ultimate_gprofile;
|
||||
if (_text->_separate) {
|
||||
text = _text._geometry;
|
||||
}
|
||||
break;
|
||||
};
|
||||
|
||||
// END CG2 CHANGE
|
||||
|
||||
cgGetError();
|
||||
|
||||
if (type == ST_FRAGMENT && caps._bug_list.count(SBUG_ati_draw_buffers)) { // CG2 CHANGE
|
||||
if (type == ST_fragment && caps._bug_list.count(SBUG_ati_draw_buffers)) {
|
||||
compiler_args[nargs++] = "-po";
|
||||
compiler_args[nargs++] = "ATI_draw_buffers";
|
||||
}
|
||||
compiler_args[nargs] = 0;
|
||||
|
||||
if ((active != (int)CG_PROFILE_UNKNOWN) && (active != ultimate)) {
|
||||
prog = cgCreateProgram(_cg_context, CG_SOURCE, _text.c_str(),
|
||||
prog = cgCreateProgram(_cg_context, CG_SOURCE, text.c_str(),
|
||||
(CGprofile)active, entry, (const char **)compiler_args);
|
||||
err = cgGetError();
|
||||
if (err == CG_NO_ERROR) {
|
||||
@ -1173,7 +1180,7 @@ cg_compile_entry_point(const char *entry, const ShaderCaps &caps, ShaderType typ
|
||||
}
|
||||
}
|
||||
|
||||
prog = cgCreateProgram(_cg_context, CG_SOURCE, _text.c_str(),
|
||||
prog = cgCreateProgram(_cg_context, CG_SOURCE, text.c_str(),
|
||||
(CGprofile)ultimate, entry, (const char **)NULL);
|
||||
err = cgGetError();
|
||||
if (err == CG_NO_ERROR) {
|
||||
@ -1186,11 +1193,11 @@ cg_compile_entry_point(const char *entry, const ShaderCaps &caps, ShaderType typ
|
||||
for (int i=0; i<(int)errlines.size(); i++) {
|
||||
string line = trim(errlines[i]);
|
||||
if (line != "") {
|
||||
gobj_cat.error() << get_filename() << ": " << errlines[i] << "\n";
|
||||
gobj_cat.error() << get_filename(type) << ": " << errlines[i] << "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gobj_cat.error() << get_filename() << ": " << cgGetErrorString(err) << "\n";
|
||||
gobj_cat.error() << get_filename(type) << ": " << cgGetErrorString(err) << "\n";
|
||||
}
|
||||
if (prog != 0) {
|
||||
cgDestroyProgram(prog);
|
||||
@ -1209,8 +1216,6 @@ cg_compile_entry_point(const char *entry, const ShaderCaps &caps, ShaderType typ
|
||||
bool Shader::
|
||||
cg_compile_shader(const ShaderCaps &caps) {
|
||||
|
||||
|
||||
|
||||
// If we already tried compiling for this set of caps, there's no point
|
||||
// trying again. Just return the results of the previous compile.
|
||||
if (caps == _cg_last_caps) {
|
||||
@ -1225,18 +1230,25 @@ cg_compile_shader(const ShaderCaps &caps) {
|
||||
|
||||
_cg_context = cgCreateContext();
|
||||
|
||||
gobj_cat.debug() << "Compiling Shader: \n" << _text << "\n";
|
||||
if (!_text->_separate) {
|
||||
gobj_cat.debug() << "Compiling Shader: \n" << _text << "\n";
|
||||
}
|
||||
|
||||
if (_cg_context == 0) {
|
||||
gobj_cat.error() << "could not create a Cg context object.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
_cg_vprogram = cg_compile_entry_point("vshader", caps, ST_VERTEX); // CG2 CHANGE
|
||||
_cg_fprogram = cg_compile_entry_point("fshader", caps, ST_FRAGMENT); // CG2 CHANGE
|
||||
if (!_text->_separate || !_text._vertex.empty()) {
|
||||
_cg_vprogram = cg_compile_entry_point("vshader", caps, ST_vertex);
|
||||
}
|
||||
|
||||
if (_text.find("gshader") != -1) {
|
||||
_cg_gprogram = cg_compile_entry_point("gshader", caps, ST_GEOMETRY);
|
||||
if (!_text->_separate || !_text._fragment.empty()) {
|
||||
_cg_fprogram = cg_compile_entry_point("fshader", caps, ST_fragment);
|
||||
}
|
||||
|
||||
if ((_text->_separate && !_text._geometry.empty()) || (!_text->_separate && _text.find("gshader") != -1)) {
|
||||
_cg_gprogram = cg_compile_entry_point("gshader", caps, ST_geometry);
|
||||
}
|
||||
|
||||
if ((_cg_vprogram == 0)||(_cg_fprogram == 0)) {
|
||||
@ -1317,7 +1329,7 @@ cg_analyze_shader(const ShaderCaps &caps) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cg_analyze_entry_point(_cg_fprogram, ST_FRAGMENT)) {
|
||||
if (!cg_analyze_entry_point(_cg_fprogram, ST_fragment)) {
|
||||
cg_release_resources();
|
||||
clear_parameters();
|
||||
return false;
|
||||
@ -1330,14 +1342,14 @@ cg_analyze_shader(const ShaderCaps &caps) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cg_analyze_entry_point(_cg_vprogram, ST_VERTEX)) {
|
||||
if (!cg_analyze_entry_point(_cg_vprogram, ST_vertex)) {
|
||||
cg_release_resources();
|
||||
clear_parameters();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_cg_gprogram != 0) {
|
||||
if (!cg_analyze_entry_point(_cg_gprogram, ST_GEOMETRY)) {
|
||||
if (!cg_analyze_entry_point(_cg_gprogram, ST_geometry)) {
|
||||
cg_release_resources();
|
||||
clear_parameters();
|
||||
return false;
|
||||
@ -1463,15 +1475,15 @@ cg_program_from_shadertype(ShaderType type) {
|
||||
CGprogram prog = 0;
|
||||
|
||||
switch(type) {
|
||||
case ST_VERTEX:
|
||||
case ST_vertex:
|
||||
prog = _cg_vprogram;
|
||||
break;
|
||||
|
||||
case ST_FRAGMENT:
|
||||
case ST_fragment:
|
||||
prog = _cg_fprogram;
|
||||
break;
|
||||
|
||||
case ST_GEOMETRY:
|
||||
case ST_geometry:
|
||||
prog = _cg_gprogram;
|
||||
break;
|
||||
};
|
||||
@ -1580,7 +1592,7 @@ cg_compile_for(const ShaderCaps &caps,
|
||||
// Description: Construct a Shader.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Shader::
|
||||
Shader(const Filename &filename, const string &text, const ShaderLanguage &lang) :
|
||||
Shader(CPT(ShaderFile) filename, CPT(ShaderFile) text, const ShaderLanguage &lang) :
|
||||
_filename(filename),
|
||||
_text(text),
|
||||
_error_flag(true),
|
||||
@ -1622,7 +1634,9 @@ Shader(const Filename &filename, const string &text, const ShaderLanguage &lang)
|
||||
|
||||
if (_language == SL_Cg) {
|
||||
#ifdef HAVE_CG
|
||||
cg_get_profile_from_header(_default_caps);
|
||||
if (!_text->_separate) {
|
||||
cg_get_profile_from_header(_default_caps);
|
||||
}
|
||||
|
||||
if (!cg_analyze_shader(_default_caps)) {
|
||||
_error_flag = true;
|
||||
@ -1632,8 +1646,13 @@ Shader(const Filename &filename, const string &text, const ShaderLanguage &lang)
|
||||
<< "Tried to load Cg shader, but no Cg support is enabled.\n";
|
||||
#endif
|
||||
} else if (_language == SL_GLSL) {
|
||||
// All of the important stuff is done in glShaderContext.
|
||||
_language = SL_GLSL;
|
||||
// All of the important stuff is done in glShaderContext,
|
||||
// to avoid gobj getting a dependency on OpenGL.
|
||||
if (!_text->_separate) {
|
||||
gobj_cat.error()
|
||||
<< "GLSL shaders must have separate shader bodies!\n";
|
||||
_error_flag = true;
|
||||
}
|
||||
} else {
|
||||
gobj_cat.error()
|
||||
<< "Shader is not in a supported shader-language.\n";
|
||||
@ -1763,47 +1782,61 @@ Shader::
|
||||
}
|
||||
}
|
||||
|
||||
// Removed for now, as the profiles are now taken from the shader source.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::load
|
||||
// Access: Published, Static
|
||||
// Description: Loads the shader with the given filename.
|
||||
// If the optional vshader or fshader parameters
|
||||
// are set and non-empty, it will be used to override
|
||||
// all other profile settings (it even overrides
|
||||
// the basic-shaders-only flag) and forces the shader
|
||||
// to use the given profile.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(Shader) Shader::
|
||||
load(const string &file) {
|
||||
return load(Filename(file));
|
||||
load(const Filename &file, const ShaderLanguage &lang) {
|
||||
PT(ShaderFile) sfile = new ShaderFile(file);
|
||||
ShaderTable::const_iterator i = _load_table.find(sfile);
|
||||
if (i != _load_table.end() && (lang == SL_none || lang == i->second->_language)) {
|
||||
return i->second;
|
||||
}
|
||||
PT(ShaderFile) sbody = new ShaderFile("");
|
||||
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
if (!vfs->read_file(file, sbody->_shared, true)) {
|
||||
gobj_cat.error() << "Could not read shader file: " << file << "\n";
|
||||
return NULL;
|
||||
}
|
||||
PT(Shader) result = new Shader(sfile, sbody, lang);
|
||||
result->_loaded = true;
|
||||
_load_table[sfile] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::load
|
||||
// Access: Published, Static
|
||||
// Description: Loads the shader with the given filename.
|
||||
// If the optional vshader or fshader parameters
|
||||
// are set and non-empty, it will be used to override
|
||||
// all other profile settings (it even overrides
|
||||
// the basic-shaders-only flag) and forces the shader
|
||||
// to use the given profile.
|
||||
// Description: This variant of Shader::load loads all shader
|
||||
// programs separately.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(Shader) Shader::
|
||||
load(const Filename &file) {
|
||||
LoadTable::const_iterator i = _load_table.find(file);
|
||||
if (i != _load_table.end()) {
|
||||
load(const ShaderLanguage &lang, const Filename &vertex, const Filename &fragment, const Filename &geometry) {
|
||||
PT(ShaderFile) sfile = new ShaderFile(vertex, fragment, geometry);
|
||||
ShaderTable::const_iterator i = _load_table.find(sfile);
|
||||
if (i != _load_table.end() && (lang == SL_none || lang == i->second->_language)) {
|
||||
return i->second;
|
||||
}
|
||||
string body;
|
||||
PT(ShaderFile) sbody = new ShaderFile("", "", "");
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
if (!vfs->read_file(file, body, true)) {
|
||||
gobj_cat.error() << "Could not read shader file: " << file << "\n";
|
||||
if (!vertex.empty() && !vfs->read_file(vertex, sbody->_vertex, true)) {
|
||||
gobj_cat.error() << "Could not read vertex shader file: " << vertex << "\n";
|
||||
return NULL;
|
||||
}
|
||||
PT(Shader) result = new Shader(file, body);
|
||||
if (!fragment.empty() && !vfs->read_file(fragment, sbody->_fragment, true)) {
|
||||
gobj_cat.error() << "Could not read fragment shader file: " << vertex << "\n";
|
||||
return NULL;
|
||||
}
|
||||
if (!geometry.empty() && !vfs->read_file(geometry, sbody->_geometry, true)) {
|
||||
gobj_cat.error() << "Could not read geometry shader file: " << vertex << "\n";
|
||||
return NULL;
|
||||
}
|
||||
PT(Shader) result = new Shader(sfile, sbody, lang);
|
||||
result->_loaded = true;
|
||||
_load_table[file] = result;
|
||||
_load_table[sfile] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1811,20 +1844,17 @@ load(const Filename &file) {
|
||||
// Function: Shader::make
|
||||
// Access: Published, Static
|
||||
// Description: Loads the shader, using the string as shader body.
|
||||
// If the optional vshader or fshader parameters
|
||||
// are set and non-empty, it will be used to override
|
||||
// all other profile settings (it even overrides
|
||||
// the basic-shaders-only flag) and forces the shader
|
||||
// to use the given profile.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
PT(Shader) Shader::
|
||||
make(const string &body) {
|
||||
MakeTable::const_iterator i = _make_table.find(body);
|
||||
if (i != _make_table.end()) {
|
||||
make(const string &body, const ShaderLanguage &lang) {
|
||||
PT(ShaderFile) sbody = new ShaderFile(body);
|
||||
ShaderTable::const_iterator i = _make_table.find(sbody);
|
||||
if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
|
||||
return i->second;
|
||||
}
|
||||
PT(Shader) result = new Shader("created-shader", body);
|
||||
_make_table[body] = result;
|
||||
PT(ShaderFile) sfile = new ShaderFile("created-shader");
|
||||
PT(Shader) result = new Shader(sfile, sbody, lang);
|
||||
_make_table[sbody] = result;
|
||||
if (dump_generated_shaders) {
|
||||
ostringstream fns;
|
||||
int index = _shaders_generated ++;
|
||||
@ -1839,6 +1869,24 @@ make(const string &body) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::make
|
||||
// Access: Published, Static
|
||||
// Description: Loads the shader, using the strings as shader bodies.
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
PT(Shader) Shader::
|
||||
make(const ShaderLanguage &lang, const string &vertex, const string &fragment, const string &geometry) {
|
||||
PT(ShaderFile) sbody = new ShaderFile(vertex, fragment, geometry);
|
||||
ShaderTable::const_iterator i = _make_table.find(sbody);
|
||||
if (i != _make_table.end() && (lang == SL_none || lang == i->second->_language)) {
|
||||
return i->second;
|
||||
}
|
||||
PT(ShaderFile) sfile = new ShaderFile("created-shader");
|
||||
PT(Shader) result = new Shader(sfile, sbody, lang);
|
||||
_make_table[sbody] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::parse_init
|
||||
// Access: Public
|
||||
@ -1859,10 +1907,11 @@ parse_init() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Shader::
|
||||
parse_line(string &result, bool lt, bool rt) {
|
||||
int len = _text.size();
|
||||
nassertv(!_text->_separate);
|
||||
int len = _text->_shared.size();
|
||||
int head = _parse;
|
||||
int tail = head;
|
||||
while ((tail < len) && (_text[tail] != '\n')) {
|
||||
while ((tail < len) && (_text->_shared[tail] != '\n')) {
|
||||
tail++;
|
||||
}
|
||||
if (tail < len) {
|
||||
@ -1871,10 +1920,10 @@ parse_line(string &result, bool lt, bool rt) {
|
||||
_parse = tail;
|
||||
}
|
||||
if (lt) {
|
||||
while ((head < tail)&&(isspace(_text[head]))) head++;
|
||||
while ((tail > head)&&(isspace(_text[tail-1]))) tail--;
|
||||
while ((head < tail)&&(isspace(_text->_shared[head]))) head++;
|
||||
while ((tail > head)&&(isspace(_text->_shared[tail-1]))) tail--;
|
||||
}
|
||||
result = _text.substr(head, tail-head);
|
||||
result = _text->_shared.substr(head, tail-head);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1887,19 +1936,20 @@ parse_line(string &result, bool lt, bool rt) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Shader::
|
||||
parse_upto(string &result, string pattern, bool include) {
|
||||
nassertv(!_text->_separate);
|
||||
GlobPattern endpat(pattern);
|
||||
int start = _parse;
|
||||
int last = _parse;
|
||||
while (_parse < (int)(_text.size())) {
|
||||
while (_parse < (int)(_text->_shared.size())) {
|
||||
string t;
|
||||
parse_line(t, true, true);
|
||||
if (endpat.matches(t)) break;
|
||||
last = _parse;
|
||||
}
|
||||
if (include) {
|
||||
result = _text.substr(start, _parse - start);
|
||||
result = _text->_shared.substr(start, _parse - start);
|
||||
} else {
|
||||
result = _text.substr(start, last - start);
|
||||
result = _text->_shared.substr(start, last - start);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1911,21 +1961,8 @@ parse_upto(string &result, string pattern, bool include) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Shader::
|
||||
parse_rest(string &result) {
|
||||
result = _text.substr(_parse, _text.size() - _parse);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::parse_lineno
|
||||
// Access: Public
|
||||
// Description: Returns the line number of the current parse pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int Shader::
|
||||
parse_lineno() {
|
||||
int result = 1;
|
||||
for (int i=0; i<_parse; i++) {
|
||||
if (_text[i] == '\n') result += 1;
|
||||
}
|
||||
return result;
|
||||
nassertv(!_text->_separate);
|
||||
result = _text->_shared.substr(_parse, _text->_shared.size() - _parse);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1936,7 +1973,7 @@ parse_lineno() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Shader::
|
||||
parse_eof() {
|
||||
return (int)_text.size() == _parse;
|
||||
return (int)_text->_shared.size() == _parse;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -2001,7 +2038,7 @@ release(PreparedGraphicsObjects *prepared_objects) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Shader::prepare_now
|
||||
// Access: Published
|
||||
// Description: Creates a context for the texture on the particular
|
||||
// Description: Creates a context for the shader on the particular
|
||||
// GSG, if it does not already exist. Returns the new
|
||||
// (or old) ShaderContext. This assumes that the
|
||||
// GraphicsStateGuardian is the currently active
|
||||
@ -2010,7 +2047,7 @@ release(PreparedGraphicsObjects *prepared_objects) {
|
||||
// should use prepare() instead.
|
||||
//
|
||||
// Normally, this is not called directly except by the
|
||||
// GraphicsStateGuardian; a texture does not need to be
|
||||
// GraphicsStateGuardian; a shader does not need to be
|
||||
// explicitly prepared by the user before it may be
|
||||
// rendered.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -38,13 +38,27 @@ class EXPCL_PANDA_GOBJ Shader: public TypedReferenceCount {
|
||||
|
||||
PUBLISHED:
|
||||
|
||||
static PT(Shader) load(const Filename &file);
|
||||
static PT(Shader) load(const string &file);
|
||||
static PT(Shader) make(const string &body);
|
||||
enum ShaderLanguage {
|
||||
SL_none,
|
||||
SL_Cg,
|
||||
SL_GLSL
|
||||
};
|
||||
enum ShaderType {
|
||||
ST_none = 0,
|
||||
ST_vertex,
|
||||
ST_fragment,
|
||||
ST_geometry,
|
||||
};
|
||||
|
||||
INLINE const Filename &get_filename() const;
|
||||
INLINE const string &get_text() const;
|
||||
INLINE bool get_error_flag() const;
|
||||
static PT(Shader) load(const Filename &file, const ShaderLanguage &lang = SL_none);
|
||||
static PT(Shader) make(const string &body, const ShaderLanguage &lang = SL_none);
|
||||
static PT(Shader) load(const ShaderLanguage &lang, const Filename &vertex, const Filename &fragment, const Filename &geometry = "");
|
||||
static PT(Shader) make(const ShaderLanguage &lang, const string &vertex, const string &fragment, const string &geometry = "");
|
||||
|
||||
INLINE const Filename get_filename(const ShaderType &type = ST_none) const;
|
||||
INLINE const string get_text(const ShaderType &type = ST_none) const;
|
||||
INLINE const bool get_error_flag() const;
|
||||
INLINE const ShaderLanguage get_language() const;
|
||||
|
||||
INLINE static ShaderUtilization get_shader_utilization();
|
||||
INLINE static void set_shader_utilization(ShaderUtilization utl);
|
||||
@ -57,14 +71,6 @@ PUBLISHED:
|
||||
|
||||
ShaderContext *prepare_now(PreparedGraphicsObjects *prepared_objects,
|
||||
GraphicsStateGuardianBase *gsg);
|
||||
|
||||
enum ShaderLanguage {
|
||||
SL_none,
|
||||
SL_Cg,
|
||||
SL_GLSL
|
||||
};
|
||||
|
||||
INLINE const ShaderLanguage get_language() const;
|
||||
|
||||
public:
|
||||
|
||||
@ -180,12 +186,6 @@ public:
|
||||
SMF_first,
|
||||
};
|
||||
|
||||
enum ShaderType {
|
||||
ST_VERTEX,
|
||||
ST_FRAGMENT,
|
||||
ST_GEOMETRY,
|
||||
};
|
||||
|
||||
struct ShaderArgId {
|
||||
string _name;
|
||||
ShaderType _type;
|
||||
@ -244,14 +244,27 @@ public:
|
||||
INLINE ShaderCaps();
|
||||
};
|
||||
|
||||
struct ShaderFile : public ReferenceCount {
|
||||
ShaderFile(string shared) { _separate = false; _shared = shared; }
|
||||
ShaderFile(string vertex, string fragment, string geometry = "") {
|
||||
_separate = true; _vertex = vertex;
|
||||
_fragment = fragment; _geometry = geometry;
|
||||
}
|
||||
bool _separate;
|
||||
string _shared;
|
||||
string _vertex;
|
||||
string _fragment;
|
||||
string _geometry;
|
||||
};
|
||||
|
||||
private:
|
||||
// These routines help split the shader into sections,
|
||||
// for those shader implementations that need to do so.
|
||||
// Don't use them when you use separate shader programs.
|
||||
void parse_init();
|
||||
void parse_line(string &result, bool rt, bool lt);
|
||||
void parse_upto(string &result, string pattern, bool include);
|
||||
void parse_rest(string &result);
|
||||
int parse_lineno();
|
||||
bool parse_eof();
|
||||
|
||||
void cp_report_error(ShaderArgInfo &arg, const string &msg);
|
||||
@ -330,10 +343,10 @@ public:
|
||||
pvector <ShaderVarSpec> _var_spec;
|
||||
|
||||
bool _error_flag;
|
||||
string _text;
|
||||
CPT(ShaderFile) _text;
|
||||
|
||||
protected:
|
||||
Filename _filename;
|
||||
CPT(ShaderFile)_filename;
|
||||
int _parse;
|
||||
bool _loaded;
|
||||
ShaderLanguage _language;
|
||||
@ -342,11 +355,10 @@ public:
|
||||
static ShaderUtilization _shader_utilization;
|
||||
static int _shaders_generated;
|
||||
|
||||
typedef pmap < Filename , Shader * > LoadTable;
|
||||
typedef pmap < string , Shader * > MakeTable;
|
||||
typedef pmap < CPT(ShaderFile), Shader * > ShaderTable;
|
||||
|
||||
static LoadTable _load_table;
|
||||
static MakeTable _make_table;
|
||||
static ShaderTable _load_table;
|
||||
static ShaderTable _make_table;
|
||||
|
||||
friend class ShaderContext;
|
||||
friend class PreparedGraphicsObjects;
|
||||
@ -355,10 +367,10 @@ public:
|
||||
Contexts _contexts;
|
||||
|
||||
private:
|
||||
Shader(const Filename &name, const string &text, const ShaderLanguage &lang = SL_none);
|
||||
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
|
||||
|
||||
public:
|
||||
Shader(CPT(ShaderFile) name, CPT(ShaderFile) text, const ShaderLanguage &lang = SL_none);
|
||||
static void register_with_read_factory();
|
||||
|
||||
~Shader();
|
||||
|
Loading…
x
Reference in New Issue
Block a user