OpenCPN Partial API docs
shaders.cpp
1 /***************************************************************************
2  *
3  * Project: OpenCPN
4  *
5  ***************************************************************************
6  * Copyright (C) 2017 by David S. Register *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the *
20  * Free Software Foundation, Inc., *
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
22  **************************************************************************/
23 
24 #include "shaders.h"
25 
26 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
27 
28 #ifdef USE_ANDROID_GLES2
29 #include <GLES2/gl2.h>
30 #include "qdebug.h"
31 #endif
32 
33 #ifdef USE_ANDROID_GLES2
34 const GLchar* preamble =
35 "\n";
36 #else
37 const GLchar* preamble =
38 "#version 120\n"
39 "#define precision\n"
40 "#define lowp\n"
41 "#define mediump\n"
42 "#define highp\n";
43 #endif
44 
45 
46 // Simple colored triangle shader
47 
48 static const GLchar* color_tri_vertex_shader_source =
49  "attribute vec2 position;\n"
50  "uniform mat4 MVMatrix;\n"
51  "uniform mat4 TransformMatrix;\n"
52  "uniform vec4 color;\n"
53  "varying vec4 fragColor;\n"
54  "void main() {\n"
55  " fragColor = color;\n"
56  " gl_Position = MVMatrix * TransformMatrix * vec4(position, 0.0, 1.0);\n"
57  "}\n";
58 
59 static const GLchar* color_tri_fragment_shader_source =
60  "precision lowp float;\n"
61  "varying vec4 fragColor;\n"
62  "void main() {\n"
63  " gl_FragColor = fragColor;\n"
64  "}\n";
65 
66 // Simple 2D texture shader
67 static const GLchar* texture_2D_vertex_shader_source =
68  "attribute vec2 aPos;\n"
69  "attribute vec2 aUV;\n"
70  "uniform mat4 MVMatrix;\n"
71  "uniform mat4 TransformMatrix;\n"
72  "varying vec2 varCoord;\n"
73  "void main() {\n"
74  " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
75  " varCoord = aUV;\n"
76  "}\n";
77 
78 static const GLchar* texture_2D_fragment_shader_source =
79  "precision lowp float;\n"
80  "uniform sampler2D uTex;\n"
81  "varying vec2 varCoord;\n"
82  "void main() {\n"
83  " gl_FragColor = texture2D(uTex, varCoord);\n"
84  "}\n";
85 
86 // Circle shader
87 
88 static const GLchar* circle_filled_vertex_shader_source =
89  "precision highp float;\n"
90  "attribute vec2 aPos;\n"
91  "uniform mat4 MVMatrix;\n"
92  "uniform mat4 TransformMatrix;\n"
93  "void main() {\n"
94  " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
95  "}\n";
96 
97 static const GLchar* circle_filled_fragment_shader_source =
98  "precision highp float;\n"
99  "uniform float border_width;\n"
100  "uniform float circle_radius;\n"
101  "uniform vec4 circle_color;\n"
102  "uniform vec4 border_color;\n"
103  "uniform vec2 circle_center;\n"
104  "void main(){\n"
105  "float d = distance(gl_FragCoord.xy, circle_center);\n"
106  "if (d < (circle_radius - border_width)) { gl_FragColor = circle_color; }\n"
107  "else if (d < circle_radius) { gl_FragColor = border_color; }\n"
108  "else { gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); }\n"
109  "}\n";
110 
111 // Alpha 2D texture shader
112 static const GLchar* texture_2DA_vertex_shader_source =
113  "attribute vec2 aPos;\n"
114  "attribute vec2 aUV;\n"
115  "uniform mat4 MVMatrix;\n"
116  "uniform mat4 TransformMatrix;\n"
117  "varying vec2 varCoord;\n"
118  "void main() {\n"
119  " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
120  " varCoord = aUV;\n"
121  "}\n";
122 
123 static const GLchar* texture_2DA_fragment_shader_source =
124  "precision lowp float;\n"
125  "uniform sampler2D uTex;\n"
126  "varying vec2 varCoord;\n"
127  "uniform vec4 color;\n"
128  "void main() {\n"
129  " gl_FragColor = texture2D(uTex, varCoord) + color;\n"
130  "}\n";
131 
132 
133 //https://vitaliburkov.wordpress.com/2016/09/17/simple-and-fast-high-quality-antialiased-lines-with-opengl/
134 static const GLchar* AALine_vertex_shader_source =
135  "uniform vec2 uViewPort; //Width and Height of the viewport\n"
136  "varying vec2 vLineCenter;\n"
137  "attribute vec2 position;\n"
138  "uniform mat4 MVMatrix;\n"
139  "uniform mat4 TransformMatrix;\n"
140  "void main()\n"
141  "{\n"
142  " vec4 pp = MVMatrix * vec4(position, 0.0, 1.0);\n"
143  " gl_Position = pp;\n"
144  " vec2 vp = uViewPort;\n"
145  " vLineCenter = 0.5*(pp.xy + vec2(1, 1))*vp;\n"
146  "}\n";
147 
148 
149 static const GLchar* AALine_fragment_shader_source =
150  "precision mediump float;\n"
151  "uniform float uLineWidth;\n"
152  "uniform vec4 color;\n"
153  "uniform float uBlendFactor; //1.5..2.5\n"
154  "varying vec2 vLineCenter;\n"
155  "void main()\n"
156  "{\n"
157  " vec4 col = color;\n"
158  " float d = length(vLineCenter-gl_FragCoord.xy);\n"
159  " float w = uLineWidth;\n"
160  " if (d>w)\n"
161  " col.w = 0.0;\n"
162  " else{\n"
163  " if(float((w/2.0-d)/(w/2.0)) < .5){\n"
164  " //col.w *= pow(float((w-d)/w), uBlendFactor);\n"
165  " col.w *= pow(float((w/2.0-d)/(w/2.0)), uBlendFactor);\n"
166  " }\n"
167  " }\n"
168  " gl_FragColor = col;\n"
169  "}\n";
170 
171 // Ring shader
172 
173 static const GLchar *ring_vertex_shader_source =
174  "precision highp float;\n"
175  "attribute vec2 aPos;\n"
176  "uniform mat4 MVMatrix;\n"
177  "uniform mat4 TransformMatrix;\n"
178  "void main() {\n"
179  " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
180  "}\n";
181 
182 static const GLchar *ring_fragment_shader_source =
183  "precision highp float;\n"
184  "uniform float border_width;\n"
185  "uniform float circle_radius;\n"
186  "uniform float ring_width;\n"
187  "uniform vec4 circle_color;\n"
188  "uniform vec4 border_color;\n"
189  "uniform vec2 circle_center;\n"
190  "uniform float sector_1;\n"
191  "uniform float sector_2;\n"
192 
193  "void main(){\n"
194  "const float PI = 3.14159265358979323846264;\n"
195  "bool bdraw = false;\n"
196 
197  "float angle = atan(gl_FragCoord.y-circle_center.y, "
198  "gl_FragCoord.x-circle_center.x);\n"
199  "angle = PI/2.0 - angle;\n"
200  "if(angle < 0.0) angle += PI * 2.0;\n"
201 
202  "if(sector_2 > PI * 2.0){\n"
203  " if((angle > sector_1) && (angle < (PI * 2.0) )){\n"
204  " bdraw = true;\n"
205  " }\n"
206  " if(angle < sector_2 - (PI * 2.0)){\n"
207  " bdraw = true;\n"
208  " }\n"
209  "} else {\n"
210  " if((angle > sector_1) && (angle < sector_2)){\n"
211  " bdraw = true;\n"
212  " }\n"
213  "}\n"
214 
215  "if(bdraw){\n"
216  " float d = distance(gl_FragCoord.xy, circle_center);\n"
217  " if (d > circle_radius) {\n"
218  " discard;\n"
219  " } else if( d > (circle_radius - border_width)) {\n"
220  " gl_FragColor = border_color;\n"
221  " } else if( d > (circle_radius - border_width - ring_width)) {\n"
222  " gl_FragColor = circle_color;\n"
223  " } else if( d > (circle_radius - border_width - ring_width - "
224  "border_width)) {\n"
225  " gl_FragColor = border_color;\n"
226  " } else {\n"
227  " discard;\n"
228  " }\n"
229  "} else{\n"
230  " discard;\n"
231  "}\n"
232  "}\n";
233 
234  // Alpha 2D texture shader
235 static const GLchar* Android_texture_2DA_vertex_shader_source =
236  "attribute vec2 aPos;\n"
237  "attribute vec2 aUV;\n"
238  "uniform mat4 MVMatrix;\n"
239  "uniform mat4 TransformMatrix;\n"
240  "varying vec2 varCoord;\n"
241  "void main() {\n"
242  " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
243  " varCoord = aUV;\n"
244  "}\n";
245 
246 static const GLchar* Android_texture_2DA_fragment_shader_source =
247  "precision lowp float;\n"
248  "uniform sampler2D uTex;\n"
249  "varying vec2 varCoord;\n"
250  "uniform vec4 color;\n"
251  "void main() {\n"
252  " gl_FragColor = texture2D(uTex, varCoord) + color;\n"
253  "}\n";
254 
255 GLShaderProgram *pAALine_shader_program[2];
256 GLShaderProgram *pcolor_tri_shader_program[2];
257 GLShaderProgram *ptexture_2D_shader_program[2];
258 GLShaderProgram *pcircle_filled_shader_program[2];
259 GLShaderProgram *ptexture_2DA_shader_program[2];
260 GLShaderProgram *pring_shader_program[2];
261 
262 GLint texture_2DA_vertex_shader_p;
263 GLint texture_2DA_fragment_shader_p;
264 GLint texture_2DA_shader_program;
265 
266 
267 bool bShadersLoaded[2];
268 
269 bool loadShaders(int index) {
270  // Are the shaders ready?
271  if (bShadersLoaded[index]) {
272  reConfigureShaders(index);
273  return true;
274  }
275 
276  bool ret_val = true;
277  GLint success;
278 
279 
280  // Simple colored triangle shader
281  if (!pcolor_tri_shader_program[index]) {
282  GLShaderProgram *shaderProgram = new GLShaderProgram;
283  shaderProgram->addShaderFromSource(color_tri_vertex_shader_source, GL_VERTEX_SHADER);
284  shaderProgram->addShaderFromSource(color_tri_fragment_shader_source, GL_FRAGMENT_SHADER);
285  shaderProgram->linkProgram();
286 
287  if (shaderProgram->isOK())
288  pcolor_tri_shader_program[index] = shaderProgram;
289  }
290 
291  if (!ptexture_2D_shader_program[index]) {
292  GLShaderProgram *shaderProgram = new GLShaderProgram;
293  shaderProgram->addShaderFromSource(texture_2D_vertex_shader_source, GL_VERTEX_SHADER);
294  shaderProgram->addShaderFromSource(texture_2D_fragment_shader_source, GL_FRAGMENT_SHADER);
295  shaderProgram->linkProgram();
296 
297  if (shaderProgram->isOK())
298  ptexture_2D_shader_program[index] = shaderProgram;
299  }
300 
301  if (!pcircle_filled_shader_program[index]) {
302  GLShaderProgram *shaderProgram = new GLShaderProgram;
303  shaderProgram->addShaderFromSource(circle_filled_vertex_shader_source, GL_VERTEX_SHADER);
304  shaderProgram->addShaderFromSource(circle_filled_fragment_shader_source, GL_FRAGMENT_SHADER);
305  shaderProgram->linkProgram();
306 
307  if (shaderProgram->isOK())
308  pcircle_filled_shader_program[index] = shaderProgram;
309  }
310 
311  if (!ptexture_2DA_shader_program[index]) {
312  GLShaderProgram *shaderProgram = new GLShaderProgram;
313  shaderProgram->addShaderFromSource(texture_2DA_vertex_shader_source, GL_VERTEX_SHADER);
314  shaderProgram->addShaderFromSource(texture_2DA_fragment_shader_source, GL_FRAGMENT_SHADER);
315  shaderProgram->linkProgram();
316 
317  if (shaderProgram->isOK())
318  ptexture_2DA_shader_program[index] = shaderProgram;
319  }
320 
321  if (!pAALine_shader_program[index]) {
322  GLShaderProgram *shaderProgram = new GLShaderProgram;
323  shaderProgram->addShaderFromSource(AALine_fragment_shader_source, GL_FRAGMENT_SHADER);
324  shaderProgram->addShaderFromSource(AALine_vertex_shader_source, GL_VERTEX_SHADER);
325  shaderProgram->linkProgram();
326 
327  if (shaderProgram->isOK())
328  pAALine_shader_program[index] = shaderProgram;
329  }
330 
331  // ring shader
332  if (!pring_shader_program[index]) {
333  GLShaderProgram *shaderProgram = new GLShaderProgram;
334  shaderProgram->addShaderFromSource(ring_fragment_shader_source, GL_FRAGMENT_SHADER);
335  shaderProgram->addShaderFromSource(ring_vertex_shader_source, GL_VERTEX_SHADER);
336  shaderProgram->linkProgram();
337 
338  if (shaderProgram->isOK())
339  pring_shader_program[index] = shaderProgram;
340  }
341 
342 #ifdef __ANDROID__
343  // 2DA shader called by some Android plugins
344  if (!texture_2DA_vertex_shader_p) {
345  /* Vertex shader */
346  texture_2DA_vertex_shader_p = glCreateShader(GL_VERTEX_SHADER);
347  glShaderSource(texture_2DA_vertex_shader_p, 1,
348  &Android_texture_2DA_vertex_shader_source, NULL);
349  glCompileShader(texture_2DA_vertex_shader_p);
350  glGetShaderiv(texture_2DA_vertex_shader_p, GL_COMPILE_STATUS,
351  &success);
352  if (!success) {
353  //glGetShaderInfoLog(texture_2DA_vertex_shader_p, INFOLOG_LEN, NULL,
354  // infoLog);
355  //printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);
356  ret_val = false;
357  }
358  }
359 
360  if (!texture_2DA_fragment_shader_p) {
361  /* Fragment shader */
362  texture_2DA_fragment_shader_p = glCreateShader(GL_FRAGMENT_SHADER);
363  glShaderSource(texture_2DA_fragment_shader_p, 1,
364  &Android_texture_2DA_fragment_shader_source, NULL);
365  glCompileShader(texture_2DA_fragment_shader_p);
366  glGetShaderiv(texture_2DA_fragment_shader_p, GL_COMPILE_STATUS,
367  &success);
368  if (!success) {
369  //glGetShaderInfoLog(texture_2DA_fragment_shader_p, INFOLOG_LEN,
370  // NULL, infoLog);
371  //printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s\n", infoLog);
372  ret_val = false;
373  }
374  }
375 
376  if (!texture_2DA_shader_program) {
377  /* Link shaders */
378  texture_2DA_shader_program = glCreateProgram();
379  glAttachShader(texture_2DA_shader_program,
380  texture_2DA_vertex_shader_p);
381  glAttachShader(texture_2DA_shader_program,
382  texture_2DA_fragment_shader_p);
383  glLinkProgram(texture_2DA_shader_program);
384  glGetProgramiv(texture_2DA_shader_program, GL_LINK_STATUS,
385  &success);
386  if (!success) {
387  //glGetProgramInfoLog(texture_2DA_shader_program, INFOLOG_LEN,
388  // NULL, infoLog);
389  //printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s\n", infoLog);
390  ret_val = false;
391  }
392  }
393 #endif
394 
395  bShadersLoaded[index] = true;
396  reConfigureShaders(index);
397 
398  return ret_val;
399 }
400 
401 void reConfigureShaders(int index) {
402 }
403 
404 void unloadShaders() {
405  bShadersLoaded[0] = bShadersLoaded[1] = false;
406 }
407 
408 GLShaderProgram *GetStaticTriShader() {
409  GLShaderProgram *shaderProgram = new GLShaderProgram;
410  shaderProgram->addShaderFromSource(color_tri_vertex_shader_source, GL_VERTEX_SHADER);
411  shaderProgram->addShaderFromSource(color_tri_fragment_shader_source, GL_FRAGMENT_SHADER);
412  shaderProgram->linkProgram();
413 
414  if (shaderProgram->isOK())
415  return shaderProgram;
416  else
417  return NULL;
418 }
419 
420 
421 #endif