SuperTuxKart
texture_shader.hpp
1 // SuperTuxKart - a fun racing game with go-kart
2 // Copyright (C) 2014-2015 SuperTuxKart-Team
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 3
7 // of the License, or (at your option) any later version.
8 //
9 // This program 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 this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 
18 #ifndef SHADER_ONLY
19 
20 #ifndef HEADER_TEXTURE_SHADER_HPP
21 #define HEADER_TEXTURE_SHADER_HPP
22 
23 #include "graphics/central_settings.hpp"
24 #include "graphics/gl_headers.hpp"
25 #include "graphics/shader.hpp"
26 #include "utils/cpp2011.hpp"
27 
28 #include <assert.h>
29 #include <functional>
30 #include <vector>
31 
32 
33 enum SamplerTypeNew
34 {
35  ST_MIN,
36  ST_NEAREST_FILTERED = ST_MIN,
37  ST_TRILINEAR_ANISOTROPIC_FILTERED,
38  ST_TRILINEAR_CUBEMAP,
39  ST_BILINEAR_FILTERED,
40  ST_NEAREST_FILTERED_ARRAY2D,
41  ST_SHADOW_SAMPLER,
42  ST_SHADOW_SAMPLER_ARRAY2D,
43  ST_TRILINEAR_CLAMPED_ARRAY2D,
44  ST_VOLUME_LINEAR_FILTERED,
45  ST_NEARED_CLAMPED_FILTERED,
46  ST_BILINEAR_CLAMPED_FILTERED,
47  ST_SEMI_TRILINEAR,
48 #ifdef USE_GLES2
49  ST_MAX = ST_SEMI_TRILINEAR
50 #else
51  ST_TEXTURE_BUFFER,
52  ST_MAX = ST_TEXTURE_BUFFER
53 #endif
54 }; // SamplerTypeNew
55 
56 // ============================================================================
63 {
64 public:
65  typedef std::function<void(GLuint, GLuint)> BindFunction;
66 
67 protected:
68  static void bindTextureNearest(GLuint tex_unit, GLuint tex_id);
69  static void bindTextureBilinear(GLuint texture_unit, GLuint tex_id);
70  static void bindTextureBilinearClamped(GLuint tex_unit, GLuint tex_id);
71  static void bindTextureNearestClamped(GLuint tex_unit, GLuint tex_id);
72  static void bindTextureTrilinearAnisotropic(GLuint tex_unit, GLuint tex_id);
73  static void bindTextureSemiTrilinear(GLuint tex_unit, GLuint tex_id);
74  static void bindCubemapTrilinear(GLuint tex_unit, GLuint tex_id);
75  static void bindTextureNearestArray(GLuint tex_unit, GLuint tex_id);
76  static void bindTextureShadow(GLuint tex_unit, GLuint tex_id);
77  static void bindTextureShadowArray(GLuint tex_unit, GLuint tex_id);
78  static void bindTrilinearClampedArrayTexture(GLuint tex_unit, GLuint tex_id);
79  static void bindTextureVolume(GLuint tex_unit, GLuint tex_id);
80  static void bindTextureBuffer(GLuint tex_unit, GLuint tex_id);
81 
82  GLuint createSamplers(SamplerTypeNew sampler_type);
83 private:
84 
85  static GLuint createNearestSampler();
86  static GLuint createTrilinearSampler();
87  static GLuint createBilinearSampler();
88  static GLuint createShadowSampler();
89  static GLuint createTrilinearClampedArray();
90  static GLuint createBilinearClampedSampler();
91  static GLuint createSemiTrilinearSampler();
92 protected:
93  static BindFunction m_all_bind_functions[];
94  std::vector<BindFunction> m_bind_functions;
95  static GLuint m_all_texture_types[];
96 }; // TextureshaderBase
97 
98 // ========================================================================
104 template<class C, int NUM_TEXTURES, typename...tp>
106  , public Shader<C, tp...>
107 {
108 
109 private:
110 
111  std::vector<GLuint> m_texture_units;
112  std::vector<GLenum> m_texture_type;
113  std::vector<GLenum> m_texture_location;
114 
115 public:
116  std::vector<GLuint> m_sampler_ids;
117 
118  // A variadic template to assign texture names
119  // ===========================================
120 private:
123  template<unsigned N, typename...Args>
125  {
126  static_assert(N == NUM_TEXTURES, "Wrong number of texture names");
127  } // assignTextureNamesImpl
128 
129  // ------------------------------------------------------------------------
133  template<unsigned N, typename...Args>
134  void assignTextureNamesImpl(GLuint tex_unit, const char *name,
135  SamplerTypeNew sampler_type, Args...args)
136  {
137 
138  m_sampler_ids.push_back(createSamplers(sampler_type));
139 
140  assert(sampler_type >= ST_MIN && sampler_type <= ST_MAX);
141  m_texture_type.push_back(m_all_texture_types[sampler_type]);
142 
143  GLuint location = this->getUniformLocation(name);
144  m_texture_location.push_back(location);
145  glUniform1i(location, tex_unit);
146  m_texture_units.push_back(tex_unit);
147 
148  // Duplicated assert
149  assert(sampler_type >= ST_MIN && sampler_type <= ST_MAX);
150  m_bind_functions.push_back( m_all_bind_functions[sampler_type]);
151 
152  assignTextureNamesImpl<N + 1>(args...);
153  } // assignTextureNamesImpl
154 
155  // ------------------------------------------------------------------------
156 public:
160  template<typename...Args>
161  void assignSamplerNames(Args...args)
162  {
163  this->use();
164  assignTextureNamesImpl<0>(args...);
165  glUseProgram(0);
166  } // AssignSamplerNames
167 
168 
169  // Variadic template implementation of setTextureUnits
170  // ===================================================
172  template<int N>
174  {
175  static_assert(N == NUM_TEXTURES, "Not enough texture set");
176  } // setTextureUnitsImpl
177 
178  // ------------------------------------------------------------------------
181  template<int N, typename... TexIds>
182  void setTextureUnitsImpl(GLuint tex_id, TexIds... args)
183  {
184  if (CVS->isARBSamplerObjectsUsable())
185  {
186  glActiveTexture(GL_TEXTURE0 + m_texture_units[N]);
187  glBindTexture(m_texture_type[N], tex_id);
188  glBindSampler(m_texture_units[N], m_sampler_ids[N]);
189  }
190  else
191  {
192  m_bind_functions[N](m_texture_units[N], tex_id);
193  }
194  setTextureUnitsImpl<N + 1>(args...);
195  } // setTextureUnitsImpl
196 
197  // ------------------------------------------------------------------------
198 public:
201  template<typename... TexIds>
202  void setTextureUnits(TexIds... args)
203  {
204  setTextureUnitsImpl<0>(args...);
205  } // setTextureUnits
206 
207 
208  // ========================================================================
209  // Variadic template implementation of setTextureHandles.
210 
214  template<int N>
216  {
217  static_assert(N == NUM_TEXTURES, "Not enough handles set");
218  } // setTextureHandlesImpl
219 
220  // ------------------------------------------------------------------------
226  template<int N, typename... HandlesId>
227  void setTextureHandlesImpl(uint64_t handle, HandlesId... args)
228  {
229 #if !defined(USE_GLES2)
230  if (handle)
231  glUniformHandleui64ARB(m_texture_location[N], handle);
232 #endif
233  setTextureHandlesImpl<N + 1>(args...);
234  } // setTextureHandlesImpl
235 
236  // ------------------------------------------------------------------------
237 public:
241  template<typename... HandlesId>
242  void setTextureHandles(HandlesId... ids)
243  {
244  setTextureHandlesImpl<0>(ids...);
245  } // SetTextureHandles
246 
247 public:
248  // ------------------------------------------------------------------------
252  {
253  for (unsigned i = 0; i < m_sampler_ids.size(); i++)
254  glDeleteSamplers(1, &m_sampler_ids[i]);
255  } // ~TextureShader
256 
257 }; // class TextureShader
258 
259 #endif
260 
261 #endif // SHADER_ONLY
void use()
Activates the shader calling glUseProgram.
Definition: shader.hpp:103
The main templated base class for all shaders that do not use textures.
Definition: shader.hpp:119
A simple non-templated base class for a shader that uses textures.
Definition: texture_shader.hpp:63
Class C needs to be the newly declared shaders class (necessary for the instance template).
Definition: texture_shader.hpp:107
void assignSamplerNames(Args...args)
The protected interface for setting sampler names - it is only called from instances.
Definition: texture_shader.hpp:161
void setTextureHandlesImpl()
End of recursion, just checks at compile time if number of arguments is correct.
Definition: texture_shader.hpp:215
void setTextureHandles(HandlesId... ids)
The protected interface.
Definition: texture_shader.hpp:242
void setTextureHandlesImpl(uint64_t handle, HandlesId... args)
Recursive implementation of setTextureHandles.
Definition: texture_shader.hpp:227
void setTextureUnitsImpl(GLuint tex_id, TexIds... args)
The recursive implementation.
Definition: texture_shader.hpp:182
void assignTextureNamesImpl(GLuint tex_unit, const char *name, SamplerTypeNew sampler_type, Args...args)
Recursive implementation, peeling the texture unit and name off the list of arguments.
Definition: texture_shader.hpp:134
void setTextureUnitsImpl()
End of recursion, just check if number of arguments is correct.
Definition: texture_shader.hpp:173
void setTextureUnits(TexIds... args)
Public implementation of setTextureUnits.
Definition: texture_shader.hpp:202
~TextureShader()
Destructor which frees al lsampler ids.
Definition: texture_shader.hpp:251
void assignTextureNamesImpl()
End of recursive variadic template AssigTextureNames.
Definition: texture_shader.hpp:124