Allolib  1.0
C++ Components For Interactive Multimedia
al_DefaultShaders.hpp
1 #ifndef INCLUDE_AL_GRAPHICS_DEFAULT_SHADERS_HPP
2 #define INCLUDE_AL_GRAPHICS_DEFAULT_SHADERS_HPP
3 
4 /* Keehong Youn, 2017, younkeehong@gmail.com
5  */
6 
7 /*
8 
9  Uniforms and Attributes in Vertex shader
10 
11  uniform mat4 al_ModelViewMatrix;
12  uniform mat4 al_ProjectionMatrix;
13  uniform mat4 al_NormalMatrix;
14 
15  layout (location = 0) in vec3 position;
16  layout (location = 1) in vec4 color;
17  layout (location = 2) in vec2 texcoord;
18  layout (location = 3) in vec3 normal;
19 
20  uniform float eye_sep;
21  uniform float foc_len;
22 
23  uniform vec4 light0_eye;
24  uniform vec4 light1_eye;
25  ...
26 
27  Uniforms in Fragment Shader
28 
29  uniform sampler2D tex0;
30  uniform vec4 col0;
31  uniform vec4 tint;
32  uniform vec4 light_global_ambient;
33 
34  uniform vec4 light0_ambient;
35  uniform vec4 light0_diffuse;
36  uniform vec4 light0_specular;
37  uniform float light0_enabled;
38  ...
39 
40  uniform vec4 material_ambient;
41  uniform vec4 material_diffuse;
42  uniform vec4 material_specular;
43  uniform float material_shininess;
44 
45 */
46 
47 #include <string>
48 #include <vector>
49 
50 #include "al/graphics/al_Shader.hpp"
51 
52 inline constexpr int al_max_num_lights() { return 8; }
53 
55  int ambient = -1;
56  int diffuse = -1;
57  int specular = -1;
58  int position = -1;
59  int enabled = -1;
60  int atten = -1;
61 };
62 
64  int ambient = -1;
65  int diffuse = -1;
66  int specular = -1;
67  int shininess = -1;
68  int emission = -1;
69 };
70 
72  int global_ambient = -1;
73  int normal_matrix = -1;
74  int num_lights = 0;
76  std::vector<per_light_uniform_locations> lights;
77  bool has_material = false;
78 };
79 
80 void al_print_lighting_uniforms(lighting_shader_uniforms const& u,
81  std::string name = "shader");
82 
83 lighting_shader_uniforms al_get_lighting_uniform_locations(
84  al::ShaderProgram& s, bool print_result = false);
85 
86 inline std::string al_default_shader_version_string() {
87  return R"(#version 330
88 )";
89 }
90 
91 inline std::string al_default_vert_shader_stereo_functions(bool is_omni) {
92  if (!is_omni)
93  return R"(
94 vec4 stereo_displace(vec4 v, float e, float f) {
95  // eye to vertex distance
96  float l = sqrt((v.x - e) * (v.x - e) + v.y * v.y + v.z * v.z);
97  // absolute z-direction distance
98  float z = abs(v.z);
99  // x coord of projection of vertex on focal plane when looked from eye
100  float t = f * (v.x - e) / z;
101  // x coord of displaced vertex to make displaced vertex be projected on focal plane
102  // when looked from origin at the same point original vertex would be projected
103  // when looked form eye
104  v.x = z * (e + t) / f;
105  // set distance fromr origin to displaced vertex same as eye to original vertex
106  v.xyz = normalize(v.xyz);
107  v.xyz *= l;
108  return v;
109 })";
110  else
111  return R"(
112 vec4 stereo_displace(vec4 v, float e, float r) {
113  vec3 OE = vec3(-v.z, 0.0, v.x); // eye direction, orthogonal to vertex vector
114  OE = normalize(OE); // but preserving +y up-vector
115  OE *= e; // set mag to eye separation
116  vec3 EV = v.xyz - OE; // eye to vertex
117  float ev = length(EV); // save length
118  EV /= ev; // normalize
119 
120  // coefs for polynomial t^2 + 2bt + c = 0
121  // derived from cosine law r^2 = t^2 + e^2 + 2tecos(theta)
122  // where theta is angle between OE and EV
123  // t is distance to sphere surface from eye
124  float b = -dot(OE, EV); // multiply -1 to dot product because
125  // OE needs to be flipped in direction
126  float c = e * e - r * r;
127  float t = -b + sqrt(b * b - c); // quadratic formula
128 
129  v.xyz = OE + t * EV; // direction from origin to sphere surface
130  v.xyz = ev * normalize(v.xyz); // normalize and set mag to eye-to-v distance
131  return v;
132 })";
133 }
134 
135 // ---------------------------------------------------------
136 
137 inline std::string al_mesh_vert_shader(bool is_omni = false) {
138  using namespace std::string_literals;
139  return al_default_shader_version_string() +
140  al_default_vert_shader_stereo_functions(is_omni) + R"(
141 uniform mat4 al_ModelViewMatrix;
142 uniform mat4 al_ProjectionMatrix;
143 layout (location = 0) in vec3 position;
144 layout (location = 1) in vec4 color;
145 uniform float eye_sep;
146 uniform float foc_len;
147 out vec4 color_;
148 void main() {
149  if (eye_sep == 0) {
150  gl_Position = al_ProjectionMatrix * al_ModelViewMatrix * vec4(position, 1.0);
151  }
152  else {
153  gl_Position = al_ProjectionMatrix * stereo_displace(al_ModelViewMatrix * vec4(position, 1.0), eye_sep, foc_len);
154  }
155  color_ = color;
156 }
157 )"s;
158 }
159 
160 inline std::string al_mesh_frag_shader() {
161  return R"(
162 #version 330
163 uniform vec4 tint;
164 in vec4 color_;
165 out vec4 frag_color;
166 void main() {
167  frag_color = color_ * tint;
168 }
169 )";
170 }
171 
172 // ---------------------------------------------------------
173 
174 inline std::string al_tex_vert_shader(bool is_omni = false) {
175  using namespace std::string_literals;
176  return al_default_shader_version_string() +
177  al_default_vert_shader_stereo_functions(is_omni) + R"(
178 uniform mat4 al_ModelViewMatrix;
179 uniform mat4 al_ProjectionMatrix;
180 layout (location = 0) in vec3 position;
181 layout (location = 2) in vec2 texcoord;
182 uniform float eye_sep;
183 uniform float foc_len;
184 out vec2 texcoord_;
185 void main() {
186  if (eye_sep == 0) {
187  gl_Position = al_ProjectionMatrix * al_ModelViewMatrix * vec4(position, 1.0);
188  }
189  else {
190  gl_Position = al_ProjectionMatrix * stereo_displace(al_ModelViewMatrix * vec4(position, 1.0), eye_sep, foc_len);
191  }
192  texcoord_ = texcoord;
193 }
194 )";
195 }
196 
197 inline std::string al_tex_frag_shader() {
198  return R"(
199 #version 330
200 uniform sampler2D tex0;
201 uniform vec4 tint;
202 in vec2 texcoord_;
203 out vec4 frag_color;
204 void main() {
205  frag_color = texture(tex0, texcoord_) * tint;
206 }
207 )";
208 }
209 
210 // ---------------------------------------------------------
211 
212 inline std::string al_color_vert_shader(bool is_omni = false) {
213  using namespace std::string_literals;
214  return al_default_shader_version_string() +
215  al_default_vert_shader_stereo_functions(is_omni) + R"(
216 uniform mat4 al_ModelViewMatrix;
217 uniform mat4 al_ProjectionMatrix;
218 layout (location = 0) in vec3 position;
219 uniform float eye_sep;
220 uniform float foc_len;
221 void main() {
222  if (eye_sep == 0) {
223  gl_Position = al_ProjectionMatrix * al_ModelViewMatrix * vec4(position, 1.0);
224  }
225  else {
226  gl_Position = al_ProjectionMatrix * stereo_displace(al_ModelViewMatrix * vec4(position, 1.0), eye_sep, foc_len);
227  }
228 }
229 )";
230 }
231 
232 inline std::string al_color_frag_shader() {
233  return R"(
234 #version 330
235 uniform vec4 col0;
236 uniform vec4 tint;
237 out vec4 frag_color;
238 void main() {
239  frag_color = col0 * tint;
240 }
241 )";
242 }
243 
244 // --------------------------------------------------------
245 
246 namespace al {
247 
248 enum class ShaderType : unsigned char {
249  COLOR, // uniform color
250  MESH, // per vertex mesh color
251  TEXTURE, // sample texture from texture coordinate per vertex
252  LIGHTING_COLOR, // ShaderType::COLOR with lighting
253  LIGHTING_MESH, // ShaderType::MESH with lighting
254  LIGHTING_TEXTURE, // ShaderType::TEXTURE with lighting
255  LIGHTING_MATERIAL // Use material for coloring with lighting
256 };
257 
258 // compile shader program as with given config
259 void compileDefaultShader(ShaderProgram& s, ShaderType type,
260  bool is_omni = false);
261 
262 // return vertex shader string for specified configuration
263 std::string multilight_vert_shader(ShaderType type, int num_lights,
264  bool is_omni = false);
265 
266 // return fragment shader string for specified configuration
267 std::string multilight_frag_shader(ShaderType type, int num_lights);
268 
269 // compile shader program as with given config with lighting
270 // TODO - `al::compileDefaultShader`
271 // overlaps functionality with this one
272 void compileMultiLightShader(ShaderProgram& s, ShaderType type, int num_lights,
273  bool is_omni = false);
274 
275 } // namespace al
276 
277 #endif
Shader program object.
Definition: al_Shader.hpp:116
Definition: al_App.hpp:23