1 /* Copyright (C) 2017 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef INCLUDED_SHADERPROGRAM 19 #define INCLUDED_SHADERPROGRAM 20 21 #include "graphics/ShaderProgramPtr.h" 22 #include "graphics/Texture.h" 23 #include "lib/ogl.h" 24 #include "lib/file/vfs/vfs_path.h" 25 #include "lib/res/handle.h" 26 27 #include <map> 28 29 struct CColor; 30 class CMatrix3D; 31 class CVector3D; 32 class CShaderDefines; 33 class CStrIntern; 34 35 // Vertex data stream flags 36 enum 37 { 38 STREAM_POS = (1 << 0), 39 STREAM_NORMAL = (1 << 1), 40 STREAM_COLOR = (1 << 2), 41 STREAM_UV0 = (1 << 3), 42 STREAM_UV1 = (1 << 4), 43 STREAM_UV2 = (1 << 5), 44 STREAM_UV3 = (1 << 6), 45 STREAM_POSTOUV0 = (1 << 7), 46 STREAM_POSTOUV1 = (1 << 8), 47 STREAM_POSTOUV2 = (1 << 9), 48 STREAM_POSTOUV3 = (1 << 10) 49 }; 50 51 /** 52 * A compiled vertex+fragment shader program. 53 * The implementation may use GL_ARB_{vertex,fragment}_program (ARB assembly syntax) 54 * or GL_ARB_{vertex,fragment}_shader (GLSL), or may use hard-coded fixed-function 55 * multitexturing setup code; the difference is hidden from the caller. 56 * 57 * Texture/uniform IDs are typically strings, corresponding to the names defined in 58 * the shader .xml file. Alternatively (and more efficiently, if used very frequently), 59 * call GetTextureBinding/GetUniformBinding and pass its return value as the ID. 60 * Setting uniforms that the shader .xml doesn't support is harmless. 61 * 62 * For a high-level overview of shaders and materials, see 63 * http://trac.wildfiregames.com/wiki/MaterialSystem 64 */ 65 class CShaderProgram 66 { 67 NONCOPYABLE(CShaderProgram); 68 69 public: 70 typedef CStrIntern attrib_id_t; 71 typedef CStrIntern texture_id_t; 72 typedef CStrIntern uniform_id_t; 73 typedef std::pair<int, GLenum> frag_index_pair_t; 74 75 /** 76 * Construct based on ARB vertex/fragment program files. 77 */ 78 static CShaderProgram* ConstructARB(const VfsPath& vertexFile, const VfsPath& fragmentFile, 79 const CShaderDefines& defines, 80 const std::map<CStrIntern, int>& vertexIndexes, const std::map<CStrIntern, frag_index_pair_t>& fragmentIndexes, 81 int streamflags); 82 83 /** 84 * Construct based on GLSL vertex/fragment shader files. 85 */ 86 static CShaderProgram* ConstructGLSL(const VfsPath& vertexFile, const VfsPath& fragmentFile, 87 const CShaderDefines& defines, 88 const std::map<CStrIntern, int>& vertexAttribs, 89 int streamflags); 90 91 /** 92 * Construct an instance of a pre-defined fixed-function pipeline setup. 93 */ 94 static CShaderProgram* ConstructFFP(const std::string& id, const CShaderDefines& defines); 95 96 /** 97 * Represents a uniform attribute or texture binding. 98 * For uniforms: 99 * - ARB shaders store vertex location in 'first', fragment location in 'second'. 100 * - GLSL shaders store uniform location in 'first', data type in 'second'. 101 * - FFP shaders store -1 in 'first', index in 'second'. 102 * For textures, all store texture target (e.g. GL_TEXTURE_2D) in 'first', texture unit in 'second'. 103 * Non-existent bindings must store -1 in both. 104 */ 105 struct Binding 106 { BindingBinding107 Binding(int a, int b) : first(a), second(b) { } 108 BindingBinding109 Binding() : first(-1), second(-1) { } 110 111 /** 112 * Returns whether this uniform attribute is active in the shader. 113 * If not then there's no point calling Uniform() to set its value. 114 */ ActiveBinding115 bool Active() { return first != -1 || second != -1; } 116 117 int first; 118 int second; 119 }; 120 ~CShaderProgram()121 virtual ~CShaderProgram() { } 122 123 virtual void Reload() = 0; 124 125 /** 126 * Returns whether this shader was successfully loaded. 127 */ 128 bool IsValid() const; 129 130 /** 131 * Binds the shader into the GL context. Call this before calling Uniform() 132 * or trying to render with it. 133 */ 134 virtual void Bind() = 0; 135 136 /** 137 * Unbinds the shader from the GL context. Call this after rendering with it. 138 */ 139 virtual void Unbind() = 0; 140 141 /** 142 * Returns bitset of STREAM_* value, indicating what vertex data streams the 143 * vertex shader needs (e.g. position, color, UV, ...). 144 */ 145 int GetStreamFlags() const; 146 147 148 virtual Binding GetTextureBinding(texture_id_t id) = 0; 149 150 // Variants of texture binding: 151 void BindTexture(texture_id_t id, CTexturePtr tex); 152 virtual void BindTexture(texture_id_t id, Handle tex) = 0; 153 virtual void BindTexture(texture_id_t id, GLuint tex) = 0; 154 virtual void BindTexture(Binding id, Handle tex) = 0; 155 156 157 virtual Binding GetUniformBinding(uniform_id_t id) = 0; 158 159 // Uniform-setting methods that subclasses must define: 160 virtual void Uniform(Binding id, float v0, float v1, float v2, float v3) = 0; 161 virtual void Uniform(Binding id, const CMatrix3D& v) = 0; 162 virtual void Uniform(Binding id, size_t count, const CMatrix3D* v) = 0; 163 164 // Convenient uniform-setting wrappers: 165 166 void Uniform(Binding id, int v); 167 void Uniform(Binding id, float v); 168 void Uniform(Binding id, float v0, float v1); 169 void Uniform(Binding id, const CVector3D& v); 170 void Uniform(Binding id, const CColor& v); 171 172 void Uniform(uniform_id_t id, int v); 173 void Uniform(uniform_id_t id, float v); 174 void Uniform(uniform_id_t id, float v0, float v1); 175 void Uniform(uniform_id_t id, const CVector3D& v); 176 void Uniform(uniform_id_t id, const CColor& v); 177 void Uniform(uniform_id_t id, float v0, float v1, float v2, float v3); 178 void Uniform(uniform_id_t id, const CMatrix3D& v); 179 void Uniform(uniform_id_t id, size_t count, const CMatrix3D* v); 180 181 // Vertex attribute pointers (equivalent to glVertexPointer etc): 182 183 virtual void VertexPointer(GLint size, GLenum type, GLsizei stride, const void* pointer); 184 virtual void NormalPointer(GLenum type, GLsizei stride, const void* pointer); 185 virtual void ColorPointer(GLint size, GLenum type, GLsizei stride, const void* pointer); 186 virtual void TexCoordPointer(GLenum texture, GLint size, GLenum type, GLsizei stride, const void* pointer); 187 virtual void VertexAttribPointer(attrib_id_t id, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); 188 virtual void VertexAttribIPointer(attrib_id_t id, GLint size, GLenum type, GLsizei stride, const void* pointer); 189 190 /** 191 * Checks that all the required vertex attributes have been set. 192 * Call this before calling glDrawArrays/glDrawElements etc to avoid potential crashes. 193 */ 194 void AssertPointersBound(); 195 196 protected: 197 CShaderProgram(int streamflags); 198 199 bool m_IsValid; 200 int m_StreamFlags; 201 202 // Non-GLSL client state handling: 203 void BindClientStates(); 204 void UnbindClientStates(); 205 int m_ValidStreams; // which streams have been specified via VertexPointer etc since the last Bind 206 }; 207 208 #endif // INCLUDED_SHADERPROGRAM 209