OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
app.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2014-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include <GLES3/gl3.h>
22 #include "app.h"
23 #include "glutil.h"
24 #include "timer.h"
25 #include "shader.h"
26 #include "common.h"
27 #include "primitives.h"
28 #include "meshloader.h"
29 #include <fstream>
30 
31 #ifndef GL_EXT_shader_pixel_local_storage
32 #define GL_EXT_shader_pixel_local_storage 1
33 #define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63
34 #define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT 0x8F67
35 #define GL_SHADER_PIXEL_LOCAL_STORAGE_EXT 0x8F64
36 #endif
37 
38 int
41 
42 Shader
48 
49 mat4
51  mat_view;
52 
54 
55 const int num_lights = 2;
57  vec3(0.0), vec3(0.0)
58 };
59 
61  vec3(0.2, 0.8, 0.9),
62  vec3(1.0, 0.4, 0.2)
63 };
64 
66  0.6f, 0.9f
67 };
68 
70  0.1f, 0.14f
71 };
72 
73 static float model_scale = 0.01f;
74 
75 // Subsurface scattering parameters
76 static float s_ambient = 0.20f; // The minimum amount of light that is transmitted
77 static float s_distortion = 0.07f; // Distorts the light direction vector
78 static float s_sharpness = 10.0f; // Produces more focused or diffused transmittance
79 static float s_scale = 3.50f; // Brightness scaling factor
80 
81 // Camera parameters
82 static float zoom = 3.0f;
83 static float rot_x = -0.5f;
84 static float rot_y = 0.0f;
85 static float delta_x = 0.0f;
86 static float delta_y = 0.0f;
87 
88 // Perspective projection parameters
89 static float z_near = 0.1f;
90 static float z_far = 15.0f;
91 static float fov_y = PI / 4.0f;
92 static float aspect_ratio = 1.0f;
93 
94 bool init_app(int width, int height)
95 {
98  aspect_ratio = float(width) / height;
99 
100  // Check if we have support for pixel local storage
101  std::string ext = std::string((const char*)glGetString(GL_EXTENSIONS));
102  ASSERT(ext.find("GL_EXT_shader_pixel_local_storage") != std::string::npos, "This device does not support shader pixel local storage");
103 
104  string res = "/data/data/com.arm.malideveloper.openglessdk.translucency/files/";
105  if (!shader_prepass.load_from_file(res + "prepass.vs", res + "prepass.fs") ||
106  !shader_thickness.load_from_file(res + "thickness.vs", res + "thickness.fs") ||
107  !shader_resolve.load_from_file(res + "resolve.vs", res + "resolve.fs") ||
108  !shader_scattering.load_from_file(res + "scattering.vs", res + "scattering.fs") ||
109  !shader_opaque.load_from_file(res + "opaque.vs", res + "opaque.fs"))
110  return false;
111 
112  if (!shader_prepass.link() ||
113  !shader_thickness.link() ||
114  !shader_resolve.link() ||
115  !shader_scattering.link() ||
116  !shader_opaque.link())
117  return false;
118 
119  sphere = gen_normal_sphere(24, 24);
120  quad = gen_quad();
121  cube = gen_normal_cube();
122 
123  if (!load_mesh_binary(teapot, res + "teapot.bin"))
124  return false;
125 
127 
128  return true;
129 }
130 
131 void free_app()
132 {
138 }
139 
140 void update_app(float dt)
141 {
142  rot_y += 0.01f * delta_x * dt;
143  rot_x += 0.01f * delta_y * dt;
144  mat_view =
145  translate(0.0f, -0.2f, -zoom) *
146  rotateX(rot_x) *
147  rotateY(rot_y);
148 
149  float alpha = 0.5 + 0.5 * sin(get_elapsed_time() * 0.4);
150  light_pos[0] = vec3(-1.0 + 2.0 * alpha, 0.0, 0.0);
151  light_pos[1] = vec3(0.8 - 2.0 * alpha, 0.0, 0.0);
152 
153  float t = get_elapsed_time();
154  light_intensity[0] = smoothstep(0.5f, 1.0f, t);
155  light_intensity[1] = smoothstep(1.5f, 2.0f, t);
156 }
157 void render_teapot(mat4 model, bool normal = true)
158 {
159  teapot.bind();
160  uniform("model", model);
161  attribfv("position", 3, 8, 0);
162  if (normal) attribfv("normal", 3, 8, 5);
163  glDrawElements(GL_TRIANGLES, teapot.num_indices, GL_UNSIGNED_INT, 0);
164 }
165 
166 void render_sphere(mat4 model, bool normal = true)
167 {
168  sphere.bind();
169  uniform("model", model);
170  attribfv("position", 3, 6, 0);
171  if (normal) attribfv("normal", 3, 6, 3);
172  glDrawElements(GL_TRIANGLES, sphere.num_indices, GL_UNSIGNED_INT, 0);
173 }
174 
175 void render_cube(mat4 model, bool normal = true)
176 {
177  cube.bind();
178  uniform("model", model);
179  attribfv("position", 3, 6, 0);
180  if (normal) attribfv("normal", 3, 6, 3);
181  glDrawElements(GL_TRIANGLES, cube.num_indices, GL_UNSIGNED_INT, 0);
182 }
183 
184 void render_pass_thickness(bool second_pass)
185 {
186  uniform("projection", mat_projection);
187  uniform("view", mat_view);
188 
189  GLenum cmp = second_pass ? GL_EQUAL : GL_ALWAYS;
190  bool use_albedo = !second_pass;
191  bool use_normal = !second_pass;
192 
193  if (use_albedo) uniform("albedo", vec3(0.7f, 0.8f, 0.9f));
194  glStencilFunc(cmp, 1, 0xFF);
195  render_teapot(translate(0.5f, -0.07f, -0.9f) * scale(0.05f) * rotateY(-0.3f), use_normal);
196 
197  if (use_albedo) uniform("albedo", vec3(0.2f, 0.5f, 0.3f));
198  glStencilFunc(cmp, 2, 0xFF);
199  render_cube(translate(-0.3f, -0.05f, 0.1f) * scale(0.4f), use_normal);
200 
201  if (use_albedo) uniform("albedo", vec3(0.7f, 0.4f, 0.2f));
202  glStencilFunc(cmp, 3, 0xFF);
203  render_cube(translate(0.9f, -0.1f, -0.1f) * scale(0.35f) * rotateY(-0.3f), use_normal);
204 
205  for (int i = 0; i < num_lights; i++)
206  {
207  if (use_albedo) uniform("albedo", light_color[i]);
208  glStencilFunc(cmp, i + 4, 0xFF);
209  render_sphere(translate(light_pos[i]) * scale(light_radius[i]), use_normal);
210  }
211 }
212 
214 {
215  // Shade translucent objects with sss algorithm
217  uniform("zNear", z_near);
218  uniform("zFar", z_far);
219  uniform("top", z_near * tan(fov_y / 2.0f));
220  uniform("right", aspect_ratio * z_near * tan(fov_y / 2.0f));
221  uniform("invResolution", vec2(1.0f / window_width, 1.0f / window_height));
222  uniform("ambient", s_ambient);
223  uniform("distortion", s_distortion);
224  uniform("sharpness", s_sharpness);
225  uniform("scale", s_scale);
226 
227  // One fullscreen pass per light
228  quad.bind();
229  attribfv("position", 3, 3, 0);
230  for (int i = 0; i < num_lights; i++)
231  {
232  uniform("lightPos",(mat_view * vec4(light_pos[i], 1.0f)).xyz());
233  uniform("lightColor", light_color[i]);
234  uniform("lightIntensity", light_intensity[i]);
235  uniform("lightRadius", light_radius[i]);
236  glDrawElements(GL_TRIANGLES, quad.num_indices, GL_UNSIGNED_INT, 0);
237  }
238 }
239 
241 {
243  uniform("projection", mat_projection);
244  uniform("view", mat_view);
245  uniform("lightPos0", light_pos[0]);
246  uniform("lightPos1", light_pos[1]);
247  uniform("lightCol0", light_color[0]);
248  uniform("lightCol1", light_color[1]);
249  uniform("lightInt0", light_intensity[0]);
250  uniform("lightInt1", light_intensity[1]);
251  render_cube(translate(0.0f, -0.5f, 0.0f) * scale(10.0f, 0.05f, 10.0f));
252 }
253 
255 {
257  quad.bind();
258  attribfv("position", 3, 3, 0);
259  glDrawElements(GL_TRIANGLES, quad.num_indices, GL_UNSIGNED_INT, 0);
260 }
261 
262 void render_app(float dt)
263 {
264  // Clearing all buffers at the beginning can lead to better performance
265  glEnable(GL_DEPTH_TEST);
266  glEnable(GL_STENCIL_TEST);
268  glDepthMask(GL_TRUE);
269  glStencilMask(0xFF);
270  glClearDepthf(1.0f);
271  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
272  glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
273 
274  // Render opaque geometry and do forward lighting on it.
275  // We write the ID of 0 to the stencil buffer, to seperate
276  // regular geometry from translucent geometry later.
277  glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
278  glStencilFunc(GL_ALWAYS, 0, 0xFF);
279  depth_write(true);
280  depth_test(true, GL_LEQUAL);
281  cull(true);
283 
284  // In this pass we render the _closest_ object's material properties
285  // to the local storage, and its ID to the stencil buffer. The ID will
286  // be used for the following pass, where we compute the thickness.
287  cull(false);
289  render_pass_thickness(false);
290 
291  // In this pass we render the same objects again, but we demand that
292  // the object being rendered has the same ID as that in the stencil
293  // buffer - that is, it is in fact the closest object for that pixel.
294  depth_write(false);
295  depth_test(false);
297  render_pass_thickness(true);
298 
299  // Apply subsurface scattering and front-lighting to geometry
300  // Translucent objects have an ID that is >= 1. We only want to
301  // shade these, so we stencil _out_ fragments with an ID = 0.
302  glStencilFunc(GL_LEQUAL, 1, 0xFF);
303  glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
305 
306  // Write back lighting for _all_ the pixels!
307  glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
308  glStencilFunc(GL_ALWAYS, 0, 0xFF);
310  glDisable(GL_STENCIL_TEST);
312 
313  // These are no longer needed, so we don't bother writing back to framebuffer.
314  GLenum to_invalidate[] = { GL_DEPTH, GL_STENCIL };
315  glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, to_invalidate);
316 }
317 
318 static bool dragging = false;
319 static float last_x = 0.0f;
320 static float last_y = 0.0f;
321 void on_pointer_down(float x, float y)
322 {
323  if (!dragging)
324  {
325  dragging = true;
326  last_x = x;
327  last_y = y;
328  }
329  else
330  {
331  delta_x = x - last_x;
332  delta_y = y - last_y;
333  }
334 }
335 
336 void on_pointer_up(float x, float y)
337 {
338  dragging = false;
339  delta_x = 0.0f;
340  delta_y = 0.0f;
341 }
static float s_distortion
Definition: app.cpp:77
static float last_y
Definition: app.cpp:320
void on_pointer_down(float x, float y)
Definition: app.cpp:376
static float fov_y
Definition: app.cpp:91
Shader shader_thickness
Definition: app.cpp:43
#define attribfv(prog, name, n, offset)
Definition: geometry.h:118
static float z_far
Definition: app.cpp:90
bool dragging
Definition: app.cpp:70
void render_pass_opaque()
Definition: app.cpp:240
Definition: matrix.h:51
Shader shader_resolve
Definition: app.cpp:43
GLint GLsizei GLsizei height
Definition: gl2ext.h:179
static float rot_x
Definition: app.cpp:83
Definition: matrix.h:28
bool load_from_file(const string *paths, GLenum *types, int count)
Definition: shader.cpp:93
void render_cube(mat4 model, bool normal=true)
Definition: app.cpp:175
float light_intensity[num_lights]
Definition: app.cpp:65
static float s_scale
Definition: app.cpp:79
mat4 mat_view
Definition: app.cpp:45
static float model_scale
Definition: app.cpp:73
static float last_x
Definition: app.cpp:319
#define GL_SHADER_PIXEL_LOCAL_STORAGE_EXT
Definition: app.cpp:35
void render_sphere(mat4 model, bool normal=true)
Definition: app.cpp:166
static mat4 rotateY(float rad)
Definition: matrix.h:320
Definition: matrix.h:75
#define PI
Definition: matrix.h:24
Mesh gen_normal_sphere(int t_samples, int s_samples)
Definition: primitives.cpp:127
void bind()
Definition: primitives.cpp:122
mat4 mat_projection
Definition: app.cpp:45
Mesh gen_quad()
Definition: primitives.cpp:105
bool load_mesh_binary(Mesh &mesh, string path)
Definition: meshloader.cpp:37
static float zoom
Definition: app.cpp:82
Shader shader_scattering
Definition: app.cpp:43
Shader shader_opaque
Definition: app.cpp:43
int num_indices
Definition: primitives.h:30
vec3 light_color
Definition: app.cpp:56
void on_pointer_up(float x, float y)
Definition: app.cpp:412
void dispose()
Definition: shader.cpp:129
bool link()
Definition: shader.cpp:124
Mesh quad
Definition: app.cpp:40
Matrix perspective
Definition: EGLPreserve.cpp:81
static float delta_x
Definition: app.cpp:85
static float s_sharpness
Definition: app.cpp:78
GLfloat GLfloat f
Definition: gl2ext.h:2707
Shader shader_prepass
Definition: app.cpp:43
void render_pass_thickness(bool second_pass)
Definition: app.cpp:184
static float rot_y
Definition: app.cpp:84
static mat4 rotateX(float rad)
Definition: matrix.h:312
void render_pass_shading()
Definition: app.cpp:213
Matrix scale
Definition: RotoZoom.cpp:64
static float z_near
Definition: app.cpp:89
void init_app(int width, int height)
Definition: app.cpp:176
static float s_ambient
Definition: app.cpp:76
void cull(bool enabled, GLenum front, GLenum mode)
Definition: glutil.cpp:27
Mesh sphere
Definition: app.cpp:40
Definition: shader.h:27
int window_height
Definition: app.cpp:80
void uniform(string name, const mat4 &v)
Definition: glutil.cpp:97
int window_width
Definition: app.cpp:80
Mesh gen_normal_cube()
Definition: primitives.cpp:23
static float delta_y
Definition: app.cpp:86
const int num_lights
Definition: app.cpp:55
GLint GLint GLint GLint GLint x
Definition: gl2ext.h:574
void render_pass_resolve()
Definition: app.cpp:254
static float smoothstep(float edge0, float edge1, float t)
Definition: matrix.h:154
Definition: matrix.h:104
vec3 light_pos
Definition: app.cpp:56
void use_shader(Shader shader)
Definition: glutil.cpp:81
#define ASSERT(x, s)
Definition: common.h:45
precision highp float
Definition: hiz_cull.cs:37
void render_teapot(mat4 model, bool normal=true)
Definition: app.cpp:157
GLint GLsizei width
Definition: gl2ext.h:179
static float aspect_ratio
Definition: app.cpp:92
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
void free_app()
Definition: app.cpp:113
uniform float dt
Definition: update.cs:29
void depth_write(bool enabled)
Definition: glutil.cpp:54
double get_elapsed_time()
Definition: timer.cpp:33
float light_radius[num_lights]
Definition: app.cpp:69
GLint y
Definition: gl2ext.h:179
static mat4 translate(float x, float y, float z)
Definition: matrix.h:336
void depth_test(bool enabled, GLenum func)
Definition: glutil.cpp:41
void render_app(float dt)
Definition: app.cpp:358
void update_app(float dt)
Definition: app.cpp:283
Mesh teapot
Definition: app.cpp:53
Mesh cube
Definition: app.cpp:53