Do WebGL fragment shaders support outerProduct? - matrix

When compiling this WebGL fragment shader in both Chrome 22 and Firefox 15:
precision mediump float;
uniform vec2 u_resolution;
uniform sampler2D u_tex;
void main() {
vec2 texCoord = gl_FragCoord.xy / u_resolution;
vec4 floatColor = texture2D(u_tex, texCoord);
mat3 outerMat = outerProduct(floatColor.rgb,floatColor.rgb);
gl_FragColor = vec4(outerMat[0], 1);
}
I'm getting this error:
ERROR: 0:8: 'outerProduct' : no matching overloaded function found
ERROR: 0:8: '=' : cannot convert from 'const mediump float' to '3X3 matrix of float'
The OpenGL ES 2.0 GLSL spec indicates that mat3 outerProduct(vec3,vec3) is supported, and the WebGL spec says that it accepts ES shaders, so I'm not sure what's going wrong. Is outerProduct not supported in WebGL fragment shaders, or am I doing something wrong?

There is no outerProduct function in OpenGL ES 2.0 GLSL. Where did you read that there was? (or am I missing it?)
Here's the spec
http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf

Try mat3 outerMat = outerProduct(vec3(floatColor.rgb),vec3(floatColor.rgb));
To expand, maybe giving it an explicit type is better than using .rgb.

it is now available with webGL2.
Check your system here: https://webglreport.com/?v=2

Related

CGAL 5.3: Example program to draw a triangulation doesn't work

