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