/** * Creates an executable shader. * * @param vs Vertex shader source code * @param fs Fragment shader source code * @param gs Geometry shader source code * @return Internal ID of compiled and linked shader generated by OpenGL */ GLhandleARB opengl_shader_create(const SCP_vector<SCP_string>& vs, const SCP_vector<SCP_string>& fs, const SCP_vector<SCP_string>& gs) { GLhandleARB vs_o = 0; GLhandleARB fs_o = 0; GLhandleARB gs_o = 0; GLhandleARB program = 0; if (!vs.empty()) { vs_o = opengl_shader_compile_object( vs, GL_VERTEX_SHADER_ARB ); if ( !vs_o ) { mprintf(("ERROR! Unable to create vertex shader!\n")); goto Done; } } if (!fs.empty()) { fs_o = opengl_shader_compile_object( fs, GL_FRAGMENT_SHADER_ARB ); if ( !fs_o ) { mprintf(("ERROR! Unable to create fragment shader!\n")); goto Done; } } if (!gs.empty()) { gs_o = opengl_shader_compile_object( gs, GL_GEOMETRY_SHADER_EXT ); if ( !gs_o ) { mprintf(("ERROR! Unable to create fragment shader!\n")); goto Done; } } program = opengl_shader_link_object(vs_o, fs_o, gs_o); if ( !program ) { mprintf(("ERROR! Unable to create shader program!\n")); } Done: if (vs_o) { vglDeleteObjectARB(vs_o); } if (fs_o) { vglDeleteObjectARB(fs_o); } if (gs_o) { vglDeleteObjectARB(gs_o); } return program; }
/** * Pass a GLSL shader source to OpenGL and compile it into a usable shader object. * Prints compilation errors (if any) to the log. * Note that this will only compile shaders into objects, linking them into executables happens later * * @param shader_source GLSL sourcecode for the shader * @param shader_type OpenGL ID for the type of shader being used, like GL_FRAGMENT_SHADER_ARB, GL_VERTEX_SHADER_ARB * @return OpenGL handle for the compiled shader object */ GLhandleARB opengl_shader_compile_object(const GLcharARB *shader_source, GLenum shader_type) { GLhandleARB shader_object = 0; GLint status = 0; shader_object = vglCreateShaderObjectARB(shader_type); vglShaderSourceARB(shader_object, 1, &shader_source, NULL); vglCompileShaderARB(shader_object); // check if the compile was successful vglGetObjectParameterivARB(shader_object, GL_OBJECT_COMPILE_STATUS_ARB, &status); opengl_shader_check_info_log(shader_object); // we failed, bail out now... if (status == 0) { // basic error check mprintf(("%s shader failed to compile:\n%s\n", (shader_type == GL_VERTEX_SHADER_ARB) ? "Vertex" : "Fragment", GLshader_info_log)); // this really shouldn't exist, but just in case if (shader_object) { vglDeleteObjectARB(shader_object); } return 0; } // we succeeded, maybe output warnings too if (strlen(GLshader_info_log) > 5) { nprintf(("SHADER-DEBUG", "%s shader compiled with warnings:\n%s\n", (shader_type == GL_VERTEX_SHADER_ARB) ? "Vertex" : "Fragment", GLshader_info_log)); } return shader_object; }
/** * Go through GL_shader and call glDeleteObject() for all created shaders, then clear GL_shader */ void opengl_shader_shutdown() { size_t i; if ( !is_minimum_GLSL_version() ) { return; } for (i = 0; i < GL_shader.size(); i++) { if (GL_shader[i].program_id) { vglDeleteObjectARB(GL_shader[i].program_id); GL_shader[i].program_id = 0; } GL_shader[i].uniforms.clear(); GL_shader[i].attributes.clear(); GL_shader[i].uniform_blocks.clear(); } GL_shader.clear(); if (GLshader_info_log != NULL) { vm_free(GLshader_info_log); GLshader_info_log = NULL; } }
/** * Link vertex shader, fragment shader and geometry shader objects into a * usable shader executable. * * Prints linker errors (if any) to the log. * * @param vertex_object Compiled vertex shader object * @param fragment_object Compiled fragment shader object * @param geometry_object Compiled geometry shader object * @return Shader executable */ GLhandleARB opengl_shader_link_object(GLhandleARB vertex_object, GLhandleARB fragment_object, GLhandleARB geometry_object) { GLhandleARB shader_object = 0; GLint status = 0; shader_object = vglCreateProgramObjectARB(); if (vertex_object) { vglAttachObjectARB(shader_object, vertex_object); } if (fragment_object) { vglAttachObjectARB(shader_object, fragment_object); } if (geometry_object) { vglAttachObjectARB(shader_object, geometry_object); if ( Current_geo_sdr_params != NULL) { #ifdef __APPLE__ vglProgramParameteriEXT((long)shader_object, GL_GEOMETRY_INPUT_TYPE_EXT, Current_geo_sdr_params->input_type); vglProgramParameteriEXT((long)shader_object, GL_GEOMETRY_OUTPUT_TYPE_EXT, Current_geo_sdr_params->output_type); vglProgramParameteriEXT((long)shader_object, GL_GEOMETRY_VERTICES_OUT_EXT, Current_geo_sdr_params->vertices_out); #else vglProgramParameteriEXT((GLuint)shader_object, GL_GEOMETRY_INPUT_TYPE_EXT, Current_geo_sdr_params->input_type); vglProgramParameteriEXT((GLuint)shader_object, GL_GEOMETRY_OUTPUT_TYPE_EXT, Current_geo_sdr_params->output_type); vglProgramParameteriEXT((GLuint)shader_object, GL_GEOMETRY_VERTICES_OUT_EXT, Current_geo_sdr_params->vertices_out); #endif } } vglLinkProgramARB(shader_object); // check if the link was successful vglGetObjectParameterivARB(shader_object, GL_OBJECT_LINK_STATUS_ARB, &status); opengl_shader_check_info_log(shader_object); // we failed, bail out now... if (status == 0) { mprintf(("Shader failed to link:\n%s\n", GLshader_info_log)); if (shader_object) { vglDeleteObjectARB(shader_object); } return 0; } // we succeeded, maybe output warnings too if (strlen(GLshader_info_log) > 5) { nprintf(("SHADER-DEBUG", "Shader linked with warnings:\n%s\n", GLshader_info_log)); } return shader_object; }
/** * Creates an executable shader. * * @param vs Vertex shader source code * @param fs Fragment shader source code * @return Internal ID of the compiled and linked shader as generated by OpenGL */ GLhandleARB opengl_shader_create(const char *vs, const char *fs) { GLhandleARB vs_o = 0; GLhandleARB fs_o = 0; GLhandleARB program = 0; if (vs) { vs_o = opengl_shader_compile_object( (const GLcharARB*)vs, GL_VERTEX_SHADER_ARB ); if ( !vs_o ) { mprintf(("ERROR! Unable to create vertex shader!\n")); goto Done; } } if (fs) { fs_o = opengl_shader_compile_object( (const GLcharARB*)fs, GL_FRAGMENT_SHADER_ARB ); if ( !fs_o ) { mprintf(("ERROR! Unable to create fragment shader!\n")); goto Done; } } program = opengl_shader_link_object(vs_o, fs_o); if ( !program ) { mprintf(("ERROR! Unable to create shader program!\n")); } Done: if (vs_o) { vglDeleteObjectARB(vs_o); } if (fs_o) { vglDeleteObjectARB(fs_o); } return program; }
void opengl_delete_shader(int sdr_handle) { Assert(sdr_handle >= 0); Assert(sdr_handle < (int)GL_shader.size()); if (GL_shader[sdr_handle].program_id) { vglDeleteObjectARB(GL_shader[sdr_handle].program_id); GL_shader[sdr_handle].program_id = 0; } GL_shader[sdr_handle].flags = 0; GL_shader[sdr_handle].flags2 = 0; GL_shader[sdr_handle].shader = NUM_SHADER_TYPES; GL_shader[sdr_handle].uniforms.clear(); GL_shader[sdr_handle].attributes.clear(); GL_shader[sdr_handle].uniform_blocks.clear(); }
/** * Pass a GLSL shader source to OpenGL and compile it into a usable shader object. * Prints compilation errors (if any) to the log. * Note that this will only compile shaders into objects, linking them into executables happens later * * @param shader_source GLSL sourcecode for the shader * @param shader_type OpenGL ID for the type of shader being used, like GL_FRAGMENT_SHADER_ARB, GL_VERTEX_SHADER_ARB * @return OpenGL handle for the compiled shader object */ GLhandleARB opengl_shader_compile_object(const SCP_vector<SCP_string>& shader_source, GLenum shader_type) { GLhandleARB shader_object = 0; GLint status = 0; SCP_vector<const GLcharARB*> sources; sources.reserve(shader_source.size()); for (auto it = shader_source.begin(); it != shader_source.end(); ++it) { sources.push_back(it->c_str()); } shader_object = vglCreateShaderObjectARB(shader_type); vglShaderSourceARB(shader_object, sources.size(), &sources[0], NULL); vglCompileShaderARB(shader_object); // check if the compile was successful vglGetObjectParameterivARB(shader_object, GL_OBJECT_COMPILE_STATUS_ARB, &status); opengl_shader_check_info_log(shader_object); // we failed, bail out now... if (status == 0) { // basic error check mprintf(("%s shader failed to compile:\n%s\n", (shader_type == GL_VERTEX_SHADER_ARB) ? "Vertex" : ((shader_type == GL_GEOMETRY_SHADER_EXT) ? "Geometry" : "Fragment"), GLshader_info_log)); // this really shouldn't exist, but just in case if (shader_object) { vglDeleteObjectARB(shader_object); } return 0; } // we succeeded, maybe output warnings too if (strlen(GLshader_info_log) > 5) { nprintf(("SHADER-DEBUG", "%s shader compiled with warnings:\n%s\n", (shader_type == GL_VERTEX_SHADER_ARB) ? "Vertex" : ((shader_type == GL_GEOMETRY_SHADER_EXT) ? "Geometry" : "Fragment"), GLshader_info_log)); } return shader_object; }
/** * Link a vertex shader object and a fragment shader object into a usable shader executable. * Prints linker errors (if any) to the log. * * @param vertex_object Compiled vertex shader object * @param fragment_object Compiled fragment shader object * @return Shader executable */ GLhandleARB opengl_shader_link_object(GLhandleARB vertex_object, GLhandleARB fragment_object) { GLhandleARB shader_object = 0; GLint status = 0; shader_object = vglCreateProgramObjectARB(); if (vertex_object) { vglAttachObjectARB(shader_object, vertex_object); } if (fragment_object) { vglAttachObjectARB(shader_object, fragment_object); } vglLinkProgramARB(shader_object); // check if the link was successful vglGetObjectParameterivARB(shader_object, GL_OBJECT_LINK_STATUS_ARB, &status); opengl_shader_check_info_log(shader_object); // we failed, bail out now... if (status == 0) { mprintf(("Shader failed to link:\n%s\n", GLshader_info_log)); if (shader_object) { vglDeleteObjectARB(shader_object); } return 0; } // we succeeded, maybe output warnings too if (strlen(GLshader_info_log) > 5) { nprintf(("SHADER-DEBUG", "Shader linked with warnings:\n%s\n", GLshader_info_log)); } return shader_object; }
/** * Go through GL_shader and call glDeleteObject() for all created shaders, then clear GL_shader */ void opengl_shader_shutdown() { size_t i; if ( !Use_GLSL ) { return; } for (i = 0; i < GL_shader.size(); i++) { if (GL_shader[i].program_id) { vglDeleteObjectARB(GL_shader[i].program_id); GL_shader[i].program_id = 0; } GL_shader[i].uniforms.clear(); } GL_shader.clear(); if (GLshader_info_log != NULL) { vm_free(GLshader_info_log); GLshader_info_log = NULL; } }