I've installed the CGAL 5.3 and tried to build and run the example program from this page. That's what I did:
cd $HOME/CGAL-5.3/release/examples/Triangulation_2
cmake -DCMAKE_BUILD_TYPE=Release -DCGAL_DIR=../../lib/cmake/CGAL .
make draw_triangulation_2
./draw_triangulation_2
However, I've got a lot of error messages in the console window - mostly complaints about OpenGL shaders, please see below:
QOpenGLShader::compile(Vertex): 0:3(1): error: `in' qualifier in declaration of `vertex' only valid for function parameters in GLSL 1.10
0:4(1): error: `in' qualifier in declaration of `color' only valid for function parameters in GLSL 1.10
0:9(1): error: `out' qualifier in declaration of `fColor' only valid for function parameters in GLSL 1.10
*** Problematic Vertex shader source code ***
#define lowp
#define mediump
#define highp
#line 1
in highp vec4 vertex;
in highp vec3 color;
uniform highp mat4 mvp_matrix;
uniform highp float point_size;
out highp vec4 fColor;
void main(void)
{
gl_PointSize = point_size;
fColor = vec4(color, 1.0);
gl_Position = mvp_matrix * vertex;
}
***
Compiling vertex source FAILED
QOpenGLShader::link: error: linking with uncompiled/unspecialized shader
linking Program FAILED
QOpenGLShader::compile(Vertex): 0:3(1): error: `in' qualifier in declaration of `vertex' only valid for function parameters in GLSL 1.10
0:4(1): error: `in' qualifier in declaration of `normal' only valid for function parameters in GLSL 1.10
0:5(1): error: `in' qualifier in declaration of `color' only valid for function parameters in GLSL 1.10
0:11(1): error: `out' qualifier in declaration of `fP' only valid for function parameters in GLSL 1.10
0:12(1): error: `out' qualifier in declaration of `fN' only valid for function parameters in GLSL 1.10
0:13(1): error: `out' qualifier in declaration of `fColor' only valid for function parameters in GLSL 1.10
*** Problematic Vertex shader source code ***
#define lowp
#define mediump
#define highp
#line 1
in highp vec4 vertex;
in highp vec3 normal;
in highp vec3 color;
uniform highp mat4 mvp_matrix;
uniform highp mat4 mv_matrix;
uniform highp float point_size;
out highp vec4 fP;
out highp vec3 fN;
out highp vec4 fColor;
void main(void)
{
fP = mv_matrix * vertex;
highp mat3 mv_matrix_3;
mv_matrix_3[0] = mv_matrix[0].xyz;
mv_matrix_3[1] = mv_matrix[1].xyz;
mv_matrix_3[2] = mv_matrix[2].xyz;
fN = mv_matrix_3* normal;
fColor = vec4(color, 1.0);
gl_PointSize = point_size;
gl_Position = mvp_matrix * vertex;
}
***
Compiling vertex source FAILED
QOpenGLShader::link: error: linking with uncompiled/unspecialized shader
linking Program FAILED
QOpenGLShader::link: error: linking with uncompiled/unspecialized shader
QOpenGLShaderProgram::attributeLocation(vertex): shader program is not linked
and so on... The viewer window, however, appeared but was empty:
The exactly same sequence of actions with CGAL 5.2.3 has given me a correct window with the triangulation and no error messages - so the OpenGL and Qt5 installations on my box look correct. The transition from the CGAL 5.2.3 to the CGAL 5.3 might be a culprit (???).
How to overcome this?
(I'm on Ubuntu 20.04.3 LTS, with standard kernel 5.11.0-27, and all the standard versions of OpenGL and Qt5)
UPDATE. I've opened an issue on the CGAL bug tracker.
I'm answering my own question. According to CGAL developers it's a bug in the Qt5-based visualization code, and there is no way to overcome it directly. The bug has been already fixed in the code repository, so the fix will be included in the next CGAL release.

OpenGL ES 3.2 doesn't recognize gl_in in geometry shader

I have the following shader code:
#version 320 es
layout(points) in;
layout(points, max_vertices=1) out;
uniform mat4 transform;
void main() {
gl_Position = gl_in[0].gl_Position * transform;
EmitVertex();
EndPrimitive();
}
But when creating the shader program I get the following error:
'gl_in' : undeclared identifier
'gl_in' : left of '[' is not of type array, matrix, or vector
'gl_Position' : field selection requires structure, vector, or matrix on left hand side
'assign' : cannot convert from 'const highp float' to 'Position 4-component vector of highp float
But in https://www.khronos.org/registry/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.html it explicitly states the existance of gl_in (as a built-in variable).
It is related to Intel UHD graphics not supporting OpenGLES explictly. When I checked what GLSL version was requested it was requesting OpenGL 2.0 which does not support gl_in as a built in.

Declare external global variables for glsl validator / webgl / three.js

I'm building a project with three.js and importing glsl files externally (with glsl-ify-loader) for use in a Three ShaderMaterial.
When using ShaderMaterial, Three prepends global variables like projectionMatrix, modelViewMatrix to my shader code pre-compilation when it concats the shader. So when I write my shader all i need is (as a simple example):
varying vec3 vNormal;
void main () {
vNormal = normal;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
... or similar.
My problem is that I'm using the glsl validator on my shader files which subsequently thinks that the pre-declared three variables are undeclared.
In JS, with eslint you could put /* global aGlobalVariableHere */ to appease the lint gods.
Is there anyway of doing this with the glsl validator? I can't find any resources that suggest how I could go about it.
You could use THREE.RawShaderMaterial (see docs), instead of ShaderMaterial. They're identical, except Raw doesn't prepend any uniforms or attributes to your shader at all, you have to do it manually. Then your linter will no longer act surprised:
Top of vertex shader:
precision highp float;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform vec3 cameraPosition;
// ...
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
// ...
You can read this page to see what uniforms and attributes get automatically added so you can add them yourself if needed in your shader code.

OpenGL ES3: no matching overloaded function found for packUnorm2x16

I am trying to pack 2 float values into 1 uint value using packUnorm2x16 method of OpenGL ES3 GLSL. But the compilation of the shader fails with 'packUnorm2x16': no matching overloaded function found error.
This is my fragment shader:
varying highp vec2 vDisplacement;
void main() {
gl_FragColor = vec4(packUnorm2x16(vDisplacement), vec3(0.0));
}
I am trying to render a result to a GL_R32UI texture.
packUnorm2x16 is supported since OpenGL ES 3.0. You've to add the version qualifier #version 300 es to the first lien of the fragment shader:
#version 300 es
varying highp vec2 vDisplacement;
void main() {
gl_FragColor = vec4(packUnorm2x16(vDisplacement), vec3(0.0));
}

Why do I need to define a precision value in webgl shaders?

I'm trying to get this tutorial to work but I ran into two issues, one of which is the following.
When I run the code as is I get an error in the fragment shader saying: THREE.WebGLShader: gl.getShaderInfoLog() ERROR: 0:2: '' : No precision specified for (float). So what I did was specifying a precision for every float/vector I define like so varying highp vec3 vNormal. This eliminates the error but I don't get why? I can't find any other example where precision values are added to variable declarations. Can anybody explain why this occurs? Does it have something to do with my Browser (Chrome 38)?
There is no default precision in WebGL fragment shaders. (High precision is default for vertex shaders.) The easiest solution is to add
precision highp float;
to all of your fragment shaders, which will eliminate the need to define the precision for all floating point vector variables, but generally,
precision mediump float;
will be preferable, for performance. I do not advise lowp; the good mobile hardware of today doesn't even support it anymore, and does the equivalent of typedeffing lowp to mediump.
Jessy's answer is correct that most fragment shaders set a default precision at the top of the fragment shader code.
However you are using Three.js's RawShaderMaterial which does not prepend any of the built-in uniforms, attributes, and precision declarations. So you have to define it yourself.
On the other hand the tutorial you linked to is using Three.js's ShaderMaterial for its material so Three.js will have the precision declaration prepended automatically.
If you remove the default uniforms/attributes from your shader code and use ShaderMaterial instead it will work without the precision code.
Vertex Shader
varying vec3 vNormal;
void main() {
vNormal = normal;
gl_Position = projectionMatrix *
modelViewMatrix *
vec4(position,1.0);
}
Fragment Shader
varying vec3 vNormal;
void main() {
vec3 light = vec3(0.5, 0.2, 1.0);
// ensure it's normalized
light = normalize(light);
// calculate the dot product of
// the light to the vertex normal
float dProd = max(0.0, dot(vNormal, light));
// feed into our frag colour
gl_FragColor = vec4(dProd, // R
dProd, // G
dProd, // B
1.0); // A
}
Update to the material
// create the sphere's material
var shaderMaterial = new THREE.ShaderMaterial({
vertexShader: document.getElementById('vertex-shader').innerHTML,
fragmentShader: document.getElementById('fragment-shader').innerHTML
});
Here is a fiddle of your code without the precision declarations.

Resources