diff --git a/source/lib/res/graphics/ogl_shader.cpp b/source/lib/res/graphics/ogl_shader.cpp deleted file mode 100644 index 5cb438214b..0000000000 --- a/source/lib/res/graphics/ogl_shader.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/* Copyright (c) 2010 Wildfire Games - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * load and link together shaders; provides hotload support. - */ - -#include "precompiled.h" -#include "ogl_shader.h" - -#include "lib/ogl.h" - -#include "ps/Filesystem.h" -#include "ps/CStr.h" -#include "ps/CLogger.h" -#include "ps/XML/Xeromyces.h" - -#include "lib/timer.h" -#include "lib/res/h_mgr.h" -#include "lib/file/vfs/vfs.h" - -static const StatusDefinition oglShaderStatusDefs[] = { - { ERR::SHDR_CREATE, L"Shader creation failed" }, - { ERR::SHDR_COMPILE, L"Shader compile failed" }, - { ERR::SHDR_NO_SHADER, L"Invalid shader reference" }, - { ERR::SHDR_LINK, L"Shader linking failed" }, - { ERR::SHDR_NO_PROGRAM, L"Invalid shader program reference" } -}; -STATUS_ADD_DEFINITIONS(oglShaderStatusDefs); - - -// Convert a shader object type into a descriptive string. -// If the type enum is not known, the given buffer is used as scratch space -// to format the type number. If buf is null, a generic string is returned. -static const wchar_t* shader_type_to_string(GLenum type, wchar_t* buf, size_t buflen) -{ - switch(type) - { - case GL_VERTEX_SHADER_ARB: return L"VERTEX_SHADER"; - case GL_FRAGMENT_SHADER_ARB: return L"FRAGMENT_SHADER"; - } - - if (!buf) - return L"unknown type enum"; - - swprintf_s(buf, buflen, L"%u", type); - return buf; -} - -// Return the OpenGL shader type enum for the given string, -// or 0 if the shader type is not known. -static GLenum string_to_shader_type(const char* name) -{ - if (!strcasecmp(name, "VERTEX_SHADER")) - return GL_VERTEX_SHADER_ARB; - if (!strcasecmp(name, "FRAGMENT_SHADER")) - return GL_FRAGMENT_SHADER_ARB; - return 0; -} - - -//---------------------------------------------------------------------------- -// Handle type implementation - -// Data for an Ogl_Shader object -struct Ogl_Shader { - // Type of shader (e.g. GL_VERTEX_SHADER_ARB) - GLenum type; - - // ID of the OpenGL shader object - GLhandleARB id; -}; - - -H_TYPE_DEFINE(Ogl_Shader); - - -// One-time initialization, called once by h_alloc, which is -// in turn called by ogl_shader_load -static void Ogl_Shader_init(Ogl_Shader* shdr, va_list args) -{ - shdr->type = va_arg(args, GLenum); -} - -TIMER_ADD_CLIENT(tc_compileShader); -TIMER_ADD_CLIENT(tc_linkProgram); - -// Reload the shader object from the source file. -// -// TODO: The OpenGL specification says that all changes to shader objects -// have absolutely no effect on a program object that contains these shaders -// when the program object is already linked. -// So, how can we inform the "parent object" (i.e. the program object) of our change? -static Status Ogl_Shader_reload(Ogl_Shader* shdr, const PIVFS& vfs, const VfsPath& pathname, Handle UNUSED(h)) -{ - Status err = ERR::FAIL; - - if (shdr->id) - return INFO::OK; - - shared_ptr file; size_t file_size; - RETURN_STATUS_IF_ERR(vfs->LoadFile(pathname, file, file_size)); - - ogl_WarnIfError(); - - shdr->id = pglCreateShaderObjectARB(shdr->type); - if (!shdr->id) - { - // May be out of memory, but bad shdr->type is also possible. - // In any case, checking OpenGL error state will help spot - // bad code. - ogl_WarnIfError(); - - WARN_RETURN(ERR::SHDR_CREATE); - } - - { - const GLchar* strings[] = { (const GLchar*)file.get() }; - const GLint tmp = (GLint)file_size; - pglShaderSourceARB(shdr->id, 1, strings, &tmp); - - // Some drivers (Mesa i915 on 945GM) give GL_INVALID_ENUM after calling - // CompileShader on a GL_FRAGMENT_PROGRAM, because the hardware doesn't support - // fragment programs. I can't find a better way to detect that situation in advance, - // so detect the error afterwards and return failure. - - ogl_WarnIfError(); - - { - TIMER_ACCRUE(tc_compileShader); - pglCompileShaderARB(shdr->id); - } - - if(ogl_SquelchError(GL_INVALID_ENUM)) - goto fail_shadercreated; - } - - { - wchar_t typenamebuf[32]; - CStrW type(shader_type_to_string(shdr->type, typenamebuf, ARRAY_SIZE(typenamebuf))); - - GLint log_length; - GLint compile_success; - pglGetShaderiv(shdr->id, GL_OBJECT_COMPILE_STATUS_ARB, &compile_success); - pglGetShaderiv(shdr->id, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length); - if (log_length > 1) - { - char* infolog = new char[log_length]; - pglGetShaderInfoLog(shdr->id, log_length, 0, infolog); - debug_printf(L"Compile log for shader %ls (type %ls):\n%hs", pathname.string().c_str(), type.c_str(), infolog); - delete[] infolog; - } - - if (!compile_success) - { - // Compilation failure caused by syntax errors and similar - // errors at the GLSL level does not set OpenGL error state - // according to the spec, but this might still prove to be - // useful some time. - ogl_WarnIfError(); - - debug_printf(L"Failed to compile shader %ls (type %ls)\n", pathname.string().c_str(), type.c_str()); - - err = ERR::SHDR_COMPILE; - goto fail_shadercreated; - } - } - - return INFO::OK; - -fail_shadercreated: - pglDeleteShader(shdr->id); - shdr->id = 0; - return err; -} - - -// Free associated resources -static void Ogl_Shader_dtor(Ogl_Shader* shdr) -{ - // shdr->id is 0 when reload has failed - if (shdr->id) - { - pglDeleteShader(shdr->id); - shdr->id = 0; - } -} - -static Status Ogl_Shader_validate(const Ogl_Shader* UNUSED(shdr)) -{ - // TODO - return INFO::OK; -} - -static Status Ogl_Shader_to_string(const Ogl_Shader* shdr, wchar_t* buf) -{ - swprintf_s(buf, H_STRING_LEN, L"Ogl_Shader %p", shdr); - return INFO::OK; -} - - -//---------------------------------------------------------------------------- -// Public API - -// Create, load and compile a shader object of the given type -// (e.g. GL_VERTEX_SHADER_ARB). The given file will be used as -// source code for the shader. -Handle ogl_shader_load(const PIVFS& vfs, const VfsPath& pathname, GLenum type) -{ - return h_alloc(H_Ogl_Shader, vfs, pathname, 0, type); -} - - -// Free all resources associated with the given handle (subject -// to refcounting). -void ogl_shader_free(Handle& h) -{ - h_free(h, H_Ogl_Shader); -} - -// Attach a shader to the given OpenGL program. -Status ogl_shader_attach(GLhandleARB program, Handle& h) -{ - H_DEREF(h, Ogl_Shader, shdr); - - if (!shdr->id) - WARN_RETURN(ERR::SHDR_NO_SHADER); - - pglAttachObjectARB(program, shdr->id); - - return INFO::OK; -} - - - -//---------------------------------------------------------------------------- -// Program type implementation - -struct Ogl_Program { - // ID of the OpenGL program object - GLhandleARB id; -}; - - -H_TYPE_DEFINE(Ogl_Program); - - -// One-time initialization, called once by h_alloc, which is -// in turn called by ogl_program_load -static void Ogl_Program_init(Ogl_Program* UNUSED(p), va_list UNUSED(args)) -{ -} - - -// Load the shader associated with one Shader element, -// and attach it to our program object. -static Status do_load_shader( - Ogl_Program* p, const VfsPath& pathname, Handle UNUSED(h), - const CXeromyces& XeroFile, const XMBElement& Shader) -{ -#define AT(x) int at_##x = XeroFile.GetAttributeID(#x) - AT(type); -#undef AT - - CStr Type = Shader.GetAttributes().GetNamedItem(at_type); - - if (Type.empty()) - { - LOGERROR(L"%ls: Missing attribute \"type\" in element \"Shader\".", pathname.string().c_str()); - WARN_RETURN(ERR::CORRUPTED); - } - - GLenum shadertype = string_to_shader_type(Type.c_str()); - - if (!shadertype) - { - LOGERROR(L"%ls: Unknown shader type \"%hs\" (valid are: VERTEX_SHADER, FRAGMENT_SHADER).", pathname.string().c_str(), Type.c_str()); - WARN_RETURN(ERR::CORRUPTED); - } - - CStr pathnameShader = Shader.GetText(); - - if (pathnameShader.empty()) - { - LOGERROR(L"%ls: Missing shader name.", pathname.string().c_str()); - WARN_RETURN(ERR::CORRUPTED); - } - - Handle hshader = ogl_shader_load(g_VFS, pathnameShader.FromUTF8(), shadertype); - RETURN_STATUS_IF_ERR(hshader); - - ogl_shader_attach(p->id, hshader); - - // According to the OpenGL specification, a shader object's deletion - // will not be final as long as the shader object is attached to a - // container object. - // TODO: How will this work with automatic reload? - ogl_shader_free(hshader); - - return INFO::OK; -} - - -// Reload the program object from the source file. -static Status Ogl_Program_reload(Ogl_Program* p, const PIVFS& vfs, const VfsPath& pathname, Handle h) -{ - if (p->id) - return INFO::OK; - - ogl_WarnIfError(); - - // Check that we're not accidentally using shaders when they're not supported - ENSURE(pglCreateProgramObjectARB != NULL); - - p->id = pglCreateProgramObjectARB(); - if (!p->id) - { - // The spec doesn't mention any error state that can be set - // here, but it may still help spot bad code. - ogl_WarnIfError(); - - WARN_RETURN(ERR::SHDR_CREATE); - } - - CXeromyces XeroFile; - if (XeroFile.Load(vfs, pathname) != PSRETURN_OK) - WARN_RETURN(ERR::CORRUPTED); // more informative error message? - - // Define all the elements and attributes used in the XML file -#define EL(x) int el_##x = XeroFile.GetElementID(#x) - EL(program); - EL(shaders); - EL(shader); -#undef EL - - XMBElement Root = XeroFile.GetRoot(); - - if (Root.GetNodeName() != el_program) - { - LOGERROR(L"%ls: XML root was not \"Program\".", pathname.string().c_str()); - WARN_RETURN(ERR::CORRUPTED); - } - - XMBElementList RootChildren = Root.GetChildNodes(); - - for(int i = 0; i < RootChildren.Count; ++i) - { - XMBElement Child = RootChildren.Item(i); - - int ChildName = Child.GetNodeName(); - if (ChildName == el_shaders) - { - XMBElementList Shaders = Child.GetChildNodes(); - - for(int j = 0; j < Shaders.Count; ++j) - { - XMBElement Shader = Shaders.Item(j); - - if (Shader.GetNodeName() != el_shader) - { - LOGERROR(L"%ls: Only \"Shader\" may be child of \"Shaders\".", pathname.string().c_str()); - WARN_RETURN(ERR::CORRUPTED); - } - - RETURN_STATUS_IF_ERR(do_load_shader(p, pathname, h, XeroFile, Shader)); - } - } - else - { - LOGWARNING(L"%ls: Unknown child of \"Program\".", pathname.string().c_str()); - } - } - - { - TIMER_ACCRUE(tc_linkProgram); - pglLinkProgramARB(p->id); - } - - GLint log_length; - GLint linked; - - pglGetProgramiv(p->id, GL_OBJECT_LINK_STATUS_ARB, &linked); - pglGetProgramiv(p->id, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length); - if (log_length > 1) - { - char* infolog = new char[log_length]; - pglGetProgramInfoLog(p->id, log_length, 0, infolog); - debug_printf(L"Linker log for %ls:\n%hs\n", pathname.string().c_str(), infolog); - delete[] infolog; - } - - if (!linked) - { - debug_printf(L"Link failed for %ls\n", pathname.string().c_str()); - WARN_RETURN(ERR::SHDR_LINK); - } - - return INFO::OK; -} - - -// Free associated resources -static void Ogl_Program_dtor(Ogl_Program* p) -{ - if (p->id) - { - pglDeleteProgram(p->id); - p->id = 0; - } -} - -static Status Ogl_Program_validate(const Ogl_Program* UNUSED(p)) -{ - // TODO - return INFO::OK; -} - -static Status Ogl_Program_to_string(const Ogl_Program* p, wchar_t* buf) -{ - swprintf_s(buf, H_STRING_LEN, L"Ogl_Program %p", p); - return INFO::OK; -} - - -//---------------------------------------------------------------------------- -// Public API - -// Load a program object based on the given XML file description. -// Shader objects are loaded and attached automatically. -Handle ogl_program_load(const PIVFS& vfs, const VfsPath& pathname) -{ - return h_alloc(H_Ogl_Program, vfs, pathname, 0); -} - -// Free all resources associated with the given program handle. -void ogl_program_free(Handle& h) -{ - h_free(h, H_Ogl_Program); -} - - -// Activate the program (glUseProgramObjectARB). -// h may be 0, in which case program objects are disabled. -Status ogl_program_use(Handle h) -{ - if (!h) - { - pglUseProgramObjectARB(0); - return INFO::OK; - } - - Ogl_Program* p = H_USER_DATA(h, Ogl_Program); - if (!p || !p->id) - { - pglUseProgramObjectARB(0); - WARN_RETURN(ERR::INVALID_HANDLE); - } - - pglUseProgramObjectARB(p->id); - return INFO::OK; -} - - -// Query uniform information -GLint ogl_program_get_uniform_location(Handle h, const char* name) -{ - H_DEREF(h, Ogl_Program, p); - - return pglGetUniformLocationARB(p->id, name); -} - - -// Query vertex attribute information -GLint ogl_program_get_attrib_location(Handle h, const char* name) -{ - H_DEREF(h, Ogl_Program, p); - - return pglGetAttribLocationARB(p->id, name); -} diff --git a/source/lib/res/graphics/ogl_shader.h b/source/lib/res/graphics/ogl_shader.h deleted file mode 100644 index 02e24ed462..0000000000 --- a/source/lib/res/graphics/ogl_shader.h +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright (c) 2010 Wildfire Games - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * load and link together shaders; provides hotload support. - */ - -#ifndef INCLUDED_OGL_SHADER -#define INCLUDED_OGL_SHADER - -#include "lib/res/handle.h" -#include "lib/file/vfs/vfs.h" - -#include "lib/ogl.h" - - -namespace ERR -{ - const Status SHDR_CREATE = -120200; - const Status SHDR_COMPILE = -120201; - const Status SHDR_NO_SHADER = -120202; - const Status SHDR_LINK = -120203; - const Status SHDR_NO_PROGRAM = -120204; -} - -/* -Encapsulate shader objects into handles, which transparently enables sharing -of shader source files between programs as well as reloading shaders at -runtime. - -NOTE: Only use functions form this module after verifying that the required -extensions are available, or all bets are off. -*/ - -/** - * Create, load and compile a shader object. - * - * @param vfs - * @param pathname Location of the file containing the shader's source code. - * @param type Type e.g. GL_VERTEX_SHADER_ARB. - **/ -Handle ogl_shader_load(const PIVFS& vfs, const VfsPath& pathname, GLenum type); - -/** - * Free all resources associated with the given handle - * (subject to reference counting). - **/ -void ogl_shader_free(Handle& h); - -/** - * Attach a shader to the given OpenGL program. - **/ -Status ogl_shader_attach(GLhandleARB program, Handle& h); - - -/* -Encapsulate program objects into handles. -*/ - -/** - * Load a program object. - * - * @param vfs - * @param pathname XML file describing the program. - * - * note: Shader objects are loaded and attached automatically. - **/ -Handle ogl_program_load(const PIVFS& vfs, const VfsPath& pathname); - -/** - * Free all resources associated with the given program handle. - * (subject to reference counting). - **/ -void ogl_program_free(Handle& h); - -/** - * Activate the program (glUseProgramObjectARB). - * - * @param h may be 0, in which case program objects are disabled. - **/ -Status ogl_program_use(Handle h); - -/** - * Query uniform information - **/ -GLint ogl_program_get_uniform_location(Handle h, const char* name); - -/** - * Query vertex attribute information - **/ -GLint ogl_program_get_attrib_location(Handle h, const char* name); - -#endif // INCLUDED_OGL_SHADER diff --git a/source/lib/status.h b/source/lib/status.h index b8d22909e3..b4f6b887f8 100644 --- a/source/lib/status.h +++ b/source/lib/status.h @@ -149,7 +149,6 @@ To summarize: +/-1SHHCC (S=subsystem, HH=header, CC=code number) 12 res 00CC h_mgr 01CC tex - 02CC ogl_shader 13 sysdep 00CC cpu diff --git a/source/renderer/TerrainRenderer.cpp b/source/renderer/TerrainRenderer.cpp index 834e0d6ecf..18703cd79a 100644 --- a/source/renderer/TerrainRenderer.cpp +++ b/source/renderer/TerrainRenderer.cpp @@ -50,8 +50,6 @@ #include "renderer/VertexArray.h" #include "renderer/WaterManager.h" -#include "lib/res/graphics/ogl_shader.h" - /////////////////////////////////////////////////////////////////////////////////////////////// // TerrainRenderer implementation @@ -680,15 +678,10 @@ bool TerrainRenderer::RenderFancyWater() glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); - // Unbind the LOS/refraction/reflection textures and the shader - g_Renderer.BindTexture(3, 0); - g_Renderer.BindTexture(2, 0); - g_Renderer.BindTexture(1, 0); + m->fancyWaterShader->Unbind(); pglActiveTextureARB(GL_TEXTURE0_ARB); - ogl_program_use(0); - glDisable(GL_BLEND); return true;